1 |
commit: a345c8eee693aff99ddd3ce3beb816cb355fc388 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Nov 5 23:29:08 2015 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Nov 5 23:29:08 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=a345c8ee |
7 |
|
8 |
Removing kdbus as per upstream developers. See http://lwn.net/Articles/663062/ |
9 |
|
10 |
5015_kdbus-8-12-2015.patch | 34349 ------------------------------------------- |
11 |
1 file changed, 34349 deletions(-) |
12 |
|
13 |
diff --git a/5015_kdbus-8-12-2015.patch b/5015_kdbus-8-12-2015.patch |
14 |
deleted file mode 100644 |
15 |
index 4e018f2..0000000 |
16 |
--- a/5015_kdbus-8-12-2015.patch |
17 |
+++ /dev/null |
18 |
@@ -1,34349 +0,0 @@ |
19 |
-diff --git a/Documentation/Makefile b/Documentation/Makefile |
20 |
-index bc05482..e2127a7 100644 |
21 |
---- a/Documentation/Makefile |
22 |
-+++ b/Documentation/Makefile |
23 |
-@@ -1,4 +1,4 @@ |
24 |
- subdir-y := accounting auxdisplay blackfin connector \ |
25 |
-- filesystems filesystems ia64 laptops mic misc-devices \ |
26 |
-+ filesystems filesystems ia64 kdbus laptops mic misc-devices \ |
27 |
- networking pcmcia prctl ptp spi timers vDSO video4linux \ |
28 |
- watchdog |
29 |
-diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt |
30 |
-index 51f4221..ec7c81b 100644 |
31 |
---- a/Documentation/ioctl/ioctl-number.txt |
32 |
-+++ b/Documentation/ioctl/ioctl-number.txt |
33 |
-@@ -292,6 +292,7 @@ Code Seq#(hex) Include File Comments |
34 |
- 0x92 00-0F drivers/usb/mon/mon_bin.c |
35 |
- 0x93 60-7F linux/auto_fs.h |
36 |
- 0x94 all fs/btrfs/ioctl.h |
37 |
-+0x95 all uapi/linux/kdbus.h kdbus IPC driver |
38 |
- 0x97 00-7F fs/ceph/ioctl.h Ceph file system |
39 |
- 0x99 00-0F 537-Addinboard driver |
40 |
- <mailto:buk@××××××××.de> |
41 |
-diff --git a/Documentation/kdbus/.gitignore b/Documentation/kdbus/.gitignore |
42 |
-new file mode 100644 |
43 |
-index 0000000..b4a77cc |
44 |
---- /dev/null |
45 |
-+++ b/Documentation/kdbus/.gitignore |
46 |
-@@ -0,0 +1,2 @@ |
47 |
-+*.7 |
48 |
-+*.html |
49 |
-diff --git a/Documentation/kdbus/Makefile b/Documentation/kdbus/Makefile |
50 |
-new file mode 100644 |
51 |
-index 0000000..8caffe5 |
52 |
---- /dev/null |
53 |
-+++ b/Documentation/kdbus/Makefile |
54 |
-@@ -0,0 +1,44 @@ |
55 |
-+DOCS := \ |
56 |
-+ kdbus.xml \ |
57 |
-+ kdbus.bus.xml \ |
58 |
-+ kdbus.connection.xml \ |
59 |
-+ kdbus.endpoint.xml \ |
60 |
-+ kdbus.fs.xml \ |
61 |
-+ kdbus.item.xml \ |
62 |
-+ kdbus.match.xml \ |
63 |
-+ kdbus.message.xml \ |
64 |
-+ kdbus.name.xml \ |
65 |
-+ kdbus.policy.xml \ |
66 |
-+ kdbus.pool.xml |
67 |
-+ |
68 |
-+XMLFILES := $(addprefix $(obj)/,$(DOCS)) |
69 |
-+MANFILES := $(patsubst %.xml, %.7, $(XMLFILES)) |
70 |
-+HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES)) |
71 |
-+ |
72 |
-+XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl --skip-validation |
73 |
-+ |
74 |
-+quiet_cmd_db2man = MAN $@ |
75 |
-+ cmd_db2man = xmlto man $(XMLTO_ARGS) -o $(obj) $< |
76 |
-+%.7: %.xml |
77 |
-+ @(which xmlto > /dev/null 2>&1) || \ |
78 |
-+ (echo "*** You need to install xmlto ***"; \ |
79 |
-+ exit 1) |
80 |
-+ $(call cmd,db2man) |
81 |
-+ |
82 |
-+quiet_cmd_db2html = HTML $@ |
83 |
-+ cmd_db2html = xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $< |
84 |
-+%.html: %.xml |
85 |
-+ @(which xmlto > /dev/null 2>&1) || \ |
86 |
-+ (echo "*** You need to install xmlto ***"; \ |
87 |
-+ exit 1) |
88 |
-+ $(call cmd,db2html) |
89 |
-+ |
90 |
-+mandocs: $(MANFILES) |
91 |
-+ |
92 |
-+htmldocs: $(HTMLFILES) |
93 |
-+ |
94 |
-+clean-files := $(MANFILES) $(HTMLFILES) |
95 |
-+ |
96 |
-+# we don't support other %docs targets right now |
97 |
-+%docs: |
98 |
-+ @true |
99 |
-diff --git a/Documentation/kdbus/kdbus.bus.xml b/Documentation/kdbus/kdbus.bus.xml |
100 |
-new file mode 100644 |
101 |
-index 0000000..83f1198 |
102 |
---- /dev/null |
103 |
-+++ b/Documentation/kdbus/kdbus.bus.xml |
104 |
-@@ -0,0 +1,344 @@ |
105 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
106 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
107 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
108 |
-+ |
109 |
-+<refentry id="kdbus.bus"> |
110 |
-+ |
111 |
-+ <refentryinfo> |
112 |
-+ <title>kdbus.bus</title> |
113 |
-+ <productname>kdbus.bus</productname> |
114 |
-+ </refentryinfo> |
115 |
-+ |
116 |
-+ <refmeta> |
117 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
118 |
-+ <manvolnum>7</manvolnum> |
119 |
-+ </refmeta> |
120 |
-+ |
121 |
-+ <refnamediv> |
122 |
-+ <refname>kdbus.bus</refname> |
123 |
-+ <refpurpose>kdbus bus</refpurpose> |
124 |
-+ </refnamediv> |
125 |
-+ |
126 |
-+ <refsect1> |
127 |
-+ <title>Description</title> |
128 |
-+ |
129 |
-+ <para> |
130 |
-+ A bus is a resource that is shared between connections in order to |
131 |
-+ transmit messages (see |
132 |
-+ <citerefentry> |
133 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
134 |
-+ <manvolnum>7</manvolnum> |
135 |
-+ </citerefentry>). |
136 |
-+ Each bus is independent, and operations on the bus will not have any |
137 |
-+ effect on other buses. A bus is a management entity that controls the |
138 |
-+ addresses of its connections, their policies and message transactions |
139 |
-+ performed via this bus. |
140 |
-+ </para> |
141 |
-+ <para> |
142 |
-+ Each bus is bound to the mount instance it was created on. It has a |
143 |
-+ custom name that is unique across all buses of a domain. In |
144 |
-+ <citerefentry> |
145 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
146 |
-+ <manvolnum>7</manvolnum> |
147 |
-+ </citerefentry> |
148 |
-+ a bus is presented as a directory. No operations can be performed on |
149 |
-+ the bus itself; instead you need to perform the operations on an endpoint |
150 |
-+ associated with the bus. Endpoints are accessible as files underneath the |
151 |
-+ bus directory. A default endpoint called <constant>bus</constant> is |
152 |
-+ provided on each bus. |
153 |
-+ </para> |
154 |
-+ <para> |
155 |
-+ Bus names may be chosen freely except for one restriction: the name must |
156 |
-+ be prefixed with the numeric effective UID of the creator and a dash. This |
157 |
-+ is required to avoid namespace clashes between different users. When |
158 |
-+ creating a bus, the name that is passed in must be properly formatted, or |
159 |
-+ the kernel will refuse creation of the bus. Example: |
160 |
-+ <literal>1047-foobar</literal> is an acceptable name for a bus |
161 |
-+ registered by a user with UID 1047. However, |
162 |
-+ <literal>1024-foobar</literal> is not, and neither is |
163 |
-+ <literal>foobar</literal>. The UID must be provided in the |
164 |
-+ user-namespace of the bus owner. |
165 |
-+ </para> |
166 |
-+ <para> |
167 |
-+ To create a new bus, you need to open the control file of a domain and |
168 |
-+ employ the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. The control |
169 |
-+ file descriptor that was used to issue |
170 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> must not previously have been |
171 |
-+ used for any other control-ioctl and must be kept open for the entire |
172 |
-+ life-time of the created bus. Closing it will immediately cleanup the |
173 |
-+ entire bus and all its associated resources and endpoints. Every control |
174 |
-+ file descriptor can only be used to create a single new bus; from that |
175 |
-+ point on, it is not used for any further communication until the final |
176 |
-+ <citerefentry> |
177 |
-+ <refentrytitle>close</refentrytitle> |
178 |
-+ <manvolnum>2</manvolnum> |
179 |
-+ </citerefentry> |
180 |
-+ . |
181 |
-+ </para> |
182 |
-+ <para> |
183 |
-+ Each bus will generate a random, 128-bit UUID upon creation. This UUID |
184 |
-+ will be returned to creators of connections through |
185 |
-+ <varname>kdbus_cmd_hello.id128</varname> and can be used to uniquely |
186 |
-+ identify buses, even across different machines or containers. The UUID |
187 |
-+ will have its variant bits set to <literal>DCE</literal>, and denote |
188 |
-+ version 4 (random). For more details on UUIDs, see <ulink |
189 |
-+ url="https://en.wikipedia.org/wiki/Universally_unique_identifier"> |
190 |
-+ the Wikipedia article on UUIDs</ulink>. |
191 |
-+ </para> |
192 |
-+ |
193 |
-+ </refsect1> |
194 |
-+ |
195 |
-+ <refsect1> |
196 |
-+ <title>Creating buses</title> |
197 |
-+ <para> |
198 |
-+ To create a new bus, the <constant>KDBUS_CMD_BUS_MAKE</constant> |
199 |
-+ command is used. It takes a <type>struct kdbus_cmd</type> argument. |
200 |
-+ </para> |
201 |
-+ <programlisting> |
202 |
-+struct kdbus_cmd { |
203 |
-+ __u64 size; |
204 |
-+ __u64 flags; |
205 |
-+ __u64 return_flags; |
206 |
-+ struct kdbus_item items[0]; |
207 |
-+}; |
208 |
-+ </programlisting> |
209 |
-+ |
210 |
-+ <para>The fields in this struct are described below.</para> |
211 |
-+ |
212 |
-+ <variablelist> |
213 |
-+ <varlistentry> |
214 |
-+ <term><varname>size</varname></term> |
215 |
-+ <listitem><para> |
216 |
-+ The overall size of the struct, including its items. |
217 |
-+ </para></listitem> |
218 |
-+ </varlistentry> |
219 |
-+ |
220 |
-+ <varlistentry> |
221 |
-+ <term><varname>flags</varname></term> |
222 |
-+ <listitem><para>The flags for creation.</para> |
223 |
-+ <variablelist> |
224 |
-+ <varlistentry> |
225 |
-+ <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term> |
226 |
-+ <listitem> |
227 |
-+ <para>Make the bus file group-accessible.</para> |
228 |
-+ </listitem> |
229 |
-+ </varlistentry> |
230 |
-+ |
231 |
-+ <varlistentry> |
232 |
-+ <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term> |
233 |
-+ <listitem> |
234 |
-+ <para>Make the bus file world-accessible.</para> |
235 |
-+ </listitem> |
236 |
-+ </varlistentry> |
237 |
-+ |
238 |
-+ <varlistentry> |
239 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
240 |
-+ <listitem> |
241 |
-+ <para> |
242 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
243 |
-+ set, no action is taken; the ioctl will return |
244 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
245 |
-+ field will have all bits set that are valid for this command. |
246 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
247 |
-+ cleared by the operation. |
248 |
-+ </para> |
249 |
-+ </listitem> |
250 |
-+ </varlistentry> |
251 |
-+ </variablelist> |
252 |
-+ </listitem> |
253 |
-+ </varlistentry> |
254 |
-+ |
255 |
-+ <varlistentry> |
256 |
-+ <term><varname>return_flags</varname></term> |
257 |
-+ <listitem><para> |
258 |
-+ Flags returned by the kernel. Currently unused and always set to |
259 |
-+ <constant>0</constant> by the kernel. |
260 |
-+ </para></listitem> |
261 |
-+ </varlistentry> |
262 |
-+ |
263 |
-+ <varlistentry> |
264 |
-+ <term><varname>items</varname></term> |
265 |
-+ <listitem> |
266 |
-+ <para> |
267 |
-+ The following items (see |
268 |
-+ <citerefentry> |
269 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
270 |
-+ <manvolnum>7</manvolnum> |
271 |
-+ </citerefentry>) |
272 |
-+ are expected for <constant>KDBUS_CMD_BUS_MAKE</constant>. |
273 |
-+ </para> |
274 |
-+ <variablelist> |
275 |
-+ <varlistentry> |
276 |
-+ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
277 |
-+ <listitem> |
278 |
-+ <para> |
279 |
-+ Contains a null-terminated string that identifies the |
280 |
-+ bus. The name must be unique across the kdbus domain and |
281 |
-+ must start with the effective UID of the caller, followed by |
282 |
-+ a '<literal>-</literal>' (dash). This item is mandatory. |
283 |
-+ </para> |
284 |
-+ </listitem> |
285 |
-+ </varlistentry> |
286 |
-+ |
287 |
-+ <varlistentry> |
288 |
-+ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
289 |
-+ <listitem> |
290 |
-+ <para> |
291 |
-+ Bus-wide bloom parameters passed in a |
292 |
-+ <type>struct kdbus_bloom_parameter</type>. These settings are |
293 |
-+ copied back to new connections verbatim. This item is |
294 |
-+ mandatory. See |
295 |
-+ <citerefentry> |
296 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
297 |
-+ <manvolnum>7</manvolnum> |
298 |
-+ </citerefentry> |
299 |
-+ for a more detailed description of this item. |
300 |
-+ </para> |
301 |
-+ </listitem> |
302 |
-+ </varlistentry> |
303 |
-+ |
304 |
-+ <varlistentry> |
305 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
306 |
-+ <listitem> |
307 |
-+ <para> |
308 |
-+ An optional item that contains a set of attach flags that are |
309 |
-+ returned to connections when they query the bus creator |
310 |
-+ metadata. If not set, no metadata is returned. |
311 |
-+ </para> |
312 |
-+ </listitem> |
313 |
-+ </varlistentry> |
314 |
-+ |
315 |
-+ <varlistentry> |
316 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
317 |
-+ <listitem><para> |
318 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
319 |
-+ kernel for known item types. See |
320 |
-+ <citerefentry> |
321 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
322 |
-+ <manvolnum>7</manvolnum> |
323 |
-+ </citerefentry> |
324 |
-+ for more details. |
325 |
-+ </para></listitem> |
326 |
-+ </varlistentry> |
327 |
-+ </variablelist> |
328 |
-+ </listitem> |
329 |
-+ </varlistentry> |
330 |
-+ </variablelist> |
331 |
-+ |
332 |
-+ <para> |
333 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
334 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
335 |
-+ </para> |
336 |
-+ </refsect1> |
337 |
-+ |
338 |
-+ <refsect1> |
339 |
-+ <title>Return value</title> |
340 |
-+ <para> |
341 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
342 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
343 |
-+ <varname>errno</varname> is set to indicate the error. |
344 |
-+ If the issued ioctl is illegal for the file descriptor used, |
345 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
346 |
-+ </para> |
347 |
-+ |
348 |
-+ <refsect2> |
349 |
-+ <title> |
350 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> may fail with the following |
351 |
-+ errors |
352 |
-+ </title> |
353 |
-+ |
354 |
-+ <variablelist> |
355 |
-+ <varlistentry> |
356 |
-+ <term><constant>EBADMSG</constant></term> |
357 |
-+ <listitem><para> |
358 |
-+ A mandatory item is missing. |
359 |
-+ </para></listitem> |
360 |
-+ </varlistentry> |
361 |
-+ |
362 |
-+ <varlistentry> |
363 |
-+ <term><constant>EINVAL</constant></term> |
364 |
-+ <listitem><para> |
365 |
-+ The flags supplied in the <constant>struct kdbus_cmd</constant> |
366 |
-+ are invalid or the supplied name does not start with the current |
367 |
-+ UID and a '<literal>-</literal>' (dash). |
368 |
-+ </para></listitem> |
369 |
-+ </varlistentry> |
370 |
-+ |
371 |
-+ <varlistentry> |
372 |
-+ <term><constant>EEXIST</constant></term> |
373 |
-+ <listitem><para> |
374 |
-+ A bus of that name already exists. |
375 |
-+ </para></listitem> |
376 |
-+ </varlistentry> |
377 |
-+ |
378 |
-+ <varlistentry> |
379 |
-+ <term><constant>ESHUTDOWN</constant></term> |
380 |
-+ <listitem><para> |
381 |
-+ The kdbus mount instance for the bus was already shut down. |
382 |
-+ </para></listitem> |
383 |
-+ </varlistentry> |
384 |
-+ |
385 |
-+ <varlistentry> |
386 |
-+ <term><constant>EMFILE</constant></term> |
387 |
-+ <listitem><para> |
388 |
-+ The maximum number of buses for the current user is exhausted. |
389 |
-+ </para></listitem> |
390 |
-+ </varlistentry> |
391 |
-+ </variablelist> |
392 |
-+ </refsect2> |
393 |
-+ </refsect1> |
394 |
-+ |
395 |
-+ <refsect1> |
396 |
-+ <title>See Also</title> |
397 |
-+ <simplelist type="inline"> |
398 |
-+ <member> |
399 |
-+ <citerefentry> |
400 |
-+ <refentrytitle>kdbus</refentrytitle> |
401 |
-+ <manvolnum>7</manvolnum> |
402 |
-+ </citerefentry> |
403 |
-+ </member> |
404 |
-+ <member> |
405 |
-+ <citerefentry> |
406 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
407 |
-+ <manvolnum>7</manvolnum> |
408 |
-+ </citerefentry> |
409 |
-+ </member> |
410 |
-+ <member> |
411 |
-+ <citerefentry> |
412 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
413 |
-+ <manvolnum>7</manvolnum> |
414 |
-+ </citerefentry> |
415 |
-+ </member> |
416 |
-+ <member> |
417 |
-+ <citerefentry> |
418 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
419 |
-+ <manvolnum>7</manvolnum> |
420 |
-+ </citerefentry> |
421 |
-+ </member> |
422 |
-+ <member> |
423 |
-+ <citerefentry> |
424 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
425 |
-+ <manvolnum>7</manvolnum> |
426 |
-+ </citerefentry> |
427 |
-+ </member> |
428 |
-+ <member> |
429 |
-+ <citerefentry> |
430 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
431 |
-+ <manvolnum>7</manvolnum> |
432 |
-+ </citerefentry> |
433 |
-+ </member> |
434 |
-+ <member> |
435 |
-+ <citerefentry> |
436 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
437 |
-+ <manvolnum>7</manvolnum> |
438 |
-+ </citerefentry> |
439 |
-+ </member> |
440 |
-+ <member> |
441 |
-+ <citerefentry> |
442 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
443 |
-+ <manvolnum>7</manvolnum> |
444 |
-+ </citerefentry> |
445 |
-+ </member> |
446 |
-+ </simplelist> |
447 |
-+ </refsect1> |
448 |
-+</refentry> |
449 |
-diff --git a/Documentation/kdbus/kdbus.connection.xml b/Documentation/kdbus/kdbus.connection.xml |
450 |
-new file mode 100644 |
451 |
-index 0000000..4bb5f30 |
452 |
---- /dev/null |
453 |
-+++ b/Documentation/kdbus/kdbus.connection.xml |
454 |
-@@ -0,0 +1,1244 @@ |
455 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
456 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
457 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
458 |
-+ |
459 |
-+<refentry id="kdbus.connection"> |
460 |
-+ |
461 |
-+ <refentryinfo> |
462 |
-+ <title>kdbus.connection</title> |
463 |
-+ <productname>kdbus.connection</productname> |
464 |
-+ </refentryinfo> |
465 |
-+ |
466 |
-+ <refmeta> |
467 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
468 |
-+ <manvolnum>7</manvolnum> |
469 |
-+ </refmeta> |
470 |
-+ |
471 |
-+ <refnamediv> |
472 |
-+ <refname>kdbus.connection</refname> |
473 |
-+ <refpurpose>kdbus connection</refpurpose> |
474 |
-+ </refnamediv> |
475 |
-+ |
476 |
-+ <refsect1> |
477 |
-+ <title>Description</title> |
478 |
-+ |
479 |
-+ <para> |
480 |
-+ Connections are identified by their <emphasis>connection ID</emphasis>, |
481 |
-+ internally implemented as a <type>uint64_t</type> counter. |
482 |
-+ The IDs of every newly created bus start at <constant>1</constant>, and |
483 |
-+ every new connection will increment the counter by <constant>1</constant>. |
484 |
-+ The IDs are not reused. |
485 |
-+ </para> |
486 |
-+ <para> |
487 |
-+ In higher level tools, the user visible representation of a connection is |
488 |
-+ defined by the D-Bus protocol specification as |
489 |
-+ <constant>":1.<ID>"</constant>. |
490 |
-+ </para> |
491 |
-+ <para> |
492 |
-+ Messages with a specific <type>uint64_t</type> destination ID are |
493 |
-+ directly delivered to the connection with the corresponding ID. Signal |
494 |
-+ messages (see |
495 |
-+ <citerefentry> |
496 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
497 |
-+ <manvolnum>7</manvolnum> |
498 |
-+ </citerefentry>) |
499 |
-+ may be addressed to the special destination ID |
500 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> (~0ULL) and will then |
501 |
-+ potentially be delivered to all currently active connections on the bus. |
502 |
-+ However, in order to receive any signal messages, clients must subscribe |
503 |
-+ to them by installing a match (see |
504 |
-+ <citerefentry> |
505 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
506 |
-+ <manvolnum>7</manvolnum> |
507 |
-+ </citerefentry>). |
508 |
-+ </para> |
509 |
-+ <para> |
510 |
-+ Messages synthesized and sent directly by the kernel will carry the |
511 |
-+ special source ID <constant>KDBUS_SRC_ID_KERNEL</constant> (0). |
512 |
-+ </para> |
513 |
-+ <para> |
514 |
-+ In addition to the unique <type>uint64_t</type> connection ID, |
515 |
-+ established connections can request the ownership of |
516 |
-+ <emphasis>well-known names</emphasis>, under which they can be found and |
517 |
-+ addressed by other bus clients. A well-known name is associated with one |
518 |
-+ and only one connection at a time. See |
519 |
-+ <citerefentry> |
520 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
521 |
-+ <manvolnum>7</manvolnum> |
522 |
-+ </citerefentry> |
523 |
-+ on name acquisition, the name registry, and the validity of names. |
524 |
-+ </para> |
525 |
-+ <para> |
526 |
-+ Messages can specify the special destination ID |
527 |
-+ <constant>KDBUS_DST_ID_NAME</constant> (0) and carry a well-known name |
528 |
-+ in the message data. Such a message is delivered to the destination |
529 |
-+ connection which owns that well-known name. |
530 |
-+ </para> |
531 |
-+ |
532 |
-+ <programlisting><![CDATA[ |
533 |
-+ +-------------------------------------------------------------------------+ |
534 |
-+ | +---------------+ +---------------------------+ | |
535 |
-+ | | Connection | | Message | -----------------+ | |
536 |
-+ | | :1.22 | --> | src: 22 | | | |
537 |
-+ | | | | dst: 25 | | | |
538 |
-+ | | | | | | | |
539 |
-+ | | | | | | | |
540 |
-+ | | | +---------------------------+ | | |
541 |
-+ | | | | | |
542 |
-+ | | | <--------------------------------------+ | | |
543 |
-+ | +---------------+ | | | |
544 |
-+ | | | | |
545 |
-+ | +---------------+ +---------------------------+ | | | |
546 |
-+ | | Connection | | Message | -----+ | | |
547 |
-+ | | :1.25 | --> | src: 25 | | | |
548 |
-+ | | | | dst: 0xffffffffffffffff | -------------+ | | |
549 |
-+ | | | | (KDBUS_DST_ID_BROADCAST) | | | | |
550 |
-+ | | | | | ---------+ | | | |
551 |
-+ | | | +---------------------------+ | | | | |
552 |
-+ | | | | | | | |
553 |
-+ | | | <--------------------------------------------------+ | |
554 |
-+ | +---------------+ | | | |
555 |
-+ | | | | |
556 |
-+ | +---------------+ +---------------------------+ | | | |
557 |
-+ | | Connection | | Message | --+ | | | |
558 |
-+ | | :1.55 | --> | src: 55 | | | | | |
559 |
-+ | | | | dst: 0 / org.foo.bar | | | | | |
560 |
-+ | | | | | | | | | |
561 |
-+ | | | | | | | | | |
562 |
-+ | | | +---------------------------+ | | | | |
563 |
-+ | | | | | | | |
564 |
-+ | | | <------------------------------------------+ | | |
565 |
-+ | +---------------+ | | | |
566 |
-+ | | | | |
567 |
-+ | +---------------+ | | | |
568 |
-+ | | Connection | | | | |
569 |
-+ | | :1.81 | | | | |
570 |
-+ | | org.foo.bar | | | | |
571 |
-+ | | | | | | |
572 |
-+ | | | | | | |
573 |
-+ | | | <-----------------------------------+ | | |
574 |
-+ | | | | | |
575 |
-+ | | | <----------------------------------------------+ | |
576 |
-+ | +---------------+ | |
577 |
-+ +-------------------------------------------------------------------------+ |
578 |
-+ ]]></programlisting> |
579 |
-+ </refsect1> |
580 |
-+ |
581 |
-+ <refsect1> |
582 |
-+ <title>Privileged connections</title> |
583 |
-+ <para> |
584 |
-+ A connection is considered <emphasis>privileged</emphasis> if the user |
585 |
-+ it was created by is the same that created the bus, or if the creating |
586 |
-+ task had <constant>CAP_IPC_OWNER</constant> set when it called |
587 |
-+ <constant>KDBUS_CMD_HELLO</constant> (see below). |
588 |
-+ </para> |
589 |
-+ <para> |
590 |
-+ Privileged connections have permission to employ certain restricted |
591 |
-+ functions and commands, which are explained below and in other kdbus |
592 |
-+ man-pages. |
593 |
-+ </para> |
594 |
-+ </refsect1> |
595 |
-+ |
596 |
-+ <refsect1> |
597 |
-+ <title>Activator and policy holder connection</title> |
598 |
-+ <para> |
599 |
-+ An <emphasis>activator</emphasis> connection is a placeholder for a |
600 |
-+ <emphasis>well-known name</emphasis>. Messages sent to such a connection |
601 |
-+ can be used to start an implementer connection, which will then get all |
602 |
-+ the messages from the activator copied over. An activator connection |
603 |
-+ cannot be used to send any message. |
604 |
-+ </para> |
605 |
-+ <para> |
606 |
-+ A <emphasis>policy holder</emphasis> connection only installs a policy |
607 |
-+ for one or more names. These policy entries are kept active as long as |
608 |
-+ the connection is alive, and are removed once it terminates. Such a |
609 |
-+ policy connection type can be used to deploy restrictions for names that |
610 |
-+ are not yet active on the bus. A policy holder connection cannot be used |
611 |
-+ to send any message. |
612 |
-+ </para> |
613 |
-+ <para> |
614 |
-+ The creation of activator or policy holder connections is restricted to |
615 |
-+ privileged users on the bus (see above). |
616 |
-+ </para> |
617 |
-+ </refsect1> |
618 |
-+ |
619 |
-+ <refsect1> |
620 |
-+ <title>Monitor connections</title> |
621 |
-+ <para> |
622 |
-+ Monitors are eavesdropping connections that receive all the traffic on the |
623 |
-+ bus, but is invisible to other connections. Such connections have all |
624 |
-+ properties of any other, regular connection, except for the following |
625 |
-+ details: |
626 |
-+ </para> |
627 |
-+ |
628 |
-+ <itemizedlist> |
629 |
-+ <listitem><para> |
630 |
-+ They will get every message sent over the bus, both unicasts and |
631 |
-+ broadcasts. |
632 |
-+ </para></listitem> |
633 |
-+ |
634 |
-+ <listitem><para> |
635 |
-+ Installing matches for signal messages is neither necessary |
636 |
-+ nor allowed. |
637 |
-+ </para></listitem> |
638 |
-+ |
639 |
-+ <listitem><para> |
640 |
-+ They cannot send messages or be directly addressed as receiver. |
641 |
-+ </para></listitem> |
642 |
-+ |
643 |
-+ <listitem><para> |
644 |
-+ They cannot own well-known names. Therefore, they also can't operate as |
645 |
-+ activators. |
646 |
-+ </para></listitem> |
647 |
-+ |
648 |
-+ <listitem><para> |
649 |
-+ Their creation and destruction will not cause |
650 |
-+ <constant>KDBUS_ITEM_ID_{ADD,REMOVE}</constant> (see |
651 |
-+ <citerefentry> |
652 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
653 |
-+ <manvolnum>7</manvolnum> |
654 |
-+ </citerefentry>). |
655 |
-+ </para></listitem> |
656 |
-+ |
657 |
-+ <listitem><para> |
658 |
-+ They are not listed with their unique name in name registry dumps |
659 |
-+ (see <constant>KDBUS_CMD_NAME_LIST</constant> in |
660 |
-+ <citerefentry> |
661 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
662 |
-+ <manvolnum>7</manvolnum> |
663 |
-+ </citerefentry>), so other connections cannot detect the presence of |
664 |
-+ a monitor. |
665 |
-+ </para></listitem> |
666 |
-+ </itemizedlist> |
667 |
-+ <para> |
668 |
-+ The creation of monitor connections is restricted to privileged users on |
669 |
-+ the bus (see above). |
670 |
-+ </para> |
671 |
-+ </refsect1> |
672 |
-+ |
673 |
-+ <refsect1> |
674 |
-+ <title>Creating connections</title> |
675 |
-+ <para> |
676 |
-+ A connection to a bus is created by opening an endpoint file (see |
677 |
-+ <citerefentry> |
678 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
679 |
-+ <manvolnum>7</manvolnum> |
680 |
-+ </citerefentry>) |
681 |
-+ of a bus and becoming an active client with the |
682 |
-+ <constant>KDBUS_CMD_HELLO</constant> ioctl. Every connection has a unique |
683 |
-+ identifier on the bus and can address messages to every other connection |
684 |
-+ on the same bus by using the peer's connection ID as the destination. |
685 |
-+ </para> |
686 |
-+ <para> |
687 |
-+ The <constant>KDBUS_CMD_HELLO</constant> ioctl takes a <type>struct |
688 |
-+ kdbus_cmd_hello</type> as argument. |
689 |
-+ </para> |
690 |
-+ |
691 |
-+ <programlisting> |
692 |
-+struct kdbus_cmd_hello { |
693 |
-+ __u64 size; |
694 |
-+ __u64 flags; |
695 |
-+ __u64 return_flags; |
696 |
-+ __u64 attach_flags_send; |
697 |
-+ __u64 attach_flags_recv; |
698 |
-+ __u64 bus_flags; |
699 |
-+ __u64 id; |
700 |
-+ __u64 pool_size; |
701 |
-+ __u64 offset; |
702 |
-+ __u8 id128[16]; |
703 |
-+ struct kdbus_item items[0]; |
704 |
-+}; |
705 |
-+ </programlisting> |
706 |
-+ |
707 |
-+ <para>The fields in this struct are described below.</para> |
708 |
-+ |
709 |
-+ <variablelist> |
710 |
-+ <varlistentry> |
711 |
-+ <term><varname>size</varname></term> |
712 |
-+ <listitem><para> |
713 |
-+ The overall size of the struct, including its items. |
714 |
-+ </para></listitem> |
715 |
-+ </varlistentry> |
716 |
-+ |
717 |
-+ <varlistentry> |
718 |
-+ <term><varname>flags</varname></term> |
719 |
-+ <listitem> |
720 |
-+ <para>Flags to apply to this connection</para> |
721 |
-+ <variablelist> |
722 |
-+ <varlistentry> |
723 |
-+ <term><constant>KDBUS_HELLO_ACCEPT_FD</constant></term> |
724 |
-+ <listitem> |
725 |
-+ <para> |
726 |
-+ When this flag is set, the connection can be sent file |
727 |
-+ descriptors as message payload of unicast messages. If it's |
728 |
-+ not set, an attempt to send file descriptors will result in |
729 |
-+ <constant>-ECOMM</constant> on the sender's side. |
730 |
-+ </para> |
731 |
-+ </listitem> |
732 |
-+ </varlistentry> |
733 |
-+ |
734 |
-+ <varlistentry> |
735 |
-+ <term><constant>KDBUS_HELLO_ACTIVATOR</constant></term> |
736 |
-+ <listitem> |
737 |
-+ <para> |
738 |
-+ Make this connection an activator (see above). With this bit |
739 |
-+ set, an item of type <constant>KDBUS_ITEM_NAME</constant> has |
740 |
-+ to be attached. This item describes the well-known name this |
741 |
-+ connection should be an activator for. |
742 |
-+ A connection can not be an activator and a policy holder at |
743 |
-+ the same time time, so this bit is not allowed together with |
744 |
-+ <constant>KDBUS_HELLO_POLICY_HOLDER</constant>. |
745 |
-+ </para> |
746 |
-+ </listitem> |
747 |
-+ </varlistentry> |
748 |
-+ |
749 |
-+ <varlistentry> |
750 |
-+ <term><constant>KDBUS_HELLO_POLICY_HOLDER</constant></term> |
751 |
-+ <listitem> |
752 |
-+ <para> |
753 |
-+ Make this connection a policy holder (see above). With this |
754 |
-+ bit set, an item of type <constant>KDBUS_ITEM_NAME</constant> |
755 |
-+ has to be attached. This item describes the well-known name |
756 |
-+ this connection should hold a policy for. |
757 |
-+ A connection can not be an activator and a policy holder at |
758 |
-+ the same time time, so this bit is not allowed together with |
759 |
-+ <constant>KDBUS_HELLO_ACTIVATOR</constant>. |
760 |
-+ </para> |
761 |
-+ </listitem> |
762 |
-+ </varlistentry> |
763 |
-+ |
764 |
-+ <varlistentry> |
765 |
-+ <term><constant>KDBUS_HELLO_MONITOR</constant></term> |
766 |
-+ <listitem> |
767 |
-+ <para> |
768 |
-+ Make this connection a monitor connection (see above). |
769 |
-+ </para> |
770 |
-+ <para> |
771 |
-+ This flag can only be set by privileged bus connections. See |
772 |
-+ below for more information. |
773 |
-+ A connection can not be monitor and an activator or a policy |
774 |
-+ holder at the same time time, so this bit is not allowed |
775 |
-+ together with <constant>KDBUS_HELLO_ACTIVATOR</constant> or |
776 |
-+ <constant>KDBUS_HELLO_POLICY_HOLDER</constant>. |
777 |
-+ </para> |
778 |
-+ </listitem> |
779 |
-+ </varlistentry> |
780 |
-+ |
781 |
-+ <varlistentry> |
782 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
783 |
-+ <listitem> |
784 |
-+ <para> |
785 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
786 |
-+ set, no action is taken; the ioctl will return |
787 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
788 |
-+ field will have all bits set that are valid for this command. |
789 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
790 |
-+ cleared by the operation. |
791 |
-+ </para> |
792 |
-+ </listitem> |
793 |
-+ </varlistentry> |
794 |
-+ </variablelist> |
795 |
-+ </listitem> |
796 |
-+ </varlistentry> |
797 |
-+ |
798 |
-+ <varlistentry> |
799 |
-+ <term><varname>return_flags</varname></term> |
800 |
-+ <listitem><para> |
801 |
-+ Flags returned by the kernel. Currently unused and always set to |
802 |
-+ <constant>0</constant> by the kernel. |
803 |
-+ </para></listitem> |
804 |
-+ </varlistentry> |
805 |
-+ |
806 |
-+ <varlistentry> |
807 |
-+ <term><varname>attach_flags_send</varname></term> |
808 |
-+ <listitem><para> |
809 |
-+ Set the bits for metadata this connection permits to be sent to the |
810 |
-+ receiving peer. Only metadata items that are both allowed to be sent |
811 |
-+ by the sender and that are requested by the receiver will be attached |
812 |
-+ to the message. |
813 |
-+ </para></listitem> |
814 |
-+ </varlistentry> |
815 |
-+ |
816 |
-+ <varlistentry> |
817 |
-+ <term><varname>attach_flags_recv</varname></term> |
818 |
-+ <listitem><para> |
819 |
-+ Request the attachment of metadata for each message received by this |
820 |
-+ connection. See |
821 |
-+ <citerefentry> |
822 |
-+ <refentrytitle>kdbus</refentrytitle> |
823 |
-+ <manvolnum>7</manvolnum> |
824 |
-+ </citerefentry> |
825 |
-+ for information about metadata, and |
826 |
-+ <citerefentry> |
827 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
828 |
-+ <manvolnum>7</manvolnum> |
829 |
-+ </citerefentry> |
830 |
-+ regarding items in general. |
831 |
-+ </para></listitem> |
832 |
-+ </varlistentry> |
833 |
-+ |
834 |
-+ <varlistentry> |
835 |
-+ <term><varname>bus_flags</varname></term> |
836 |
-+ <listitem><para> |
837 |
-+ Upon successful completion of the ioctl, this member will contain the |
838 |
-+ flags of the bus it connected to. |
839 |
-+ </para></listitem> |
840 |
-+ </varlistentry> |
841 |
-+ |
842 |
-+ <varlistentry> |
843 |
-+ <term><varname>id</varname></term> |
844 |
-+ <listitem><para> |
845 |
-+ Upon successful completion of the command, this member will contain |
846 |
-+ the numerical ID of the new connection. |
847 |
-+ </para></listitem> |
848 |
-+ </varlistentry> |
849 |
-+ |
850 |
-+ <varlistentry> |
851 |
-+ <term><varname>pool_size</varname></term> |
852 |
-+ <listitem><para> |
853 |
-+ The size of the communication pool, in bytes. The pool can be |
854 |
-+ accessed by calling |
855 |
-+ <citerefentry> |
856 |
-+ <refentrytitle>mmap</refentrytitle> |
857 |
-+ <manvolnum>2</manvolnum> |
858 |
-+ </citerefentry> |
859 |
-+ on the file descriptor that was used to issue the |
860 |
-+ <constant>KDBUS_CMD_HELLO</constant> ioctl. |
861 |
-+ The pool size of a connection must be greater than |
862 |
-+ <constant>0</constant> and a multiple of |
863 |
-+ <constant>PAGE_SIZE</constant>. See |
864 |
-+ <citerefentry> |
865 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
866 |
-+ <manvolnum>7</manvolnum> |
867 |
-+ </citerefentry> |
868 |
-+ for more information. |
869 |
-+ </para></listitem> |
870 |
-+ </varlistentry> |
871 |
-+ |
872 |
-+ <varlistentry> |
873 |
-+ <term><varname>offset</varname></term> |
874 |
-+ <listitem><para> |
875 |
-+ The kernel will return the offset in the pool where returned details |
876 |
-+ will be stored. See below. |
877 |
-+ </para></listitem> |
878 |
-+ </varlistentry> |
879 |
-+ |
880 |
-+ <varlistentry> |
881 |
-+ <term><varname>id128</varname></term> |
882 |
-+ <listitem><para> |
883 |
-+ Upon successful completion of the ioctl, this member will contain the |
884 |
-+ <emphasis>128-bit UUID</emphasis> of the connected bus. |
885 |
-+ </para></listitem> |
886 |
-+ </varlistentry> |
887 |
-+ |
888 |
-+ <varlistentry> |
889 |
-+ <term><varname>items</varname></term> |
890 |
-+ <listitem> |
891 |
-+ <para> |
892 |
-+ Variable list of items containing optional additional information. |
893 |
-+ The following items are currently expected/valid: |
894 |
-+ </para> |
895 |
-+ <variablelist> |
896 |
-+ <varlistentry> |
897 |
-+ <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term> |
898 |
-+ <listitem> |
899 |
-+ <para> |
900 |
-+ Contains a string that describes this connection, so it can |
901 |
-+ be identified later. |
902 |
-+ </para> |
903 |
-+ </listitem> |
904 |
-+ </varlistentry> |
905 |
-+ |
906 |
-+ <varlistentry> |
907 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
908 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
909 |
-+ <listitem> |
910 |
-+ <para> |
911 |
-+ For activators and policy holders only, combinations of |
912 |
-+ these two items describe policy access entries. See |
913 |
-+ <citerefentry> |
914 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
915 |
-+ <manvolnum>7</manvolnum> |
916 |
-+ </citerefentry> |
917 |
-+ for further details. |
918 |
-+ </para> |
919 |
-+ </listitem> |
920 |
-+ </varlistentry> |
921 |
-+ |
922 |
-+ <varlistentry> |
923 |
-+ <term><constant>KDBUS_ITEM_CREDS</constant></term> |
924 |
-+ <term><constant>KDBUS_ITEM_PIDS</constant></term> |
925 |
-+ <term><constant>KDBUS_ITEM_SECLABEL</constant></term> |
926 |
-+ <listitem> |
927 |
-+ <para> |
928 |
-+ Privileged bus users may submit these types in order to |
929 |
-+ create connections with faked credentials. This information |
930 |
-+ will be returned when peer information is queried by |
931 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant>. See below for more |
932 |
-+ information on retrieving information on connections. |
933 |
-+ </para> |
934 |
-+ </listitem> |
935 |
-+ </varlistentry> |
936 |
-+ |
937 |
-+ <varlistentry> |
938 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
939 |
-+ <listitem><para> |
940 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
941 |
-+ kernel for known item types. See |
942 |
-+ <citerefentry> |
943 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
944 |
-+ <manvolnum>7</manvolnum> |
945 |
-+ </citerefentry> |
946 |
-+ for more details. |
947 |
-+ </para></listitem> |
948 |
-+ </varlistentry> |
949 |
-+ </variablelist> |
950 |
-+ |
951 |
-+ <para> |
952 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
953 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
954 |
-+ </para> |
955 |
-+ </listitem> |
956 |
-+ </varlistentry> |
957 |
-+ </variablelist> |
958 |
-+ |
959 |
-+ <para> |
960 |
-+ At the offset returned in the <varname>offset</varname> field of |
961 |
-+ <type>struct kdbus_cmd_hello</type>, the kernel will store items |
962 |
-+ of the following types: |
963 |
-+ </para> |
964 |
-+ |
965 |
-+ <variablelist> |
966 |
-+ <varlistentry> |
967 |
-+ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
968 |
-+ <listitem> |
969 |
-+ <para> |
970 |
-+ Bloom filter parameter as defined by the bus creator. |
971 |
-+ </para> |
972 |
-+ </listitem> |
973 |
-+ </varlistentry> |
974 |
-+ </variablelist> |
975 |
-+ |
976 |
-+ <para> |
977 |
-+ The offset in the pool has to be freed with the |
978 |
-+ <constant>KDBUS_CMD_FREE</constant> ioctl. See |
979 |
-+ <citerefentry> |
980 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
981 |
-+ <manvolnum>7</manvolnum> |
982 |
-+ </citerefentry> |
983 |
-+ for further information. |
984 |
-+ </para> |
985 |
-+ </refsect1> |
986 |
-+ |
987 |
-+ <refsect1> |
988 |
-+ <title>Retrieving information on a connection</title> |
989 |
-+ <para> |
990 |
-+ The <constant>KDBUS_CMD_CONN_INFO</constant> ioctl can be used to |
991 |
-+ retrieve credentials and properties of the initial creator of a |
992 |
-+ connection. This ioctl uses the following struct. |
993 |
-+ </para> |
994 |
-+ |
995 |
-+ <programlisting> |
996 |
-+struct kdbus_cmd_info { |
997 |
-+ __u64 size; |
998 |
-+ __u64 flags; |
999 |
-+ __u64 return_flags; |
1000 |
-+ __u64 id; |
1001 |
-+ __u64 attach_flags; |
1002 |
-+ __u64 offset; |
1003 |
-+ __u64 info_size; |
1004 |
-+ struct kdbus_item items[0]; |
1005 |
-+}; |
1006 |
-+ </programlisting> |
1007 |
-+ |
1008 |
-+ <variablelist> |
1009 |
-+ <varlistentry> |
1010 |
-+ <term><varname>size</varname></term> |
1011 |
-+ <listitem><para> |
1012 |
-+ The overall size of the struct, including its items. |
1013 |
-+ </para></listitem> |
1014 |
-+ </varlistentry> |
1015 |
-+ |
1016 |
-+ <varlistentry> |
1017 |
-+ <term><varname>flags</varname></term> |
1018 |
-+ <listitem><para> |
1019 |
-+ Currently, no flags are supported. |
1020 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1021 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1022 |
-+ and the <varname>flags</varname> field is set to |
1023 |
-+ <constant>0</constant>. |
1024 |
-+ </para></listitem> |
1025 |
-+ </varlistentry> |
1026 |
-+ |
1027 |
-+ <varlistentry> |
1028 |
-+ <term><varname>return_flags</varname></term> |
1029 |
-+ <listitem><para> |
1030 |
-+ Flags returned by the kernel. Currently unused and always set to |
1031 |
-+ <constant>0</constant> by the kernel. |
1032 |
-+ </para></listitem> |
1033 |
-+ </varlistentry> |
1034 |
-+ |
1035 |
-+ <varlistentry> |
1036 |
-+ <term><varname>id</varname></term> |
1037 |
-+ <listitem><para> |
1038 |
-+ The numerical ID of the connection for which information is to be |
1039 |
-+ retrieved. If set to a non-zero value, the |
1040 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant> item is ignored. |
1041 |
-+ </para></listitem> |
1042 |
-+ </varlistentry> |
1043 |
-+ |
1044 |
-+ <varlistentry> |
1045 |
-+ <term><varname>attach_flags</varname></term> |
1046 |
-+ <listitem><para> |
1047 |
-+ Specifies which metadata items should be attached to the answer. See |
1048 |
-+ <citerefentry> |
1049 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
1050 |
-+ <manvolnum>7</manvolnum> |
1051 |
-+ </citerefentry>. |
1052 |
-+ </para></listitem> |
1053 |
-+ </varlistentry> |
1054 |
-+ |
1055 |
-+ <varlistentry> |
1056 |
-+ <term><varname>offset</varname></term> |
1057 |
-+ <listitem><para> |
1058 |
-+ When the ioctl returns, this field will contain the offset of the |
1059 |
-+ connection information inside the caller's pool. See |
1060 |
-+ <citerefentry> |
1061 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1062 |
-+ <manvolnum>7</manvolnum> |
1063 |
-+ </citerefentry> |
1064 |
-+ for further information. |
1065 |
-+ </para></listitem> |
1066 |
-+ </varlistentry> |
1067 |
-+ |
1068 |
-+ <varlistentry> |
1069 |
-+ <term><varname>info_size</varname></term> |
1070 |
-+ <listitem><para> |
1071 |
-+ The kernel will return the size of the returned information, so |
1072 |
-+ applications can optionally |
1073 |
-+ <citerefentry> |
1074 |
-+ <refentrytitle>mmap</refentrytitle> |
1075 |
-+ <manvolnum>2</manvolnum> |
1076 |
-+ </citerefentry> |
1077 |
-+ specific parts of the pool. See |
1078 |
-+ <citerefentry> |
1079 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1080 |
-+ <manvolnum>7</manvolnum> |
1081 |
-+ </citerefentry> |
1082 |
-+ for further information. |
1083 |
-+ </para></listitem> |
1084 |
-+ </varlistentry> |
1085 |
-+ |
1086 |
-+ <varlistentry> |
1087 |
-+ <term><varname>items</varname></term> |
1088 |
-+ <listitem> |
1089 |
-+ <para> |
1090 |
-+ The following items are expected for |
1091 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant>. |
1092 |
-+ </para> |
1093 |
-+ <variablelist> |
1094 |
-+ <varlistentry> |
1095 |
-+ <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term> |
1096 |
-+ <listitem> |
1097 |
-+ <para> |
1098 |
-+ Contains the well-known name of the connection to look up as. |
1099 |
-+ This item is mandatory if the <varname>id</varname> field is |
1100 |
-+ set to 0. |
1101 |
-+ </para> |
1102 |
-+ </listitem> |
1103 |
-+ </varlistentry> |
1104 |
-+ |
1105 |
-+ <varlistentry> |
1106 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1107 |
-+ <listitem><para> |
1108 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1109 |
-+ kernel for known item types. See |
1110 |
-+ <citerefentry> |
1111 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1112 |
-+ <manvolnum>7</manvolnum> |
1113 |
-+ </citerefentry> |
1114 |
-+ for more details. |
1115 |
-+ </para></listitem> |
1116 |
-+ </varlistentry> |
1117 |
-+ </variablelist> |
1118 |
-+ <para> |
1119 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1120 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1121 |
-+ </para> |
1122 |
-+ </listitem> |
1123 |
-+ </varlistentry> |
1124 |
-+ </variablelist> |
1125 |
-+ |
1126 |
-+ <para> |
1127 |
-+ When the ioctl returns, the following struct will be stored in the |
1128 |
-+ caller's pool at <varname>offset</varname>. The fields in this struct |
1129 |
-+ are described below. |
1130 |
-+ </para> |
1131 |
-+ |
1132 |
-+ <programlisting> |
1133 |
-+struct kdbus_info { |
1134 |
-+ __u64 size; |
1135 |
-+ __u64 id; |
1136 |
-+ __u64 flags; |
1137 |
-+ struct kdbus_item items[0]; |
1138 |
-+}; |
1139 |
-+ </programlisting> |
1140 |
-+ |
1141 |
-+ <variablelist> |
1142 |
-+ <varlistentry> |
1143 |
-+ <term><varname>size</varname></term> |
1144 |
-+ <listitem><para> |
1145 |
-+ The overall size of the struct, including its items. |
1146 |
-+ </para></listitem> |
1147 |
-+ </varlistentry> |
1148 |
-+ |
1149 |
-+ <varlistentry> |
1150 |
-+ <term><varname>id</varname></term> |
1151 |
-+ <listitem><para> |
1152 |
-+ The connection's unique ID. |
1153 |
-+ </para></listitem> |
1154 |
-+ </varlistentry> |
1155 |
-+ |
1156 |
-+ <varlistentry> |
1157 |
-+ <term><varname>flags</varname></term> |
1158 |
-+ <listitem><para> |
1159 |
-+ The connection's flags as specified when it was created. |
1160 |
-+ </para></listitem> |
1161 |
-+ </varlistentry> |
1162 |
-+ |
1163 |
-+ <varlistentry> |
1164 |
-+ <term><varname>items</varname></term> |
1165 |
-+ <listitem> |
1166 |
-+ <para> |
1167 |
-+ Depending on the <varname>flags</varname> field in |
1168 |
-+ <type>struct kdbus_cmd_info</type>, items of types |
1169 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant> and |
1170 |
-+ <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant> may follow here. |
1171 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> is also allowed. |
1172 |
-+ </para> |
1173 |
-+ </listitem> |
1174 |
-+ </varlistentry> |
1175 |
-+ </variablelist> |
1176 |
-+ |
1177 |
-+ <para> |
1178 |
-+ Once the caller is finished with parsing the return buffer, it needs to |
1179 |
-+ employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in |
1180 |
-+ order to free the buffer part. See |
1181 |
-+ <citerefentry> |
1182 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1183 |
-+ <manvolnum>7</manvolnum> |
1184 |
-+ </citerefentry> |
1185 |
-+ for further information. |
1186 |
-+ </para> |
1187 |
-+ </refsect1> |
1188 |
-+ |
1189 |
-+ <refsect1> |
1190 |
-+ <title>Getting information about a connection's bus creator</title> |
1191 |
-+ <para> |
1192 |
-+ The <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> ioctl takes the same |
1193 |
-+ struct as <constant>KDBUS_CMD_CONN_INFO</constant>, but is used to |
1194 |
-+ retrieve information about the creator of the bus the connection is |
1195 |
-+ attached to. The metadata returned by this call is collected during the |
1196 |
-+ creation of the bus and is never altered afterwards, so it provides |
1197 |
-+ pristine information on the task that created the bus, at the moment when |
1198 |
-+ it did so. |
1199 |
-+ </para> |
1200 |
-+ <para> |
1201 |
-+ In response to this call, a slice in the connection's pool is allocated |
1202 |
-+ and filled with an object of type <type>struct kdbus_info</type>, |
1203 |
-+ pointed to by the ioctl's <varname>offset</varname> field. |
1204 |
-+ </para> |
1205 |
-+ |
1206 |
-+ <programlisting> |
1207 |
-+struct kdbus_info { |
1208 |
-+ __u64 size; |
1209 |
-+ __u64 id; |
1210 |
-+ __u64 flags; |
1211 |
-+ struct kdbus_item items[0]; |
1212 |
-+}; |
1213 |
-+ </programlisting> |
1214 |
-+ |
1215 |
-+ <variablelist> |
1216 |
-+ <varlistentry> |
1217 |
-+ <term><varname>size</varname></term> |
1218 |
-+ <listitem><para> |
1219 |
-+ The overall size of the struct, including its items. |
1220 |
-+ </para></listitem> |
1221 |
-+ </varlistentry> |
1222 |
-+ |
1223 |
-+ <varlistentry> |
1224 |
-+ <term><varname>id</varname></term> |
1225 |
-+ <listitem><para> |
1226 |
-+ The bus ID. |
1227 |
-+ </para></listitem> |
1228 |
-+ </varlistentry> |
1229 |
-+ |
1230 |
-+ <varlistentry> |
1231 |
-+ <term><varname>flags</varname></term> |
1232 |
-+ <listitem><para> |
1233 |
-+ The bus flags as specified when it was created. |
1234 |
-+ </para></listitem> |
1235 |
-+ </varlistentry> |
1236 |
-+ |
1237 |
-+ <varlistentry> |
1238 |
-+ <term><varname>items</varname></term> |
1239 |
-+ <listitem> |
1240 |
-+ <para> |
1241 |
-+ Metadata information is stored in items here. The item list |
1242 |
-+ contains a <constant>KDBUS_ITEM_MAKE_NAME</constant> item that |
1243 |
-+ indicates the bus name of the calling connection. |
1244 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed to probe |
1245 |
-+ for known item types. |
1246 |
-+ </para> |
1247 |
-+ </listitem> |
1248 |
-+ </varlistentry> |
1249 |
-+ </variablelist> |
1250 |
-+ |
1251 |
-+ <para> |
1252 |
-+ Once the caller is finished with parsing the return buffer, it needs to |
1253 |
-+ employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in |
1254 |
-+ order to free the buffer part. See |
1255 |
-+ <citerefentry> |
1256 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1257 |
-+ <manvolnum>7</manvolnum> |
1258 |
-+ </citerefentry> |
1259 |
-+ for further information. |
1260 |
-+ </para> |
1261 |
-+ </refsect1> |
1262 |
-+ |
1263 |
-+ <refsect1> |
1264 |
-+ <title>Updating connection details</title> |
1265 |
-+ <para> |
1266 |
-+ Some of a connection's details can be updated with the |
1267 |
-+ <constant>KDBUS_CMD_CONN_UPDATE</constant> ioctl, using the file |
1268 |
-+ descriptor that was used to create the connection. The update command |
1269 |
-+ uses the following struct. |
1270 |
-+ </para> |
1271 |
-+ |
1272 |
-+ <programlisting> |
1273 |
-+struct kdbus_cmd { |
1274 |
-+ __u64 size; |
1275 |
-+ __u64 flags; |
1276 |
-+ __u64 return_flags; |
1277 |
-+ struct kdbus_item items[0]; |
1278 |
-+}; |
1279 |
-+ </programlisting> |
1280 |
-+ |
1281 |
-+ <variablelist> |
1282 |
-+ <varlistentry> |
1283 |
-+ <term><varname>size</varname></term> |
1284 |
-+ <listitem><para> |
1285 |
-+ The overall size of the struct, including its items. |
1286 |
-+ </para></listitem> |
1287 |
-+ </varlistentry> |
1288 |
-+ |
1289 |
-+ <varlistentry> |
1290 |
-+ <term><varname>flags</varname></term> |
1291 |
-+ <listitem><para> |
1292 |
-+ Currently, no flags are supported. |
1293 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1294 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1295 |
-+ and the <varname>flags</varname> field is set to |
1296 |
-+ <constant>0</constant>. |
1297 |
-+ </para></listitem> |
1298 |
-+ </varlistentry> |
1299 |
-+ |
1300 |
-+ <varlistentry> |
1301 |
-+ <term><varname>return_flags</varname></term> |
1302 |
-+ <listitem><para> |
1303 |
-+ Flags returned by the kernel. Currently unused and always set to |
1304 |
-+ <constant>0</constant> by the kernel. |
1305 |
-+ </para></listitem> |
1306 |
-+ </varlistentry> |
1307 |
-+ |
1308 |
-+ <varlistentry> |
1309 |
-+ <term><varname>items</varname></term> |
1310 |
-+ <listitem> |
1311 |
-+ <para> |
1312 |
-+ Items to describe the connection details to be updated. The |
1313 |
-+ following item types are supported. |
1314 |
-+ </para> |
1315 |
-+ <variablelist> |
1316 |
-+ <varlistentry> |
1317 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
1318 |
-+ <listitem> |
1319 |
-+ <para> |
1320 |
-+ Supply a new set of metadata items that this connection |
1321 |
-+ permits to be sent along with messages. |
1322 |
-+ </para> |
1323 |
-+ </listitem> |
1324 |
-+ </varlistentry> |
1325 |
-+ |
1326 |
-+ <varlistentry> |
1327 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
1328 |
-+ <listitem> |
1329 |
-+ <para> |
1330 |
-+ Supply a new set of metadata items that this connection |
1331 |
-+ requests to be attached to each message. |
1332 |
-+ </para> |
1333 |
-+ </listitem> |
1334 |
-+ </varlistentry> |
1335 |
-+ |
1336 |
-+ <varlistentry> |
1337 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1338 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1339 |
-+ <listitem> |
1340 |
-+ <para> |
1341 |
-+ Policy holder connections may supply a new set of policy |
1342 |
-+ information with these items. For other connection types, |
1343 |
-+ <constant>EOPNOTSUPP</constant> is returned in |
1344 |
-+ <varname>errno</varname>. |
1345 |
-+ </para> |
1346 |
-+ </listitem> |
1347 |
-+ </varlistentry> |
1348 |
-+ |
1349 |
-+ <varlistentry> |
1350 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1351 |
-+ <listitem><para> |
1352 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1353 |
-+ kernel for known item types. See |
1354 |
-+ <citerefentry> |
1355 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1356 |
-+ <manvolnum>7</manvolnum> |
1357 |
-+ </citerefentry> |
1358 |
-+ for more details. |
1359 |
-+ </para></listitem> |
1360 |
-+ </varlistentry> |
1361 |
-+ </variablelist> |
1362 |
-+ |
1363 |
-+ <para> |
1364 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1365 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1366 |
-+ </para> |
1367 |
-+ </listitem> |
1368 |
-+ </varlistentry> |
1369 |
-+ </variablelist> |
1370 |
-+ </refsect1> |
1371 |
-+ |
1372 |
-+ <refsect1> |
1373 |
-+ <title>Termination of connections</title> |
1374 |
-+ <para> |
1375 |
-+ A connection can be terminated by simply calling |
1376 |
-+ <citerefentry> |
1377 |
-+ <refentrytitle>close</refentrytitle> |
1378 |
-+ <manvolnum>2</manvolnum> |
1379 |
-+ </citerefentry> |
1380 |
-+ on its file descriptor. All pending incoming messages will be discarded, |
1381 |
-+ and the memory allocated by the pool will be freed. |
1382 |
-+ </para> |
1383 |
-+ |
1384 |
-+ <para> |
1385 |
-+ An alternative way of closing down a connection is via the |
1386 |
-+ <constant>KDBUS_CMD_BYEBYE</constant> ioctl. This ioctl will succeed only |
1387 |
-+ if the message queue of the connection is empty at the time of closing; |
1388 |
-+ otherwise, the ioctl will fail with <varname>errno</varname> set to |
1389 |
-+ <constant>EBUSY</constant>. When this ioctl returns |
1390 |
-+ successfully, the connection has been terminated and won't accept any new |
1391 |
-+ messages from remote peers. This way, a connection can be terminated |
1392 |
-+ race-free, without losing any messages. The ioctl takes an argument of |
1393 |
-+ type <type>struct kdbus_cmd</type>. |
1394 |
-+ </para> |
1395 |
-+ |
1396 |
-+ <programlisting> |
1397 |
-+struct kdbus_cmd { |
1398 |
-+ __u64 size; |
1399 |
-+ __u64 flags; |
1400 |
-+ __u64 return_flags; |
1401 |
-+ struct kdbus_item items[0]; |
1402 |
-+}; |
1403 |
-+ </programlisting> |
1404 |
-+ |
1405 |
-+ <variablelist> |
1406 |
-+ <varlistentry> |
1407 |
-+ <term><varname>size</varname></term> |
1408 |
-+ <listitem><para> |
1409 |
-+ The overall size of the struct, including its items. |
1410 |
-+ </para></listitem> |
1411 |
-+ </varlistentry> |
1412 |
-+ |
1413 |
-+ <varlistentry> |
1414 |
-+ <term><varname>flags</varname></term> |
1415 |
-+ <listitem><para> |
1416 |
-+ Currently, no flags are supported. |
1417 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1418 |
-+ valid flags. If set, the ioctl will fail with |
1419 |
-+ <varname>errno</varname> set to <constant>EPROTO</constant>, and |
1420 |
-+ the <varname>flags</varname> field is set to <constant>0</constant>. |
1421 |
-+ </para></listitem> |
1422 |
-+ </varlistentry> |
1423 |
-+ |
1424 |
-+ <varlistentry> |
1425 |
-+ <term><varname>return_flags</varname></term> |
1426 |
-+ <listitem><para> |
1427 |
-+ Flags returned by the kernel. Currently unused and always set to |
1428 |
-+ <constant>0</constant> by the kernel. |
1429 |
-+ </para></listitem> |
1430 |
-+ </varlistentry> |
1431 |
-+ |
1432 |
-+ <varlistentry> |
1433 |
-+ <term><varname>items</varname></term> |
1434 |
-+ <listitem> |
1435 |
-+ <para> |
1436 |
-+ The following item types are supported. |
1437 |
-+ </para> |
1438 |
-+ <variablelist> |
1439 |
-+ <varlistentry> |
1440 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1441 |
-+ <listitem><para> |
1442 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1443 |
-+ kernel for known item types. See |
1444 |
-+ <citerefentry> |
1445 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1446 |
-+ <manvolnum>7</manvolnum> |
1447 |
-+ </citerefentry> |
1448 |
-+ for more details. |
1449 |
-+ </para></listitem> |
1450 |
-+ </varlistentry> |
1451 |
-+ </variablelist> |
1452 |
-+ |
1453 |
-+ <para> |
1454 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1455 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1456 |
-+ </para> |
1457 |
-+ </listitem> |
1458 |
-+ </varlistentry> |
1459 |
-+ </variablelist> |
1460 |
-+ </refsect1> |
1461 |
-+ |
1462 |
-+ <refsect1> |
1463 |
-+ <title>Return value</title> |
1464 |
-+ <para> |
1465 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
1466 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
1467 |
-+ <varname>errno</varname> is set to indicate the error. |
1468 |
-+ If the issued ioctl is illegal for the file descriptor used, |
1469 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
1470 |
-+ </para> |
1471 |
-+ |
1472 |
-+ <refsect2> |
1473 |
-+ <title> |
1474 |
-+ <constant>KDBUS_CMD_HELLO</constant> may fail with the following |
1475 |
-+ errors |
1476 |
-+ </title> |
1477 |
-+ |
1478 |
-+ <variablelist> |
1479 |
-+ <varlistentry> |
1480 |
-+ <term><constant>EFAULT</constant></term> |
1481 |
-+ <listitem><para> |
1482 |
-+ The supplied pool size was 0 or not a multiple of the page size. |
1483 |
-+ </para></listitem> |
1484 |
-+ </varlistentry> |
1485 |
-+ |
1486 |
-+ <varlistentry> |
1487 |
-+ <term><constant>EINVAL</constant></term> |
1488 |
-+ <listitem><para> |
1489 |
-+ The flags supplied in <type>struct kdbus_cmd_hello</type> |
1490 |
-+ are invalid. |
1491 |
-+ </para></listitem> |
1492 |
-+ </varlistentry> |
1493 |
-+ |
1494 |
-+ <varlistentry> |
1495 |
-+ <term><constant>EINVAL</constant></term> |
1496 |
-+ <listitem><para> |
1497 |
-+ An illegal combination of |
1498 |
-+ <constant>KDBUS_HELLO_MONITOR</constant>, |
1499 |
-+ <constant>KDBUS_HELLO_ACTIVATOR</constant> and |
1500 |
-+ <constant>KDBUS_HELLO_POLICY_HOLDER</constant> was passed in |
1501 |
-+ <varname>flags</varname>. |
1502 |
-+ </para></listitem> |
1503 |
-+ </varlistentry> |
1504 |
-+ |
1505 |
-+ <varlistentry> |
1506 |
-+ <term><constant>EINVAL</constant></term> |
1507 |
-+ <listitem><para> |
1508 |
-+ An invalid set of items was supplied. |
1509 |
-+ </para></listitem> |
1510 |
-+ </varlistentry> |
1511 |
-+ |
1512 |
-+ <varlistentry> |
1513 |
-+ <term><constant>ECONNREFUSED</constant></term> |
1514 |
-+ <listitem><para> |
1515 |
-+ The attach_flags_send field did not satisfy the requirements of |
1516 |
-+ the bus. |
1517 |
-+ </para></listitem> |
1518 |
-+ </varlistentry> |
1519 |
-+ |
1520 |
-+ <varlistentry> |
1521 |
-+ <term><constant>EPERM</constant></term> |
1522 |
-+ <listitem><para> |
1523 |
-+ A <constant>KDBUS_ITEM_CREDS</constant> items was supplied, but the |
1524 |
-+ current user is not privileged. |
1525 |
-+ </para></listitem> |
1526 |
-+ </varlistentry> |
1527 |
-+ |
1528 |
-+ <varlistentry> |
1529 |
-+ <term><constant>ESHUTDOWN</constant></term> |
1530 |
-+ <listitem><para> |
1531 |
-+ The bus you were trying to connect to has already been shut down. |
1532 |
-+ </para></listitem> |
1533 |
-+ </varlistentry> |
1534 |
-+ |
1535 |
-+ <varlistentry> |
1536 |
-+ <term><constant>EMFILE</constant></term> |
1537 |
-+ <listitem><para> |
1538 |
-+ The maximum number of connections on the bus has been reached. |
1539 |
-+ </para></listitem> |
1540 |
-+ </varlistentry> |
1541 |
-+ |
1542 |
-+ <varlistentry> |
1543 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
1544 |
-+ <listitem><para> |
1545 |
-+ The endpoint does not support the connection flags supplied in |
1546 |
-+ <type>struct kdbus_cmd_hello</type>. |
1547 |
-+ </para></listitem> |
1548 |
-+ </varlistentry> |
1549 |
-+ </variablelist> |
1550 |
-+ </refsect2> |
1551 |
-+ |
1552 |
-+ <refsect2> |
1553 |
-+ <title> |
1554 |
-+ <constant>KDBUS_CMD_BYEBYE</constant> may fail with the following |
1555 |
-+ errors |
1556 |
-+ </title> |
1557 |
-+ |
1558 |
-+ <variablelist> |
1559 |
-+ <varlistentry> |
1560 |
-+ <term><constant>EALREADY</constant></term> |
1561 |
-+ <listitem><para> |
1562 |
-+ The connection has already been shut down. |
1563 |
-+ </para></listitem> |
1564 |
-+ </varlistentry> |
1565 |
-+ |
1566 |
-+ <varlistentry> |
1567 |
-+ <term><constant>EBUSY</constant></term> |
1568 |
-+ <listitem><para> |
1569 |
-+ There are still messages queued up in the connection's pool. |
1570 |
-+ </para></listitem> |
1571 |
-+ </varlistentry> |
1572 |
-+ </variablelist> |
1573 |
-+ </refsect2> |
1574 |
-+ |
1575 |
-+ <refsect2> |
1576 |
-+ <title> |
1577 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant> may fail with the following |
1578 |
-+ errors |
1579 |
-+ </title> |
1580 |
-+ |
1581 |
-+ <variablelist> |
1582 |
-+ <varlistentry> |
1583 |
-+ <term><constant>EINVAL</constant></term> |
1584 |
-+ <listitem><para> |
1585 |
-+ Invalid flags, or neither an ID nor a name was provided, or the |
1586 |
-+ name is invalid. |
1587 |
-+ </para></listitem> |
1588 |
-+ </varlistentry> |
1589 |
-+ |
1590 |
-+ <varlistentry> |
1591 |
-+ <term><constant>ESRCH</constant></term> |
1592 |
-+ <listitem><para> |
1593 |
-+ Connection lookup by name failed. |
1594 |
-+ </para></listitem> |
1595 |
-+ </varlistentry> |
1596 |
-+ |
1597 |
-+ <varlistentry> |
1598 |
-+ <term><constant>ENXIO</constant></term> |
1599 |
-+ <listitem><para> |
1600 |
-+ No connection with the provided connection ID found. |
1601 |
-+ </para></listitem> |
1602 |
-+ </varlistentry> |
1603 |
-+ </variablelist> |
1604 |
-+ </refsect2> |
1605 |
-+ |
1606 |
-+ <refsect2> |
1607 |
-+ <title> |
1608 |
-+ <constant>KDBUS_CMD_CONN_UPDATE</constant> may fail with the following |
1609 |
-+ errors |
1610 |
-+ </title> |
1611 |
-+ |
1612 |
-+ <variablelist> |
1613 |
-+ <varlistentry> |
1614 |
-+ <term><constant>EINVAL</constant></term> |
1615 |
-+ <listitem><para> |
1616 |
-+ Illegal flags or items. |
1617 |
-+ </para></listitem> |
1618 |
-+ </varlistentry> |
1619 |
-+ |
1620 |
-+ <varlistentry> |
1621 |
-+ <term><constant>EINVAL</constant></term> |
1622 |
-+ <listitem><para> |
1623 |
-+ Wildcards submitted in policy entries, or illegal sequence |
1624 |
-+ of policy items. |
1625 |
-+ </para></listitem> |
1626 |
-+ </varlistentry> |
1627 |
-+ |
1628 |
-+ <varlistentry> |
1629 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
1630 |
-+ <listitem><para> |
1631 |
-+ Operation not supported by connection. |
1632 |
-+ </para></listitem> |
1633 |
-+ </varlistentry> |
1634 |
-+ |
1635 |
-+ <varlistentry> |
1636 |
-+ <term><constant>E2BIG</constant></term> |
1637 |
-+ <listitem><para> |
1638 |
-+ Too many policy items attached. |
1639 |
-+ </para></listitem> |
1640 |
-+ </varlistentry> |
1641 |
-+ </variablelist> |
1642 |
-+ </refsect2> |
1643 |
-+ </refsect1> |
1644 |
-+ |
1645 |
-+ <refsect1> |
1646 |
-+ <title>See Also</title> |
1647 |
-+ <simplelist type="inline"> |
1648 |
-+ <member> |
1649 |
-+ <citerefentry> |
1650 |
-+ <refentrytitle>kdbus</refentrytitle> |
1651 |
-+ <manvolnum>7</manvolnum> |
1652 |
-+ </citerefentry> |
1653 |
-+ </member> |
1654 |
-+ <member> |
1655 |
-+ <citerefentry> |
1656 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
1657 |
-+ <manvolnum>7</manvolnum> |
1658 |
-+ </citerefentry> |
1659 |
-+ </member> |
1660 |
-+ <member> |
1661 |
-+ <citerefentry> |
1662 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
1663 |
-+ <manvolnum>7</manvolnum> |
1664 |
-+ </citerefentry> |
1665 |
-+ </member> |
1666 |
-+ <member> |
1667 |
-+ <citerefentry> |
1668 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
1669 |
-+ <manvolnum>7</manvolnum> |
1670 |
-+ </citerefentry> |
1671 |
-+ </member> |
1672 |
-+ <member> |
1673 |
-+ <citerefentry> |
1674 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
1675 |
-+ <manvolnum>7</manvolnum> |
1676 |
-+ </citerefentry> |
1677 |
-+ </member> |
1678 |
-+ <member> |
1679 |
-+ <citerefentry> |
1680 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1681 |
-+ <manvolnum>7</manvolnum> |
1682 |
-+ </citerefentry> |
1683 |
-+ </member> |
1684 |
-+ <member> |
1685 |
-+ <citerefentry> |
1686 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1687 |
-+ <manvolnum>7</manvolnum> |
1688 |
-+ </citerefentry> |
1689 |
-+ </member> |
1690 |
-+ <member> |
1691 |
-+ <citerefentry> |
1692 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1693 |
-+ <manvolnum>7</manvolnum> |
1694 |
-+ </citerefentry> |
1695 |
-+ </member> |
1696 |
-+ </simplelist> |
1697 |
-+ </refsect1> |
1698 |
-+</refentry> |
1699 |
-diff --git a/Documentation/kdbus/kdbus.endpoint.xml b/Documentation/kdbus/kdbus.endpoint.xml |
1700 |
-new file mode 100644 |
1701 |
-index 0000000..6632485 |
1702 |
---- /dev/null |
1703 |
-+++ b/Documentation/kdbus/kdbus.endpoint.xml |
1704 |
-@@ -0,0 +1,429 @@ |
1705 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
1706 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
1707 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
1708 |
-+ |
1709 |
-+<refentry id="kdbus.endpoint"> |
1710 |
-+ |
1711 |
-+ <refentryinfo> |
1712 |
-+ <title>kdbus.endpoint</title> |
1713 |
-+ <productname>kdbus.endpoint</productname> |
1714 |
-+ </refentryinfo> |
1715 |
-+ |
1716 |
-+ <refmeta> |
1717 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
1718 |
-+ <manvolnum>7</manvolnum> |
1719 |
-+ </refmeta> |
1720 |
-+ |
1721 |
-+ <refnamediv> |
1722 |
-+ <refname>kdbus.endpoint</refname> |
1723 |
-+ <refpurpose>kdbus endpoint</refpurpose> |
1724 |
-+ </refnamediv> |
1725 |
-+ |
1726 |
-+ <refsect1> |
1727 |
-+ <title>Description</title> |
1728 |
-+ |
1729 |
-+ <para> |
1730 |
-+ Endpoints are entry points to a bus (see |
1731 |
-+ <citerefentry> |
1732 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
1733 |
-+ <manvolnum>7</manvolnum> |
1734 |
-+ </citerefentry>). |
1735 |
-+ By default, each bus has a default |
1736 |
-+ endpoint called 'bus'. The bus owner has the ability to create custom |
1737 |
-+ endpoints with specific names, permissions, and policy databases |
1738 |
-+ (see below). An endpoint is presented as file underneath the directory |
1739 |
-+ of the parent bus. |
1740 |
-+ </para> |
1741 |
-+ <para> |
1742 |
-+ To create a custom endpoint, open the default endpoint |
1743 |
-+ (<literal>bus</literal>) and use the |
1744 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> ioctl with |
1745 |
-+ <type>struct kdbus_cmd</type>. Custom endpoints always have a policy |
1746 |
-+ database that, by default, forbids any operation. You have to explicitly |
1747 |
-+ install policy entries to allow any operation on this endpoint. |
1748 |
-+ </para> |
1749 |
-+ <para> |
1750 |
-+ Once <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> succeeded, the new |
1751 |
-+ endpoint will appear in the filesystem |
1752 |
-+ (<citerefentry> |
1753 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
1754 |
-+ <manvolnum>7</manvolnum> |
1755 |
-+ </citerefentry>), and the used file descriptor will manage the |
1756 |
-+ newly created endpoint resource. It cannot be used to manage further |
1757 |
-+ resources and must be kept open as long as the endpoint is needed. The |
1758 |
-+ endpoint will be terminated as soon as the file descriptor is closed. |
1759 |
-+ </para> |
1760 |
-+ <para> |
1761 |
-+ Endpoint names may be chosen freely except for one restriction: the name |
1762 |
-+ must be prefixed with the numeric effective UID of the creator and a dash. |
1763 |
-+ This is required to avoid namespace clashes between different users. When |
1764 |
-+ creating an endpoint, the name that is passed in must be properly |
1765 |
-+ formatted or the kernel will refuse creation of the endpoint. Example: |
1766 |
-+ <literal>1047-my-endpoint</literal> is an acceptable name for an |
1767 |
-+ endpoint registered by a user with UID 1047. However, |
1768 |
-+ <literal>1024-my-endpoint</literal> is not, and neither is |
1769 |
-+ <literal>my-endpoint</literal>. The UID must be provided in the |
1770 |
-+ user-namespace of the bus. |
1771 |
-+ </para> |
1772 |
-+ <para> |
1773 |
-+ To create connections to a bus, use <constant>KDBUS_CMD_HELLO</constant> |
1774 |
-+ on a file descriptor returned by <function>open()</function> on an |
1775 |
-+ endpoint node. See |
1776 |
-+ <citerefentry> |
1777 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
1778 |
-+ <manvolnum>7</manvolnum> |
1779 |
-+ </citerefentry> |
1780 |
-+ for further details. |
1781 |
-+ </para> |
1782 |
-+ </refsect1> |
1783 |
-+ |
1784 |
-+ <refsect1> |
1785 |
-+ <title>Creating custom endpoints</title> |
1786 |
-+ <para> |
1787 |
-+ To create a new endpoint, the |
1788 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> command is used. Along with |
1789 |
-+ the endpoint's name, which will be used to expose the endpoint in the |
1790 |
-+ <citerefentry> |
1791 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
1792 |
-+ <manvolnum>7</manvolnum> |
1793 |
-+ </citerefentry>, |
1794 |
-+ the command also optionally takes items to set up the endpoint's |
1795 |
-+ <citerefentry> |
1796 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1797 |
-+ <manvolnum>7</manvolnum> |
1798 |
-+ </citerefentry>. |
1799 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> takes a |
1800 |
-+ <type>struct kdbus_cmd</type> argument. |
1801 |
-+ </para> |
1802 |
-+ <programlisting> |
1803 |
-+struct kdbus_cmd { |
1804 |
-+ __u64 size; |
1805 |
-+ __u64 flags; |
1806 |
-+ __u64 return_flags; |
1807 |
-+ struct kdbus_item items[0]; |
1808 |
-+}; |
1809 |
-+ </programlisting> |
1810 |
-+ |
1811 |
-+ <para>The fields in this struct are described below.</para> |
1812 |
-+ |
1813 |
-+ <variablelist> |
1814 |
-+ <varlistentry> |
1815 |
-+ <term><varname>size</varname></term> |
1816 |
-+ <listitem><para> |
1817 |
-+ The overall size of the struct, including its items. |
1818 |
-+ </para></listitem> |
1819 |
-+ </varlistentry> |
1820 |
-+ |
1821 |
-+ <varlistentry> |
1822 |
-+ <term><varname>flags</varname></term> |
1823 |
-+ <listitem><para>The flags for creation.</para> |
1824 |
-+ <variablelist> |
1825 |
-+ <varlistentry> |
1826 |
-+ <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term> |
1827 |
-+ <listitem> |
1828 |
-+ <para>Make the endpoint file group-accessible.</para> |
1829 |
-+ </listitem> |
1830 |
-+ </varlistentry> |
1831 |
-+ |
1832 |
-+ <varlistentry> |
1833 |
-+ <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term> |
1834 |
-+ <listitem> |
1835 |
-+ <para>Make the endpoint file world-accessible.</para> |
1836 |
-+ </listitem> |
1837 |
-+ </varlistentry> |
1838 |
-+ |
1839 |
-+ <varlistentry> |
1840 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
1841 |
-+ <listitem> |
1842 |
-+ <para> |
1843 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
1844 |
-+ set, no action is taken; the ioctl will return |
1845 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
1846 |
-+ field will have all bits set that are valid for this command. |
1847 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
1848 |
-+ cleared by the operation. |
1849 |
-+ </para> |
1850 |
-+ </listitem> |
1851 |
-+ </varlistentry> |
1852 |
-+ </variablelist> |
1853 |
-+ </listitem> |
1854 |
-+ </varlistentry> |
1855 |
-+ |
1856 |
-+ <varlistentry> |
1857 |
-+ <term><varname>return_flags</varname></term> |
1858 |
-+ <listitem><para> |
1859 |
-+ Flags returned by the kernel. Currently unused and always set to |
1860 |
-+ <constant>0</constant> by the kernel. |
1861 |
-+ </para></listitem> |
1862 |
-+ </varlistentry> |
1863 |
-+ |
1864 |
-+ <varlistentry> |
1865 |
-+ <term><varname>items</varname></term> |
1866 |
-+ <listitem> |
1867 |
-+ <para> |
1868 |
-+ The following items are expected for |
1869 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. |
1870 |
-+ </para> |
1871 |
-+ <variablelist> |
1872 |
-+ <varlistentry> |
1873 |
-+ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
1874 |
-+ <listitem> |
1875 |
-+ <para>Contains a string to identify the endpoint name.</para> |
1876 |
-+ </listitem> |
1877 |
-+ </varlistentry> |
1878 |
-+ |
1879 |
-+ <varlistentry> |
1880 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1881 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1882 |
-+ <listitem> |
1883 |
-+ <para> |
1884 |
-+ These items are used to set the policy attached to the |
1885 |
-+ endpoint. For more details on bus and endpoint policies, see |
1886 |
-+ <citerefentry> |
1887 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1888 |
-+ <manvolnum>7</manvolnum> |
1889 |
-+ </citerefentry>. |
1890 |
-+ </para> |
1891 |
-+ </listitem> |
1892 |
-+ </varlistentry> |
1893 |
-+ </variablelist> |
1894 |
-+ <para> |
1895 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1896 |
-+ <varname>errno</varname> set to <varname>EINVAL</varname>. |
1897 |
-+ </para> |
1898 |
-+ </listitem> |
1899 |
-+ </varlistentry> |
1900 |
-+ </variablelist> |
1901 |
-+ </refsect1> |
1902 |
-+ |
1903 |
-+ <refsect1> |
1904 |
-+ <title>Updating endpoints</title> |
1905 |
-+ <para> |
1906 |
-+ To update an existing endpoint, the |
1907 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> command is used on the file |
1908 |
-+ descriptor that was used to create the endpoint, using |
1909 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. The only relevant detail of |
1910 |
-+ the endpoint that can be updated is the policy. When the command is |
1911 |
-+ employed, the policy of the endpoint is <emphasis>replaced</emphasis> |
1912 |
-+ atomically with the new set of rules. |
1913 |
-+ The command takes a <type>struct kdbus_cmd</type> argument. |
1914 |
-+ </para> |
1915 |
-+ <programlisting> |
1916 |
-+struct kdbus_cmd { |
1917 |
-+ __u64 size; |
1918 |
-+ __u64 flags; |
1919 |
-+ __u64 return_flags; |
1920 |
-+ struct kdbus_item items[0]; |
1921 |
-+}; |
1922 |
-+ </programlisting> |
1923 |
-+ |
1924 |
-+ <para>The fields in this struct are described below.</para> |
1925 |
-+ |
1926 |
-+ <variablelist> |
1927 |
-+ <varlistentry> |
1928 |
-+ <term><varname>size</varname></term> |
1929 |
-+ <listitem><para> |
1930 |
-+ The overall size of the struct, including its items. |
1931 |
-+ </para></listitem> |
1932 |
-+ </varlistentry> |
1933 |
-+ |
1934 |
-+ <varlistentry> |
1935 |
-+ <term><varname>flags</varname></term> |
1936 |
-+ <listitem><para> |
1937 |
-+ Unused for this command. |
1938 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1939 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1940 |
-+ and the <varname>flags</varname> field is set to |
1941 |
-+ <constant>0</constant>. |
1942 |
-+ </para></listitem> |
1943 |
-+ </varlistentry> |
1944 |
-+ |
1945 |
-+ <varlistentry> |
1946 |
-+ <term><varname>return_flags</varname></term> |
1947 |
-+ <listitem><para> |
1948 |
-+ Flags returned by the kernel. Currently unused and always set to |
1949 |
-+ <constant>0</constant> by the kernel. |
1950 |
-+ </para></listitem> |
1951 |
-+ </varlistentry> |
1952 |
-+ |
1953 |
-+ <varlistentry> |
1954 |
-+ <term><varname>items</varname></term> |
1955 |
-+ <listitem> |
1956 |
-+ <para> |
1957 |
-+ The following items are expected for |
1958 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant>. |
1959 |
-+ </para> |
1960 |
-+ <variablelist> |
1961 |
-+ <varlistentry> |
1962 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1963 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1964 |
-+ <listitem> |
1965 |
-+ <para> |
1966 |
-+ These items are used to set the policy attached to the |
1967 |
-+ endpoint. For more details on bus and endpoint policies, see |
1968 |
-+ <citerefentry> |
1969 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1970 |
-+ <manvolnum>7</manvolnum> |
1971 |
-+ </citerefentry>. |
1972 |
-+ Existing policy is atomically replaced with the new rules |
1973 |
-+ provided. |
1974 |
-+ </para> |
1975 |
-+ </listitem> |
1976 |
-+ </varlistentry> |
1977 |
-+ |
1978 |
-+ <varlistentry> |
1979 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1980 |
-+ <listitem><para> |
1981 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1982 |
-+ kernel for known item types. See |
1983 |
-+ <citerefentry> |
1984 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1985 |
-+ <manvolnum>7</manvolnum> |
1986 |
-+ </citerefentry> |
1987 |
-+ for more details. |
1988 |
-+ </para></listitem> |
1989 |
-+ </varlistentry> |
1990 |
-+ </variablelist> |
1991 |
-+ <para> |
1992 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1993 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1994 |
-+ </para> |
1995 |
-+ </listitem> |
1996 |
-+ </varlistentry> |
1997 |
-+ </variablelist> |
1998 |
-+ </refsect1> |
1999 |
-+ |
2000 |
-+ <refsect1> |
2001 |
-+ <title>Return value</title> |
2002 |
-+ <para> |
2003 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
2004 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
2005 |
-+ <varname>errno</varname> is set to indicate the error. |
2006 |
-+ If the issued ioctl is illegal for the file descriptor used, |
2007 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
2008 |
-+ </para> |
2009 |
-+ |
2010 |
-+ <refsect2> |
2011 |
-+ <title> |
2012 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> may fail with the |
2013 |
-+ following errors |
2014 |
-+ </title> |
2015 |
-+ |
2016 |
-+ <variablelist> |
2017 |
-+ <varlistentry> |
2018 |
-+ <term><constant>EINVAL</constant></term> |
2019 |
-+ <listitem><para> |
2020 |
-+ The flags supplied in the <type>struct kdbus_cmd</type> |
2021 |
-+ are invalid. |
2022 |
-+ </para></listitem> |
2023 |
-+ </varlistentry> |
2024 |
-+ |
2025 |
-+ <varlistentry> |
2026 |
-+ <term><constant>EINVAL</constant></term> |
2027 |
-+ <listitem><para> |
2028 |
-+ Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and |
2029 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided. |
2030 |
-+ </para></listitem> |
2031 |
-+ </varlistentry> |
2032 |
-+ |
2033 |
-+ <varlistentry> |
2034 |
-+ <term><constant>EEXIST</constant></term> |
2035 |
-+ <listitem><para> |
2036 |
-+ An endpoint of that name already exists. |
2037 |
-+ </para></listitem> |
2038 |
-+ </varlistentry> |
2039 |
-+ |
2040 |
-+ <varlistentry> |
2041 |
-+ <term><constant>EPERM</constant></term> |
2042 |
-+ <listitem><para> |
2043 |
-+ The calling user is not privileged. See |
2044 |
-+ <citerefentry> |
2045 |
-+ <refentrytitle>kdbus</refentrytitle> |
2046 |
-+ <manvolnum>7</manvolnum> |
2047 |
-+ </citerefentry> |
2048 |
-+ for information about privileged users. |
2049 |
-+ </para></listitem> |
2050 |
-+ </varlistentry> |
2051 |
-+ </variablelist> |
2052 |
-+ </refsect2> |
2053 |
-+ |
2054 |
-+ <refsect2> |
2055 |
-+ <title> |
2056 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> may fail with the |
2057 |
-+ following errors |
2058 |
-+ </title> |
2059 |
-+ |
2060 |
-+ <variablelist> |
2061 |
-+ <varlistentry> |
2062 |
-+ <term><constant>EINVAL</constant></term> |
2063 |
-+ <listitem><para> |
2064 |
-+ The flags supplied in <type>struct kdbus_cmd</type> |
2065 |
-+ are invalid. |
2066 |
-+ </para></listitem> |
2067 |
-+ </varlistentry> |
2068 |
-+ |
2069 |
-+ <varlistentry> |
2070 |
-+ <term><constant>EINVAL</constant></term> |
2071 |
-+ <listitem><para> |
2072 |
-+ Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and |
2073 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided. |
2074 |
-+ </para></listitem> |
2075 |
-+ </varlistentry> |
2076 |
-+ </variablelist> |
2077 |
-+ </refsect2> |
2078 |
-+ </refsect1> |
2079 |
-+ |
2080 |
-+ <refsect1> |
2081 |
-+ <title>See Also</title> |
2082 |
-+ <simplelist type="inline"> |
2083 |
-+ <member> |
2084 |
-+ <citerefentry> |
2085 |
-+ <refentrytitle>kdbus</refentrytitle> |
2086 |
-+ <manvolnum>7</manvolnum> |
2087 |
-+ </citerefentry> |
2088 |
-+ </member> |
2089 |
-+ <member> |
2090 |
-+ <citerefentry> |
2091 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2092 |
-+ <manvolnum>7</manvolnum> |
2093 |
-+ </citerefentry> |
2094 |
-+ </member> |
2095 |
-+ <member> |
2096 |
-+ <citerefentry> |
2097 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2098 |
-+ <manvolnum>7</manvolnum> |
2099 |
-+ </citerefentry> |
2100 |
-+ </member> |
2101 |
-+ <member> |
2102 |
-+ <citerefentry> |
2103 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
2104 |
-+ <manvolnum>7</manvolnum> |
2105 |
-+ </citerefentry> |
2106 |
-+ </member> |
2107 |
-+ <member> |
2108 |
-+ <citerefentry> |
2109 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
2110 |
-+ <manvolnum>7</manvolnum> |
2111 |
-+ </citerefentry> |
2112 |
-+ </member> |
2113 |
-+ <member> |
2114 |
-+ <citerefentry> |
2115 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2116 |
-+ <manvolnum>7</manvolnum> |
2117 |
-+ </citerefentry> |
2118 |
-+ </member> |
2119 |
-+ <member> |
2120 |
-+ <citerefentry> |
2121 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
2122 |
-+ <manvolnum>7</manvolnum> |
2123 |
-+ </citerefentry> |
2124 |
-+ </member> |
2125 |
-+ <member> |
2126 |
-+ <citerefentry> |
2127 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
2128 |
-+ <manvolnum>7</manvolnum> |
2129 |
-+ </citerefentry> |
2130 |
-+ </member> |
2131 |
-+ </simplelist> |
2132 |
-+ </refsect1> |
2133 |
-+</refentry> |
2134 |
-diff --git a/Documentation/kdbus/kdbus.fs.xml b/Documentation/kdbus/kdbus.fs.xml |
2135 |
-new file mode 100644 |
2136 |
-index 0000000..8c2a90e |
2137 |
---- /dev/null |
2138 |
-+++ b/Documentation/kdbus/kdbus.fs.xml |
2139 |
-@@ -0,0 +1,124 @@ |
2140 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
2141 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
2142 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
2143 |
-+ |
2144 |
-+<refentry id="kdbus_fs"> |
2145 |
-+ |
2146 |
-+ <refentryinfo> |
2147 |
-+ <title>kdbus.fs</title> |
2148 |
-+ <productname>kdbus.fs</productname> |
2149 |
-+ </refentryinfo> |
2150 |
-+ |
2151 |
-+ <refmeta> |
2152 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
2153 |
-+ <manvolnum>7</manvolnum> |
2154 |
-+ </refmeta> |
2155 |
-+ |
2156 |
-+ <refnamediv> |
2157 |
-+ <refname>kdbus.fs</refname> |
2158 |
-+ <refpurpose>kdbus file system</refpurpose> |
2159 |
-+ </refnamediv> |
2160 |
-+ |
2161 |
-+ <refsect1> |
2162 |
-+ <title>File-system Layout</title> |
2163 |
-+ |
2164 |
-+ <para> |
2165 |
-+ The <emphasis>kdbusfs</emphasis> pseudo filesystem provides access to |
2166 |
-+ kdbus entities, such as <emphasis>buses</emphasis> and |
2167 |
-+ <emphasis>endpoints</emphasis>. Each time the filesystem is mounted, |
2168 |
-+ a new, isolated kdbus instance is created, which is independent from the |
2169 |
-+ other instances. |
2170 |
-+ </para> |
2171 |
-+ <para> |
2172 |
-+ The system-wide standard mount point for <emphasis>kdbusfs</emphasis> is |
2173 |
-+ <constant>/sys/fs/kdbus</constant>. |
2174 |
-+ </para> |
2175 |
-+ |
2176 |
-+ <para> |
2177 |
-+ Buses are represented as directories in the file system layout, whereas |
2178 |
-+ endpoints are exposed as files inside these directories. At the top-level, |
2179 |
-+ a <emphasis>control</emphasis> node is present, which can be opened to |
2180 |
-+ create new buses via the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. |
2181 |
-+ Each <emphasis>bus</emphasis> shows a default endpoint called |
2182 |
-+ <varname>bus</varname>, which can be opened to either create a connection |
2183 |
-+ with the <constant>KDBUS_CMD_HELLO</constant> ioctl, or to create new |
2184 |
-+ custom endpoints for the bus with |
2185 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. See |
2186 |
-+ <citerefentry> |
2187 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2188 |
-+ <manvolnum>7</manvolnum> |
2189 |
-+ </citerefentry>, |
2190 |
-+ <citerefentry> |
2191 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
2192 |
-+ <manvolnum>7</manvolnum> |
2193 |
-+ </citerefentry> and |
2194 |
-+ <citerefentry> |
2195 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2196 |
-+ <manvolnum>7</manvolnum> |
2197 |
-+ </citerefentry> |
2198 |
-+ for more details. |
2199 |
-+ </para> |
2200 |
-+ |
2201 |
-+ <para>Following, you can see an example layout of the |
2202 |
-+ <emphasis>kdbusfs</emphasis> filesystem:</para> |
2203 |
-+ |
2204 |
-+<programlisting> |
2205 |
-+ /sys/fs/kdbus/ ; mount-point |
2206 |
-+ |-- 0-system ; bus directory |
2207 |
-+ | |-- bus ; default endpoint |
2208 |
-+ | `-- 1017-custom ; custom endpoint |
2209 |
-+ |-- 1000-user ; bus directory |
2210 |
-+ | |-- bus ; default endpoint |
2211 |
-+ | |-- 1000-service-A ; custom endpoint |
2212 |
-+ | `-- 1000-service-B ; custom endpoint |
2213 |
-+ `-- control ; control file |
2214 |
-+</programlisting> |
2215 |
-+ </refsect1> |
2216 |
-+ |
2217 |
-+ <refsect1> |
2218 |
-+ <title>Mounting instances</title> |
2219 |
-+ <para> |
2220 |
-+ In order to get a new and separate kdbus environment, a new instance |
2221 |
-+ of <emphasis>kdbusfs</emphasis> can be mounted like this: |
2222 |
-+ </para> |
2223 |
-+<programlisting> |
2224 |
-+ # mount -t kdbusfs kdbusfs /tmp/new_kdbus/ |
2225 |
-+</programlisting> |
2226 |
-+ </refsect1> |
2227 |
-+ |
2228 |
-+ <refsect1> |
2229 |
-+ <title>See Also</title> |
2230 |
-+ <simplelist type="inline"> |
2231 |
-+ <member> |
2232 |
-+ <citerefentry> |
2233 |
-+ <refentrytitle>kdbus</refentrytitle> |
2234 |
-+ <manvolnum>7</manvolnum> |
2235 |
-+ </citerefentry> |
2236 |
-+ </member> |
2237 |
-+ <member> |
2238 |
-+ <citerefentry> |
2239 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2240 |
-+ <manvolnum>7</manvolnum> |
2241 |
-+ </citerefentry> |
2242 |
-+ </member> |
2243 |
-+ <member> |
2244 |
-+ <citerefentry> |
2245 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
2246 |
-+ <manvolnum>7</manvolnum> |
2247 |
-+ </citerefentry> |
2248 |
-+ </member> |
2249 |
-+ <member> |
2250 |
-+ <citerefentry> |
2251 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2252 |
-+ <manvolnum>7</manvolnum> |
2253 |
-+ </citerefentry> |
2254 |
-+ </member> |
2255 |
-+ <member> |
2256 |
-+ <citerefentry> |
2257 |
-+ <refentrytitle>mount</refentrytitle> |
2258 |
-+ <manvolnum>8</manvolnum> |
2259 |
-+ </citerefentry> |
2260 |
-+ </member> |
2261 |
-+ </simplelist> |
2262 |
-+ </refsect1> |
2263 |
-+</refentry> |
2264 |
-diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml |
2265 |
-new file mode 100644 |
2266 |
-index 0000000..ee09dfa |
2267 |
---- /dev/null |
2268 |
-+++ b/Documentation/kdbus/kdbus.item.xml |
2269 |
-@@ -0,0 +1,839 @@ |
2270 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
2271 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
2272 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
2273 |
-+ |
2274 |
-+<refentry id="kdbus"> |
2275 |
-+ |
2276 |
-+ <refentryinfo> |
2277 |
-+ <title>kdbus.item</title> |
2278 |
-+ <productname>kdbus item</productname> |
2279 |
-+ </refentryinfo> |
2280 |
-+ |
2281 |
-+ <refmeta> |
2282 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
2283 |
-+ <manvolnum>7</manvolnum> |
2284 |
-+ </refmeta> |
2285 |
-+ |
2286 |
-+ <refnamediv> |
2287 |
-+ <refname>kdbus.item</refname> |
2288 |
-+ <refpurpose>kdbus item structure, layout and usage</refpurpose> |
2289 |
-+ </refnamediv> |
2290 |
-+ |
2291 |
-+ <refsect1> |
2292 |
-+ <title>Description</title> |
2293 |
-+ |
2294 |
-+ <para> |
2295 |
-+ To flexibly augment transport structures, data blobs of type |
2296 |
-+ <type>struct kdbus_item</type> can be attached to the structs passed |
2297 |
-+ into the ioctls. Some ioctls make items of certain types mandatory, |
2298 |
-+ others are optional. Items that are unsupported by ioctls they are |
2299 |
-+ attached to will cause the ioctl to fail with <varname>errno</varname> |
2300 |
-+ set to <constant>EINVAL</constant>. |
2301 |
-+ Items are also used for information stored in a connection's |
2302 |
-+ <emphasis>pool</emphasis>, such as received messages, name lists or |
2303 |
-+ requested connection or bus owner information. Depending on the type of |
2304 |
-+ an item, its total size is either fixed or variable. |
2305 |
-+ </para> |
2306 |
-+ |
2307 |
-+ <refsect2> |
2308 |
-+ <title>Chaining items</title> |
2309 |
-+ <para> |
2310 |
-+ Whenever items are used as part of the kdbus kernel API, they are |
2311 |
-+ embedded in structs that are embedded inside structs that themselves |
2312 |
-+ include a size field containing the overall size of the structure. |
2313 |
-+ This allows multiple items to be chained up, and an item iterator |
2314 |
-+ (see below) is capable of detecting the end of an item chain. |
2315 |
-+ </para> |
2316 |
-+ </refsect2> |
2317 |
-+ |
2318 |
-+ <refsect2> |
2319 |
-+ <title>Alignment</title> |
2320 |
-+ <para> |
2321 |
-+ The kernel expects all items to be aligned to 8-byte boundaries. |
2322 |
-+ Unaligned items will cause the ioctl they are used with to fail |
2323 |
-+ with <varname>errno</varname> set to <constant>EINVAL</constant>. |
2324 |
-+ An item that has an unaligned size itself hence needs to be padded |
2325 |
-+ if it is followed by another item. |
2326 |
-+ </para> |
2327 |
-+ </refsect2> |
2328 |
-+ |
2329 |
-+ <refsect2> |
2330 |
-+ <title>Iterating items</title> |
2331 |
-+ <para> |
2332 |
-+ A simple iterator would iterate over the items until the items have |
2333 |
-+ reached the embedding structure's overall size. An example |
2334 |
-+ implementation is shown below. |
2335 |
-+ </para> |
2336 |
-+ |
2337 |
-+ <programlisting><![CDATA[ |
2338 |
-+#define KDBUS_ALIGN8(val) (((val) + 7) & ~7) |
2339 |
-+ |
2340 |
-+#define KDBUS_ITEM_NEXT(item) \ |
2341 |
-+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) |
2342 |
-+ |
2343 |
-+#define KDBUS_ITEM_FOREACH(item, head, first) \ |
2344 |
-+ for ((item) = (head)->first; \ |
2345 |
-+ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ |
2346 |
-+ ((uint8_t *)(item) >= (uint8_t *)(head)); \ |
2347 |
-+ (item) = KDBUS_ITEM_NEXT(item)) |
2348 |
-+ ]]></programlisting> |
2349 |
-+ </refsect2> |
2350 |
-+ </refsect1> |
2351 |
-+ |
2352 |
-+ <refsect1> |
2353 |
-+ <title>Item layout</title> |
2354 |
-+ <para> |
2355 |
-+ A <type>struct kdbus_item</type> consists of a |
2356 |
-+ <varname>size</varname> field, describing its overall size, and a |
2357 |
-+ <varname>type</varname> field, both 64 bit wide. They are followed by |
2358 |
-+ a union to store information that is specific to the item's type. |
2359 |
-+ The struct layout is shown below. |
2360 |
-+ </para> |
2361 |
-+ |
2362 |
-+ <programlisting> |
2363 |
-+struct kdbus_item { |
2364 |
-+ __u64 size; |
2365 |
-+ __u64 type; |
2366 |
-+ /* item payload - see below */ |
2367 |
-+ union { |
2368 |
-+ __u8 data[0]; |
2369 |
-+ __u32 data32[0]; |
2370 |
-+ __u64 data64[0]; |
2371 |
-+ char str[0]; |
2372 |
-+ |
2373 |
-+ __u64 id; |
2374 |
-+ struct kdbus_vec vec; |
2375 |
-+ struct kdbus_creds creds; |
2376 |
-+ struct kdbus_pids pids; |
2377 |
-+ struct kdbus_audit audit; |
2378 |
-+ struct kdbus_caps caps; |
2379 |
-+ struct kdbus_timestamp timestamp; |
2380 |
-+ struct kdbus_name name; |
2381 |
-+ struct kdbus_bloom_parameter bloom_parameter; |
2382 |
-+ struct kdbus_bloom_filter bloom_filter; |
2383 |
-+ struct kdbus_memfd memfd; |
2384 |
-+ int fds[0]; |
2385 |
-+ struct kdbus_notify_name_change name_change; |
2386 |
-+ struct kdbus_notify_id_change id_change; |
2387 |
-+ struct kdbus_policy_access policy_access; |
2388 |
-+ }; |
2389 |
-+}; |
2390 |
-+ </programlisting> |
2391 |
-+ |
2392 |
-+ <para> |
2393 |
-+ <type>struct kdbus_item</type> should never be used to allocate |
2394 |
-+ an item instance, as its size may grow in future releases of the API. |
2395 |
-+ Instead, it should be manually assembled by storing the |
2396 |
-+ <varname>size</varname>, <varname>type</varname> and payload to a |
2397 |
-+ struct of its own. |
2398 |
-+ </para> |
2399 |
-+ </refsect1> |
2400 |
-+ |
2401 |
-+ <refsect1> |
2402 |
-+ <title>Item types</title> |
2403 |
-+ |
2404 |
-+ <refsect2> |
2405 |
-+ <title>Negotiation item</title> |
2406 |
-+ <variablelist> |
2407 |
-+ <varlistentry> |
2408 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
2409 |
-+ <listitem><para> |
2410 |
-+ With this item is attached to any ioctl, programs can |
2411 |
-+ <emphasis>probe</emphasis> the kernel for known item types. |
2412 |
-+ The item carries an array of <type>uint64_t</type> values in |
2413 |
-+ <varname>item.data64</varname>, each set to an item type to |
2414 |
-+ probe. The kernel will reset each member of this array that is |
2415 |
-+ not recognized as valid item type to <constant>0</constant>. |
2416 |
-+ This way, users can negotiate kernel features at start-up to |
2417 |
-+ keep newer userspace compatible with older kernels. This item |
2418 |
-+ is never attached by the kernel in response to any command. |
2419 |
-+ </para></listitem> |
2420 |
-+ </varlistentry> |
2421 |
-+ </variablelist> |
2422 |
-+ </refsect2> |
2423 |
-+ |
2424 |
-+ <refsect2> |
2425 |
-+ <title>Command specific items</title> |
2426 |
-+ <variablelist> |
2427 |
-+ <varlistentry> |
2428 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
2429 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term> |
2430 |
-+ <listitem><para> |
2431 |
-+ Messages are directly copied by the sending process into the |
2432 |
-+ receiver's |
2433 |
-+ <citerefentry> |
2434 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
2435 |
-+ <manvolnum>7</manvolnum> |
2436 |
-+ </citerefentry>. |
2437 |
-+ This way, two peers can exchange data by effectively doing a |
2438 |
-+ single-copy from one process to another; the kernel will not buffer |
2439 |
-+ the data anywhere else. <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> |
2440 |
-+ is used when <emphasis>sending</emphasis> message. The item |
2441 |
-+ references a memory address when the payload data can be found. |
2442 |
-+ <constant>KDBUS_ITEM_PAYLOAD_OFF</constant> is used when messages |
2443 |
-+ are <emphasis>received</emphasis>, and the |
2444 |
-+ <constant>offset</constant> value describes the offset inside the |
2445 |
-+ receiving connection's |
2446 |
-+ <citerefentry> |
2447 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
2448 |
-+ <manvolnum>7</manvolnum> |
2449 |
-+ </citerefentry> |
2450 |
-+ where the message payload can be found. See |
2451 |
-+ <citerefentry> |
2452 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2453 |
-+ <manvolnum>7</manvolnum> |
2454 |
-+ </citerefentry> |
2455 |
-+ for more information on passing of payload data along with a |
2456 |
-+ message. |
2457 |
-+ <programlisting> |
2458 |
-+struct kdbus_vec { |
2459 |
-+ __u64 size; |
2460 |
-+ union { |
2461 |
-+ __u64 address; |
2462 |
-+ __u64 offset; |
2463 |
-+ }; |
2464 |
-+}; |
2465 |
-+ </programlisting> |
2466 |
-+ </para></listitem> |
2467 |
-+ </varlistentry> |
2468 |
-+ |
2469 |
-+ <varlistentry> |
2470 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
2471 |
-+ <listitem><para> |
2472 |
-+ Transports a file descriptor of a <emphasis>memfd</emphasis> in |
2473 |
-+ <type>struct kdbus_memfd</type> in <varname>item.memfd</varname>. |
2474 |
-+ The <varname>size</varname> field has to match the actual size of |
2475 |
-+ the memfd that was specified when it was created. The |
2476 |
-+ <varname>start</varname> parameter denotes the offset inside the |
2477 |
-+ memfd at which the referenced payload starts. See |
2478 |
-+ <citerefentry> |
2479 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2480 |
-+ <manvolnum>7</manvolnum> |
2481 |
-+ </citerefentry> |
2482 |
-+ for more information on passing of payload data along with a |
2483 |
-+ message. |
2484 |
-+ <programlisting> |
2485 |
-+struct kdbus_memfd { |
2486 |
-+ __u64 start; |
2487 |
-+ __u64 size; |
2488 |
-+ int fd; |
2489 |
-+ __u32 __pad; |
2490 |
-+}; |
2491 |
-+ </programlisting> |
2492 |
-+ </para></listitem> |
2493 |
-+ </varlistentry> |
2494 |
-+ |
2495 |
-+ <varlistentry> |
2496 |
-+ <term><constant>KDBUS_ITEM_FDS</constant></term> |
2497 |
-+ <listitem><para> |
2498 |
-+ Contains an array of <emphasis>file descriptors</emphasis>. |
2499 |
-+ When used with <constant>KDBUS_CMD_SEND</constant>, the values of |
2500 |
-+ this array must be filled with valid file descriptor numbers. |
2501 |
-+ When received as item attached to a message, the array will |
2502 |
-+ contain the numbers of the installed file descriptors, or |
2503 |
-+ <constant>-1</constant> in case an error occurred. |
2504 |
-+ In either case, the number of entries in the array is derived from |
2505 |
-+ the item's total size. See |
2506 |
-+ <citerefentry> |
2507 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2508 |
-+ <manvolnum>7</manvolnum> |
2509 |
-+ </citerefentry> |
2510 |
-+ for more information. |
2511 |
-+ </para></listitem> |
2512 |
-+ </varlistentry> |
2513 |
-+ </variablelist> |
2514 |
-+ </refsect2> |
2515 |
-+ |
2516 |
-+ <refsect2> |
2517 |
-+ <title>Items specific to some commands</title> |
2518 |
-+ <variablelist> |
2519 |
-+ <varlistentry> |
2520 |
-+ <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term> |
2521 |
-+ <listitem><para> |
2522 |
-+ Transports a file descriptor that can be used to cancel a |
2523 |
-+ synchronous <constant>KDBUS_CMD_SEND</constant> operation by |
2524 |
-+ writing to it. The file descriptor is stored in |
2525 |
-+ <varname>item.fd[0]</varname>. The item may only contain one |
2526 |
-+ file descriptor. See |
2527 |
-+ <citerefentry> |
2528 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2529 |
-+ <manvolnum>7</manvolnum> |
2530 |
-+ </citerefentry> |
2531 |
-+ for more information on this item and how to use it. |
2532 |
-+ </para></listitem> |
2533 |
-+ </varlistentry> |
2534 |
-+ |
2535 |
-+ <varlistentry> |
2536 |
-+ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
2537 |
-+ <listitem><para> |
2538 |
-+ Contains a set of <emphasis>bloom parameters</emphasis> as |
2539 |
-+ <type>struct kdbus_bloom_parameter</type> in |
2540 |
-+ <varname>item.bloom_parameter</varname>. |
2541 |
-+ The item is passed from userspace to kernel during the |
2542 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl, and returned |
2543 |
-+ verbatim when <constant>KDBUS_CMD_HELLO</constant> is called. |
2544 |
-+ The kernel does not use the bloom parameters, but they need to |
2545 |
-+ be known by each connection on the bus in order to define the |
2546 |
-+ bloom filter hash details. See |
2547 |
-+ <citerefentry> |
2548 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2549 |
-+ <manvolnum>7</manvolnum> |
2550 |
-+ </citerefentry> |
2551 |
-+ for more information on matching and bloom filters. |
2552 |
-+ <programlisting> |
2553 |
-+struct kdbus_bloom_parameter { |
2554 |
-+ __u64 size; |
2555 |
-+ __u64 n_hash; |
2556 |
-+}; |
2557 |
-+ </programlisting> |
2558 |
-+ </para></listitem> |
2559 |
-+ </varlistentry> |
2560 |
-+ |
2561 |
-+ <varlistentry> |
2562 |
-+ <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term> |
2563 |
-+ <listitem><para> |
2564 |
-+ Carries a <emphasis>bloom filter</emphasis> as |
2565 |
-+ <type>struct kdbus_bloom_filter</type> in |
2566 |
-+ <varname>item.bloom_filter</varname>. It is mandatory to send this |
2567 |
-+ item attached to a <type>struct kdbus_msg</type>, in case the |
2568 |
-+ message is a signal. This item is never transported from kernel to |
2569 |
-+ userspace. See |
2570 |
-+ <citerefentry> |
2571 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2572 |
-+ <manvolnum>7</manvolnum> |
2573 |
-+ </citerefentry> |
2574 |
-+ for more information on matching and bloom filters. |
2575 |
-+ <programlisting> |
2576 |
-+struct kdbus_bloom_filter { |
2577 |
-+ __u64 generation; |
2578 |
-+ __u64 data[0]; |
2579 |
-+}; |
2580 |
-+ </programlisting> |
2581 |
-+ </para></listitem> |
2582 |
-+ </varlistentry> |
2583 |
-+ |
2584 |
-+ <varlistentry> |
2585 |
-+ <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term> |
2586 |
-+ <listitem><para> |
2587 |
-+ Transports a <emphasis>bloom mask</emphasis> as binary data blob |
2588 |
-+ stored in <varname>item.data</varname>. This item is used to |
2589 |
-+ describe a match into a connection's match database. See |
2590 |
-+ <citerefentry> |
2591 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2592 |
-+ <manvolnum>7</manvolnum> |
2593 |
-+ </citerefentry> |
2594 |
-+ for more information on matching and bloom filters. |
2595 |
-+ </para></listitem> |
2596 |
-+ </varlistentry> |
2597 |
-+ |
2598 |
-+ <varlistentry> |
2599 |
-+ <term><constant>KDBUS_ITEM_DST_NAME</constant></term> |
2600 |
-+ <listitem><para> |
2601 |
-+ Contains a <emphasis>well-known name</emphasis> to send a |
2602 |
-+ message to, as null-terminated string in |
2603 |
-+ <varname>item.str</varname>. This item is used with |
2604 |
-+ <constant>KDBUS_CMD_SEND</constant>. See |
2605 |
-+ <citerefentry> |
2606 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2607 |
-+ <manvolnum>7</manvolnum> |
2608 |
-+ </citerefentry> |
2609 |
-+ for more information on how to send a message. |
2610 |
-+ </para></listitem> |
2611 |
-+ </varlistentry> |
2612 |
-+ |
2613 |
-+ <varlistentry> |
2614 |
-+ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
2615 |
-+ <listitem><para> |
2616 |
-+ Contains a <emphasis>bus name</emphasis> or |
2617 |
-+ <emphasis>endpoint name</emphasis>, stored as null-terminated |
2618 |
-+ string in <varname>item.str</varname>. This item is sent from |
2619 |
-+ userspace to kernel when buses or endpoints are created, and |
2620 |
-+ returned back to userspace when the bus creator information is |
2621 |
-+ queried. See |
2622 |
-+ <citerefentry> |
2623 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2624 |
-+ <manvolnum>7</manvolnum> |
2625 |
-+ </citerefentry> |
2626 |
-+ and |
2627 |
-+ <citerefentry> |
2628 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2629 |
-+ <manvolnum>7</manvolnum> |
2630 |
-+ </citerefentry>. |
2631 |
-+ </para></listitem> |
2632 |
-+ </varlistentry> |
2633 |
-+ |
2634 |
-+ <varlistentry> |
2635 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
2636 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
2637 |
-+ <listitem><para> |
2638 |
-+ Contains a set of <emphasis>attach flags</emphasis> at |
2639 |
-+ <emphasis>send</emphasis> or <emphasis>receive</emphasis> time. See |
2640 |
-+ <citerefentry> |
2641 |
-+ <refentrytitle>kdbus</refentrytitle> |
2642 |
-+ <manvolnum>7</manvolnum> |
2643 |
-+ </citerefentry>, |
2644 |
-+ <citerefentry> |
2645 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2646 |
-+ <manvolnum>7</manvolnum> |
2647 |
-+ </citerefentry> and |
2648 |
-+ <citerefentry> |
2649 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
2650 |
-+ <manvolnum>7</manvolnum> |
2651 |
-+ </citerefentry> |
2652 |
-+ for more information on attach flags. |
2653 |
-+ </para></listitem> |
2654 |
-+ </varlistentry> |
2655 |
-+ |
2656 |
-+ <varlistentry> |
2657 |
-+ <term><constant>KDBUS_ITEM_ID</constant></term> |
2658 |
-+ <listitem><para> |
2659 |
-+ Transports a connection's <emphasis>numerical ID</emphasis> of |
2660 |
-+ a connection as <type>uint64_t</type> value in |
2661 |
-+ <varname>item.id</varname>. |
2662 |
-+ </para></listitem> |
2663 |
-+ </varlistentry> |
2664 |
-+ |
2665 |
-+ <varlistentry> |
2666 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
2667 |
-+ <listitem><para> |
2668 |
-+ Transports a name associated with the |
2669 |
-+ <emphasis>name registry</emphasis> as null-terminated string as |
2670 |
-+ <type>struct kdbus_name</type> in |
2671 |
-+ <varname>item.name</varname>. The <varname>flags</varname> |
2672 |
-+ contains the flags of the name. See |
2673 |
-+ <citerefentry> |
2674 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
2675 |
-+ <manvolnum>7</manvolnum> |
2676 |
-+ </citerefentry> |
2677 |
-+ for more information on how to access the name registry of a bus. |
2678 |
-+ <programlisting> |
2679 |
-+struct kdbus_name { |
2680 |
-+ __u64 flags; |
2681 |
-+ char name[0]; |
2682 |
-+}; |
2683 |
-+ </programlisting> |
2684 |
-+ </para></listitem> |
2685 |
-+ </varlistentry> |
2686 |
-+ </variablelist> |
2687 |
-+ </refsect2> |
2688 |
-+ |
2689 |
-+ <refsect2> |
2690 |
-+ <title>Items attached by the kernel as metadata</title> |
2691 |
-+ |
2692 |
-+ <variablelist> |
2693 |
-+ <varlistentry> |
2694 |
-+ <term><constant>KDBUS_ITEM_TIMESTAMP</constant></term> |
2695 |
-+ <listitem><para> |
2696 |
-+ Contains both the <emphasis>monotonic</emphasis> and the |
2697 |
-+ <emphasis>realtime</emphasis> timestamp, taken when the message |
2698 |
-+ was processed on the kernel side. |
2699 |
-+ Stored as <type>struct kdbus_timestamp</type> in |
2700 |
-+ <varname>item.timestamp</varname>. |
2701 |
-+ <programlisting> |
2702 |
-+struct kdbus_timestamp { |
2703 |
-+ __u64 seqnum; |
2704 |
-+ __u64 monotonic_ns; |
2705 |
-+ __u64 realtime_ns; |
2706 |
-+}; |
2707 |
-+ </programlisting> |
2708 |
-+ </para></listitem> |
2709 |
-+ </varlistentry> |
2710 |
-+ |
2711 |
-+ <varlistentry> |
2712 |
-+ <term><constant>KDBUS_ITEM_CREDS</constant></term> |
2713 |
-+ <listitem><para> |
2714 |
-+ Contains a set of <emphasis>user</emphasis> and |
2715 |
-+ <emphasis>group</emphasis> information as 32-bit values, in the |
2716 |
-+ usual four flavors: real, effective, saved and filesystem related. |
2717 |
-+ Stored as <type>struct kdbus_creds</type> in |
2718 |
-+ <varname>item.creds</varname>. |
2719 |
-+ <programlisting> |
2720 |
-+struct kdbus_creds { |
2721 |
-+ __u32 uid; |
2722 |
-+ __u32 euid; |
2723 |
-+ __u32 suid; |
2724 |
-+ __u32 fsuid; |
2725 |
-+ __u32 gid; |
2726 |
-+ __u32 egid; |
2727 |
-+ __u32 sgid; |
2728 |
-+ __u32 fsgid; |
2729 |
-+}; |
2730 |
-+ </programlisting> |
2731 |
-+ </para></listitem> |
2732 |
-+ </varlistentry> |
2733 |
-+ |
2734 |
-+ <varlistentry> |
2735 |
-+ <term><constant>KDBUS_ITEM_PIDS</constant></term> |
2736 |
-+ <listitem><para> |
2737 |
-+ Contains the <emphasis>PID</emphasis>, <emphasis>TID</emphasis> |
2738 |
-+ and <emphasis>parent PID (PPID)</emphasis> of a remote peer. |
2739 |
-+ Stored as <type>struct kdbus_pids</type> in |
2740 |
-+ <varname>item.pids</varname>. |
2741 |
-+ <programlisting> |
2742 |
-+struct kdbus_pids { |
2743 |
-+ __u64 pid; |
2744 |
-+ __u64 tid; |
2745 |
-+ __u64 ppid; |
2746 |
-+}; |
2747 |
-+ </programlisting> |
2748 |
-+ </para></listitem> |
2749 |
-+ </varlistentry> |
2750 |
-+ |
2751 |
-+ <varlistentry> |
2752 |
-+ <term><constant>KDBUS_ITEM_AUXGROUPS</constant></term> |
2753 |
-+ <listitem><para> |
2754 |
-+ Contains the <emphasis>auxiliary (supplementary) groups</emphasis> |
2755 |
-+ a remote peer is a member of, stored as array of |
2756 |
-+ <type>uint32_t</type> values in <varname>item.data32</varname>. |
2757 |
-+ The array length can be determined by looking at the item's total |
2758 |
-+ size, subtracting the size of the header and dividing the |
2759 |
-+ remainder by <constant>sizeof(uint32_t)</constant>. |
2760 |
-+ </para></listitem> |
2761 |
-+ </varlistentry> |
2762 |
-+ |
2763 |
-+ <varlistentry> |
2764 |
-+ <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term> |
2765 |
-+ <listitem><para> |
2766 |
-+ Contains a <emphasis>well-known name</emphasis> currently owned |
2767 |
-+ by a connection. The name is stored as null-terminated string in |
2768 |
-+ <varname>item.str</varname>. Its length can also be derived from |
2769 |
-+ the item's total size. |
2770 |
-+ </para></listitem> |
2771 |
-+ </varlistentry> |
2772 |
-+ |
2773 |
-+ <varlistentry> |
2774 |
-+ <term><constant>KDBUS_ITEM_TID_COMM</constant> [*]</term> |
2775 |
-+ <listitem><para> |
2776 |
-+ Contains the <emphasis>comm</emphasis> string of a task's |
2777 |
-+ <emphasis>TID</emphasis> (thread ID), stored as null-terminated |
2778 |
-+ string in <varname>item.str</varname>. Its length can also be |
2779 |
-+ derived from the item's total size. Receivers of this item should |
2780 |
-+ not use its contents for any kind of security measures. See below. |
2781 |
-+ </para></listitem> |
2782 |
-+ </varlistentry> |
2783 |
-+ |
2784 |
-+ <varlistentry> |
2785 |
-+ <term><constant>KDBUS_ITEM_PID_COMM</constant> [*]</term> |
2786 |
-+ <listitem><para> |
2787 |
-+ Contains the <emphasis>comm</emphasis> string of a task's |
2788 |
-+ <emphasis>PID</emphasis> (process ID), stored as null-terminated |
2789 |
-+ string in <varname>item.str</varname>. Its length can also be |
2790 |
-+ derived from the item's total size. Receivers of this item should |
2791 |
-+ not use its contents for any kind of security measures. See below. |
2792 |
-+ </para></listitem> |
2793 |
-+ </varlistentry> |
2794 |
-+ |
2795 |
-+ <varlistentry> |
2796 |
-+ <term><constant>KDBUS_ITEM_EXE</constant> [*]</term> |
2797 |
-+ <listitem><para> |
2798 |
-+ Contains the <emphasis>path to the executable</emphasis> of a task, |
2799 |
-+ stored as null-terminated string in <varname>item.str</varname>. Its |
2800 |
-+ length can also be derived from the item's total size. Receivers of |
2801 |
-+ this item should not use its contents for any kind of security |
2802 |
-+ measures. See below. |
2803 |
-+ </para></listitem> |
2804 |
-+ </varlistentry> |
2805 |
-+ |
2806 |
-+ <varlistentry> |
2807 |
-+ <term><constant>KDBUS_ITEM_CMDLINE</constant> [*]</term> |
2808 |
-+ <listitem><para> |
2809 |
-+ Contains the <emphasis>command line arguments</emphasis> of a |
2810 |
-+ task, stored as an <emphasis>array</emphasis> of null-terminated |
2811 |
-+ strings in <varname>item.str</varname>. The total length of all |
2812 |
-+ strings in the array can be derived from the item's total size. |
2813 |
-+ Receivers of this item should not use its contents for any kind |
2814 |
-+ of security measures. See below. |
2815 |
-+ </para></listitem> |
2816 |
-+ </varlistentry> |
2817 |
-+ |
2818 |
-+ <varlistentry> |
2819 |
-+ <term><constant>KDBUS_ITEM_CGROUP</constant></term> |
2820 |
-+ <listitem><para> |
2821 |
-+ Contains the <emphasis>cgroup path</emphasis> of a task, stored |
2822 |
-+ as null-terminated string in <varname>item.str</varname>. Its |
2823 |
-+ length can also be derived from the item's total size. |
2824 |
-+ </para></listitem> |
2825 |
-+ </varlistentry> |
2826 |
-+ |
2827 |
-+ <varlistentry> |
2828 |
-+ <term><constant>KDBUS_ITEM_CAPS</constant></term> |
2829 |
-+ <listitem><para> |
2830 |
-+ Contains sets of <emphasis>capabilities</emphasis>, stored as |
2831 |
-+ <type>struct kdbus_caps</type> in <varname>item.caps</varname>. |
2832 |
-+ As the item size may increase in the future, programs should be |
2833 |
-+ written in a way that it takes |
2834 |
-+ <varname>item.caps.last_cap</varname> into account, and derive |
2835 |
-+ the number of sets and rows from the item size and the reported |
2836 |
-+ number of valid capability bits. |
2837 |
-+ <programlisting> |
2838 |
-+struct kdbus_caps { |
2839 |
-+ __u32 last_cap; |
2840 |
-+ __u32 caps[0]; |
2841 |
-+}; |
2842 |
-+ </programlisting> |
2843 |
-+ </para></listitem> |
2844 |
-+ </varlistentry> |
2845 |
-+ |
2846 |
-+ <varlistentry> |
2847 |
-+ <term><constant>KDBUS_ITEM_SECLABEL</constant></term> |
2848 |
-+ <listitem><para> |
2849 |
-+ Contains the <emphasis>LSM label</emphasis> of a task, stored as |
2850 |
-+ null-terminated string in <varname>item.str</varname>. Its length |
2851 |
-+ can also be derived from the item's total size. |
2852 |
-+ </para></listitem> |
2853 |
-+ </varlistentry> |
2854 |
-+ |
2855 |
-+ <varlistentry> |
2856 |
-+ <term><constant>KDBUS_ITEM_AUDIT</constant></term> |
2857 |
-+ <listitem><para> |
2858 |
-+ Contains the audit <emphasis>sessionid</emphasis> and |
2859 |
-+ <emphasis>loginuid</emphasis> of a task, stored as |
2860 |
-+ <type>struct kdbus_audit</type> in |
2861 |
-+ <varname>item.audit</varname>. |
2862 |
-+ <programlisting> |
2863 |
-+struct kdbus_audit { |
2864 |
-+ __u32 sessionid; |
2865 |
-+ __u32 loginuid; |
2866 |
-+}; |
2867 |
-+ </programlisting> |
2868 |
-+ </para></listitem> |
2869 |
-+ </varlistentry> |
2870 |
-+ |
2871 |
-+ <varlistentry> |
2872 |
-+ <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term> |
2873 |
-+ <listitem><para> |
2874 |
-+ Contains the <emphasis>connection description</emphasis>, as set |
2875 |
-+ by <constant>KDBUS_CMD_HELLO</constant> or |
2876 |
-+ <constant>KDBUS_CMD_CONN_UPDATE</constant>, stored as |
2877 |
-+ null-terminated string in <varname>item.str</varname>. Its length |
2878 |
-+ can also be derived from the item's total size. |
2879 |
-+ </para></listitem> |
2880 |
-+ </varlistentry> |
2881 |
-+ </variablelist> |
2882 |
-+ |
2883 |
-+ <para> |
2884 |
-+ All metadata is automatically translated into the |
2885 |
-+ <emphasis>namespaces</emphasis> of the task that receives them. See |
2886 |
-+ <citerefentry> |
2887 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2888 |
-+ <manvolnum>7</manvolnum> |
2889 |
-+ </citerefentry> |
2890 |
-+ for more information. |
2891 |
-+ </para> |
2892 |
-+ |
2893 |
-+ <para> |
2894 |
-+ [*] Note that the content stored in metadata items of type |
2895 |
-+ <constant>KDBUS_ITEM_TID_COMM</constant>, |
2896 |
-+ <constant>KDBUS_ITEM_PID_COMM</constant>, |
2897 |
-+ <constant>KDBUS_ITEM_EXE</constant> and |
2898 |
-+ <constant>KDBUS_ITEM_CMDLINE</constant> |
2899 |
-+ can easily be tampered by the sending tasks. Therefore, they should |
2900 |
-+ <emphasis>not</emphasis> be used for any sort of security relevant |
2901 |
-+ assumptions. The only reason they are transmitted is to let |
2902 |
-+ receivers know about details that were set when metadata was |
2903 |
-+ collected, even though the task they were collected from is not |
2904 |
-+ active any longer when the items are received. |
2905 |
-+ </para> |
2906 |
-+ </refsect2> |
2907 |
-+ |
2908 |
-+ <refsect2> |
2909 |
-+ <title>Items used for policy entries, matches and notifications</title> |
2910 |
-+ |
2911 |
-+ <variablelist> |
2912 |
-+ <varlistentry> |
2913 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
2914 |
-+ <listitem><para> |
2915 |
-+ This item describes a <emphasis>policy access</emphasis> entry to |
2916 |
-+ access the policy database of a |
2917 |
-+ <citerefentry> |
2918 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2919 |
-+ <manvolnum>7</manvolnum> |
2920 |
-+ </citerefentry> or |
2921 |
-+ <citerefentry> |
2922 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2923 |
-+ <manvolnum>7</manvolnum> |
2924 |
-+ </citerefentry>. |
2925 |
-+ Please refer to |
2926 |
-+ <citerefentry> |
2927 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
2928 |
-+ <manvolnum>7</manvolnum> |
2929 |
-+ </citerefentry> |
2930 |
-+ for more information on the policy database and how to access it. |
2931 |
-+ <programlisting> |
2932 |
-+struct kdbus_policy_access { |
2933 |
-+ __u64 type; |
2934 |
-+ __u64 access; |
2935 |
-+ __u64 id; |
2936 |
-+}; |
2937 |
-+ </programlisting> |
2938 |
-+ </para></listitem> |
2939 |
-+ </varlistentry> |
2940 |
-+ |
2941 |
-+ <varlistentry> |
2942 |
-+ <term><constant>KDBUS_ITEM_ID_ADD</constant></term> |
2943 |
-+ <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term> |
2944 |
-+ <listitem><para> |
2945 |
-+ This item is sent as attachment to a |
2946 |
-+ <emphasis>kernel notification</emphasis> and indicates that a |
2947 |
-+ new connection was created on the bus, or that a connection was |
2948 |
-+ disconnected, respectively. It stores a |
2949 |
-+ <type>struct kdbus_notify_id_change</type> in |
2950 |
-+ <varname>item.id_change</varname>. |
2951 |
-+ The <varname>id</varname> field contains the numeric ID of the |
2952 |
-+ connection that was added or removed, and <varname>flags</varname> |
2953 |
-+ is set to the connection flags, as passed by |
2954 |
-+ <constant>KDBUS_CMD_HELLO</constant>. See |
2955 |
-+ <citerefentry> |
2956 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2957 |
-+ <manvolnum>7</manvolnum> |
2958 |
-+ </citerefentry> |
2959 |
-+ and |
2960 |
-+ <citerefentry> |
2961 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2962 |
-+ <manvolnum>7</manvolnum> |
2963 |
-+ </citerefentry> |
2964 |
-+ for more information on matches and notification messages. |
2965 |
-+ <programlisting> |
2966 |
-+struct kdbus_notify_id_change { |
2967 |
-+ __u64 id; |
2968 |
-+ __u64 flags; |
2969 |
-+}; |
2970 |
-+ </programlisting> |
2971 |
-+ </para></listitem> |
2972 |
-+ </varlistentry> |
2973 |
-+ |
2974 |
-+ <varlistentry> |
2975 |
-+ <term><constant>KDBUS_ITEM_NAME_ADD</constant></term> |
2976 |
-+ <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term> |
2977 |
-+ <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term> |
2978 |
-+ <listitem><para> |
2979 |
-+ This item is sent as attachment to a |
2980 |
-+ <emphasis>kernel notification</emphasis> and indicates that a |
2981 |
-+ <emphasis>well-known name</emphasis> appeared, disappeared or |
2982 |
-+ transferred to another owner on the bus. It stores a |
2983 |
-+ <type>struct kdbus_notify_name_change</type> in |
2984 |
-+ <varname>item.name_change</varname>. |
2985 |
-+ <varname>old_id</varname> describes the former owner of the name |
2986 |
-+ and is set to <constant>0</constant> values in case of |
2987 |
-+ <constant>KDBUS_ITEM_NAME_ADD</constant>. |
2988 |
-+ <varname>new_id</varname> describes the new owner of the name and |
2989 |
-+ is set to <constant>0</constant> values in case of |
2990 |
-+ <constant>KDBUS_ITEM_NAME_REMOVE</constant>. |
2991 |
-+ The <varname>name</varname> field contains the well-known name the |
2992 |
-+ notification is about, as null-terminated string. See |
2993 |
-+ <citerefentry> |
2994 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2995 |
-+ <manvolnum>7</manvolnum> |
2996 |
-+ </citerefentry> |
2997 |
-+ and |
2998 |
-+ <citerefentry> |
2999 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3000 |
-+ <manvolnum>7</manvolnum> |
3001 |
-+ </citerefentry> |
3002 |
-+ for more information on matches and notification messages. |
3003 |
-+ <programlisting> |
3004 |
-+struct kdbus_notify_name_change { |
3005 |
-+ struct kdbus_notify_id_change old_id; |
3006 |
-+ struct kdbus_notify_id_change new_id; |
3007 |
-+ char name[0]; |
3008 |
-+}; |
3009 |
-+ </programlisting> |
3010 |
-+ </para></listitem> |
3011 |
-+ </varlistentry> |
3012 |
-+ |
3013 |
-+ <varlistentry> |
3014 |
-+ <term><constant>KDBUS_ITEM_REPLY_TIMEOUT</constant></term> |
3015 |
-+ <listitem><para> |
3016 |
-+ This item is sent as attachment to a |
3017 |
-+ <emphasis>kernel notification</emphasis>. It informs the receiver |
3018 |
-+ that an expected reply to a message was not received in time. |
3019 |
-+ The remote peer ID and the message cookie are stored in the message |
3020 |
-+ header. See |
3021 |
-+ <citerefentry> |
3022 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3023 |
-+ <manvolnum>7</manvolnum> |
3024 |
-+ </citerefentry> |
3025 |
-+ for more information about messages, timeouts and notifications. |
3026 |
-+ </para></listitem> |
3027 |
-+ </varlistentry> |
3028 |
-+ |
3029 |
-+ <varlistentry> |
3030 |
-+ <term><constant>KDBUS_ITEM_REPLY_DEAD</constant></term> |
3031 |
-+ <listitem><para> |
3032 |
-+ This item is sent as attachment to a |
3033 |
-+ <emphasis>kernel notification</emphasis>. It informs the receiver |
3034 |
-+ that a remote connection a reply is expected from was disconnected |
3035 |
-+ before that reply was sent. The remote peer ID and the message |
3036 |
-+ cookie are stored in the message header. See |
3037 |
-+ <citerefentry> |
3038 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3039 |
-+ <manvolnum>7</manvolnum> |
3040 |
-+ </citerefentry> |
3041 |
-+ for more information about messages, timeouts and notifications. |
3042 |
-+ </para></listitem> |
3043 |
-+ </varlistentry> |
3044 |
-+ </variablelist> |
3045 |
-+ </refsect2> |
3046 |
-+ </refsect1> |
3047 |
-+ |
3048 |
-+ <refsect1> |
3049 |
-+ <title>See Also</title> |
3050 |
-+ <simplelist type="inline"> |
3051 |
-+ <member> |
3052 |
-+ <citerefentry> |
3053 |
-+ <refentrytitle>kdbus</refentrytitle> |
3054 |
-+ <manvolnum>7</manvolnum> |
3055 |
-+ </citerefentry> |
3056 |
-+ </member> |
3057 |
-+ <member> |
3058 |
-+ <citerefentry> |
3059 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
3060 |
-+ <manvolnum>7</manvolnum> |
3061 |
-+ </citerefentry> |
3062 |
-+ </member> |
3063 |
-+ <member> |
3064 |
-+ <citerefentry> |
3065 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
3066 |
-+ <manvolnum>7</manvolnum> |
3067 |
-+ </citerefentry> |
3068 |
-+ </member> |
3069 |
-+ <member> |
3070 |
-+ <citerefentry> |
3071 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
3072 |
-+ <manvolnum>7</manvolnum> |
3073 |
-+ </citerefentry> |
3074 |
-+ </member> |
3075 |
-+ <member> |
3076 |
-+ <citerefentry> |
3077 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
3078 |
-+ <manvolnum>7</manvolnum> |
3079 |
-+ </citerefentry> |
3080 |
-+ </member> |
3081 |
-+ <member> |
3082 |
-+ <citerefentry> |
3083 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3084 |
-+ <manvolnum>7</manvolnum> |
3085 |
-+ </citerefentry> |
3086 |
-+ </member> |
3087 |
-+ <member> |
3088 |
-+ <citerefentry> |
3089 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
3090 |
-+ <manvolnum>7</manvolnum> |
3091 |
-+ </citerefentry> |
3092 |
-+ </member> |
3093 |
-+ <member> |
3094 |
-+ <citerefentry> |
3095 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
3096 |
-+ <manvolnum>7</manvolnum> |
3097 |
-+ </citerefentry> |
3098 |
-+ </member> |
3099 |
-+ <member> |
3100 |
-+ <citerefentry> |
3101 |
-+ <refentrytitle>memfd_create</refentrytitle> |
3102 |
-+ <manvolnum>2</manvolnum> |
3103 |
-+ </citerefentry> |
3104 |
-+ </member> |
3105 |
-+ </simplelist> |
3106 |
-+ </refsect1> |
3107 |
-+ |
3108 |
-+</refentry> |
3109 |
-diff --git a/Documentation/kdbus/kdbus.match.xml b/Documentation/kdbus/kdbus.match.xml |
3110 |
-new file mode 100644 |
3111 |
-index 0000000..ae38e04 |
3112 |
---- /dev/null |
3113 |
-+++ b/Documentation/kdbus/kdbus.match.xml |
3114 |
-@@ -0,0 +1,555 @@ |
3115 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
3116 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
3117 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
3118 |
-+ |
3119 |
-+<refentry id="kdbus.match"> |
3120 |
-+ |
3121 |
-+ <refentryinfo> |
3122 |
-+ <title>kdbus.match</title> |
3123 |
-+ <productname>kdbus.match</productname> |
3124 |
-+ </refentryinfo> |
3125 |
-+ |
3126 |
-+ <refmeta> |
3127 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
3128 |
-+ <manvolnum>7</manvolnum> |
3129 |
-+ </refmeta> |
3130 |
-+ |
3131 |
-+ <refnamediv> |
3132 |
-+ <refname>kdbus.match</refname> |
3133 |
-+ <refpurpose>kdbus match</refpurpose> |
3134 |
-+ </refnamediv> |
3135 |
-+ |
3136 |
-+ <refsect1> |
3137 |
-+ <title>Description</title> |
3138 |
-+ |
3139 |
-+ <para> |
3140 |
-+ kdbus connections can install matches in order to subscribe to signal |
3141 |
-+ messages sent on the bus. Such signal messages can be either directed |
3142 |
-+ to a single connection (by setting a specific connection ID in |
3143 |
-+ <varname>struct kdbus_msg.dst_id</varname> or by sending it to a |
3144 |
-+ well-known name), or to potentially <emphasis>all</emphasis> currently |
3145 |
-+ active connections on the bus (by setting |
3146 |
-+ <varname>struct kdbus_msg.dst_id</varname> to |
3147 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant>). |
3148 |
-+ A signal message always has the <constant>KDBUS_MSG_SIGNAL</constant> |
3149 |
-+ bit set in the <varname>flags</varname> bitfield. |
3150 |
-+ Also, signal messages can originate from either the kernel (called |
3151 |
-+ <emphasis>notifications</emphasis>), or from other bus connections. |
3152 |
-+ In either case, a bus connection needs to have a suitable |
3153 |
-+ <emphasis>match</emphasis> installed in order to receive any signal |
3154 |
-+ message. Without any rules installed in the connection, no signal message |
3155 |
-+ will be received. |
3156 |
-+ </para> |
3157 |
-+ </refsect1> |
3158 |
-+ |
3159 |
-+ <refsect1> |
3160 |
-+ <title>Matches for signal messages from other connections</title> |
3161 |
-+ <para> |
3162 |
-+ Matches for messages from other connections (not kernel notifications) |
3163 |
-+ are implemented as bloom filters (see below). The sender adds certain |
3164 |
-+ properties of the message as elements to a bloom filter bit field, and |
3165 |
-+ sends that along with the signal message. |
3166 |
-+ |
3167 |
-+ The receiving connection adds the message properties it is interested in |
3168 |
-+ as elements to a bloom mask bit field, and uploads the mask as match rule, |
3169 |
-+ possibly along with some other rules to further limit the match. |
3170 |
-+ |
3171 |
-+ The kernel will match the signal message's bloom filter against the |
3172 |
-+ connection's bloom mask (simply by &-ing it), and will decide whether |
3173 |
-+ the message should be delivered to a connection. |
3174 |
-+ </para> |
3175 |
-+ <para> |
3176 |
-+ The kernel has no notion of any specific properties of the signal message, |
3177 |
-+ all it sees are the bit fields of the bloom filter and the mask to match |
3178 |
-+ against. The use of bloom filters allows simple and efficient matching, |
3179 |
-+ without exposing any message properties or internals to the kernel side. |
3180 |
-+ Clients need to deal with the fact that they might receive signal messages |
3181 |
-+ which they did not subscribe to, as the bloom filter might allow |
3182 |
-+ false-positives to pass the filter. |
3183 |
-+ |
3184 |
-+ To allow the future extension of the set of elements in the bloom filter, |
3185 |
-+ the filter specifies a <emphasis>generation</emphasis> number. A later |
3186 |
-+ generation must always contain all elements of the set of the previous |
3187 |
-+ generation, but can add new elements to the set. The match rules mask can |
3188 |
-+ carry an array with all previous generations of masks individually stored. |
3189 |
-+ When the filter and mask are matched by the kernel, the mask with the |
3190 |
-+ closest matching generation is selected as the index into the mask array. |
3191 |
-+ </para> |
3192 |
-+ </refsect1> |
3193 |
-+ |
3194 |
-+ <refsect1> |
3195 |
-+ <title>Bloom filters</title> |
3196 |
-+ <para> |
3197 |
-+ Bloom filters allow checking whether a given word is present in a |
3198 |
-+ dictionary. This allows connections to set up a mask for information it |
3199 |
-+ is interested in, and will be delivered signal messages that have a |
3200 |
-+ matching filter. |
3201 |
-+ |
3202 |
-+ For general information, see |
3203 |
-+ <ulink url="https://en.wikipedia.org/wiki/Bloom_filter">the Wikipedia |
3204 |
-+ article on bloom filters</ulink>. |
3205 |
-+ </para> |
3206 |
-+ <para> |
3207 |
-+ The size of the bloom filter is defined per bus when it is created, in |
3208 |
-+ <varname>kdbus_bloom_parameter.size</varname>. All bloom filters attached |
3209 |
-+ to signal messages on the bus must match this size, and all bloom filter |
3210 |
-+ matches uploaded by connections must also match the size, or a multiple |
3211 |
-+ thereof (see below). |
3212 |
-+ |
3213 |
-+ The calculation of the mask has to be done in userspace applications. The |
3214 |
-+ kernel just checks the bitmasks to decide whether or not to let the |
3215 |
-+ message pass. All bits in the mask must match the filter in and bit-wise |
3216 |
-+ <emphasis>AND</emphasis> logic, but the mask may have more bits set than |
3217 |
-+ the filter. Consequently, false positive matches are expected to happen, |
3218 |
-+ and programs must deal with that fact by checking the contents of the |
3219 |
-+ payload again at receive time. |
3220 |
-+ </para> |
3221 |
-+ <para> |
3222 |
-+ Masks are entities that are always passed to the kernel as part of a |
3223 |
-+ match (with an item of type <constant>KDBUS_ITEM_BLOOM_MASK</constant>), |
3224 |
-+ and filters can be attached to signals, with an item of type |
3225 |
-+ <constant>KDBUS_ITEM_BLOOM_FILTER</constant>. For a filter to match, all |
3226 |
-+ its bits have to be set in the match mask as well. |
3227 |
-+ </para> |
3228 |
-+ <para> |
3229 |
-+ For example, consider a bus that has a bloom size of 8 bytes, and the |
3230 |
-+ following mask/filter combinations: |
3231 |
-+ </para> |
3232 |
-+ <programlisting><![CDATA[ |
3233 |
-+ filter 0x0101010101010101 |
3234 |
-+ mask 0x0101010101010101 |
3235 |
-+ -> matches |
3236 |
-+ |
3237 |
-+ filter 0x0303030303030303 |
3238 |
-+ mask 0x0101010101010101 |
3239 |
-+ -> doesn't match |
3240 |
-+ |
3241 |
-+ filter 0x0101010101010101 |
3242 |
-+ mask 0x0303030303030303 |
3243 |
-+ -> matches |
3244 |
-+ ]]></programlisting> |
3245 |
-+ |
3246 |
-+ <para> |
3247 |
-+ Hence, in order to catch all messages, a mask filled with |
3248 |
-+ <constant>0xff</constant> bytes can be installed as a wildcard match rule. |
3249 |
-+ </para> |
3250 |
-+ |
3251 |
-+ <refsect2> |
3252 |
-+ <title>Generations</title> |
3253 |
-+ |
3254 |
-+ <para> |
3255 |
-+ Uploaded matches may contain multiple masks, which have to be as large |
3256 |
-+ as the bloom filter size defined by the bus. Each block of a mask is |
3257 |
-+ called a <emphasis>generation</emphasis>, starting at index 0. |
3258 |
-+ |
3259 |
-+ At match time, when a signal is about to be delivered, a bloom mask |
3260 |
-+ generation is passed, which denotes which of the bloom masks the filter |
3261 |
-+ should be matched against. This allows programs to provide backward |
3262 |
-+ compatible masks at upload time, while older clients can still match |
3263 |
-+ against older versions of filters. |
3264 |
-+ </para> |
3265 |
-+ </refsect2> |
3266 |
-+ </refsect1> |
3267 |
-+ |
3268 |
-+ <refsect1> |
3269 |
-+ <title>Matches for kernel notifications</title> |
3270 |
-+ <para> |
3271 |
-+ To receive kernel generated notifications (see |
3272 |
-+ <citerefentry> |
3273 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3274 |
-+ <manvolnum>7</manvolnum> |
3275 |
-+ </citerefentry>), |
3276 |
-+ a connection must install match rules that are different from |
3277 |
-+ the bloom filter matches described in the section above. They can be |
3278 |
-+ filtered by the connection ID that caused the notification to be sent, by |
3279 |
-+ one of the names it currently owns, or by the type of the notification |
3280 |
-+ (ID/name add/remove/change). |
3281 |
-+ </para> |
3282 |
-+ </refsect1> |
3283 |
-+ |
3284 |
-+ <refsect1> |
3285 |
-+ <title>Adding a match</title> |
3286 |
-+ <para> |
3287 |
-+ To add a match, the <constant>KDBUS_CMD_MATCH_ADD</constant> ioctl is |
3288 |
-+ used, which takes a <type>struct kdbus_cmd_match</type> as an argument |
3289 |
-+ described below. |
3290 |
-+ |
3291 |
-+ Note that each of the items attached to this command will internally |
3292 |
-+ create one match <emphasis>rule</emphasis>, and the collection of them, |
3293 |
-+ which is submitted as one block via the ioctl, is called a |
3294 |
-+ <emphasis>match</emphasis>. To allow a message to pass, all rules of a |
3295 |
-+ match have to be satisfied. Hence, adding more items to the command will |
3296 |
-+ only narrow the possibility of a match to effectively let the message |
3297 |
-+ pass, and will decrease the chance that the connection's process will be |
3298 |
-+ woken up needlessly. |
3299 |
-+ |
3300 |
-+ Multiple matches can be installed per connection. As long as one of it has |
3301 |
-+ a set of rules which allows the message to pass, this one will be |
3302 |
-+ decisive. |
3303 |
-+ </para> |
3304 |
-+ |
3305 |
-+ <programlisting> |
3306 |
-+struct kdbus_cmd_match { |
3307 |
-+ __u64 size; |
3308 |
-+ __u64 flags; |
3309 |
-+ __u64 return_flags; |
3310 |
-+ __u64 cookie; |
3311 |
-+ struct kdbus_item items[0]; |
3312 |
-+}; |
3313 |
-+ </programlisting> |
3314 |
-+ |
3315 |
-+ <para>The fields in this struct are described below.</para> |
3316 |
-+ |
3317 |
-+ <variablelist> |
3318 |
-+ <varlistentry> |
3319 |
-+ <term><varname>size</varname></term> |
3320 |
-+ <listitem><para> |
3321 |
-+ The overall size of the struct, including its items. |
3322 |
-+ </para></listitem> |
3323 |
-+ </varlistentry> |
3324 |
-+ |
3325 |
-+ <varlistentry> |
3326 |
-+ <term><varname>flags</varname></term> |
3327 |
-+ <listitem><para>Flags to control the behavior of the ioctl.</para> |
3328 |
-+ <variablelist> |
3329 |
-+ <varlistentry> |
3330 |
-+ <term><constant>KDBUS_MATCH_REPLACE</constant></term> |
3331 |
-+ <listitem> |
3332 |
-+ <para>Make the endpoint file group-accessible</para> |
3333 |
-+ </listitem> |
3334 |
-+ </varlistentry> |
3335 |
-+ |
3336 |
-+ <varlistentry> |
3337 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
3338 |
-+ <listitem> |
3339 |
-+ <para> |
3340 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
3341 |
-+ set, no action is taken; the ioctl will return |
3342 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
3343 |
-+ field will have all bits set that are valid for this command. |
3344 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
3345 |
-+ cleared by the operation. |
3346 |
-+ </para> |
3347 |
-+ </listitem> |
3348 |
-+ </varlistentry> |
3349 |
-+ </variablelist> |
3350 |
-+ </listitem> |
3351 |
-+ </varlistentry> |
3352 |
-+ |
3353 |
-+ <varlistentry> |
3354 |
-+ <term><varname>return_flags</varname></term> |
3355 |
-+ <listitem><para> |
3356 |
-+ Flags returned by the kernel. Currently unused and always set to |
3357 |
-+ <constant>0</constant> by the kernel. |
3358 |
-+ </para></listitem> |
3359 |
-+ </varlistentry> |
3360 |
-+ |
3361 |
-+ <varlistentry> |
3362 |
-+ <term><varname>cookie</varname></term> |
3363 |
-+ <listitem><para> |
3364 |
-+ A cookie which identifies the match, so it can be referred to when |
3365 |
-+ removing it. |
3366 |
-+ </para></listitem> |
3367 |
-+ </varlistentry> |
3368 |
-+ |
3369 |
-+ <varlistentry> |
3370 |
-+ <term><varname>items</varname></term> |
3371 |
-+ <listitem> |
3372 |
-+ <para> |
3373 |
-+ Items to define the actual rules of the matches. The following item |
3374 |
-+ types are expected. Each item will create one new match rule. |
3375 |
-+ </para> |
3376 |
-+ <variablelist> |
3377 |
-+ <varlistentry> |
3378 |
-+ <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term> |
3379 |
-+ <listitem> |
3380 |
-+ <para> |
3381 |
-+ An item that carries the bloom filter mask to match against |
3382 |
-+ in its data field. The payload size must match the bloom |
3383 |
-+ filter size that was specified when the bus was created. |
3384 |
-+ See the "Bloom filters" section above for more information on |
3385 |
-+ bloom filters. |
3386 |
-+ </para> |
3387 |
-+ </listitem> |
3388 |
-+ </varlistentry> |
3389 |
-+ |
3390 |
-+ <varlistentry> |
3391 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
3392 |
-+ <listitem> |
3393 |
-+ <para> |
3394 |
-+ When used as part of kernel notifications, this item specifies |
3395 |
-+ a name that is acquired, lost or that changed its owner (see |
3396 |
-+ below). When used as part of a match for user-generated signal |
3397 |
-+ messages, it specifies a name that the sending connection must |
3398 |
-+ own at the time of sending the signal. |
3399 |
-+ </para> |
3400 |
-+ </listitem> |
3401 |
-+ </varlistentry> |
3402 |
-+ |
3403 |
-+ <varlistentry> |
3404 |
-+ <term><constant>KDBUS_ITEM_ID</constant></term> |
3405 |
-+ <listitem> |
3406 |
-+ <para> |
3407 |
-+ Specify a sender connection's ID that will match this rule. |
3408 |
-+ For kernel notifications, this specifies the ID of a |
3409 |
-+ connection that was added to or removed from the bus. |
3410 |
-+ For used-generated signals, it specifies the ID of the |
3411 |
-+ connection that sent the signal message. |
3412 |
-+ </para> |
3413 |
-+ </listitem> |
3414 |
-+ </varlistentry> |
3415 |
-+ |
3416 |
-+ <varlistentry> |
3417 |
-+ <term><constant>KDBUS_ITEM_NAME_ADD</constant></term> |
3418 |
-+ <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term> |
3419 |
-+ <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term> |
3420 |
-+ <listitem> |
3421 |
-+ <para> |
3422 |
-+ These items request delivery of kernel notifications that |
3423 |
-+ describe a name acquisition, loss, or change. The details |
3424 |
-+ are stored in the item's |
3425 |
-+ <varname>kdbus_notify_name_change</varname> member. |
3426 |
-+ All information specified must be matched in order to make |
3427 |
-+ the message pass. Use |
3428 |
-+ <constant>KDBUS_MATCH_ID_ANY</constant> to |
3429 |
-+ match against any unique connection ID. |
3430 |
-+ </para> |
3431 |
-+ </listitem> |
3432 |
-+ </varlistentry> |
3433 |
-+ |
3434 |
-+ <varlistentry> |
3435 |
-+ <term><constant>KDBUS_ITEM_ID_ADD</constant></term> |
3436 |
-+ <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term> |
3437 |
-+ <listitem> |
3438 |
-+ <para> |
3439 |
-+ These items request delivery of kernel notifications that are |
3440 |
-+ generated when a connection is created or terminated. |
3441 |
-+ <type>struct kdbus_notify_id_change</type> is used to |
3442 |
-+ store the actual match information. This item can be used to |
3443 |
-+ monitor one particular connection ID, or, when the ID field |
3444 |
-+ is set to <constant>KDBUS_MATCH_ID_ANY</constant>, |
3445 |
-+ all of them. |
3446 |
-+ </para> |
3447 |
-+ </listitem> |
3448 |
-+ </varlistentry> |
3449 |
-+ |
3450 |
-+ <varlistentry> |
3451 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
3452 |
-+ <listitem><para> |
3453 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
3454 |
-+ kernel for known item types. See |
3455 |
-+ <citerefentry> |
3456 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
3457 |
-+ <manvolnum>7</manvolnum> |
3458 |
-+ </citerefentry> |
3459 |
-+ for more details. |
3460 |
-+ </para></listitem> |
3461 |
-+ </varlistentry> |
3462 |
-+ </variablelist> |
3463 |
-+ |
3464 |
-+ <para> |
3465 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
3466 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
3467 |
-+ </para> |
3468 |
-+ </listitem> |
3469 |
-+ </varlistentry> |
3470 |
-+ </variablelist> |
3471 |
-+ |
3472 |
-+ <para> |
3473 |
-+ Refer to |
3474 |
-+ <citerefentry> |
3475 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3476 |
-+ <manvolnum>7</manvolnum> |
3477 |
-+ </citerefentry> |
3478 |
-+ for more information on message types. |
3479 |
-+ </para> |
3480 |
-+ </refsect1> |
3481 |
-+ |
3482 |
-+ <refsect1> |
3483 |
-+ <title>Removing a match</title> |
3484 |
-+ <para> |
3485 |
-+ Matches can be removed with the |
3486 |
-+ <constant>KDBUS_CMD_MATCH_REMOVE</constant> ioctl, which takes |
3487 |
-+ <type>struct kdbus_cmd_match</type> as argument, but its fields |
3488 |
-+ usage slightly differs compared to that of |
3489 |
-+ <constant>KDBUS_CMD_MATCH_ADD</constant>. |
3490 |
-+ </para> |
3491 |
-+ |
3492 |
-+ <programlisting> |
3493 |
-+struct kdbus_cmd_match { |
3494 |
-+ __u64 size; |
3495 |
-+ __u64 cookie; |
3496 |
-+ __u64 flags; |
3497 |
-+ __u64 return_flags; |
3498 |
-+ struct kdbus_item items[0]; |
3499 |
-+}; |
3500 |
-+ </programlisting> |
3501 |
-+ |
3502 |
-+ <para>The fields in this struct are described below.</para> |
3503 |
-+ |
3504 |
-+ <variablelist> |
3505 |
-+ <varlistentry> |
3506 |
-+ <term><varname>size</varname></term> |
3507 |
-+ <listitem><para> |
3508 |
-+ The overall size of the struct, including its items. |
3509 |
-+ </para></listitem> |
3510 |
-+ </varlistentry> |
3511 |
-+ |
3512 |
-+ <varlistentry> |
3513 |
-+ <term><varname>cookie</varname></term> |
3514 |
-+ <listitem><para> |
3515 |
-+ The cookie of the match, as it was passed when the match was added. |
3516 |
-+ All matches that have this cookie will be removed. |
3517 |
-+ </para></listitem> |
3518 |
-+ </varlistentry> |
3519 |
-+ |
3520 |
-+ <varlistentry> |
3521 |
-+ <term><varname>flags</varname></term> |
3522 |
-+ <listitem><para> |
3523 |
-+ No flags are supported for this use case. |
3524 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
3525 |
-+ valid flags. If set, the ioctl will fail with |
3526 |
-+ <errorcode>-1</errorcode>, <varname>errno</varname> is set to |
3527 |
-+ <constant>EPROTO</constant>, and the <varname>flags</varname> field |
3528 |
-+ is set to <constant>0</constant>. |
3529 |
-+ </para></listitem> |
3530 |
-+ </varlistentry> |
3531 |
-+ |
3532 |
-+ <varlistentry> |
3533 |
-+ <term><varname>return_flags</varname></term> |
3534 |
-+ <listitem><para> |
3535 |
-+ Flags returned by the kernel. Currently unused and always set to |
3536 |
-+ <constant>0</constant> by the kernel. |
3537 |
-+ </para></listitem> |
3538 |
-+ </varlistentry> |
3539 |
-+ |
3540 |
-+ <varlistentry> |
3541 |
-+ <term><varname>items</varname></term> |
3542 |
-+ <listitem> |
3543 |
-+ <para> |
3544 |
-+ No items are supported for this use case, but |
3545 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed nevertheless. |
3546 |
-+ </para> |
3547 |
-+ </listitem> |
3548 |
-+ </varlistentry> |
3549 |
-+ </variablelist> |
3550 |
-+ </refsect1> |
3551 |
-+ |
3552 |
-+ <refsect1> |
3553 |
-+ <title>Return value</title> |
3554 |
-+ <para> |
3555 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
3556 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
3557 |
-+ <varname>errno</varname> is set to indicate the error. |
3558 |
-+ If the issued ioctl is illegal for the file descriptor used, |
3559 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
3560 |
-+ </para> |
3561 |
-+ |
3562 |
-+ <refsect2> |
3563 |
-+ <title> |
3564 |
-+ <constant>KDBUS_CMD_MATCH_ADD</constant> may fail with the following |
3565 |
-+ errors |
3566 |
-+ </title> |
3567 |
-+ |
3568 |
-+ <variablelist> |
3569 |
-+ <varlistentry> |
3570 |
-+ <term><constant>EINVAL</constant></term> |
3571 |
-+ <listitem><para> |
3572 |
-+ Illegal flags or items. |
3573 |
-+ </para></listitem> |
3574 |
-+ </varlistentry> |
3575 |
-+ |
3576 |
-+ <varlistentry> |
3577 |
-+ <term><constant>EDOM</constant></term> |
3578 |
-+ <listitem><para> |
3579 |
-+ Illegal bloom filter size. |
3580 |
-+ </para></listitem> |
3581 |
-+ </varlistentry> |
3582 |
-+ |
3583 |
-+ <varlistentry> |
3584 |
-+ <term><constant>EMFILE</constant></term> |
3585 |
-+ <listitem><para> |
3586 |
-+ Too many matches for this connection. |
3587 |
-+ </para></listitem> |
3588 |
-+ </varlistentry> |
3589 |
-+ </variablelist> |
3590 |
-+ </refsect2> |
3591 |
-+ |
3592 |
-+ <refsect2> |
3593 |
-+ <title> |
3594 |
-+ <constant>KDBUS_CMD_MATCH_REMOVE</constant> may fail with the following |
3595 |
-+ errors |
3596 |
-+ </title> |
3597 |
-+ |
3598 |
-+ <variablelist> |
3599 |
-+ <varlistentry> |
3600 |
-+ <term><constant>EINVAL</constant></term> |
3601 |
-+ <listitem><para> |
3602 |
-+ Illegal flags. |
3603 |
-+ </para></listitem> |
3604 |
-+ </varlistentry> |
3605 |
-+ |
3606 |
-+ <varlistentry> |
3607 |
-+ <term><constant>EBADSLT</constant></term> |
3608 |
-+ <listitem><para> |
3609 |
-+ A match entry with the given cookie could not be found. |
3610 |
-+ </para></listitem> |
3611 |
-+ </varlistentry> |
3612 |
-+ </variablelist> |
3613 |
-+ </refsect2> |
3614 |
-+ </refsect1> |
3615 |
-+ |
3616 |
-+ <refsect1> |
3617 |
-+ <title>See Also</title> |
3618 |
-+ <simplelist type="inline"> |
3619 |
-+ <member> |
3620 |
-+ <citerefentry> |
3621 |
-+ <refentrytitle>kdbus</refentrytitle> |
3622 |
-+ <manvolnum>7</manvolnum> |
3623 |
-+ </citerefentry> |
3624 |
-+ </member> |
3625 |
-+ <member> |
3626 |
-+ <citerefentry> |
3627 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
3628 |
-+ <manvolnum>7</manvolnum> |
3629 |
-+ </citerefentry> |
3630 |
-+ </member> |
3631 |
-+ <member> |
3632 |
-+ <citerefentry> |
3633 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
3634 |
-+ <manvolnum>7</manvolnum> |
3635 |
-+ </citerefentry> |
3636 |
-+ </member> |
3637 |
-+ <member> |
3638 |
-+ <citerefentry> |
3639 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
3640 |
-+ <manvolnum>7</manvolnum> |
3641 |
-+ </citerefentry> |
3642 |
-+ </member> |
3643 |
-+ <member> |
3644 |
-+ <citerefentry> |
3645 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
3646 |
-+ <manvolnum>7</manvolnum> |
3647 |
-+ </citerefentry> |
3648 |
-+ </member> |
3649 |
-+ <member> |
3650 |
-+ <citerefentry> |
3651 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3652 |
-+ <manvolnum>7</manvolnum> |
3653 |
-+ </citerefentry> |
3654 |
-+ </member> |
3655 |
-+ <member> |
3656 |
-+ <citerefentry> |
3657 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
3658 |
-+ <manvolnum>7</manvolnum> |
3659 |
-+ </citerefentry> |
3660 |
-+ </member> |
3661 |
-+ <member> |
3662 |
-+ <citerefentry> |
3663 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
3664 |
-+ <manvolnum>7</manvolnum> |
3665 |
-+ </citerefentry> |
3666 |
-+ </member> |
3667 |
-+ </simplelist> |
3668 |
-+ </refsect1> |
3669 |
-+</refentry> |
3670 |
-diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml |
3671 |
-new file mode 100644 |
3672 |
-index 0000000..0115d9d |
3673 |
---- /dev/null |
3674 |
-+++ b/Documentation/kdbus/kdbus.message.xml |
3675 |
-@@ -0,0 +1,1276 @@ |
3676 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
3677 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
3678 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
3679 |
-+ |
3680 |
-+<refentry id="kdbus.message"> |
3681 |
-+ |
3682 |
-+ <refentryinfo> |
3683 |
-+ <title>kdbus.message</title> |
3684 |
-+ <productname>kdbus.message</productname> |
3685 |
-+ </refentryinfo> |
3686 |
-+ |
3687 |
-+ <refmeta> |
3688 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3689 |
-+ <manvolnum>7</manvolnum> |
3690 |
-+ </refmeta> |
3691 |
-+ |
3692 |
-+ <refnamediv> |
3693 |
-+ <refname>kdbus.message</refname> |
3694 |
-+ <refpurpose>kdbus message</refpurpose> |
3695 |
-+ </refnamediv> |
3696 |
-+ |
3697 |
-+ <refsect1> |
3698 |
-+ <title>Description</title> |
3699 |
-+ |
3700 |
-+ <para> |
3701 |
-+ A kdbus message is used to exchange information between two connections |
3702 |
-+ on a bus, or to transport notifications from the kernel to one or many |
3703 |
-+ connections. This document describes the layout of messages, how payload |
3704 |
-+ is added to them and how they are sent and received. |
3705 |
-+ </para> |
3706 |
-+ </refsect1> |
3707 |
-+ |
3708 |
-+ <refsect1> |
3709 |
-+ <title>Message layout</title> |
3710 |
-+ |
3711 |
-+ <para>The layout of a message is shown below.</para> |
3712 |
-+ |
3713 |
-+ <programlisting> |
3714 |
-+ +-------------------------------------------------------------------------+ |
3715 |
-+ | Message | |
3716 |
-+ | +---------------------------------------------------------------------+ | |
3717 |
-+ | | Header | | |
3718 |
-+ | | size: overall message size, including the data records | | |
3719 |
-+ | | destination: connection ID of the receiver | | |
3720 |
-+ | | source: connection ID of the sender (set by kernel) | | |
3721 |
-+ | | payload_type: "DBusDBus" textual identifier stored as uint64_t | | |
3722 |
-+ | +---------------------------------------------------------------------+ | |
3723 |
-+ | +---------------------------------------------------------------------+ | |
3724 |
-+ | | Data Record | | |
3725 |
-+ | | size: overall record size (without padding) | | |
3726 |
-+ | | type: type of data | | |
3727 |
-+ | | data: reference to data (address or file descriptor) | | |
3728 |
-+ | +---------------------------------------------------------------------+ | |
3729 |
-+ | +---------------------------------------------------------------------+ | |
3730 |
-+ | | padding bytes to the next 8 byte alignment | | |
3731 |
-+ | +---------------------------------------------------------------------+ | |
3732 |
-+ | +---------------------------------------------------------------------+ | |
3733 |
-+ | | Data Record | | |
3734 |
-+ | | size: overall record size (without padding) | | |
3735 |
-+ | | ... | | |
3736 |
-+ | +---------------------------------------------------------------------+ | |
3737 |
-+ | +---------------------------------------------------------------------+ | |
3738 |
-+ | | padding bytes to the next 8 byte alignment | | |
3739 |
-+ | +---------------------------------------------------------------------+ | |
3740 |
-+ | +---------------------------------------------------------------------+ | |
3741 |
-+ | | Data Record | | |
3742 |
-+ | | size: overall record size | | |
3743 |
-+ | | ... | | |
3744 |
-+ | +---------------------------------------------------------------------+ | |
3745 |
-+ | ... further data records ... | |
3746 |
-+ +-------------------------------------------------------------------------+ |
3747 |
-+ </programlisting> |
3748 |
-+ </refsect1> |
3749 |
-+ |
3750 |
-+ <refsect1> |
3751 |
-+ <title>Message payload</title> |
3752 |
-+ |
3753 |
-+ <para> |
3754 |
-+ When connecting to the bus, receivers request a memory pool of a given |
3755 |
-+ size, large enough to carry all backlog of data enqueued for the |
3756 |
-+ connection. The pool is internally backed by a shared memory file which |
3757 |
-+ can be <function>mmap()</function>ed by the receiver. See |
3758 |
-+ <citerefentry> |
3759 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
3760 |
-+ <manvolnum>7</manvolnum> |
3761 |
-+ </citerefentry> |
3762 |
-+ for more information. |
3763 |
-+ </para> |
3764 |
-+ |
3765 |
-+ <para> |
3766 |
-+ Message payload must be described in items attached to a message when |
3767 |
-+ it is sent. A receiver can access the payload by looking at the items |
3768 |
-+ that are attached to a message in its pool. The following items are used. |
3769 |
-+ </para> |
3770 |
-+ |
3771 |
-+ <variablelist> |
3772 |
-+ <varlistentry> |
3773 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
3774 |
-+ <listitem> |
3775 |
-+ <para> |
3776 |
-+ This item references a piece of memory on the sender side which is |
3777 |
-+ directly copied into the receiver's pool. This way, two peers can |
3778 |
-+ exchange data by effectively doing a single-copy from one process |
3779 |
-+ to another; the kernel will not buffer the data anywhere else. |
3780 |
-+ This item is never found in a message received by a connection. |
3781 |
-+ </para> |
3782 |
-+ </listitem> |
3783 |
-+ </varlistentry> |
3784 |
-+ |
3785 |
-+ <varlistentry> |
3786 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term> |
3787 |
-+ <listitem> |
3788 |
-+ <para> |
3789 |
-+ This item is attached to messages on the receiving side and points |
3790 |
-+ to a memory area inside the receiver's pool. The |
3791 |
-+ <varname>offset</varname> variable in the item denotes the memory |
3792 |
-+ location relative to the message itself. |
3793 |
-+ </para> |
3794 |
-+ </listitem> |
3795 |
-+ </varlistentry> |
3796 |
-+ |
3797 |
-+ <varlistentry> |
3798 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
3799 |
-+ <listitem> |
3800 |
-+ <para> |
3801 |
-+ Messages can reference <emphasis>memfd</emphasis> files which |
3802 |
-+ contain the data. memfd files are tmpfs-backed files that allow |
3803 |
-+ sealing of the content of the file, which prevents all writable |
3804 |
-+ access to the file content. |
3805 |
-+ </para> |
3806 |
-+ <para> |
3807 |
-+ Only memfds that have |
3808 |
-+ <constant>(F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_SEAL) |
3809 |
-+ </constant> |
3810 |
-+ set are accepted as payload data, which enforces reliable passing of |
3811 |
-+ data. The receiver can assume that neither the sender nor anyone |
3812 |
-+ else can alter the content after the message is sent. If those |
3813 |
-+ seals are not set on the memfd, the ioctl will fail with |
3814 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> will be |
3815 |
-+ set to <constant>ETXTBUSY</constant>. |
3816 |
-+ </para> |
3817 |
-+ </listitem> |
3818 |
-+ </varlistentry> |
3819 |
-+ |
3820 |
-+ <varlistentry> |
3821 |
-+ <term><constant>KDBUS_ITEM_FDS</constant></term> |
3822 |
-+ <listitem> |
3823 |
-+ <para> |
3824 |
-+ Messages can transport regular file descriptors via |
3825 |
-+ <constant>KDBUS_ITEM_FDS</constant>. This item carries an array |
3826 |
-+ of <type>int</type> values in <varname>item.fd</varname>. The |
3827 |
-+ maximum number of file descriptors in the item is |
3828 |
-+ <constant>253</constant>, and only one item of this type is |
3829 |
-+ accepted per message. All passed values must be valid file |
3830 |
-+ descriptors; the open count of each file descriptors is increased |
3831 |
-+ by installing it to the receiver's task. This item can only be |
3832 |
-+ used for directed messages, not for broadcasts, and only to |
3833 |
-+ remote peers that have opted-in for receiving file descriptors |
3834 |
-+ at connection time (<constant>KDBUS_HELLO_ACCEPT_FD</constant>). |
3835 |
-+ </para> |
3836 |
-+ </listitem> |
3837 |
-+ </varlistentry> |
3838 |
-+ </variablelist> |
3839 |
-+ |
3840 |
-+ <para> |
3841 |
-+ The sender must not make any assumptions on the type in which data is |
3842 |
-+ received by the remote peer. The kernel is free to re-pack multiple |
3843 |
-+ <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> and |
3844 |
-+ <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> payloads. For instance, the |
3845 |
-+ kernel may decide to merge multiple <constant>VECs</constant> into a |
3846 |
-+ single <constant>VEC</constant>, inline <constant>MEMFD</constant> |
3847 |
-+ payloads into memory, or merge all passed <constant>VECs</constant> into a |
3848 |
-+ single <constant>MEMFD</constant>. However, the kernel preserves the order |
3849 |
-+ of passed data. This means that the order of all <constant>VEC</constant> |
3850 |
-+ and <constant>MEMFD</constant> items is not changed in respect to each |
3851 |
-+ other. In other words: All passed <constant>VEC</constant> and |
3852 |
-+ <constant>MEMFD</constant> data payloads are treated as a single stream |
3853 |
-+ of data that may be received by the remote peer in a different set of |
3854 |
-+ chunks than it was sent as. |
3855 |
-+ </para> |
3856 |
-+ </refsect1> |
3857 |
-+ |
3858 |
-+ <refsect1> |
3859 |
-+ <title>Sending messages</title> |
3860 |
-+ |
3861 |
-+ <para> |
3862 |
-+ Messages are passed to the kernel with the |
3863 |
-+ <constant>KDBUS_CMD_SEND</constant> ioctl. Depending on the destination |
3864 |
-+ address of the message, the kernel delivers the message to the specific |
3865 |
-+ destination connection, or to some subset of all connections on the same |
3866 |
-+ bus. Sending messages across buses is not possible. Messages are always |
3867 |
-+ queued in the memory pool of the destination connection (see above). |
3868 |
-+ </para> |
3869 |
-+ |
3870 |
-+ <para> |
3871 |
-+ The <constant>KDBUS_CMD_SEND</constant> ioctl uses a |
3872 |
-+ <type>struct kdbus_cmd_send</type> to describe the message |
3873 |
-+ transfer. |
3874 |
-+ </para> |
3875 |
-+ <programlisting> |
3876 |
-+struct kdbus_cmd_send { |
3877 |
-+ __u64 size; |
3878 |
-+ __u64 flags; |
3879 |
-+ __u64 return_flags; |
3880 |
-+ __u64 msg_address; |
3881 |
-+ struct kdbus_msg_info reply; |
3882 |
-+ struct kdbus_item items[0]; |
3883 |
-+}; |
3884 |
-+ </programlisting> |
3885 |
-+ |
3886 |
-+ <para>The fields in this struct are described below.</para> |
3887 |
-+ |
3888 |
-+ <variablelist> |
3889 |
-+ <varlistentry> |
3890 |
-+ <term><varname>size</varname></term> |
3891 |
-+ <listitem><para> |
3892 |
-+ The overall size of the struct, including its items. |
3893 |
-+ </para></listitem> |
3894 |
-+ </varlistentry> |
3895 |
-+ |
3896 |
-+ <varlistentry> |
3897 |
-+ <term><varname>flags</varname></term> |
3898 |
-+ <listitem><para>Flags for message delivery</para> |
3899 |
-+ <variablelist> |
3900 |
-+ <varlistentry> |
3901 |
-+ <term><constant>KDBUS_SEND_SYNC_REPLY</constant></term> |
3902 |
-+ <listitem> |
3903 |
-+ <para> |
3904 |
-+ By default, all calls to kdbus are considered asynchronous, |
3905 |
-+ non-blocking. However, as there are many use cases that need |
3906 |
-+ to wait for a remote peer to answer a method call, there's a |
3907 |
-+ way to send a message and wait for a reply in a synchronous |
3908 |
-+ fashion. This is what the |
3909 |
-+ <constant>KDBUS_SEND_SYNC_REPLY</constant> controls. The |
3910 |
-+ <constant>KDBUS_CMD_SEND</constant> ioctl will block until the |
3911 |
-+ reply has arrived, the timeout limit is reached, in case the |
3912 |
-+ remote connection was shut down, or if interrupted by a signal |
3913 |
-+ before any reply; see |
3914 |
-+ <citerefentry> |
3915 |
-+ <refentrytitle>signal</refentrytitle> |
3916 |
-+ <manvolnum>7</manvolnum> |
3917 |
-+ </citerefentry>. |
3918 |
-+ |
3919 |
-+ The offset of the reply message in the sender's pool is stored |
3920 |
-+ in <varname>reply</varname> when the ioctl has returned without |
3921 |
-+ error. Hence, there is no need for another |
3922 |
-+ <constant>KDBUS_CMD_RECV</constant> ioctl or anything else to |
3923 |
-+ receive the reply. |
3924 |
-+ </para> |
3925 |
-+ </listitem> |
3926 |
-+ </varlistentry> |
3927 |
-+ |
3928 |
-+ <varlistentry> |
3929 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
3930 |
-+ <listitem> |
3931 |
-+ <para> |
3932 |
-+ Request a set of valid flags for this ioctl. When this bit is |
3933 |
-+ set, no action is taken; the ioctl will fail with |
3934 |
-+ <errorcode>-1</errorcode>, <varname>errno</varname> |
3935 |
-+ is set to <constant>EPROTO</constant>. |
3936 |
-+ Once the ioctl returned, the <varname>flags</varname> |
3937 |
-+ field will have all bits set that the kernel recognizes as |
3938 |
-+ valid for this command. |
3939 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
3940 |
-+ cleared by the operation. |
3941 |
-+ </para> |
3942 |
-+ </listitem> |
3943 |
-+ </varlistentry> |
3944 |
-+ </variablelist> |
3945 |
-+ </listitem> |
3946 |
-+ </varlistentry> |
3947 |
-+ |
3948 |
-+ <varlistentry> |
3949 |
-+ <term><varname>return_flags</varname></term> |
3950 |
-+ <listitem><para> |
3951 |
-+ Flags returned by the kernel. Currently unused and always set to |
3952 |
-+ <constant>0</constant> by the kernel. |
3953 |
-+ </para></listitem> |
3954 |
-+ </varlistentry> |
3955 |
-+ |
3956 |
-+ <varlistentry> |
3957 |
-+ <term><varname>msg_address</varname></term> |
3958 |
-+ <listitem><para> |
3959 |
-+ In this field, users have to provide a pointer to a message |
3960 |
-+ (<type>struct kdbus_msg</type>) to send. See below for a |
3961 |
-+ detailed description. |
3962 |
-+ </para></listitem> |
3963 |
-+ </varlistentry> |
3964 |
-+ |
3965 |
-+ <varlistentry> |
3966 |
-+ <term><varname>reply</varname></term> |
3967 |
-+ <listitem><para> |
3968 |
-+ Only used for synchronous replies. See description of |
3969 |
-+ <type>struct kdbus_cmd_recv</type> for more details. |
3970 |
-+ </para></listitem> |
3971 |
-+ </varlistentry> |
3972 |
-+ |
3973 |
-+ <varlistentry> |
3974 |
-+ <term><varname>items</varname></term> |
3975 |
-+ <listitem> |
3976 |
-+ <para> |
3977 |
-+ The following items are currently recognized. |
3978 |
-+ </para> |
3979 |
-+ <variablelist> |
3980 |
-+ <varlistentry> |
3981 |
-+ <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term> |
3982 |
-+ <listitem> |
3983 |
-+ <para> |
3984 |
-+ When this optional item is passed in, and the call is |
3985 |
-+ executed as SYNC call, the passed in file descriptor can be |
3986 |
-+ used as alternative cancellation point. The kernel will call |
3987 |
-+ <citerefentry> |
3988 |
-+ <refentrytitle>poll</refentrytitle> |
3989 |
-+ <manvolnum>2</manvolnum> |
3990 |
-+ </citerefentry> |
3991 |
-+ on this file descriptor, and once it reports any incoming |
3992 |
-+ bytes, the blocking send operation will be canceled; the |
3993 |
-+ blocking, synchronous ioctl call will return |
3994 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> will |
3995 |
-+ be set to <errorname>ECANCELED</errorname>. |
3996 |
-+ Any type of file descriptor on which |
3997 |
-+ <citerefentry> |
3998 |
-+ <refentrytitle>poll</refentrytitle> |
3999 |
-+ <manvolnum>2</manvolnum> |
4000 |
-+ </citerefentry> |
4001 |
-+ can be called on can be used as payload to this item; for |
4002 |
-+ example, an eventfd can be used for this purpose, see |
4003 |
-+ <citerefentry> |
4004 |
-+ <refentrytitle>eventfd</refentrytitle> |
4005 |
-+ <manvolnum>2</manvolnum> |
4006 |
-+ </citerefentry>. |
4007 |
-+ For asynchronous message sending, this item is allowed but |
4008 |
-+ ignored. |
4009 |
-+ </para> |
4010 |
-+ </listitem> |
4011 |
-+ </varlistentry> |
4012 |
-+ </variablelist> |
4013 |
-+ <para> |
4014 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
4015 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
4016 |
-+ </para> |
4017 |
-+ </listitem> |
4018 |
-+ </varlistentry> |
4019 |
-+ </variablelist> |
4020 |
-+ |
4021 |
-+ <para> |
4022 |
-+ The message referenced by the <varname>msg_address</varname> above has |
4023 |
-+ the following layout. |
4024 |
-+ </para> |
4025 |
-+ |
4026 |
-+ <programlisting> |
4027 |
-+struct kdbus_msg { |
4028 |
-+ __u64 size; |
4029 |
-+ __u64 flags; |
4030 |
-+ __s64 priority; |
4031 |
-+ __u64 dst_id; |
4032 |
-+ __u64 src_id; |
4033 |
-+ __u64 payload_type; |
4034 |
-+ __u64 cookie; |
4035 |
-+ __u64 timeout_ns; |
4036 |
-+ __u64 cookie_reply; |
4037 |
-+ struct kdbus_item items[0]; |
4038 |
-+}; |
4039 |
-+ </programlisting> |
4040 |
-+ |
4041 |
-+ <para>The fields in this struct are described below.</para> |
4042 |
-+ |
4043 |
-+ <variablelist> |
4044 |
-+ <varlistentry> |
4045 |
-+ <term><varname>size</varname></term> |
4046 |
-+ <listitem><para> |
4047 |
-+ The overall size of the struct, including its items. |
4048 |
-+ </para></listitem> |
4049 |
-+ </varlistentry> |
4050 |
-+ |
4051 |
-+ <varlistentry> |
4052 |
-+ <term><varname>flags</varname></term> |
4053 |
-+ <listitem><para>Flags to describe message details.</para> |
4054 |
-+ <variablelist> |
4055 |
-+ <varlistentry> |
4056 |
-+ <term><constant>KDBUS_MSG_EXPECT_REPLY</constant></term> |
4057 |
-+ <listitem> |
4058 |
-+ <para> |
4059 |
-+ Expect a reply to this message from the remote peer. With |
4060 |
-+ this bit set, the timeout_ns field must be set to a non-zero |
4061 |
-+ number of nanoseconds in which the receiving peer is expected |
4062 |
-+ to reply. If such a reply is not received in time, the sender |
4063 |
-+ will be notified with a timeout message (see below). The |
4064 |
-+ value must be an absolute value, in nanoseconds and based on |
4065 |
-+ <constant>CLOCK_MONOTONIC</constant>. |
4066 |
-+ </para><para> |
4067 |
-+ For a message to be accepted as reply, it must be a direct |
4068 |
-+ message to the original sender (not a broadcast and not a |
4069 |
-+ signal message), and its |
4070 |
-+ <varname>kdbus_msg.cookie_reply</varname> must match the |
4071 |
-+ previous message's <varname>kdbus_msg.cookie</varname>. |
4072 |
-+ </para><para> |
4073 |
-+ Expected replies also temporarily open the policy of the |
4074 |
-+ sending connection, so the other peer is allowed to respond |
4075 |
-+ within the given time window. |
4076 |
-+ </para> |
4077 |
-+ </listitem> |
4078 |
-+ </varlistentry> |
4079 |
-+ |
4080 |
-+ <varlistentry> |
4081 |
-+ <term><constant>KDBUS_MSG_NO_AUTO_START</constant></term> |
4082 |
-+ <listitem> |
4083 |
-+ <para> |
4084 |
-+ By default, when a message is sent to an activator |
4085 |
-+ connection, the activator is notified and will start an |
4086 |
-+ implementer. This flag inhibits that behavior. With this bit |
4087 |
-+ set, and the remote being an activator, the ioctl will fail |
4088 |
-+ with <varname>errno</varname> set to |
4089 |
-+ <constant>EADDRNOTAVAIL</constant>. |
4090 |
-+ </para> |
4091 |
-+ </listitem> |
4092 |
-+ </varlistentry> |
4093 |
-+ |
4094 |
-+ <varlistentry> |
4095 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
4096 |
-+ <listitem> |
4097 |
-+ <para> |
4098 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
4099 |
-+ set, no action is taken; the ioctl will return |
4100 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
4101 |
-+ field will have all bits set that are valid for this command. |
4102 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
4103 |
-+ cleared by the operation. |
4104 |
-+ </para> |
4105 |
-+ </listitem> |
4106 |
-+ </varlistentry> |
4107 |
-+ </variablelist> |
4108 |
-+ </listitem> |
4109 |
-+ </varlistentry> |
4110 |
-+ |
4111 |
-+ <varlistentry> |
4112 |
-+ <term><varname>priority</varname></term> |
4113 |
-+ <listitem><para> |
4114 |
-+ The priority of this message. Receiving messages (see below) may |
4115 |
-+ optionally be constrained to messages of a minimal priority. This |
4116 |
-+ allows for use cases where timing critical data is interleaved with |
4117 |
-+ control data on the same connection. If unused, the priority field |
4118 |
-+ should be set to <constant>0</constant>. |
4119 |
-+ </para></listitem> |
4120 |
-+ </varlistentry> |
4121 |
-+ |
4122 |
-+ <varlistentry> |
4123 |
-+ <term><varname>dst_id</varname></term> |
4124 |
-+ <listitem><para> |
4125 |
-+ The numeric ID of the destination connection, or |
4126 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> |
4127 |
-+ (~0ULL) to address every peer on the bus, or |
4128 |
-+ <constant>KDBUS_DST_ID_NAME</constant> (0) to look |
4129 |
-+ it up dynamically from the bus' name registry. |
4130 |
-+ In the latter case, an item of type |
4131 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> is mandatory. |
4132 |
-+ Also see |
4133 |
-+ <citerefentry> |
4134 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
4135 |
-+ <manvolnum>7</manvolnum> |
4136 |
-+ </citerefentry> |
4137 |
-+ . |
4138 |
-+ </para></listitem> |
4139 |
-+ </varlistentry> |
4140 |
-+ |
4141 |
-+ <varlistentry> |
4142 |
-+ <term><varname>src_id</varname></term> |
4143 |
-+ <listitem><para> |
4144 |
-+ Upon return of the ioctl, this member will contain the sending |
4145 |
-+ connection's numerical ID. Should be 0 at send time. |
4146 |
-+ </para></listitem> |
4147 |
-+ </varlistentry> |
4148 |
-+ |
4149 |
-+ <varlistentry> |
4150 |
-+ <term><varname>payload_type</varname></term> |
4151 |
-+ <listitem><para> |
4152 |
-+ Type of the payload in the actual data records. Currently, only |
4153 |
-+ <constant>KDBUS_PAYLOAD_DBUS</constant> is accepted as input value |
4154 |
-+ of this field. When receiving messages that are generated by the |
4155 |
-+ kernel (notifications), this field will contain |
4156 |
-+ <constant>KDBUS_PAYLOAD_KERNEL</constant>. |
4157 |
-+ </para></listitem> |
4158 |
-+ </varlistentry> |
4159 |
-+ |
4160 |
-+ <varlistentry> |
4161 |
-+ <term><varname>cookie</varname></term> |
4162 |
-+ <listitem><para> |
4163 |
-+ Cookie of this message, for later recognition. Also, when replying |
4164 |
-+ to a message (see above), the <varname>cookie_reply</varname> |
4165 |
-+ field must match this value. |
4166 |
-+ </para></listitem> |
4167 |
-+ </varlistentry> |
4168 |
-+ |
4169 |
-+ <varlistentry> |
4170 |
-+ <term><varname>timeout_ns</varname></term> |
4171 |
-+ <listitem><para> |
4172 |
-+ If the message sent requires a reply from the remote peer (see above), |
4173 |
-+ this field contains the timeout in absolute nanoseconds based on |
4174 |
-+ <constant>CLOCK_MONOTONIC</constant>. Also see |
4175 |
-+ <citerefentry> |
4176 |
-+ <refentrytitle>clock_gettime</refentrytitle> |
4177 |
-+ <manvolnum>2</manvolnum> |
4178 |
-+ </citerefentry>. |
4179 |
-+ </para></listitem> |
4180 |
-+ </varlistentry> |
4181 |
-+ |
4182 |
-+ <varlistentry> |
4183 |
-+ <term><varname>cookie_reply</varname></term> |
4184 |
-+ <listitem><para> |
4185 |
-+ If the message sent is a reply to another message, this field must |
4186 |
-+ match the cookie of the formerly received message. |
4187 |
-+ </para></listitem> |
4188 |
-+ </varlistentry> |
4189 |
-+ |
4190 |
-+ <varlistentry> |
4191 |
-+ <term><varname>items</varname></term> |
4192 |
-+ <listitem> |
4193 |
-+ <para> |
4194 |
-+ A dynamically sized list of items to contain additional information. |
4195 |
-+ The following items are expected/valid: |
4196 |
-+ </para> |
4197 |
-+ <variablelist> |
4198 |
-+ <varlistentry> |
4199 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
4200 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
4201 |
-+ <term><constant>KDBUS_ITEM_FDS</constant></term> |
4202 |
-+ <listitem> |
4203 |
-+ <para> |
4204 |
-+ Actual data records containing the payload. See section |
4205 |
-+ "Message payload". |
4206 |
-+ </para> |
4207 |
-+ </listitem> |
4208 |
-+ </varlistentry> |
4209 |
-+ |
4210 |
-+ <varlistentry> |
4211 |
-+ <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term> |
4212 |
-+ <listitem> |
4213 |
-+ <para> |
4214 |
-+ Bloom filter for matches (see below). |
4215 |
-+ </para> |
4216 |
-+ </listitem> |
4217 |
-+ </varlistentry> |
4218 |
-+ |
4219 |
-+ <varlistentry> |
4220 |
-+ <term><constant>KDBUS_ITEM_DST_NAME</constant></term> |
4221 |
-+ <listitem> |
4222 |
-+ <para> |
4223 |
-+ Well-known name to send this message to. Required if |
4224 |
-+ <varname>dst_id</varname> is set to |
4225 |
-+ <constant>KDBUS_DST_ID_NAME</constant>. |
4226 |
-+ If a connection holding the given name can't be found, |
4227 |
-+ the ioctl will fail with <varname>errno</varname> set to |
4228 |
-+ <constant>ESRCH</constant> is returned. |
4229 |
-+ </para> |
4230 |
-+ <para> |
4231 |
-+ For messages to a unique name (ID), this item is optional. If |
4232 |
-+ present, the kernel will make sure the name owner matches the |
4233 |
-+ given unique name. This allows programs to tie the message |
4234 |
-+ sending to the condition that a name is currently owned by a |
4235 |
-+ certain unique name. |
4236 |
-+ </para> |
4237 |
-+ </listitem> |
4238 |
-+ </varlistentry> |
4239 |
-+ </variablelist> |
4240 |
-+ </listitem> |
4241 |
-+ </varlistentry> |
4242 |
-+ </variablelist> |
4243 |
-+ |
4244 |
-+ <para> |
4245 |
-+ The message will be augmented by the requested metadata items when |
4246 |
-+ queued into the receiver's pool. See |
4247 |
-+ <citerefentry> |
4248 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
4249 |
-+ <manvolnum>7</manvolnum> |
4250 |
-+ </citerefentry> |
4251 |
-+ and |
4252 |
-+ <citerefentry> |
4253 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
4254 |
-+ <manvolnum>7</manvolnum> |
4255 |
-+ </citerefentry> |
4256 |
-+ for more information on metadata. |
4257 |
-+ </para> |
4258 |
-+ </refsect1> |
4259 |
-+ |
4260 |
-+ <refsect1> |
4261 |
-+ <title>Receiving messages</title> |
4262 |
-+ |
4263 |
-+ <para> |
4264 |
-+ Messages are received by the client with the |
4265 |
-+ <constant>KDBUS_CMD_RECV</constant> ioctl. The endpoint file of the bus |
4266 |
-+ supports <function>poll()/epoll()/select()</function>; when new messages |
4267 |
-+ are available on the connection's file descriptor, |
4268 |
-+ <constant>POLLIN</constant> is reported. For compatibility reasons, |
4269 |
-+ <constant>POLLOUT</constant> is always reported as well. Note, however, |
4270 |
-+ that the latter does not guarantee that a message can in fact be sent, as |
4271 |
-+ this depends on how many pending messages the receiver has in its pool. |
4272 |
-+ </para> |
4273 |
-+ |
4274 |
-+ <para> |
4275 |
-+ With the <constant>KDBUS_CMD_RECV</constant> ioctl, a |
4276 |
-+ <type>struct kdbus_cmd_recv</type> is used. |
4277 |
-+ </para> |
4278 |
-+ |
4279 |
-+ <programlisting> |
4280 |
-+struct kdbus_cmd_recv { |
4281 |
-+ __u64 size; |
4282 |
-+ __u64 flags; |
4283 |
-+ __u64 return_flags; |
4284 |
-+ __s64 priority; |
4285 |
-+ __u64 dropped_msgs; |
4286 |
-+ struct kdbus_msg_info msg; |
4287 |
-+ struct kdbus_item items[0]; |
4288 |
-+}; |
4289 |
-+ </programlisting> |
4290 |
-+ |
4291 |
-+ <para>The fields in this struct are described below.</para> |
4292 |
-+ |
4293 |
-+ <variablelist> |
4294 |
-+ <varlistentry> |
4295 |
-+ <term><varname>size</varname></term> |
4296 |
-+ <listitem><para> |
4297 |
-+ The overall size of the struct, including its items. |
4298 |
-+ </para></listitem> |
4299 |
-+ </varlistentry> |
4300 |
-+ |
4301 |
-+ <varlistentry> |
4302 |
-+ <term><varname>flags</varname></term> |
4303 |
-+ <listitem><para>Flags to control the receive command.</para> |
4304 |
-+ <variablelist> |
4305 |
-+ <varlistentry> |
4306 |
-+ <term><constant>KDBUS_RECV_PEEK</constant></term> |
4307 |
-+ <listitem> |
4308 |
-+ <para> |
4309 |
-+ Just return the location of the next message. Do not install |
4310 |
-+ file descriptors or anything else. This is usually used to |
4311 |
-+ determine the sender of the next queued message. |
4312 |
-+ </para> |
4313 |
-+ </listitem> |
4314 |
-+ </varlistentry> |
4315 |
-+ |
4316 |
-+ <varlistentry> |
4317 |
-+ <term><constant>KDBUS_RECV_DROP</constant></term> |
4318 |
-+ <listitem> |
4319 |
-+ <para> |
4320 |
-+ Drop the next message without doing anything else with it, |
4321 |
-+ and free the pool slice. This a short-cut for |
4322 |
-+ <constant>KDBUS_RECV_PEEK</constant> and |
4323 |
-+ <constant>KDBUS_CMD_FREE</constant>. |
4324 |
-+ </para> |
4325 |
-+ </listitem> |
4326 |
-+ </varlistentry> |
4327 |
-+ |
4328 |
-+ <varlistentry> |
4329 |
-+ <term><constant>KDBUS_RECV_USE_PRIORITY</constant></term> |
4330 |
-+ <listitem> |
4331 |
-+ <para> |
4332 |
-+ Dequeue the messages ordered by their priority, and filtering |
4333 |
-+ them with the priority field (see below). |
4334 |
-+ </para> |
4335 |
-+ </listitem> |
4336 |
-+ </varlistentry> |
4337 |
-+ |
4338 |
-+ <varlistentry> |
4339 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
4340 |
-+ <listitem> |
4341 |
-+ <para> |
4342 |
-+ Request a set of valid flags for this ioctl. When this bit is |
4343 |
-+ set, no action is taken; the ioctl will fail with |
4344 |
-+ <errorcode>-1</errorcode>, <varname>errno</varname> |
4345 |
-+ is set to <constant>EPROTO</constant>. |
4346 |
-+ Once the ioctl returned, the <varname>flags</varname> |
4347 |
-+ field will have all bits set that the kernel recognizes as |
4348 |
-+ valid for this command. |
4349 |
-+ </para> |
4350 |
-+ </listitem> |
4351 |
-+ </varlistentry> |
4352 |
-+ </variablelist> |
4353 |
-+ </listitem> |
4354 |
-+ </varlistentry> |
4355 |
-+ |
4356 |
-+ <varlistentry> |
4357 |
-+ <term><varname>return_flags</varname></term> |
4358 |
-+ <listitem><para> |
4359 |
-+ Flags returned by the kernel. If the <varname>dropped_msgs</varname> |
4360 |
-+ field is non-zero, <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> |
4361 |
-+ is set. If a file descriptor could not be installed, the |
4362 |
-+ <constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant> flag is set. |
4363 |
-+ </para></listitem> |
4364 |
-+ </varlistentry> |
4365 |
-+ |
4366 |
-+ <varlistentry> |
4367 |
-+ <term><varname>priority</varname></term> |
4368 |
-+ <listitem><para> |
4369 |
-+ With <constant>KDBUS_RECV_USE_PRIORITY</constant> set in |
4370 |
-+ <varname>flags</varname>, messages will be dequeued ordered by their |
4371 |
-+ priority, starting with the highest value. Also, messages will be |
4372 |
-+ filtered by the value given in this field, so the returned message |
4373 |
-+ will at least have the requested priority. If no such message is |
4374 |
-+ waiting in the queue, the ioctl will fail, and |
4375 |
-+ <varname>errno</varname> will be set to <constant>EAGAIN</constant>. |
4376 |
-+ </para></listitem> |
4377 |
-+ </varlistentry> |
4378 |
-+ |
4379 |
-+ <varlistentry> |
4380 |
-+ <term><varname>dropped_msgs</varname></term> |
4381 |
-+ <listitem><para> |
4382 |
-+ Whenever a message with <constant>KDBUS_MSG_SIGNAL</constant> is sent |
4383 |
-+ but cannot be queued on a peer (e.g., as it contains FDs but the peer |
4384 |
-+ does not support FDs, or there is no space left in the peer's pool) |
4385 |
-+ the 'dropped_msgs' counter of the peer is incremented. On the next |
4386 |
-+ RECV ioctl, the 'dropped_msgs' field is copied into the ioctl struct |
4387 |
-+ and cleared on the peer. If it was non-zero, the |
4388 |
-+ <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> flag will be set |
4389 |
-+ in <varname>return_flags</varname>. Note that this will only happen |
4390 |
-+ if the ioctl succeeded or failed with <constant>EAGAIN</constant>. In |
4391 |
-+ other error cases, the 'dropped_msgs' field of the peer is left |
4392 |
-+ untouched. |
4393 |
-+ </para></listitem> |
4394 |
-+ </varlistentry> |
4395 |
-+ |
4396 |
-+ <varlistentry> |
4397 |
-+ <term><varname>msg</varname></term> |
4398 |
-+ <listitem><para> |
4399 |
-+ Embedded struct containing information on the received message when |
4400 |
-+ this command succeeded (see below). |
4401 |
-+ </para></listitem> |
4402 |
-+ </varlistentry> |
4403 |
-+ |
4404 |
-+ <varlistentry> |
4405 |
-+ <term><varname>items</varname></term> |
4406 |
-+ <listitem><para> |
4407 |
-+ Items to specify further details for the receive command. |
4408 |
-+ Currently unused, and all items will be rejected with |
4409 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
4410 |
-+ </para></listitem> |
4411 |
-+ </varlistentry> |
4412 |
-+ </variablelist> |
4413 |
-+ |
4414 |
-+ <para> |
4415 |
-+ Both <type>struct kdbus_cmd_recv</type> and |
4416 |
-+ <type>struct kdbus_cmd_send</type> embed |
4417 |
-+ <type>struct kdbus_msg_info</type>. |
4418 |
-+ For the <constant>KDBUS_CMD_SEND</constant> ioctl, it is used to catch |
4419 |
-+ synchronous replies, if one was requested, and is unused otherwise. |
4420 |
-+ </para> |
4421 |
-+ |
4422 |
-+ <programlisting> |
4423 |
-+struct kdbus_msg_info { |
4424 |
-+ __u64 offset; |
4425 |
-+ __u64 msg_size; |
4426 |
-+ __u64 return_flags; |
4427 |
-+}; |
4428 |
-+ </programlisting> |
4429 |
-+ |
4430 |
-+ <para>The fields in this struct are described below.</para> |
4431 |
-+ |
4432 |
-+ <variablelist> |
4433 |
-+ <varlistentry> |
4434 |
-+ <term><varname>offset</varname></term> |
4435 |
-+ <listitem><para> |
4436 |
-+ Upon return of the ioctl, this field contains the offset in the |
4437 |
-+ receiver's memory pool. The memory must be freed with |
4438 |
-+ <constant>KDBUS_CMD_FREE</constant>. See |
4439 |
-+ <citerefentry> |
4440 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
4441 |
-+ <manvolnum>7</manvolnum> |
4442 |
-+ </citerefentry> |
4443 |
-+ for further details. |
4444 |
-+ </para></listitem> |
4445 |
-+ </varlistentry> |
4446 |
-+ |
4447 |
-+ <varlistentry> |
4448 |
-+ <term><varname>msg_size</varname></term> |
4449 |
-+ <listitem><para> |
4450 |
-+ Upon successful return of the ioctl, this field contains the size of |
4451 |
-+ the allocated slice at offset <varname>offset</varname>. |
4452 |
-+ It is the combination of the size of the stored |
4453 |
-+ <type>struct kdbus_msg</type> object plus all appended VECs. |
4454 |
-+ You can use it in combination with <varname>offset</varname> to map |
4455 |
-+ a single message, instead of mapping the entire pool. See |
4456 |
-+ <citerefentry> |
4457 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
4458 |
-+ <manvolnum>7</manvolnum> |
4459 |
-+ </citerefentry> |
4460 |
-+ for further details. |
4461 |
-+ </para></listitem> |
4462 |
-+ </varlistentry> |
4463 |
-+ |
4464 |
-+ <varlistentry> |
4465 |
-+ <term><varname>return_flags</varname></term> |
4466 |
-+ <listitem> |
4467 |
-+ <para> |
4468 |
-+ Kernel-provided return flags. Currently, the following flags are |
4469 |
-+ defined. |
4470 |
-+ </para> |
4471 |
-+ <variablelist> |
4472 |
-+ <varlistentry> |
4473 |
-+ <term><constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant></term> |
4474 |
-+ <listitem> |
4475 |
-+ <para> |
4476 |
-+ The message contained memfds or file descriptors, and the |
4477 |
-+ kernel failed to install one or more of them at receive time. |
4478 |
-+ Most probably that happened because the maximum number of |
4479 |
-+ file descriptors for the receiver's task were exceeded. |
4480 |
-+ In such cases, the message is still delivered, so this is not |
4481 |
-+ a fatal condition. File descriptors numbers inside the |
4482 |
-+ <constant>KDBUS_ITEM_FDS</constant> item or memfd files |
4483 |
-+ referenced by <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> |
4484 |
-+ items which could not be installed will be set to |
4485 |
-+ <constant>-1</constant>. |
4486 |
-+ </para> |
4487 |
-+ </listitem> |
4488 |
-+ </varlistentry> |
4489 |
-+ </variablelist> |
4490 |
-+ </listitem> |
4491 |
-+ </varlistentry> |
4492 |
-+ </variablelist> |
4493 |
-+ |
4494 |
-+ <para> |
4495 |
-+ Unless <constant>KDBUS_RECV_DROP</constant> was passed, the |
4496 |
-+ <varname>offset</varname> field contains the location of the new message |
4497 |
-+ inside the receiver's pool after the <constant>KDBUS_CMD_RECV</constant> |
4498 |
-+ ioctl was employed. The message is stored as <type>struct kdbus_msg</type> |
4499 |
-+ at this offset, and can be interpreted with the semantics described above. |
4500 |
-+ </para> |
4501 |
-+ <para> |
4502 |
-+ Also, if the connection allowed for file descriptor to be passed |
4503 |
-+ (<constant>KDBUS_HELLO_ACCEPT_FD</constant>), and if the message contained |
4504 |
-+ any, they will be installed into the receiving process when the |
4505 |
-+ <constant>KDBUS_CMD_RECV</constant> ioctl is called. |
4506 |
-+ <emphasis>memfds</emphasis> may always be part of the message payload. |
4507 |
-+ The receiving task is obliged to close all file descriptors appropriately |
4508 |
-+ once no longer needed. If <constant>KDBUS_RECV_PEEK</constant> is set, no |
4509 |
-+ file descriptors are installed. This allows for peeking at a message, |
4510 |
-+ looking at its metadata only and dropping it via |
4511 |
-+ <constant>KDBUS_RECV_DROP</constant>, without installing any of the file |
4512 |
-+ descriptors into the receiving process. |
4513 |
-+ </para> |
4514 |
-+ <para> |
4515 |
-+ The caller is obliged to call the <constant>KDBUS_CMD_FREE</constant> |
4516 |
-+ ioctl with the returned offset when the memory is no longer needed. |
4517 |
-+ </para> |
4518 |
-+ </refsect1> |
4519 |
-+ |
4520 |
-+ <refsect1> |
4521 |
-+ <title>Notifications</title> |
4522 |
-+ <para> |
4523 |
-+ A kernel notification is a regular kdbus message with the following |
4524 |
-+ details. |
4525 |
-+ </para> |
4526 |
-+ |
4527 |
-+ <itemizedlist> |
4528 |
-+ <listitem><para> |
4529 |
-+ kdbus_msg.src_id == <constant>KDBUS_SRC_ID_KERNEL</constant> |
4530 |
-+ </para></listitem> |
4531 |
-+ <listitem><para> |
4532 |
-+ kdbus_msg.dst_id == <constant>KDBUS_DST_ID_BROADCAST</constant> |
4533 |
-+ </para></listitem> |
4534 |
-+ <listitem><para> |
4535 |
-+ kdbus_msg.payload_type == <constant>KDBUS_PAYLOAD_KERNEL</constant> |
4536 |
-+ </para></listitem> |
4537 |
-+ <listitem><para> |
4538 |
-+ Has exactly one of the items attached that are described below. |
4539 |
-+ </para></listitem> |
4540 |
-+ <listitem><para> |
4541 |
-+ Always has a timestamp item (<constant>KDBUS_ITEM_TIMESTAMP</constant>) |
4542 |
-+ attached. |
4543 |
-+ </para></listitem> |
4544 |
-+ </itemizedlist> |
4545 |
-+ |
4546 |
-+ <para> |
4547 |
-+ The kernel will notify its users of the following events. |
4548 |
-+ </para> |
4549 |
-+ |
4550 |
-+ <itemizedlist> |
4551 |
-+ <listitem><para> |
4552 |
-+ When connection <emphasis>A</emphasis> is terminated while connection |
4553 |
-+ <emphasis>B</emphasis> is waiting for a reply from it, connection |
4554 |
-+ <emphasis>B</emphasis> is notified with a message with an item of |
4555 |
-+ type <constant>KDBUS_ITEM_REPLY_DEAD</constant>. |
4556 |
-+ </para></listitem> |
4557 |
-+ |
4558 |
-+ <listitem><para> |
4559 |
-+ When connection <emphasis>A</emphasis> does not receive a reply from |
4560 |
-+ connection <emphasis>B</emphasis> within the specified timeout window, |
4561 |
-+ connection <emphasis>A</emphasis> will receive a message with an |
4562 |
-+ item of type <constant>KDBUS_ITEM_REPLY_TIMEOUT</constant>. |
4563 |
-+ </para></listitem> |
4564 |
-+ |
4565 |
-+ <listitem><para> |
4566 |
-+ When an ordinary connection (not a monitor) is created on or removed |
4567 |
-+ from a bus, messages with an item of type |
4568 |
-+ <constant>KDBUS_ITEM_ID_ADD</constant> or |
4569 |
-+ <constant>KDBUS_ITEM_ID_REMOVE</constant>, respectively, are delivered |
4570 |
-+ to all bus members that match these messages through their match |
4571 |
-+ database. Eavesdroppers (monitor connections) do not cause such |
4572 |
-+ notifications to be sent. They are invisible on the bus. |
4573 |
-+ </para></listitem> |
4574 |
-+ |
4575 |
-+ <listitem><para> |
4576 |
-+ When a connection gains or loses ownership of a name, messages with an |
4577 |
-+ item of type <constant>KDBUS_ITEM_NAME_ADD</constant>, |
4578 |
-+ <constant>KDBUS_ITEM_NAME_REMOVE</constant> or |
4579 |
-+ <constant>KDBUS_ITEM_NAME_CHANGE</constant> are delivered to all bus |
4580 |
-+ members that match these messages through their match database. |
4581 |
-+ </para></listitem> |
4582 |
-+ </itemizedlist> |
4583 |
-+ </refsect1> |
4584 |
-+ |
4585 |
-+ <refsect1> |
4586 |
-+ <title>Return value</title> |
4587 |
-+ <para> |
4588 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
4589 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
4590 |
-+ <varname>errno</varname> is set to indicate the error. |
4591 |
-+ If the issued ioctl is illegal for the file descriptor used, |
4592 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
4593 |
-+ </para> |
4594 |
-+ |
4595 |
-+ <refsect2> |
4596 |
-+ <title> |
4597 |
-+ <constant>KDBUS_CMD_SEND</constant> may fail with the following |
4598 |
-+ errors |
4599 |
-+ </title> |
4600 |
-+ |
4601 |
-+ <variablelist> |
4602 |
-+ <varlistentry> |
4603 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
4604 |
-+ <listitem><para> |
4605 |
-+ The connection is not an ordinary connection, or the passed |
4606 |
-+ file descriptors in <constant>KDBUS_ITEM_FDS</constant> item are |
4607 |
-+ either kdbus handles or unix domain sockets. Both are currently |
4608 |
-+ unsupported. |
4609 |
-+ </para></listitem> |
4610 |
-+ </varlistentry> |
4611 |
-+ |
4612 |
-+ <varlistentry> |
4613 |
-+ <term><constant>EINVAL</constant></term> |
4614 |
-+ <listitem><para> |
4615 |
-+ The submitted payload type is |
4616 |
-+ <constant>KDBUS_PAYLOAD_KERNEL</constant>, |
4617 |
-+ <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set without timeout |
4618 |
-+ or cookie values, <constant>KDBUS_SEND_SYNC_REPLY</constant> was |
4619 |
-+ set without <constant>KDBUS_MSG_EXPECT_REPLY</constant>, an invalid |
4620 |
-+ item was supplied, <constant>src_id</constant> was non-zero and was |
4621 |
-+ different from the current connection's ID, a supplied memfd had a |
4622 |
-+ size of 0, or a string was not properly null-terminated. |
4623 |
-+ </para></listitem> |
4624 |
-+ </varlistentry> |
4625 |
-+ |
4626 |
-+ <varlistentry> |
4627 |
-+ <term><constant>ENOTUNIQ</constant></term> |
4628 |
-+ <listitem><para> |
4629 |
-+ The supplied destination is |
4630 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> and either |
4631 |
-+ file descriptors were passed, or |
4632 |
-+ <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set, |
4633 |
-+ or a timeout was given. |
4634 |
-+ </para></listitem> |
4635 |
-+ </varlistentry> |
4636 |
-+ |
4637 |
-+ <varlistentry> |
4638 |
-+ <term><constant>E2BIG</constant></term> |
4639 |
-+ <listitem><para> |
4640 |
-+ Too many items. |
4641 |
-+ </para></listitem> |
4642 |
-+ </varlistentry> |
4643 |
-+ |
4644 |
-+ <varlistentry> |
4645 |
-+ <term><constant>EMSGSIZE</constant></term> |
4646 |
-+ <listitem><para> |
4647 |
-+ The size of the message header and items or the payload vector |
4648 |
-+ is excessive. |
4649 |
-+ </para></listitem> |
4650 |
-+ </varlistentry> |
4651 |
-+ |
4652 |
-+ <varlistentry> |
4653 |
-+ <term><constant>EEXIST</constant></term> |
4654 |
-+ <listitem><para> |
4655 |
-+ Multiple <constant>KDBUS_ITEM_FDS</constant>, |
4656 |
-+ <constant>KDBUS_ITEM_BLOOM_FILTER</constant> or |
4657 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> items were supplied. |
4658 |
-+ </para></listitem> |
4659 |
-+ </varlistentry> |
4660 |
-+ |
4661 |
-+ <varlistentry> |
4662 |
-+ <term><constant>EBADF</constant></term> |
4663 |
-+ <listitem><para> |
4664 |
-+ The supplied <constant>KDBUS_ITEM_FDS</constant> or |
4665 |
-+ <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> items |
4666 |
-+ contained an illegal file descriptor. |
4667 |
-+ </para></listitem> |
4668 |
-+ </varlistentry> |
4669 |
-+ |
4670 |
-+ <varlistentry> |
4671 |
-+ <term><constant>EMEDIUMTYPE</constant></term> |
4672 |
-+ <listitem><para> |
4673 |
-+ The supplied memfd is not a sealed kdbus memfd. |
4674 |
-+ </para></listitem> |
4675 |
-+ </varlistentry> |
4676 |
-+ |
4677 |
-+ <varlistentry> |
4678 |
-+ <term><constant>EMFILE</constant></term> |
4679 |
-+ <listitem><para> |
4680 |
-+ Too many file descriptors inside a |
4681 |
-+ <constant>KDBUS_ITEM_FDS</constant>. |
4682 |
-+ </para></listitem> |
4683 |
-+ </varlistentry> |
4684 |
-+ |
4685 |
-+ <varlistentry> |
4686 |
-+ <term><constant>EBADMSG</constant></term> |
4687 |
-+ <listitem><para> |
4688 |
-+ An item had illegal size, both a <constant>dst_id</constant> and a |
4689 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> was given, or both a name |
4690 |
-+ and a bloom filter was given. |
4691 |
-+ </para></listitem> |
4692 |
-+ </varlistentry> |
4693 |
-+ |
4694 |
-+ <varlistentry> |
4695 |
-+ <term><constant>ETXTBSY</constant></term> |
4696 |
-+ <listitem><para> |
4697 |
-+ The supplied kdbus memfd file cannot be sealed or the seal |
4698 |
-+ was removed, because it is shared with other processes or |
4699 |
-+ still mapped with |
4700 |
-+ <citerefentry> |
4701 |
-+ <refentrytitle>mmap</refentrytitle> |
4702 |
-+ <manvolnum>2</manvolnum> |
4703 |
-+ </citerefentry>. |
4704 |
-+ </para></listitem> |
4705 |
-+ </varlistentry> |
4706 |
-+ |
4707 |
-+ <varlistentry> |
4708 |
-+ <term><constant>ECOMM</constant></term> |
4709 |
-+ <listitem><para> |
4710 |
-+ A peer does not accept the file descriptors addressed to it. |
4711 |
-+ </para></listitem> |
4712 |
-+ </varlistentry> |
4713 |
-+ |
4714 |
-+ <varlistentry> |
4715 |
-+ <term><constant>EFAULT</constant></term> |
4716 |
-+ <listitem><para> |
4717 |
-+ The supplied bloom filter size was not 64-bit aligned, or supplied |
4718 |
-+ memory could not be accessed by the kernel. |
4719 |
-+ </para></listitem> |
4720 |
-+ </varlistentry> |
4721 |
-+ |
4722 |
-+ <varlistentry> |
4723 |
-+ <term><constant>EDOM</constant></term> |
4724 |
-+ <listitem><para> |
4725 |
-+ The supplied bloom filter size did not match the bloom filter |
4726 |
-+ size of the bus. |
4727 |
-+ </para></listitem> |
4728 |
-+ </varlistentry> |
4729 |
-+ |
4730 |
-+ <varlistentry> |
4731 |
-+ <term><constant>EDESTADDRREQ</constant></term> |
4732 |
-+ <listitem><para> |
4733 |
-+ <constant>dst_id</constant> was set to |
4734 |
-+ <constant>KDBUS_DST_ID_NAME</constant>, but no |
4735 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> was attached. |
4736 |
-+ </para></listitem> |
4737 |
-+ </varlistentry> |
4738 |
-+ |
4739 |
-+ <varlistentry> |
4740 |
-+ <term><constant>ESRCH</constant></term> |
4741 |
-+ <listitem><para> |
4742 |
-+ The name to look up was not found in the name registry. |
4743 |
-+ </para></listitem> |
4744 |
-+ </varlistentry> |
4745 |
-+ |
4746 |
-+ <varlistentry> |
4747 |
-+ <term><constant>EADDRNOTAVAIL</constant></term> |
4748 |
-+ <listitem><para> |
4749 |
-+ <constant>KDBUS_MSG_NO_AUTO_START</constant> was given but the |
4750 |
-+ destination connection is an activator. |
4751 |
-+ </para></listitem> |
4752 |
-+ </varlistentry> |
4753 |
-+ |
4754 |
-+ <varlistentry> |
4755 |
-+ <term><constant>ENXIO</constant></term> |
4756 |
-+ <listitem><para> |
4757 |
-+ The passed numeric destination connection ID couldn't be found, |
4758 |
-+ or is not connected. |
4759 |
-+ </para></listitem> |
4760 |
-+ </varlistentry> |
4761 |
-+ |
4762 |
-+ <varlistentry> |
4763 |
-+ <term><constant>ECONNRESET</constant></term> |
4764 |
-+ <listitem><para> |
4765 |
-+ The destination connection is no longer active. |
4766 |
-+ </para></listitem> |
4767 |
-+ </varlistentry> |
4768 |
-+ |
4769 |
-+ <varlistentry> |
4770 |
-+ <term><constant>ETIMEDOUT</constant></term> |
4771 |
-+ <listitem><para> |
4772 |
-+ Timeout while synchronously waiting for a reply. |
4773 |
-+ </para></listitem> |
4774 |
-+ </varlistentry> |
4775 |
-+ |
4776 |
-+ <varlistentry> |
4777 |
-+ <term><constant>EINTR</constant></term> |
4778 |
-+ <listitem><para> |
4779 |
-+ Interrupted system call while synchronously waiting for a reply. |
4780 |
-+ </para></listitem> |
4781 |
-+ </varlistentry> |
4782 |
-+ |
4783 |
-+ <varlistentry> |
4784 |
-+ <term><constant>EPIPE</constant></term> |
4785 |
-+ <listitem><para> |
4786 |
-+ When sending a message, a synchronous reply from the receiving |
4787 |
-+ connection was expected but the connection died before answering. |
4788 |
-+ </para></listitem> |
4789 |
-+ </varlistentry> |
4790 |
-+ |
4791 |
-+ <varlistentry> |
4792 |
-+ <term><constant>ENOBUFS</constant></term> |
4793 |
-+ <listitem><para> |
4794 |
-+ Too many pending messages on the receiver side. |
4795 |
-+ </para></listitem> |
4796 |
-+ </varlistentry> |
4797 |
-+ |
4798 |
-+ <varlistentry> |
4799 |
-+ <term><constant>EREMCHG</constant></term> |
4800 |
-+ <listitem><para> |
4801 |
-+ Both a well-known name and a unique name (ID) was given, but |
4802 |
-+ the name is not currently owned by that connection. |
4803 |
-+ </para></listitem> |
4804 |
-+ </varlistentry> |
4805 |
-+ |
4806 |
-+ <varlistentry> |
4807 |
-+ <term><constant>EXFULL</constant></term> |
4808 |
-+ <listitem><para> |
4809 |
-+ The memory pool of the receiver is full. |
4810 |
-+ </para></listitem> |
4811 |
-+ </varlistentry> |
4812 |
-+ |
4813 |
-+ <varlistentry> |
4814 |
-+ <term><constant>EREMOTEIO</constant></term> |
4815 |
-+ <listitem><para> |
4816 |
-+ While synchronously waiting for a reply, the remote peer |
4817 |
-+ failed with an I/O error. |
4818 |
-+ </para></listitem> |
4819 |
-+ </varlistentry> |
4820 |
-+ </variablelist> |
4821 |
-+ </refsect2> |
4822 |
-+ |
4823 |
-+ <refsect2> |
4824 |
-+ <title> |
4825 |
-+ <constant>KDBUS_CMD_RECV</constant> may fail with the following |
4826 |
-+ errors |
4827 |
-+ </title> |
4828 |
-+ |
4829 |
-+ <variablelist> |
4830 |
-+ <varlistentry> |
4831 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
4832 |
-+ <listitem><para> |
4833 |
-+ The connection is not an ordinary connection, or the passed |
4834 |
-+ file descriptors are either kdbus handles or unix domain |
4835 |
-+ sockets. Both are currently unsupported. |
4836 |
-+ </para></listitem> |
4837 |
-+ </varlistentry> |
4838 |
-+ |
4839 |
-+ <varlistentry> |
4840 |
-+ <term><constant>EINVAL</constant></term> |
4841 |
-+ <listitem><para> |
4842 |
-+ Invalid flags or offset. |
4843 |
-+ </para></listitem> |
4844 |
-+ </varlistentry> |
4845 |
-+ |
4846 |
-+ <varlistentry> |
4847 |
-+ <term><constant>EAGAIN</constant></term> |
4848 |
-+ <listitem><para> |
4849 |
-+ No message found in the queue. |
4850 |
-+ </para></listitem> |
4851 |
-+ </varlistentry> |
4852 |
-+ </variablelist> |
4853 |
-+ </refsect2> |
4854 |
-+ </refsect1> |
4855 |
-+ |
4856 |
-+ <refsect1> |
4857 |
-+ <title>See Also</title> |
4858 |
-+ <simplelist type="inline"> |
4859 |
-+ <member> |
4860 |
-+ <citerefentry> |
4861 |
-+ <refentrytitle>kdbus</refentrytitle> |
4862 |
-+ <manvolnum>7</manvolnum> |
4863 |
-+ </citerefentry> |
4864 |
-+ </member> |
4865 |
-+ <member> |
4866 |
-+ <citerefentry> |
4867 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
4868 |
-+ <manvolnum>7</manvolnum> |
4869 |
-+ </citerefentry> |
4870 |
-+ </member> |
4871 |
-+ <member> |
4872 |
-+ <citerefentry> |
4873 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
4874 |
-+ <manvolnum>7</manvolnum> |
4875 |
-+ </citerefentry> |
4876 |
-+ </member> |
4877 |
-+ <member> |
4878 |
-+ <citerefentry> |
4879 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
4880 |
-+ <manvolnum>7</manvolnum> |
4881 |
-+ </citerefentry> |
4882 |
-+ </member> |
4883 |
-+ <member> |
4884 |
-+ <citerefentry> |
4885 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
4886 |
-+ <manvolnum>7</manvolnum> |
4887 |
-+ </citerefentry> |
4888 |
-+ </member> |
4889 |
-+ <member> |
4890 |
-+ <citerefentry> |
4891 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
4892 |
-+ <manvolnum>7</manvolnum> |
4893 |
-+ </citerefentry> |
4894 |
-+ </member> |
4895 |
-+ <member> |
4896 |
-+ <citerefentry> |
4897 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
4898 |
-+ <manvolnum>7</manvolnum> |
4899 |
-+ </citerefentry> |
4900 |
-+ </member> |
4901 |
-+ <member> |
4902 |
-+ <citerefentry> |
4903 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
4904 |
-+ <manvolnum>7</manvolnum> |
4905 |
-+ </citerefentry> |
4906 |
-+ </member> |
4907 |
-+ <member> |
4908 |
-+ <citerefentry> |
4909 |
-+ <refentrytitle>clock_gettime</refentrytitle> |
4910 |
-+ <manvolnum>2</manvolnum> |
4911 |
-+ </citerefentry> |
4912 |
-+ </member> |
4913 |
-+ <member> |
4914 |
-+ <citerefentry> |
4915 |
-+ <refentrytitle>ioctl</refentrytitle> |
4916 |
-+ <manvolnum>2</manvolnum> |
4917 |
-+ </citerefentry> |
4918 |
-+ </member> |
4919 |
-+ <member> |
4920 |
-+ <citerefentry> |
4921 |
-+ <refentrytitle>poll</refentrytitle> |
4922 |
-+ <manvolnum>2</manvolnum> |
4923 |
-+ </citerefentry> |
4924 |
-+ </member> |
4925 |
-+ <member> |
4926 |
-+ <citerefentry> |
4927 |
-+ <refentrytitle>select</refentrytitle> |
4928 |
-+ <manvolnum>2</manvolnum> |
4929 |
-+ </citerefentry> |
4930 |
-+ </member> |
4931 |
-+ <member> |
4932 |
-+ <citerefentry> |
4933 |
-+ <refentrytitle>epoll</refentrytitle> |
4934 |
-+ <manvolnum>7</manvolnum> |
4935 |
-+ </citerefentry> |
4936 |
-+ </member> |
4937 |
-+ <member> |
4938 |
-+ <citerefentry> |
4939 |
-+ <refentrytitle>eventfd</refentrytitle> |
4940 |
-+ <manvolnum>2</manvolnum> |
4941 |
-+ </citerefentry> |
4942 |
-+ </member> |
4943 |
-+ <member> |
4944 |
-+ <citerefentry> |
4945 |
-+ <refentrytitle>memfd_create</refentrytitle> |
4946 |
-+ <manvolnum>2</manvolnum> |
4947 |
-+ </citerefentry> |
4948 |
-+ </member> |
4949 |
-+ </simplelist> |
4950 |
-+ </refsect1> |
4951 |
-+</refentry> |
4952 |
-diff --git a/Documentation/kdbus/kdbus.name.xml b/Documentation/kdbus/kdbus.name.xml |
4953 |
-new file mode 100644 |
4954 |
-index 0000000..3f5f6a6 |
4955 |
---- /dev/null |
4956 |
-+++ b/Documentation/kdbus/kdbus.name.xml |
4957 |
-@@ -0,0 +1,711 @@ |
4958 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
4959 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
4960 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
4961 |
-+ |
4962 |
-+<refentry id="kdbus.name"> |
4963 |
-+ |
4964 |
-+ <refentryinfo> |
4965 |
-+ <title>kdbus.name</title> |
4966 |
-+ <productname>kdbus.name</productname> |
4967 |
-+ </refentryinfo> |
4968 |
-+ |
4969 |
-+ <refmeta> |
4970 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
4971 |
-+ <manvolnum>7</manvolnum> |
4972 |
-+ </refmeta> |
4973 |
-+ |
4974 |
-+ <refnamediv> |
4975 |
-+ <refname>kdbus.name</refname> |
4976 |
-+ <refpurpose>kdbus.name</refpurpose> |
4977 |
-+ </refnamediv> |
4978 |
-+ |
4979 |
-+ <refsect1> |
4980 |
-+ <title>Description</title> |
4981 |
-+ <para> |
4982 |
-+ Each |
4983 |
-+ <citerefentry> |
4984 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
4985 |
-+ <manvolnum>7</manvolnum> |
4986 |
-+ </citerefentry> |
4987 |
-+ instantiates a name registry to resolve well-known names into unique |
4988 |
-+ connection IDs for message delivery. The registry will be queried when a |
4989 |
-+ message is sent with <varname>kdbus_msg.dst_id</varname> set to |
4990 |
-+ <constant>KDBUS_DST_ID_NAME</constant>, or when a registry dump is |
4991 |
-+ requested with <constant>KDBUS_CMD_NAME_LIST</constant>. |
4992 |
-+ </para> |
4993 |
-+ |
4994 |
-+ <para> |
4995 |
-+ All of the below is subject to policy rules for <emphasis>SEE</emphasis> |
4996 |
-+ and <emphasis>OWN</emphasis> permissions. See |
4997 |
-+ <citerefentry> |
4998 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
4999 |
-+ <manvolnum>7</manvolnum> |
5000 |
-+ </citerefentry> |
5001 |
-+ for more information. |
5002 |
-+ </para> |
5003 |
-+ </refsect1> |
5004 |
-+ |
5005 |
-+ <refsect1> |
5006 |
-+ <title>Name validity</title> |
5007 |
-+ <para> |
5008 |
-+ A name has to comply with the following rules in order to be considered |
5009 |
-+ valid. |
5010 |
-+ </para> |
5011 |
-+ |
5012 |
-+ <itemizedlist> |
5013 |
-+ <listitem> |
5014 |
-+ <para> |
5015 |
-+ The name has two or more elements separated by a |
5016 |
-+ '<literal>.</literal>' (period) character. |
5017 |
-+ </para> |
5018 |
-+ </listitem> |
5019 |
-+ <listitem> |
5020 |
-+ <para> |
5021 |
-+ All elements must contain at least one character. |
5022 |
-+ </para> |
5023 |
-+ </listitem> |
5024 |
-+ <listitem> |
5025 |
-+ <para> |
5026 |
-+ Each element must only contain the ASCII characters |
5027 |
-+ <literal>[A-Z][a-z][0-9]_</literal> and must not begin with a |
5028 |
-+ digit. |
5029 |
-+ </para> |
5030 |
-+ </listitem> |
5031 |
-+ <listitem> |
5032 |
-+ <para> |
5033 |
-+ The name must contain at least one '<literal>.</literal>' (period) |
5034 |
-+ character (and thus at least two elements). |
5035 |
-+ </para> |
5036 |
-+ </listitem> |
5037 |
-+ <listitem> |
5038 |
-+ <para> |
5039 |
-+ The name must not begin with a '<literal>.</literal>' (period) |
5040 |
-+ character. |
5041 |
-+ </para> |
5042 |
-+ </listitem> |
5043 |
-+ <listitem> |
5044 |
-+ <para> |
5045 |
-+ The name must not exceed <constant>255</constant> characters in |
5046 |
-+ length. |
5047 |
-+ </para> |
5048 |
-+ </listitem> |
5049 |
-+ </itemizedlist> |
5050 |
-+ </refsect1> |
5051 |
-+ |
5052 |
-+ <refsect1> |
5053 |
-+ <title>Acquiring a name</title> |
5054 |
-+ <para> |
5055 |
-+ To acquire a name, a client uses the |
5056 |
-+ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> ioctl with |
5057 |
-+ <type>struct kdbus_cmd</type> as argument. |
5058 |
-+ </para> |
5059 |
-+ |
5060 |
-+ <programlisting> |
5061 |
-+struct kdbus_cmd { |
5062 |
-+ __u64 size; |
5063 |
-+ __u64 flags; |
5064 |
-+ __u64 return_flags; |
5065 |
-+ struct kdbus_item items[0]; |
5066 |
-+}; |
5067 |
-+ </programlisting> |
5068 |
-+ |
5069 |
-+ <para>The fields in this struct are described below.</para> |
5070 |
-+ |
5071 |
-+ <variablelist> |
5072 |
-+ <varlistentry> |
5073 |
-+ <term><varname>size</varname></term> |
5074 |
-+ <listitem><para> |
5075 |
-+ The overall size of the struct, including its items. |
5076 |
-+ </para></listitem> |
5077 |
-+ </varlistentry> |
5078 |
-+ |
5079 |
-+ <varlistentry> |
5080 |
-+ <term><varname>flags</varname></term> |
5081 |
-+ <listitem><para>Flags to control details in the name acquisition.</para> |
5082 |
-+ <variablelist> |
5083 |
-+ <varlistentry> |
5084 |
-+ <term><constant>KDBUS_NAME_REPLACE_EXISTING</constant></term> |
5085 |
-+ <listitem> |
5086 |
-+ <para> |
5087 |
-+ Acquiring a name that is already present usually fails, |
5088 |
-+ unless this flag is set in the call, and |
5089 |
-+ <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> (see below) |
5090 |
-+ was set when the current owner of the name acquired it, or |
5091 |
-+ if the current owner is an activator connection (see |
5092 |
-+ <citerefentry> |
5093 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5094 |
-+ <manvolnum>7</manvolnum> |
5095 |
-+ </citerefentry>). |
5096 |
-+ </para> |
5097 |
-+ </listitem> |
5098 |
-+ </varlistentry> |
5099 |
-+ |
5100 |
-+ <varlistentry> |
5101 |
-+ <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term> |
5102 |
-+ <listitem> |
5103 |
-+ <para> |
5104 |
-+ Allow other connections to take over this name. When this |
5105 |
-+ happens, the former owner of the connection will be notified |
5106 |
-+ of the name loss. |
5107 |
-+ </para> |
5108 |
-+ </listitem> |
5109 |
-+ </varlistentry> |
5110 |
-+ |
5111 |
-+ <varlistentry> |
5112 |
-+ <term><constant>KDBUS_NAME_QUEUE</constant></term> |
5113 |
-+ <listitem> |
5114 |
-+ <para> |
5115 |
-+ A name that is already acquired by a connection can not be |
5116 |
-+ acquired again (unless the |
5117 |
-+ <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> flag was |
5118 |
-+ set during acquisition; see above). |
5119 |
-+ However, a connection can put itself in a queue of |
5120 |
-+ connections waiting for the name to be released. Once that |
5121 |
-+ happens, the first connection in that queue becomes the new |
5122 |
-+ owner and is notified accordingly. |
5123 |
-+ </para> |
5124 |
-+ </listitem> |
5125 |
-+ </varlistentry> |
5126 |
-+ |
5127 |
-+ <varlistentry> |
5128 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5129 |
-+ <listitem> |
5130 |
-+ <para> |
5131 |
-+ Request a set of valid flags for this ioctl. When this bit is |
5132 |
-+ set, no action is taken; the ioctl will fail with |
5133 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> |
5134 |
-+ is set to <constant>EPROTO</constant>. |
5135 |
-+ Once the ioctl returned, the <varname>flags</varname> |
5136 |
-+ field will have all bits set that the kernel recognizes as |
5137 |
-+ valid for this command. |
5138 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5139 |
-+ cleared by the operation. |
5140 |
-+ </para> |
5141 |
-+ </listitem> |
5142 |
-+ </varlistentry> |
5143 |
-+ </variablelist> |
5144 |
-+ </listitem> |
5145 |
-+ </varlistentry> |
5146 |
-+ |
5147 |
-+ <varlistentry> |
5148 |
-+ <term><varname>return_flags</varname></term> |
5149 |
-+ <listitem> |
5150 |
-+ <para> |
5151 |
-+ Flags returned by the kernel. Currently, the following may be |
5152 |
-+ returned by the kernel. |
5153 |
-+ </para> |
5154 |
-+ <variablelist> |
5155 |
-+ <varlistentry> |
5156 |
-+ <term><constant>KDBUS_NAME_IN_QUEUE</constant></term> |
5157 |
-+ <listitem> |
5158 |
-+ <para> |
5159 |
-+ The name was not acquired yet, but the connection was |
5160 |
-+ placed in the queue of peers waiting for the name. |
5161 |
-+ This can only happen if <constant>KDBUS_NAME_QUEUE</constant> |
5162 |
-+ was set in the <varname>flags</varname> member (see above). |
5163 |
-+ The connection will receive a name owner change notification |
5164 |
-+ once the current owner has given up the name and its |
5165 |
-+ ownership was transferred. |
5166 |
-+ </para> |
5167 |
-+ </listitem> |
5168 |
-+ </varlistentry> |
5169 |
-+ </variablelist> |
5170 |
-+ </listitem> |
5171 |
-+ </varlistentry> |
5172 |
-+ |
5173 |
-+ <varlistentry> |
5174 |
-+ <term><varname>items</varname></term> |
5175 |
-+ <listitem> |
5176 |
-+ <para> |
5177 |
-+ Items to submit the name. Currently, one item of type |
5178 |
-+ <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and |
5179 |
-+ the contained string must be a valid bus name. |
5180 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for |
5181 |
-+ valid item types. See |
5182 |
-+ <citerefentry> |
5183 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5184 |
-+ <manvolnum>7</manvolnum> |
5185 |
-+ </citerefentry> |
5186 |
-+ for a detailed description of how this item is used. |
5187 |
-+ </para> |
5188 |
-+ <para> |
5189 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
5190 |
-+ <varname>errno</varname> set to <errorname>>EINVAL</errorname>. |
5191 |
-+ </para> |
5192 |
-+ </listitem> |
5193 |
-+ </varlistentry> |
5194 |
-+ </variablelist> |
5195 |
-+ </refsect1> |
5196 |
-+ |
5197 |
-+ <refsect1> |
5198 |
-+ <title>Releasing a name</title> |
5199 |
-+ <para> |
5200 |
-+ A connection may release a name explicitly with the |
5201 |
-+ <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl. If the connection was |
5202 |
-+ an implementer of an activatable name, its pending messages are moved |
5203 |
-+ back to the activator. If there are any connections queued up as waiters |
5204 |
-+ for the name, the first one in the queue (the oldest entry) will become |
5205 |
-+ the new owner. The same happens implicitly for all names once a |
5206 |
-+ connection terminates. See |
5207 |
-+ <citerefentry> |
5208 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5209 |
-+ <manvolnum>7</manvolnum> |
5210 |
-+ </citerefentry> |
5211 |
-+ for more information on connections. |
5212 |
-+ </para> |
5213 |
-+ <para> |
5214 |
-+ The <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl uses the same data |
5215 |
-+ structure as the acquisition call |
5216 |
-+ (<constant>KDBUS_CMD_NAME_ACQUIRE</constant>), |
5217 |
-+ but with slightly different field usage. |
5218 |
-+ </para> |
5219 |
-+ |
5220 |
-+ <programlisting> |
5221 |
-+struct kdbus_cmd { |
5222 |
-+ __u64 size; |
5223 |
-+ __u64 flags; |
5224 |
-+ __u64 return_flags; |
5225 |
-+ struct kdbus_item items[0]; |
5226 |
-+}; |
5227 |
-+ </programlisting> |
5228 |
-+ |
5229 |
-+ <para>The fields in this struct are described below.</para> |
5230 |
-+ |
5231 |
-+ <variablelist> |
5232 |
-+ <varlistentry> |
5233 |
-+ <term><varname>size</varname></term> |
5234 |
-+ <listitem><para> |
5235 |
-+ The overall size of the struct, including its items. |
5236 |
-+ </para></listitem> |
5237 |
-+ </varlistentry> |
5238 |
-+ |
5239 |
-+ <varlistentry> |
5240 |
-+ <term><varname>flags</varname></term> |
5241 |
-+ <listitem><para> |
5242 |
-+ Flags to the command. Currently unused. |
5243 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
5244 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
5245 |
-+ and the <varname>flags</varname> field is set to |
5246 |
-+ <constant>0</constant>. |
5247 |
-+ </para></listitem> |
5248 |
-+ </varlistentry> |
5249 |
-+ |
5250 |
-+ <varlistentry> |
5251 |
-+ <term><varname>return_flags</varname></term> |
5252 |
-+ <listitem><para> |
5253 |
-+ Flags returned by the kernel. Currently unused and always set to |
5254 |
-+ <constant>0</constant> by the kernel. |
5255 |
-+ </para></listitem> |
5256 |
-+ </varlistentry> |
5257 |
-+ |
5258 |
-+ <varlistentry> |
5259 |
-+ <term><varname>items</varname></term> |
5260 |
-+ <listitem> |
5261 |
-+ <para> |
5262 |
-+ Items to submit the name. Currently, one item of type |
5263 |
-+ <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and |
5264 |
-+ the contained string must be a valid bus name. |
5265 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for |
5266 |
-+ valid item types. See |
5267 |
-+ <citerefentry> |
5268 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5269 |
-+ <manvolnum>7</manvolnum> |
5270 |
-+ </citerefentry> |
5271 |
-+ for a detailed description of how this item is used. |
5272 |
-+ </para> |
5273 |
-+ <para> |
5274 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
5275 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
5276 |
-+ </para> |
5277 |
-+ </listitem> |
5278 |
-+ </varlistentry> |
5279 |
-+ </variablelist> |
5280 |
-+ </refsect1> |
5281 |
-+ |
5282 |
-+ <refsect1> |
5283 |
-+ <title>Dumping the name registry</title> |
5284 |
-+ <para> |
5285 |
-+ A connection may request a complete or filtered dump of currently active |
5286 |
-+ bus names with the <constant>KDBUS_CMD_LIST</constant> ioctl, which |
5287 |
-+ takes a <type>struct kdbus_cmd_list</type> as argument. |
5288 |
-+ </para> |
5289 |
-+ |
5290 |
-+ <programlisting> |
5291 |
-+struct kdbus_cmd_list { |
5292 |
-+ __u64 flags; |
5293 |
-+ __u64 return_flags; |
5294 |
-+ __u64 offset; |
5295 |
-+}; |
5296 |
-+ </programlisting> |
5297 |
-+ |
5298 |
-+ <para>The fields in this struct are described below.</para> |
5299 |
-+ |
5300 |
-+ <variablelist> |
5301 |
-+ <varlistentry> |
5302 |
-+ <term><varname>flags</varname></term> |
5303 |
-+ <listitem> |
5304 |
-+ <para> |
5305 |
-+ Any combination of flags to specify which names should be dumped. |
5306 |
-+ </para> |
5307 |
-+ <variablelist> |
5308 |
-+ <varlistentry> |
5309 |
-+ <term><constant>KDBUS_LIST_UNIQUE</constant></term> |
5310 |
-+ <listitem> |
5311 |
-+ <para> |
5312 |
-+ List the unique (numeric) IDs of the connection, whether it |
5313 |
-+ owns a name or not. |
5314 |
-+ </para> |
5315 |
-+ </listitem> |
5316 |
-+ </varlistentry> |
5317 |
-+ |
5318 |
-+ <varlistentry> |
5319 |
-+ <term><constant>KDBUS_LIST_NAMES</constant></term> |
5320 |
-+ <listitem> |
5321 |
-+ <para> |
5322 |
-+ List well-known names stored in the database which are |
5323 |
-+ actively owned by a real connection (not an activator). |
5324 |
-+ </para> |
5325 |
-+ </listitem> |
5326 |
-+ </varlistentry> |
5327 |
-+ |
5328 |
-+ <varlistentry> |
5329 |
-+ <term><constant>KDBUS_LIST_ACTIVATORS</constant></term> |
5330 |
-+ <listitem> |
5331 |
-+ <para> |
5332 |
-+ List names that are owned by an activator. |
5333 |
-+ </para> |
5334 |
-+ </listitem> |
5335 |
-+ </varlistentry> |
5336 |
-+ |
5337 |
-+ <varlistentry> |
5338 |
-+ <term><constant>KDBUS_LIST_QUEUED</constant></term> |
5339 |
-+ <listitem> |
5340 |
-+ <para> |
5341 |
-+ List connections that are not yet owning a name but are |
5342 |
-+ waiting for it to become available. |
5343 |
-+ </para> |
5344 |
-+ </listitem> |
5345 |
-+ </varlistentry> |
5346 |
-+ |
5347 |
-+ <varlistentry> |
5348 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5349 |
-+ <listitem> |
5350 |
-+ <para> |
5351 |
-+ Request a set of valid flags for this ioctl. When this bit is |
5352 |
-+ set, no action is taken; the ioctl will fail with |
5353 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> |
5354 |
-+ is set to <constant>EPROTO</constant>. |
5355 |
-+ Once the ioctl returned, the <varname>flags</varname> |
5356 |
-+ field will have all bits set that the kernel recognizes as |
5357 |
-+ valid for this command. |
5358 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5359 |
-+ cleared by the operation. |
5360 |
-+ </para> |
5361 |
-+ </listitem> |
5362 |
-+ </varlistentry> |
5363 |
-+ </variablelist> |
5364 |
-+ </listitem> |
5365 |
-+ </varlistentry> |
5366 |
-+ |
5367 |
-+ <varlistentry> |
5368 |
-+ <term><varname>return_flags</varname></term> |
5369 |
-+ <listitem><para> |
5370 |
-+ Flags returned by the kernel. Currently unused and always set to |
5371 |
-+ <constant>0</constant> by the kernel. |
5372 |
-+ </para></listitem> |
5373 |
-+ </varlistentry> |
5374 |
-+ |
5375 |
-+ <varlistentry> |
5376 |
-+ <term><varname>offset</varname></term> |
5377 |
-+ <listitem><para> |
5378 |
-+ When the ioctl returns successfully, the offset to the name registry |
5379 |
-+ dump inside the connection's pool will be stored in this field. |
5380 |
-+ </para></listitem> |
5381 |
-+ </varlistentry> |
5382 |
-+ </variablelist> |
5383 |
-+ |
5384 |
-+ <para> |
5385 |
-+ The returned list of names is stored in a <type>struct kdbus_list</type> |
5386 |
-+ that in turn contains an array of type <type>struct kdbus_info</type>, |
5387 |
-+ The array-size in bytes is given as <varname>list_size</varname>. |
5388 |
-+ The fields inside <type>struct kdbus_info</type> is described next. |
5389 |
-+ </para> |
5390 |
-+ |
5391 |
-+ <programlisting> |
5392 |
-+struct kdbus_info { |
5393 |
-+ __u64 size; |
5394 |
-+ __u64 id; |
5395 |
-+ __u64 flags; |
5396 |
-+ struct kdbus_item items[0]; |
5397 |
-+}; |
5398 |
-+ </programlisting> |
5399 |
-+ |
5400 |
-+ <para>The fields in this struct are described below.</para> |
5401 |
-+ |
5402 |
-+ <variablelist> |
5403 |
-+ <varlistentry> |
5404 |
-+ <term><varname>size</varname></term> |
5405 |
-+ <listitem><para> |
5406 |
-+ The overall size of the struct, including its items. |
5407 |
-+ </para></listitem> |
5408 |
-+ </varlistentry> |
5409 |
-+ |
5410 |
-+ <varlistentry> |
5411 |
-+ <term><varname>id</varname></term> |
5412 |
-+ <listitem><para> |
5413 |
-+ The owning connection's unique ID. |
5414 |
-+ </para></listitem> |
5415 |
-+ </varlistentry> |
5416 |
-+ |
5417 |
-+ <varlistentry> |
5418 |
-+ <term><varname>flags</varname></term> |
5419 |
-+ <listitem><para> |
5420 |
-+ The flags of the owning connection. |
5421 |
-+ </para></listitem> |
5422 |
-+ </varlistentry> |
5423 |
-+ |
5424 |
-+ <varlistentry> |
5425 |
-+ <term><varname>items</varname></term> |
5426 |
-+ <listitem> |
5427 |
-+ <para> |
5428 |
-+ Items containing the actual name. Currently, one item of type |
5429 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant> will be attached, |
5430 |
-+ including the name's flags. In that item, the flags field of the |
5431 |
-+ name may carry the following bits: |
5432 |
-+ </para> |
5433 |
-+ <variablelist> |
5434 |
-+ <varlistentry> |
5435 |
-+ <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term> |
5436 |
-+ <listitem> |
5437 |
-+ <para> |
5438 |
-+ Other connections are allowed to take over this name from the |
5439 |
-+ connection that owns it. |
5440 |
-+ </para> |
5441 |
-+ </listitem> |
5442 |
-+ </varlistentry> |
5443 |
-+ |
5444 |
-+ <varlistentry> |
5445 |
-+ <term><constant>KDBUS_NAME_IN_QUEUE</constant></term> |
5446 |
-+ <listitem> |
5447 |
-+ <para> |
5448 |
-+ When retrieving a list of currently acquired names in the |
5449 |
-+ registry, this flag indicates whether the connection |
5450 |
-+ actually owns the name or is currently waiting for it to |
5451 |
-+ become available. |
5452 |
-+ </para> |
5453 |
-+ </listitem> |
5454 |
-+ </varlistentry> |
5455 |
-+ |
5456 |
-+ <varlistentry> |
5457 |
-+ <term><constant>KDBUS_NAME_ACTIVATOR</constant></term> |
5458 |
-+ <listitem> |
5459 |
-+ <para> |
5460 |
-+ An activator connection owns a name as a placeholder for an |
5461 |
-+ implementer, which is started on demand by programs as soon |
5462 |
-+ as the first message arrives. There's some more information |
5463 |
-+ on this topic in |
5464 |
-+ <citerefentry> |
5465 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5466 |
-+ <manvolnum>7</manvolnum> |
5467 |
-+ </citerefentry> |
5468 |
-+ . |
5469 |
-+ </para> |
5470 |
-+ <para> |
5471 |
-+ In contrast to |
5472 |
-+ <constant>KDBUS_NAME_REPLACE_EXISTING</constant>, |
5473 |
-+ when a name is taken over from an activator connection, all |
5474 |
-+ the messages that have been queued in the activator |
5475 |
-+ connection will be moved over to the new owner. The activator |
5476 |
-+ connection will still be tracked for the name and will take |
5477 |
-+ control again if the implementer connection terminates. |
5478 |
-+ </para> |
5479 |
-+ <para> |
5480 |
-+ This flag can not be used when acquiring a name, but is |
5481 |
-+ implicitly set through <constant>KDBUS_CMD_HELLO</constant> |
5482 |
-+ with <constant>KDBUS_HELLO_ACTIVATOR</constant> set in |
5483 |
-+ <varname>kdbus_cmd_hello.conn_flags</varname>. |
5484 |
-+ </para> |
5485 |
-+ </listitem> |
5486 |
-+ </varlistentry> |
5487 |
-+ |
5488 |
-+ <varlistentry> |
5489 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5490 |
-+ <listitem> |
5491 |
-+ <para> |
5492 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
5493 |
-+ set, no action is taken; the ioctl will return |
5494 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
5495 |
-+ field will have all bits set that are valid for this command. |
5496 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5497 |
-+ cleared by the operation. |
5498 |
-+ </para> |
5499 |
-+ </listitem> |
5500 |
-+ </varlistentry> |
5501 |
-+ </variablelist> |
5502 |
-+ </listitem> |
5503 |
-+ </varlistentry> |
5504 |
-+ </variablelist> |
5505 |
-+ |
5506 |
-+ <para> |
5507 |
-+ The returned buffer must be freed with the |
5508 |
-+ <constant>KDBUS_CMD_FREE</constant> ioctl when the user is finished with |
5509 |
-+ it. See |
5510 |
-+ <citerefentry> |
5511 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
5512 |
-+ <manvolnum>7</manvolnum> |
5513 |
-+ </citerefentry> |
5514 |
-+ for more information. |
5515 |
-+ </para> |
5516 |
-+ </refsect1> |
5517 |
-+ |
5518 |
-+ <refsect1> |
5519 |
-+ <title>Return value</title> |
5520 |
-+ <para> |
5521 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
5522 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
5523 |
-+ <varname>errno</varname> is set to indicate the error. |
5524 |
-+ If the issued ioctl is illegal for the file descriptor used, |
5525 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
5526 |
-+ </para> |
5527 |
-+ |
5528 |
-+ <refsect2> |
5529 |
-+ <title> |
5530 |
-+ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> may fail with the following |
5531 |
-+ errors |
5532 |
-+ </title> |
5533 |
-+ |
5534 |
-+ <variablelist> |
5535 |
-+ <varlistentry> |
5536 |
-+ <term><constant>EINVAL</constant></term> |
5537 |
-+ <listitem><para> |
5538 |
-+ Illegal command flags, illegal name provided, or an activator |
5539 |
-+ tried to acquire a second name. |
5540 |
-+ </para></listitem> |
5541 |
-+ </varlistentry> |
5542 |
-+ |
5543 |
-+ <varlistentry> |
5544 |
-+ <term><constant>EPERM</constant></term> |
5545 |
-+ <listitem><para> |
5546 |
-+ Policy prohibited name ownership. |
5547 |
-+ </para></listitem> |
5548 |
-+ </varlistentry> |
5549 |
-+ |
5550 |
-+ <varlistentry> |
5551 |
-+ <term><constant>EALREADY</constant></term> |
5552 |
-+ <listitem><para> |
5553 |
-+ Connection already owns that name. |
5554 |
-+ </para></listitem> |
5555 |
-+ </varlistentry> |
5556 |
-+ |
5557 |
-+ <varlistentry> |
5558 |
-+ <term><constant>EEXIST</constant></term> |
5559 |
-+ <listitem><para> |
5560 |
-+ The name already exists and can not be taken over. |
5561 |
-+ </para></listitem> |
5562 |
-+ </varlistentry> |
5563 |
-+ |
5564 |
-+ <varlistentry> |
5565 |
-+ <term><constant>E2BIG</constant></term> |
5566 |
-+ <listitem><para> |
5567 |
-+ The maximum number of well-known names per connection is exhausted. |
5568 |
-+ </para></listitem> |
5569 |
-+ </varlistentry> |
5570 |
-+ </variablelist> |
5571 |
-+ </refsect2> |
5572 |
-+ |
5573 |
-+ <refsect2> |
5574 |
-+ <title> |
5575 |
-+ <constant>KDBUS_CMD_NAME_RELEASE</constant> |
5576 |
-+ may fail with the following errors |
5577 |
-+ </title> |
5578 |
-+ |
5579 |
-+ <variablelist> |
5580 |
-+ <varlistentry> |
5581 |
-+ <term><constant>EINVAL</constant></term> |
5582 |
-+ <listitem><para> |
5583 |
-+ Invalid command flags, or invalid name provided. |
5584 |
-+ </para></listitem> |
5585 |
-+ </varlistentry> |
5586 |
-+ |
5587 |
-+ <varlistentry> |
5588 |
-+ <term><constant>ESRCH</constant></term> |
5589 |
-+ <listitem><para> |
5590 |
-+ Name is not found in the registry. |
5591 |
-+ </para></listitem> |
5592 |
-+ </varlistentry> |
5593 |
-+ |
5594 |
-+ <varlistentry> |
5595 |
-+ <term><constant>EADDRINUSE</constant></term> |
5596 |
-+ <listitem><para> |
5597 |
-+ Name is owned by a different connection and can't be released. |
5598 |
-+ </para></listitem> |
5599 |
-+ </varlistentry> |
5600 |
-+ </variablelist> |
5601 |
-+ </refsect2> |
5602 |
-+ |
5603 |
-+ <refsect2> |
5604 |
-+ <title> |
5605 |
-+ <constant>KDBUS_CMD_LIST</constant> may fail with the following |
5606 |
-+ errors |
5607 |
-+ </title> |
5608 |
-+ |
5609 |
-+ <variablelist> |
5610 |
-+ <varlistentry> |
5611 |
-+ <term><constant>EINVAL</constant></term> |
5612 |
-+ <listitem><para> |
5613 |
-+ Invalid command flags |
5614 |
-+ </para></listitem> |
5615 |
-+ </varlistentry> |
5616 |
-+ |
5617 |
-+ <varlistentry> |
5618 |
-+ <term><constant>ENOBUFS</constant></term> |
5619 |
-+ <listitem><para> |
5620 |
-+ No available memory in the connection's pool. |
5621 |
-+ </para></listitem> |
5622 |
-+ </varlistentry> |
5623 |
-+ </variablelist> |
5624 |
-+ </refsect2> |
5625 |
-+ </refsect1> |
5626 |
-+ |
5627 |
-+ <refsect1> |
5628 |
-+ <title>See Also</title> |
5629 |
-+ <simplelist type="inline"> |
5630 |
-+ <member> |
5631 |
-+ <citerefentry> |
5632 |
-+ <refentrytitle>kdbus</refentrytitle> |
5633 |
-+ <manvolnum>7</manvolnum> |
5634 |
-+ </citerefentry> |
5635 |
-+ </member> |
5636 |
-+ <member> |
5637 |
-+ <citerefentry> |
5638 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
5639 |
-+ <manvolnum>7</manvolnum> |
5640 |
-+ </citerefentry> |
5641 |
-+ </member> |
5642 |
-+ <member> |
5643 |
-+ <citerefentry> |
5644 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5645 |
-+ <manvolnum>7</manvolnum> |
5646 |
-+ </citerefentry> |
5647 |
-+ </member> |
5648 |
-+ <member> |
5649 |
-+ <citerefentry> |
5650 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5651 |
-+ <manvolnum>7</manvolnum> |
5652 |
-+ </citerefentry> |
5653 |
-+ </member> |
5654 |
-+ <member> |
5655 |
-+ <citerefentry> |
5656 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
5657 |
-+ <manvolnum>7</manvolnum> |
5658 |
-+ </citerefentry> |
5659 |
-+ </member> |
5660 |
-+ <member> |
5661 |
-+ <citerefentry> |
5662 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
5663 |
-+ <manvolnum>7</manvolnum> |
5664 |
-+ </citerefentry> |
5665 |
-+ </member> |
5666 |
-+ </simplelist> |
5667 |
-+ </refsect1> |
5668 |
-+</refentry> |
5669 |
-diff --git a/Documentation/kdbus/kdbus.policy.xml b/Documentation/kdbus/kdbus.policy.xml |
5670 |
-new file mode 100644 |
5671 |
-index 0000000..6732416 |
5672 |
---- /dev/null |
5673 |
-+++ b/Documentation/kdbus/kdbus.policy.xml |
5674 |
-@@ -0,0 +1,406 @@ |
5675 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
5676 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
5677 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
5678 |
-+ |
5679 |
-+<refentry id="kdbus.policy"> |
5680 |
-+ |
5681 |
-+ <refentryinfo> |
5682 |
-+ <title>kdbus.policy</title> |
5683 |
-+ <productname>kdbus.policy</productname> |
5684 |
-+ </refentryinfo> |
5685 |
-+ |
5686 |
-+ <refmeta> |
5687 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
5688 |
-+ <manvolnum>7</manvolnum> |
5689 |
-+ </refmeta> |
5690 |
-+ |
5691 |
-+ <refnamediv> |
5692 |
-+ <refname>kdbus.policy</refname> |
5693 |
-+ <refpurpose>kdbus policy</refpurpose> |
5694 |
-+ </refnamediv> |
5695 |
-+ |
5696 |
-+ <refsect1> |
5697 |
-+ <title>Description</title> |
5698 |
-+ |
5699 |
-+ <para> |
5700 |
-+ A kdbus policy restricts the possibilities of connections to own, see and |
5701 |
-+ talk to well-known names. A policy can be associated with a bus (through a |
5702 |
-+ policy holder connection) or a custom endpoint. kdbus stores its policy |
5703 |
-+ information in a database that can be accessed through the following |
5704 |
-+ ioctl commands: |
5705 |
-+ </para> |
5706 |
-+ |
5707 |
-+ <variablelist> |
5708 |
-+ <varlistentry> |
5709 |
-+ <term><constant>KDBUS_CMD_HELLO</constant></term> |
5710 |
-+ <listitem><para> |
5711 |
-+ When creating, or updating, a policy holder connection. See |
5712 |
-+ <citerefentry> |
5713 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5714 |
-+ <manvolnum>7</manvolnum> |
5715 |
-+ </citerefentry>. |
5716 |
-+ </para></listitem> |
5717 |
-+ </varlistentry> |
5718 |
-+ |
5719 |
-+ <varlistentry> |
5720 |
-+ <term><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></term> |
5721 |
-+ <term><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></term> |
5722 |
-+ <listitem><para> |
5723 |
-+ When creating, or updating, a bus custom endpoint. See |
5724 |
-+ <citerefentry> |
5725 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
5726 |
-+ <manvolnum>7</manvolnum> |
5727 |
-+ </citerefentry>. |
5728 |
-+ </para></listitem> |
5729 |
-+ </varlistentry> |
5730 |
-+ </variablelist> |
5731 |
-+ |
5732 |
-+ <para> |
5733 |
-+ In all cases, the name and policy access information is stored in items |
5734 |
-+ of type <constant>KDBUS_ITEM_NAME</constant> and |
5735 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant>. For this transport, the |
5736 |
-+ following rules apply. |
5737 |
-+ </para> |
5738 |
-+ |
5739 |
-+ <itemizedlist> |
5740 |
-+ <listitem> |
5741 |
-+ <para> |
5742 |
-+ An item of type <constant>KDBUS_ITEM_NAME</constant> must be followed |
5743 |
-+ by at least one <constant>KDBUS_ITEM_POLICY_ACCESS</constant> item. |
5744 |
-+ </para> |
5745 |
-+ </listitem> |
5746 |
-+ |
5747 |
-+ <listitem> |
5748 |
-+ <para> |
5749 |
-+ An item of type <constant>KDBUS_ITEM_NAME</constant> can be followed |
5750 |
-+ by an arbitrary number of |
5751 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> items. |
5752 |
-+ </para> |
5753 |
-+ </listitem> |
5754 |
-+ |
5755 |
-+ <listitem> |
5756 |
-+ <para> |
5757 |
-+ An arbitrary number of groups of names and access levels can be given. |
5758 |
-+ </para> |
5759 |
-+ </listitem> |
5760 |
-+ </itemizedlist> |
5761 |
-+ |
5762 |
-+ <para> |
5763 |
-+ Names passed in items of type <constant>KDBUS_ITEM_NAME</constant> must |
5764 |
-+ comply to the rules of valid kdbus.name. See |
5765 |
-+ <citerefentry> |
5766 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
5767 |
-+ <manvolnum>7</manvolnum> |
5768 |
-+ </citerefentry> |
5769 |
-+ for more information. |
5770 |
-+ |
5771 |
-+ The payload of an item of type |
5772 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> is defined by the following |
5773 |
-+ struct. For more information on the layout of items, please refer to |
5774 |
-+ <citerefentry> |
5775 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5776 |
-+ <manvolnum>7</manvolnum> |
5777 |
-+ </citerefentry>. |
5778 |
-+ </para> |
5779 |
-+ |
5780 |
-+ <programlisting> |
5781 |
-+struct kdbus_policy_access { |
5782 |
-+ __u64 type; |
5783 |
-+ __u64 access; |
5784 |
-+ __u64 id; |
5785 |
-+}; |
5786 |
-+ </programlisting> |
5787 |
-+ |
5788 |
-+ <para>The fields in this struct are described below.</para> |
5789 |
-+ |
5790 |
-+ <variablelist> |
5791 |
-+ <varlistentry> |
5792 |
-+ <term><varname>type</varname></term> |
5793 |
-+ <listitem> |
5794 |
-+ <para> |
5795 |
-+ One of the following. |
5796 |
-+ </para> |
5797 |
-+ |
5798 |
-+ <variablelist> |
5799 |
-+ <varlistentry> |
5800 |
-+ <term><constant>KDBUS_POLICY_ACCESS_USER</constant></term> |
5801 |
-+ <listitem><para> |
5802 |
-+ Grant access to a user with the UID stored in the |
5803 |
-+ <varname>id</varname> field. |
5804 |
-+ </para></listitem> |
5805 |
-+ </varlistentry> |
5806 |
-+ |
5807 |
-+ <varlistentry> |
5808 |
-+ <term><constant>KDBUS_POLICY_ACCESS_GROUP</constant></term> |
5809 |
-+ <listitem><para> |
5810 |
-+ Grant access to a user with the GID stored in the |
5811 |
-+ <varname>id</varname> field. |
5812 |
-+ </para></listitem> |
5813 |
-+ </varlistentry> |
5814 |
-+ |
5815 |
-+ <varlistentry> |
5816 |
-+ <term><constant>KDBUS_POLICY_ACCESS_WORLD</constant></term> |
5817 |
-+ <listitem><para> |
5818 |
-+ Grant access to everyone. The <varname>id</varname> field |
5819 |
-+ is ignored. |
5820 |
-+ </para></listitem> |
5821 |
-+ </varlistentry> |
5822 |
-+ </variablelist> |
5823 |
-+ </listitem> |
5824 |
-+ </varlistentry> |
5825 |
-+ |
5826 |
-+ <varlistentry> |
5827 |
-+ <term><varname>access</varname></term> |
5828 |
-+ <listitem> |
5829 |
-+ <para> |
5830 |
-+ The access to grant. One of the following. |
5831 |
-+ </para> |
5832 |
-+ |
5833 |
-+ <variablelist> |
5834 |
-+ <varlistentry> |
5835 |
-+ <term><constant>KDBUS_POLICY_SEE</constant></term> |
5836 |
-+ <listitem><para> |
5837 |
-+ Allow the name to be seen. |
5838 |
-+ </para></listitem> |
5839 |
-+ </varlistentry> |
5840 |
-+ |
5841 |
-+ <varlistentry> |
5842 |
-+ <term><constant>KDBUS_POLICY_TALK</constant></term> |
5843 |
-+ <listitem><para> |
5844 |
-+ Allow the name to be talked to. |
5845 |
-+ </para></listitem> |
5846 |
-+ </varlistentry> |
5847 |
-+ |
5848 |
-+ <varlistentry> |
5849 |
-+ <term><constant>KDBUS_POLICY_OWN</constant></term> |
5850 |
-+ <listitem><para> |
5851 |
-+ Allow the name to be owned. |
5852 |
-+ </para></listitem> |
5853 |
-+ </varlistentry> |
5854 |
-+ </variablelist> |
5855 |
-+ </listitem> |
5856 |
-+ </varlistentry> |
5857 |
-+ |
5858 |
-+ <varlistentry> |
5859 |
-+ <term><varname>id</varname></term> |
5860 |
-+ <listitem><para> |
5861 |
-+ For <constant>KDBUS_POLICY_ACCESS_USER</constant>, stores the UID. |
5862 |
-+ For <constant>KDBUS_POLICY_ACCESS_GROUP</constant>, stores the GID. |
5863 |
-+ </para></listitem> |
5864 |
-+ </varlistentry> |
5865 |
-+ |
5866 |
-+ </variablelist> |
5867 |
-+ |
5868 |
-+ <para> |
5869 |
-+ All endpoints of buses have an empty policy database by default. |
5870 |
-+ Therefore, unless policy rules are added, all operations will also be |
5871 |
-+ denied by default. Also see |
5872 |
-+ <citerefentry> |
5873 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
5874 |
-+ <manvolnum>7</manvolnum> |
5875 |
-+ </citerefentry>. |
5876 |
-+ </para> |
5877 |
-+ </refsect1> |
5878 |
-+ |
5879 |
-+ <refsect1> |
5880 |
-+ <title>Wildcard names</title> |
5881 |
-+ <para> |
5882 |
-+ Policy holder connections may upload names that contain the wildcard |
5883 |
-+ suffix (<literal>".*"</literal>). Such a policy entry is effective for |
5884 |
-+ every well-known name that extends the provided name by exactly one more |
5885 |
-+ level. |
5886 |
-+ |
5887 |
-+ For example, the name <literal>foo.bar.*</literal> matches both |
5888 |
-+ <literal>"foo.bar.baz"</literal> and |
5889 |
-+ <literal>"foo.bar.bazbaz"</literal> are, but not |
5890 |
-+ <literal>"foo.bar.baz.baz"</literal>. |
5891 |
-+ |
5892 |
-+ This allows connections to take control over multiple names that the |
5893 |
-+ policy holder doesn't need to know about when uploading the policy. |
5894 |
-+ |
5895 |
-+ Such wildcard entries are not allowed for custom endpoints. |
5896 |
-+ </para> |
5897 |
-+ </refsect1> |
5898 |
-+ |
5899 |
-+ <refsect1> |
5900 |
-+ <title>Privileged connections</title> |
5901 |
-+ <para> |
5902 |
-+ The policy database is overruled when action is taken by a privileged |
5903 |
-+ connection. Please refer to |
5904 |
-+ <citerefentry> |
5905 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5906 |
-+ <manvolnum>7</manvolnum> |
5907 |
-+ </citerefentry> |
5908 |
-+ for more information on what makes a connection privileged. |
5909 |
-+ </para> |
5910 |
-+ </refsect1> |
5911 |
-+ |
5912 |
-+ <refsect1> |
5913 |
-+ <title>Examples</title> |
5914 |
-+ <para> |
5915 |
-+ For instance, a set of policy rules may look like this: |
5916 |
-+ </para> |
5917 |
-+ |
5918 |
-+ <programlisting> |
5919 |
-+KDBUS_ITEM_NAME: str='org.foo.bar' |
5920 |
-+KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=1000 |
5921 |
-+KDBUS_ITEM_POLICY_ACCESS: type=USER, access=TALK, ID=1001 |
5922 |
-+KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=SEE |
5923 |
-+ |
5924 |
-+KDBUS_ITEM_NAME: str='org.blah.baz' |
5925 |
-+KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=0 |
5926 |
-+KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=TALK |
5927 |
-+ </programlisting> |
5928 |
-+ |
5929 |
-+ <para> |
5930 |
-+ That means that 'org.foo.bar' may only be owned by UID 1000, but every |
5931 |
-+ user on the bus is allowed to see the name. However, only UID 1001 may |
5932 |
-+ actually send a message to the connection and receive a reply from it. |
5933 |
-+ |
5934 |
-+ The second rule allows 'org.blah.baz' to be owned by UID 0 only, but |
5935 |
-+ every user may talk to it. |
5936 |
-+ </para> |
5937 |
-+ </refsect1> |
5938 |
-+ |
5939 |
-+ <refsect1> |
5940 |
-+ <title>TALK access and multiple well-known names per connection</title> |
5941 |
-+ <para> |
5942 |
-+ Note that TALK access is checked against all names of a connection. For |
5943 |
-+ example, if a connection owns both <constant>'org.foo.bar'</constant> and |
5944 |
-+ <constant>'org.blah.baz'</constant>, and the policy database allows |
5945 |
-+ <constant>'org.blah.baz'</constant> to be talked to by WORLD, then this |
5946 |
-+ permission is also granted to <constant>'org.foo.bar'</constant>. That |
5947 |
-+ might sound illogical, but after all, we allow messages to be directed to |
5948 |
-+ either the ID or a well-known name, and policy is applied to the |
5949 |
-+ connection, not the name. In other words, the effective TALK policy for a |
5950 |
-+ connection is the most permissive of all names the connection owns. |
5951 |
-+ |
5952 |
-+ For broadcast messages, the receiver needs TALK permissions to the sender |
5953 |
-+ to receive the broadcast. |
5954 |
-+ </para> |
5955 |
-+ <para> |
5956 |
-+ Both the endpoint and the bus policy databases are consulted to allow |
5957 |
-+ name registry listing, owning a well-known name and message delivery. |
5958 |
-+ If either one fails, the operation is failed with |
5959 |
-+ <varname>errno</varname> set to <constant>EPERM</constant>. |
5960 |
-+ |
5961 |
-+ For best practices, connections that own names with a restricted TALK |
5962 |
-+ access should not install matches. This avoids cases where the sent |
5963 |
-+ message may pass the bloom filter due to false-positives and may also |
5964 |
-+ satisfy the policy rules. |
5965 |
-+ |
5966 |
-+ Also see |
5967 |
-+ <citerefentry> |
5968 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
5969 |
-+ <manvolnum>7</manvolnum> |
5970 |
-+ </citerefentry>. |
5971 |
-+ </para> |
5972 |
-+ </refsect1> |
5973 |
-+ |
5974 |
-+ <refsect1> |
5975 |
-+ <title>Implicit policies</title> |
5976 |
-+ <para> |
5977 |
-+ Depending on the type of the endpoint, a set of implicit rules that |
5978 |
-+ override installed policies might be enforced. |
5979 |
-+ |
5980 |
-+ On default endpoints, the following set is enforced and checked before |
5981 |
-+ any user-supplied policy is checked. |
5982 |
-+ </para> |
5983 |
-+ |
5984 |
-+ <itemizedlist> |
5985 |
-+ <listitem> |
5986 |
-+ <para> |
5987 |
-+ Privileged connections always override any installed policy. Those |
5988 |
-+ connections could easily install their own policies, so there is no |
5989 |
-+ reason to enforce installed policies. |
5990 |
-+ </para> |
5991 |
-+ </listitem> |
5992 |
-+ <listitem> |
5993 |
-+ <para> |
5994 |
-+ Connections can always talk to connections of the same user. This |
5995 |
-+ includes broadcast messages. |
5996 |
-+ </para> |
5997 |
-+ </listitem> |
5998 |
-+ </itemizedlist> |
5999 |
-+ |
6000 |
-+ <para> |
6001 |
-+ Custom endpoints have stricter policies. The following rules apply: |
6002 |
-+ </para> |
6003 |
-+ |
6004 |
-+ <itemizedlist> |
6005 |
-+ <listitem> |
6006 |
-+ <para> |
6007 |
-+ Policy rules are always enforced, even if the connection is a |
6008 |
-+ privileged connection. |
6009 |
-+ </para> |
6010 |
-+ </listitem> |
6011 |
-+ <listitem> |
6012 |
-+ <para> |
6013 |
-+ Policy rules are always enforced for <constant>TALK</constant> access, |
6014 |
-+ even if both ends are running under the same user. This includes |
6015 |
-+ broadcast messages. |
6016 |
-+ </para> |
6017 |
-+ </listitem> |
6018 |
-+ <listitem> |
6019 |
-+ <para> |
6020 |
-+ To restrict the set of names that can be seen, endpoint policies can |
6021 |
-+ install <constant>SEE</constant> policies. |
6022 |
-+ </para> |
6023 |
-+ </listitem> |
6024 |
-+ </itemizedlist> |
6025 |
-+ </refsect1> |
6026 |
-+ |
6027 |
-+ <refsect1> |
6028 |
-+ <title>See Also</title> |
6029 |
-+ <simplelist type="inline"> |
6030 |
-+ <member> |
6031 |
-+ <citerefentry> |
6032 |
-+ <refentrytitle>kdbus</refentrytitle> |
6033 |
-+ <manvolnum>7</manvolnum> |
6034 |
-+ </citerefentry> |
6035 |
-+ </member> |
6036 |
-+ <member> |
6037 |
-+ <citerefentry> |
6038 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
6039 |
-+ <manvolnum>7</manvolnum> |
6040 |
-+ </citerefentry> |
6041 |
-+ </member> |
6042 |
-+ <member> |
6043 |
-+ <citerefentry> |
6044 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
6045 |
-+ <manvolnum>7</manvolnum> |
6046 |
-+ </citerefentry> |
6047 |
-+ </member> |
6048 |
-+ <member> |
6049 |
-+ <citerefentry> |
6050 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
6051 |
-+ <manvolnum>7</manvolnum> |
6052 |
-+ </citerefentry> |
6053 |
-+ </member> |
6054 |
-+ <member> |
6055 |
-+ <citerefentry> |
6056 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
6057 |
-+ <manvolnum>7</manvolnum> |
6058 |
-+ </citerefentry> |
6059 |
-+ </member> |
6060 |
-+ <member> |
6061 |
-+ <citerefentry> |
6062 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
6063 |
-+ <manvolnum>7</manvolnum> |
6064 |
-+ </citerefentry> |
6065 |
-+ </member> |
6066 |
-+ <member> |
6067 |
-+ <citerefentry> |
6068 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6069 |
-+ <manvolnum>7</manvolnum> |
6070 |
-+ </citerefentry> |
6071 |
-+ </member> |
6072 |
-+ <member> |
6073 |
-+ <citerefentry> |
6074 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
6075 |
-+ <manvolnum>7</manvolnum> |
6076 |
-+ </citerefentry> |
6077 |
-+ </member> |
6078 |
-+ </simplelist> |
6079 |
-+ </refsect1> |
6080 |
-+</refentry> |
6081 |
-diff --git a/Documentation/kdbus/kdbus.pool.xml b/Documentation/kdbus/kdbus.pool.xml |
6082 |
-new file mode 100644 |
6083 |
-index 0000000..a9e16f1 |
6084 |
---- /dev/null |
6085 |
-+++ b/Documentation/kdbus/kdbus.pool.xml |
6086 |
-@@ -0,0 +1,326 @@ |
6087 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
6088 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
6089 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
6090 |
-+ |
6091 |
-+<refentry id="kdbus.pool"> |
6092 |
-+ |
6093 |
-+ <refentryinfo> |
6094 |
-+ <title>kdbus.pool</title> |
6095 |
-+ <productname>kdbus.pool</productname> |
6096 |
-+ </refentryinfo> |
6097 |
-+ |
6098 |
-+ <refmeta> |
6099 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
6100 |
-+ <manvolnum>7</manvolnum> |
6101 |
-+ </refmeta> |
6102 |
-+ |
6103 |
-+ <refnamediv> |
6104 |
-+ <refname>kdbus.pool</refname> |
6105 |
-+ <refpurpose>kdbus pool</refpurpose> |
6106 |
-+ </refnamediv> |
6107 |
-+ |
6108 |
-+ <refsect1> |
6109 |
-+ <title>Description</title> |
6110 |
-+ <para> |
6111 |
-+ A pool for data received from the kernel is installed for every |
6112 |
-+ <emphasis>connection</emphasis> of the <emphasis>bus</emphasis>, and |
6113 |
-+ is sized according to the information stored in the |
6114 |
-+ <varname>pool_size</varname> member of <type>struct kdbus_cmd_hello</type> |
6115 |
-+ when <constant>KDBUS_CMD_HELLO</constant> is employed. Internally, the |
6116 |
-+ pool is segmented into <emphasis>slices</emphasis>, each referenced by its |
6117 |
-+ <emphasis>offset</emphasis> in the pool, expressed in <type>bytes</type>. |
6118 |
-+ See |
6119 |
-+ <citerefentry> |
6120 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6121 |
-+ <manvolnum>7</manvolnum> |
6122 |
-+ </citerefentry> |
6123 |
-+ for more information about <constant>KDBUS_CMD_HELLO</constant>. |
6124 |
-+ </para> |
6125 |
-+ |
6126 |
-+ <para> |
6127 |
-+ The pool is written to by the kernel when one of the following |
6128 |
-+ <emphasis>ioctls</emphasis> is issued: |
6129 |
-+ |
6130 |
-+ <variablelist> |
6131 |
-+ <varlistentry> |
6132 |
-+ <term><constant>KDBUS_CMD_HELLO</constant></term> |
6133 |
-+ <listitem><para> |
6134 |
-+ ... to receive details about the bus the connection was made to |
6135 |
-+ </para></listitem> |
6136 |
-+ </varlistentry> |
6137 |
-+ <varlistentry> |
6138 |
-+ <term><constant>KDBUS_CMD_RECV</constant></term> |
6139 |
-+ <listitem><para> |
6140 |
-+ ... to receive a message |
6141 |
-+ </para></listitem> |
6142 |
-+ </varlistentry> |
6143 |
-+ <varlistentry> |
6144 |
-+ <term><constant>KDBUS_CMD_LIST</constant></term> |
6145 |
-+ <listitem><para> |
6146 |
-+ ... to dump the name registry |
6147 |
-+ </para></listitem> |
6148 |
-+ </varlistentry> |
6149 |
-+ <varlistentry> |
6150 |
-+ <term><constant>KDBUS_CMD_CONN_INFO</constant></term> |
6151 |
-+ <listitem><para> |
6152 |
-+ ... to retrieve information on a connection |
6153 |
-+ </para></listitem> |
6154 |
-+ </varlistentry> |
6155 |
-+ <varlistentry> |
6156 |
-+ <term><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></term> |
6157 |
-+ <listitem><para> |
6158 |
-+ ... to retrieve information about a connection's bus creator |
6159 |
-+ </para></listitem> |
6160 |
-+ </varlistentry> |
6161 |
-+ </variablelist> |
6162 |
-+ |
6163 |
-+ </para> |
6164 |
-+ <para> |
6165 |
-+ The <varname>offset</varname> fields returned by either one of the |
6166 |
-+ aforementioned ioctls describe offsets inside the pool. In order to make |
6167 |
-+ the slice available for subsequent calls, |
6168 |
-+ <constant>KDBUS_CMD_FREE</constant> has to be called on that offset |
6169 |
-+ (see below). Otherwise, the pool will fill up, and the connection won't |
6170 |
-+ be able to receive any more information through its pool. |
6171 |
-+ </para> |
6172 |
-+ </refsect1> |
6173 |
-+ |
6174 |
-+ <refsect1> |
6175 |
-+ <title>Pool slice allocation</title> |
6176 |
-+ <para> |
6177 |
-+ Pool slices are allocated by the kernel in order to report information |
6178 |
-+ back to a task, such as messages, returned name list etc. |
6179 |
-+ Allocation of pool slices cannot be initiated by userspace. See |
6180 |
-+ <citerefentry> |
6181 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6182 |
-+ <manvolnum>7</manvolnum> |
6183 |
-+ </citerefentry> |
6184 |
-+ and |
6185 |
-+ <citerefentry> |
6186 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6187 |
-+ <manvolnum>7</manvolnum> |
6188 |
-+ </citerefentry> |
6189 |
-+ for examples of commands that use the <emphasis>pool</emphasis> to |
6190 |
-+ return data. |
6191 |
-+ </para> |
6192 |
-+ </refsect1> |
6193 |
-+ |
6194 |
-+ <refsect1> |
6195 |
-+ <title>Accessing the pool memory</title> |
6196 |
-+ <para> |
6197 |
-+ Memory in the pool is read-only for userspace and may only be written |
6198 |
-+ to by the kernel. To read from the pool memory, the caller is expected to |
6199 |
-+ <citerefentry> |
6200 |
-+ <refentrytitle>mmap</refentrytitle> |
6201 |
-+ <manvolnum>2</manvolnum> |
6202 |
-+ </citerefentry> |
6203 |
-+ the buffer into its task, like this: |
6204 |
-+ </para> |
6205 |
-+ <programlisting> |
6206 |
-+uint8_t *buf = mmap(NULL, size, PROT_READ, MAP_SHARED, conn_fd, 0); |
6207 |
-+ </programlisting> |
6208 |
-+ |
6209 |
-+ <para> |
6210 |
-+ In order to map the entire pool, the <varname>size</varname> parameter in |
6211 |
-+ the example above should be set to the value of the |
6212 |
-+ <varname>pool_size</varname> member of |
6213 |
-+ <type>struct kdbus_cmd_hello</type> when |
6214 |
-+ <constant>KDBUS_CMD_HELLO</constant> was employed to create the |
6215 |
-+ connection (see above). |
6216 |
-+ </para> |
6217 |
-+ |
6218 |
-+ <para> |
6219 |
-+ The <emphasis>file descriptor</emphasis> used to map the memory must be |
6220 |
-+ the one that was used to create the <emphasis>connection</emphasis>. |
6221 |
-+ In other words, the one that was used to call |
6222 |
-+ <constant>KDBUS_CMD_HELLO</constant>. See |
6223 |
-+ <citerefentry> |
6224 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6225 |
-+ <manvolnum>7</manvolnum> |
6226 |
-+ </citerefentry> |
6227 |
-+ for more details. |
6228 |
-+ </para> |
6229 |
-+ |
6230 |
-+ <para> |
6231 |
-+ Alternatively, instead of mapping the entire pool buffer, only parts |
6232 |
-+ of it can be mapped. Every kdbus command that returns an |
6233 |
-+ <emphasis>offset</emphasis> (see above) also reports a |
6234 |
-+ <emphasis>size</emphasis> along with it, so programs can be written |
6235 |
-+ in a way that it only maps portions of the pool to access a specific |
6236 |
-+ <emphasis>slice</emphasis>. |
6237 |
-+ </para> |
6238 |
-+ |
6239 |
-+ <para> |
6240 |
-+ When access to the pool memory is no longer needed, programs should |
6241 |
-+ call <function>munmap()</function> on the pointer returned by |
6242 |
-+ <function>mmap()</function>. |
6243 |
-+ </para> |
6244 |
-+ </refsect1> |
6245 |
-+ |
6246 |
-+ <refsect1> |
6247 |
-+ <title>Freeing pool slices</title> |
6248 |
-+ <para> |
6249 |
-+ The <constant>KDBUS_CMD_FREE</constant> ioctl is used to free a slice |
6250 |
-+ inside the pool, describing an offset that was returned in an |
6251 |
-+ <varname>offset</varname> field of another ioctl struct. |
6252 |
-+ The <constant>KDBUS_CMD_FREE</constant> command takes a |
6253 |
-+ <type>struct kdbus_cmd_free</type> as argument. |
6254 |
-+ </para> |
6255 |
-+ |
6256 |
-+<programlisting> |
6257 |
-+struct kdbus_cmd_free { |
6258 |
-+ __u64 size; |
6259 |
-+ __u64 flags; |
6260 |
-+ __u64 return_flags; |
6261 |
-+ __u64 offset; |
6262 |
-+ struct kdbus_item items[0]; |
6263 |
-+}; |
6264 |
-+</programlisting> |
6265 |
-+ |
6266 |
-+ <para>The fields in this struct are described below.</para> |
6267 |
-+ |
6268 |
-+ <variablelist> |
6269 |
-+ <varlistentry> |
6270 |
-+ <term><varname>size</varname></term> |
6271 |
-+ <listitem><para> |
6272 |
-+ The overall size of the struct, including its items. |
6273 |
-+ </para></listitem> |
6274 |
-+ </varlistentry> |
6275 |
-+ |
6276 |
-+ <varlistentry> |
6277 |
-+ <term><varname>flags</varname></term> |
6278 |
-+ <listitem><para> |
6279 |
-+ Currently unused. |
6280 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
6281 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
6282 |
-+ and the <varname>flags</varname> field is set to |
6283 |
-+ <constant>0</constant>. |
6284 |
-+ </para></listitem> |
6285 |
-+ </varlistentry> |
6286 |
-+ |
6287 |
-+ <varlistentry> |
6288 |
-+ <term><varname>return_flags</varname></term> |
6289 |
-+ <listitem><para> |
6290 |
-+ Flags returned by the kernel. Currently unused and always set to |
6291 |
-+ <constant>0</constant> by the kernel. |
6292 |
-+ </para></listitem> |
6293 |
-+ </varlistentry> |
6294 |
-+ |
6295 |
-+ <varlistentry> |
6296 |
-+ <term><varname>offset</varname></term> |
6297 |
-+ <listitem><para> |
6298 |
-+ The offset to free, as returned by other ioctls that allocated |
6299 |
-+ memory for returned information. |
6300 |
-+ </para></listitem> |
6301 |
-+ </varlistentry> |
6302 |
-+ |
6303 |
-+ <varlistentry> |
6304 |
-+ <term><varname>items</varname></term> |
6305 |
-+ <listitem><para> |
6306 |
-+ Items to specify further details for the receive command. |
6307 |
-+ Currently unused. |
6308 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
6309 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
6310 |
-+ All items except for |
6311 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> (see |
6312 |
-+ <citerefentry> |
6313 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
6314 |
-+ <manvolnum>7</manvolnum> |
6315 |
-+ </citerefentry> |
6316 |
-+ ) will be rejected. |
6317 |
-+ </para></listitem> |
6318 |
-+ </varlistentry> |
6319 |
-+ </variablelist> |
6320 |
-+ </refsect1> |
6321 |
-+ |
6322 |
-+ <refsect1> |
6323 |
-+ <title>Return value</title> |
6324 |
-+ <para> |
6325 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
6326 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
6327 |
-+ <varname>errno</varname> is set to indicate the error. |
6328 |
-+ If the issued ioctl is illegal for the file descriptor used, |
6329 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
6330 |
-+ </para> |
6331 |
-+ |
6332 |
-+ <refsect2> |
6333 |
-+ <title> |
6334 |
-+ <constant>KDBUS_CMD_FREE</constant> may fail with the following |
6335 |
-+ errors |
6336 |
-+ </title> |
6337 |
-+ |
6338 |
-+ <variablelist> |
6339 |
-+ <varlistentry> |
6340 |
-+ <term><constant>ENXIO</constant></term> |
6341 |
-+ <listitem><para> |
6342 |
-+ No pool slice found at given offset. |
6343 |
-+ </para></listitem> |
6344 |
-+ </varlistentry> |
6345 |
-+ |
6346 |
-+ <varlistentry> |
6347 |
-+ <term><constant>EINVAL</constant></term> |
6348 |
-+ <listitem><para> |
6349 |
-+ Invalid flags provided. |
6350 |
-+ </para></listitem> |
6351 |
-+ </varlistentry> |
6352 |
-+ |
6353 |
-+ <varlistentry> |
6354 |
-+ <term><constant>EINVAL</constant></term> |
6355 |
-+ <listitem><para> |
6356 |
-+ The offset is valid, but the user is not allowed to free the slice. |
6357 |
-+ This happens, for example, if the offset was retrieved with |
6358 |
-+ <constant>KDBUS_RECV_PEEK</constant>. |
6359 |
-+ </para></listitem> |
6360 |
-+ </varlistentry> |
6361 |
-+ </variablelist> |
6362 |
-+ </refsect2> |
6363 |
-+ </refsect1> |
6364 |
-+ |
6365 |
-+ <refsect1> |
6366 |
-+ <title>See Also</title> |
6367 |
-+ <simplelist type="inline"> |
6368 |
-+ <member> |
6369 |
-+ <citerefentry> |
6370 |
-+ <refentrytitle>kdbus</refentrytitle> |
6371 |
-+ <manvolnum>7</manvolnum> |
6372 |
-+ </citerefentry> |
6373 |
-+ </member> |
6374 |
-+ <member> |
6375 |
-+ <citerefentry> |
6376 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
6377 |
-+ <manvolnum>7</manvolnum> |
6378 |
-+ </citerefentry> |
6379 |
-+ </member> |
6380 |
-+ <member> |
6381 |
-+ <citerefentry> |
6382 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6383 |
-+ <manvolnum>7</manvolnum> |
6384 |
-+ </citerefentry> |
6385 |
-+ </member> |
6386 |
-+ <member> |
6387 |
-+ <citerefentry> |
6388 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
6389 |
-+ <manvolnum>7</manvolnum> |
6390 |
-+ </citerefentry> |
6391 |
-+ </member> |
6392 |
-+ <member> |
6393 |
-+ <citerefentry> |
6394 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6395 |
-+ <manvolnum>7</manvolnum> |
6396 |
-+ </citerefentry> |
6397 |
-+ </member> |
6398 |
-+ <member> |
6399 |
-+ <citerefentry> |
6400 |
-+ <refentrytitle>mmap</refentrytitle> |
6401 |
-+ <manvolnum>2</manvolnum> |
6402 |
-+ </citerefentry> |
6403 |
-+ </member> |
6404 |
-+ <member> |
6405 |
-+ <citerefentry> |
6406 |
-+ <refentrytitle>munmap</refentrytitle> |
6407 |
-+ <manvolnum>2</manvolnum> |
6408 |
-+ </citerefentry> |
6409 |
-+ </member> |
6410 |
-+ </simplelist> |
6411 |
-+ </refsect1> |
6412 |
-+</refentry> |
6413 |
-diff --git a/Documentation/kdbus/kdbus.xml b/Documentation/kdbus/kdbus.xml |
6414 |
-new file mode 100644 |
6415 |
-index 0000000..d8e7400 |
6416 |
---- /dev/null |
6417 |
-+++ b/Documentation/kdbus/kdbus.xml |
6418 |
-@@ -0,0 +1,1012 @@ |
6419 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
6420 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
6421 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
6422 |
-+ |
6423 |
-+<refentry id="kdbus"> |
6424 |
-+ |
6425 |
-+ <refentryinfo> |
6426 |
-+ <title>kdbus</title> |
6427 |
-+ <productname>kdbus</productname> |
6428 |
-+ </refentryinfo> |
6429 |
-+ |
6430 |
-+ <refmeta> |
6431 |
-+ <refentrytitle>kdbus</refentrytitle> |
6432 |
-+ <manvolnum>7</manvolnum> |
6433 |
-+ </refmeta> |
6434 |
-+ |
6435 |
-+ <refnamediv> |
6436 |
-+ <refname>kdbus</refname> |
6437 |
-+ <refpurpose>Kernel Message Bus</refpurpose> |
6438 |
-+ </refnamediv> |
6439 |
-+ |
6440 |
-+ <refsect1> |
6441 |
-+ <title>Synopsis</title> |
6442 |
-+ <para> |
6443 |
-+ kdbus is an inter-process communication bus system controlled by the |
6444 |
-+ kernel. It provides user-space with an API to create buses and send |
6445 |
-+ unicast and multicast messages to one, or many, peers connected to the |
6446 |
-+ same bus. It does not enforce any layout on the transmitted data, but |
6447 |
-+ only provides the transport layer used for message interchange between |
6448 |
-+ peers. |
6449 |
-+ </para> |
6450 |
-+ <para> |
6451 |
-+ This set of man-pages gives a comprehensive overview of the kernel-level |
6452 |
-+ API, with all ioctl commands, associated structs and bit masks. However, |
6453 |
-+ most people will not use this API level directly, but rather let one of |
6454 |
-+ the high-level abstraction libraries help them integrate D-Bus |
6455 |
-+ functionality into their applications. |
6456 |
-+ </para> |
6457 |
-+ </refsect1> |
6458 |
-+ |
6459 |
-+ <refsect1> |
6460 |
-+ <title>Description</title> |
6461 |
-+ <para> |
6462 |
-+ kdbus provides a pseudo filesystem called <emphasis>kdbusfs</emphasis>, |
6463 |
-+ which is usually mounted on <filename>/sys/fs/kdbus</filename>. Bus |
6464 |
-+ primitives can be accessed as files and sub-directories underneath this |
6465 |
-+ mount-point. Any advanced operations are done via |
6466 |
-+ <function>ioctl()</function> on files created by |
6467 |
-+ <emphasis>kdbusfs</emphasis>. Multiple mount-points of |
6468 |
-+ <emphasis>kdbusfs</emphasis> are independent of each other. This allows |
6469 |
-+ namespacing of kdbus by mounting a new instance of |
6470 |
-+ <emphasis>kdbusfs</emphasis> in a new mount-namespace. kdbus calls these |
6471 |
-+ mount instances domains and each bus belongs to exactly one domain. |
6472 |
-+ </para> |
6473 |
-+ |
6474 |
-+ <para> |
6475 |
-+ kdbus was designed as a transport layer for D-Bus, but is in no way |
6476 |
-+ limited, nor controlled by the D-Bus protocol specification. The D-Bus |
6477 |
-+ protocol is one possible application layer on top of kdbus. |
6478 |
-+ </para> |
6479 |
-+ |
6480 |
-+ <para> |
6481 |
-+ For the general D-Bus protocol specification, its payload format, its |
6482 |
-+ marshaling, and its communication semantics, please refer to the |
6483 |
-+ <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html"> |
6484 |
-+ D-Bus specification</ulink>. |
6485 |
-+ </para> |
6486 |
-+ |
6487 |
-+ </refsect1> |
6488 |
-+ |
6489 |
-+ <refsect1> |
6490 |
-+ <title>Terminology</title> |
6491 |
-+ |
6492 |
-+ <refsect2> |
6493 |
-+ <title>Domain</title> |
6494 |
-+ <para> |
6495 |
-+ A domain is a <emphasis>kdbusfs</emphasis> mount-point containing all |
6496 |
-+ the bus primitives. Each domain is independent, and separate domains |
6497 |
-+ do not affect each other. |
6498 |
-+ </para> |
6499 |
-+ </refsect2> |
6500 |
-+ |
6501 |
-+ <refsect2> |
6502 |
-+ <title>Bus</title> |
6503 |
-+ <para> |
6504 |
-+ A bus is a named object inside a domain. Clients exchange messages |
6505 |
-+ over a bus. Multiple buses themselves have no connection to each other; |
6506 |
-+ messages can only be exchanged on the same bus. The default endpoint of |
6507 |
-+ a bus, to which clients establish connections, is the "bus" file |
6508 |
-+ /sys/fs/kdbus/<bus name>/bus. |
6509 |
-+ Common operating system setups create one "system bus" per system, |
6510 |
-+ and one "user bus" for every logged-in user. Applications or services |
6511 |
-+ may create their own private buses. The kernel driver does not |
6512 |
-+ distinguish between different bus types, they are all handled the same |
6513 |
-+ way. See |
6514 |
-+ <citerefentry> |
6515 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
6516 |
-+ <manvolnum>7</manvolnum> |
6517 |
-+ </citerefentry> |
6518 |
-+ for more details. |
6519 |
-+ </para> |
6520 |
-+ </refsect2> |
6521 |
-+ |
6522 |
-+ <refsect2> |
6523 |
-+ <title>Endpoint</title> |
6524 |
-+ <para> |
6525 |
-+ An endpoint provides a file to talk to a bus. Opening an endpoint |
6526 |
-+ creates a new connection to the bus to which the endpoint belongs. All |
6527 |
-+ endpoints have unique names and are accessible as files underneath the |
6528 |
-+ directory of a bus, e.g., /sys/fs/kdbus/<bus>/<endpoint> |
6529 |
-+ Every bus has a default endpoint called "bus". |
6530 |
-+ A bus can optionally offer additional endpoints with custom names |
6531 |
-+ to provide restricted access to the bus. Custom endpoints carry |
6532 |
-+ additional policy which can be used to create sandboxes with |
6533 |
-+ locked-down, limited, filtered access to a bus. See |
6534 |
-+ <citerefentry> |
6535 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
6536 |
-+ <manvolnum>7</manvolnum> |
6537 |
-+ </citerefentry> |
6538 |
-+ for more details. |
6539 |
-+ </para> |
6540 |
-+ </refsect2> |
6541 |
-+ |
6542 |
-+ <refsect2> |
6543 |
-+ <title>Connection</title> |
6544 |
-+ <para> |
6545 |
-+ A connection to a bus is created by opening an endpoint file of a |
6546 |
-+ bus. Every ordinary client connection has a unique identifier on the |
6547 |
-+ bus and can address messages to every other connection on the same |
6548 |
-+ bus by using the peer's connection ID as the destination. See |
6549 |
-+ <citerefentry> |
6550 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6551 |
-+ <manvolnum>7</manvolnum> |
6552 |
-+ </citerefentry> |
6553 |
-+ for more details. |
6554 |
-+ </para> |
6555 |
-+ </refsect2> |
6556 |
-+ |
6557 |
-+ <refsect2> |
6558 |
-+ <title>Pool</title> |
6559 |
-+ <para> |
6560 |
-+ Each connection allocates a piece of shmem-backed memory that is |
6561 |
-+ used to receive messages and answers to ioctl commands from the kernel. |
6562 |
-+ It is never used to send anything to the kernel. In order to access that |
6563 |
-+ memory, an application must mmap() it into its address space. See |
6564 |
-+ <citerefentry> |
6565 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
6566 |
-+ <manvolnum>7</manvolnum> |
6567 |
-+ </citerefentry> |
6568 |
-+ for more details. |
6569 |
-+ </para> |
6570 |
-+ </refsect2> |
6571 |
-+ |
6572 |
-+ <refsect2> |
6573 |
-+ <title>Well-known Name</title> |
6574 |
-+ <para> |
6575 |
-+ A connection can, in addition to its implicit unique connection ID, |
6576 |
-+ request the ownership of a textual well-known name. Well-known names are |
6577 |
-+ noted in reverse-domain notation, such as com.example.service1. A |
6578 |
-+ connection that offers a service on a bus is usually reached by its |
6579 |
-+ well-known name. An analogy of connection ID and well-known name is an |
6580 |
-+ IP address and a DNS name associated with that address. See |
6581 |
-+ <citerefentry> |
6582 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6583 |
-+ <manvolnum>7</manvolnum> |
6584 |
-+ </citerefentry> |
6585 |
-+ for more details. |
6586 |
-+ </para> |
6587 |
-+ </refsect2> |
6588 |
-+ |
6589 |
-+ <refsect2> |
6590 |
-+ <title>Message</title> |
6591 |
-+ <para> |
6592 |
-+ Connections can exchange messages with other connections by addressing |
6593 |
-+ the peers with their connection ID or well-known name. A message |
6594 |
-+ consists of a message header with information on how to route the |
6595 |
-+ message, and the message payload, which is a logical byte stream of |
6596 |
-+ arbitrary size. Messages can carry additional file descriptors to be |
6597 |
-+ passed from one connection to another, just like passing file |
6598 |
-+ descriptors over UNIX domain sockets. Every connection can specify which |
6599 |
-+ set of metadata the kernel should attach to the message when it is |
6600 |
-+ delivered to the receiving connection. Metadata contains information |
6601 |
-+ like: system time stamps, UID, GID, TID, proc-starttime, well-known |
6602 |
-+ names, process comm, process exe, process argv, cgroup, capabilities, |
6603 |
-+ seclabel, audit session, loginuid and the connection's human-readable |
6604 |
-+ name. See |
6605 |
-+ <citerefentry> |
6606 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
6607 |
-+ <manvolnum>7</manvolnum> |
6608 |
-+ </citerefentry> |
6609 |
-+ for more details. |
6610 |
-+ </para> |
6611 |
-+ </refsect2> |
6612 |
-+ |
6613 |
-+ <refsect2> |
6614 |
-+ <title>Item</title> |
6615 |
-+ <para> |
6616 |
-+ The API of kdbus implements the notion of items, submitted through and |
6617 |
-+ returned by most ioctls, and stored inside data structures in the |
6618 |
-+ connection's pool. See |
6619 |
-+ <citerefentry> |
6620 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
6621 |
-+ <manvolnum>7</manvolnum> |
6622 |
-+ </citerefentry> |
6623 |
-+ for more details. |
6624 |
-+ </para> |
6625 |
-+ </refsect2> |
6626 |
-+ |
6627 |
-+ <refsect2> |
6628 |
-+ <title>Broadcast, signal, filter, match</title> |
6629 |
-+ <para> |
6630 |
-+ Signals are messages that a receiver opts in for by installing a blob of |
6631 |
-+ bytes, called a 'match'. Signal messages must always carry a |
6632 |
-+ counter-part blob, called a 'filter', and signals are only delivered to |
6633 |
-+ peers which have a match that white-lists the message's filter. Senders |
6634 |
-+ of signal messages can use either a single connection ID as receiver, |
6635 |
-+ or the special connection ID |
6636 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> to potentially send it to |
6637 |
-+ all connections of a bus, following the logic described above. See |
6638 |
-+ <citerefentry> |
6639 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
6640 |
-+ <manvolnum>7</manvolnum> |
6641 |
-+ </citerefentry> |
6642 |
-+ and |
6643 |
-+ <citerefentry> |
6644 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
6645 |
-+ <manvolnum>7</manvolnum> |
6646 |
-+ </citerefentry> |
6647 |
-+ for more details. |
6648 |
-+ </para> |
6649 |
-+ </refsect2> |
6650 |
-+ |
6651 |
-+ <refsect2> |
6652 |
-+ <title>Policy</title> |
6653 |
-+ <para> |
6654 |
-+ A policy is a set of rules that define which connections can see, talk |
6655 |
-+ to, or register a well-known name on the bus. A policy is attached to |
6656 |
-+ buses and custom endpoints, and modified by policy holder connections or |
6657 |
-+ owners of custom endpoints. See |
6658 |
-+ <citerefentry> |
6659 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
6660 |
-+ <manvolnum>7</manvolnum> |
6661 |
-+ </citerefentry> |
6662 |
-+ for more details. |
6663 |
-+ </para> |
6664 |
-+ </refsect2> |
6665 |
-+ |
6666 |
-+ <refsect2> |
6667 |
-+ <title>Privileged bus users</title> |
6668 |
-+ <para> |
6669 |
-+ A user connecting to the bus is considered privileged if it is either |
6670 |
-+ the creator of the bus, or if it has the CAP_IPC_OWNER capability flag |
6671 |
-+ set. See |
6672 |
-+ <citerefentry> |
6673 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6674 |
-+ <manvolnum>7</manvolnum> |
6675 |
-+ </citerefentry> |
6676 |
-+ for more details. |
6677 |
-+ </para> |
6678 |
-+ </refsect2> |
6679 |
-+ </refsect1> |
6680 |
-+ |
6681 |
-+ <refsect1> |
6682 |
-+ <title>Bus Layout</title> |
6683 |
-+ |
6684 |
-+ <para> |
6685 |
-+ A <emphasis>bus</emphasis> provides and defines an environment that peers |
6686 |
-+ can connect to for message interchange. A bus is created via the kdbus |
6687 |
-+ control interface and can be modified by the bus creator. It applies the |
6688 |
-+ policy that control all bus operations. The bus creator itself does not |
6689 |
-+ participate as a peer. To establish a peer |
6690 |
-+ <emphasis>connection</emphasis>, you have to open one of the |
6691 |
-+ <emphasis>endpoints</emphasis> of a bus. Each bus provides a default |
6692 |
-+ endpoint, but further endpoints can be created on-demand. Endpoints are |
6693 |
-+ used to apply additional policies for all connections on this endpoint. |
6694 |
-+ Thus, they provide additional filters to further restrict access of |
6695 |
-+ specific connections to the bus. |
6696 |
-+ </para> |
6697 |
-+ |
6698 |
-+ <para> |
6699 |
-+ Following, you can see an example bus layout: |
6700 |
-+ </para> |
6701 |
-+ |
6702 |
-+ <programlisting><![CDATA[ |
6703 |
-+ Bus Creator |
6704 |
-+ | |
6705 |
-+ | |
6706 |
-+ +-----+ |
6707 |
-+ | Bus | |
6708 |
-+ +-----+ |
6709 |
-+ | |
6710 |
-+ __________________/ \__________________ |
6711 |
-+ / \ |
6712 |
-+ | | |
6713 |
-+ +----------+ +----------+ |
6714 |
-+ | Endpoint | | Endpoint | |
6715 |
-+ +----------+ +----------+ |
6716 |
-+ _________/|\_________ _________/|\_________ |
6717 |
-+ / | \ / | \ |
6718 |
-+ | | | | | | |
6719 |
-+ | | | | | | |
6720 |
-+ Connection Connection Connection Connection Connection Connection |
6721 |
-+ ]]></programlisting> |
6722 |
-+ |
6723 |
-+ </refsect1> |
6724 |
-+ |
6725 |
-+ <refsect1> |
6726 |
-+ <title>Data structures and interconnections</title> |
6727 |
-+ <programlisting><![CDATA[ |
6728 |
-+ +--------------------------------------------------------------------------+ |
6729 |
-+ | Domain (Mount Point) | |
6730 |
-+ | /sys/fs/kdbus/control | |
6731 |
-+ | +----------------------------------------------------------------------+ | |
6732 |
-+ | | Bus (System Bus) | | |
6733 |
-+ | | /sys/fs/kdbus/0-system/ | | |
6734 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6735 |
-+ | | | Endpoint | | Endpoint | | | |
6736 |
-+ | | | /sys/fs/kdbus/0-system/bus | | /sys/fs/kdbus/0-system/ep.app | | | |
6737 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6738 |
-+ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6739 |
-+ | | | Connection | | Connection | | Connection | | Connection | | | |
6740 |
-+ | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | | |
6741 |
-+ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6742 |
-+ | +----------------------------------------------------------------------+ | |
6743 |
-+ | | |
6744 |
-+ | +----------------------------------------------------------------------+ | |
6745 |
-+ | | Bus (User Bus for UID 2702) | | |
6746 |
-+ | | /sys/fs/kdbus/2702-user/ | | |
6747 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6748 |
-+ | | | Endpoint | | Endpoint | | | |
6749 |
-+ | | | /sys/fs/kdbus/2702-user/bus | | /sys/fs/kdbus/2702-user/ep.app | | | |
6750 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6751 |
-+ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6752 |
-+ | | | Connection | | Connection | | Connection | | Connection | | | |
6753 |
-+ | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | | |
6754 |
-+ | | +--------------+ +--------------+ +--------------------------------+ | | |
6755 |
-+ | +----------------------------------------------------------------------+ | |
6756 |
-+ +--------------------------------------------------------------------------+ |
6757 |
-+ ]]></programlisting> |
6758 |
-+ </refsect1> |
6759 |
-+ |
6760 |
-+ <refsect1> |
6761 |
-+ <title>Metadata</title> |
6762 |
-+ |
6763 |
-+ <refsect2> |
6764 |
-+ <title>When metadata is collected</title> |
6765 |
-+ <para> |
6766 |
-+ kdbus records data about the system in certain situations. Such metadata |
6767 |
-+ can refer to the currently active process (creds, PIDs, current user |
6768 |
-+ groups, process names and its executable path, cgroup membership, |
6769 |
-+ capabilities, security label and audit information), connection |
6770 |
-+ information (description string, currently owned names) and time stamps. |
6771 |
-+ </para> |
6772 |
-+ <para> |
6773 |
-+ Metadata is collected at the following times. |
6774 |
-+ </para> |
6775 |
-+ |
6776 |
-+ <itemizedlist> |
6777 |
-+ <listitem><para> |
6778 |
-+ When a bus is created (<constant>KDBUS_CMD_MAKE</constant>), |
6779 |
-+ information about the calling task is collected. This data is returned |
6780 |
-+ by the kernel via the <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> |
6781 |
-+ call. |
6782 |
-+ </para></listitem> |
6783 |
-+ |
6784 |
-+ <listitem> |
6785 |
-+ <para> |
6786 |
-+ When a connection is created (<constant>KDBUS_CMD_HELLO</constant>), |
6787 |
-+ information about the calling task is collected. Alternatively, a |
6788 |
-+ privileged connection may provide 'faked' information about |
6789 |
-+ credentials, PIDs and security labels which will be stored instead. |
6790 |
-+ This data is returned by the kernel as information on a connection |
6791 |
-+ (<constant>KDBUS_CMD_CONN_INFO</constant>). Only metadata that a |
6792 |
-+ connection allowed to be sent (by setting its bit in |
6793 |
-+ <varname>attach_flags_send</varname>) will be exported in this way. |
6794 |
-+ </para> |
6795 |
-+ </listitem> |
6796 |
-+ |
6797 |
-+ <listitem> |
6798 |
-+ <para> |
6799 |
-+ When a message is sent (<constant>KDBUS_CMD_SEND</constant>), |
6800 |
-+ information about the sending task and the sending connection is |
6801 |
-+ collected. This metadata will be attached to the message when it |
6802 |
-+ arrives in the receiver's pool. If the connection sending the |
6803 |
-+ message installed faked credentials (see |
6804 |
-+ <citerefentry> |
6805 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6806 |
-+ <manvolnum>7</manvolnum> |
6807 |
-+ </citerefentry>), |
6808 |
-+ the message will not be augmented by any information about the |
6809 |
-+ currently sending task. Note that only metadata that was requested |
6810 |
-+ by the receiving connection will be collected and attached to |
6811 |
-+ messages. |
6812 |
-+ </para> |
6813 |
-+ </listitem> |
6814 |
-+ </itemizedlist> |
6815 |
-+ |
6816 |
-+ <para> |
6817 |
-+ Which metadata items are actually delivered depends on the following |
6818 |
-+ sets and masks: |
6819 |
-+ </para> |
6820 |
-+ |
6821 |
-+ <itemizedlist> |
6822 |
-+ <listitem><para> |
6823 |
-+ (a) the system-wide kmod creds mask |
6824 |
-+ (module parameter <varname>attach_flags_mask</varname>) |
6825 |
-+ </para></listitem> |
6826 |
-+ |
6827 |
-+ <listitem><para> |
6828 |
-+ (b) the per-connection send creds mask, set by the connecting client |
6829 |
-+ </para></listitem> |
6830 |
-+ |
6831 |
-+ <listitem><para> |
6832 |
-+ (c) the per-connection receive creds mask, set by the connecting |
6833 |
-+ client |
6834 |
-+ </para></listitem> |
6835 |
-+ |
6836 |
-+ <listitem><para> |
6837 |
-+ (d) the per-bus minimal creds mask, set by the bus creator |
6838 |
-+ </para></listitem> |
6839 |
-+ |
6840 |
-+ <listitem><para> |
6841 |
-+ (e) the per-bus owner creds mask, set by the bus creator |
6842 |
-+ </para></listitem> |
6843 |
-+ |
6844 |
-+ <listitem><para> |
6845 |
-+ (f) the mask specified when querying creds of a bus peer |
6846 |
-+ </para></listitem> |
6847 |
-+ |
6848 |
-+ <listitem><para> |
6849 |
-+ (g) the mask specified when querying creds of a bus owner |
6850 |
-+ </para></listitem> |
6851 |
-+ </itemizedlist> |
6852 |
-+ |
6853 |
-+ <para> |
6854 |
-+ With the following rules: |
6855 |
-+ </para> |
6856 |
-+ |
6857 |
-+ <itemizedlist> |
6858 |
-+ <listitem> |
6859 |
-+ <para> |
6860 |
-+ [1] The creds attached to messages are determined as |
6861 |
-+ <constant>a & b & c</constant>. |
6862 |
-+ </para> |
6863 |
-+ </listitem> |
6864 |
-+ |
6865 |
-+ <listitem> |
6866 |
-+ <para> |
6867 |
-+ [2] When connecting to a bus (<constant>KDBUS_CMD_HELLO</constant>), |
6868 |
-+ and <constant>~b & d != 0</constant>, the call will fail with, |
6869 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> is set to |
6870 |
-+ <constant>ECONNREFUSED</constant>. |
6871 |
-+ </para> |
6872 |
-+ </listitem> |
6873 |
-+ |
6874 |
-+ <listitem> |
6875 |
-+ <para> |
6876 |
-+ [3] When querying creds of a bus peer, the creds returned are |
6877 |
-+ <constant>a & b & f</constant>. |
6878 |
-+ </para> |
6879 |
-+ </listitem> |
6880 |
-+ |
6881 |
-+ <listitem> |
6882 |
-+ <para> |
6883 |
-+ [4] When querying creds of a bus owner, the creds returned are |
6884 |
-+ <constant>a & e & g</constant>. |
6885 |
-+ </para> |
6886 |
-+ </listitem> |
6887 |
-+ </itemizedlist> |
6888 |
-+ |
6889 |
-+ <para> |
6890 |
-+ Hence, programs might not always get all requested metadata items that |
6891 |
-+ it requested. Code must be written so that it can cope with this fact. |
6892 |
-+ </para> |
6893 |
-+ </refsect2> |
6894 |
-+ |
6895 |
-+ <refsect2> |
6896 |
-+ <title>Benefits and heads-up</title> |
6897 |
-+ <para> |
6898 |
-+ Attaching metadata to messages has two major benefits. |
6899 |
-+ |
6900 |
-+ <itemizedlist> |
6901 |
-+ <listitem> |
6902 |
-+ <para> |
6903 |
-+ Metadata attached to messages is gathered at the moment when the |
6904 |
-+ other side calls <constant>KDBUS_CMD_SEND</constant>, or, |
6905 |
-+ respectively, then the kernel notification is generated. There is |
6906 |
-+ no need for the receiving peer to retrieve information about the |
6907 |
-+ task in a second step. This closes a race gap that would otherwise |
6908 |
-+ be inherent. |
6909 |
-+ </para> |
6910 |
-+ </listitem> |
6911 |
-+ <listitem> |
6912 |
-+ <para> |
6913 |
-+ As metadata is delivered along with messages in the same data |
6914 |
-+ blob, no extra calls to kernel functions etc. are needed to gather |
6915 |
-+ them. |
6916 |
-+ </para> |
6917 |
-+ </listitem> |
6918 |
-+ </itemizedlist> |
6919 |
-+ |
6920 |
-+ Note, however, that collecting metadata does come at a price for |
6921 |
-+ performance, so developers should carefully assess which metadata to |
6922 |
-+ really opt-in for. For best practice, data that is not needed as part |
6923 |
-+ of a message should not be requested by the connection in the first |
6924 |
-+ place (see <varname>attach_flags_recv</varname> in |
6925 |
-+ <constant>KDBUS_CMD_HELLO</constant>). |
6926 |
-+ </para> |
6927 |
-+ </refsect2> |
6928 |
-+ |
6929 |
-+ <refsect2> |
6930 |
-+ <title>Attach flags for metadata items</title> |
6931 |
-+ <para> |
6932 |
-+ To let the kernel know which metadata information to attach as items |
6933 |
-+ to the aforementioned commands, it uses a bitmask. In those, the |
6934 |
-+ following <emphasis>attach flags</emphasis> are currently supported. |
6935 |
-+ Both the <varname>attach_flags_recv</varname> and |
6936 |
-+ <varname>attach_flags_send</varname> fields of |
6937 |
-+ <type>struct kdbus_cmd_hello</type>, as well as the payload of the |
6938 |
-+ <constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant> and |
6939 |
-+ <constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant> items follow this |
6940 |
-+ scheme. |
6941 |
-+ </para> |
6942 |
-+ |
6943 |
-+ <variablelist> |
6944 |
-+ <varlistentry> |
6945 |
-+ <term><constant>KDBUS_ATTACH_TIMESTAMP</constant></term> |
6946 |
-+ <listitem><para> |
6947 |
-+ Requests the attachment of an item of type |
6948 |
-+ <constant>KDBUS_ITEM_TIMESTAMP</constant>. |
6949 |
-+ </para></listitem> |
6950 |
-+ </varlistentry> |
6951 |
-+ |
6952 |
-+ <varlistentry> |
6953 |
-+ <term><constant>KDBUS_ATTACH_CREDS</constant></term> |
6954 |
-+ <listitem><para> |
6955 |
-+ Requests the attachment of an item of type |
6956 |
-+ <constant>KDBUS_ITEM_CREDS</constant>. |
6957 |
-+ </para></listitem> |
6958 |
-+ </varlistentry> |
6959 |
-+ |
6960 |
-+ <varlistentry> |
6961 |
-+ <term><constant>KDBUS_ATTACH_PIDS</constant></term> |
6962 |
-+ <listitem><para> |
6963 |
-+ Requests the attachment of an item of type |
6964 |
-+ <constant>KDBUS_ITEM_PIDS</constant>. |
6965 |
-+ </para></listitem> |
6966 |
-+ </varlistentry> |
6967 |
-+ |
6968 |
-+ <varlistentry> |
6969 |
-+ <term><constant>KDBUS_ATTACH_AUXGROUPS</constant></term> |
6970 |
-+ <listitem><para> |
6971 |
-+ Requests the attachment of an item of type |
6972 |
-+ <constant>KDBUS_ITEM_AUXGROUPS</constant>. |
6973 |
-+ </para></listitem> |
6974 |
-+ </varlistentry> |
6975 |
-+ |
6976 |
-+ <varlistentry> |
6977 |
-+ <term><constant>KDBUS_ATTACH_NAMES</constant></term> |
6978 |
-+ <listitem><para> |
6979 |
-+ Requests the attachment of an item of type |
6980 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant>. |
6981 |
-+ </para></listitem> |
6982 |
-+ </varlistentry> |
6983 |
-+ |
6984 |
-+ <varlistentry> |
6985 |
-+ <term><constant>KDBUS_ATTACH_TID_COMM</constant></term> |
6986 |
-+ <listitem><para> |
6987 |
-+ Requests the attachment of an item of type |
6988 |
-+ <constant>KDBUS_ITEM_TID_COMM</constant>. |
6989 |
-+ </para></listitem> |
6990 |
-+ </varlistentry> |
6991 |
-+ |
6992 |
-+ <varlistentry> |
6993 |
-+ <term><constant>KDBUS_ATTACH_PID_COMM</constant></term> |
6994 |
-+ <listitem><para> |
6995 |
-+ Requests the attachment of an item of type |
6996 |
-+ <constant>KDBUS_ITEM_PID_COMM</constant>. |
6997 |
-+ </para></listitem> |
6998 |
-+ </varlistentry> |
6999 |
-+ |
7000 |
-+ <varlistentry> |
7001 |
-+ <term><constant>KDBUS_ATTACH_EXE</constant></term> |
7002 |
-+ <listitem><para> |
7003 |
-+ Requests the attachment of an item of type |
7004 |
-+ <constant>KDBUS_ITEM_EXE</constant>. |
7005 |
-+ </para></listitem> |
7006 |
-+ </varlistentry> |
7007 |
-+ |
7008 |
-+ <varlistentry> |
7009 |
-+ <term><constant>KDBUS_ATTACH_CMDLINE</constant></term> |
7010 |
-+ <listitem><para> |
7011 |
-+ Requests the attachment of an item of type |
7012 |
-+ <constant>KDBUS_ITEM_CMDLINE</constant>. |
7013 |
-+ </para></listitem> |
7014 |
-+ </varlistentry> |
7015 |
-+ |
7016 |
-+ <varlistentry> |
7017 |
-+ <term><constant>KDBUS_ATTACH_CGROUP</constant></term> |
7018 |
-+ <listitem><para> |
7019 |
-+ Requests the attachment of an item of type |
7020 |
-+ <constant>KDBUS_ITEM_CGROUP</constant>. |
7021 |
-+ </para></listitem> |
7022 |
-+ </varlistentry> |
7023 |
-+ |
7024 |
-+ <varlistentry> |
7025 |
-+ <term><constant>KDBUS_ATTACH_CAPS</constant></term> |
7026 |
-+ <listitem><para> |
7027 |
-+ Requests the attachment of an item of type |
7028 |
-+ <constant>KDBUS_ITEM_CAPS</constant>. |
7029 |
-+ </para></listitem> |
7030 |
-+ </varlistentry> |
7031 |
-+ |
7032 |
-+ <varlistentry> |
7033 |
-+ <term><constant>KDBUS_ATTACH_SECLABEL</constant></term> |
7034 |
-+ <listitem><para> |
7035 |
-+ Requests the attachment of an item of type |
7036 |
-+ <constant>KDBUS_ITEM_SECLABEL</constant>. |
7037 |
-+ </para></listitem> |
7038 |
-+ </varlistentry> |
7039 |
-+ |
7040 |
-+ <varlistentry> |
7041 |
-+ <term><constant>KDBUS_ATTACH_AUDIT</constant></term> |
7042 |
-+ <listitem><para> |
7043 |
-+ Requests the attachment of an item of type |
7044 |
-+ <constant>KDBUS_ITEM_AUDIT</constant>. |
7045 |
-+ </para></listitem> |
7046 |
-+ </varlistentry> |
7047 |
-+ |
7048 |
-+ <varlistentry> |
7049 |
-+ <term><constant>KDBUS_ATTACH_CONN_DESCRIPTION</constant></term> |
7050 |
-+ <listitem><para> |
7051 |
-+ Requests the attachment of an item of type |
7052 |
-+ <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant>. |
7053 |
-+ </para></listitem> |
7054 |
-+ </varlistentry> |
7055 |
-+ </variablelist> |
7056 |
-+ |
7057 |
-+ <para> |
7058 |
-+ Please refer to |
7059 |
-+ <citerefentry> |
7060 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
7061 |
-+ <manvolnum>7</manvolnum> |
7062 |
-+ </citerefentry> |
7063 |
-+ for detailed information about the layout and payload of items and |
7064 |
-+ what metadata should be used to. |
7065 |
-+ </para> |
7066 |
-+ </refsect2> |
7067 |
-+ </refsect1> |
7068 |
-+ |
7069 |
-+ <refsect1> |
7070 |
-+ <title>The ioctl interface</title> |
7071 |
-+ |
7072 |
-+ <para> |
7073 |
-+ As stated in the 'synopsis' section above, application developers are |
7074 |
-+ strongly encouraged to use kdbus through one of the high-level D-Bus |
7075 |
-+ abstraction libraries, rather than using the low-level API directly. |
7076 |
-+ </para> |
7077 |
-+ |
7078 |
-+ <para> |
7079 |
-+ kdbus on the kernel level exposes its functions exclusively through |
7080 |
-+ <citerefentry> |
7081 |
-+ <refentrytitle>ioctl</refentrytitle> |
7082 |
-+ <manvolnum>2</manvolnum> |
7083 |
-+ </citerefentry>, |
7084 |
-+ employed on file descriptors returned by |
7085 |
-+ <citerefentry> |
7086 |
-+ <refentrytitle>open</refentrytitle> |
7087 |
-+ <manvolnum>2</manvolnum> |
7088 |
-+ </citerefentry> |
7089 |
-+ on pseudo files exposed by |
7090 |
-+ <citerefentry> |
7091 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
7092 |
-+ <manvolnum>7</manvolnum> |
7093 |
-+ </citerefentry>. |
7094 |
-+ </para> |
7095 |
-+ <para> |
7096 |
-+ Following is a list of all the ioctls, along with the command structs |
7097 |
-+ they must be used with. |
7098 |
-+ </para> |
7099 |
-+ |
7100 |
-+ <informaltable frame="none"> |
7101 |
-+ <tgroup cols="3" colsep="1"> |
7102 |
-+ <thead> |
7103 |
-+ <row> |
7104 |
-+ <entry>ioctl signature</entry> |
7105 |
-+ <entry>command</entry> |
7106 |
-+ <entry>transported struct</entry> |
7107 |
-+ </row> |
7108 |
-+ </thead> |
7109 |
-+ <tbody> |
7110 |
-+ <row> |
7111 |
-+ <entry><constant>0x40189500</constant></entry> |
7112 |
-+ <entry><constant>KDBUS_CMD_BUS_MAKE</constant></entry> |
7113 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7114 |
-+ </row><row> |
7115 |
-+ <entry><constant>0x40189510</constant></entry> |
7116 |
-+ <entry><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></entry> |
7117 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7118 |
-+ </row><row> |
7119 |
-+ <entry><constant>0xc0609580</constant></entry> |
7120 |
-+ <entry><constant>KDBUS_CMD_HELLO</constant></entry> |
7121 |
-+ <entry><type>struct kdbus_cmd_hello *</type></entry> |
7122 |
-+ </row><row> |
7123 |
-+ <entry><constant>0x40189582</constant></entry> |
7124 |
-+ <entry><constant>KDBUS_CMD_BYEBYE</constant></entry> |
7125 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7126 |
-+ </row><row> |
7127 |
-+ <entry><constant>0x40389590</constant></entry> |
7128 |
-+ <entry><constant>KDBUS_CMD_SEND</constant></entry> |
7129 |
-+ <entry><type>struct kdbus_cmd_send *</type></entry> |
7130 |
-+ </row><row> |
7131 |
-+ <entry><constant>0x80409591</constant></entry> |
7132 |
-+ <entry><constant>KDBUS_CMD_RECV</constant></entry> |
7133 |
-+ <entry><type>struct kdbus_cmd_recv *</type></entry> |
7134 |
-+ </row><row> |
7135 |
-+ <entry><constant>0x40209583</constant></entry> |
7136 |
-+ <entry><constant>KDBUS_CMD_FREE</constant></entry> |
7137 |
-+ <entry><type>struct kdbus_cmd_free *</type></entry> |
7138 |
-+ </row><row> |
7139 |
-+ <entry><constant>0x401895a0</constant></entry> |
7140 |
-+ <entry><constant>KDBUS_CMD_NAME_ACQUIRE</constant></entry> |
7141 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7142 |
-+ </row><row> |
7143 |
-+ <entry><constant>0x401895a1</constant></entry> |
7144 |
-+ <entry><constant>KDBUS_CMD_NAME_RELEASE</constant></entry> |
7145 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7146 |
-+ </row><row> |
7147 |
-+ <entry><constant>0x80289586</constant></entry> |
7148 |
-+ <entry><constant>KDBUS_CMD_LIST</constant></entry> |
7149 |
-+ <entry><type>struct kdbus_cmd_list *</type></entry> |
7150 |
-+ </row><row> |
7151 |
-+ <entry><constant>0x80309584</constant></entry> |
7152 |
-+ <entry><constant>KDBUS_CMD_CONN_INFO</constant></entry> |
7153 |
-+ <entry><type>struct kdbus_cmd_info *</type></entry> |
7154 |
-+ </row><row> |
7155 |
-+ <entry><constant>0x40209551</constant></entry> |
7156 |
-+ <entry><constant>KDBUS_CMD_UPDATE</constant></entry> |
7157 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7158 |
-+ </row><row> |
7159 |
-+ <entry><constant>0x80309585</constant></entry> |
7160 |
-+ <entry><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></entry> |
7161 |
-+ <entry><type>struct kdbus_cmd_info *</type></entry> |
7162 |
-+ </row><row> |
7163 |
-+ <entry><constant>0x40189511</constant></entry> |
7164 |
-+ <entry><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></entry> |
7165 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7166 |
-+ </row><row> |
7167 |
-+ <entry><constant>0x402095b0</constant></entry> |
7168 |
-+ <entry><constant>KDBUS_CMD_MATCH_ADD</constant></entry> |
7169 |
-+ <entry><type>struct kdbus_cmd_match *</type></entry> |
7170 |
-+ </row><row> |
7171 |
-+ <entry><constant>0x402095b1</constant></entry> |
7172 |
-+ <entry><constant>KDBUS_CMD_MATCH_REMOVE</constant></entry> |
7173 |
-+ <entry><type>struct kdbus_cmd_match *</type></entry> |
7174 |
-+ </row> |
7175 |
-+ </tbody> |
7176 |
-+ </tgroup> |
7177 |
-+ </informaltable> |
7178 |
-+ |
7179 |
-+ <para> |
7180 |
-+ Depending on the type of <emphasis>kdbusfs</emphasis> node that was |
7181 |
-+ opened and what ioctls have been executed on a file descriptor before, |
7182 |
-+ a different sub-set of ioctl commands is allowed. |
7183 |
-+ </para> |
7184 |
-+ |
7185 |
-+ <itemizedlist> |
7186 |
-+ <listitem> |
7187 |
-+ <para> |
7188 |
-+ On a file descriptor resulting from opening a |
7189 |
-+ <emphasis>control node</emphasis>, only the |
7190 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl may be executed. |
7191 |
-+ </para> |
7192 |
-+ </listitem> |
7193 |
-+ <listitem> |
7194 |
-+ <para> |
7195 |
-+ On a file descriptor resulting from opening a |
7196 |
-+ <emphasis>bus endpoint node</emphasis>, only the |
7197 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> and |
7198 |
-+ <constant>KDBUS_CMD_HELLO</constant> ioctls may be executed. |
7199 |
-+ </para> |
7200 |
-+ </listitem> |
7201 |
-+ <listitem> |
7202 |
-+ <para> |
7203 |
-+ A file descriptor that was used to create a bus |
7204 |
-+ (via <constant>KDBUS_CMD_BUS_MAKE</constant>) is called a |
7205 |
-+ <emphasis>bus owner</emphasis> file descriptor. The bus will be |
7206 |
-+ active as long as the file descriptor is kept open. |
7207 |
-+ A bus owner file descriptor can not be used to |
7208 |
-+ employ any further ioctls. As soon as |
7209 |
-+ <citerefentry> |
7210 |
-+ <refentrytitle>close</refentrytitle> |
7211 |
-+ <manvolnum>2</manvolnum> |
7212 |
-+ </citerefentry> |
7213 |
-+ is called on it, the bus will be shut down, along will all associated |
7214 |
-+ endpoints and connections. See |
7215 |
-+ <citerefentry> |
7216 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
7217 |
-+ <manvolnum>7</manvolnum> |
7218 |
-+ </citerefentry> |
7219 |
-+ for more details. |
7220 |
-+ </para> |
7221 |
-+ </listitem> |
7222 |
-+ <listitem> |
7223 |
-+ <para> |
7224 |
-+ A file descriptor that was used to create an endpoint |
7225 |
-+ (via <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>) is called an |
7226 |
-+ <emphasis>endpoint owner</emphasis> file descriptor. The endpoint |
7227 |
-+ will be active as long as the file descriptor is kept open. |
7228 |
-+ An endpoint owner file descriptor can only be used |
7229 |
-+ to update details of an endpoint through the |
7230 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> ioctl. As soon as |
7231 |
-+ <citerefentry> |
7232 |
-+ <refentrytitle>close</refentrytitle> |
7233 |
-+ <manvolnum>2</manvolnum> |
7234 |
-+ </citerefentry> |
7235 |
-+ is called on it, the endpoint will be removed from the bus, and all |
7236 |
-+ connections that are connected to the bus through it are shut down. |
7237 |
-+ See |
7238 |
-+ <citerefentry> |
7239 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
7240 |
-+ <manvolnum>7</manvolnum> |
7241 |
-+ </citerefentry> |
7242 |
-+ for more details. |
7243 |
-+ </para> |
7244 |
-+ </listitem> |
7245 |
-+ <listitem> |
7246 |
-+ <para> |
7247 |
-+ A file descriptor that was used to create a connection |
7248 |
-+ (via <constant>KDBUS_CMD_HELLO</constant>) is called a |
7249 |
-+ <emphasis>connection owner</emphasis> file descriptor. The connection |
7250 |
-+ will be active as long as the file descriptor is kept open. |
7251 |
-+ A connection owner file descriptor may be used to |
7252 |
-+ issue any of the following ioctls. |
7253 |
-+ </para> |
7254 |
-+ |
7255 |
-+ <itemizedlist> |
7256 |
-+ <listitem><para> |
7257 |
-+ <constant>KDBUS_CMD_UPDATE</constant> to tweak details of the |
7258 |
-+ connection. See |
7259 |
-+ <citerefentry> |
7260 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7261 |
-+ <manvolnum>7</manvolnum> |
7262 |
-+ </citerefentry>. |
7263 |
-+ </para></listitem> |
7264 |
-+ |
7265 |
-+ <listitem><para> |
7266 |
-+ <constant>KDBUS_CMD_BYEBYE</constant> to shut down a connection |
7267 |
-+ without losing messages. See |
7268 |
-+ <citerefentry> |
7269 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7270 |
-+ <manvolnum>7</manvolnum> |
7271 |
-+ </citerefentry>. |
7272 |
-+ </para></listitem> |
7273 |
-+ |
7274 |
-+ <listitem><para> |
7275 |
-+ <constant>KDBUS_CMD_FREE</constant> to free a slice of memory in |
7276 |
-+ the pool. See |
7277 |
-+ <citerefentry> |
7278 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
7279 |
-+ <manvolnum>7</manvolnum> |
7280 |
-+ </citerefentry>. |
7281 |
-+ </para></listitem> |
7282 |
-+ |
7283 |
-+ <listitem><para> |
7284 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant> to retrieve information |
7285 |
-+ on other connections on the bus. See |
7286 |
-+ <citerefentry> |
7287 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7288 |
-+ <manvolnum>7</manvolnum> |
7289 |
-+ </citerefentry>. |
7290 |
-+ </para></listitem> |
7291 |
-+ |
7292 |
-+ <listitem><para> |
7293 |
-+ <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> to retrieve |
7294 |
-+ information on the bus creator. See |
7295 |
-+ <citerefentry> |
7296 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7297 |
-+ <manvolnum>7</manvolnum> |
7298 |
-+ </citerefentry>. |
7299 |
-+ </para></listitem> |
7300 |
-+ |
7301 |
-+ <listitem><para> |
7302 |
-+ <constant>KDBUS_CMD_LIST</constant> to retrieve a list of |
7303 |
-+ currently active well-known names and unique IDs on the bus. See |
7304 |
-+ <citerefentry> |
7305 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
7306 |
-+ <manvolnum>7</manvolnum> |
7307 |
-+ </citerefentry>. |
7308 |
-+ </para></listitem> |
7309 |
-+ |
7310 |
-+ <listitem><para> |
7311 |
-+ <constant>KDBUS_CMD_SEND</constant> and |
7312 |
-+ <constant>KDBUS_CMD_RECV</constant> to send or receive a message. |
7313 |
-+ See |
7314 |
-+ <citerefentry> |
7315 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
7316 |
-+ <manvolnum>7</manvolnum> |
7317 |
-+ </citerefentry>. |
7318 |
-+ </para></listitem> |
7319 |
-+ |
7320 |
-+ <listitem><para> |
7321 |
-+ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> and |
7322 |
-+ <constant>KDBUS_CMD_NAME_RELEASE</constant> to acquire or release |
7323 |
-+ a well-known name on the bus. See |
7324 |
-+ <citerefentry> |
7325 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
7326 |
-+ <manvolnum>7</manvolnum> |
7327 |
-+ </citerefentry>. |
7328 |
-+ </para></listitem> |
7329 |
-+ |
7330 |
-+ <listitem><para> |
7331 |
-+ <constant>KDBUS_CMD_MATCH_ADD</constant> and |
7332 |
-+ <constant>KDBUS_CMD_MATCH_REMOVE</constant> to add or remove |
7333 |
-+ a match for signal messages. See |
7334 |
-+ <citerefentry> |
7335 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
7336 |
-+ <manvolnum>7</manvolnum> |
7337 |
-+ </citerefentry>. |
7338 |
-+ </para></listitem> |
7339 |
-+ </itemizedlist> |
7340 |
-+ </listitem> |
7341 |
-+ </itemizedlist> |
7342 |
-+ |
7343 |
-+ <para> |
7344 |
-+ These ioctls, along with the structs they transport, are explained in |
7345 |
-+ detail in the other documents linked to in the "See Also" section below. |
7346 |
-+ </para> |
7347 |
-+ </refsect1> |
7348 |
-+ |
7349 |
-+ <refsect1> |
7350 |
-+ <title>See Also</title> |
7351 |
-+ <simplelist type="inline"> |
7352 |
-+ <member> |
7353 |
-+ <citerefentry> |
7354 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
7355 |
-+ <manvolnum>7</manvolnum> |
7356 |
-+ </citerefentry> |
7357 |
-+ </member> |
7358 |
-+ <member> |
7359 |
-+ <citerefentry> |
7360 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7361 |
-+ <manvolnum>7</manvolnum> |
7362 |
-+ </citerefentry> |
7363 |
-+ </member> |
7364 |
-+ <member> |
7365 |
-+ <citerefentry> |
7366 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
7367 |
-+ <manvolnum>7</manvolnum> |
7368 |
-+ </citerefentry> |
7369 |
-+ </member> |
7370 |
-+ <member> |
7371 |
-+ <citerefentry> |
7372 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
7373 |
-+ <manvolnum>7</manvolnum> |
7374 |
-+ </citerefentry> |
7375 |
-+ </member> |
7376 |
-+ <member> |
7377 |
-+ <citerefentry> |
7378 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
7379 |
-+ <manvolnum>7</manvolnum> |
7380 |
-+ </citerefentry> |
7381 |
-+ </member> |
7382 |
-+ <member> |
7383 |
-+ <citerefentry> |
7384 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
7385 |
-+ <manvolnum>7</manvolnum> |
7386 |
-+ </citerefentry> |
7387 |
-+ </member> |
7388 |
-+ <member> |
7389 |
-+ <citerefentry> |
7390 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
7391 |
-+ <manvolnum>7</manvolnum> |
7392 |
-+ </citerefentry> |
7393 |
-+ </member> |
7394 |
-+ <member> |
7395 |
-+ <citerefentry> |
7396 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
7397 |
-+ <manvolnum>7</manvolnum> |
7398 |
-+ </citerefentry> |
7399 |
-+ </member> |
7400 |
-+ <member> |
7401 |
-+ <citerefentry> |
7402 |
-+ <refentrytitle>ioctl</refentrytitle> |
7403 |
-+ <manvolnum>2</manvolnum> |
7404 |
-+ </citerefentry> |
7405 |
-+ </member> |
7406 |
-+ <member> |
7407 |
-+ <citerefentry> |
7408 |
-+ <refentrytitle>mmap</refentrytitle> |
7409 |
-+ <manvolnum>2</manvolnum> |
7410 |
-+ </citerefentry> |
7411 |
-+ </member> |
7412 |
-+ <member> |
7413 |
-+ <citerefentry> |
7414 |
-+ <refentrytitle>open</refentrytitle> |
7415 |
-+ <manvolnum>2</manvolnum> |
7416 |
-+ </citerefentry> |
7417 |
-+ </member> |
7418 |
-+ <member> |
7419 |
-+ <citerefentry> |
7420 |
-+ <refentrytitle>close</refentrytitle> |
7421 |
-+ <manvolnum>2</manvolnum> |
7422 |
-+ </citerefentry> |
7423 |
-+ </member> |
7424 |
-+ <member> |
7425 |
-+ <ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink> |
7426 |
-+ </member> |
7427 |
-+ </simplelist> |
7428 |
-+ </refsect1> |
7429 |
-+ |
7430 |
-+</refentry> |
7431 |
-diff --git a/Documentation/kdbus/stylesheet.xsl b/Documentation/kdbus/stylesheet.xsl |
7432 |
-new file mode 100644 |
7433 |
-index 0000000..52565ea |
7434 |
---- /dev/null |
7435 |
-+++ b/Documentation/kdbus/stylesheet.xsl |
7436 |
-@@ -0,0 +1,16 @@ |
7437 |
-+<?xml version="1.0" encoding="UTF-8"?> |
7438 |
-+<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"> |
7439 |
-+ <param name="chunk.quietly">1</param> |
7440 |
-+ <param name="funcsynopsis.style">ansi</param> |
7441 |
-+ <param name="funcsynopsis.tabular.threshold">80</param> |
7442 |
-+ <param name="callout.graphics">0</param> |
7443 |
-+ <param name="paper.type">A4</param> |
7444 |
-+ <param name="generate.section.toc.level">2</param> |
7445 |
-+ <param name="use.id.as.filename">1</param> |
7446 |
-+ <param name="citerefentry.link">1</param> |
7447 |
-+ <strip-space elements="*"/> |
7448 |
-+ <template name="generate.citerefentry.link"> |
7449 |
-+ <value-of select="refentrytitle"/> |
7450 |
-+ <text>.html</text> |
7451 |
-+ </template> |
7452 |
-+</stylesheet> |
7453 |
-diff --git a/MAINTAINERS b/MAINTAINERS |
7454 |
-index d8afd29..02f7668 100644 |
7455 |
---- a/MAINTAINERS |
7456 |
-+++ b/MAINTAINERS |
7457 |
-@@ -5585,6 +5585,19 @@ S: Maintained |
7458 |
- F: Documentation/kbuild/kconfig-language.txt |
7459 |
- F: scripts/kconfig/ |
7460 |
- |
7461 |
-+KDBUS |
7462 |
-+M: Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
7463 |
-+M: Daniel Mack <daniel@××××××.org> |
7464 |
-+M: David Herrmann <dh.herrmann@××××××××××.com> |
7465 |
-+M: Djalal Harouni <tixxdz@××××××.org> |
7466 |
-+L: linux-kernel@×××××××××××.org |
7467 |
-+S: Maintained |
7468 |
-+F: ipc/kdbus/* |
7469 |
-+F: samples/kdbus/* |
7470 |
-+F: Documentation/kdbus/* |
7471 |
-+F: include/uapi/linux/kdbus.h |
7472 |
-+F: tools/testing/selftests/kdbus/ |
7473 |
-+ |
7474 |
- KDUMP |
7475 |
- M: Vivek Goyal <vgoyal@××××××.com> |
7476 |
- M: Haren Myneni <hbabu@××××××.com> |
7477 |
-diff --git a/Makefile b/Makefile |
7478 |
-index f5c8983..a1c8d57 100644 |
7479 |
---- a/Makefile |
7480 |
-+++ b/Makefile |
7481 |
-@@ -1343,6 +1343,7 @@ $(help-board-dirs): help-%: |
7482 |
- %docs: scripts_basic FORCE |
7483 |
- $(Q)$(MAKE) $(build)=scripts build_docproc |
7484 |
- $(Q)$(MAKE) $(build)=Documentation/DocBook $@ |
7485 |
-+ $(Q)$(MAKE) $(build)=Documentation/kdbus $@ |
7486 |
- |
7487 |
- else # KBUILD_EXTMOD |
7488 |
- |
7489 |
-diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild |
7490 |
-index 1a0006a..4842a98 100644 |
7491 |
---- a/include/uapi/linux/Kbuild |
7492 |
-+++ b/include/uapi/linux/Kbuild |
7493 |
-@@ -215,6 +215,7 @@ header-y += ixjuser.h |
7494 |
- header-y += jffs2.h |
7495 |
- header-y += joystick.h |
7496 |
- header-y += kcmp.h |
7497 |
-+header-y += kdbus.h |
7498 |
- header-y += kdev_t.h |
7499 |
- header-y += kd.h |
7500 |
- header-y += kernelcapi.h |
7501 |
-diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h |
7502 |
-new file mode 100644 |
7503 |
-index 0000000..4fc44cb |
7504 |
---- /dev/null |
7505 |
-+++ b/include/uapi/linux/kdbus.h |
7506 |
-@@ -0,0 +1,984 @@ |
7507 |
-+/* |
7508 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
7509 |
-+ * the terms of the GNU Lesser General Public License as published by the |
7510 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
7511 |
-+ * your option) any later version. |
7512 |
-+ */ |
7513 |
-+ |
7514 |
-+#ifndef _UAPI_KDBUS_H_ |
7515 |
-+#define _UAPI_KDBUS_H_ |
7516 |
-+ |
7517 |
-+#include <linux/ioctl.h> |
7518 |
-+#include <linux/types.h> |
7519 |
-+ |
7520 |
-+#define KDBUS_IOCTL_MAGIC 0x95 |
7521 |
-+#define KDBUS_SRC_ID_KERNEL (0) |
7522 |
-+#define KDBUS_DST_ID_NAME (0) |
7523 |
-+#define KDBUS_MATCH_ID_ANY (~0ULL) |
7524 |
-+#define KDBUS_DST_ID_BROADCAST (~0ULL) |
7525 |
-+#define KDBUS_FLAG_NEGOTIATE (1ULL << 63) |
7526 |
-+ |
7527 |
-+/** |
7528 |
-+ * struct kdbus_notify_id_change - name registry change message |
7529 |
-+ * @id: New or former owner of the name |
7530 |
-+ * @flags: flags field from KDBUS_HELLO_* |
7531 |
-+ * |
7532 |
-+ * Sent from kernel to userspace when the owner or activator of |
7533 |
-+ * a well-known name changes. |
7534 |
-+ * |
7535 |
-+ * Attached to: |
7536 |
-+ * KDBUS_ITEM_ID_ADD |
7537 |
-+ * KDBUS_ITEM_ID_REMOVE |
7538 |
-+ */ |
7539 |
-+struct kdbus_notify_id_change { |
7540 |
-+ __u64 id; |
7541 |
-+ __u64 flags; |
7542 |
-+} __attribute__((__aligned__(8))); |
7543 |
-+ |
7544 |
-+/** |
7545 |
-+ * struct kdbus_notify_name_change - name registry change message |
7546 |
-+ * @old_id: ID and flags of former owner of a name |
7547 |
-+ * @new_id: ID and flags of new owner of a name |
7548 |
-+ * @name: Well-known name |
7549 |
-+ * |
7550 |
-+ * Sent from kernel to userspace when the owner or activator of |
7551 |
-+ * a well-known name changes. |
7552 |
-+ * |
7553 |
-+ * Attached to: |
7554 |
-+ * KDBUS_ITEM_NAME_ADD |
7555 |
-+ * KDBUS_ITEM_NAME_REMOVE |
7556 |
-+ * KDBUS_ITEM_NAME_CHANGE |
7557 |
-+ */ |
7558 |
-+struct kdbus_notify_name_change { |
7559 |
-+ struct kdbus_notify_id_change old_id; |
7560 |
-+ struct kdbus_notify_id_change new_id; |
7561 |
-+ char name[0]; |
7562 |
-+} __attribute__((__aligned__(8))); |
7563 |
-+ |
7564 |
-+/** |
7565 |
-+ * struct kdbus_creds - process credentials |
7566 |
-+ * @uid: User ID |
7567 |
-+ * @euid: Effective UID |
7568 |
-+ * @suid: Saved UID |
7569 |
-+ * @fsuid: Filesystem UID |
7570 |
-+ * @gid: Group ID |
7571 |
-+ * @egid: Effective GID |
7572 |
-+ * @sgid: Saved GID |
7573 |
-+ * @fsgid: Filesystem GID |
7574 |
-+ * |
7575 |
-+ * Attached to: |
7576 |
-+ * KDBUS_ITEM_CREDS |
7577 |
-+ */ |
7578 |
-+struct kdbus_creds { |
7579 |
-+ __u64 uid; |
7580 |
-+ __u64 euid; |
7581 |
-+ __u64 suid; |
7582 |
-+ __u64 fsuid; |
7583 |
-+ __u64 gid; |
7584 |
-+ __u64 egid; |
7585 |
-+ __u64 sgid; |
7586 |
-+ __u64 fsgid; |
7587 |
-+} __attribute__((__aligned__(8))); |
7588 |
-+ |
7589 |
-+/** |
7590 |
-+ * struct kdbus_pids - process identifiers |
7591 |
-+ * @pid: Process ID |
7592 |
-+ * @tid: Thread ID |
7593 |
-+ * @ppid: Parent process ID |
7594 |
-+ * |
7595 |
-+ * The PID and TID of a process. |
7596 |
-+ * |
7597 |
-+ * Attached to: |
7598 |
-+ * KDBUS_ITEM_PIDS |
7599 |
-+ */ |
7600 |
-+struct kdbus_pids { |
7601 |
-+ __u64 pid; |
7602 |
-+ __u64 tid; |
7603 |
-+ __u64 ppid; |
7604 |
-+} __attribute__((__aligned__(8))); |
7605 |
-+ |
7606 |
-+/** |
7607 |
-+ * struct kdbus_caps - process capabilities |
7608 |
-+ * @last_cap: Highest currently known capability bit |
7609 |
-+ * @caps: Variable number of 32-bit capabilities flags |
7610 |
-+ * |
7611 |
-+ * Contains a variable number of 32-bit capabilities flags. |
7612 |
-+ * |
7613 |
-+ * Attached to: |
7614 |
-+ * KDBUS_ITEM_CAPS |
7615 |
-+ */ |
7616 |
-+struct kdbus_caps { |
7617 |
-+ __u32 last_cap; |
7618 |
-+ __u32 caps[0]; |
7619 |
-+} __attribute__((__aligned__(8))); |
7620 |
-+ |
7621 |
-+/** |
7622 |
-+ * struct kdbus_audit - audit information |
7623 |
-+ * @sessionid: The audit session ID |
7624 |
-+ * @loginuid: The audit login uid |
7625 |
-+ * |
7626 |
-+ * Attached to: |
7627 |
-+ * KDBUS_ITEM_AUDIT |
7628 |
-+ */ |
7629 |
-+struct kdbus_audit { |
7630 |
-+ __u32 sessionid; |
7631 |
-+ __u32 loginuid; |
7632 |
-+} __attribute__((__aligned__(8))); |
7633 |
-+ |
7634 |
-+/** |
7635 |
-+ * struct kdbus_timestamp |
7636 |
-+ * @seqnum: Global per-domain message sequence number |
7637 |
-+ * @monotonic_ns: Monotonic timestamp, in nanoseconds |
7638 |
-+ * @realtime_ns: Realtime timestamp, in nanoseconds |
7639 |
-+ * |
7640 |
-+ * Attached to: |
7641 |
-+ * KDBUS_ITEM_TIMESTAMP |
7642 |
-+ */ |
7643 |
-+struct kdbus_timestamp { |
7644 |
-+ __u64 seqnum; |
7645 |
-+ __u64 monotonic_ns; |
7646 |
-+ __u64 realtime_ns; |
7647 |
-+} __attribute__((__aligned__(8))); |
7648 |
-+ |
7649 |
-+/** |
7650 |
-+ * struct kdbus_vec - I/O vector for kdbus payload items |
7651 |
-+ * @size: The size of the vector |
7652 |
-+ * @address: Memory address of data buffer |
7653 |
-+ * @offset: Offset in the in-message payload memory, |
7654 |
-+ * relative to the message head |
7655 |
-+ * |
7656 |
-+ * Attached to: |
7657 |
-+ * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF |
7658 |
-+ */ |
7659 |
-+struct kdbus_vec { |
7660 |
-+ __u64 size; |
7661 |
-+ union { |
7662 |
-+ __u64 address; |
7663 |
-+ __u64 offset; |
7664 |
-+ }; |
7665 |
-+} __attribute__((__aligned__(8))); |
7666 |
-+ |
7667 |
-+/** |
7668 |
-+ * struct kdbus_bloom_parameter - bus-wide bloom parameters |
7669 |
-+ * @size: Size of the bit field in bytes (m / 8) |
7670 |
-+ * @n_hash: Number of hash functions used (k) |
7671 |
-+ */ |
7672 |
-+struct kdbus_bloom_parameter { |
7673 |
-+ __u64 size; |
7674 |
-+ __u64 n_hash; |
7675 |
-+} __attribute__((__aligned__(8))); |
7676 |
-+ |
7677 |
-+/** |
7678 |
-+ * struct kdbus_bloom_filter - bloom filter containing n elements |
7679 |
-+ * @generation: Generation of the element set in the filter |
7680 |
-+ * @data: Bit field, multiple of 8 bytes |
7681 |
-+ */ |
7682 |
-+struct kdbus_bloom_filter { |
7683 |
-+ __u64 generation; |
7684 |
-+ __u64 data[0]; |
7685 |
-+} __attribute__((__aligned__(8))); |
7686 |
-+ |
7687 |
-+/** |
7688 |
-+ * struct kdbus_memfd - a kdbus memfd |
7689 |
-+ * @start: The offset into the memfd where the segment starts |
7690 |
-+ * @size: The size of the memfd segment |
7691 |
-+ * @fd: The file descriptor number |
7692 |
-+ * @__pad: Padding to ensure proper alignment and size |
7693 |
-+ * |
7694 |
-+ * Attached to: |
7695 |
-+ * KDBUS_ITEM_PAYLOAD_MEMFD |
7696 |
-+ */ |
7697 |
-+struct kdbus_memfd { |
7698 |
-+ __u64 start; |
7699 |
-+ __u64 size; |
7700 |
-+ int fd; |
7701 |
-+ __u32 __pad; |
7702 |
-+} __attribute__((__aligned__(8))); |
7703 |
-+ |
7704 |
-+/** |
7705 |
-+ * struct kdbus_name - a registered well-known name with its flags |
7706 |
-+ * @flags: Flags from KDBUS_NAME_* |
7707 |
-+ * @name: Well-known name |
7708 |
-+ * |
7709 |
-+ * Attached to: |
7710 |
-+ * KDBUS_ITEM_OWNED_NAME |
7711 |
-+ */ |
7712 |
-+struct kdbus_name { |
7713 |
-+ __u64 flags; |
7714 |
-+ char name[0]; |
7715 |
-+} __attribute__((__aligned__(8))); |
7716 |
-+ |
7717 |
-+/** |
7718 |
-+ * enum kdbus_policy_access_type - permissions of a policy record |
7719 |
-+ * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid |
7720 |
-+ * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid |
7721 |
-+ * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid |
7722 |
-+ * @KDBUS_POLICY_ACCESS_WORLD: World-accessible |
7723 |
-+ */ |
7724 |
-+enum kdbus_policy_access_type { |
7725 |
-+ _KDBUS_POLICY_ACCESS_NULL, |
7726 |
-+ KDBUS_POLICY_ACCESS_USER, |
7727 |
-+ KDBUS_POLICY_ACCESS_GROUP, |
7728 |
-+ KDBUS_POLICY_ACCESS_WORLD, |
7729 |
-+}; |
7730 |
-+ |
7731 |
-+/** |
7732 |
-+ * enum kdbus_policy_access_flags - mode flags |
7733 |
-+ * @KDBUS_POLICY_OWN: Allow to own a well-known name |
7734 |
-+ * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE |
7735 |
-+ * @KDBUS_POLICY_TALK: Allow communication to a well-known name |
7736 |
-+ * Implies KDBUS_POLICY_SEE |
7737 |
-+ * @KDBUS_POLICY_SEE: Allow to see a well-known name |
7738 |
-+ */ |
7739 |
-+enum kdbus_policy_type { |
7740 |
-+ KDBUS_POLICY_SEE = 0, |
7741 |
-+ KDBUS_POLICY_TALK, |
7742 |
-+ KDBUS_POLICY_OWN, |
7743 |
-+}; |
7744 |
-+ |
7745 |
-+/** |
7746 |
-+ * struct kdbus_policy_access - policy access item |
7747 |
-+ * @type: One of KDBUS_POLICY_ACCESS_* types |
7748 |
-+ * @access: Access to grant |
7749 |
-+ * @id: For KDBUS_POLICY_ACCESS_USER, the uid |
7750 |
-+ * For KDBUS_POLICY_ACCESS_GROUP, the gid |
7751 |
-+ */ |
7752 |
-+struct kdbus_policy_access { |
7753 |
-+ __u64 type; /* USER, GROUP, WORLD */ |
7754 |
-+ __u64 access; /* OWN, TALK, SEE */ |
7755 |
-+ __u64 id; /* uid, gid, 0 */ |
7756 |
-+} __attribute__((__aligned__(8))); |
7757 |
-+ |
7758 |
-+/** |
7759 |
-+ * enum kdbus_attach_flags - flags for metadata attachments |
7760 |
-+ * @KDBUS_ATTACH_TIMESTAMP: Timestamp |
7761 |
-+ * @KDBUS_ATTACH_CREDS: Credentials |
7762 |
-+ * @KDBUS_ATTACH_PIDS: PIDs |
7763 |
-+ * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups |
7764 |
-+ * @KDBUS_ATTACH_NAMES: Well-known names |
7765 |
-+ * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID |
7766 |
-+ * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID |
7767 |
-+ * @KDBUS_ATTACH_EXE: The path of the executable |
7768 |
-+ * @KDBUS_ATTACH_CMDLINE: The process command line |
7769 |
-+ * @KDBUS_ATTACH_CGROUP: The croup membership |
7770 |
-+ * @KDBUS_ATTACH_CAPS: The process capabilities |
7771 |
-+ * @KDBUS_ATTACH_SECLABEL: The security label |
7772 |
-+ * @KDBUS_ATTACH_AUDIT: The audit IDs |
7773 |
-+ * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name |
7774 |
-+ * @_KDBUS_ATTACH_ALL: All of the above |
7775 |
-+ * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of |
7776 |
-+ * metatdata. |
7777 |
-+ */ |
7778 |
-+enum kdbus_attach_flags { |
7779 |
-+ KDBUS_ATTACH_TIMESTAMP = 1ULL << 0, |
7780 |
-+ KDBUS_ATTACH_CREDS = 1ULL << 1, |
7781 |
-+ KDBUS_ATTACH_PIDS = 1ULL << 2, |
7782 |
-+ KDBUS_ATTACH_AUXGROUPS = 1ULL << 3, |
7783 |
-+ KDBUS_ATTACH_NAMES = 1ULL << 4, |
7784 |
-+ KDBUS_ATTACH_TID_COMM = 1ULL << 5, |
7785 |
-+ KDBUS_ATTACH_PID_COMM = 1ULL << 6, |
7786 |
-+ KDBUS_ATTACH_EXE = 1ULL << 7, |
7787 |
-+ KDBUS_ATTACH_CMDLINE = 1ULL << 8, |
7788 |
-+ KDBUS_ATTACH_CGROUP = 1ULL << 9, |
7789 |
-+ KDBUS_ATTACH_CAPS = 1ULL << 10, |
7790 |
-+ KDBUS_ATTACH_SECLABEL = 1ULL << 11, |
7791 |
-+ KDBUS_ATTACH_AUDIT = 1ULL << 12, |
7792 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13, |
7793 |
-+ _KDBUS_ATTACH_ALL = (1ULL << 14) - 1, |
7794 |
-+ _KDBUS_ATTACH_ANY = ~0ULL |
7795 |
-+}; |
7796 |
-+ |
7797 |
-+/** |
7798 |
-+ * enum kdbus_item_type - item types to chain data in a list |
7799 |
-+ * @_KDBUS_ITEM_NULL: Uninitialized/invalid |
7800 |
-+ * @_KDBUS_ITEM_USER_BASE: Start of user items |
7801 |
-+ * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items |
7802 |
-+ * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data |
7803 |
-+ * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head |
7804 |
-+ * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd |
7805 |
-+ * @KDBUS_ITEM_FDS: Attached file descriptors |
7806 |
-+ * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous |
7807 |
-+ * operation by writing to it from |
7808 |
-+ * userspace |
7809 |
-+ * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with |
7810 |
-+ * KDBUS_CMD_BUS_MAKE, carries a |
7811 |
-+ * struct kdbus_bloom_parameter |
7812 |
-+ * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message, |
7813 |
-+ * used to match against a bloom mask of a |
7814 |
-+ * connection, carries a struct |
7815 |
-+ * kdbus_bloom_filter |
7816 |
-+ * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a |
7817 |
-+ * message'sbloom filter |
7818 |
-+ * @KDBUS_ITEM_DST_NAME: Destination's well-known name |
7819 |
-+ * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint |
7820 |
-+ * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which |
7821 |
-+ * metadata a connection opts in to send |
7822 |
-+ * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which |
7823 |
-+ * metadata a connection requests to |
7824 |
-+ * receive for each reeceived message |
7825 |
-+ * @KDBUS_ITEM_ID: Connection ID |
7826 |
-+ * @KDBUS_ITEM_NAME: Well-know name with flags |
7827 |
-+ * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items |
7828 |
-+ * @KDBUS_ITEM_TIMESTAMP: Timestamp |
7829 |
-+ * @KDBUS_ITEM_CREDS: Process credentials |
7830 |
-+ * @KDBUS_ITEM_PIDS: Process identifiers |
7831 |
-+ * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups |
7832 |
-+ * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated |
7833 |
-+ * connection |
7834 |
-+ * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier |
7835 |
-+ * (Don't trust this, see below.) |
7836 |
-+ * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier |
7837 |
-+ * (Don't trust this, see below.) |
7838 |
-+ * @KDBUS_ITEM_EXE: The path of the executable |
7839 |
-+ * (Don't trust this, see below.) |
7840 |
-+ * @KDBUS_ITEM_CMDLINE: The process command line |
7841 |
-+ * (Don't trust this, see below.) |
7842 |
-+ * @KDBUS_ITEM_CGROUP: The croup membership |
7843 |
-+ * @KDBUS_ITEM_CAPS: The process capabilities |
7844 |
-+ * @KDBUS_ITEM_SECLABEL: The security label |
7845 |
-+ * @KDBUS_ITEM_AUDIT: The audit IDs |
7846 |
-+ * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name |
7847 |
-+ * (debugging) |
7848 |
-+ * @_KDBUS_ITEM_POLICY_BASE: Start of policy items |
7849 |
-+ * @KDBUS_ITEM_POLICY_ACCESS: Policy access block |
7850 |
-+ * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items |
7851 |
-+ * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change |
7852 |
-+ * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change |
7853 |
-+ * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change |
7854 |
-+ * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change |
7855 |
-+ * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change |
7856 |
-+ * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached |
7857 |
-+ * @KDBUS_ITEM_REPLY_DEAD: Destination died |
7858 |
-+ * |
7859 |
-+ * N.B: The process and thread COMM fields, as well as the CMDLINE and |
7860 |
-+ * EXE fields may be altered by unprivileged processes und should |
7861 |
-+ * hence *not* used for security decisions. Peers should make use of |
7862 |
-+ * these items only for informational purposes, such as generating log |
7863 |
-+ * records. |
7864 |
-+ */ |
7865 |
-+enum kdbus_item_type { |
7866 |
-+ _KDBUS_ITEM_NULL, |
7867 |
-+ _KDBUS_ITEM_USER_BASE, |
7868 |
-+ KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE, |
7869 |
-+ KDBUS_ITEM_PAYLOAD_VEC, |
7870 |
-+ KDBUS_ITEM_PAYLOAD_OFF, |
7871 |
-+ KDBUS_ITEM_PAYLOAD_MEMFD, |
7872 |
-+ KDBUS_ITEM_FDS, |
7873 |
-+ KDBUS_ITEM_CANCEL_FD, |
7874 |
-+ KDBUS_ITEM_BLOOM_PARAMETER, |
7875 |
-+ KDBUS_ITEM_BLOOM_FILTER, |
7876 |
-+ KDBUS_ITEM_BLOOM_MASK, |
7877 |
-+ KDBUS_ITEM_DST_NAME, |
7878 |
-+ KDBUS_ITEM_MAKE_NAME, |
7879 |
-+ KDBUS_ITEM_ATTACH_FLAGS_SEND, |
7880 |
-+ KDBUS_ITEM_ATTACH_FLAGS_RECV, |
7881 |
-+ KDBUS_ITEM_ID, |
7882 |
-+ KDBUS_ITEM_NAME, |
7883 |
-+ KDBUS_ITEM_DST_ID, |
7884 |
-+ |
7885 |
-+ /* keep these item types in sync with KDBUS_ATTACH_* flags */ |
7886 |
-+ _KDBUS_ITEM_ATTACH_BASE = 0x1000, |
7887 |
-+ KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE, |
7888 |
-+ KDBUS_ITEM_CREDS, |
7889 |
-+ KDBUS_ITEM_PIDS, |
7890 |
-+ KDBUS_ITEM_AUXGROUPS, |
7891 |
-+ KDBUS_ITEM_OWNED_NAME, |
7892 |
-+ KDBUS_ITEM_TID_COMM, |
7893 |
-+ KDBUS_ITEM_PID_COMM, |
7894 |
-+ KDBUS_ITEM_EXE, |
7895 |
-+ KDBUS_ITEM_CMDLINE, |
7896 |
-+ KDBUS_ITEM_CGROUP, |
7897 |
-+ KDBUS_ITEM_CAPS, |
7898 |
-+ KDBUS_ITEM_SECLABEL, |
7899 |
-+ KDBUS_ITEM_AUDIT, |
7900 |
-+ KDBUS_ITEM_CONN_DESCRIPTION, |
7901 |
-+ |
7902 |
-+ _KDBUS_ITEM_POLICY_BASE = 0x2000, |
7903 |
-+ KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE, |
7904 |
-+ |
7905 |
-+ _KDBUS_ITEM_KERNEL_BASE = 0x8000, |
7906 |
-+ KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE, |
7907 |
-+ KDBUS_ITEM_NAME_REMOVE, |
7908 |
-+ KDBUS_ITEM_NAME_CHANGE, |
7909 |
-+ KDBUS_ITEM_ID_ADD, |
7910 |
-+ KDBUS_ITEM_ID_REMOVE, |
7911 |
-+ KDBUS_ITEM_REPLY_TIMEOUT, |
7912 |
-+ KDBUS_ITEM_REPLY_DEAD, |
7913 |
-+}; |
7914 |
-+ |
7915 |
-+/** |
7916 |
-+ * struct kdbus_item - chain of data blocks |
7917 |
-+ * @size: Overall data record size |
7918 |
-+ * @type: Kdbus_item type of data |
7919 |
-+ * @data: Generic bytes |
7920 |
-+ * @data32: Generic 32 bit array |
7921 |
-+ * @data64: Generic 64 bit array |
7922 |
-+ * @str: Generic string |
7923 |
-+ * @id: Connection ID |
7924 |
-+ * @vec: KDBUS_ITEM_PAYLOAD_VEC |
7925 |
-+ * @creds: KDBUS_ITEM_CREDS |
7926 |
-+ * @audit: KDBUS_ITEM_AUDIT |
7927 |
-+ * @timestamp: KDBUS_ITEM_TIMESTAMP |
7928 |
-+ * @name: KDBUS_ITEM_NAME |
7929 |
-+ * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER |
7930 |
-+ * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER |
7931 |
-+ * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD |
7932 |
-+ * @name_change: KDBUS_ITEM_NAME_ADD |
7933 |
-+ * KDBUS_ITEM_NAME_REMOVE |
7934 |
-+ * KDBUS_ITEM_NAME_CHANGE |
7935 |
-+ * @id_change: KDBUS_ITEM_ID_ADD |
7936 |
-+ * KDBUS_ITEM_ID_REMOVE |
7937 |
-+ * @policy: KDBUS_ITEM_POLICY_ACCESS |
7938 |
-+ */ |
7939 |
-+struct kdbus_item { |
7940 |
-+ __u64 size; |
7941 |
-+ __u64 type; |
7942 |
-+ union { |
7943 |
-+ __u8 data[0]; |
7944 |
-+ __u32 data32[0]; |
7945 |
-+ __u64 data64[0]; |
7946 |
-+ char str[0]; |
7947 |
-+ |
7948 |
-+ __u64 id; |
7949 |
-+ struct kdbus_vec vec; |
7950 |
-+ struct kdbus_creds creds; |
7951 |
-+ struct kdbus_pids pids; |
7952 |
-+ struct kdbus_audit audit; |
7953 |
-+ struct kdbus_caps caps; |
7954 |
-+ struct kdbus_timestamp timestamp; |
7955 |
-+ struct kdbus_name name; |
7956 |
-+ struct kdbus_bloom_parameter bloom_parameter; |
7957 |
-+ struct kdbus_bloom_filter bloom_filter; |
7958 |
-+ struct kdbus_memfd memfd; |
7959 |
-+ int fds[0]; |
7960 |
-+ struct kdbus_notify_name_change name_change; |
7961 |
-+ struct kdbus_notify_id_change id_change; |
7962 |
-+ struct kdbus_policy_access policy_access; |
7963 |
-+ }; |
7964 |
-+} __attribute__((__aligned__(8))); |
7965 |
-+ |
7966 |
-+/** |
7967 |
-+ * enum kdbus_msg_flags - type of message |
7968 |
-+ * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for |
7969 |
-+ * method calls. The userspace-supplied |
7970 |
-+ * cookie identifies the message and the |
7971 |
-+ * respective reply carries the cookie |
7972 |
-+ * in cookie_reply |
7973 |
-+ * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed |
7974 |
-+ * name is not currently active. This flag is |
7975 |
-+ * not looked at by the kernel but only |
7976 |
-+ * serves as hint for userspace implementations. |
7977 |
-+ * @KDBUS_MSG_SIGNAL: Treat this message as signal |
7978 |
-+ */ |
7979 |
-+enum kdbus_msg_flags { |
7980 |
-+ KDBUS_MSG_EXPECT_REPLY = 1ULL << 0, |
7981 |
-+ KDBUS_MSG_NO_AUTO_START = 1ULL << 1, |
7982 |
-+ KDBUS_MSG_SIGNAL = 1ULL << 2, |
7983 |
-+}; |
7984 |
-+ |
7985 |
-+/** |
7986 |
-+ * enum kdbus_payload_type - type of payload carried by message |
7987 |
-+ * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message |
7988 |
-+ * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus" |
7989 |
-+ * |
7990 |
-+ * Any payload-type is accepted. Common types will get added here once |
7991 |
-+ * established. |
7992 |
-+ */ |
7993 |
-+enum kdbus_payload_type { |
7994 |
-+ KDBUS_PAYLOAD_KERNEL, |
7995 |
-+ KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL, |
7996 |
-+}; |
7997 |
-+ |
7998 |
-+/** |
7999 |
-+ * struct kdbus_msg - the representation of a kdbus message |
8000 |
-+ * @size: Total size of the message |
8001 |
-+ * @flags: Message flags (KDBUS_MSG_*), userspace → kernel |
8002 |
-+ * @priority: Message queue priority value |
8003 |
-+ * @dst_id: 64-bit ID of the destination connection |
8004 |
-+ * @src_id: 64-bit ID of the source connection |
8005 |
-+ * @payload_type: Payload type (KDBUS_PAYLOAD_*) |
8006 |
-+ * @cookie: Userspace-supplied cookie, for the connection |
8007 |
-+ * to identify its messages |
8008 |
-+ * @timeout_ns: The time to wait for a message reply from the peer. |
8009 |
-+ * If there is no reply, and the send command is |
8010 |
-+ * executed asynchronously, a kernel-generated message |
8011 |
-+ * with an attached KDBUS_ITEM_REPLY_TIMEOUT item |
8012 |
-+ * is sent to @src_id. For synchronously executed send |
8013 |
-+ * command, the value denotes the maximum time the call |
8014 |
-+ * blocks to wait for a reply. The timeout is expected in |
8015 |
-+ * nanoseconds and as absolute CLOCK_MONOTONIC value. |
8016 |
-+ * @cookie_reply: A reply to the requesting message with the same |
8017 |
-+ * cookie. The requesting connection can match its |
8018 |
-+ * request and the reply with this value |
8019 |
-+ * @items: A list of kdbus_items containing the message payload |
8020 |
-+ */ |
8021 |
-+struct kdbus_msg { |
8022 |
-+ __u64 size; |
8023 |
-+ __u64 flags; |
8024 |
-+ __s64 priority; |
8025 |
-+ __u64 dst_id; |
8026 |
-+ __u64 src_id; |
8027 |
-+ __u64 payload_type; |
8028 |
-+ __u64 cookie; |
8029 |
-+ union { |
8030 |
-+ __u64 timeout_ns; |
8031 |
-+ __u64 cookie_reply; |
8032 |
-+ }; |
8033 |
-+ struct kdbus_item items[0]; |
8034 |
-+} __attribute__((__aligned__(8))); |
8035 |
-+ |
8036 |
-+/** |
8037 |
-+ * struct kdbus_msg_info - returned message container |
8038 |
-+ * @offset: Offset of kdbus_msg slice in pool |
8039 |
-+ * @msg_size: Copy of the kdbus_msg.size field |
8040 |
-+ * @return_flags: Command return flags, kernel → userspace |
8041 |
-+ */ |
8042 |
-+struct kdbus_msg_info { |
8043 |
-+ __u64 offset; |
8044 |
-+ __u64 msg_size; |
8045 |
-+ __u64 return_flags; |
8046 |
-+} __attribute__((__aligned__(8))); |
8047 |
-+ |
8048 |
-+/** |
8049 |
-+ * enum kdbus_send_flags - flags for sending messages |
8050 |
-+ * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to |
8051 |
-+ * reply to this message. The |
8052 |
-+ * KDBUS_CMD_SEND ioctl() will block |
8053 |
-+ * until the reply is received, and |
8054 |
-+ * reply in struct kdbus_cmd_send will |
8055 |
-+ * yield the offset in the sender's pool |
8056 |
-+ * where the reply can be found. |
8057 |
-+ * This flag is only valid if |
8058 |
-+ * @KDBUS_MSG_EXPECT_REPLY is set as well. |
8059 |
-+ */ |
8060 |
-+enum kdbus_send_flags { |
8061 |
-+ KDBUS_SEND_SYNC_REPLY = 1ULL << 0, |
8062 |
-+}; |
8063 |
-+ |
8064 |
-+/** |
8065 |
-+ * struct kdbus_cmd_send - send message |
8066 |
-+ * @size: Overall size of this structure |
8067 |
-+ * @flags: Flags to change send behavior (KDBUS_SEND_*) |
8068 |
-+ * @return_flags: Command return flags, kernel → userspace |
8069 |
-+ * @msg_address: Storage address of the kdbus_msg to send |
8070 |
-+ * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY |
8071 |
-+ * was given |
8072 |
-+ * @items: Additional items for this command |
8073 |
-+ */ |
8074 |
-+struct kdbus_cmd_send { |
8075 |
-+ __u64 size; |
8076 |
-+ __u64 flags; |
8077 |
-+ __u64 return_flags; |
8078 |
-+ __u64 msg_address; |
8079 |
-+ struct kdbus_msg_info reply; |
8080 |
-+ struct kdbus_item items[0]; |
8081 |
-+} __attribute__((__aligned__(8))); |
8082 |
-+ |
8083 |
-+/** |
8084 |
-+ * enum kdbus_recv_flags - flags for de-queuing messages |
8085 |
-+ * @KDBUS_RECV_PEEK: Return the next queued message without |
8086 |
-+ * actually de-queuing it, and without installing |
8087 |
-+ * any file descriptors or other resources. It is |
8088 |
-+ * usually used to determine the activating |
8089 |
-+ * connection of a bus name. |
8090 |
-+ * @KDBUS_RECV_DROP: Drop and free the next queued message and all |
8091 |
-+ * its resources without actually receiving it. |
8092 |
-+ * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or |
8093 |
-+ * higher priority (lowest values); if not set, |
8094 |
-+ * the priority value is ignored. |
8095 |
-+ */ |
8096 |
-+enum kdbus_recv_flags { |
8097 |
-+ KDBUS_RECV_PEEK = 1ULL << 0, |
8098 |
-+ KDBUS_RECV_DROP = 1ULL << 1, |
8099 |
-+ KDBUS_RECV_USE_PRIORITY = 1ULL << 2, |
8100 |
-+}; |
8101 |
-+ |
8102 |
-+/** |
8103 |
-+ * enum kdbus_recv_return_flags - return flags for message receive commands |
8104 |
-+ * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not |
8105 |
-+ * be installed. These descriptors in |
8106 |
-+ * KDBUS_ITEM_FDS will carry the value -1. |
8107 |
-+ * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since |
8108 |
-+ * the last time a message was received. |
8109 |
-+ * The 'dropped_msgs' counter contains the |
8110 |
-+ * number of messages dropped pool |
8111 |
-+ * overflows or other missed broadcasts. |
8112 |
-+ */ |
8113 |
-+enum kdbus_recv_return_flags { |
8114 |
-+ KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0, |
8115 |
-+ KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1, |
8116 |
-+}; |
8117 |
-+ |
8118 |
-+/** |
8119 |
-+ * struct kdbus_cmd_recv - struct to de-queue a buffered message |
8120 |
-+ * @size: Overall size of this object |
8121 |
-+ * @flags: KDBUS_RECV_* flags, userspace → kernel |
8122 |
-+ * @return_flags: Command return flags, kernel → userspace |
8123 |
-+ * @priority: Minimum priority of the messages to de-queue. Lowest |
8124 |
-+ * values have the highest priority. |
8125 |
-+ * @dropped_msgs: In case there were any dropped messages since the last |
8126 |
-+ * time a message was received, this will be set to the |
8127 |
-+ * number of lost messages and |
8128 |
-+ * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in |
8129 |
-+ * 'return_flags'. This can only happen if the ioctl |
8130 |
-+ * returns 0 or EAGAIN. |
8131 |
-+ * @msg: Return storage for received message. |
8132 |
-+ * @items: Additional items for this command. |
8133 |
-+ * |
8134 |
-+ * This struct is used with the KDBUS_CMD_RECV ioctl. |
8135 |
-+ */ |
8136 |
-+struct kdbus_cmd_recv { |
8137 |
-+ __u64 size; |
8138 |
-+ __u64 flags; |
8139 |
-+ __u64 return_flags; |
8140 |
-+ __s64 priority; |
8141 |
-+ __u64 dropped_msgs; |
8142 |
-+ struct kdbus_msg_info msg; |
8143 |
-+ struct kdbus_item items[0]; |
8144 |
-+} __attribute__((__aligned__(8))); |
8145 |
-+ |
8146 |
-+/** |
8147 |
-+ * struct kdbus_cmd_free - struct to free a slice of memory in the pool |
8148 |
-+ * @size: Overall size of this structure |
8149 |
-+ * @flags: Flags for the free command, userspace → kernel |
8150 |
-+ * @return_flags: Command return flags, kernel → userspace |
8151 |
-+ * @offset: The offset of the memory slice, as returned by other |
8152 |
-+ * ioctls |
8153 |
-+ * @items: Additional items to modify the behavior |
8154 |
-+ * |
8155 |
-+ * This struct is used with the KDBUS_CMD_FREE ioctl. |
8156 |
-+ */ |
8157 |
-+struct kdbus_cmd_free { |
8158 |
-+ __u64 size; |
8159 |
-+ __u64 flags; |
8160 |
-+ __u64 return_flags; |
8161 |
-+ __u64 offset; |
8162 |
-+ struct kdbus_item items[0]; |
8163 |
-+} __attribute__((__aligned__(8))); |
8164 |
-+ |
8165 |
-+/** |
8166 |
-+ * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello |
8167 |
-+ * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of |
8168 |
-+ * any passed file descriptors |
8169 |
-+ * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers |
8170 |
-+ * a well-know name for a process to be started |
8171 |
-+ * when traffic arrives |
8172 |
-+ * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers |
8173 |
-+ * policy entries for a name. The provided name |
8174 |
-+ * is not activated and not registered with the |
8175 |
-+ * name database, it only allows unprivileged |
8176 |
-+ * connections to acquire a name, talk or discover |
8177 |
-+ * a service |
8178 |
-+ * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor |
8179 |
-+ * bus traffic |
8180 |
-+ */ |
8181 |
-+enum kdbus_hello_flags { |
8182 |
-+ KDBUS_HELLO_ACCEPT_FD = 1ULL << 0, |
8183 |
-+ KDBUS_HELLO_ACTIVATOR = 1ULL << 1, |
8184 |
-+ KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2, |
8185 |
-+ KDBUS_HELLO_MONITOR = 1ULL << 3, |
8186 |
-+}; |
8187 |
-+ |
8188 |
-+/** |
8189 |
-+ * struct kdbus_cmd_hello - struct to say hello to kdbus |
8190 |
-+ * @size: The total size of the structure |
8191 |
-+ * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel |
8192 |
-+ * @return_flags: Command return flags, kernel → userspace |
8193 |
-+ * @attach_flags_send: Mask of metadata to attach to each message sent |
8194 |
-+ * off by this connection (KDBUS_ATTACH_*) |
8195 |
-+ * @attach_flags_recv: Mask of metadata to attach to each message receieved |
8196 |
-+ * by the new connection (KDBUS_ATTACH_*) |
8197 |
-+ * @bus_flags: The flags field copied verbatim from the original |
8198 |
-+ * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful |
8199 |
-+ * to do negotiation of features of the payload that is |
8200 |
-+ * transferred (kernel → userspace) |
8201 |
-+ * @id: The ID of this connection (kernel → userspace) |
8202 |
-+ * @pool_size: Size of the connection's buffer where the received |
8203 |
-+ * messages are placed |
8204 |
-+ * @offset: Pool offset where items are returned to report |
8205 |
-+ * additional information about the bus and the newly |
8206 |
-+ * created connection. |
8207 |
-+ * @items_size: Size of buffer returned in the pool slice at @offset. |
8208 |
-+ * @id128: Unique 128-bit ID of the bus (kernel → userspace) |
8209 |
-+ * @items: A list of items |
8210 |
-+ * |
8211 |
-+ * This struct is used with the KDBUS_CMD_HELLO ioctl. |
8212 |
-+ */ |
8213 |
-+struct kdbus_cmd_hello { |
8214 |
-+ __u64 size; |
8215 |
-+ __u64 flags; |
8216 |
-+ __u64 return_flags; |
8217 |
-+ __u64 attach_flags_send; |
8218 |
-+ __u64 attach_flags_recv; |
8219 |
-+ __u64 bus_flags; |
8220 |
-+ __u64 id; |
8221 |
-+ __u64 pool_size; |
8222 |
-+ __u64 offset; |
8223 |
-+ __u64 items_size; |
8224 |
-+ __u8 id128[16]; |
8225 |
-+ struct kdbus_item items[0]; |
8226 |
-+} __attribute__((__aligned__(8))); |
8227 |
-+ |
8228 |
-+/** |
8229 |
-+ * struct kdbus_info - connection information |
8230 |
-+ * @size: total size of the struct |
8231 |
-+ * @id: 64bit object ID |
8232 |
-+ * @flags: object creation flags |
8233 |
-+ * @items: list of items |
8234 |
-+ * |
8235 |
-+ * Note that the user is responsible for freeing the allocated memory with |
8236 |
-+ * the KDBUS_CMD_FREE ioctl. |
8237 |
-+ */ |
8238 |
-+struct kdbus_info { |
8239 |
-+ __u64 size; |
8240 |
-+ __u64 id; |
8241 |
-+ __u64 flags; |
8242 |
-+ struct kdbus_item items[0]; |
8243 |
-+} __attribute__((__aligned__(8))); |
8244 |
-+ |
8245 |
-+/** |
8246 |
-+ * enum kdbus_list_flags - what to include into the returned list |
8247 |
-+ * @KDBUS_LIST_UNIQUE: active connections |
8248 |
-+ * @KDBUS_LIST_ACTIVATORS: activator connections |
8249 |
-+ * @KDBUS_LIST_NAMES: known well-known names |
8250 |
-+ * @KDBUS_LIST_QUEUED: queued-up names |
8251 |
-+ */ |
8252 |
-+enum kdbus_list_flags { |
8253 |
-+ KDBUS_LIST_UNIQUE = 1ULL << 0, |
8254 |
-+ KDBUS_LIST_NAMES = 1ULL << 1, |
8255 |
-+ KDBUS_LIST_ACTIVATORS = 1ULL << 2, |
8256 |
-+ KDBUS_LIST_QUEUED = 1ULL << 3, |
8257 |
-+}; |
8258 |
-+ |
8259 |
-+/** |
8260 |
-+ * struct kdbus_cmd_list - list connections |
8261 |
-+ * @size: overall size of this object |
8262 |
-+ * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel |
8263 |
-+ * @return_flags: command return flags, kernel → userspace |
8264 |
-+ * @offset: Offset in the caller's pool buffer where an array of |
8265 |
-+ * kdbus_info objects is stored. |
8266 |
-+ * The user must use KDBUS_CMD_FREE to free the |
8267 |
-+ * allocated memory. |
8268 |
-+ * @list_size: size of returned list in bytes |
8269 |
-+ * @items: Items for the command. Reserved for future use. |
8270 |
-+ * |
8271 |
-+ * This structure is used with the KDBUS_CMD_LIST ioctl. |
8272 |
-+ */ |
8273 |
-+struct kdbus_cmd_list { |
8274 |
-+ __u64 size; |
8275 |
-+ __u64 flags; |
8276 |
-+ __u64 return_flags; |
8277 |
-+ __u64 offset; |
8278 |
-+ __u64 list_size; |
8279 |
-+ struct kdbus_item items[0]; |
8280 |
-+} __attribute__((__aligned__(8))); |
8281 |
-+ |
8282 |
-+/** |
8283 |
-+ * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl |
8284 |
-+ * @size: The total size of the struct |
8285 |
-+ * @flags: Flags for this ioctl, userspace → kernel |
8286 |
-+ * @return_flags: Command return flags, kernel → userspace |
8287 |
-+ * @id: The 64-bit ID of the connection. If set to zero, passing |
8288 |
-+ * @name is required. kdbus will look up the name to |
8289 |
-+ * determine the ID in this case. |
8290 |
-+ * @attach_flags: Set of attach flags to specify the set of information |
8291 |
-+ * to receive, userspace → kernel |
8292 |
-+ * @offset: Returned offset in the caller's pool buffer where the |
8293 |
-+ * kdbus_info struct result is stored. The user must |
8294 |
-+ * use KDBUS_CMD_FREE to free the allocated memory. |
8295 |
-+ * @info_size: Output buffer to report size of data at @offset. |
8296 |
-+ * @items: The optional item list, containing the |
8297 |
-+ * well-known name to look up as a KDBUS_ITEM_NAME. |
8298 |
-+ * Only needed in case @id is zero. |
8299 |
-+ * |
8300 |
-+ * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will |
8301 |
-+ * tell the user the offset in the connection pool buffer at which to find the |
8302 |
-+ * result in a struct kdbus_info. |
8303 |
-+ */ |
8304 |
-+struct kdbus_cmd_info { |
8305 |
-+ __u64 size; |
8306 |
-+ __u64 flags; |
8307 |
-+ __u64 return_flags; |
8308 |
-+ __u64 id; |
8309 |
-+ __u64 attach_flags; |
8310 |
-+ __u64 offset; |
8311 |
-+ __u64 info_size; |
8312 |
-+ struct kdbus_item items[0]; |
8313 |
-+} __attribute__((__aligned__(8))); |
8314 |
-+ |
8315 |
-+/** |
8316 |
-+ * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl |
8317 |
-+ * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already |
8318 |
-+ * exists, remove them before installing the new |
8319 |
-+ * matches. |
8320 |
-+ */ |
8321 |
-+enum kdbus_cmd_match_flags { |
8322 |
-+ KDBUS_MATCH_REPLACE = 1ULL << 0, |
8323 |
-+}; |
8324 |
-+ |
8325 |
-+/** |
8326 |
-+ * struct kdbus_cmd_match - struct to add or remove matches |
8327 |
-+ * @size: The total size of the struct |
8328 |
-+ * @flags: Flags for match command (KDBUS_MATCH_*), |
8329 |
-+ * userspace → kernel |
8330 |
-+ * @return_flags: Command return flags, kernel → userspace |
8331 |
-+ * @cookie: Userspace supplied cookie. When removing, the cookie |
8332 |
-+ * identifies the match to remove |
8333 |
-+ * @items: A list of items for additional information |
8334 |
-+ * |
8335 |
-+ * This structure is used with the KDBUS_CMD_MATCH_ADD and |
8336 |
-+ * KDBUS_CMD_MATCH_REMOVE ioctl. |
8337 |
-+ */ |
8338 |
-+struct kdbus_cmd_match { |
8339 |
-+ __u64 size; |
8340 |
-+ __u64 flags; |
8341 |
-+ __u64 return_flags; |
8342 |
-+ __u64 cookie; |
8343 |
-+ struct kdbus_item items[0]; |
8344 |
-+} __attribute__((__aligned__(8))); |
8345 |
-+ |
8346 |
-+/** |
8347 |
-+ * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE |
8348 |
-+ * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible |
8349 |
-+ * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible |
8350 |
-+ */ |
8351 |
-+enum kdbus_make_flags { |
8352 |
-+ KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0, |
8353 |
-+ KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1, |
8354 |
-+}; |
8355 |
-+ |
8356 |
-+/** |
8357 |
-+ * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE |
8358 |
-+ * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections |
8359 |
-+ * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name |
8360 |
-+ * @KDBUS_NAME_QUEUE: Name should be queued if busy |
8361 |
-+ * @KDBUS_NAME_IN_QUEUE: Name is queued |
8362 |
-+ * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection |
8363 |
-+ * @KDBUS_NAME_PRIMARY: Primary owner of the name |
8364 |
-+ * @KDBUS_NAME_ACQUIRED: Name was acquired/queued _now_ |
8365 |
-+ */ |
8366 |
-+enum kdbus_name_flags { |
8367 |
-+ KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0, |
8368 |
-+ KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1, |
8369 |
-+ KDBUS_NAME_QUEUE = 1ULL << 2, |
8370 |
-+ KDBUS_NAME_IN_QUEUE = 1ULL << 3, |
8371 |
-+ KDBUS_NAME_ACTIVATOR = 1ULL << 4, |
8372 |
-+ KDBUS_NAME_PRIMARY = 1ULL << 5, |
8373 |
-+ KDBUS_NAME_ACQUIRED = 1ULL << 6, |
8374 |
-+}; |
8375 |
-+ |
8376 |
-+/** |
8377 |
-+ * struct kdbus_cmd - generic ioctl payload |
8378 |
-+ * @size: Overall size of this structure |
8379 |
-+ * @flags: Flags for this ioctl, userspace → kernel |
8380 |
-+ * @return_flags: Ioctl return flags, kernel → userspace |
8381 |
-+ * @items: Additional items to modify the behavior |
8382 |
-+ * |
8383 |
-+ * This is a generic ioctl payload object. It's used by all ioctls that only |
8384 |
-+ * take flags and items as input. |
8385 |
-+ */ |
8386 |
-+struct kdbus_cmd { |
8387 |
-+ __u64 size; |
8388 |
-+ __u64 flags; |
8389 |
-+ __u64 return_flags; |
8390 |
-+ struct kdbus_item items[0]; |
8391 |
-+} __attribute__((__aligned__(8))); |
8392 |
-+ |
8393 |
-+/** |
8394 |
-+ * Ioctl API |
8395 |
-+ * |
8396 |
-+ * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command |
8397 |
-+ * creates a new bus with the specified |
8398 |
-+ * name. The bus is immediately shut down and |
8399 |
-+ * cleaned up when the opened file descriptor is |
8400 |
-+ * closed. |
8401 |
-+ * |
8402 |
-+ * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to |
8403 |
-+ * the bus. Such endpoints usually carry a more |
8404 |
-+ * restrictive policy and grant restricted access |
8405 |
-+ * to specific applications. |
8406 |
-+ * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used |
8407 |
-+ * to update the policy. |
8408 |
-+ * |
8409 |
-+ * KDBUS_CMD_HELLO: By opening the bus node, a connection is |
8410 |
-+ * created. After a HELLO the opened connection |
8411 |
-+ * becomes an active peer on the bus. |
8412 |
-+ * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to |
8413 |
-+ * update the metadata subscription mask and |
8414 |
-+ * policy. |
8415 |
-+ * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no |
8416 |
-+ * messages queued up in the connection's pool, |
8417 |
-+ * the call succeeds, and the handle is rendered |
8418 |
-+ * unusable. Otherwise, -EBUSY is returned without |
8419 |
-+ * any further side-effects. |
8420 |
-+ * KDBUS_CMD_FREE: Release the allocated memory in the receiver's |
8421 |
-+ * pool. |
8422 |
-+ * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the |
8423 |
-+ * initial creator of the connection. The data was |
8424 |
-+ * stored at registration time and does not |
8425 |
-+ * necessarily represent the connected process or |
8426 |
-+ * the actual state of the process. |
8427 |
-+ * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus |
8428 |
-+ * a connection is attached to. |
8429 |
-+ * |
8430 |
-+ * KDBUS_CMD_SEND: Send a message and pass data from userspace to |
8431 |
-+ * the kernel. |
8432 |
-+ * KDBUS_CMD_RECV: Receive a message from the kernel which is |
8433 |
-+ * placed in the receiver's pool. |
8434 |
-+ * |
8435 |
-+ * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with |
8436 |
-+ * the connection. Well-known names are used to |
8437 |
-+ * address a peer on the bus. |
8438 |
-+ * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection |
8439 |
-+ * currently owns. |
8440 |
-+ * KDBUS_CMD_LIST: Retrieve the list of all currently registered |
8441 |
-+ * well-known and unique names. |
8442 |
-+ * |
8443 |
-+ * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should |
8444 |
-+ * be delivered to the connection. |
8445 |
-+ * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages. |
8446 |
-+ */ |
8447 |
-+enum kdbus_ioctl_type { |
8448 |
-+ /* bus owner (00-0f) */ |
8449 |
-+ KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00, |
8450 |
-+ struct kdbus_cmd), |
8451 |
-+ |
8452 |
-+ /* endpoint owner (10-1f) */ |
8453 |
-+ KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10, |
8454 |
-+ struct kdbus_cmd), |
8455 |
-+ KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11, |
8456 |
-+ struct kdbus_cmd), |
8457 |
-+ |
8458 |
-+ /* connection owner (80-ff) */ |
8459 |
-+ KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80, |
8460 |
-+ struct kdbus_cmd_hello), |
8461 |
-+ KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81, |
8462 |
-+ struct kdbus_cmd), |
8463 |
-+ KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82, |
8464 |
-+ struct kdbus_cmd), |
8465 |
-+ KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83, |
8466 |
-+ struct kdbus_cmd_free), |
8467 |
-+ KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84, |
8468 |
-+ struct kdbus_cmd_info), |
8469 |
-+ KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85, |
8470 |
-+ struct kdbus_cmd_info), |
8471 |
-+ KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86, |
8472 |
-+ struct kdbus_cmd_list), |
8473 |
-+ |
8474 |
-+ KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90, |
8475 |
-+ struct kdbus_cmd_send), |
8476 |
-+ KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91, |
8477 |
-+ struct kdbus_cmd_recv), |
8478 |
-+ |
8479 |
-+ KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0, |
8480 |
-+ struct kdbus_cmd), |
8481 |
-+ KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1, |
8482 |
-+ struct kdbus_cmd), |
8483 |
-+ |
8484 |
-+ KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0, |
8485 |
-+ struct kdbus_cmd_match), |
8486 |
-+ KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1, |
8487 |
-+ struct kdbus_cmd_match), |
8488 |
-+}; |
8489 |
-+ |
8490 |
-+#endif /* _UAPI_KDBUS_H_ */ |
8491 |
-diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h |
8492 |
-index 7b1425a..ce2ac5a 100644 |
8493 |
---- a/include/uapi/linux/magic.h |
8494 |
-+++ b/include/uapi/linux/magic.h |
8495 |
-@@ -76,4 +76,6 @@ |
8496 |
- #define BTRFS_TEST_MAGIC 0x73727279 |
8497 |
- #define NSFS_MAGIC 0x6e736673 |
8498 |
- |
8499 |
-+#define KDBUS_SUPER_MAGIC 0x44427573 |
8500 |
-+ |
8501 |
- #endif /* __LINUX_MAGIC_H__ */ |
8502 |
-diff --git a/init/Kconfig b/init/Kconfig |
8503 |
-index dc24dec..9388071 100644 |
8504 |
---- a/init/Kconfig |
8505 |
-+++ b/init/Kconfig |
8506 |
-@@ -261,6 +261,19 @@ config POSIX_MQUEUE_SYSCTL |
8507 |
- depends on SYSCTL |
8508 |
- default y |
8509 |
- |
8510 |
-+config KDBUS |
8511 |
-+ tristate "kdbus interprocess communication" |
8512 |
-+ depends on TMPFS |
8513 |
-+ help |
8514 |
-+ D-Bus is a system for low-latency, low-overhead, easy to use |
8515 |
-+ interprocess communication (IPC). |
8516 |
-+ |
8517 |
-+ See the man-pages and HTML files in Documentation/kdbus/ |
8518 |
-+ that are generated by 'make mandocs' and 'make htmldocs'. |
8519 |
-+ |
8520 |
-+ If you have an ordinary machine, select M here. The module |
8521 |
-+ will be called kdbus. |
8522 |
-+ |
8523 |
- config CROSS_MEMORY_ATTACH |
8524 |
- bool "Enable process_vm_readv/writev syscalls" |
8525 |
- depends on MMU |
8526 |
-diff --git a/ipc/Makefile b/ipc/Makefile |
8527 |
-index 86c7300..68ec416 100644 |
8528 |
---- a/ipc/Makefile |
8529 |
-+++ b/ipc/Makefile |
8530 |
-@@ -9,4 +9,4 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
8531 |
- obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
8532 |
- obj-$(CONFIG_IPC_NS) += namespace.o |
8533 |
- obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o |
8534 |
-- |
8535 |
-+obj-$(CONFIG_KDBUS) += kdbus/ |
8536 |
-diff --git a/ipc/kdbus/Makefile b/ipc/kdbus/Makefile |
8537 |
-new file mode 100644 |
8538 |
-index 0000000..66663a1 |
8539 |
---- /dev/null |
8540 |
-+++ b/ipc/kdbus/Makefile |
8541 |
-@@ -0,0 +1,33 @@ |
8542 |
-+# |
8543 |
-+# By setting KDBUS_EXT=2, the kdbus module will be built as kdbus2.ko, and |
8544 |
-+# KBUILD_MODNAME=kdbus2. This has the effect that all exported objects have |
8545 |
-+# different names than usually (kdbus2fs, /sys/fs/kdbus2/) and you can run |
8546 |
-+# your test-infrastructure against the kdbus2.ko, while running your system |
8547 |
-+# on kdbus.ko. |
8548 |
-+# |
8549 |
-+# To just build the module, use: |
8550 |
-+# make KDBUS_EXT=2 M=ipc/kdbus |
8551 |
-+# |
8552 |
-+ |
8553 |
-+kdbus$(KDBUS_EXT)-y := \ |
8554 |
-+ bus.o \ |
8555 |
-+ connection.o \ |
8556 |
-+ endpoint.o \ |
8557 |
-+ fs.o \ |
8558 |
-+ handle.o \ |
8559 |
-+ item.o \ |
8560 |
-+ main.o \ |
8561 |
-+ match.o \ |
8562 |
-+ message.o \ |
8563 |
-+ metadata.o \ |
8564 |
-+ names.o \ |
8565 |
-+ node.o \ |
8566 |
-+ notify.o \ |
8567 |
-+ domain.o \ |
8568 |
-+ policy.o \ |
8569 |
-+ pool.o \ |
8570 |
-+ reply.o \ |
8571 |
-+ queue.o \ |
8572 |
-+ util.o |
8573 |
-+ |
8574 |
-+obj-$(CONFIG_KDBUS) += kdbus$(KDBUS_EXT).o |
8575 |
-diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c |
8576 |
-new file mode 100644 |
8577 |
-index 0000000..a67f825 |
8578 |
---- /dev/null |
8579 |
-+++ b/ipc/kdbus/bus.c |
8580 |
-@@ -0,0 +1,514 @@ |
8581 |
-+/* |
8582 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
8583 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
8584 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
8585 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
8586 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
8587 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
8588 |
-+ * |
8589 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
8590 |
-+ * the terms of the GNU Lesser General Public License as published by the |
8591 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
8592 |
-+ * your option) any later version. |
8593 |
-+ */ |
8594 |
-+ |
8595 |
-+#include <linux/fs.h> |
8596 |
-+#include <linux/hashtable.h> |
8597 |
-+#include <linux/init.h> |
8598 |
-+#include <linux/module.h> |
8599 |
-+#include <linux/random.h> |
8600 |
-+#include <linux/sched.h> |
8601 |
-+#include <linux/sizes.h> |
8602 |
-+#include <linux/slab.h> |
8603 |
-+#include <linux/uaccess.h> |
8604 |
-+#include <linux/uio.h> |
8605 |
-+ |
8606 |
-+#include "bus.h" |
8607 |
-+#include "notify.h" |
8608 |
-+#include "connection.h" |
8609 |
-+#include "domain.h" |
8610 |
-+#include "endpoint.h" |
8611 |
-+#include "handle.h" |
8612 |
-+#include "item.h" |
8613 |
-+#include "match.h" |
8614 |
-+#include "message.h" |
8615 |
-+#include "metadata.h" |
8616 |
-+#include "names.h" |
8617 |
-+#include "policy.h" |
8618 |
-+#include "util.h" |
8619 |
-+ |
8620 |
-+static void kdbus_bus_free(struct kdbus_node *node) |
8621 |
-+{ |
8622 |
-+ struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node); |
8623 |
-+ |
8624 |
-+ WARN_ON(!list_empty(&bus->monitors_list)); |
8625 |
-+ WARN_ON(!hash_empty(bus->conn_hash)); |
8626 |
-+ |
8627 |
-+ kdbus_notify_free(bus); |
8628 |
-+ |
8629 |
-+ kdbus_user_unref(bus->creator); |
8630 |
-+ kdbus_name_registry_free(bus->name_registry); |
8631 |
-+ kdbus_domain_unref(bus->domain); |
8632 |
-+ kdbus_policy_db_clear(&bus->policy_db); |
8633 |
-+ kdbus_meta_proc_unref(bus->creator_meta); |
8634 |
-+ kfree(bus); |
8635 |
-+} |
8636 |
-+ |
8637 |
-+static void kdbus_bus_release(struct kdbus_node *node, bool was_active) |
8638 |
-+{ |
8639 |
-+ struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node); |
8640 |
-+ |
8641 |
-+ if (was_active) |
8642 |
-+ atomic_dec(&bus->creator->buses); |
8643 |
-+} |
8644 |
-+ |
8645 |
-+static struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain, |
8646 |
-+ const char *name, |
8647 |
-+ struct kdbus_bloom_parameter *bloom, |
8648 |
-+ const u64 *pattach_owner, |
8649 |
-+ u64 flags, kuid_t uid, kgid_t gid) |
8650 |
-+{ |
8651 |
-+ struct kdbus_bus *b; |
8652 |
-+ u64 attach_owner; |
8653 |
-+ int ret; |
8654 |
-+ |
8655 |
-+ if (bloom->size < 8 || bloom->size > KDBUS_BUS_BLOOM_MAX_SIZE || |
8656 |
-+ !KDBUS_IS_ALIGNED8(bloom->size) || bloom->n_hash < 1) |
8657 |
-+ return ERR_PTR(-EINVAL); |
8658 |
-+ |
8659 |
-+ ret = kdbus_sanitize_attach_flags(pattach_owner ? *pattach_owner : 0, |
8660 |
-+ &attach_owner); |
8661 |
-+ if (ret < 0) |
8662 |
-+ return ERR_PTR(ret); |
8663 |
-+ |
8664 |
-+ ret = kdbus_verify_uid_prefix(name, domain->user_namespace, uid); |
8665 |
-+ if (ret < 0) |
8666 |
-+ return ERR_PTR(ret); |
8667 |
-+ |
8668 |
-+ b = kzalloc(sizeof(*b), GFP_KERNEL); |
8669 |
-+ if (!b) |
8670 |
-+ return ERR_PTR(-ENOMEM); |
8671 |
-+ |
8672 |
-+ kdbus_node_init(&b->node, KDBUS_NODE_BUS); |
8673 |
-+ |
8674 |
-+ b->node.free_cb = kdbus_bus_free; |
8675 |
-+ b->node.release_cb = kdbus_bus_release; |
8676 |
-+ b->node.uid = uid; |
8677 |
-+ b->node.gid = gid; |
8678 |
-+ b->node.mode = S_IRUSR | S_IXUSR; |
8679 |
-+ |
8680 |
-+ if (flags & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
8681 |
-+ b->node.mode |= S_IRGRP | S_IXGRP; |
8682 |
-+ if (flags & KDBUS_MAKE_ACCESS_WORLD) |
8683 |
-+ b->node.mode |= S_IROTH | S_IXOTH; |
8684 |
-+ |
8685 |
-+ b->id = atomic64_inc_return(&domain->last_id); |
8686 |
-+ b->bus_flags = flags; |
8687 |
-+ b->attach_flags_owner = attach_owner; |
8688 |
-+ generate_random_uuid(b->id128); |
8689 |
-+ b->bloom = *bloom; |
8690 |
-+ b->domain = kdbus_domain_ref(domain); |
8691 |
-+ |
8692 |
-+ kdbus_policy_db_init(&b->policy_db); |
8693 |
-+ |
8694 |
-+ init_rwsem(&b->conn_rwlock); |
8695 |
-+ hash_init(b->conn_hash); |
8696 |
-+ INIT_LIST_HEAD(&b->monitors_list); |
8697 |
-+ |
8698 |
-+ INIT_LIST_HEAD(&b->notify_list); |
8699 |
-+ spin_lock_init(&b->notify_lock); |
8700 |
-+ mutex_init(&b->notify_flush_lock); |
8701 |
-+ |
8702 |
-+ ret = kdbus_node_link(&b->node, &domain->node, name); |
8703 |
-+ if (ret < 0) |
8704 |
-+ goto exit_unref; |
8705 |
-+ |
8706 |
-+ /* cache the metadata/credentials of the creator */ |
8707 |
-+ b->creator_meta = kdbus_meta_proc_new(); |
8708 |
-+ if (IS_ERR(b->creator_meta)) { |
8709 |
-+ ret = PTR_ERR(b->creator_meta); |
8710 |
-+ b->creator_meta = NULL; |
8711 |
-+ goto exit_unref; |
8712 |
-+ } |
8713 |
-+ |
8714 |
-+ ret = kdbus_meta_proc_collect(b->creator_meta, |
8715 |
-+ KDBUS_ATTACH_CREDS | |
8716 |
-+ KDBUS_ATTACH_PIDS | |
8717 |
-+ KDBUS_ATTACH_AUXGROUPS | |
8718 |
-+ KDBUS_ATTACH_TID_COMM | |
8719 |
-+ KDBUS_ATTACH_PID_COMM | |
8720 |
-+ KDBUS_ATTACH_EXE | |
8721 |
-+ KDBUS_ATTACH_CMDLINE | |
8722 |
-+ KDBUS_ATTACH_CGROUP | |
8723 |
-+ KDBUS_ATTACH_CAPS | |
8724 |
-+ KDBUS_ATTACH_SECLABEL | |
8725 |
-+ KDBUS_ATTACH_AUDIT); |
8726 |
-+ if (ret < 0) |
8727 |
-+ goto exit_unref; |
8728 |
-+ |
8729 |
-+ b->name_registry = kdbus_name_registry_new(); |
8730 |
-+ if (IS_ERR(b->name_registry)) { |
8731 |
-+ ret = PTR_ERR(b->name_registry); |
8732 |
-+ b->name_registry = NULL; |
8733 |
-+ goto exit_unref; |
8734 |
-+ } |
8735 |
-+ |
8736 |
-+ /* |
8737 |
-+ * Bus-limits of the creator are accounted on its real UID, just like |
8738 |
-+ * all other per-user limits. |
8739 |
-+ */ |
8740 |
-+ b->creator = kdbus_user_lookup(domain, current_uid()); |
8741 |
-+ if (IS_ERR(b->creator)) { |
8742 |
-+ ret = PTR_ERR(b->creator); |
8743 |
-+ b->creator = NULL; |
8744 |
-+ goto exit_unref; |
8745 |
-+ } |
8746 |
-+ |
8747 |
-+ return b; |
8748 |
-+ |
8749 |
-+exit_unref: |
8750 |
-+ kdbus_node_deactivate(&b->node); |
8751 |
-+ kdbus_node_unref(&b->node); |
8752 |
-+ return ERR_PTR(ret); |
8753 |
-+} |
8754 |
-+ |
8755 |
-+/** |
8756 |
-+ * kdbus_bus_ref() - increase the reference counter of a kdbus_bus |
8757 |
-+ * @bus: The bus to reference |
8758 |
-+ * |
8759 |
-+ * Every user of a bus, except for its creator, must add a reference to the |
8760 |
-+ * kdbus_bus using this function. |
8761 |
-+ * |
8762 |
-+ * Return: the bus itself |
8763 |
-+ */ |
8764 |
-+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus) |
8765 |
-+{ |
8766 |
-+ if (bus) |
8767 |
-+ kdbus_node_ref(&bus->node); |
8768 |
-+ return bus; |
8769 |
-+} |
8770 |
-+ |
8771 |
-+/** |
8772 |
-+ * kdbus_bus_unref() - decrease the reference counter of a kdbus_bus |
8773 |
-+ * @bus: The bus to unref |
8774 |
-+ * |
8775 |
-+ * Release a reference. If the reference count drops to 0, the bus will be |
8776 |
-+ * freed. |
8777 |
-+ * |
8778 |
-+ * Return: NULL |
8779 |
-+ */ |
8780 |
-+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus) |
8781 |
-+{ |
8782 |
-+ if (bus) |
8783 |
-+ kdbus_node_unref(&bus->node); |
8784 |
-+ return NULL; |
8785 |
-+} |
8786 |
-+ |
8787 |
-+/** |
8788 |
-+ * kdbus_bus_find_conn_by_id() - find a connection with a given id |
8789 |
-+ * @bus: The bus to look for the connection |
8790 |
-+ * @id: The 64-bit connection id |
8791 |
-+ * |
8792 |
-+ * Looks up a connection with a given id. The returned connection |
8793 |
-+ * is ref'ed, and needs to be unref'ed by the user. Returns NULL if |
8794 |
-+ * the connection can't be found. |
8795 |
-+ */ |
8796 |
-+struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id) |
8797 |
-+{ |
8798 |
-+ struct kdbus_conn *conn, *found = NULL; |
8799 |
-+ |
8800 |
-+ down_read(&bus->conn_rwlock); |
8801 |
-+ hash_for_each_possible(bus->conn_hash, conn, hentry, id) |
8802 |
-+ if (conn->id == id) { |
8803 |
-+ found = kdbus_conn_ref(conn); |
8804 |
-+ break; |
8805 |
-+ } |
8806 |
-+ up_read(&bus->conn_rwlock); |
8807 |
-+ |
8808 |
-+ return found; |
8809 |
-+} |
8810 |
-+ |
8811 |
-+/** |
8812 |
-+ * kdbus_bus_broadcast() - send a message to all subscribed connections |
8813 |
-+ * @bus: The bus the connections are connected to |
8814 |
-+ * @conn_src: The source connection, may be %NULL for kernel notifications |
8815 |
-+ * @staging: Staging object containing the message to send |
8816 |
-+ * |
8817 |
-+ * Send message to all connections that are currently active on the bus. |
8818 |
-+ * Connections must still have matches installed in order to let the message |
8819 |
-+ * pass. |
8820 |
-+ * |
8821 |
-+ * The caller must hold the name-registry lock of @bus. |
8822 |
-+ */ |
8823 |
-+void kdbus_bus_broadcast(struct kdbus_bus *bus, |
8824 |
-+ struct kdbus_conn *conn_src, |
8825 |
-+ struct kdbus_staging *staging) |
8826 |
-+{ |
8827 |
-+ struct kdbus_conn *conn_dst; |
8828 |
-+ unsigned int i; |
8829 |
-+ int ret; |
8830 |
-+ |
8831 |
-+ lockdep_assert_held(&bus->name_registry->rwlock); |
8832 |
-+ |
8833 |
-+ /* |
8834 |
-+ * Make sure broadcast are queued on monitors before we send it out to |
8835 |
-+ * anyone else. Otherwise, connections might react to broadcasts before |
8836 |
-+ * the monitor gets the broadcast queued. In the worst case, the |
8837 |
-+ * monitor sees a reaction to the broadcast before the broadcast itself. |
8838 |
-+ * We don't give ordering guarantees across connections (and monitors |
8839 |
-+ * can re-construct order via sequence numbers), but we should at least |
8840 |
-+ * try to avoid re-ordering for monitors. |
8841 |
-+ */ |
8842 |
-+ kdbus_bus_eavesdrop(bus, conn_src, staging); |
8843 |
-+ |
8844 |
-+ down_read(&bus->conn_rwlock); |
8845 |
-+ hash_for_each(bus->conn_hash, i, conn_dst, hentry) { |
8846 |
-+ if (!kdbus_conn_is_ordinary(conn_dst)) |
8847 |
-+ continue; |
8848 |
-+ |
8849 |
-+ /* |
8850 |
-+ * Check if there is a match for the kmsg object in |
8851 |
-+ * the destination connection match db |
8852 |
-+ */ |
8853 |
-+ if (!kdbus_match_db_match_msg(conn_dst->match_db, conn_src, |
8854 |
-+ staging)) |
8855 |
-+ continue; |
8856 |
-+ |
8857 |
-+ if (conn_src) { |
8858 |
-+ /* |
8859 |
-+ * Anyone can send broadcasts, as they have no |
8860 |
-+ * destination. But a receiver needs TALK access to |
8861 |
-+ * the sender in order to receive broadcasts. |
8862 |
-+ */ |
8863 |
-+ if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src)) |
8864 |
-+ continue; |
8865 |
-+ } else { |
8866 |
-+ /* |
8867 |
-+ * Check if there is a policy db that prevents the |
8868 |
-+ * destination connection from receiving this kernel |
8869 |
-+ * notification |
8870 |
-+ */ |
8871 |
-+ if (!kdbus_conn_policy_see_notification(conn_dst, NULL, |
8872 |
-+ staging->msg)) |
8873 |
-+ continue; |
8874 |
-+ } |
8875 |
-+ |
8876 |
-+ ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging, |
8877 |
-+ NULL, NULL); |
8878 |
-+ if (ret < 0) |
8879 |
-+ kdbus_conn_lost_message(conn_dst); |
8880 |
-+ } |
8881 |
-+ up_read(&bus->conn_rwlock); |
8882 |
-+} |
8883 |
-+ |
8884 |
-+/** |
8885 |
-+ * kdbus_bus_eavesdrop() - send a message to all subscribed monitors |
8886 |
-+ * @bus: The bus the monitors are connected to |
8887 |
-+ * @conn_src: The source connection, may be %NULL for kernel notifications |
8888 |
-+ * @staging: Staging object containing the message to send |
8889 |
-+ * |
8890 |
-+ * Send message to all monitors that are currently active on the bus. Monitors |
8891 |
-+ * must still have matches installed in order to let the message pass. |
8892 |
-+ * |
8893 |
-+ * The caller must hold the name-registry lock of @bus. |
8894 |
-+ */ |
8895 |
-+void kdbus_bus_eavesdrop(struct kdbus_bus *bus, |
8896 |
-+ struct kdbus_conn *conn_src, |
8897 |
-+ struct kdbus_staging *staging) |
8898 |
-+{ |
8899 |
-+ struct kdbus_conn *conn_dst; |
8900 |
-+ int ret; |
8901 |
-+ |
8902 |
-+ /* |
8903 |
-+ * Monitor connections get all messages; ignore possible errors |
8904 |
-+ * when sending messages to monitor connections. |
8905 |
-+ */ |
8906 |
-+ |
8907 |
-+ lockdep_assert_held(&bus->name_registry->rwlock); |
8908 |
-+ |
8909 |
-+ down_read(&bus->conn_rwlock); |
8910 |
-+ list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) { |
8911 |
-+ ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging, |
8912 |
-+ NULL, NULL); |
8913 |
-+ if (ret < 0) |
8914 |
-+ kdbus_conn_lost_message(conn_dst); |
8915 |
-+ } |
8916 |
-+ up_read(&bus->conn_rwlock); |
8917 |
-+} |
8918 |
-+ |
8919 |
-+/** |
8920 |
-+ * kdbus_cmd_bus_make() - handle KDBUS_CMD_BUS_MAKE |
8921 |
-+ * @domain: domain to operate on |
8922 |
-+ * @argp: command payload |
8923 |
-+ * |
8924 |
-+ * Return: NULL or newly created bus on success, ERR_PTR on failure. |
8925 |
-+ */ |
8926 |
-+struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, |
8927 |
-+ void __user *argp) |
8928 |
-+{ |
8929 |
-+ struct kdbus_bus *bus = NULL; |
8930 |
-+ struct kdbus_cmd *cmd; |
8931 |
-+ struct kdbus_ep *ep = NULL; |
8932 |
-+ int ret; |
8933 |
-+ |
8934 |
-+ struct kdbus_arg argv[] = { |
8935 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
8936 |
-+ { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, |
8937 |
-+ { .type = KDBUS_ITEM_BLOOM_PARAMETER, .mandatory = true }, |
8938 |
-+ { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND }, |
8939 |
-+ }; |
8940 |
-+ struct kdbus_args args = { |
8941 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
8942 |
-+ KDBUS_MAKE_ACCESS_GROUP | |
8943 |
-+ KDBUS_MAKE_ACCESS_WORLD, |
8944 |
-+ .argv = argv, |
8945 |
-+ .argc = ARRAY_SIZE(argv), |
8946 |
-+ }; |
8947 |
-+ |
8948 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
8949 |
-+ if (ret < 0) |
8950 |
-+ return ERR_PTR(ret); |
8951 |
-+ if (ret > 0) |
8952 |
-+ return NULL; |
8953 |
-+ |
8954 |
-+ bus = kdbus_bus_new(domain, |
8955 |
-+ argv[1].item->str, &argv[2].item->bloom_parameter, |
8956 |
-+ argv[3].item ? argv[3].item->data64 : NULL, |
8957 |
-+ cmd->flags, current_euid(), current_egid()); |
8958 |
-+ if (IS_ERR(bus)) { |
8959 |
-+ ret = PTR_ERR(bus); |
8960 |
-+ bus = NULL; |
8961 |
-+ goto exit; |
8962 |
-+ } |
8963 |
-+ |
8964 |
-+ if (atomic_inc_return(&bus->creator->buses) > KDBUS_USER_MAX_BUSES) { |
8965 |
-+ atomic_dec(&bus->creator->buses); |
8966 |
-+ ret = -EMFILE; |
8967 |
-+ goto exit; |
8968 |
-+ } |
8969 |
-+ |
8970 |
-+ if (!kdbus_node_activate(&bus->node)) { |
8971 |
-+ atomic_dec(&bus->creator->buses); |
8972 |
-+ ret = -ESHUTDOWN; |
8973 |
-+ goto exit; |
8974 |
-+ } |
8975 |
-+ |
8976 |
-+ ep = kdbus_ep_new(bus, "bus", cmd->flags, bus->node.uid, bus->node.gid, |
8977 |
-+ false); |
8978 |
-+ if (IS_ERR(ep)) { |
8979 |
-+ ret = PTR_ERR(ep); |
8980 |
-+ ep = NULL; |
8981 |
-+ goto exit; |
8982 |
-+ } |
8983 |
-+ |
8984 |
-+ if (!kdbus_node_activate(&ep->node)) { |
8985 |
-+ ret = -ESHUTDOWN; |
8986 |
-+ goto exit; |
8987 |
-+ } |
8988 |
-+ |
8989 |
-+ /* |
8990 |
-+ * Drop our own reference, effectively causing the endpoint to be |
8991 |
-+ * deactivated and released when the parent bus is. |
8992 |
-+ */ |
8993 |
-+ ep = kdbus_ep_unref(ep); |
8994 |
-+ |
8995 |
-+exit: |
8996 |
-+ ret = kdbus_args_clear(&args, ret); |
8997 |
-+ if (ret < 0) { |
8998 |
-+ if (ep) { |
8999 |
-+ kdbus_node_deactivate(&ep->node); |
9000 |
-+ kdbus_ep_unref(ep); |
9001 |
-+ } |
9002 |
-+ if (bus) { |
9003 |
-+ kdbus_node_deactivate(&bus->node); |
9004 |
-+ kdbus_bus_unref(bus); |
9005 |
-+ } |
9006 |
-+ return ERR_PTR(ret); |
9007 |
-+ } |
9008 |
-+ return bus; |
9009 |
-+} |
9010 |
-+ |
9011 |
-+/** |
9012 |
-+ * kdbus_cmd_bus_creator_info() - handle KDBUS_CMD_BUS_CREATOR_INFO |
9013 |
-+ * @conn: connection to operate on |
9014 |
-+ * @argp: command payload |
9015 |
-+ * |
9016 |
-+ * Return: >=0 on success, negative error code on failure. |
9017 |
-+ */ |
9018 |
-+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp) |
9019 |
-+{ |
9020 |
-+ struct kdbus_cmd_info *cmd; |
9021 |
-+ struct kdbus_bus *bus = conn->ep->bus; |
9022 |
-+ struct kdbus_pool_slice *slice = NULL; |
9023 |
-+ struct kdbus_item *meta_items = NULL; |
9024 |
-+ struct kdbus_item_header item_hdr; |
9025 |
-+ struct kdbus_info info = {}; |
9026 |
-+ size_t meta_size, name_len, cnt = 0; |
9027 |
-+ struct kvec kvec[6]; |
9028 |
-+ u64 attach_flags, size = 0; |
9029 |
-+ int ret; |
9030 |
-+ |
9031 |
-+ struct kdbus_arg argv[] = { |
9032 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
9033 |
-+ }; |
9034 |
-+ struct kdbus_args args = { |
9035 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
9036 |
-+ .argv = argv, |
9037 |
-+ .argc = ARRAY_SIZE(argv), |
9038 |
-+ }; |
9039 |
-+ |
9040 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
9041 |
-+ if (ret != 0) |
9042 |
-+ return ret; |
9043 |
-+ |
9044 |
-+ ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags); |
9045 |
-+ if (ret < 0) |
9046 |
-+ goto exit; |
9047 |
-+ |
9048 |
-+ attach_flags &= bus->attach_flags_owner; |
9049 |
-+ |
9050 |
-+ ret = kdbus_meta_emit(bus->creator_meta, NULL, NULL, conn, |
9051 |
-+ attach_flags, &meta_items, &meta_size); |
9052 |
-+ if (ret < 0) |
9053 |
-+ goto exit; |
9054 |
-+ |
9055 |
-+ name_len = strlen(bus->node.name) + 1; |
9056 |
-+ info.id = bus->id; |
9057 |
-+ info.flags = bus->bus_flags; |
9058 |
-+ item_hdr.type = KDBUS_ITEM_MAKE_NAME; |
9059 |
-+ item_hdr.size = KDBUS_ITEM_HEADER_SIZE + name_len; |
9060 |
-+ |
9061 |
-+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size); |
9062 |
-+ kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &size); |
9063 |
-+ kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &size); |
9064 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &size); |
9065 |
-+ if (meta_size > 0) { |
9066 |
-+ kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size); |
9067 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &size); |
9068 |
-+ } |
9069 |
-+ |
9070 |
-+ info.size = size; |
9071 |
-+ |
9072 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
9073 |
-+ if (IS_ERR(slice)) { |
9074 |
-+ ret = PTR_ERR(slice); |
9075 |
-+ slice = NULL; |
9076 |
-+ goto exit; |
9077 |
-+ } |
9078 |
-+ |
9079 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, size); |
9080 |
-+ if (ret < 0) |
9081 |
-+ goto exit; |
9082 |
-+ |
9083 |
-+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size); |
9084 |
-+ |
9085 |
-+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
9086 |
-+ kdbus_member_set_user(&cmd->info_size, argp, |
9087 |
-+ typeof(*cmd), info_size)) |
9088 |
-+ ret = -EFAULT; |
9089 |
-+ |
9090 |
-+exit: |
9091 |
-+ kdbus_pool_slice_release(slice); |
9092 |
-+ kfree(meta_items); |
9093 |
-+ return kdbus_args_clear(&args, ret); |
9094 |
-+} |
9095 |
-diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h |
9096 |
-new file mode 100644 |
9097 |
-index 0000000..8c2acae |
9098 |
---- /dev/null |
9099 |
-+++ b/ipc/kdbus/bus.h |
9100 |
-@@ -0,0 +1,101 @@ |
9101 |
-+/* |
9102 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
9103 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
9104 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
9105 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
9106 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
9107 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
9108 |
-+ * |
9109 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
9110 |
-+ * the terms of the GNU Lesser General Public License as published by the |
9111 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
9112 |
-+ * your option) any later version. |
9113 |
-+ */ |
9114 |
-+ |
9115 |
-+#ifndef __KDBUS_BUS_H |
9116 |
-+#define __KDBUS_BUS_H |
9117 |
-+ |
9118 |
-+#include <linux/hashtable.h> |
9119 |
-+#include <linux/list.h> |
9120 |
-+#include <linux/mutex.h> |
9121 |
-+#include <linux/rwsem.h> |
9122 |
-+#include <linux/spinlock.h> |
9123 |
-+#include <uapi/linux/kdbus.h> |
9124 |
-+ |
9125 |
-+#include "metadata.h" |
9126 |
-+#include "names.h" |
9127 |
-+#include "node.h" |
9128 |
-+#include "policy.h" |
9129 |
-+ |
9130 |
-+struct kdbus_conn; |
9131 |
-+struct kdbus_domain; |
9132 |
-+struct kdbus_staging; |
9133 |
-+struct kdbus_user; |
9134 |
-+ |
9135 |
-+/** |
9136 |
-+ * struct kdbus_bus - bus in a domain |
9137 |
-+ * @node: kdbus_node |
9138 |
-+ * @id: ID of this bus in the domain |
9139 |
-+ * @bus_flags: Simple pass-through flags from userspace to userspace |
9140 |
-+ * @attach_flags_owner: KDBUS_ATTACH_* flags of bus creator that other |
9141 |
-+ * connections can see or query |
9142 |
-+ * @id128: Unique random 128 bit ID of this bus |
9143 |
-+ * @bloom: Bloom parameters |
9144 |
-+ * @domain: Domain of this bus |
9145 |
-+ * @creator: Creator of the bus |
9146 |
-+ * @creator_meta: Meta information about the bus creator |
9147 |
-+ * @last_message_id: Last used message id |
9148 |
-+ * @policy_db: Policy database for this bus |
9149 |
-+ * @name_registry: Name registry of this bus |
9150 |
-+ * @conn_rwlock: Read/Write lock for all lists of child connections |
9151 |
-+ * @conn_hash: Map of connection IDs |
9152 |
-+ * @monitors_list: Connections that monitor this bus |
9153 |
-+ * @notify_list: List of pending kernel-generated messages |
9154 |
-+ * @notify_lock: Notification list lock |
9155 |
-+ * @notify_flush_lock: Notification flushing lock |
9156 |
-+ */ |
9157 |
-+struct kdbus_bus { |
9158 |
-+ struct kdbus_node node; |
9159 |
-+ |
9160 |
-+ /* static */ |
9161 |
-+ u64 id; |
9162 |
-+ u64 bus_flags; |
9163 |
-+ u64 attach_flags_owner; |
9164 |
-+ u8 id128[16]; |
9165 |
-+ struct kdbus_bloom_parameter bloom; |
9166 |
-+ struct kdbus_domain *domain; |
9167 |
-+ struct kdbus_user *creator; |
9168 |
-+ struct kdbus_meta_proc *creator_meta; |
9169 |
-+ |
9170 |
-+ /* protected by own locks */ |
9171 |
-+ atomic64_t last_message_id; |
9172 |
-+ struct kdbus_policy_db policy_db; |
9173 |
-+ struct kdbus_name_registry *name_registry; |
9174 |
-+ |
9175 |
-+ /* protected by conn_rwlock */ |
9176 |
-+ struct rw_semaphore conn_rwlock; |
9177 |
-+ DECLARE_HASHTABLE(conn_hash, 8); |
9178 |
-+ struct list_head monitors_list; |
9179 |
-+ |
9180 |
-+ /* protected by notify_lock */ |
9181 |
-+ struct list_head notify_list; |
9182 |
-+ spinlock_t notify_lock; |
9183 |
-+ struct mutex notify_flush_lock; |
9184 |
-+}; |
9185 |
-+ |
9186 |
-+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus); |
9187 |
-+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus); |
9188 |
-+ |
9189 |
-+struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id); |
9190 |
-+void kdbus_bus_broadcast(struct kdbus_bus *bus, |
9191 |
-+ struct kdbus_conn *conn_src, |
9192 |
-+ struct kdbus_staging *staging); |
9193 |
-+void kdbus_bus_eavesdrop(struct kdbus_bus *bus, |
9194 |
-+ struct kdbus_conn *conn_src, |
9195 |
-+ struct kdbus_staging *staging); |
9196 |
-+ |
9197 |
-+struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, |
9198 |
-+ void __user *argp); |
9199 |
-+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp); |
9200 |
-+ |
9201 |
-+#endif |
9202 |
-diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c |
9203 |
-new file mode 100644 |
9204 |
-index 0000000..ef63d65 |
9205 |
---- /dev/null |
9206 |
-+++ b/ipc/kdbus/connection.c |
9207 |
-@@ -0,0 +1,2227 @@ |
9208 |
-+/* |
9209 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
9210 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
9211 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
9212 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
9213 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
9214 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
9215 |
-+ * |
9216 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
9217 |
-+ * the terms of the GNU Lesser General Public License as published by the |
9218 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
9219 |
-+ * your option) any later version. |
9220 |
-+ */ |
9221 |
-+ |
9222 |
-+#include <linux/audit.h> |
9223 |
-+#include <linux/file.h> |
9224 |
-+#include <linux/fs.h> |
9225 |
-+#include <linux/fs_struct.h> |
9226 |
-+#include <linux/hashtable.h> |
9227 |
-+#include <linux/idr.h> |
9228 |
-+#include <linux/init.h> |
9229 |
-+#include <linux/math64.h> |
9230 |
-+#include <linux/mm.h> |
9231 |
-+#include <linux/module.h> |
9232 |
-+#include <linux/mutex.h> |
9233 |
-+#include <linux/path.h> |
9234 |
-+#include <linux/poll.h> |
9235 |
-+#include <linux/sched.h> |
9236 |
-+#include <linux/shmem_fs.h> |
9237 |
-+#include <linux/sizes.h> |
9238 |
-+#include <linux/slab.h> |
9239 |
-+#include <linux/syscalls.h> |
9240 |
-+#include <linux/uio.h> |
9241 |
-+ |
9242 |
-+#include "bus.h" |
9243 |
-+#include "connection.h" |
9244 |
-+#include "endpoint.h" |
9245 |
-+#include "handle.h" |
9246 |
-+#include "match.h" |
9247 |
-+#include "message.h" |
9248 |
-+#include "metadata.h" |
9249 |
-+#include "names.h" |
9250 |
-+#include "domain.h" |
9251 |
-+#include "item.h" |
9252 |
-+#include "notify.h" |
9253 |
-+#include "policy.h" |
9254 |
-+#include "pool.h" |
9255 |
-+#include "reply.h" |
9256 |
-+#include "util.h" |
9257 |
-+#include "queue.h" |
9258 |
-+ |
9259 |
-+#define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2) |
9260 |
-+#define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1) |
9261 |
-+ |
9262 |
-+static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, |
9263 |
-+ struct file *file, |
9264 |
-+ struct kdbus_cmd_hello *hello, |
9265 |
-+ const char *name, |
9266 |
-+ const struct kdbus_creds *creds, |
9267 |
-+ const struct kdbus_pids *pids, |
9268 |
-+ const char *seclabel, |
9269 |
-+ const char *conn_description) |
9270 |
-+{ |
9271 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9272 |
-+ static struct lock_class_key __key; |
9273 |
-+#endif |
9274 |
-+ struct kdbus_pool_slice *slice = NULL; |
9275 |
-+ struct kdbus_bus *bus = ep->bus; |
9276 |
-+ struct kdbus_conn *conn; |
9277 |
-+ u64 attach_flags_send; |
9278 |
-+ u64 attach_flags_recv; |
9279 |
-+ u64 items_size = 0; |
9280 |
-+ bool is_policy_holder; |
9281 |
-+ bool is_activator; |
9282 |
-+ bool is_monitor; |
9283 |
-+ bool privileged; |
9284 |
-+ bool owner; |
9285 |
-+ struct kvec kvec; |
9286 |
-+ int ret; |
9287 |
-+ |
9288 |
-+ struct { |
9289 |
-+ u64 size; |
9290 |
-+ u64 type; |
9291 |
-+ struct kdbus_bloom_parameter bloom; |
9292 |
-+ } bloom_item; |
9293 |
-+ |
9294 |
-+ privileged = kdbus_ep_is_privileged(ep, file); |
9295 |
-+ owner = kdbus_ep_is_owner(ep, file); |
9296 |
-+ |
9297 |
-+ is_monitor = hello->flags & KDBUS_HELLO_MONITOR; |
9298 |
-+ is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR; |
9299 |
-+ is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER; |
9300 |
-+ |
9301 |
-+ if (!hello->pool_size || !IS_ALIGNED(hello->pool_size, PAGE_SIZE)) |
9302 |
-+ return ERR_PTR(-EINVAL); |
9303 |
-+ if (is_monitor + is_activator + is_policy_holder > 1) |
9304 |
-+ return ERR_PTR(-EINVAL); |
9305 |
-+ if (name && !is_activator && !is_policy_holder) |
9306 |
-+ return ERR_PTR(-EINVAL); |
9307 |
-+ if (!name && (is_activator || is_policy_holder)) |
9308 |
-+ return ERR_PTR(-EINVAL); |
9309 |
-+ if (name && !kdbus_name_is_valid(name, true)) |
9310 |
-+ return ERR_PTR(-EINVAL); |
9311 |
-+ if (is_monitor && ep->user) |
9312 |
-+ return ERR_PTR(-EOPNOTSUPP); |
9313 |
-+ if (!owner && (is_activator || is_policy_holder || is_monitor)) |
9314 |
-+ return ERR_PTR(-EPERM); |
9315 |
-+ if (!owner && (creds || pids || seclabel)) |
9316 |
-+ return ERR_PTR(-EPERM); |
9317 |
-+ |
9318 |
-+ ret = kdbus_sanitize_attach_flags(hello->attach_flags_send, |
9319 |
-+ &attach_flags_send); |
9320 |
-+ if (ret < 0) |
9321 |
-+ return ERR_PTR(ret); |
9322 |
-+ |
9323 |
-+ ret = kdbus_sanitize_attach_flags(hello->attach_flags_recv, |
9324 |
-+ &attach_flags_recv); |
9325 |
-+ if (ret < 0) |
9326 |
-+ return ERR_PTR(ret); |
9327 |
-+ |
9328 |
-+ conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
9329 |
-+ if (!conn) |
9330 |
-+ return ERR_PTR(-ENOMEM); |
9331 |
-+ |
9332 |
-+ kref_init(&conn->kref); |
9333 |
-+ atomic_set(&conn->active, KDBUS_CONN_ACTIVE_NEW); |
9334 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9335 |
-+ lockdep_init_map(&conn->dep_map, "s_active", &__key, 0); |
9336 |
-+#endif |
9337 |
-+ mutex_init(&conn->lock); |
9338 |
-+ INIT_LIST_HEAD(&conn->names_list); |
9339 |
-+ INIT_LIST_HEAD(&conn->reply_list); |
9340 |
-+ atomic_set(&conn->request_count, 0); |
9341 |
-+ atomic_set(&conn->lost_count, 0); |
9342 |
-+ INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work); |
9343 |
-+ conn->cred = get_cred(file->f_cred); |
9344 |
-+ conn->pid = get_pid(task_pid(current)); |
9345 |
-+ get_fs_root(current->fs, &conn->root_path); |
9346 |
-+ init_waitqueue_head(&conn->wait); |
9347 |
-+ kdbus_queue_init(&conn->queue); |
9348 |
-+ conn->privileged = privileged; |
9349 |
-+ conn->owner = owner; |
9350 |
-+ conn->ep = kdbus_ep_ref(ep); |
9351 |
-+ conn->id = atomic64_inc_return(&bus->domain->last_id); |
9352 |
-+ conn->flags = hello->flags; |
9353 |
-+ atomic64_set(&conn->attach_flags_send, attach_flags_send); |
9354 |
-+ atomic64_set(&conn->attach_flags_recv, attach_flags_recv); |
9355 |
-+ INIT_LIST_HEAD(&conn->monitor_entry); |
9356 |
-+ |
9357 |
-+ if (conn_description) { |
9358 |
-+ conn->description = kstrdup(conn_description, GFP_KERNEL); |
9359 |
-+ if (!conn->description) { |
9360 |
-+ ret = -ENOMEM; |
9361 |
-+ goto exit_unref; |
9362 |
-+ } |
9363 |
-+ } |
9364 |
-+ |
9365 |
-+ conn->pool = kdbus_pool_new(conn->description, hello->pool_size); |
9366 |
-+ if (IS_ERR(conn->pool)) { |
9367 |
-+ ret = PTR_ERR(conn->pool); |
9368 |
-+ conn->pool = NULL; |
9369 |
-+ goto exit_unref; |
9370 |
-+ } |
9371 |
-+ |
9372 |
-+ conn->match_db = kdbus_match_db_new(); |
9373 |
-+ if (IS_ERR(conn->match_db)) { |
9374 |
-+ ret = PTR_ERR(conn->match_db); |
9375 |
-+ conn->match_db = NULL; |
9376 |
-+ goto exit_unref; |
9377 |
-+ } |
9378 |
-+ |
9379 |
-+ /* return properties of this connection to the caller */ |
9380 |
-+ hello->bus_flags = bus->bus_flags; |
9381 |
-+ hello->id = conn->id; |
9382 |
-+ |
9383 |
-+ BUILD_BUG_ON(sizeof(bus->id128) != sizeof(hello->id128)); |
9384 |
-+ memcpy(hello->id128, bus->id128, sizeof(hello->id128)); |
9385 |
-+ |
9386 |
-+ /* privileged processes can impersonate somebody else */ |
9387 |
-+ if (creds || pids || seclabel) { |
9388 |
-+ conn->meta_fake = kdbus_meta_fake_new(); |
9389 |
-+ if (IS_ERR(conn->meta_fake)) { |
9390 |
-+ ret = PTR_ERR(conn->meta_fake); |
9391 |
-+ conn->meta_fake = NULL; |
9392 |
-+ goto exit_unref; |
9393 |
-+ } |
9394 |
-+ |
9395 |
-+ ret = kdbus_meta_fake_collect(conn->meta_fake, |
9396 |
-+ creds, pids, seclabel); |
9397 |
-+ if (ret < 0) |
9398 |
-+ goto exit_unref; |
9399 |
-+ } else { |
9400 |
-+ conn->meta_proc = kdbus_meta_proc_new(); |
9401 |
-+ if (IS_ERR(conn->meta_proc)) { |
9402 |
-+ ret = PTR_ERR(conn->meta_proc); |
9403 |
-+ conn->meta_proc = NULL; |
9404 |
-+ goto exit_unref; |
9405 |
-+ } |
9406 |
-+ |
9407 |
-+ ret = kdbus_meta_proc_collect(conn->meta_proc, |
9408 |
-+ KDBUS_ATTACH_CREDS | |
9409 |
-+ KDBUS_ATTACH_PIDS | |
9410 |
-+ KDBUS_ATTACH_AUXGROUPS | |
9411 |
-+ KDBUS_ATTACH_TID_COMM | |
9412 |
-+ KDBUS_ATTACH_PID_COMM | |
9413 |
-+ KDBUS_ATTACH_EXE | |
9414 |
-+ KDBUS_ATTACH_CMDLINE | |
9415 |
-+ KDBUS_ATTACH_CGROUP | |
9416 |
-+ KDBUS_ATTACH_CAPS | |
9417 |
-+ KDBUS_ATTACH_SECLABEL | |
9418 |
-+ KDBUS_ATTACH_AUDIT); |
9419 |
-+ if (ret < 0) |
9420 |
-+ goto exit_unref; |
9421 |
-+ } |
9422 |
-+ |
9423 |
-+ /* |
9424 |
-+ * Account the connection against the current user (UID), or for |
9425 |
-+ * custom endpoints use the anonymous user assigned to the endpoint. |
9426 |
-+ * Note that limits are always accounted against the real UID, not |
9427 |
-+ * the effective UID (cred->user always points to the accounting of |
9428 |
-+ * cred->uid, not cred->euid). |
9429 |
-+ * In case the caller is privileged, we allow changing the accounting |
9430 |
-+ * to the faked user. |
9431 |
-+ */ |
9432 |
-+ if (ep->user) { |
9433 |
-+ conn->user = kdbus_user_ref(ep->user); |
9434 |
-+ } else { |
9435 |
-+ kuid_t uid; |
9436 |
-+ |
9437 |
-+ if (conn->meta_fake && uid_valid(conn->meta_fake->uid) && |
9438 |
-+ conn->privileged) |
9439 |
-+ uid = conn->meta_fake->uid; |
9440 |
-+ else |
9441 |
-+ uid = conn->cred->uid; |
9442 |
-+ |
9443 |
-+ conn->user = kdbus_user_lookup(ep->bus->domain, uid); |
9444 |
-+ if (IS_ERR(conn->user)) { |
9445 |
-+ ret = PTR_ERR(conn->user); |
9446 |
-+ conn->user = NULL; |
9447 |
-+ goto exit_unref; |
9448 |
-+ } |
9449 |
-+ } |
9450 |
-+ |
9451 |
-+ if (atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) { |
9452 |
-+ /* decremented by destructor as conn->user is valid */ |
9453 |
-+ ret = -EMFILE; |
9454 |
-+ goto exit_unref; |
9455 |
-+ } |
9456 |
-+ |
9457 |
-+ bloom_item.size = sizeof(bloom_item); |
9458 |
-+ bloom_item.type = KDBUS_ITEM_BLOOM_PARAMETER; |
9459 |
-+ bloom_item.bloom = bus->bloom; |
9460 |
-+ kdbus_kvec_set(&kvec, &bloom_item, bloom_item.size, &items_size); |
9461 |
-+ |
9462 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, items_size, false); |
9463 |
-+ if (IS_ERR(slice)) { |
9464 |
-+ ret = PTR_ERR(slice); |
9465 |
-+ slice = NULL; |
9466 |
-+ goto exit_unref; |
9467 |
-+ } |
9468 |
-+ |
9469 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, 0, &kvec, 1, items_size); |
9470 |
-+ if (ret < 0) |
9471 |
-+ goto exit_unref; |
9472 |
-+ |
9473 |
-+ kdbus_pool_slice_publish(slice, &hello->offset, &hello->items_size); |
9474 |
-+ kdbus_pool_slice_release(slice); |
9475 |
-+ |
9476 |
-+ return conn; |
9477 |
-+ |
9478 |
-+exit_unref: |
9479 |
-+ kdbus_pool_slice_release(slice); |
9480 |
-+ kdbus_conn_unref(conn); |
9481 |
-+ return ERR_PTR(ret); |
9482 |
-+} |
9483 |
-+ |
9484 |
-+static void __kdbus_conn_free(struct kref *kref) |
9485 |
-+{ |
9486 |
-+ struct kdbus_conn *conn = container_of(kref, struct kdbus_conn, kref); |
9487 |
-+ |
9488 |
-+ WARN_ON(kdbus_conn_active(conn)); |
9489 |
-+ WARN_ON(delayed_work_pending(&conn->work)); |
9490 |
-+ WARN_ON(!list_empty(&conn->queue.msg_list)); |
9491 |
-+ WARN_ON(!list_empty(&conn->names_list)); |
9492 |
-+ WARN_ON(!list_empty(&conn->reply_list)); |
9493 |
-+ |
9494 |
-+ if (conn->user) { |
9495 |
-+ atomic_dec(&conn->user->connections); |
9496 |
-+ kdbus_user_unref(conn->user); |
9497 |
-+ } |
9498 |
-+ |
9499 |
-+ kdbus_meta_fake_free(conn->meta_fake); |
9500 |
-+ kdbus_meta_proc_unref(conn->meta_proc); |
9501 |
-+ kdbus_match_db_free(conn->match_db); |
9502 |
-+ kdbus_pool_free(conn->pool); |
9503 |
-+ kdbus_ep_unref(conn->ep); |
9504 |
-+ path_put(&conn->root_path); |
9505 |
-+ put_pid(conn->pid); |
9506 |
-+ put_cred(conn->cred); |
9507 |
-+ kfree(conn->description); |
9508 |
-+ kfree(conn->quota); |
9509 |
-+ kfree(conn); |
9510 |
-+} |
9511 |
-+ |
9512 |
-+/** |
9513 |
-+ * kdbus_conn_ref() - take a connection reference |
9514 |
-+ * @conn: Connection, may be %NULL |
9515 |
-+ * |
9516 |
-+ * Return: the connection itself |
9517 |
-+ */ |
9518 |
-+struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn) |
9519 |
-+{ |
9520 |
-+ if (conn) |
9521 |
-+ kref_get(&conn->kref); |
9522 |
-+ return conn; |
9523 |
-+} |
9524 |
-+ |
9525 |
-+/** |
9526 |
-+ * kdbus_conn_unref() - drop a connection reference |
9527 |
-+ * @conn: Connection (may be NULL) |
9528 |
-+ * |
9529 |
-+ * When the last reference is dropped, the connection's internal structure |
9530 |
-+ * is freed. |
9531 |
-+ * |
9532 |
-+ * Return: NULL |
9533 |
-+ */ |
9534 |
-+struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn) |
9535 |
-+{ |
9536 |
-+ if (conn) |
9537 |
-+ kref_put(&conn->kref, __kdbus_conn_free); |
9538 |
-+ return NULL; |
9539 |
-+} |
9540 |
-+ |
9541 |
-+/** |
9542 |
-+ * kdbus_conn_active() - connection is not disconnected |
9543 |
-+ * @conn: Connection to check |
9544 |
-+ * |
9545 |
-+ * Return true if the connection was not disconnected, yet. Note that a |
9546 |
-+ * connection might be disconnected asynchronously, unless you hold the |
9547 |
-+ * connection lock. If that's not suitable for you, see kdbus_conn_acquire() to |
9548 |
-+ * suppress connection shutdown for a short period. |
9549 |
-+ * |
9550 |
-+ * Return: true if the connection is still active |
9551 |
-+ */ |
9552 |
-+bool kdbus_conn_active(const struct kdbus_conn *conn) |
9553 |
-+{ |
9554 |
-+ return atomic_read(&conn->active) >= 0; |
9555 |
-+} |
9556 |
-+ |
9557 |
-+/** |
9558 |
-+ * kdbus_conn_acquire() - acquire an active connection reference |
9559 |
-+ * @conn: Connection |
9560 |
-+ * |
9561 |
-+ * Users can close a connection via KDBUS_BYEBYE (or by destroying the |
9562 |
-+ * endpoint/bus/...) at any time. Whenever this happens, we should deny any |
9563 |
-+ * user-visible action on this connection and signal ECONNRESET instead. |
9564 |
-+ * To avoid testing for connection availability everytime you take the |
9565 |
-+ * connection-lock, you can acquire a connection for short periods. |
9566 |
-+ * |
9567 |
-+ * By calling kdbus_conn_acquire(), you gain an "active reference" to the |
9568 |
-+ * connection. You must also hold a regular reference at any time! As long as |
9569 |
-+ * you hold the active-ref, the connection will not be shut down. However, if |
9570 |
-+ * the connection was shut down, you can never acquire an active-ref again. |
9571 |
-+ * |
9572 |
-+ * kdbus_conn_disconnect() disables the connection and then waits for all active |
9573 |
-+ * references to be dropped. It will also wake up any pending operation. |
9574 |
-+ * However, you must not sleep for an indefinite period while holding an |
9575 |
-+ * active-reference. Otherwise, kdbus_conn_disconnect() might stall. If you need |
9576 |
-+ * to sleep for an indefinite period, either release the reference and try to |
9577 |
-+ * acquire it again after waking up, or make kdbus_conn_disconnect() wake up |
9578 |
-+ * your wait-queue. |
9579 |
-+ * |
9580 |
-+ * Return: 0 on success, negative error code on failure. |
9581 |
-+ */ |
9582 |
-+int kdbus_conn_acquire(struct kdbus_conn *conn) |
9583 |
-+{ |
9584 |
-+ if (!atomic_inc_unless_negative(&conn->active)) |
9585 |
-+ return -ECONNRESET; |
9586 |
-+ |
9587 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9588 |
-+ rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_); |
9589 |
-+#endif |
9590 |
-+ |
9591 |
-+ return 0; |
9592 |
-+} |
9593 |
-+ |
9594 |
-+/** |
9595 |
-+ * kdbus_conn_release() - release an active connection reference |
9596 |
-+ * @conn: Connection |
9597 |
-+ * |
9598 |
-+ * This releases an active reference that has been acquired via |
9599 |
-+ * kdbus_conn_acquire(). If the connection was already disabled and this is the |
9600 |
-+ * last active-ref that is dropped, the disconnect-waiter will be woken up and |
9601 |
-+ * properly close the connection. |
9602 |
-+ */ |
9603 |
-+void kdbus_conn_release(struct kdbus_conn *conn) |
9604 |
-+{ |
9605 |
-+ int v; |
9606 |
-+ |
9607 |
-+ if (!conn) |
9608 |
-+ return; |
9609 |
-+ |
9610 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9611 |
-+ rwsem_release(&conn->dep_map, 1, _RET_IP_); |
9612 |
-+#endif |
9613 |
-+ |
9614 |
-+ v = atomic_dec_return(&conn->active); |
9615 |
-+ if (v != KDBUS_CONN_ACTIVE_BIAS) |
9616 |
-+ return; |
9617 |
-+ |
9618 |
-+ wake_up_all(&conn->wait); |
9619 |
-+} |
9620 |
-+ |
9621 |
-+static int kdbus_conn_connect(struct kdbus_conn *conn, const char *name) |
9622 |
-+{ |
9623 |
-+ struct kdbus_ep *ep = conn->ep; |
9624 |
-+ struct kdbus_bus *bus = ep->bus; |
9625 |
-+ int ret; |
9626 |
-+ |
9627 |
-+ if (WARN_ON(atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_NEW)) |
9628 |
-+ return -EALREADY; |
9629 |
-+ |
9630 |
-+ /* make sure the ep-node is active while we add our connection */ |
9631 |
-+ if (!kdbus_node_acquire(&ep->node)) |
9632 |
-+ return -ESHUTDOWN; |
9633 |
-+ |
9634 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
9635 |
-+ mutex_lock(&ep->lock); |
9636 |
-+ down_write(&bus->conn_rwlock); |
9637 |
-+ |
9638 |
-+ /* link into monitor list */ |
9639 |
-+ if (kdbus_conn_is_monitor(conn)) |
9640 |
-+ list_add_tail(&conn->monitor_entry, &bus->monitors_list); |
9641 |
-+ |
9642 |
-+ /* link into bus and endpoint */ |
9643 |
-+ list_add_tail(&conn->ep_entry, &ep->conn_list); |
9644 |
-+ hash_add(bus->conn_hash, &conn->hentry, conn->id); |
9645 |
-+ |
9646 |
-+ /* enable lookups and acquire active ref */ |
9647 |
-+ atomic_set(&conn->active, 1); |
9648 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9649 |
-+ rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_); |
9650 |
-+#endif |
9651 |
-+ |
9652 |
-+ up_write(&bus->conn_rwlock); |
9653 |
-+ mutex_unlock(&ep->lock); |
9654 |
-+ |
9655 |
-+ kdbus_node_release(&ep->node); |
9656 |
-+ |
9657 |
-+ /* |
9658 |
-+ * Notify subscribers about the new active connection, unless it is |
9659 |
-+ * a monitor. Monitors are invisible on the bus, can't be addressed |
9660 |
-+ * directly, and won't cause any notifications. |
9661 |
-+ */ |
9662 |
-+ if (!kdbus_conn_is_monitor(conn)) { |
9663 |
-+ ret = kdbus_notify_id_change(bus, KDBUS_ITEM_ID_ADD, |
9664 |
-+ conn->id, conn->flags); |
9665 |
-+ if (ret < 0) |
9666 |
-+ goto exit_disconnect; |
9667 |
-+ } |
9668 |
-+ |
9669 |
-+ if (kdbus_conn_is_activator(conn)) { |
9670 |
-+ u64 flags = KDBUS_NAME_ACTIVATOR; |
9671 |
-+ |
9672 |
-+ if (WARN_ON(!name)) { |
9673 |
-+ ret = -EINVAL; |
9674 |
-+ goto exit_disconnect; |
9675 |
-+ } |
9676 |
-+ |
9677 |
-+ ret = kdbus_name_acquire(bus->name_registry, conn, name, |
9678 |
-+ flags, NULL); |
9679 |
-+ if (ret < 0) |
9680 |
-+ goto exit_disconnect; |
9681 |
-+ } |
9682 |
-+ |
9683 |
-+ kdbus_conn_release(conn); |
9684 |
-+ kdbus_notify_flush(bus); |
9685 |
-+ return 0; |
9686 |
-+ |
9687 |
-+exit_disconnect: |
9688 |
-+ kdbus_conn_release(conn); |
9689 |
-+ kdbus_conn_disconnect(conn, false); |
9690 |
-+ return ret; |
9691 |
-+} |
9692 |
-+ |
9693 |
-+/** |
9694 |
-+ * kdbus_conn_disconnect() - disconnect a connection |
9695 |
-+ * @conn: The connection to disconnect |
9696 |
-+ * @ensure_queue_empty: Flag to indicate if the call should fail in |
9697 |
-+ * case the connection's message list is not |
9698 |
-+ * empty |
9699 |
-+ * |
9700 |
-+ * If @ensure_msg_list_empty is true, and the connection has pending messages, |
9701 |
-+ * -EBUSY is returned. |
9702 |
-+ * |
9703 |
-+ * Return: 0 on success, negative errno on failure |
9704 |
-+ */ |
9705 |
-+int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty) |
9706 |
-+{ |
9707 |
-+ struct kdbus_queue_entry *entry, *tmp; |
9708 |
-+ struct kdbus_bus *bus = conn->ep->bus; |
9709 |
-+ struct kdbus_reply *r, *r_tmp; |
9710 |
-+ struct kdbus_conn *c; |
9711 |
-+ int i, v; |
9712 |
-+ |
9713 |
-+ mutex_lock(&conn->lock); |
9714 |
-+ v = atomic_read(&conn->active); |
9715 |
-+ if (v == KDBUS_CONN_ACTIVE_NEW) { |
9716 |
-+ /* was never connected */ |
9717 |
-+ mutex_unlock(&conn->lock); |
9718 |
-+ return 0; |
9719 |
-+ } |
9720 |
-+ if (v < 0) { |
9721 |
-+ /* already dead */ |
9722 |
-+ mutex_unlock(&conn->lock); |
9723 |
-+ return -ECONNRESET; |
9724 |
-+ } |
9725 |
-+ if (ensure_queue_empty && !list_empty(&conn->queue.msg_list)) { |
9726 |
-+ /* still busy */ |
9727 |
-+ mutex_unlock(&conn->lock); |
9728 |
-+ return -EBUSY; |
9729 |
-+ } |
9730 |
-+ |
9731 |
-+ atomic_add(KDBUS_CONN_ACTIVE_BIAS, &conn->active); |
9732 |
-+ mutex_unlock(&conn->lock); |
9733 |
-+ |
9734 |
-+ wake_up_interruptible(&conn->wait); |
9735 |
-+ |
9736 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9737 |
-+ rwsem_acquire(&conn->dep_map, 0, 0, _RET_IP_); |
9738 |
-+ if (atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_BIAS) |
9739 |
-+ lock_contended(&conn->dep_map, _RET_IP_); |
9740 |
-+#endif |
9741 |
-+ |
9742 |
-+ wait_event(conn->wait, |
9743 |
-+ atomic_read(&conn->active) == KDBUS_CONN_ACTIVE_BIAS); |
9744 |
-+ |
9745 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9746 |
-+ lock_acquired(&conn->dep_map, _RET_IP_); |
9747 |
-+ rwsem_release(&conn->dep_map, 1, _RET_IP_); |
9748 |
-+#endif |
9749 |
-+ |
9750 |
-+ cancel_delayed_work_sync(&conn->work); |
9751 |
-+ kdbus_policy_remove_owner(&conn->ep->bus->policy_db, conn); |
9752 |
-+ |
9753 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
9754 |
-+ mutex_lock(&conn->ep->lock); |
9755 |
-+ down_write(&bus->conn_rwlock); |
9756 |
-+ |
9757 |
-+ /* remove from bus and endpoint */ |
9758 |
-+ hash_del(&conn->hentry); |
9759 |
-+ list_del(&conn->monitor_entry); |
9760 |
-+ list_del(&conn->ep_entry); |
9761 |
-+ |
9762 |
-+ up_write(&bus->conn_rwlock); |
9763 |
-+ mutex_unlock(&conn->ep->lock); |
9764 |
-+ |
9765 |
-+ /* |
9766 |
-+ * Remove all names associated with this connection; this possibly |
9767 |
-+ * moves queued messages back to the activator connection. |
9768 |
-+ */ |
9769 |
-+ kdbus_name_release_all(bus->name_registry, conn); |
9770 |
-+ |
9771 |
-+ /* if we die while other connections wait for our reply, notify them */ |
9772 |
-+ mutex_lock(&conn->lock); |
9773 |
-+ list_for_each_entry_safe(entry, tmp, &conn->queue.msg_list, entry) { |
9774 |
-+ if (entry->reply) |
9775 |
-+ kdbus_notify_reply_dead(bus, |
9776 |
-+ entry->reply->reply_dst->id, |
9777 |
-+ entry->reply->cookie); |
9778 |
-+ kdbus_queue_entry_free(entry); |
9779 |
-+ } |
9780 |
-+ |
9781 |
-+ list_for_each_entry_safe(r, r_tmp, &conn->reply_list, entry) |
9782 |
-+ kdbus_reply_unlink(r); |
9783 |
-+ mutex_unlock(&conn->lock); |
9784 |
-+ |
9785 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
9786 |
-+ down_read(&bus->conn_rwlock); |
9787 |
-+ hash_for_each(bus->conn_hash, i, c, hentry) { |
9788 |
-+ mutex_lock(&c->lock); |
9789 |
-+ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) { |
9790 |
-+ if (r->reply_src != conn) |
9791 |
-+ continue; |
9792 |
-+ |
9793 |
-+ if (r->sync) |
9794 |
-+ kdbus_sync_reply_wakeup(r, -EPIPE); |
9795 |
-+ else |
9796 |
-+ /* send a 'connection dead' notification */ |
9797 |
-+ kdbus_notify_reply_dead(bus, c->id, r->cookie); |
9798 |
-+ |
9799 |
-+ kdbus_reply_unlink(r); |
9800 |
-+ } |
9801 |
-+ mutex_unlock(&c->lock); |
9802 |
-+ } |
9803 |
-+ up_read(&bus->conn_rwlock); |
9804 |
-+ |
9805 |
-+ if (!kdbus_conn_is_monitor(conn)) |
9806 |
-+ kdbus_notify_id_change(bus, KDBUS_ITEM_ID_REMOVE, |
9807 |
-+ conn->id, conn->flags); |
9808 |
-+ |
9809 |
-+ kdbus_notify_flush(bus); |
9810 |
-+ |
9811 |
-+ return 0; |
9812 |
-+} |
9813 |
-+ |
9814 |
-+/** |
9815 |
-+ * kdbus_conn_has_name() - check if a connection owns a name |
9816 |
-+ * @conn: Connection |
9817 |
-+ * @name: Well-know name to check for |
9818 |
-+ * |
9819 |
-+ * The caller must hold the registry lock of conn->ep->bus. |
9820 |
-+ * |
9821 |
-+ * Return: true if the name is currently owned by the connection |
9822 |
-+ */ |
9823 |
-+bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name) |
9824 |
-+{ |
9825 |
-+ struct kdbus_name_owner *owner; |
9826 |
-+ |
9827 |
-+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
9828 |
-+ |
9829 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) |
9830 |
-+ if (!(owner->flags & KDBUS_NAME_IN_QUEUE) && |
9831 |
-+ !strcmp(name, owner->name->name)) |
9832 |
-+ return true; |
9833 |
-+ |
9834 |
-+ return false; |
9835 |
-+} |
9836 |
-+ |
9837 |
-+struct kdbus_quota { |
9838 |
-+ u32 memory; |
9839 |
-+ u16 msgs; |
9840 |
-+ u8 fds; |
9841 |
-+}; |
9842 |
-+ |
9843 |
-+/** |
9844 |
-+ * kdbus_conn_quota_inc() - increase quota accounting |
9845 |
-+ * @c: connection owning the quota tracking |
9846 |
-+ * @u: user to account for (or NULL for kernel accounting) |
9847 |
-+ * @memory: size of memory to account for |
9848 |
-+ * @fds: number of FDs to account for |
9849 |
-+ * |
9850 |
-+ * This call manages the quotas on resource @c. That is, it's used if other |
9851 |
-+ * users want to use the resources of connection @c, which so far only concerns |
9852 |
-+ * the receive queue of the destination. |
9853 |
-+ * |
9854 |
-+ * This increases the quota-accounting for user @u by @memory bytes and @fds |
9855 |
-+ * file descriptors. If the user has already reached the quota limits, this call |
9856 |
-+ * will not do any accounting but return a negative error code indicating the |
9857 |
-+ * failure. |
9858 |
-+ * |
9859 |
-+ * Return: 0 on success, negative error code on failure. |
9860 |
-+ */ |
9861 |
-+int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, |
9862 |
-+ size_t memory, size_t fds) |
9863 |
-+{ |
9864 |
-+ struct kdbus_quota *quota; |
9865 |
-+ size_t available, accounted; |
9866 |
-+ unsigned int id; |
9867 |
-+ |
9868 |
-+ /* |
9869 |
-+ * Pool Layout: |
9870 |
-+ * 50% of a pool is always owned by the connection. It is reserved for |
9871 |
-+ * kernel queries, handling received messages and other tasks that are |
9872 |
-+ * under control of the pool owner. The other 50% of the pool are used |
9873 |
-+ * as incoming queue. |
9874 |
-+ * As we optionally support user-space based policies, we need fair |
9875 |
-+ * allocation schemes. Furthermore, resource utilization should be |
9876 |
-+ * maximized, so only minimal resources stay reserved. However, we need |
9877 |
-+ * to adapt to a dynamic number of users, as we cannot know how many |
9878 |
-+ * users will talk to a connection. Therefore, the current allocation |
9879 |
-+ * works like this: |
9880 |
-+ * We limit the number of bytes in a destination's pool per sending |
9881 |
-+ * user. The space available for a user is 33% of the unused pool space |
9882 |
-+ * (whereas the space used by the user itself is also treated as |
9883 |
-+ * 'unused'). This way, we favor users coming first, but keep enough |
9884 |
-+ * pool space available for any following users. Given that messages are |
9885 |
-+ * dequeued in FIFO order, this should balance nicely if the number of |
9886 |
-+ * users grows. At the same time, this algorithm guarantees that the |
9887 |
-+ * space available to a connection is reduced dynamically, the more |
9888 |
-+ * concurrent users talk to a connection. |
9889 |
-+ */ |
9890 |
-+ |
9891 |
-+ /* per user-accounting is expensive, so we keep state small */ |
9892 |
-+ BUILD_BUG_ON(sizeof(quota->memory) != 4); |
9893 |
-+ BUILD_BUG_ON(sizeof(quota->msgs) != 2); |
9894 |
-+ BUILD_BUG_ON(sizeof(quota->fds) != 1); |
9895 |
-+ BUILD_BUG_ON(KDBUS_CONN_MAX_MSGS > U16_MAX); |
9896 |
-+ BUILD_BUG_ON(KDBUS_CONN_MAX_FDS_PER_USER > U8_MAX); |
9897 |
-+ |
9898 |
-+ id = u ? u->id : KDBUS_USER_KERNEL_ID; |
9899 |
-+ if (id >= c->n_quota) { |
9900 |
-+ unsigned int users; |
9901 |
-+ |
9902 |
-+ users = max(KDBUS_ALIGN8(id) + 8, id); |
9903 |
-+ quota = krealloc(c->quota, users * sizeof(*quota), |
9904 |
-+ GFP_KERNEL | __GFP_ZERO); |
9905 |
-+ if (!quota) |
9906 |
-+ return -ENOMEM; |
9907 |
-+ |
9908 |
-+ c->n_quota = users; |
9909 |
-+ c->quota = quota; |
9910 |
-+ } |
9911 |
-+ |
9912 |
-+ quota = &c->quota[id]; |
9913 |
-+ kdbus_pool_accounted(c->pool, &available, &accounted); |
9914 |
-+ |
9915 |
-+ /* half the pool is _always_ reserved for the pool owner */ |
9916 |
-+ available /= 2; |
9917 |
-+ |
9918 |
-+ /* |
9919 |
-+ * Pool owner slices are un-accounted slices; they can claim more |
9920 |
-+ * than 50% of the queue. However, the slices we're dealing with here |
9921 |
-+ * belong to the incoming queue, hence they are 'accounted' slices |
9922 |
-+ * to which the 50%-limit applies. |
9923 |
-+ */ |
9924 |
-+ if (available < accounted) |
9925 |
-+ return -ENOBUFS; |
9926 |
-+ |
9927 |
-+ /* 1/3 of the remaining space (including your own memory) */ |
9928 |
-+ available = (available - accounted + quota->memory) / 3; |
9929 |
-+ |
9930 |
-+ if (available < quota->memory || |
9931 |
-+ available - quota->memory < memory || |
9932 |
-+ quota->memory + memory > U32_MAX) |
9933 |
-+ return -ENOBUFS; |
9934 |
-+ if (quota->msgs >= KDBUS_CONN_MAX_MSGS) |
9935 |
-+ return -ENOBUFS; |
9936 |
-+ if (quota->fds + fds < quota->fds || |
9937 |
-+ quota->fds + fds > KDBUS_CONN_MAX_FDS_PER_USER) |
9938 |
-+ return -EMFILE; |
9939 |
-+ |
9940 |
-+ quota->memory += memory; |
9941 |
-+ quota->fds += fds; |
9942 |
-+ ++quota->msgs; |
9943 |
-+ return 0; |
9944 |
-+} |
9945 |
-+ |
9946 |
-+/** |
9947 |
-+ * kdbus_conn_quota_dec() - decrease quota accounting |
9948 |
-+ * @c: connection owning the quota tracking |
9949 |
-+ * @u: user which was accounted for (or NULL for kernel accounting) |
9950 |
-+ * @memory: size of memory which was accounted for |
9951 |
-+ * @fds: number of FDs which were accounted for |
9952 |
-+ * |
9953 |
-+ * This does the reverse of kdbus_conn_quota_inc(). You have to release any |
9954 |
-+ * accounted resources that you called kdbus_conn_quota_inc() for. However, you |
9955 |
-+ * must not call kdbus_conn_quota_dec() if the accounting failed (that is, |
9956 |
-+ * kdbus_conn_quota_inc() failed). |
9957 |
-+ */ |
9958 |
-+void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, |
9959 |
-+ size_t memory, size_t fds) |
9960 |
-+{ |
9961 |
-+ struct kdbus_quota *quota; |
9962 |
-+ unsigned int id; |
9963 |
-+ |
9964 |
-+ id = u ? u->id : KDBUS_USER_KERNEL_ID; |
9965 |
-+ if (WARN_ON(id >= c->n_quota)) |
9966 |
-+ return; |
9967 |
-+ |
9968 |
-+ quota = &c->quota[id]; |
9969 |
-+ |
9970 |
-+ if (!WARN_ON(quota->msgs == 0)) |
9971 |
-+ --quota->msgs; |
9972 |
-+ if (!WARN_ON(quota->memory < memory)) |
9973 |
-+ quota->memory -= memory; |
9974 |
-+ if (!WARN_ON(quota->fds < fds)) |
9975 |
-+ quota->fds -= fds; |
9976 |
-+} |
9977 |
-+ |
9978 |
-+/** |
9979 |
-+ * kdbus_conn_lost_message() - handle lost messages |
9980 |
-+ * @c: connection that lost a message |
9981 |
-+ * |
9982 |
-+ * kdbus is reliable. That means, we try hard to never lose messages. However, |
9983 |
-+ * memory is limited, so we cannot rely on transmissions to never fail. |
9984 |
-+ * Therefore, we use quota-limits to let callers know if their unicast message |
9985 |
-+ * cannot be transmitted to a peer. This works fine for unicasts, but for |
9986 |
-+ * broadcasts we cannot make the caller handle the transmission failure. |
9987 |
-+ * Instead, we must let the destination know that it couldn't receive a |
9988 |
-+ * broadcast. |
9989 |
-+ * As this is an unlikely scenario, we keep it simple. A single lost-counter |
9990 |
-+ * remembers the number of lost messages since the last call to RECV. The next |
9991 |
-+ * message retrieval will notify the connection that it lost messages since the |
9992 |
-+ * last message retrieval and thus should resync its state. |
9993 |
-+ */ |
9994 |
-+void kdbus_conn_lost_message(struct kdbus_conn *c) |
9995 |
-+{ |
9996 |
-+ if (atomic_inc_return(&c->lost_count) == 1) |
9997 |
-+ wake_up_interruptible(&c->wait); |
9998 |
-+} |
9999 |
-+ |
10000 |
-+/* Callers should take the conn_dst lock */ |
10001 |
-+static struct kdbus_queue_entry * |
10002 |
-+kdbus_conn_entry_make(struct kdbus_conn *conn_src, |
10003 |
-+ struct kdbus_conn *conn_dst, |
10004 |
-+ struct kdbus_staging *staging) |
10005 |
-+{ |
10006 |
-+ /* The remote connection was disconnected */ |
10007 |
-+ if (!kdbus_conn_active(conn_dst)) |
10008 |
-+ return ERR_PTR(-ECONNRESET); |
10009 |
-+ |
10010 |
-+ /* |
10011 |
-+ * If the connection does not accept file descriptors but the message |
10012 |
-+ * has some attached, refuse it. |
10013 |
-+ * |
10014 |
-+ * If this is a monitor connection, accept the message. In that |
10015 |
-+ * case, all file descriptors will be set to -1 at receive time. |
10016 |
-+ */ |
10017 |
-+ if (!kdbus_conn_is_monitor(conn_dst) && |
10018 |
-+ !(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) && |
10019 |
-+ staging->gaps && staging->gaps->n_fds > 0) |
10020 |
-+ return ERR_PTR(-ECOMM); |
10021 |
-+ |
10022 |
-+ return kdbus_queue_entry_new(conn_src, conn_dst, staging); |
10023 |
-+} |
10024 |
-+ |
10025 |
-+/* |
10026 |
-+ * Synchronously responding to a message, allocate a queue entry |
10027 |
-+ * and attach it to the reply tracking object. |
10028 |
-+ * The connection's queue will never get to see it. |
10029 |
-+ */ |
10030 |
-+static int kdbus_conn_entry_sync_attach(struct kdbus_conn *conn_dst, |
10031 |
-+ struct kdbus_staging *staging, |
10032 |
-+ struct kdbus_reply *reply_wake) |
10033 |
-+{ |
10034 |
-+ struct kdbus_queue_entry *entry; |
10035 |
-+ int remote_ret, ret = 0; |
10036 |
-+ |
10037 |
-+ mutex_lock(&reply_wake->reply_dst->lock); |
10038 |
-+ |
10039 |
-+ /* |
10040 |
-+ * If we are still waiting then proceed, allocate a queue |
10041 |
-+ * entry and attach it to the reply object |
10042 |
-+ */ |
10043 |
-+ if (reply_wake->waiting) { |
10044 |
-+ entry = kdbus_conn_entry_make(reply_wake->reply_src, conn_dst, |
10045 |
-+ staging); |
10046 |
-+ if (IS_ERR(entry)) |
10047 |
-+ ret = PTR_ERR(entry); |
10048 |
-+ else |
10049 |
-+ /* Attach the entry to the reply object */ |
10050 |
-+ reply_wake->queue_entry = entry; |
10051 |
-+ } else { |
10052 |
-+ ret = -ECONNRESET; |
10053 |
-+ } |
10054 |
-+ |
10055 |
-+ /* |
10056 |
-+ * Update the reply object and wake up remote peer only |
10057 |
-+ * on appropriate return codes |
10058 |
-+ * |
10059 |
-+ * * -ECOMM: if the replying connection failed with -ECOMM |
10060 |
-+ * then wakeup remote peer with -EREMOTEIO |
10061 |
-+ * |
10062 |
-+ * We do this to differenciate between -ECOMM errors |
10063 |
-+ * from the original sender perspective: |
10064 |
-+ * -ECOMM error during the sync send and |
10065 |
-+ * -ECOMM error during the sync reply, this last |
10066 |
-+ * one is rewritten to -EREMOTEIO |
10067 |
-+ * |
10068 |
-+ * * Wake up on all other return codes. |
10069 |
-+ */ |
10070 |
-+ remote_ret = ret; |
10071 |
-+ |
10072 |
-+ if (ret == -ECOMM) |
10073 |
-+ remote_ret = -EREMOTEIO; |
10074 |
-+ |
10075 |
-+ kdbus_sync_reply_wakeup(reply_wake, remote_ret); |
10076 |
-+ kdbus_reply_unlink(reply_wake); |
10077 |
-+ mutex_unlock(&reply_wake->reply_dst->lock); |
10078 |
-+ |
10079 |
-+ return ret; |
10080 |
-+} |
10081 |
-+ |
10082 |
-+/** |
10083 |
-+ * kdbus_conn_entry_insert() - enqueue a message into the receiver's pool |
10084 |
-+ * @conn_src: The sending connection |
10085 |
-+ * @conn_dst: The connection to queue into |
10086 |
-+ * @staging: Message to send |
10087 |
-+ * @reply: The reply tracker to attach to the queue entry |
10088 |
-+ * @name: Destination name this msg is sent to, or NULL |
10089 |
-+ * |
10090 |
-+ * Return: 0 on success. negative error otherwise. |
10091 |
-+ */ |
10092 |
-+int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, |
10093 |
-+ struct kdbus_conn *conn_dst, |
10094 |
-+ struct kdbus_staging *staging, |
10095 |
-+ struct kdbus_reply *reply, |
10096 |
-+ const struct kdbus_name_entry *name) |
10097 |
-+{ |
10098 |
-+ struct kdbus_queue_entry *entry; |
10099 |
-+ int ret; |
10100 |
-+ |
10101 |
-+ kdbus_conn_lock2(conn_src, conn_dst); |
10102 |
-+ |
10103 |
-+ entry = kdbus_conn_entry_make(conn_src, conn_dst, staging); |
10104 |
-+ if (IS_ERR(entry)) { |
10105 |
-+ ret = PTR_ERR(entry); |
10106 |
-+ goto exit_unlock; |
10107 |
-+ } |
10108 |
-+ |
10109 |
-+ if (reply) { |
10110 |
-+ kdbus_reply_link(reply); |
10111 |
-+ if (!reply->sync) |
10112 |
-+ schedule_delayed_work(&conn_src->work, 0); |
10113 |
-+ } |
10114 |
-+ |
10115 |
-+ /* |
10116 |
-+ * Record the sequence number of the registered name; it will |
10117 |
-+ * be remembered by the queue, in case messages addressed to a |
10118 |
-+ * name need to be moved from or to an activator. |
10119 |
-+ */ |
10120 |
-+ if (name) |
10121 |
-+ entry->dst_name_id = name->name_id; |
10122 |
-+ |
10123 |
-+ kdbus_queue_entry_enqueue(entry, reply); |
10124 |
-+ wake_up_interruptible(&conn_dst->wait); |
10125 |
-+ |
10126 |
-+ ret = 0; |
10127 |
-+ |
10128 |
-+exit_unlock: |
10129 |
-+ kdbus_conn_unlock2(conn_src, conn_dst); |
10130 |
-+ return ret; |
10131 |
-+} |
10132 |
-+ |
10133 |
-+static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src, |
10134 |
-+ struct kdbus_cmd_send *cmd_send, |
10135 |
-+ struct file *ioctl_file, |
10136 |
-+ struct file *cancel_fd, |
10137 |
-+ struct kdbus_reply *reply_wait, |
10138 |
-+ ktime_t expire) |
10139 |
-+{ |
10140 |
-+ struct kdbus_queue_entry *entry; |
10141 |
-+ struct poll_wqueues pwq = {}; |
10142 |
-+ int ret; |
10143 |
-+ |
10144 |
-+ if (WARN_ON(!reply_wait)) |
10145 |
-+ return -EIO; |
10146 |
-+ |
10147 |
-+ /* |
10148 |
-+ * Block until the reply arrives. reply_wait is left untouched |
10149 |
-+ * by the timeout scans that might be conducted for other, |
10150 |
-+ * asynchronous replies of conn_src. |
10151 |
-+ */ |
10152 |
-+ |
10153 |
-+ poll_initwait(&pwq); |
10154 |
-+ poll_wait(ioctl_file, &conn_src->wait, &pwq.pt); |
10155 |
-+ |
10156 |
-+ for (;;) { |
10157 |
-+ /* |
10158 |
-+ * Any of the following conditions will stop our synchronously |
10159 |
-+ * blocking SEND command: |
10160 |
-+ * |
10161 |
-+ * a) The origin sender closed its connection |
10162 |
-+ * b) The remote peer answered, setting reply_wait->waiting = 0 |
10163 |
-+ * c) The cancel FD was written to |
10164 |
-+ * d) A signal was received |
10165 |
-+ * e) The specified timeout was reached, and none of the above |
10166 |
-+ * conditions kicked in. |
10167 |
-+ */ |
10168 |
-+ |
10169 |
-+ /* |
10170 |
-+ * We have already acquired an active reference when |
10171 |
-+ * entering here, but another thread may call |
10172 |
-+ * KDBUS_CMD_BYEBYE which does not acquire an active |
10173 |
-+ * reference, therefore kdbus_conn_disconnect() will |
10174 |
-+ * not wait for us. |
10175 |
-+ */ |
10176 |
-+ if (!kdbus_conn_active(conn_src)) { |
10177 |
-+ ret = -ECONNRESET; |
10178 |
-+ break; |
10179 |
-+ } |
10180 |
-+ |
10181 |
-+ /* |
10182 |
-+ * After the replying peer unset the waiting variable |
10183 |
-+ * it will wake up us. |
10184 |
-+ */ |
10185 |
-+ if (!reply_wait->waiting) { |
10186 |
-+ ret = reply_wait->err; |
10187 |
-+ break; |
10188 |
-+ } |
10189 |
-+ |
10190 |
-+ if (cancel_fd) { |
10191 |
-+ unsigned int r; |
10192 |
-+ |
10193 |
-+ r = cancel_fd->f_op->poll(cancel_fd, &pwq.pt); |
10194 |
-+ if (r & POLLIN) { |
10195 |
-+ ret = -ECANCELED; |
10196 |
-+ break; |
10197 |
-+ } |
10198 |
-+ } |
10199 |
-+ |
10200 |
-+ if (signal_pending(current)) { |
10201 |
-+ ret = -EINTR; |
10202 |
-+ break; |
10203 |
-+ } |
10204 |
-+ |
10205 |
-+ if (!poll_schedule_timeout(&pwq, TASK_INTERRUPTIBLE, |
10206 |
-+ &expire, 0)) { |
10207 |
-+ ret = -ETIMEDOUT; |
10208 |
-+ break; |
10209 |
-+ } |
10210 |
-+ |
10211 |
-+ /* |
10212 |
-+ * Reset the poll worker func, so the waitqueues are not |
10213 |
-+ * added to the poll table again. We just reuse what we've |
10214 |
-+ * collected earlier for further iterations. |
10215 |
-+ */ |
10216 |
-+ init_poll_funcptr(&pwq.pt, NULL); |
10217 |
-+ } |
10218 |
-+ |
10219 |
-+ poll_freewait(&pwq); |
10220 |
-+ |
10221 |
-+ if (ret == -EINTR) { |
10222 |
-+ /* |
10223 |
-+ * Interrupted system call. Unref the reply object, and pass |
10224 |
-+ * the return value down the chain. Mark the reply as |
10225 |
-+ * interrupted, so the cleanup work can remove it, but do not |
10226 |
-+ * unlink it from the list. Once the syscall restarts, we'll |
10227 |
-+ * pick it up and wait on it again. |
10228 |
-+ */ |
10229 |
-+ mutex_lock(&conn_src->lock); |
10230 |
-+ reply_wait->interrupted = true; |
10231 |
-+ schedule_delayed_work(&conn_src->work, 0); |
10232 |
-+ mutex_unlock(&conn_src->lock); |
10233 |
-+ |
10234 |
-+ return -ERESTARTSYS; |
10235 |
-+ } |
10236 |
-+ |
10237 |
-+ mutex_lock(&conn_src->lock); |
10238 |
-+ reply_wait->waiting = false; |
10239 |
-+ entry = reply_wait->queue_entry; |
10240 |
-+ if (entry) { |
10241 |
-+ ret = kdbus_queue_entry_install(entry, |
10242 |
-+ &cmd_send->reply.return_flags, |
10243 |
-+ true); |
10244 |
-+ kdbus_pool_slice_publish(entry->slice, &cmd_send->reply.offset, |
10245 |
-+ &cmd_send->reply.msg_size); |
10246 |
-+ kdbus_queue_entry_free(entry); |
10247 |
-+ } |
10248 |
-+ kdbus_reply_unlink(reply_wait); |
10249 |
-+ mutex_unlock(&conn_src->lock); |
10250 |
-+ |
10251 |
-+ return ret; |
10252 |
-+} |
10253 |
-+ |
10254 |
-+static int kdbus_pin_dst(struct kdbus_bus *bus, |
10255 |
-+ struct kdbus_staging *staging, |
10256 |
-+ struct kdbus_name_entry **out_name, |
10257 |
-+ struct kdbus_conn **out_dst) |
10258 |
-+{ |
10259 |
-+ const struct kdbus_msg *msg = staging->msg; |
10260 |
-+ struct kdbus_name_owner *owner = NULL; |
10261 |
-+ struct kdbus_name_entry *name = NULL; |
10262 |
-+ struct kdbus_conn *dst = NULL; |
10263 |
-+ int ret; |
10264 |
-+ |
10265 |
-+ lockdep_assert_held(&bus->name_registry->rwlock); |
10266 |
-+ |
10267 |
-+ if (!staging->dst_name) { |
10268 |
-+ dst = kdbus_bus_find_conn_by_id(bus, msg->dst_id); |
10269 |
-+ if (!dst) |
10270 |
-+ return -ENXIO; |
10271 |
-+ |
10272 |
-+ if (!kdbus_conn_is_ordinary(dst)) { |
10273 |
-+ ret = -ENXIO; |
10274 |
-+ goto error; |
10275 |
-+ } |
10276 |
-+ } else { |
10277 |
-+ name = kdbus_name_lookup_unlocked(bus->name_registry, |
10278 |
-+ staging->dst_name); |
10279 |
-+ if (name) |
10280 |
-+ owner = kdbus_name_get_owner(name); |
10281 |
-+ if (!owner) |
10282 |
-+ return -ESRCH; |
10283 |
-+ |
10284 |
-+ /* |
10285 |
-+ * If both a name and a connection ID are given as destination |
10286 |
-+ * of a message, check that the currently owning connection of |
10287 |
-+ * the name matches the specified ID. |
10288 |
-+ * This way, we allow userspace to send the message to a |
10289 |
-+ * specific connection by ID only if the connection currently |
10290 |
-+ * owns the given name. |
10291 |
-+ */ |
10292 |
-+ if (msg->dst_id != KDBUS_DST_ID_NAME && |
10293 |
-+ msg->dst_id != owner->conn->id) |
10294 |
-+ return -EREMCHG; |
10295 |
-+ |
10296 |
-+ if ((msg->flags & KDBUS_MSG_NO_AUTO_START) && |
10297 |
-+ kdbus_conn_is_activator(owner->conn)) |
10298 |
-+ return -EADDRNOTAVAIL; |
10299 |
-+ |
10300 |
-+ dst = kdbus_conn_ref(owner->conn); |
10301 |
-+ } |
10302 |
-+ |
10303 |
-+ *out_name = name; |
10304 |
-+ *out_dst = dst; |
10305 |
-+ return 0; |
10306 |
-+ |
10307 |
-+error: |
10308 |
-+ kdbus_conn_unref(dst); |
10309 |
-+ return ret; |
10310 |
-+} |
10311 |
-+ |
10312 |
-+static int kdbus_conn_reply(struct kdbus_conn *src, |
10313 |
-+ struct kdbus_staging *staging) |
10314 |
-+{ |
10315 |
-+ const struct kdbus_msg *msg = staging->msg; |
10316 |
-+ struct kdbus_name_entry *name = NULL; |
10317 |
-+ struct kdbus_reply *reply, *wake = NULL; |
10318 |
-+ struct kdbus_conn *dst = NULL; |
10319 |
-+ struct kdbus_bus *bus = src->ep->bus; |
10320 |
-+ int ret; |
10321 |
-+ |
10322 |
-+ if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) || |
10323 |
-+ WARN_ON(msg->flags & KDBUS_MSG_EXPECT_REPLY) || |
10324 |
-+ WARN_ON(msg->flags & KDBUS_MSG_SIGNAL)) |
10325 |
-+ return -EINVAL; |
10326 |
-+ |
10327 |
-+ /* name-registry must be locked for lookup *and* collecting data */ |
10328 |
-+ down_read(&bus->name_registry->rwlock); |
10329 |
-+ |
10330 |
-+ /* find and pin destination */ |
10331 |
-+ |
10332 |
-+ ret = kdbus_pin_dst(bus, staging, &name, &dst); |
10333 |
-+ if (ret < 0) |
10334 |
-+ goto exit; |
10335 |
-+ |
10336 |
-+ mutex_lock(&dst->lock); |
10337 |
-+ reply = kdbus_reply_find(src, dst, msg->cookie_reply); |
10338 |
-+ if (reply) { |
10339 |
-+ if (reply->sync) |
10340 |
-+ wake = kdbus_reply_ref(reply); |
10341 |
-+ kdbus_reply_unlink(reply); |
10342 |
-+ } |
10343 |
-+ mutex_unlock(&dst->lock); |
10344 |
-+ |
10345 |
-+ if (!reply) { |
10346 |
-+ ret = -EBADSLT; |
10347 |
-+ goto exit; |
10348 |
-+ } |
10349 |
-+ |
10350 |
-+ /* send message */ |
10351 |
-+ |
10352 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10353 |
-+ |
10354 |
-+ if (wake) |
10355 |
-+ ret = kdbus_conn_entry_sync_attach(dst, staging, wake); |
10356 |
-+ else |
10357 |
-+ ret = kdbus_conn_entry_insert(src, dst, staging, NULL, name); |
10358 |
-+ |
10359 |
-+exit: |
10360 |
-+ up_read(&bus->name_registry->rwlock); |
10361 |
-+ kdbus_reply_unref(wake); |
10362 |
-+ kdbus_conn_unref(dst); |
10363 |
-+ return ret; |
10364 |
-+} |
10365 |
-+ |
10366 |
-+static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src, |
10367 |
-+ struct kdbus_staging *staging, |
10368 |
-+ ktime_t exp) |
10369 |
-+{ |
10370 |
-+ const struct kdbus_msg *msg = staging->msg; |
10371 |
-+ struct kdbus_name_entry *name = NULL; |
10372 |
-+ struct kdbus_reply *wait = NULL; |
10373 |
-+ struct kdbus_conn *dst = NULL; |
10374 |
-+ struct kdbus_bus *bus = src->ep->bus; |
10375 |
-+ int ret; |
10376 |
-+ |
10377 |
-+ if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) || |
10378 |
-+ WARN_ON(msg->flags & KDBUS_MSG_SIGNAL) || |
10379 |
-+ WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY))) |
10380 |
-+ return ERR_PTR(-EINVAL); |
10381 |
-+ |
10382 |
-+ /* resume previous wait-context, if available */ |
10383 |
-+ |
10384 |
-+ mutex_lock(&src->lock); |
10385 |
-+ wait = kdbus_reply_find(NULL, src, msg->cookie); |
10386 |
-+ if (wait) { |
10387 |
-+ if (wait->interrupted) { |
10388 |
-+ kdbus_reply_ref(wait); |
10389 |
-+ wait->interrupted = false; |
10390 |
-+ } else { |
10391 |
-+ wait = NULL; |
10392 |
-+ } |
10393 |
-+ } |
10394 |
-+ mutex_unlock(&src->lock); |
10395 |
-+ |
10396 |
-+ if (wait) |
10397 |
-+ return wait; |
10398 |
-+ |
10399 |
-+ if (ktime_compare(ktime_get(), exp) >= 0) |
10400 |
-+ return ERR_PTR(-ETIMEDOUT); |
10401 |
-+ |
10402 |
-+ /* name-registry must be locked for lookup *and* collecting data */ |
10403 |
-+ down_read(&bus->name_registry->rwlock); |
10404 |
-+ |
10405 |
-+ /* find and pin destination */ |
10406 |
-+ |
10407 |
-+ ret = kdbus_pin_dst(bus, staging, &name, &dst); |
10408 |
-+ if (ret < 0) |
10409 |
-+ goto exit; |
10410 |
-+ |
10411 |
-+ if (!kdbus_conn_policy_talk(src, current_cred(), dst)) { |
10412 |
-+ ret = -EPERM; |
10413 |
-+ goto exit; |
10414 |
-+ } |
10415 |
-+ |
10416 |
-+ wait = kdbus_reply_new(dst, src, msg, name, true); |
10417 |
-+ if (IS_ERR(wait)) { |
10418 |
-+ ret = PTR_ERR(wait); |
10419 |
-+ wait = NULL; |
10420 |
-+ goto exit; |
10421 |
-+ } |
10422 |
-+ |
10423 |
-+ /* send message */ |
10424 |
-+ |
10425 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10426 |
-+ |
10427 |
-+ ret = kdbus_conn_entry_insert(src, dst, staging, wait, name); |
10428 |
-+ if (ret < 0) |
10429 |
-+ goto exit; |
10430 |
-+ |
10431 |
-+ ret = 0; |
10432 |
-+ |
10433 |
-+exit: |
10434 |
-+ up_read(&bus->name_registry->rwlock); |
10435 |
-+ if (ret < 0) { |
10436 |
-+ kdbus_reply_unref(wait); |
10437 |
-+ wait = ERR_PTR(ret); |
10438 |
-+ } |
10439 |
-+ kdbus_conn_unref(dst); |
10440 |
-+ return wait; |
10441 |
-+} |
10442 |
-+ |
10443 |
-+static int kdbus_conn_unicast(struct kdbus_conn *src, |
10444 |
-+ struct kdbus_staging *staging) |
10445 |
-+{ |
10446 |
-+ const struct kdbus_msg *msg = staging->msg; |
10447 |
-+ struct kdbus_name_entry *name = NULL; |
10448 |
-+ struct kdbus_reply *wait = NULL; |
10449 |
-+ struct kdbus_conn *dst = NULL; |
10450 |
-+ struct kdbus_bus *bus = src->ep->bus; |
10451 |
-+ bool is_signal = (msg->flags & KDBUS_MSG_SIGNAL); |
10452 |
-+ int ret = 0; |
10453 |
-+ |
10454 |
-+ if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) || |
10455 |
-+ WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY) && |
10456 |
-+ msg->cookie_reply != 0)) |
10457 |
-+ return -EINVAL; |
10458 |
-+ |
10459 |
-+ /* name-registry must be locked for lookup *and* collecting data */ |
10460 |
-+ down_read(&bus->name_registry->rwlock); |
10461 |
-+ |
10462 |
-+ /* find and pin destination */ |
10463 |
-+ |
10464 |
-+ ret = kdbus_pin_dst(bus, staging, &name, &dst); |
10465 |
-+ if (ret < 0) |
10466 |
-+ goto exit; |
10467 |
-+ |
10468 |
-+ if (is_signal) { |
10469 |
-+ /* like broadcasts we eavesdrop even if the msg is dropped */ |
10470 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10471 |
-+ |
10472 |
-+ /* drop silently if peer is not interested or not privileged */ |
10473 |
-+ if (!kdbus_match_db_match_msg(dst->match_db, src, staging) || |
10474 |
-+ !kdbus_conn_policy_talk(dst, NULL, src)) |
10475 |
-+ goto exit; |
10476 |
-+ } else if (!kdbus_conn_policy_talk(src, current_cred(), dst)) { |
10477 |
-+ ret = -EPERM; |
10478 |
-+ goto exit; |
10479 |
-+ } else if (msg->flags & KDBUS_MSG_EXPECT_REPLY) { |
10480 |
-+ wait = kdbus_reply_new(dst, src, msg, name, false); |
10481 |
-+ if (IS_ERR(wait)) { |
10482 |
-+ ret = PTR_ERR(wait); |
10483 |
-+ wait = NULL; |
10484 |
-+ goto exit; |
10485 |
-+ } |
10486 |
-+ } |
10487 |
-+ |
10488 |
-+ /* send message */ |
10489 |
-+ |
10490 |
-+ if (!is_signal) |
10491 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10492 |
-+ |
10493 |
-+ ret = kdbus_conn_entry_insert(src, dst, staging, wait, name); |
10494 |
-+ if (ret < 0 && !is_signal) |
10495 |
-+ goto exit; |
10496 |
-+ |
10497 |
-+ /* signals are treated like broadcasts, recv-errors are ignored */ |
10498 |
-+ ret = 0; |
10499 |
-+ |
10500 |
-+exit: |
10501 |
-+ up_read(&bus->name_registry->rwlock); |
10502 |
-+ kdbus_reply_unref(wait); |
10503 |
-+ kdbus_conn_unref(dst); |
10504 |
-+ return ret; |
10505 |
-+} |
10506 |
-+ |
10507 |
-+/** |
10508 |
-+ * kdbus_conn_move_messages() - move messages from one connection to another |
10509 |
-+ * @conn_dst: Connection to copy to |
10510 |
-+ * @conn_src: Connection to copy from |
10511 |
-+ * @name_id: Filter for the sequence number of the registered |
10512 |
-+ * name, 0 means no filtering. |
10513 |
-+ * |
10514 |
-+ * Move all messages from one connection to another. This is used when |
10515 |
-+ * an implementer connection is taking over/giving back a well-known name |
10516 |
-+ * from/to an activator connection. |
10517 |
-+ */ |
10518 |
-+void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, |
10519 |
-+ struct kdbus_conn *conn_src, |
10520 |
-+ u64 name_id) |
10521 |
-+{ |
10522 |
-+ struct kdbus_queue_entry *e, *e_tmp; |
10523 |
-+ struct kdbus_reply *r, *r_tmp; |
10524 |
-+ struct kdbus_bus *bus; |
10525 |
-+ struct kdbus_conn *c; |
10526 |
-+ LIST_HEAD(msg_list); |
10527 |
-+ int i, ret = 0; |
10528 |
-+ |
10529 |
-+ if (WARN_ON(conn_src == conn_dst)) |
10530 |
-+ return; |
10531 |
-+ |
10532 |
-+ bus = conn_src->ep->bus; |
10533 |
-+ |
10534 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
10535 |
-+ down_read(&bus->conn_rwlock); |
10536 |
-+ hash_for_each(bus->conn_hash, i, c, hentry) { |
10537 |
-+ if (c == conn_src || c == conn_dst) |
10538 |
-+ continue; |
10539 |
-+ |
10540 |
-+ mutex_lock(&c->lock); |
10541 |
-+ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) { |
10542 |
-+ if (r->reply_src != conn_src) |
10543 |
-+ continue; |
10544 |
-+ |
10545 |
-+ /* filter messages for a specific name */ |
10546 |
-+ if (name_id > 0 && r->name_id != name_id) |
10547 |
-+ continue; |
10548 |
-+ |
10549 |
-+ kdbus_conn_unref(r->reply_src); |
10550 |
-+ r->reply_src = kdbus_conn_ref(conn_dst); |
10551 |
-+ } |
10552 |
-+ mutex_unlock(&c->lock); |
10553 |
-+ } |
10554 |
-+ up_read(&bus->conn_rwlock); |
10555 |
-+ |
10556 |
-+ kdbus_conn_lock2(conn_src, conn_dst); |
10557 |
-+ list_for_each_entry_safe(e, e_tmp, &conn_src->queue.msg_list, entry) { |
10558 |
-+ /* filter messages for a specific name */ |
10559 |
-+ if (name_id > 0 && e->dst_name_id != name_id) |
10560 |
-+ continue; |
10561 |
-+ |
10562 |
-+ if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) && |
10563 |
-+ e->gaps && e->gaps->n_fds > 0) { |
10564 |
-+ kdbus_conn_lost_message(conn_dst); |
10565 |
-+ kdbus_queue_entry_free(e); |
10566 |
-+ continue; |
10567 |
-+ } |
10568 |
-+ |
10569 |
-+ ret = kdbus_queue_entry_move(e, conn_dst); |
10570 |
-+ if (ret < 0) { |
10571 |
-+ kdbus_conn_lost_message(conn_dst); |
10572 |
-+ kdbus_queue_entry_free(e); |
10573 |
-+ continue; |
10574 |
-+ } |
10575 |
-+ } |
10576 |
-+ kdbus_conn_unlock2(conn_src, conn_dst); |
10577 |
-+ |
10578 |
-+ /* wake up poll() */ |
10579 |
-+ wake_up_interruptible(&conn_dst->wait); |
10580 |
-+} |
10581 |
-+ |
10582 |
-+/* query the policy-database for all names of @whom */ |
10583 |
-+static bool kdbus_conn_policy_query_all(struct kdbus_conn *conn, |
10584 |
-+ const struct cred *conn_creds, |
10585 |
-+ struct kdbus_policy_db *db, |
10586 |
-+ struct kdbus_conn *whom, |
10587 |
-+ unsigned int access) |
10588 |
-+{ |
10589 |
-+ struct kdbus_name_owner *owner; |
10590 |
-+ bool pass = false; |
10591 |
-+ int res; |
10592 |
-+ |
10593 |
-+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
10594 |
-+ |
10595 |
-+ down_read(&db->entries_rwlock); |
10596 |
-+ mutex_lock(&whom->lock); |
10597 |
-+ |
10598 |
-+ list_for_each_entry(owner, &whom->names_list, conn_entry) { |
10599 |
-+ if (owner->flags & KDBUS_NAME_IN_QUEUE) |
10600 |
-+ continue; |
10601 |
-+ |
10602 |
-+ res = kdbus_policy_query_unlocked(db, |
10603 |
-+ conn_creds ? : conn->cred, |
10604 |
-+ owner->name->name, |
10605 |
-+ kdbus_strhash(owner->name->name)); |
10606 |
-+ if (res >= (int)access) { |
10607 |
-+ pass = true; |
10608 |
-+ break; |
10609 |
-+ } |
10610 |
-+ } |
10611 |
-+ |
10612 |
-+ mutex_unlock(&whom->lock); |
10613 |
-+ up_read(&db->entries_rwlock); |
10614 |
-+ |
10615 |
-+ return pass; |
10616 |
-+} |
10617 |
-+ |
10618 |
-+/** |
10619 |
-+ * kdbus_conn_policy_own_name() - verify a connection can own the given name |
10620 |
-+ * @conn: Connection |
10621 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10622 |
-+ * @name: Name |
10623 |
-+ * |
10624 |
-+ * This verifies that @conn is allowed to acquire the well-known name @name. |
10625 |
-+ * |
10626 |
-+ * Return: true if allowed, false if not. |
10627 |
-+ */ |
10628 |
-+bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, |
10629 |
-+ const struct cred *conn_creds, |
10630 |
-+ const char *name) |
10631 |
-+{ |
10632 |
-+ unsigned int hash = kdbus_strhash(name); |
10633 |
-+ int res; |
10634 |
-+ |
10635 |
-+ if (!conn_creds) |
10636 |
-+ conn_creds = conn->cred; |
10637 |
-+ |
10638 |
-+ if (conn->ep->user) { |
10639 |
-+ res = kdbus_policy_query(&conn->ep->policy_db, conn_creds, |
10640 |
-+ name, hash); |
10641 |
-+ if (res < KDBUS_POLICY_OWN) |
10642 |
-+ return false; |
10643 |
-+ } |
10644 |
-+ |
10645 |
-+ if (conn->owner) |
10646 |
-+ return true; |
10647 |
-+ |
10648 |
-+ res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds, |
10649 |
-+ name, hash); |
10650 |
-+ return res >= KDBUS_POLICY_OWN; |
10651 |
-+} |
10652 |
-+ |
10653 |
-+/** |
10654 |
-+ * kdbus_conn_policy_talk() - verify a connection can talk to a given peer |
10655 |
-+ * @conn: Connection that tries to talk |
10656 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10657 |
-+ * @to: Connection that is talked to |
10658 |
-+ * |
10659 |
-+ * This verifies that @conn is allowed to talk to @to. |
10660 |
-+ * |
10661 |
-+ * Return: true if allowed, false if not. |
10662 |
-+ */ |
10663 |
-+bool kdbus_conn_policy_talk(struct kdbus_conn *conn, |
10664 |
-+ const struct cred *conn_creds, |
10665 |
-+ struct kdbus_conn *to) |
10666 |
-+{ |
10667 |
-+ if (!conn_creds) |
10668 |
-+ conn_creds = conn->cred; |
10669 |
-+ |
10670 |
-+ if (conn->ep->user && |
10671 |
-+ !kdbus_conn_policy_query_all(conn, conn_creds, &conn->ep->policy_db, |
10672 |
-+ to, KDBUS_POLICY_TALK)) |
10673 |
-+ return false; |
10674 |
-+ |
10675 |
-+ if (conn->owner) |
10676 |
-+ return true; |
10677 |
-+ if (uid_eq(conn_creds->euid, to->cred->uid)) |
10678 |
-+ return true; |
10679 |
-+ |
10680 |
-+ return kdbus_conn_policy_query_all(conn, conn_creds, |
10681 |
-+ &conn->ep->bus->policy_db, to, |
10682 |
-+ KDBUS_POLICY_TALK); |
10683 |
-+} |
10684 |
-+ |
10685 |
-+/** |
10686 |
-+ * kdbus_conn_policy_see_name_unlocked() - verify a connection can see a given |
10687 |
-+ * name |
10688 |
-+ * @conn: Connection |
10689 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10690 |
-+ * @name: Name |
10691 |
-+ * |
10692 |
-+ * This verifies that @conn is allowed to see the well-known name @name. Caller |
10693 |
-+ * must hold policy-lock. |
10694 |
-+ * |
10695 |
-+ * Return: true if allowed, false if not. |
10696 |
-+ */ |
10697 |
-+bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, |
10698 |
-+ const struct cred *conn_creds, |
10699 |
-+ const char *name) |
10700 |
-+{ |
10701 |
-+ int res; |
10702 |
-+ |
10703 |
-+ /* |
10704 |
-+ * By default, all names are visible on a bus. SEE policies can only be |
10705 |
-+ * installed on custom endpoints, where by default no name is visible. |
10706 |
-+ */ |
10707 |
-+ if (!conn->ep->user) |
10708 |
-+ return true; |
10709 |
-+ |
10710 |
-+ res = kdbus_policy_query_unlocked(&conn->ep->policy_db, |
10711 |
-+ conn_creds ? : conn->cred, |
10712 |
-+ name, kdbus_strhash(name)); |
10713 |
-+ return res >= KDBUS_POLICY_SEE; |
10714 |
-+} |
10715 |
-+ |
10716 |
-+static bool kdbus_conn_policy_see_name(struct kdbus_conn *conn, |
10717 |
-+ const struct cred *conn_creds, |
10718 |
-+ const char *name) |
10719 |
-+{ |
10720 |
-+ bool res; |
10721 |
-+ |
10722 |
-+ down_read(&conn->ep->policy_db.entries_rwlock); |
10723 |
-+ res = kdbus_conn_policy_see_name_unlocked(conn, conn_creds, name); |
10724 |
-+ up_read(&conn->ep->policy_db.entries_rwlock); |
10725 |
-+ |
10726 |
-+ return res; |
10727 |
-+} |
10728 |
-+ |
10729 |
-+static bool kdbus_conn_policy_see(struct kdbus_conn *conn, |
10730 |
-+ const struct cred *conn_creds, |
10731 |
-+ struct kdbus_conn *whom) |
10732 |
-+{ |
10733 |
-+ /* |
10734 |
-+ * By default, all names are visible on a bus, so a connection can |
10735 |
-+ * always see other connections. SEE policies can only be installed on |
10736 |
-+ * custom endpoints, where by default no name is visible and we hide |
10737 |
-+ * peers from each other, unless you see at least _one_ name of the |
10738 |
-+ * peer. |
10739 |
-+ */ |
10740 |
-+ return !conn->ep->user || |
10741 |
-+ kdbus_conn_policy_query_all(conn, conn_creds, |
10742 |
-+ &conn->ep->policy_db, whom, |
10743 |
-+ KDBUS_POLICY_SEE); |
10744 |
-+} |
10745 |
-+ |
10746 |
-+/** |
10747 |
-+ * kdbus_conn_policy_see_notification() - verify a connection is allowed to |
10748 |
-+ * receive a given kernel notification |
10749 |
-+ * @conn: Connection |
10750 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10751 |
-+ * @msg: Notification message |
10752 |
-+ * |
10753 |
-+ * This checks whether @conn is allowed to see the kernel notification. |
10754 |
-+ * |
10755 |
-+ * Return: true if allowed, false if not. |
10756 |
-+ */ |
10757 |
-+bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, |
10758 |
-+ const struct cred *conn_creds, |
10759 |
-+ const struct kdbus_msg *msg) |
10760 |
-+{ |
10761 |
-+ /* |
10762 |
-+ * Depending on the notification type, broadcasted kernel notifications |
10763 |
-+ * have to be filtered: |
10764 |
-+ * |
10765 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}: This notification is forwarded |
10766 |
-+ * to a peer if, and only if, that peer can see the name this |
10767 |
-+ * notification is for. |
10768 |
-+ * |
10769 |
-+ * KDBUS_ITEM_ID_{ADD,REMOVE}: Notifications for ID changes are |
10770 |
-+ * broadcast to everyone, to allow tracking peers. |
10771 |
-+ */ |
10772 |
-+ |
10773 |
-+ switch (msg->items[0].type) { |
10774 |
-+ case KDBUS_ITEM_NAME_ADD: |
10775 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
10776 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
10777 |
-+ return kdbus_conn_policy_see_name(conn, conn_creds, |
10778 |
-+ msg->items[0].name_change.name); |
10779 |
-+ |
10780 |
-+ case KDBUS_ITEM_ID_ADD: |
10781 |
-+ case KDBUS_ITEM_ID_REMOVE: |
10782 |
-+ return true; |
10783 |
-+ |
10784 |
-+ default: |
10785 |
-+ WARN(1, "Invalid type for notification broadcast: %llu\n", |
10786 |
-+ (unsigned long long)msg->items[0].type); |
10787 |
-+ return false; |
10788 |
-+ } |
10789 |
-+} |
10790 |
-+ |
10791 |
-+/** |
10792 |
-+ * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO |
10793 |
-+ * @ep: Endpoint to operate on |
10794 |
-+ * @file: File this connection is opened on |
10795 |
-+ * @argp: Command payload |
10796 |
-+ * |
10797 |
-+ * Return: NULL or newly created connection on success, ERR_PTR on failure. |
10798 |
-+ */ |
10799 |
-+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file, |
10800 |
-+ void __user *argp) |
10801 |
-+{ |
10802 |
-+ struct kdbus_cmd_hello *cmd; |
10803 |
-+ struct kdbus_conn *c = NULL; |
10804 |
-+ const char *item_name; |
10805 |
-+ int ret; |
10806 |
-+ |
10807 |
-+ struct kdbus_arg argv[] = { |
10808 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
10809 |
-+ { .type = KDBUS_ITEM_NAME }, |
10810 |
-+ { .type = KDBUS_ITEM_CREDS }, |
10811 |
-+ { .type = KDBUS_ITEM_PIDS }, |
10812 |
-+ { .type = KDBUS_ITEM_SECLABEL }, |
10813 |
-+ { .type = KDBUS_ITEM_CONN_DESCRIPTION }, |
10814 |
-+ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
10815 |
-+ }; |
10816 |
-+ struct kdbus_args args = { |
10817 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
10818 |
-+ KDBUS_HELLO_ACCEPT_FD | |
10819 |
-+ KDBUS_HELLO_ACTIVATOR | |
10820 |
-+ KDBUS_HELLO_POLICY_HOLDER | |
10821 |
-+ KDBUS_HELLO_MONITOR, |
10822 |
-+ .argv = argv, |
10823 |
-+ .argc = ARRAY_SIZE(argv), |
10824 |
-+ }; |
10825 |
-+ |
10826 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
10827 |
-+ if (ret < 0) |
10828 |
-+ return ERR_PTR(ret); |
10829 |
-+ if (ret > 0) |
10830 |
-+ return NULL; |
10831 |
-+ |
10832 |
-+ item_name = argv[1].item ? argv[1].item->str : NULL; |
10833 |
-+ |
10834 |
-+ c = kdbus_conn_new(ep, file, cmd, item_name, |
10835 |
-+ argv[2].item ? &argv[2].item->creds : NULL, |
10836 |
-+ argv[3].item ? &argv[3].item->pids : NULL, |
10837 |
-+ argv[4].item ? argv[4].item->str : NULL, |
10838 |
-+ argv[5].item ? argv[5].item->str : NULL); |
10839 |
-+ if (IS_ERR(c)) { |
10840 |
-+ ret = PTR_ERR(c); |
10841 |
-+ c = NULL; |
10842 |
-+ goto exit; |
10843 |
-+ } |
10844 |
-+ |
10845 |
-+ ret = kdbus_conn_connect(c, item_name); |
10846 |
-+ if (ret < 0) |
10847 |
-+ goto exit; |
10848 |
-+ |
10849 |
-+ if (kdbus_conn_is_activator(c) || kdbus_conn_is_policy_holder(c)) { |
10850 |
-+ ret = kdbus_conn_acquire(c); |
10851 |
-+ if (ret < 0) |
10852 |
-+ goto exit; |
10853 |
-+ |
10854 |
-+ ret = kdbus_policy_set(&c->ep->bus->policy_db, args.items, |
10855 |
-+ args.items_size, 1, |
10856 |
-+ kdbus_conn_is_policy_holder(c), c); |
10857 |
-+ kdbus_conn_release(c); |
10858 |
-+ if (ret < 0) |
10859 |
-+ goto exit; |
10860 |
-+ } |
10861 |
-+ |
10862 |
-+ if (copy_to_user(argp, cmd, sizeof(*cmd))) |
10863 |
-+ ret = -EFAULT; |
10864 |
-+ |
10865 |
-+exit: |
10866 |
-+ ret = kdbus_args_clear(&args, ret); |
10867 |
-+ if (ret < 0) { |
10868 |
-+ if (c) { |
10869 |
-+ kdbus_conn_disconnect(c, false); |
10870 |
-+ kdbus_conn_unref(c); |
10871 |
-+ } |
10872 |
-+ return ERR_PTR(ret); |
10873 |
-+ } |
10874 |
-+ return c; |
10875 |
-+} |
10876 |
-+ |
10877 |
-+/** |
10878 |
-+ * kdbus_cmd_byebye_unlocked() - handle KDBUS_CMD_BYEBYE |
10879 |
-+ * @conn: connection to operate on |
10880 |
-+ * @argp: command payload |
10881 |
-+ * |
10882 |
-+ * The caller must not hold any active reference to @conn or this will deadlock. |
10883 |
-+ * |
10884 |
-+ * Return: >=0 on success, negative error code on failure. |
10885 |
-+ */ |
10886 |
-+int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp) |
10887 |
-+{ |
10888 |
-+ struct kdbus_cmd *cmd; |
10889 |
-+ int ret; |
10890 |
-+ |
10891 |
-+ struct kdbus_arg argv[] = { |
10892 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
10893 |
-+ }; |
10894 |
-+ struct kdbus_args args = { |
10895 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
10896 |
-+ .argv = argv, |
10897 |
-+ .argc = ARRAY_SIZE(argv), |
10898 |
-+ }; |
10899 |
-+ |
10900 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
10901 |
-+ return -EOPNOTSUPP; |
10902 |
-+ |
10903 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
10904 |
-+ if (ret != 0) |
10905 |
-+ return ret; |
10906 |
-+ |
10907 |
-+ ret = kdbus_conn_disconnect(conn, true); |
10908 |
-+ return kdbus_args_clear(&args, ret); |
10909 |
-+} |
10910 |
-+ |
10911 |
-+/** |
10912 |
-+ * kdbus_cmd_conn_info() - handle KDBUS_CMD_CONN_INFO |
10913 |
-+ * @conn: connection to operate on |
10914 |
-+ * @argp: command payload |
10915 |
-+ * |
10916 |
-+ * Return: >=0 on success, negative error code on failure. |
10917 |
-+ */ |
10918 |
-+int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp) |
10919 |
-+{ |
10920 |
-+ struct kdbus_meta_conn *conn_meta = NULL; |
10921 |
-+ struct kdbus_pool_slice *slice = NULL; |
10922 |
-+ struct kdbus_name_entry *entry = NULL; |
10923 |
-+ struct kdbus_name_owner *owner = NULL; |
10924 |
-+ struct kdbus_conn *owner_conn = NULL; |
10925 |
-+ struct kdbus_item *meta_items = NULL; |
10926 |
-+ struct kdbus_info info = {}; |
10927 |
-+ struct kdbus_cmd_info *cmd; |
10928 |
-+ struct kdbus_bus *bus = conn->ep->bus; |
10929 |
-+ struct kvec kvec[3]; |
10930 |
-+ size_t meta_size, cnt = 0; |
10931 |
-+ const char *name; |
10932 |
-+ u64 attach_flags, size = 0; |
10933 |
-+ int ret; |
10934 |
-+ |
10935 |
-+ struct kdbus_arg argv[] = { |
10936 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
10937 |
-+ { .type = KDBUS_ITEM_NAME }, |
10938 |
-+ }; |
10939 |
-+ struct kdbus_args args = { |
10940 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
10941 |
-+ .argv = argv, |
10942 |
-+ .argc = ARRAY_SIZE(argv), |
10943 |
-+ }; |
10944 |
-+ |
10945 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
10946 |
-+ if (ret != 0) |
10947 |
-+ return ret; |
10948 |
-+ |
10949 |
-+ /* registry must be held throughout lookup *and* collecting data */ |
10950 |
-+ down_read(&bus->name_registry->rwlock); |
10951 |
-+ |
10952 |
-+ ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags); |
10953 |
-+ if (ret < 0) |
10954 |
-+ goto exit; |
10955 |
-+ |
10956 |
-+ name = argv[1].item ? argv[1].item->str : NULL; |
10957 |
-+ |
10958 |
-+ if (name) { |
10959 |
-+ entry = kdbus_name_lookup_unlocked(bus->name_registry, name); |
10960 |
-+ if (entry) |
10961 |
-+ owner = kdbus_name_get_owner(entry); |
10962 |
-+ if (!owner || |
10963 |
-+ !kdbus_conn_policy_see_name(conn, current_cred(), name) || |
10964 |
-+ (cmd->id != 0 && owner->conn->id != cmd->id)) { |
10965 |
-+ /* pretend a name doesn't exist if you cannot see it */ |
10966 |
-+ ret = -ESRCH; |
10967 |
-+ goto exit; |
10968 |
-+ } |
10969 |
-+ |
10970 |
-+ owner_conn = kdbus_conn_ref(owner->conn); |
10971 |
-+ } else if (cmd->id > 0) { |
10972 |
-+ owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id); |
10973 |
-+ if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(), |
10974 |
-+ owner_conn)) { |
10975 |
-+ /* pretend an id doesn't exist if you cannot see it */ |
10976 |
-+ ret = -ENXIO; |
10977 |
-+ goto exit; |
10978 |
-+ } |
10979 |
-+ } else { |
10980 |
-+ ret = -EINVAL; |
10981 |
-+ goto exit; |
10982 |
-+ } |
10983 |
-+ |
10984 |
-+ attach_flags &= atomic64_read(&owner_conn->attach_flags_send); |
10985 |
-+ |
10986 |
-+ conn_meta = kdbus_meta_conn_new(); |
10987 |
-+ if (IS_ERR(conn_meta)) { |
10988 |
-+ ret = PTR_ERR(conn_meta); |
10989 |
-+ conn_meta = NULL; |
10990 |
-+ goto exit; |
10991 |
-+ } |
10992 |
-+ |
10993 |
-+ ret = kdbus_meta_conn_collect(conn_meta, owner_conn, 0, attach_flags); |
10994 |
-+ if (ret < 0) |
10995 |
-+ goto exit; |
10996 |
-+ |
10997 |
-+ ret = kdbus_meta_emit(owner_conn->meta_proc, owner_conn->meta_fake, |
10998 |
-+ conn_meta, conn, attach_flags, |
10999 |
-+ &meta_items, &meta_size); |
11000 |
-+ if (ret < 0) |
11001 |
-+ goto exit; |
11002 |
-+ |
11003 |
-+ info.id = owner_conn->id; |
11004 |
-+ info.flags = owner_conn->flags; |
11005 |
-+ |
11006 |
-+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size); |
11007 |
-+ if (meta_size > 0) { |
11008 |
-+ kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size); |
11009 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &size); |
11010 |
-+ } |
11011 |
-+ |
11012 |
-+ info.size = size; |
11013 |
-+ |
11014 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
11015 |
-+ if (IS_ERR(slice)) { |
11016 |
-+ ret = PTR_ERR(slice); |
11017 |
-+ slice = NULL; |
11018 |
-+ goto exit; |
11019 |
-+ } |
11020 |
-+ |
11021 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, size); |
11022 |
-+ if (ret < 0) |
11023 |
-+ goto exit; |
11024 |
-+ |
11025 |
-+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size); |
11026 |
-+ |
11027 |
-+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
11028 |
-+ kdbus_member_set_user(&cmd->info_size, argp, |
11029 |
-+ typeof(*cmd), info_size)) { |
11030 |
-+ ret = -EFAULT; |
11031 |
-+ goto exit; |
11032 |
-+ } |
11033 |
-+ |
11034 |
-+ ret = 0; |
11035 |
-+ |
11036 |
-+exit: |
11037 |
-+ up_read(&bus->name_registry->rwlock); |
11038 |
-+ kdbus_pool_slice_release(slice); |
11039 |
-+ kfree(meta_items); |
11040 |
-+ kdbus_meta_conn_unref(conn_meta); |
11041 |
-+ kdbus_conn_unref(owner_conn); |
11042 |
-+ return kdbus_args_clear(&args, ret); |
11043 |
-+} |
11044 |
-+ |
11045 |
-+/** |
11046 |
-+ * kdbus_cmd_update() - handle KDBUS_CMD_UPDATE |
11047 |
-+ * @conn: connection to operate on |
11048 |
-+ * @argp: command payload |
11049 |
-+ * |
11050 |
-+ * Return: >=0 on success, negative error code on failure. |
11051 |
-+ */ |
11052 |
-+int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp) |
11053 |
-+{ |
11054 |
-+ struct kdbus_item *item_policy; |
11055 |
-+ u64 *item_attach_send = NULL; |
11056 |
-+ u64 *item_attach_recv = NULL; |
11057 |
-+ struct kdbus_cmd *cmd; |
11058 |
-+ u64 attach_send; |
11059 |
-+ u64 attach_recv; |
11060 |
-+ int ret; |
11061 |
-+ |
11062 |
-+ struct kdbus_arg argv[] = { |
11063 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11064 |
-+ { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND }, |
11065 |
-+ { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV }, |
11066 |
-+ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
11067 |
-+ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
11068 |
-+ }; |
11069 |
-+ struct kdbus_args args = { |
11070 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11071 |
-+ .argv = argv, |
11072 |
-+ .argc = ARRAY_SIZE(argv), |
11073 |
-+ }; |
11074 |
-+ |
11075 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11076 |
-+ if (ret != 0) |
11077 |
-+ return ret; |
11078 |
-+ |
11079 |
-+ item_attach_send = argv[1].item ? &argv[1].item->data64[0] : NULL; |
11080 |
-+ item_attach_recv = argv[2].item ? &argv[2].item->data64[0] : NULL; |
11081 |
-+ item_policy = argv[3].item ? : argv[4].item; |
11082 |
-+ |
11083 |
-+ if (item_attach_send) { |
11084 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11085 |
-+ !kdbus_conn_is_monitor(conn)) { |
11086 |
-+ ret = -EOPNOTSUPP; |
11087 |
-+ goto exit; |
11088 |
-+ } |
11089 |
-+ |
11090 |
-+ ret = kdbus_sanitize_attach_flags(*item_attach_send, |
11091 |
-+ &attach_send); |
11092 |
-+ if (ret < 0) |
11093 |
-+ goto exit; |
11094 |
-+ } |
11095 |
-+ |
11096 |
-+ if (item_attach_recv) { |
11097 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11098 |
-+ !kdbus_conn_is_monitor(conn) && |
11099 |
-+ !kdbus_conn_is_activator(conn)) { |
11100 |
-+ ret = -EOPNOTSUPP; |
11101 |
-+ goto exit; |
11102 |
-+ } |
11103 |
-+ |
11104 |
-+ ret = kdbus_sanitize_attach_flags(*item_attach_recv, |
11105 |
-+ &attach_recv); |
11106 |
-+ if (ret < 0) |
11107 |
-+ goto exit; |
11108 |
-+ } |
11109 |
-+ |
11110 |
-+ if (item_policy && !kdbus_conn_is_policy_holder(conn)) { |
11111 |
-+ ret = -EOPNOTSUPP; |
11112 |
-+ goto exit; |
11113 |
-+ } |
11114 |
-+ |
11115 |
-+ /* now that we verified the input, update the connection */ |
11116 |
-+ |
11117 |
-+ if (item_policy) { |
11118 |
-+ ret = kdbus_policy_set(&conn->ep->bus->policy_db, cmd->items, |
11119 |
-+ KDBUS_ITEMS_SIZE(cmd, items), |
11120 |
-+ 1, true, conn); |
11121 |
-+ if (ret < 0) |
11122 |
-+ goto exit; |
11123 |
-+ } |
11124 |
-+ |
11125 |
-+ if (item_attach_send) |
11126 |
-+ atomic64_set(&conn->attach_flags_send, attach_send); |
11127 |
-+ |
11128 |
-+ if (item_attach_recv) |
11129 |
-+ atomic64_set(&conn->attach_flags_recv, attach_recv); |
11130 |
-+ |
11131 |
-+exit: |
11132 |
-+ return kdbus_args_clear(&args, ret); |
11133 |
-+} |
11134 |
-+ |
11135 |
-+/** |
11136 |
-+ * kdbus_cmd_send() - handle KDBUS_CMD_SEND |
11137 |
-+ * @conn: connection to operate on |
11138 |
-+ * @f: file this command was called on |
11139 |
-+ * @argp: command payload |
11140 |
-+ * |
11141 |
-+ * Return: >=0 on success, negative error code on failure. |
11142 |
-+ */ |
11143 |
-+int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp) |
11144 |
-+{ |
11145 |
-+ struct kdbus_cmd_send *cmd; |
11146 |
-+ struct kdbus_staging *staging = NULL; |
11147 |
-+ struct kdbus_msg *msg = NULL; |
11148 |
-+ struct file *cancel_fd = NULL; |
11149 |
-+ int ret, ret2; |
11150 |
-+ |
11151 |
-+ /* command arguments */ |
11152 |
-+ struct kdbus_arg argv[] = { |
11153 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11154 |
-+ { .type = KDBUS_ITEM_CANCEL_FD }, |
11155 |
-+ }; |
11156 |
-+ struct kdbus_args args = { |
11157 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11158 |
-+ KDBUS_SEND_SYNC_REPLY, |
11159 |
-+ .argv = argv, |
11160 |
-+ .argc = ARRAY_SIZE(argv), |
11161 |
-+ }; |
11162 |
-+ |
11163 |
-+ /* message arguments */ |
11164 |
-+ struct kdbus_arg msg_argv[] = { |
11165 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11166 |
-+ { .type = KDBUS_ITEM_PAYLOAD_VEC, .multiple = true }, |
11167 |
-+ { .type = KDBUS_ITEM_PAYLOAD_MEMFD, .multiple = true }, |
11168 |
-+ { .type = KDBUS_ITEM_FDS }, |
11169 |
-+ { .type = KDBUS_ITEM_BLOOM_FILTER }, |
11170 |
-+ { .type = KDBUS_ITEM_DST_NAME }, |
11171 |
-+ }; |
11172 |
-+ struct kdbus_args msg_args = { |
11173 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11174 |
-+ KDBUS_MSG_EXPECT_REPLY | |
11175 |
-+ KDBUS_MSG_NO_AUTO_START | |
11176 |
-+ KDBUS_MSG_SIGNAL, |
11177 |
-+ .argv = msg_argv, |
11178 |
-+ .argc = ARRAY_SIZE(msg_argv), |
11179 |
-+ }; |
11180 |
-+ |
11181 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
11182 |
-+ return -EOPNOTSUPP; |
11183 |
-+ |
11184 |
-+ /* make sure to parse both, @cmd and @msg on negotiation */ |
11185 |
-+ |
11186 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11187 |
-+ if (ret < 0) |
11188 |
-+ goto exit; |
11189 |
-+ else if (ret > 0 && !cmd->msg_address) /* negotiation without msg */ |
11190 |
-+ goto exit; |
11191 |
-+ |
11192 |
-+ ret2 = kdbus_args_parse_msg(&msg_args, KDBUS_PTR(cmd->msg_address), |
11193 |
-+ &msg); |
11194 |
-+ if (ret2 < 0) { /* cannot parse message */ |
11195 |
-+ ret = ret2; |
11196 |
-+ goto exit; |
11197 |
-+ } else if (ret2 > 0 && !ret) { /* msg-negot implies cmd-negot */ |
11198 |
-+ ret = -EINVAL; |
11199 |
-+ goto exit; |
11200 |
-+ } else if (ret > 0) { /* negotiation */ |
11201 |
-+ goto exit; |
11202 |
-+ } |
11203 |
-+ |
11204 |
-+ /* here we parsed both, @cmd and @msg, and neither wants negotiation */ |
11205 |
-+ |
11206 |
-+ cmd->reply.return_flags = 0; |
11207 |
-+ kdbus_pool_publish_empty(conn->pool, &cmd->reply.offset, |
11208 |
-+ &cmd->reply.msg_size); |
11209 |
-+ |
11210 |
-+ if (argv[1].item) { |
11211 |
-+ cancel_fd = fget(argv[1].item->fds[0]); |
11212 |
-+ if (!cancel_fd) { |
11213 |
-+ ret = -EBADF; |
11214 |
-+ goto exit; |
11215 |
-+ } |
11216 |
-+ |
11217 |
-+ if (!cancel_fd->f_op->poll) { |
11218 |
-+ ret = -EINVAL; |
11219 |
-+ goto exit; |
11220 |
-+ } |
11221 |
-+ } |
11222 |
-+ |
11223 |
-+ /* patch-in the source of this message */ |
11224 |
-+ if (msg->src_id > 0 && msg->src_id != conn->id) { |
11225 |
-+ ret = -EINVAL; |
11226 |
-+ goto exit; |
11227 |
-+ } |
11228 |
-+ msg->src_id = conn->id; |
11229 |
-+ |
11230 |
-+ staging = kdbus_staging_new_user(conn->ep->bus, cmd, msg); |
11231 |
-+ if (IS_ERR(staging)) { |
11232 |
-+ ret = PTR_ERR(staging); |
11233 |
-+ staging = NULL; |
11234 |
-+ goto exit; |
11235 |
-+ } |
11236 |
-+ |
11237 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST) { |
11238 |
-+ down_read(&conn->ep->bus->name_registry->rwlock); |
11239 |
-+ kdbus_bus_broadcast(conn->ep->bus, conn, staging); |
11240 |
-+ up_read(&conn->ep->bus->name_registry->rwlock); |
11241 |
-+ } else if (cmd->flags & KDBUS_SEND_SYNC_REPLY) { |
11242 |
-+ struct kdbus_reply *r; |
11243 |
-+ ktime_t exp; |
11244 |
-+ |
11245 |
-+ exp = ns_to_ktime(msg->timeout_ns); |
11246 |
-+ r = kdbus_conn_call(conn, staging, exp); |
11247 |
-+ if (IS_ERR(r)) { |
11248 |
-+ ret = PTR_ERR(r); |
11249 |
-+ goto exit; |
11250 |
-+ } |
11251 |
-+ |
11252 |
-+ ret = kdbus_conn_wait_reply(conn, cmd, f, cancel_fd, r, exp); |
11253 |
-+ kdbus_reply_unref(r); |
11254 |
-+ if (ret < 0) |
11255 |
-+ goto exit; |
11256 |
-+ } else if ((msg->flags & KDBUS_MSG_EXPECT_REPLY) || |
11257 |
-+ msg->cookie_reply == 0) { |
11258 |
-+ ret = kdbus_conn_unicast(conn, staging); |
11259 |
-+ if (ret < 0) |
11260 |
-+ goto exit; |
11261 |
-+ } else { |
11262 |
-+ ret = kdbus_conn_reply(conn, staging); |
11263 |
-+ if (ret < 0) |
11264 |
-+ goto exit; |
11265 |
-+ } |
11266 |
-+ |
11267 |
-+ if (kdbus_member_set_user(&cmd->reply, argp, typeof(*cmd), reply)) |
11268 |
-+ ret = -EFAULT; |
11269 |
-+ |
11270 |
-+exit: |
11271 |
-+ if (cancel_fd) |
11272 |
-+ fput(cancel_fd); |
11273 |
-+ kdbus_staging_free(staging); |
11274 |
-+ ret = kdbus_args_clear(&msg_args, ret); |
11275 |
-+ return kdbus_args_clear(&args, ret); |
11276 |
-+} |
11277 |
-+ |
11278 |
-+/** |
11279 |
-+ * kdbus_cmd_recv() - handle KDBUS_CMD_RECV |
11280 |
-+ * @conn: connection to operate on |
11281 |
-+ * @argp: command payload |
11282 |
-+ * |
11283 |
-+ * Return: >=0 on success, negative error code on failure. |
11284 |
-+ */ |
11285 |
-+int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp) |
11286 |
-+{ |
11287 |
-+ struct kdbus_queue_entry *entry; |
11288 |
-+ struct kdbus_cmd_recv *cmd; |
11289 |
-+ int ret; |
11290 |
-+ |
11291 |
-+ struct kdbus_arg argv[] = { |
11292 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11293 |
-+ }; |
11294 |
-+ struct kdbus_args args = { |
11295 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11296 |
-+ KDBUS_RECV_PEEK | |
11297 |
-+ KDBUS_RECV_DROP | |
11298 |
-+ KDBUS_RECV_USE_PRIORITY, |
11299 |
-+ .argv = argv, |
11300 |
-+ .argc = ARRAY_SIZE(argv), |
11301 |
-+ }; |
11302 |
-+ |
11303 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11304 |
-+ !kdbus_conn_is_monitor(conn) && |
11305 |
-+ !kdbus_conn_is_activator(conn)) |
11306 |
-+ return -EOPNOTSUPP; |
11307 |
-+ |
11308 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11309 |
-+ if (ret != 0) |
11310 |
-+ return ret; |
11311 |
-+ |
11312 |
-+ cmd->dropped_msgs = 0; |
11313 |
-+ cmd->msg.return_flags = 0; |
11314 |
-+ kdbus_pool_publish_empty(conn->pool, &cmd->msg.offset, |
11315 |
-+ &cmd->msg.msg_size); |
11316 |
-+ |
11317 |
-+ /* DROP+priority is not realiably, so prevent it */ |
11318 |
-+ if ((cmd->flags & KDBUS_RECV_DROP) && |
11319 |
-+ (cmd->flags & KDBUS_RECV_USE_PRIORITY)) { |
11320 |
-+ ret = -EINVAL; |
11321 |
-+ goto exit; |
11322 |
-+ } |
11323 |
-+ |
11324 |
-+ mutex_lock(&conn->lock); |
11325 |
-+ |
11326 |
-+ entry = kdbus_queue_peek(&conn->queue, cmd->priority, |
11327 |
-+ cmd->flags & KDBUS_RECV_USE_PRIORITY); |
11328 |
-+ if (!entry) { |
11329 |
-+ mutex_unlock(&conn->lock); |
11330 |
-+ ret = -EAGAIN; |
11331 |
-+ } else if (cmd->flags & KDBUS_RECV_DROP) { |
11332 |
-+ struct kdbus_reply *reply = kdbus_reply_ref(entry->reply); |
11333 |
-+ |
11334 |
-+ kdbus_queue_entry_free(entry); |
11335 |
-+ |
11336 |
-+ mutex_unlock(&conn->lock); |
11337 |
-+ |
11338 |
-+ if (reply) { |
11339 |
-+ mutex_lock(&reply->reply_dst->lock); |
11340 |
-+ if (!list_empty(&reply->entry)) { |
11341 |
-+ kdbus_reply_unlink(reply); |
11342 |
-+ if (reply->sync) |
11343 |
-+ kdbus_sync_reply_wakeup(reply, -EPIPE); |
11344 |
-+ else |
11345 |
-+ kdbus_notify_reply_dead(conn->ep->bus, |
11346 |
-+ reply->reply_dst->id, |
11347 |
-+ reply->cookie); |
11348 |
-+ } |
11349 |
-+ mutex_unlock(&reply->reply_dst->lock); |
11350 |
-+ kdbus_notify_flush(conn->ep->bus); |
11351 |
-+ } |
11352 |
-+ |
11353 |
-+ kdbus_reply_unref(reply); |
11354 |
-+ } else { |
11355 |
-+ bool install_fds; |
11356 |
-+ |
11357 |
-+ /* |
11358 |
-+ * PEEK just returns the location of the next message. Do not |
11359 |
-+ * install FDs nor memfds nor anything else. The only |
11360 |
-+ * information of interest should be the message header and |
11361 |
-+ * metadata. Any FD numbers in the payload is undefined for |
11362 |
-+ * PEEK'ed messages. |
11363 |
-+ * Also make sure to never install fds into a connection that |
11364 |
-+ * has refused to receive any. Ordinary connections will not get |
11365 |
-+ * messages with FDs queued (the receiver will get -ECOMM), but |
11366 |
-+ * eavesdroppers might. |
11367 |
-+ */ |
11368 |
-+ install_fds = (conn->flags & KDBUS_HELLO_ACCEPT_FD) && |
11369 |
-+ !(cmd->flags & KDBUS_RECV_PEEK); |
11370 |
-+ |
11371 |
-+ ret = kdbus_queue_entry_install(entry, |
11372 |
-+ &cmd->msg.return_flags, |
11373 |
-+ install_fds); |
11374 |
-+ if (ret < 0) { |
11375 |
-+ mutex_unlock(&conn->lock); |
11376 |
-+ goto exit; |
11377 |
-+ } |
11378 |
-+ |
11379 |
-+ kdbus_pool_slice_publish(entry->slice, &cmd->msg.offset, |
11380 |
-+ &cmd->msg.msg_size); |
11381 |
-+ |
11382 |
-+ if (!(cmd->flags & KDBUS_RECV_PEEK)) |
11383 |
-+ kdbus_queue_entry_free(entry); |
11384 |
-+ |
11385 |
-+ mutex_unlock(&conn->lock); |
11386 |
-+ } |
11387 |
-+ |
11388 |
-+ cmd->dropped_msgs = atomic_xchg(&conn->lost_count, 0); |
11389 |
-+ if (cmd->dropped_msgs > 0) |
11390 |
-+ cmd->return_flags |= KDBUS_RECV_RETURN_DROPPED_MSGS; |
11391 |
-+ |
11392 |
-+ if (kdbus_member_set_user(&cmd->msg, argp, typeof(*cmd), msg) || |
11393 |
-+ kdbus_member_set_user(&cmd->dropped_msgs, argp, typeof(*cmd), |
11394 |
-+ dropped_msgs)) |
11395 |
-+ ret = -EFAULT; |
11396 |
-+ |
11397 |
-+exit: |
11398 |
-+ return kdbus_args_clear(&args, ret); |
11399 |
-+} |
11400 |
-+ |
11401 |
-+/** |
11402 |
-+ * kdbus_cmd_free() - handle KDBUS_CMD_FREE |
11403 |
-+ * @conn: connection to operate on |
11404 |
-+ * @argp: command payload |
11405 |
-+ * |
11406 |
-+ * Return: >=0 on success, negative error code on failure. |
11407 |
-+ */ |
11408 |
-+int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp) |
11409 |
-+{ |
11410 |
-+ struct kdbus_cmd_free *cmd; |
11411 |
-+ int ret; |
11412 |
-+ |
11413 |
-+ struct kdbus_arg argv[] = { |
11414 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11415 |
-+ }; |
11416 |
-+ struct kdbus_args args = { |
11417 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11418 |
-+ .argv = argv, |
11419 |
-+ .argc = ARRAY_SIZE(argv), |
11420 |
-+ }; |
11421 |
-+ |
11422 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11423 |
-+ !kdbus_conn_is_monitor(conn) && |
11424 |
-+ !kdbus_conn_is_activator(conn)) |
11425 |
-+ return -EOPNOTSUPP; |
11426 |
-+ |
11427 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11428 |
-+ if (ret != 0) |
11429 |
-+ return ret; |
11430 |
-+ |
11431 |
-+ ret = kdbus_pool_release_offset(conn->pool, cmd->offset); |
11432 |
-+ |
11433 |
-+ return kdbus_args_clear(&args, ret); |
11434 |
-+} |
11435 |
-diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h |
11436 |
-new file mode 100644 |
11437 |
-index 0000000..1ad0820 |
11438 |
---- /dev/null |
11439 |
-+++ b/ipc/kdbus/connection.h |
11440 |
-@@ -0,0 +1,260 @@ |
11441 |
-+/* |
11442 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
11443 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
11444 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
11445 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
11446 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
11447 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
11448 |
-+ * |
11449 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
11450 |
-+ * the terms of the GNU Lesser General Public License as published by the |
11451 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
11452 |
-+ * your option) any later version. |
11453 |
-+ */ |
11454 |
-+ |
11455 |
-+#ifndef __KDBUS_CONNECTION_H |
11456 |
-+#define __KDBUS_CONNECTION_H |
11457 |
-+ |
11458 |
-+#include <linux/atomic.h> |
11459 |
-+#include <linux/kref.h> |
11460 |
-+#include <linux/lockdep.h> |
11461 |
-+#include <linux/path.h> |
11462 |
-+ |
11463 |
-+#include "limits.h" |
11464 |
-+#include "metadata.h" |
11465 |
-+#include "pool.h" |
11466 |
-+#include "queue.h" |
11467 |
-+#include "util.h" |
11468 |
-+ |
11469 |
-+#define KDBUS_HELLO_SPECIAL_CONN (KDBUS_HELLO_ACTIVATOR | \ |
11470 |
-+ KDBUS_HELLO_POLICY_HOLDER | \ |
11471 |
-+ KDBUS_HELLO_MONITOR) |
11472 |
-+ |
11473 |
-+struct kdbus_name_entry; |
11474 |
-+struct kdbus_quota; |
11475 |
-+struct kdbus_staging; |
11476 |
-+ |
11477 |
-+/** |
11478 |
-+ * struct kdbus_conn - connection to a bus |
11479 |
-+ * @kref: Reference count |
11480 |
-+ * @active: Active references to the connection |
11481 |
-+ * @id: Connection ID |
11482 |
-+ * @flags: KDBUS_HELLO_* flags |
11483 |
-+ * @attach_flags_send: KDBUS_ATTACH_* flags for sending |
11484 |
-+ * @attach_flags_recv: KDBUS_ATTACH_* flags for receiving |
11485 |
-+ * @description: Human-readable connection description, used for |
11486 |
-+ * debugging. This field is only set when the |
11487 |
-+ * connection is created. |
11488 |
-+ * @ep: The endpoint this connection belongs to |
11489 |
-+ * @lock: Connection data lock |
11490 |
-+ * @hentry: Entry in ID <-> connection map |
11491 |
-+ * @ep_entry: Entry in endpoint |
11492 |
-+ * @monitor_entry: Entry in monitor, if the connection is a monitor |
11493 |
-+ * @reply_list: List of connections this connection should |
11494 |
-+ * reply to |
11495 |
-+ * @work: Delayed work to handle timeouts |
11496 |
-+ * activator for |
11497 |
-+ * @match_db: Subscription filter to broadcast messages |
11498 |
-+ * @meta_proc: Process metadata of connection creator, or NULL |
11499 |
-+ * @meta_fake: Faked metadata, or NULL |
11500 |
-+ * @pool: The user's buffer to receive messages |
11501 |
-+ * @user: Owner of the connection |
11502 |
-+ * @cred: The credentials of the connection at creation time |
11503 |
-+ * @pid: Pid at creation time |
11504 |
-+ * @root_path: Root path at creation time |
11505 |
-+ * @request_count: Number of pending requests issued by this |
11506 |
-+ * connection that are waiting for replies from |
11507 |
-+ * other peers |
11508 |
-+ * @lost_count: Number of lost broadcast messages |
11509 |
-+ * @wait: Wake up this endpoint |
11510 |
-+ * @queue: The message queue associated with this connection |
11511 |
-+ * @quota: Array of per-user quota indexed by user->id |
11512 |
-+ * @n_quota: Number of elements in quota array |
11513 |
-+ * @names_list: List of well-known names |
11514 |
-+ * @name_count: Number of owned well-known names |
11515 |
-+ * @privileged: Whether this connection is privileged on the domain |
11516 |
-+ * @owner: Owned by the same user as the bus owner |
11517 |
-+ */ |
11518 |
-+struct kdbus_conn { |
11519 |
-+ struct kref kref; |
11520 |
-+ atomic_t active; |
11521 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
11522 |
-+ struct lockdep_map dep_map; |
11523 |
-+#endif |
11524 |
-+ u64 id; |
11525 |
-+ u64 flags; |
11526 |
-+ atomic64_t attach_flags_send; |
11527 |
-+ atomic64_t attach_flags_recv; |
11528 |
-+ const char *description; |
11529 |
-+ struct kdbus_ep *ep; |
11530 |
-+ struct mutex lock; |
11531 |
-+ struct hlist_node hentry; |
11532 |
-+ struct list_head ep_entry; |
11533 |
-+ struct list_head monitor_entry; |
11534 |
-+ struct list_head reply_list; |
11535 |
-+ struct delayed_work work; |
11536 |
-+ struct kdbus_match_db *match_db; |
11537 |
-+ struct kdbus_meta_proc *meta_proc; |
11538 |
-+ struct kdbus_meta_fake *meta_fake; |
11539 |
-+ struct kdbus_pool *pool; |
11540 |
-+ struct kdbus_user *user; |
11541 |
-+ const struct cred *cred; |
11542 |
-+ struct pid *pid; |
11543 |
-+ struct path root_path; |
11544 |
-+ atomic_t request_count; |
11545 |
-+ atomic_t lost_count; |
11546 |
-+ wait_queue_head_t wait; |
11547 |
-+ struct kdbus_queue queue; |
11548 |
-+ |
11549 |
-+ struct kdbus_quota *quota; |
11550 |
-+ unsigned int n_quota; |
11551 |
-+ |
11552 |
-+ /* protected by registry->rwlock */ |
11553 |
-+ struct list_head names_list; |
11554 |
-+ unsigned int name_count; |
11555 |
-+ |
11556 |
-+ bool privileged:1; |
11557 |
-+ bool owner:1; |
11558 |
-+}; |
11559 |
-+ |
11560 |
-+struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn); |
11561 |
-+struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn); |
11562 |
-+bool kdbus_conn_active(const struct kdbus_conn *conn); |
11563 |
-+int kdbus_conn_acquire(struct kdbus_conn *conn); |
11564 |
-+void kdbus_conn_release(struct kdbus_conn *conn); |
11565 |
-+int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty); |
11566 |
-+bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name); |
11567 |
-+int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, |
11568 |
-+ size_t memory, size_t fds); |
11569 |
-+void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, |
11570 |
-+ size_t memory, size_t fds); |
11571 |
-+void kdbus_conn_lost_message(struct kdbus_conn *c); |
11572 |
-+int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, |
11573 |
-+ struct kdbus_conn *conn_dst, |
11574 |
-+ struct kdbus_staging *staging, |
11575 |
-+ struct kdbus_reply *reply, |
11576 |
-+ const struct kdbus_name_entry *name); |
11577 |
-+void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, |
11578 |
-+ struct kdbus_conn *conn_src, |
11579 |
-+ u64 name_id); |
11580 |
-+ |
11581 |
-+/* policy */ |
11582 |
-+bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, |
11583 |
-+ const struct cred *conn_creds, |
11584 |
-+ const char *name); |
11585 |
-+bool kdbus_conn_policy_talk(struct kdbus_conn *conn, |
11586 |
-+ const struct cred *conn_creds, |
11587 |
-+ struct kdbus_conn *to); |
11588 |
-+bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, |
11589 |
-+ const struct cred *curr_creds, |
11590 |
-+ const char *name); |
11591 |
-+bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, |
11592 |
-+ const struct cred *curr_creds, |
11593 |
-+ const struct kdbus_msg *msg); |
11594 |
-+ |
11595 |
-+/* command dispatcher */ |
11596 |
-+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file, |
11597 |
-+ void __user *argp); |
11598 |
-+int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp); |
11599 |
-+int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp); |
11600 |
-+int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp); |
11601 |
-+int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp); |
11602 |
-+int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp); |
11603 |
-+int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp); |
11604 |
-+ |
11605 |
-+/** |
11606 |
-+ * kdbus_conn_is_ordinary() - Check if connection is ordinary |
11607 |
-+ * @conn: The connection to check |
11608 |
-+ * |
11609 |
-+ * Return: Non-zero if the connection is an ordinary connection |
11610 |
-+ */ |
11611 |
-+static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn) |
11612 |
-+{ |
11613 |
-+ return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN); |
11614 |
-+} |
11615 |
-+ |
11616 |
-+/** |
11617 |
-+ * kdbus_conn_is_activator() - Check if connection is an activator |
11618 |
-+ * @conn: The connection to check |
11619 |
-+ * |
11620 |
-+ * Return: Non-zero if the connection is an activator |
11621 |
-+ */ |
11622 |
-+static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn) |
11623 |
-+{ |
11624 |
-+ return conn->flags & KDBUS_HELLO_ACTIVATOR; |
11625 |
-+} |
11626 |
-+ |
11627 |
-+/** |
11628 |
-+ * kdbus_conn_is_policy_holder() - Check if connection is a policy holder |
11629 |
-+ * @conn: The connection to check |
11630 |
-+ * |
11631 |
-+ * Return: Non-zero if the connection is a policy holder |
11632 |
-+ */ |
11633 |
-+static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn) |
11634 |
-+{ |
11635 |
-+ return conn->flags & KDBUS_HELLO_POLICY_HOLDER; |
11636 |
-+} |
11637 |
-+ |
11638 |
-+/** |
11639 |
-+ * kdbus_conn_is_monitor() - Check if connection is a monitor |
11640 |
-+ * @conn: The connection to check |
11641 |
-+ * |
11642 |
-+ * Return: Non-zero if the connection is a monitor |
11643 |
-+ */ |
11644 |
-+static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn) |
11645 |
-+{ |
11646 |
-+ return conn->flags & KDBUS_HELLO_MONITOR; |
11647 |
-+} |
11648 |
-+ |
11649 |
-+/** |
11650 |
-+ * kdbus_conn_lock2() - Lock two connections |
11651 |
-+ * @a: connection A to lock or NULL |
11652 |
-+ * @b: connection B to lock or NULL |
11653 |
-+ * |
11654 |
-+ * Lock two connections at once. As we need to have a stable locking order, we |
11655 |
-+ * always lock the connection with lower memory address first. |
11656 |
-+ */ |
11657 |
-+static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b) |
11658 |
-+{ |
11659 |
-+ if (a < b) { |
11660 |
-+ if (a) |
11661 |
-+ mutex_lock(&a->lock); |
11662 |
-+ if (b && b != a) |
11663 |
-+ mutex_lock_nested(&b->lock, !!a); |
11664 |
-+ } else { |
11665 |
-+ if (b) |
11666 |
-+ mutex_lock(&b->lock); |
11667 |
-+ if (a && a != b) |
11668 |
-+ mutex_lock_nested(&a->lock, !!b); |
11669 |
-+ } |
11670 |
-+} |
11671 |
-+ |
11672 |
-+/** |
11673 |
-+ * kdbus_conn_unlock2() - Unlock two connections |
11674 |
-+ * @a: connection A to unlock or NULL |
11675 |
-+ * @b: connection B to unlock or NULL |
11676 |
-+ * |
11677 |
-+ * Unlock two connections at once. See kdbus_conn_lock2(). |
11678 |
-+ */ |
11679 |
-+static inline void kdbus_conn_unlock2(struct kdbus_conn *a, |
11680 |
-+ struct kdbus_conn *b) |
11681 |
-+{ |
11682 |
-+ if (a) |
11683 |
-+ mutex_unlock(&a->lock); |
11684 |
-+ if (b && b != a) |
11685 |
-+ mutex_unlock(&b->lock); |
11686 |
-+} |
11687 |
-+ |
11688 |
-+/** |
11689 |
-+ * kdbus_conn_assert_active() - lockdep assert on active lock |
11690 |
-+ * @conn: connection that shall be active |
11691 |
-+ * |
11692 |
-+ * This verifies via lockdep that the caller holds an active reference to the |
11693 |
-+ * given connection. |
11694 |
-+ */ |
11695 |
-+static inline void kdbus_conn_assert_active(struct kdbus_conn *conn) |
11696 |
-+{ |
11697 |
-+ lockdep_assert_held(conn); |
11698 |
-+} |
11699 |
-+ |
11700 |
-+#endif |
11701 |
-diff --git a/ipc/kdbus/domain.c b/ipc/kdbus/domain.c |
11702 |
-new file mode 100644 |
11703 |
-index 0000000..ac9f760 |
11704 |
---- /dev/null |
11705 |
-+++ b/ipc/kdbus/domain.c |
11706 |
-@@ -0,0 +1,296 @@ |
11707 |
-+/* |
11708 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
11709 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
11710 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
11711 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
11712 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
11713 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
11714 |
-+ * |
11715 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
11716 |
-+ * the terms of the GNU Lesser General Public License as published by the |
11717 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
11718 |
-+ * your option) any later version. |
11719 |
-+ */ |
11720 |
-+ |
11721 |
-+#include <linux/fs.h> |
11722 |
-+#include <linux/idr.h> |
11723 |
-+#include <linux/init.h> |
11724 |
-+#include <linux/module.h> |
11725 |
-+#include <linux/sched.h> |
11726 |
-+#include <linux/sizes.h> |
11727 |
-+#include <linux/slab.h> |
11728 |
-+#include <linux/uaccess.h> |
11729 |
-+ |
11730 |
-+#include "bus.h" |
11731 |
-+#include "domain.h" |
11732 |
-+#include "handle.h" |
11733 |
-+#include "item.h" |
11734 |
-+#include "limits.h" |
11735 |
-+#include "util.h" |
11736 |
-+ |
11737 |
-+static void kdbus_domain_control_free(struct kdbus_node *node) |
11738 |
-+{ |
11739 |
-+ kfree(node); |
11740 |
-+} |
11741 |
-+ |
11742 |
-+static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain, |
11743 |
-+ unsigned int access) |
11744 |
-+{ |
11745 |
-+ struct kdbus_node *node; |
11746 |
-+ int ret; |
11747 |
-+ |
11748 |
-+ node = kzalloc(sizeof(*node), GFP_KERNEL); |
11749 |
-+ if (!node) |
11750 |
-+ return ERR_PTR(-ENOMEM); |
11751 |
-+ |
11752 |
-+ kdbus_node_init(node, KDBUS_NODE_CONTROL); |
11753 |
-+ |
11754 |
-+ node->free_cb = kdbus_domain_control_free; |
11755 |
-+ node->mode = domain->node.mode; |
11756 |
-+ node->mode = S_IRUSR | S_IWUSR; |
11757 |
-+ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
11758 |
-+ node->mode |= S_IRGRP | S_IWGRP; |
11759 |
-+ if (access & KDBUS_MAKE_ACCESS_WORLD) |
11760 |
-+ node->mode |= S_IROTH | S_IWOTH; |
11761 |
-+ |
11762 |
-+ ret = kdbus_node_link(node, &domain->node, "control"); |
11763 |
-+ if (ret < 0) |
11764 |
-+ goto exit_free; |
11765 |
-+ |
11766 |
-+ return node; |
11767 |
-+ |
11768 |
-+exit_free: |
11769 |
-+ kdbus_node_deactivate(node); |
11770 |
-+ kdbus_node_unref(node); |
11771 |
-+ return ERR_PTR(ret); |
11772 |
-+} |
11773 |
-+ |
11774 |
-+static void kdbus_domain_free(struct kdbus_node *node) |
11775 |
-+{ |
11776 |
-+ struct kdbus_domain *domain = |
11777 |
-+ container_of(node, struct kdbus_domain, node); |
11778 |
-+ |
11779 |
-+ put_user_ns(domain->user_namespace); |
11780 |
-+ ida_destroy(&domain->user_ida); |
11781 |
-+ idr_destroy(&domain->user_idr); |
11782 |
-+ kfree(domain); |
11783 |
-+} |
11784 |
-+ |
11785 |
-+/** |
11786 |
-+ * kdbus_domain_new() - create a new domain |
11787 |
-+ * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*) |
11788 |
-+ * |
11789 |
-+ * Return: a new kdbus_domain on success, ERR_PTR on failure |
11790 |
-+ */ |
11791 |
-+struct kdbus_domain *kdbus_domain_new(unsigned int access) |
11792 |
-+{ |
11793 |
-+ struct kdbus_domain *d; |
11794 |
-+ int ret; |
11795 |
-+ |
11796 |
-+ d = kzalloc(sizeof(*d), GFP_KERNEL); |
11797 |
-+ if (!d) |
11798 |
-+ return ERR_PTR(-ENOMEM); |
11799 |
-+ |
11800 |
-+ kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN); |
11801 |
-+ |
11802 |
-+ d->node.free_cb = kdbus_domain_free; |
11803 |
-+ d->node.mode = S_IRUSR | S_IXUSR; |
11804 |
-+ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
11805 |
-+ d->node.mode |= S_IRGRP | S_IXGRP; |
11806 |
-+ if (access & KDBUS_MAKE_ACCESS_WORLD) |
11807 |
-+ d->node.mode |= S_IROTH | S_IXOTH; |
11808 |
-+ |
11809 |
-+ mutex_init(&d->lock); |
11810 |
-+ idr_init(&d->user_idr); |
11811 |
-+ ida_init(&d->user_ida); |
11812 |
-+ |
11813 |
-+ /* Pin user namespace so we can guarantee domain-unique bus * names. */ |
11814 |
-+ d->user_namespace = get_user_ns(current_user_ns()); |
11815 |
-+ |
11816 |
-+ ret = kdbus_node_link(&d->node, NULL, NULL); |
11817 |
-+ if (ret < 0) |
11818 |
-+ goto exit_unref; |
11819 |
-+ |
11820 |
-+ return d; |
11821 |
-+ |
11822 |
-+exit_unref: |
11823 |
-+ kdbus_node_deactivate(&d->node); |
11824 |
-+ kdbus_node_unref(&d->node); |
11825 |
-+ return ERR_PTR(ret); |
11826 |
-+} |
11827 |
-+ |
11828 |
-+/** |
11829 |
-+ * kdbus_domain_ref() - take a domain reference |
11830 |
-+ * @domain: Domain |
11831 |
-+ * |
11832 |
-+ * Return: the domain itself |
11833 |
-+ */ |
11834 |
-+struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain) |
11835 |
-+{ |
11836 |
-+ if (domain) |
11837 |
-+ kdbus_node_ref(&domain->node); |
11838 |
-+ return domain; |
11839 |
-+} |
11840 |
-+ |
11841 |
-+/** |
11842 |
-+ * kdbus_domain_unref() - drop a domain reference |
11843 |
-+ * @domain: Domain |
11844 |
-+ * |
11845 |
-+ * When the last reference is dropped, the domain internal structure |
11846 |
-+ * is freed. |
11847 |
-+ * |
11848 |
-+ * Return: NULL |
11849 |
-+ */ |
11850 |
-+struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain) |
11851 |
-+{ |
11852 |
-+ if (domain) |
11853 |
-+ kdbus_node_unref(&domain->node); |
11854 |
-+ return NULL; |
11855 |
-+} |
11856 |
-+ |
11857 |
-+/** |
11858 |
-+ * kdbus_domain_populate() - populate static domain nodes |
11859 |
-+ * @domain: domain to populate |
11860 |
-+ * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes |
11861 |
-+ * |
11862 |
-+ * Allocate and activate static sub-nodes of the given domain. This will fail if |
11863 |
-+ * you call it on a non-active node or if the domain was already populated. |
11864 |
-+ * |
11865 |
-+ * Return: 0 on success, negative error code on failure. |
11866 |
-+ */ |
11867 |
-+int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access) |
11868 |
-+{ |
11869 |
-+ struct kdbus_node *control; |
11870 |
-+ |
11871 |
-+ /* |
11872 |
-+ * Create a control-node for this domain. We drop our own reference |
11873 |
-+ * immediately, effectively causing the node to be deactivated and |
11874 |
-+ * released when the parent domain is. |
11875 |
-+ */ |
11876 |
-+ control = kdbus_domain_control_new(domain, access); |
11877 |
-+ if (IS_ERR(control)) |
11878 |
-+ return PTR_ERR(control); |
11879 |
-+ |
11880 |
-+ kdbus_node_activate(control); |
11881 |
-+ kdbus_node_unref(control); |
11882 |
-+ return 0; |
11883 |
-+} |
11884 |
-+ |
11885 |
-+/** |
11886 |
-+ * kdbus_user_lookup() - lookup a kdbus_user object |
11887 |
-+ * @domain: domain of the user |
11888 |
-+ * @uid: uid of the user; INVALID_UID for an anon user |
11889 |
-+ * |
11890 |
-+ * Lookup the kdbus user accounting object for the given domain. If INVALID_UID |
11891 |
-+ * is passed, a new anonymous user is created which is private to the caller. |
11892 |
-+ * |
11893 |
-+ * Return: The user object is returned, ERR_PTR on failure. |
11894 |
-+ */ |
11895 |
-+struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid) |
11896 |
-+{ |
11897 |
-+ struct kdbus_user *u = NULL, *old = NULL; |
11898 |
-+ int ret; |
11899 |
-+ |
11900 |
-+ mutex_lock(&domain->lock); |
11901 |
-+ |
11902 |
-+ if (uid_valid(uid)) { |
11903 |
-+ old = idr_find(&domain->user_idr, __kuid_val(uid)); |
11904 |
-+ /* |
11905 |
-+ * If the object is about to be destroyed, ignore it and |
11906 |
-+ * replace the slot in the IDR later on. |
11907 |
-+ */ |
11908 |
-+ if (old && kref_get_unless_zero(&old->kref)) { |
11909 |
-+ mutex_unlock(&domain->lock); |
11910 |
-+ return old; |
11911 |
-+ } |
11912 |
-+ } |
11913 |
-+ |
11914 |
-+ u = kzalloc(sizeof(*u), GFP_KERNEL); |
11915 |
-+ if (!u) { |
11916 |
-+ ret = -ENOMEM; |
11917 |
-+ goto exit; |
11918 |
-+ } |
11919 |
-+ |
11920 |
-+ kref_init(&u->kref); |
11921 |
-+ u->domain = kdbus_domain_ref(domain); |
11922 |
-+ u->uid = uid; |
11923 |
-+ atomic_set(&u->buses, 0); |
11924 |
-+ atomic_set(&u->connections, 0); |
11925 |
-+ |
11926 |
-+ if (uid_valid(uid)) { |
11927 |
-+ if (old) { |
11928 |
-+ idr_replace(&domain->user_idr, u, __kuid_val(uid)); |
11929 |
-+ old->uid = INVALID_UID; /* mark old as removed */ |
11930 |
-+ } else { |
11931 |
-+ ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid), |
11932 |
-+ __kuid_val(uid) + 1, GFP_KERNEL); |
11933 |
-+ if (ret < 0) |
11934 |
-+ goto exit; |
11935 |
-+ } |
11936 |
-+ } |
11937 |
-+ |
11938 |
-+ /* |
11939 |
-+ * Allocate the smallest possible index for this user; used |
11940 |
-+ * in arrays for accounting user quota in receiver queues. |
11941 |
-+ */ |
11942 |
-+ ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL); |
11943 |
-+ if (ret < 0) |
11944 |
-+ goto exit; |
11945 |
-+ |
11946 |
-+ u->id = ret; |
11947 |
-+ mutex_unlock(&domain->lock); |
11948 |
-+ return u; |
11949 |
-+ |
11950 |
-+exit: |
11951 |
-+ if (u) { |
11952 |
-+ if (uid_valid(u->uid)) |
11953 |
-+ idr_remove(&domain->user_idr, __kuid_val(u->uid)); |
11954 |
-+ kdbus_domain_unref(u->domain); |
11955 |
-+ kfree(u); |
11956 |
-+ } |
11957 |
-+ mutex_unlock(&domain->lock); |
11958 |
-+ return ERR_PTR(ret); |
11959 |
-+} |
11960 |
-+ |
11961 |
-+static void __kdbus_user_free(struct kref *kref) |
11962 |
-+{ |
11963 |
-+ struct kdbus_user *user = container_of(kref, struct kdbus_user, kref); |
11964 |
-+ |
11965 |
-+ WARN_ON(atomic_read(&user->buses) > 0); |
11966 |
-+ WARN_ON(atomic_read(&user->connections) > 0); |
11967 |
-+ |
11968 |
-+ mutex_lock(&user->domain->lock); |
11969 |
-+ ida_simple_remove(&user->domain->user_ida, user->id); |
11970 |
-+ if (uid_valid(user->uid)) |
11971 |
-+ idr_remove(&user->domain->user_idr, __kuid_val(user->uid)); |
11972 |
-+ mutex_unlock(&user->domain->lock); |
11973 |
-+ |
11974 |
-+ kdbus_domain_unref(user->domain); |
11975 |
-+ kfree(user); |
11976 |
-+} |
11977 |
-+ |
11978 |
-+/** |
11979 |
-+ * kdbus_user_ref() - take a user reference |
11980 |
-+ * @u: User |
11981 |
-+ * |
11982 |
-+ * Return: @u is returned |
11983 |
-+ */ |
11984 |
-+struct kdbus_user *kdbus_user_ref(struct kdbus_user *u) |
11985 |
-+{ |
11986 |
-+ if (u) |
11987 |
-+ kref_get(&u->kref); |
11988 |
-+ return u; |
11989 |
-+} |
11990 |
-+ |
11991 |
-+/** |
11992 |
-+ * kdbus_user_unref() - drop a user reference |
11993 |
-+ * @u: User |
11994 |
-+ * |
11995 |
-+ * Return: NULL |
11996 |
-+ */ |
11997 |
-+struct kdbus_user *kdbus_user_unref(struct kdbus_user *u) |
11998 |
-+{ |
11999 |
-+ if (u) |
12000 |
-+ kref_put(&u->kref, __kdbus_user_free); |
12001 |
-+ return NULL; |
12002 |
-+} |
12003 |
-diff --git a/ipc/kdbus/domain.h b/ipc/kdbus/domain.h |
12004 |
-new file mode 100644 |
12005 |
-index 0000000..447a2bd |
12006 |
---- /dev/null |
12007 |
-+++ b/ipc/kdbus/domain.h |
12008 |
-@@ -0,0 +1,77 @@ |
12009 |
-+/* |
12010 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12011 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12012 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12013 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12014 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12015 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12016 |
-+ * |
12017 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12018 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12019 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12020 |
-+ * your option) any later version. |
12021 |
-+ */ |
12022 |
-+ |
12023 |
-+#ifndef __KDBUS_DOMAIN_H |
12024 |
-+#define __KDBUS_DOMAIN_H |
12025 |
-+ |
12026 |
-+#include <linux/fs.h> |
12027 |
-+#include <linux/idr.h> |
12028 |
-+#include <linux/kref.h> |
12029 |
-+#include <linux/user_namespace.h> |
12030 |
-+ |
12031 |
-+#include "node.h" |
12032 |
-+ |
12033 |
-+/** |
12034 |
-+ * struct kdbus_domain - domain for buses |
12035 |
-+ * @node: Underlying API node |
12036 |
-+ * @lock: Domain data lock |
12037 |
-+ * @last_id: Last used object id |
12038 |
-+ * @user_idr: Set of all users indexed by UID |
12039 |
-+ * @user_ida: Set of all users to compute small indices |
12040 |
-+ * @user_namespace: User namespace, pinned at creation time |
12041 |
-+ * @dentry: Root dentry of VFS mount (don't use outside of kdbusfs) |
12042 |
-+ */ |
12043 |
-+struct kdbus_domain { |
12044 |
-+ struct kdbus_node node; |
12045 |
-+ struct mutex lock; |
12046 |
-+ atomic64_t last_id; |
12047 |
-+ struct idr user_idr; |
12048 |
-+ struct ida user_ida; |
12049 |
-+ struct user_namespace *user_namespace; |
12050 |
-+ struct dentry *dentry; |
12051 |
-+}; |
12052 |
-+ |
12053 |
-+/** |
12054 |
-+ * struct kdbus_user - resource accounting for users |
12055 |
-+ * @kref: Reference counter |
12056 |
-+ * @domain: Domain of the user |
12057 |
-+ * @id: Index of this user |
12058 |
-+ * @uid: UID of the user |
12059 |
-+ * @buses: Number of buses the user has created |
12060 |
-+ * @connections: Number of connections the user has created |
12061 |
-+ */ |
12062 |
-+struct kdbus_user { |
12063 |
-+ struct kref kref; |
12064 |
-+ struct kdbus_domain *domain; |
12065 |
-+ unsigned int id; |
12066 |
-+ kuid_t uid; |
12067 |
-+ atomic_t buses; |
12068 |
-+ atomic_t connections; |
12069 |
-+}; |
12070 |
-+ |
12071 |
-+#define kdbus_domain_from_node(_node) \ |
12072 |
-+ container_of((_node), struct kdbus_domain, node) |
12073 |
-+ |
12074 |
-+struct kdbus_domain *kdbus_domain_new(unsigned int access); |
12075 |
-+struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain); |
12076 |
-+struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain); |
12077 |
-+int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access); |
12078 |
-+ |
12079 |
-+#define KDBUS_USER_KERNEL_ID 0 /* ID 0 is reserved for kernel accounting */ |
12080 |
-+ |
12081 |
-+struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid); |
12082 |
-+struct kdbus_user *kdbus_user_ref(struct kdbus_user *u); |
12083 |
-+struct kdbus_user *kdbus_user_unref(struct kdbus_user *u); |
12084 |
-+ |
12085 |
-+#endif |
12086 |
-diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c |
12087 |
-new file mode 100644 |
12088 |
-index 0000000..44e7a20 |
12089 |
---- /dev/null |
12090 |
-+++ b/ipc/kdbus/endpoint.c |
12091 |
-@@ -0,0 +1,303 @@ |
12092 |
-+/* |
12093 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12094 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12095 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12096 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12097 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12098 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12099 |
-+ * |
12100 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12101 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12102 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12103 |
-+ * your option) any later version. |
12104 |
-+ */ |
12105 |
-+ |
12106 |
-+#include <linux/fs.h> |
12107 |
-+#include <linux/idr.h> |
12108 |
-+#include <linux/init.h> |
12109 |
-+#include <linux/module.h> |
12110 |
-+#include <linux/sched.h> |
12111 |
-+#include <linux/sizes.h> |
12112 |
-+#include <linux/slab.h> |
12113 |
-+#include <linux/uaccess.h> |
12114 |
-+#include <linux/uio.h> |
12115 |
-+ |
12116 |
-+#include "bus.h" |
12117 |
-+#include "connection.h" |
12118 |
-+#include "domain.h" |
12119 |
-+#include "endpoint.h" |
12120 |
-+#include "handle.h" |
12121 |
-+#include "item.h" |
12122 |
-+#include "message.h" |
12123 |
-+#include "policy.h" |
12124 |
-+ |
12125 |
-+static void kdbus_ep_free(struct kdbus_node *node) |
12126 |
-+{ |
12127 |
-+ struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); |
12128 |
-+ |
12129 |
-+ WARN_ON(!list_empty(&ep->conn_list)); |
12130 |
-+ |
12131 |
-+ kdbus_policy_db_clear(&ep->policy_db); |
12132 |
-+ kdbus_bus_unref(ep->bus); |
12133 |
-+ kdbus_user_unref(ep->user); |
12134 |
-+ kfree(ep); |
12135 |
-+} |
12136 |
-+ |
12137 |
-+static void kdbus_ep_release(struct kdbus_node *node, bool was_active) |
12138 |
-+{ |
12139 |
-+ struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); |
12140 |
-+ |
12141 |
-+ /* disconnect all connections to this endpoint */ |
12142 |
-+ for (;;) { |
12143 |
-+ struct kdbus_conn *conn; |
12144 |
-+ |
12145 |
-+ mutex_lock(&ep->lock); |
12146 |
-+ conn = list_first_entry_or_null(&ep->conn_list, |
12147 |
-+ struct kdbus_conn, |
12148 |
-+ ep_entry); |
12149 |
-+ if (!conn) { |
12150 |
-+ mutex_unlock(&ep->lock); |
12151 |
-+ break; |
12152 |
-+ } |
12153 |
-+ |
12154 |
-+ /* take reference, release lock, disconnect without lock */ |
12155 |
-+ kdbus_conn_ref(conn); |
12156 |
-+ mutex_unlock(&ep->lock); |
12157 |
-+ |
12158 |
-+ kdbus_conn_disconnect(conn, false); |
12159 |
-+ kdbus_conn_unref(conn); |
12160 |
-+ } |
12161 |
-+} |
12162 |
-+ |
12163 |
-+/** |
12164 |
-+ * kdbus_ep_new() - create a new endpoint |
12165 |
-+ * @bus: The bus this endpoint will be created for |
12166 |
-+ * @name: The name of the endpoint |
12167 |
-+ * @access: The access flags for this node (KDBUS_MAKE_ACCESS_*) |
12168 |
-+ * @uid: The uid of the node |
12169 |
-+ * @gid: The gid of the node |
12170 |
-+ * @is_custom: Whether this is a custom endpoint |
12171 |
-+ * |
12172 |
-+ * This function will create a new endpoint with the given |
12173 |
-+ * name and properties for a given bus. |
12174 |
-+ * |
12175 |
-+ * Return: a new kdbus_ep on success, ERR_PTR on failure. |
12176 |
-+ */ |
12177 |
-+struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, |
12178 |
-+ unsigned int access, kuid_t uid, kgid_t gid, |
12179 |
-+ bool is_custom) |
12180 |
-+{ |
12181 |
-+ struct kdbus_ep *e; |
12182 |
-+ int ret; |
12183 |
-+ |
12184 |
-+ /* |
12185 |
-+ * Validate only custom endpoints names, default endpoints |
12186 |
-+ * with a "bus" name are created when the bus is created |
12187 |
-+ */ |
12188 |
-+ if (is_custom) { |
12189 |
-+ ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace, |
12190 |
-+ uid); |
12191 |
-+ if (ret < 0) |
12192 |
-+ return ERR_PTR(ret); |
12193 |
-+ } |
12194 |
-+ |
12195 |
-+ e = kzalloc(sizeof(*e), GFP_KERNEL); |
12196 |
-+ if (!e) |
12197 |
-+ return ERR_PTR(-ENOMEM); |
12198 |
-+ |
12199 |
-+ kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT); |
12200 |
-+ |
12201 |
-+ e->node.free_cb = kdbus_ep_free; |
12202 |
-+ e->node.release_cb = kdbus_ep_release; |
12203 |
-+ e->node.uid = uid; |
12204 |
-+ e->node.gid = gid; |
12205 |
-+ e->node.mode = S_IRUSR | S_IWUSR; |
12206 |
-+ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
12207 |
-+ e->node.mode |= S_IRGRP | S_IWGRP; |
12208 |
-+ if (access & KDBUS_MAKE_ACCESS_WORLD) |
12209 |
-+ e->node.mode |= S_IROTH | S_IWOTH; |
12210 |
-+ |
12211 |
-+ mutex_init(&e->lock); |
12212 |
-+ INIT_LIST_HEAD(&e->conn_list); |
12213 |
-+ kdbus_policy_db_init(&e->policy_db); |
12214 |
-+ e->bus = kdbus_bus_ref(bus); |
12215 |
-+ |
12216 |
-+ ret = kdbus_node_link(&e->node, &bus->node, name); |
12217 |
-+ if (ret < 0) |
12218 |
-+ goto exit_unref; |
12219 |
-+ |
12220 |
-+ /* |
12221 |
-+ * Transactions on custom endpoints are never accounted on the global |
12222 |
-+ * user limits. Instead, for each custom endpoint, we create a custom, |
12223 |
-+ * unique user, which all transactions are accounted on. Regardless of |
12224 |
-+ * the user using that endpoint, it is always accounted on the same |
12225 |
-+ * user-object. This budget is not shared with ordinary users on |
12226 |
-+ * non-custom endpoints. |
12227 |
-+ */ |
12228 |
-+ if (is_custom) { |
12229 |
-+ e->user = kdbus_user_lookup(bus->domain, INVALID_UID); |
12230 |
-+ if (IS_ERR(e->user)) { |
12231 |
-+ ret = PTR_ERR(e->user); |
12232 |
-+ e->user = NULL; |
12233 |
-+ goto exit_unref; |
12234 |
-+ } |
12235 |
-+ } |
12236 |
-+ |
12237 |
-+ return e; |
12238 |
-+ |
12239 |
-+exit_unref: |
12240 |
-+ kdbus_node_deactivate(&e->node); |
12241 |
-+ kdbus_node_unref(&e->node); |
12242 |
-+ return ERR_PTR(ret); |
12243 |
-+} |
12244 |
-+ |
12245 |
-+/** |
12246 |
-+ * kdbus_ep_ref() - increase the reference counter of a kdbus_ep |
12247 |
-+ * @ep: The endpoint to reference |
12248 |
-+ * |
12249 |
-+ * Every user of an endpoint, except for its creator, must add a reference to |
12250 |
-+ * the kdbus_ep instance using this function. |
12251 |
-+ * |
12252 |
-+ * Return: the ep itself |
12253 |
-+ */ |
12254 |
-+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep) |
12255 |
-+{ |
12256 |
-+ if (ep) |
12257 |
-+ kdbus_node_ref(&ep->node); |
12258 |
-+ return ep; |
12259 |
-+} |
12260 |
-+ |
12261 |
-+/** |
12262 |
-+ * kdbus_ep_unref() - decrease the reference counter of a kdbus_ep |
12263 |
-+ * @ep: The ep to unref |
12264 |
-+ * |
12265 |
-+ * Release a reference. If the reference count drops to 0, the ep will be |
12266 |
-+ * freed. |
12267 |
-+ * |
12268 |
-+ * Return: NULL |
12269 |
-+ */ |
12270 |
-+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep) |
12271 |
-+{ |
12272 |
-+ if (ep) |
12273 |
-+ kdbus_node_unref(&ep->node); |
12274 |
-+ return NULL; |
12275 |
-+} |
12276 |
-+ |
12277 |
-+/** |
12278 |
-+ * kdbus_ep_is_privileged() - check whether a file is privileged |
12279 |
-+ * @ep: endpoint to operate on |
12280 |
-+ * @file: file to test |
12281 |
-+ * |
12282 |
-+ * Return: True if @file is privileged in the domain of @ep. |
12283 |
-+ */ |
12284 |
-+bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file) |
12285 |
-+{ |
12286 |
-+ return !ep->user && |
12287 |
-+ file_ns_capable(file, ep->bus->domain->user_namespace, |
12288 |
-+ CAP_IPC_OWNER); |
12289 |
-+} |
12290 |
-+ |
12291 |
-+/** |
12292 |
-+ * kdbus_ep_is_owner() - check whether a file should be treated as bus owner |
12293 |
-+ * @ep: endpoint to operate on |
12294 |
-+ * @file: file to test |
12295 |
-+ * |
12296 |
-+ * Return: True if @file should be treated as bus owner on @ep |
12297 |
-+ */ |
12298 |
-+bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file) |
12299 |
-+{ |
12300 |
-+ return !ep->user && |
12301 |
-+ (uid_eq(file->f_cred->euid, ep->bus->node.uid) || |
12302 |
-+ kdbus_ep_is_privileged(ep, file)); |
12303 |
-+} |
12304 |
-+ |
12305 |
-+/** |
12306 |
-+ * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE |
12307 |
-+ * @bus: bus to operate on |
12308 |
-+ * @argp: command payload |
12309 |
-+ * |
12310 |
-+ * Return: NULL or newly created endpoint on success, ERR_PTR on failure. |
12311 |
-+ */ |
12312 |
-+struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp) |
12313 |
-+{ |
12314 |
-+ const char *item_make_name; |
12315 |
-+ struct kdbus_ep *ep = NULL; |
12316 |
-+ struct kdbus_cmd *cmd; |
12317 |
-+ int ret; |
12318 |
-+ |
12319 |
-+ struct kdbus_arg argv[] = { |
12320 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
12321 |
-+ { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, |
12322 |
-+ }; |
12323 |
-+ struct kdbus_args args = { |
12324 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
12325 |
-+ KDBUS_MAKE_ACCESS_GROUP | |
12326 |
-+ KDBUS_MAKE_ACCESS_WORLD, |
12327 |
-+ .argv = argv, |
12328 |
-+ .argc = ARRAY_SIZE(argv), |
12329 |
-+ }; |
12330 |
-+ |
12331 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
12332 |
-+ if (ret < 0) |
12333 |
-+ return ERR_PTR(ret); |
12334 |
-+ if (ret > 0) |
12335 |
-+ return NULL; |
12336 |
-+ |
12337 |
-+ item_make_name = argv[1].item->str; |
12338 |
-+ |
12339 |
-+ ep = kdbus_ep_new(bus, item_make_name, cmd->flags, |
12340 |
-+ current_euid(), current_egid(), true); |
12341 |
-+ if (IS_ERR(ep)) { |
12342 |
-+ ret = PTR_ERR(ep); |
12343 |
-+ ep = NULL; |
12344 |
-+ goto exit; |
12345 |
-+ } |
12346 |
-+ |
12347 |
-+ if (!kdbus_node_activate(&ep->node)) { |
12348 |
-+ ret = -ESHUTDOWN; |
12349 |
-+ goto exit; |
12350 |
-+ } |
12351 |
-+ |
12352 |
-+exit: |
12353 |
-+ ret = kdbus_args_clear(&args, ret); |
12354 |
-+ if (ret < 0) { |
12355 |
-+ if (ep) { |
12356 |
-+ kdbus_node_deactivate(&ep->node); |
12357 |
-+ kdbus_ep_unref(ep); |
12358 |
-+ } |
12359 |
-+ return ERR_PTR(ret); |
12360 |
-+ } |
12361 |
-+ return ep; |
12362 |
-+} |
12363 |
-+ |
12364 |
-+/** |
12365 |
-+ * kdbus_cmd_ep_update() - handle KDBUS_CMD_ENDPOINT_UPDATE |
12366 |
-+ * @ep: endpoint to operate on |
12367 |
-+ * @argp: command payload |
12368 |
-+ * |
12369 |
-+ * Return: >=0 on success, negative error code on failure. |
12370 |
-+ */ |
12371 |
-+int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp) |
12372 |
-+{ |
12373 |
-+ struct kdbus_cmd *cmd; |
12374 |
-+ int ret; |
12375 |
-+ |
12376 |
-+ struct kdbus_arg argv[] = { |
12377 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
12378 |
-+ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
12379 |
-+ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
12380 |
-+ }; |
12381 |
-+ struct kdbus_args args = { |
12382 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
12383 |
-+ .argv = argv, |
12384 |
-+ .argc = ARRAY_SIZE(argv), |
12385 |
-+ }; |
12386 |
-+ |
12387 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
12388 |
-+ if (ret != 0) |
12389 |
-+ return ret; |
12390 |
-+ |
12391 |
-+ ret = kdbus_policy_set(&ep->policy_db, args.items, args.items_size, |
12392 |
-+ 0, true, ep); |
12393 |
-+ return kdbus_args_clear(&args, ret); |
12394 |
-+} |
12395 |
-diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h |
12396 |
-new file mode 100644 |
12397 |
-index 0000000..e0da59f |
12398 |
---- /dev/null |
12399 |
-+++ b/ipc/kdbus/endpoint.h |
12400 |
-@@ -0,0 +1,70 @@ |
12401 |
-+/* |
12402 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12403 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12404 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12405 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12406 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12407 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12408 |
-+ * |
12409 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12410 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12411 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12412 |
-+ * your option) any later version. |
12413 |
-+ */ |
12414 |
-+ |
12415 |
-+#ifndef __KDBUS_ENDPOINT_H |
12416 |
-+#define __KDBUS_ENDPOINT_H |
12417 |
-+ |
12418 |
-+#include <linux/list.h> |
12419 |
-+#include <linux/mutex.h> |
12420 |
-+#include <linux/uidgid.h> |
12421 |
-+#include "node.h" |
12422 |
-+#include "policy.h" |
12423 |
-+ |
12424 |
-+struct kdbus_bus; |
12425 |
-+struct kdbus_user; |
12426 |
-+ |
12427 |
-+/** |
12428 |
-+ * struct kdbus_ep - endpoint to access a bus |
12429 |
-+ * @node: The kdbus node |
12430 |
-+ * @lock: Endpoint data lock |
12431 |
-+ * @bus: Bus behind this endpoint |
12432 |
-+ * @user: Custom enpoints account against an anonymous user |
12433 |
-+ * @policy_db: Uploaded policy |
12434 |
-+ * @conn_list: Connections of this endpoint |
12435 |
-+ * |
12436 |
-+ * An endpoint offers access to a bus; the default endpoint node name is "bus". |
12437 |
-+ * Additional custom endpoints to the same bus can be created and they can |
12438 |
-+ * carry their own policies/filters. |
12439 |
-+ */ |
12440 |
-+struct kdbus_ep { |
12441 |
-+ struct kdbus_node node; |
12442 |
-+ struct mutex lock; |
12443 |
-+ |
12444 |
-+ /* static */ |
12445 |
-+ struct kdbus_bus *bus; |
12446 |
-+ struct kdbus_user *user; |
12447 |
-+ |
12448 |
-+ /* protected by own locks */ |
12449 |
-+ struct kdbus_policy_db policy_db; |
12450 |
-+ |
12451 |
-+ /* protected by ep->lock */ |
12452 |
-+ struct list_head conn_list; |
12453 |
-+}; |
12454 |
-+ |
12455 |
-+#define kdbus_ep_from_node(_node) \ |
12456 |
-+ container_of((_node), struct kdbus_ep, node) |
12457 |
-+ |
12458 |
-+struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, |
12459 |
-+ unsigned int access, kuid_t uid, kgid_t gid, |
12460 |
-+ bool policy); |
12461 |
-+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep); |
12462 |
-+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep); |
12463 |
-+ |
12464 |
-+bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file); |
12465 |
-+bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file); |
12466 |
-+ |
12467 |
-+struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp); |
12468 |
-+int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp); |
12469 |
-+ |
12470 |
-+#endif |
12471 |
-diff --git a/ipc/kdbus/fs.c b/ipc/kdbus/fs.c |
12472 |
-new file mode 100644 |
12473 |
-index 0000000..09c4809 |
12474 |
---- /dev/null |
12475 |
-+++ b/ipc/kdbus/fs.c |
12476 |
-@@ -0,0 +1,508 @@ |
12477 |
-+/* |
12478 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12479 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12480 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12481 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12482 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12483 |
-+ * |
12484 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12485 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12486 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12487 |
-+ * your option) any later version. |
12488 |
-+ */ |
12489 |
-+ |
12490 |
-+#include <linux/dcache.h> |
12491 |
-+#include <linux/fs.h> |
12492 |
-+#include <linux/fsnotify.h> |
12493 |
-+#include <linux/init.h> |
12494 |
-+#include <linux/ipc_namespace.h> |
12495 |
-+#include <linux/magic.h> |
12496 |
-+#include <linux/module.h> |
12497 |
-+#include <linux/mount.h> |
12498 |
-+#include <linux/mutex.h> |
12499 |
-+#include <linux/namei.h> |
12500 |
-+#include <linux/pagemap.h> |
12501 |
-+#include <linux/sched.h> |
12502 |
-+#include <linux/slab.h> |
12503 |
-+ |
12504 |
-+#include "bus.h" |
12505 |
-+#include "domain.h" |
12506 |
-+#include "endpoint.h" |
12507 |
-+#include "fs.h" |
12508 |
-+#include "handle.h" |
12509 |
-+#include "node.h" |
12510 |
-+ |
12511 |
-+#define kdbus_node_from_dentry(_dentry) \ |
12512 |
-+ ((struct kdbus_node *)(_dentry)->d_fsdata) |
12513 |
-+ |
12514 |
-+static struct inode *fs_inode_get(struct super_block *sb, |
12515 |
-+ struct kdbus_node *node); |
12516 |
-+ |
12517 |
-+/* |
12518 |
-+ * Directory Management |
12519 |
-+ */ |
12520 |
-+ |
12521 |
-+static inline unsigned char kdbus_dt_type(struct kdbus_node *node) |
12522 |
-+{ |
12523 |
-+ switch (node->type) { |
12524 |
-+ case KDBUS_NODE_DOMAIN: |
12525 |
-+ case KDBUS_NODE_BUS: |
12526 |
-+ return DT_DIR; |
12527 |
-+ case KDBUS_NODE_CONTROL: |
12528 |
-+ case KDBUS_NODE_ENDPOINT: |
12529 |
-+ return DT_REG; |
12530 |
-+ } |
12531 |
-+ |
12532 |
-+ return DT_UNKNOWN; |
12533 |
-+} |
12534 |
-+ |
12535 |
-+static int fs_dir_fop_iterate(struct file *file, struct dir_context *ctx) |
12536 |
-+{ |
12537 |
-+ struct dentry *dentry = file->f_path.dentry; |
12538 |
-+ struct kdbus_node *parent = kdbus_node_from_dentry(dentry); |
12539 |
-+ struct kdbus_node *old, *next = file->private_data; |
12540 |
-+ |
12541 |
-+ /* |
12542 |
-+ * kdbusfs directory iterator (modelled after sysfs/kernfs) |
12543 |
-+ * When iterating kdbusfs directories, we iterate all children of the |
12544 |
-+ * parent kdbus_node object. We use ctx->pos to store the hash of the |
12545 |
-+ * child and file->private_data to store a reference to the next node |
12546 |
-+ * object. If ctx->pos is not modified via llseek while you iterate a |
12547 |
-+ * directory, then we use the file->private_data node pointer to |
12548 |
-+ * directly access the next node in the tree. |
12549 |
-+ * However, if you directly seek on the directory, we have to find the |
12550 |
-+ * closest node to that position and cannot use our node pointer. This |
12551 |
-+ * means iterating the rb-tree to find the closest match and start over |
12552 |
-+ * from there. |
12553 |
-+ * Note that hash values are not necessarily unique. Therefore, llseek |
12554 |
-+ * is not guaranteed to seek to the same node that you got when you |
12555 |
-+ * retrieved the position. Seeking to 0, 1, 2 and >=INT_MAX is safe, |
12556 |
-+ * though. We could use the inode-number as position, but this would |
12557 |
-+ * require another rb-tree for fast access. Kernfs and others already |
12558 |
-+ * ignore those conflicts, so we should be fine, too. |
12559 |
-+ */ |
12560 |
-+ |
12561 |
-+ if (!dir_emit_dots(file, ctx)) |
12562 |
-+ return 0; |
12563 |
-+ |
12564 |
-+ /* acquire @next; if deactivated, or seek detected, find next node */ |
12565 |
-+ old = next; |
12566 |
-+ if (next && ctx->pos == next->hash) { |
12567 |
-+ if (kdbus_node_acquire(next)) |
12568 |
-+ kdbus_node_ref(next); |
12569 |
-+ else |
12570 |
-+ next = kdbus_node_next_child(parent, next); |
12571 |
-+ } else { |
12572 |
-+ next = kdbus_node_find_closest(parent, ctx->pos); |
12573 |
-+ } |
12574 |
-+ kdbus_node_unref(old); |
12575 |
-+ |
12576 |
-+ while (next) { |
12577 |
-+ /* emit @next */ |
12578 |
-+ file->private_data = next; |
12579 |
-+ ctx->pos = next->hash; |
12580 |
-+ |
12581 |
-+ kdbus_node_release(next); |
12582 |
-+ |
12583 |
-+ if (!dir_emit(ctx, next->name, strlen(next->name), next->id, |
12584 |
-+ kdbus_dt_type(next))) |
12585 |
-+ return 0; |
12586 |
-+ |
12587 |
-+ /* find next node after @next */ |
12588 |
-+ old = next; |
12589 |
-+ next = kdbus_node_next_child(parent, next); |
12590 |
-+ kdbus_node_unref(old); |
12591 |
-+ } |
12592 |
-+ |
12593 |
-+ file->private_data = NULL; |
12594 |
-+ ctx->pos = INT_MAX; |
12595 |
-+ |
12596 |
-+ return 0; |
12597 |
-+} |
12598 |
-+ |
12599 |
-+static loff_t fs_dir_fop_llseek(struct file *file, loff_t offset, int whence) |
12600 |
-+{ |
12601 |
-+ struct inode *inode = file_inode(file); |
12602 |
-+ loff_t ret; |
12603 |
-+ |
12604 |
-+ /* protect f_off against fop_iterate */ |
12605 |
-+ mutex_lock(&inode->i_mutex); |
12606 |
-+ ret = generic_file_llseek(file, offset, whence); |
12607 |
-+ mutex_unlock(&inode->i_mutex); |
12608 |
-+ |
12609 |
-+ return ret; |
12610 |
-+} |
12611 |
-+ |
12612 |
-+static int fs_dir_fop_release(struct inode *inode, struct file *file) |
12613 |
-+{ |
12614 |
-+ kdbus_node_unref(file->private_data); |
12615 |
-+ return 0; |
12616 |
-+} |
12617 |
-+ |
12618 |
-+static const struct file_operations fs_dir_fops = { |
12619 |
-+ .read = generic_read_dir, |
12620 |
-+ .iterate = fs_dir_fop_iterate, |
12621 |
-+ .llseek = fs_dir_fop_llseek, |
12622 |
-+ .release = fs_dir_fop_release, |
12623 |
-+}; |
12624 |
-+ |
12625 |
-+static struct dentry *fs_dir_iop_lookup(struct inode *dir, |
12626 |
-+ struct dentry *dentry, |
12627 |
-+ unsigned int flags) |
12628 |
-+{ |
12629 |
-+ struct dentry *dnew = NULL; |
12630 |
-+ struct kdbus_node *parent; |
12631 |
-+ struct kdbus_node *node; |
12632 |
-+ struct inode *inode; |
12633 |
-+ |
12634 |
-+ parent = kdbus_node_from_dentry(dentry->d_parent); |
12635 |
-+ if (!kdbus_node_acquire(parent)) |
12636 |
-+ return NULL; |
12637 |
-+ |
12638 |
-+ /* returns reference to _acquired_ child node */ |
12639 |
-+ node = kdbus_node_find_child(parent, dentry->d_name.name); |
12640 |
-+ if (node) { |
12641 |
-+ dentry->d_fsdata = node; |
12642 |
-+ inode = fs_inode_get(dir->i_sb, node); |
12643 |
-+ if (IS_ERR(inode)) |
12644 |
-+ dnew = ERR_CAST(inode); |
12645 |
-+ else |
12646 |
-+ dnew = d_splice_alias(inode, dentry); |
12647 |
-+ |
12648 |
-+ kdbus_node_release(node); |
12649 |
-+ } |
12650 |
-+ |
12651 |
-+ kdbus_node_release(parent); |
12652 |
-+ return dnew; |
12653 |
-+} |
12654 |
-+ |
12655 |
-+static const struct inode_operations fs_dir_iops = { |
12656 |
-+ .permission = generic_permission, |
12657 |
-+ .lookup = fs_dir_iop_lookup, |
12658 |
-+}; |
12659 |
-+ |
12660 |
-+/* |
12661 |
-+ * Inode Management |
12662 |
-+ */ |
12663 |
-+ |
12664 |
-+static const struct inode_operations fs_inode_iops = { |
12665 |
-+ .permission = generic_permission, |
12666 |
-+}; |
12667 |
-+ |
12668 |
-+static struct inode *fs_inode_get(struct super_block *sb, |
12669 |
-+ struct kdbus_node *node) |
12670 |
-+{ |
12671 |
-+ struct inode *inode; |
12672 |
-+ |
12673 |
-+ inode = iget_locked(sb, node->id); |
12674 |
-+ if (!inode) |
12675 |
-+ return ERR_PTR(-ENOMEM); |
12676 |
-+ if (!(inode->i_state & I_NEW)) |
12677 |
-+ return inode; |
12678 |
-+ |
12679 |
-+ inode->i_private = kdbus_node_ref(node); |
12680 |
-+ inode->i_mapping->a_ops = &empty_aops; |
12681 |
-+ inode->i_mode = node->mode & S_IALLUGO; |
12682 |
-+ inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
12683 |
-+ inode->i_uid = node->uid; |
12684 |
-+ inode->i_gid = node->gid; |
12685 |
-+ |
12686 |
-+ switch (node->type) { |
12687 |
-+ case KDBUS_NODE_DOMAIN: |
12688 |
-+ case KDBUS_NODE_BUS: |
12689 |
-+ inode->i_mode |= S_IFDIR; |
12690 |
-+ inode->i_op = &fs_dir_iops; |
12691 |
-+ inode->i_fop = &fs_dir_fops; |
12692 |
-+ set_nlink(inode, 2); |
12693 |
-+ break; |
12694 |
-+ case KDBUS_NODE_CONTROL: |
12695 |
-+ case KDBUS_NODE_ENDPOINT: |
12696 |
-+ inode->i_mode |= S_IFREG; |
12697 |
-+ inode->i_op = &fs_inode_iops; |
12698 |
-+ inode->i_fop = &kdbus_handle_ops; |
12699 |
-+ break; |
12700 |
-+ } |
12701 |
-+ |
12702 |
-+ unlock_new_inode(inode); |
12703 |
-+ |
12704 |
-+ return inode; |
12705 |
-+} |
12706 |
-+ |
12707 |
-+/* |
12708 |
-+ * Superblock Management |
12709 |
-+ */ |
12710 |
-+ |
12711 |
-+static int fs_super_dop_revalidate(struct dentry *dentry, unsigned int flags) |
12712 |
-+{ |
12713 |
-+ struct kdbus_node *node; |
12714 |
-+ |
12715 |
-+ /* Force lookup on negatives */ |
12716 |
-+ if (!dentry->d_inode) |
12717 |
-+ return 0; |
12718 |
-+ |
12719 |
-+ node = kdbus_node_from_dentry(dentry); |
12720 |
-+ |
12721 |
-+ /* see whether the node has been removed */ |
12722 |
-+ if (!kdbus_node_is_active(node)) |
12723 |
-+ return 0; |
12724 |
-+ |
12725 |
-+ return 1; |
12726 |
-+} |
12727 |
-+ |
12728 |
-+static void fs_super_dop_release(struct dentry *dentry) |
12729 |
-+{ |
12730 |
-+ kdbus_node_unref(dentry->d_fsdata); |
12731 |
-+} |
12732 |
-+ |
12733 |
-+static const struct dentry_operations fs_super_dops = { |
12734 |
-+ .d_revalidate = fs_super_dop_revalidate, |
12735 |
-+ .d_release = fs_super_dop_release, |
12736 |
-+}; |
12737 |
-+ |
12738 |
-+static void fs_super_sop_evict_inode(struct inode *inode) |
12739 |
-+{ |
12740 |
-+ struct kdbus_node *node = kdbus_node_from_inode(inode); |
12741 |
-+ |
12742 |
-+ truncate_inode_pages_final(&inode->i_data); |
12743 |
-+ clear_inode(inode); |
12744 |
-+ kdbus_node_unref(node); |
12745 |
-+} |
12746 |
-+ |
12747 |
-+static const struct super_operations fs_super_sops = { |
12748 |
-+ .statfs = simple_statfs, |
12749 |
-+ .drop_inode = generic_delete_inode, |
12750 |
-+ .evict_inode = fs_super_sop_evict_inode, |
12751 |
-+}; |
12752 |
-+ |
12753 |
-+static int fs_super_fill(struct super_block *sb) |
12754 |
-+{ |
12755 |
-+ struct kdbus_domain *domain = sb->s_fs_info; |
12756 |
-+ struct inode *inode; |
12757 |
-+ int ret; |
12758 |
-+ |
12759 |
-+ sb->s_blocksize = PAGE_CACHE_SIZE; |
12760 |
-+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
12761 |
-+ sb->s_magic = KDBUS_SUPER_MAGIC; |
12762 |
-+ sb->s_maxbytes = MAX_LFS_FILESIZE; |
12763 |
-+ sb->s_op = &fs_super_sops; |
12764 |
-+ sb->s_time_gran = 1; |
12765 |
-+ |
12766 |
-+ inode = fs_inode_get(sb, &domain->node); |
12767 |
-+ if (IS_ERR(inode)) |
12768 |
-+ return PTR_ERR(inode); |
12769 |
-+ |
12770 |
-+ sb->s_root = d_make_root(inode); |
12771 |
-+ if (!sb->s_root) { |
12772 |
-+ /* d_make_root iput()s the inode on failure */ |
12773 |
-+ return -ENOMEM; |
12774 |
-+ } |
12775 |
-+ |
12776 |
-+ /* sb holds domain reference */ |
12777 |
-+ sb->s_root->d_fsdata = &domain->node; |
12778 |
-+ sb->s_d_op = &fs_super_dops; |
12779 |
-+ |
12780 |
-+ /* sb holds root reference */ |
12781 |
-+ domain->dentry = sb->s_root; |
12782 |
-+ |
12783 |
-+ if (!kdbus_node_activate(&domain->node)) |
12784 |
-+ return -ESHUTDOWN; |
12785 |
-+ |
12786 |
-+ ret = kdbus_domain_populate(domain, KDBUS_MAKE_ACCESS_WORLD); |
12787 |
-+ if (ret < 0) |
12788 |
-+ return ret; |
12789 |
-+ |
12790 |
-+ sb->s_flags |= MS_ACTIVE; |
12791 |
-+ return 0; |
12792 |
-+} |
12793 |
-+ |
12794 |
-+static void fs_super_kill(struct super_block *sb) |
12795 |
-+{ |
12796 |
-+ struct kdbus_domain *domain = sb->s_fs_info; |
12797 |
-+ |
12798 |
-+ if (domain) { |
12799 |
-+ kdbus_node_deactivate(&domain->node); |
12800 |
-+ domain->dentry = NULL; |
12801 |
-+ } |
12802 |
-+ |
12803 |
-+ kill_anon_super(sb); |
12804 |
-+ kdbus_domain_unref(domain); |
12805 |
-+} |
12806 |
-+ |
12807 |
-+static int fs_super_set(struct super_block *sb, void *data) |
12808 |
-+{ |
12809 |
-+ int ret; |
12810 |
-+ |
12811 |
-+ ret = set_anon_super(sb, data); |
12812 |
-+ if (!ret) |
12813 |
-+ sb->s_fs_info = data; |
12814 |
-+ |
12815 |
-+ return ret; |
12816 |
-+} |
12817 |
-+ |
12818 |
-+static struct dentry *fs_super_mount(struct file_system_type *fs_type, |
12819 |
-+ int flags, const char *dev_name, |
12820 |
-+ void *data) |
12821 |
-+{ |
12822 |
-+ struct kdbus_domain *domain; |
12823 |
-+ struct super_block *sb; |
12824 |
-+ int ret; |
12825 |
-+ |
12826 |
-+ domain = kdbus_domain_new(KDBUS_MAKE_ACCESS_WORLD); |
12827 |
-+ if (IS_ERR(domain)) |
12828 |
-+ return ERR_CAST(domain); |
12829 |
-+ |
12830 |
-+ sb = sget(fs_type, NULL, fs_super_set, flags, domain); |
12831 |
-+ if (IS_ERR(sb)) { |
12832 |
-+ kdbus_node_deactivate(&domain->node); |
12833 |
-+ kdbus_domain_unref(domain); |
12834 |
-+ return ERR_CAST(sb); |
12835 |
-+ } |
12836 |
-+ |
12837 |
-+ WARN_ON(sb->s_fs_info != domain); |
12838 |
-+ WARN_ON(sb->s_root); |
12839 |
-+ |
12840 |
-+ ret = fs_super_fill(sb); |
12841 |
-+ if (ret < 0) { |
12842 |
-+ /* calls into ->kill_sb() when done */ |
12843 |
-+ deactivate_locked_super(sb); |
12844 |
-+ return ERR_PTR(ret); |
12845 |
-+ } |
12846 |
-+ |
12847 |
-+ return dget(sb->s_root); |
12848 |
-+} |
12849 |
-+ |
12850 |
-+static struct file_system_type fs_type = { |
12851 |
-+ .name = KBUILD_MODNAME "fs", |
12852 |
-+ .owner = THIS_MODULE, |
12853 |
-+ .mount = fs_super_mount, |
12854 |
-+ .kill_sb = fs_super_kill, |
12855 |
-+ .fs_flags = FS_USERNS_MOUNT, |
12856 |
-+}; |
12857 |
-+ |
12858 |
-+/** |
12859 |
-+ * kdbus_fs_init() - register kdbus filesystem |
12860 |
-+ * |
12861 |
-+ * This registers a filesystem with the VFS layer. The filesystem is called |
12862 |
-+ * `KBUILD_MODNAME "fs"', which usually resolves to `kdbusfs'. The nameing |
12863 |
-+ * scheme allows to set KBUILD_MODNAME to "kdbus2" and you will get an |
12864 |
-+ * independent filesystem for developers. |
12865 |
-+ * |
12866 |
-+ * Each mount of the kdbusfs filesystem has an kdbus_domain attached. |
12867 |
-+ * Operations on this mount will only affect the attached domain. On each mount |
12868 |
-+ * a new domain is automatically created and used for this mount exclusively. |
12869 |
-+ * If you want to share a domain across multiple mounts, you need to bind-mount |
12870 |
-+ * it. |
12871 |
-+ * |
12872 |
-+ * Mounts of kdbusfs (with a different domain each) are unrelated to each other |
12873 |
-+ * and will never have any effect on any domain but their own. |
12874 |
-+ * |
12875 |
-+ * Return: 0 on success, negative error otherwise. |
12876 |
-+ */ |
12877 |
-+int kdbus_fs_init(void) |
12878 |
-+{ |
12879 |
-+ return register_filesystem(&fs_type); |
12880 |
-+} |
12881 |
-+ |
12882 |
-+/** |
12883 |
-+ * kdbus_fs_exit() - unregister kdbus filesystem |
12884 |
-+ * |
12885 |
-+ * This does the reverse to kdbus_fs_init(). It unregisters the kdbusfs |
12886 |
-+ * filesystem from VFS and cleans up any allocated resources. |
12887 |
-+ */ |
12888 |
-+void kdbus_fs_exit(void) |
12889 |
-+{ |
12890 |
-+ unregister_filesystem(&fs_type); |
12891 |
-+} |
12892 |
-+ |
12893 |
-+/* acquire domain of @node, making sure all ancestors are active */ |
12894 |
-+static struct kdbus_domain *fs_acquire_domain(struct kdbus_node *node) |
12895 |
-+{ |
12896 |
-+ struct kdbus_domain *domain; |
12897 |
-+ struct kdbus_node *iter; |
12898 |
-+ |
12899 |
-+ /* caller must guarantee that @node is linked */ |
12900 |
-+ for (iter = node; iter->parent; iter = iter->parent) |
12901 |
-+ if (!kdbus_node_is_active(iter->parent)) |
12902 |
-+ return NULL; |
12903 |
-+ |
12904 |
-+ /* root nodes are always domains */ |
12905 |
-+ if (WARN_ON(iter->type != KDBUS_NODE_DOMAIN)) |
12906 |
-+ return NULL; |
12907 |
-+ |
12908 |
-+ domain = kdbus_domain_from_node(iter); |
12909 |
-+ if (!kdbus_node_acquire(&domain->node)) |
12910 |
-+ return NULL; |
12911 |
-+ |
12912 |
-+ return domain; |
12913 |
-+} |
12914 |
-+ |
12915 |
-+/** |
12916 |
-+ * kdbus_fs_flush() - flush dcache entries of a node |
12917 |
-+ * @node: Node to flush entries of |
12918 |
-+ * |
12919 |
-+ * This flushes all VFS filesystem cache entries for a node and all its |
12920 |
-+ * children. This should be called whenever a node is destroyed during |
12921 |
-+ * runtime. It will flush the cache entries so the linked objects can be |
12922 |
-+ * deallocated. |
12923 |
-+ * |
12924 |
-+ * This is a no-op if you call it on active nodes (they really should stay in |
12925 |
-+ * cache) or on nodes with deactivated parents (flushing the parent is enough). |
12926 |
-+ * Furthermore, there is no need to call it on nodes whose lifetime is bound to |
12927 |
-+ * their parents'. In those cases, the parent-flush will always also flush the |
12928 |
-+ * children. |
12929 |
-+ */ |
12930 |
-+void kdbus_fs_flush(struct kdbus_node *node) |
12931 |
-+{ |
12932 |
-+ struct dentry *dentry, *parent_dentry = NULL; |
12933 |
-+ struct kdbus_domain *domain; |
12934 |
-+ struct qstr name; |
12935 |
-+ |
12936 |
-+ /* active nodes should remain in cache */ |
12937 |
-+ if (!kdbus_node_is_deactivated(node)) |
12938 |
-+ return; |
12939 |
-+ |
12940 |
-+ /* nodes that were never linked were never instantiated */ |
12941 |
-+ if (!node->parent) |
12942 |
-+ return; |
12943 |
-+ |
12944 |
-+ /* acquire domain and verify all ancestors are active */ |
12945 |
-+ domain = fs_acquire_domain(node); |
12946 |
-+ if (!domain) |
12947 |
-+ return; |
12948 |
-+ |
12949 |
-+ switch (node->type) { |
12950 |
-+ case KDBUS_NODE_ENDPOINT: |
12951 |
-+ if (WARN_ON(!node->parent || !node->parent->name)) |
12952 |
-+ goto exit; |
12953 |
-+ |
12954 |
-+ name.name = node->parent->name; |
12955 |
-+ name.len = strlen(node->parent->name); |
12956 |
-+ parent_dentry = d_hash_and_lookup(domain->dentry, &name); |
12957 |
-+ if (IS_ERR_OR_NULL(parent_dentry)) |
12958 |
-+ goto exit; |
12959 |
-+ |
12960 |
-+ /* fallthrough */ |
12961 |
-+ case KDBUS_NODE_BUS: |
12962 |
-+ if (WARN_ON(!node->name)) |
12963 |
-+ goto exit; |
12964 |
-+ |
12965 |
-+ name.name = node->name; |
12966 |
-+ name.len = strlen(node->name); |
12967 |
-+ dentry = d_hash_and_lookup(parent_dentry ? : domain->dentry, |
12968 |
-+ &name); |
12969 |
-+ if (!IS_ERR_OR_NULL(dentry)) { |
12970 |
-+ d_invalidate(dentry); |
12971 |
-+ dput(dentry); |
12972 |
-+ } |
12973 |
-+ |
12974 |
-+ dput(parent_dentry); |
12975 |
-+ break; |
12976 |
-+ |
12977 |
-+ default: |
12978 |
-+ /* all other types are bound to their parent lifetime */ |
12979 |
-+ break; |
12980 |
-+ } |
12981 |
-+ |
12982 |
-+exit: |
12983 |
-+ kdbus_node_release(&domain->node); |
12984 |
-+} |
12985 |
-diff --git a/ipc/kdbus/fs.h b/ipc/kdbus/fs.h |
12986 |
-new file mode 100644 |
12987 |
-index 0000000..62f7d6a |
12988 |
---- /dev/null |
12989 |
-+++ b/ipc/kdbus/fs.h |
12990 |
-@@ -0,0 +1,28 @@ |
12991 |
-+/* |
12992 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12993 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12994 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12995 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12996 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12997 |
-+ * |
12998 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12999 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13000 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13001 |
-+ * your option) any later version. |
13002 |
-+ */ |
13003 |
-+ |
13004 |
-+#ifndef __KDBUSFS_H |
13005 |
-+#define __KDBUSFS_H |
13006 |
-+ |
13007 |
-+#include <linux/kernel.h> |
13008 |
-+ |
13009 |
-+struct kdbus_node; |
13010 |
-+ |
13011 |
-+int kdbus_fs_init(void); |
13012 |
-+void kdbus_fs_exit(void); |
13013 |
-+void kdbus_fs_flush(struct kdbus_node *node); |
13014 |
-+ |
13015 |
-+#define kdbus_node_from_inode(_inode) \ |
13016 |
-+ ((struct kdbus_node *)(_inode)->i_private) |
13017 |
-+ |
13018 |
-+#endif |
13019 |
-diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c |
13020 |
-new file mode 100644 |
13021 |
-index 0000000..fc60932 |
13022 |
---- /dev/null |
13023 |
-+++ b/ipc/kdbus/handle.c |
13024 |
-@@ -0,0 +1,691 @@ |
13025 |
-+/* |
13026 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13027 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13028 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13029 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13030 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13031 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
13032 |
-+ * |
13033 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13034 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13035 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13036 |
-+ * your option) any later version. |
13037 |
-+ */ |
13038 |
-+ |
13039 |
-+#include <linux/file.h> |
13040 |
-+#include <linux/fs.h> |
13041 |
-+#include <linux/idr.h> |
13042 |
-+#include <linux/init.h> |
13043 |
-+#include <linux/kdev_t.h> |
13044 |
-+#include <linux/module.h> |
13045 |
-+#include <linux/mutex.h> |
13046 |
-+#include <linux/poll.h> |
13047 |
-+#include <linux/rwsem.h> |
13048 |
-+#include <linux/sched.h> |
13049 |
-+#include <linux/sizes.h> |
13050 |
-+#include <linux/slab.h> |
13051 |
-+#include <linux/uaccess.h> |
13052 |
-+#include <linux/syscalls.h> |
13053 |
-+ |
13054 |
-+#include "bus.h" |
13055 |
-+#include "connection.h" |
13056 |
-+#include "endpoint.h" |
13057 |
-+#include "fs.h" |
13058 |
-+#include "handle.h" |
13059 |
-+#include "item.h" |
13060 |
-+#include "match.h" |
13061 |
-+#include "message.h" |
13062 |
-+#include "names.h" |
13063 |
-+#include "domain.h" |
13064 |
-+#include "policy.h" |
13065 |
-+ |
13066 |
-+static int kdbus_args_verify(struct kdbus_args *args) |
13067 |
-+{ |
13068 |
-+ struct kdbus_item *item; |
13069 |
-+ size_t i; |
13070 |
-+ int ret; |
13071 |
-+ |
13072 |
-+ KDBUS_ITEMS_FOREACH(item, args->items, args->items_size) { |
13073 |
-+ struct kdbus_arg *arg = NULL; |
13074 |
-+ |
13075 |
-+ if (!KDBUS_ITEM_VALID(item, args->items, args->items_size)) |
13076 |
-+ return -EINVAL; |
13077 |
-+ |
13078 |
-+ for (i = 0; i < args->argc; ++i) |
13079 |
-+ if (args->argv[i].type == item->type) |
13080 |
-+ break; |
13081 |
-+ if (i >= args->argc) |
13082 |
-+ return -EINVAL; |
13083 |
-+ |
13084 |
-+ arg = &args->argv[i]; |
13085 |
-+ |
13086 |
-+ ret = kdbus_item_validate(item); |
13087 |
-+ if (ret < 0) |
13088 |
-+ return ret; |
13089 |
-+ |
13090 |
-+ if (arg->item && !arg->multiple) |
13091 |
-+ return -EINVAL; |
13092 |
-+ |
13093 |
-+ arg->item = item; |
13094 |
-+ } |
13095 |
-+ |
13096 |
-+ if (!KDBUS_ITEMS_END(item, args->items, args->items_size)) |
13097 |
-+ return -EINVAL; |
13098 |
-+ |
13099 |
-+ return 0; |
13100 |
-+} |
13101 |
-+ |
13102 |
-+static int kdbus_args_negotiate(struct kdbus_args *args) |
13103 |
-+{ |
13104 |
-+ struct kdbus_item __user *user; |
13105 |
-+ struct kdbus_item *negotiation; |
13106 |
-+ size_t i, j, num; |
13107 |
-+ |
13108 |
-+ /* |
13109 |
-+ * If KDBUS_FLAG_NEGOTIATE is set, we overwrite the flags field with |
13110 |
-+ * the set of supported flags. Furthermore, if an KDBUS_ITEM_NEGOTIATE |
13111 |
-+ * item is passed, we iterate its payload (array of u64, each set to an |
13112 |
-+ * item type) and clear all unsupported item-types to 0. |
13113 |
-+ * The caller might do this recursively, if other flags or objects are |
13114 |
-+ * embedded in the payload itself. |
13115 |
-+ */ |
13116 |
-+ |
13117 |
-+ if (args->cmd->flags & KDBUS_FLAG_NEGOTIATE) { |
13118 |
-+ if (put_user(args->allowed_flags & ~KDBUS_FLAG_NEGOTIATE, |
13119 |
-+ &args->user->flags)) |
13120 |
-+ return -EFAULT; |
13121 |
-+ } |
13122 |
-+ |
13123 |
-+ if (args->argc < 1 || args->argv[0].type != KDBUS_ITEM_NEGOTIATE || |
13124 |
-+ !args->argv[0].item) |
13125 |
-+ return 0; |
13126 |
-+ |
13127 |
-+ negotiation = args->argv[0].item; |
13128 |
-+ user = (struct kdbus_item __user *) |
13129 |
-+ ((u8 __user *)args->user + |
13130 |
-+ ((u8 *)negotiation - (u8 *)args->cmd)); |
13131 |
-+ num = KDBUS_ITEM_PAYLOAD_SIZE(negotiation) / sizeof(u64); |
13132 |
-+ |
13133 |
-+ for (i = 0; i < num; ++i) { |
13134 |
-+ for (j = 0; j < args->argc; ++j) |
13135 |
-+ if (negotiation->data64[i] == args->argv[j].type) |
13136 |
-+ break; |
13137 |
-+ |
13138 |
-+ if (j < args->argc) |
13139 |
-+ continue; |
13140 |
-+ |
13141 |
-+ /* this item is not supported, clear it out */ |
13142 |
-+ negotiation->data64[i] = 0; |
13143 |
-+ if (put_user(negotiation->data64[i], &user->data64[i])) |
13144 |
-+ return -EFAULT; |
13145 |
-+ } |
13146 |
-+ |
13147 |
-+ return 0; |
13148 |
-+} |
13149 |
-+ |
13150 |
-+/** |
13151 |
-+ * __kdbus_args_parse() - parse payload of kdbus command |
13152 |
-+ * @args: object to parse data into |
13153 |
-+ * @is_cmd: whether this is a command or msg payload |
13154 |
-+ * @argp: user-space location of command payload to parse |
13155 |
-+ * @type_size: overall size of command payload to parse |
13156 |
-+ * @items_offset: offset of items array in command payload |
13157 |
-+ * @out: output variable to store pointer to copied payload |
13158 |
-+ * |
13159 |
-+ * This parses the ioctl payload at user-space location @argp into @args. @args |
13160 |
-+ * must be pre-initialized by the caller to reflect the supported flags and |
13161 |
-+ * items of this command. This parser will then copy the command payload into |
13162 |
-+ * kernel-space, verify correctness and consistency and cache pointers to parsed |
13163 |
-+ * items and other data in @args. |
13164 |
-+ * |
13165 |
-+ * If this function succeeded, you must call kdbus_args_clear() to release |
13166 |
-+ * allocated resources before destroying @args. |
13167 |
-+ * |
13168 |
-+ * This can also be used to import kdbus_msg objects. In that case, @is_cmd must |
13169 |
-+ * be set to 'false' and the 'return_flags' field will not be touched (as it |
13170 |
-+ * doesn't exist on kdbus_msg). |
13171 |
-+ * |
13172 |
-+ * Return: On failure a negative error code is returned. Otherwise, 1 is |
13173 |
-+ * returned if negotiation was requested, 0 if not. |
13174 |
-+ */ |
13175 |
-+int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp, |
13176 |
-+ size_t type_size, size_t items_offset, void **out) |
13177 |
-+{ |
13178 |
-+ u64 user_size; |
13179 |
-+ int ret, i; |
13180 |
-+ |
13181 |
-+ ret = kdbus_copy_from_user(&user_size, argp, sizeof(user_size)); |
13182 |
-+ if (ret < 0) |
13183 |
-+ return ret; |
13184 |
-+ |
13185 |
-+ if (user_size < type_size) |
13186 |
-+ return -EINVAL; |
13187 |
-+ if (user_size > KDBUS_CMD_MAX_SIZE) |
13188 |
-+ return -EMSGSIZE; |
13189 |
-+ |
13190 |
-+ if (user_size <= sizeof(args->cmd_buf)) { |
13191 |
-+ if (copy_from_user(args->cmd_buf, argp, user_size)) |
13192 |
-+ return -EFAULT; |
13193 |
-+ args->cmd = (void*)args->cmd_buf; |
13194 |
-+ } else { |
13195 |
-+ args->cmd = memdup_user(argp, user_size); |
13196 |
-+ if (IS_ERR(args->cmd)) |
13197 |
-+ return PTR_ERR(args->cmd); |
13198 |
-+ } |
13199 |
-+ |
13200 |
-+ if (args->cmd->size != user_size) { |
13201 |
-+ ret = -EINVAL; |
13202 |
-+ goto error; |
13203 |
-+ } |
13204 |
-+ |
13205 |
-+ if (is_cmd) |
13206 |
-+ args->cmd->return_flags = 0; |
13207 |
-+ args->user = argp; |
13208 |
-+ args->items = (void *)((u8 *)args->cmd + items_offset); |
13209 |
-+ args->items_size = args->cmd->size - items_offset; |
13210 |
-+ args->is_cmd = is_cmd; |
13211 |
-+ |
13212 |
-+ if (args->cmd->flags & ~args->allowed_flags) { |
13213 |
-+ ret = -EINVAL; |
13214 |
-+ goto error; |
13215 |
-+ } |
13216 |
-+ |
13217 |
-+ ret = kdbus_args_verify(args); |
13218 |
-+ if (ret < 0) |
13219 |
-+ goto error; |
13220 |
-+ |
13221 |
-+ ret = kdbus_args_negotiate(args); |
13222 |
-+ if (ret < 0) |
13223 |
-+ goto error; |
13224 |
-+ |
13225 |
-+ /* mandatory items must be given (but not on negotiation) */ |
13226 |
-+ if (!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE)) { |
13227 |
-+ for (i = 0; i < args->argc; ++i) |
13228 |
-+ if (args->argv[i].mandatory && !args->argv[i].item) { |
13229 |
-+ ret = -EINVAL; |
13230 |
-+ goto error; |
13231 |
-+ } |
13232 |
-+ } |
13233 |
-+ |
13234 |
-+ *out = args->cmd; |
13235 |
-+ return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE); |
13236 |
-+ |
13237 |
-+error: |
13238 |
-+ return kdbus_args_clear(args, ret); |
13239 |
-+} |
13240 |
-+ |
13241 |
-+/** |
13242 |
-+ * kdbus_args_clear() - release allocated command resources |
13243 |
-+ * @args: object to release resources of |
13244 |
-+ * @ret: return value of this command |
13245 |
-+ * |
13246 |
-+ * This frees all allocated resources on @args and copies the command result |
13247 |
-+ * flags into user-space. @ret is usually returned unchanged by this function, |
13248 |
-+ * so it can be used in the final 'return' statement of the command handler. |
13249 |
-+ * |
13250 |
-+ * Return: -EFAULT if return values cannot be copied into user-space, otherwise |
13251 |
-+ * @ret is returned unchanged. |
13252 |
-+ */ |
13253 |
-+int kdbus_args_clear(struct kdbus_args *args, int ret) |
13254 |
-+{ |
13255 |
-+ if (!args) |
13256 |
-+ return ret; |
13257 |
-+ |
13258 |
-+ if (!IS_ERR_OR_NULL(args->cmd)) { |
13259 |
-+ if (args->is_cmd && put_user(args->cmd->return_flags, |
13260 |
-+ &args->user->return_flags)) |
13261 |
-+ ret = -EFAULT; |
13262 |
-+ if (args->cmd != (void*)args->cmd_buf) |
13263 |
-+ kfree(args->cmd); |
13264 |
-+ args->cmd = NULL; |
13265 |
-+ } |
13266 |
-+ |
13267 |
-+ return ret; |
13268 |
-+} |
13269 |
-+ |
13270 |
-+/** |
13271 |
-+ * enum kdbus_handle_type - type an handle can be of |
13272 |
-+ * @KDBUS_HANDLE_NONE: no type set, yet |
13273 |
-+ * @KDBUS_HANDLE_BUS_OWNER: bus owner |
13274 |
-+ * @KDBUS_HANDLE_EP_OWNER: endpoint owner |
13275 |
-+ * @KDBUS_HANDLE_CONNECTED: endpoint connection after HELLO |
13276 |
-+ */ |
13277 |
-+enum kdbus_handle_type { |
13278 |
-+ KDBUS_HANDLE_NONE, |
13279 |
-+ KDBUS_HANDLE_BUS_OWNER, |
13280 |
-+ KDBUS_HANDLE_EP_OWNER, |
13281 |
-+ KDBUS_HANDLE_CONNECTED, |
13282 |
-+}; |
13283 |
-+ |
13284 |
-+/** |
13285 |
-+ * struct kdbus_handle - handle to the kdbus system |
13286 |
-+ * @lock: handle lock |
13287 |
-+ * @type: type of this handle (KDBUS_HANDLE_*) |
13288 |
-+ * @bus_owner: bus this handle owns |
13289 |
-+ * @ep_owner: endpoint this handle owns |
13290 |
-+ * @conn: connection this handle owns |
13291 |
-+ */ |
13292 |
-+struct kdbus_handle { |
13293 |
-+ struct mutex lock; |
13294 |
-+ |
13295 |
-+ enum kdbus_handle_type type; |
13296 |
-+ union { |
13297 |
-+ struct kdbus_bus *bus_owner; |
13298 |
-+ struct kdbus_ep *ep_owner; |
13299 |
-+ struct kdbus_conn *conn; |
13300 |
-+ }; |
13301 |
-+}; |
13302 |
-+ |
13303 |
-+static int kdbus_handle_open(struct inode *inode, struct file *file) |
13304 |
-+{ |
13305 |
-+ struct kdbus_handle *handle; |
13306 |
-+ struct kdbus_node *node; |
13307 |
-+ int ret; |
13308 |
-+ |
13309 |
-+ node = kdbus_node_from_inode(inode); |
13310 |
-+ if (!kdbus_node_acquire(node)) |
13311 |
-+ return -ESHUTDOWN; |
13312 |
-+ |
13313 |
-+ handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
13314 |
-+ if (!handle) { |
13315 |
-+ ret = -ENOMEM; |
13316 |
-+ goto exit; |
13317 |
-+ } |
13318 |
-+ |
13319 |
-+ mutex_init(&handle->lock); |
13320 |
-+ handle->type = KDBUS_HANDLE_NONE; |
13321 |
-+ |
13322 |
-+ file->private_data = handle; |
13323 |
-+ ret = 0; |
13324 |
-+ |
13325 |
-+exit: |
13326 |
-+ kdbus_node_release(node); |
13327 |
-+ return ret; |
13328 |
-+} |
13329 |
-+ |
13330 |
-+static int kdbus_handle_release(struct inode *inode, struct file *file) |
13331 |
-+{ |
13332 |
-+ struct kdbus_handle *handle = file->private_data; |
13333 |
-+ |
13334 |
-+ switch (handle->type) { |
13335 |
-+ case KDBUS_HANDLE_BUS_OWNER: |
13336 |
-+ if (handle->bus_owner) { |
13337 |
-+ kdbus_node_deactivate(&handle->bus_owner->node); |
13338 |
-+ kdbus_bus_unref(handle->bus_owner); |
13339 |
-+ } |
13340 |
-+ break; |
13341 |
-+ case KDBUS_HANDLE_EP_OWNER: |
13342 |
-+ if (handle->ep_owner) { |
13343 |
-+ kdbus_node_deactivate(&handle->ep_owner->node); |
13344 |
-+ kdbus_ep_unref(handle->ep_owner); |
13345 |
-+ } |
13346 |
-+ break; |
13347 |
-+ case KDBUS_HANDLE_CONNECTED: |
13348 |
-+ kdbus_conn_disconnect(handle->conn, false); |
13349 |
-+ kdbus_conn_unref(handle->conn); |
13350 |
-+ break; |
13351 |
-+ case KDBUS_HANDLE_NONE: |
13352 |
-+ /* nothing to clean up */ |
13353 |
-+ break; |
13354 |
-+ } |
13355 |
-+ |
13356 |
-+ kfree(handle); |
13357 |
-+ |
13358 |
-+ return 0; |
13359 |
-+} |
13360 |
-+ |
13361 |
-+static long kdbus_handle_ioctl_control(struct file *file, unsigned int cmd, |
13362 |
-+ void __user *argp) |
13363 |
-+{ |
13364 |
-+ struct kdbus_handle *handle = file->private_data; |
13365 |
-+ struct kdbus_node *node = file_inode(file)->i_private; |
13366 |
-+ struct kdbus_domain *domain; |
13367 |
-+ int ret = 0; |
13368 |
-+ |
13369 |
-+ if (!kdbus_node_acquire(node)) |
13370 |
-+ return -ESHUTDOWN; |
13371 |
-+ |
13372 |
-+ /* |
13373 |
-+ * The parent of control-nodes is always a domain, make sure to pin it |
13374 |
-+ * so the parent is actually valid. |
13375 |
-+ */ |
13376 |
-+ domain = kdbus_domain_from_node(node->parent); |
13377 |
-+ if (!kdbus_node_acquire(&domain->node)) { |
13378 |
-+ kdbus_node_release(node); |
13379 |
-+ return -ESHUTDOWN; |
13380 |
-+ } |
13381 |
-+ |
13382 |
-+ switch (cmd) { |
13383 |
-+ case KDBUS_CMD_BUS_MAKE: { |
13384 |
-+ struct kdbus_bus *bus; |
13385 |
-+ |
13386 |
-+ bus = kdbus_cmd_bus_make(domain, argp); |
13387 |
-+ if (IS_ERR_OR_NULL(bus)) { |
13388 |
-+ ret = PTR_ERR_OR_ZERO(bus); |
13389 |
-+ break; |
13390 |
-+ } |
13391 |
-+ |
13392 |
-+ handle->bus_owner = bus; |
13393 |
-+ ret = KDBUS_HANDLE_BUS_OWNER; |
13394 |
-+ break; |
13395 |
-+ } |
13396 |
-+ |
13397 |
-+ default: |
13398 |
-+ ret = -EBADFD; |
13399 |
-+ break; |
13400 |
-+ } |
13401 |
-+ |
13402 |
-+ kdbus_node_release(&domain->node); |
13403 |
-+ kdbus_node_release(node); |
13404 |
-+ return ret; |
13405 |
-+} |
13406 |
-+ |
13407 |
-+static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd, |
13408 |
-+ void __user *buf) |
13409 |
-+{ |
13410 |
-+ struct kdbus_handle *handle = file->private_data; |
13411 |
-+ struct kdbus_node *node = file_inode(file)->i_private; |
13412 |
-+ struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node); |
13413 |
-+ struct kdbus_bus *bus = file_ep->bus; |
13414 |
-+ struct kdbus_conn *conn; |
13415 |
-+ int ret = 0; |
13416 |
-+ |
13417 |
-+ if (!kdbus_node_acquire(node)) |
13418 |
-+ return -ESHUTDOWN; |
13419 |
-+ |
13420 |
-+ switch (cmd) { |
13421 |
-+ case KDBUS_CMD_ENDPOINT_MAKE: { |
13422 |
-+ /* creating custom endpoints is a privileged operation */ |
13423 |
-+ if (!kdbus_ep_is_owner(file_ep, file)) { |
13424 |
-+ ret = -EPERM; |
13425 |
-+ break; |
13426 |
-+ } |
13427 |
-+ |
13428 |
-+ ep = kdbus_cmd_ep_make(bus, buf); |
13429 |
-+ if (IS_ERR_OR_NULL(ep)) { |
13430 |
-+ ret = PTR_ERR_OR_ZERO(ep); |
13431 |
-+ break; |
13432 |
-+ } |
13433 |
-+ |
13434 |
-+ handle->ep_owner = ep; |
13435 |
-+ ret = KDBUS_HANDLE_EP_OWNER; |
13436 |
-+ break; |
13437 |
-+ } |
13438 |
-+ |
13439 |
-+ case KDBUS_CMD_HELLO: |
13440 |
-+ conn = kdbus_cmd_hello(file_ep, file, buf); |
13441 |
-+ if (IS_ERR_OR_NULL(conn)) { |
13442 |
-+ ret = PTR_ERR_OR_ZERO(conn); |
13443 |
-+ break; |
13444 |
-+ } |
13445 |
-+ |
13446 |
-+ handle->conn = conn; |
13447 |
-+ ret = KDBUS_HANDLE_CONNECTED; |
13448 |
-+ break; |
13449 |
-+ |
13450 |
-+ default: |
13451 |
-+ ret = -EBADFD; |
13452 |
-+ break; |
13453 |
-+ } |
13454 |
-+ |
13455 |
-+ kdbus_node_release(node); |
13456 |
-+ return ret; |
13457 |
-+} |
13458 |
-+ |
13459 |
-+static long kdbus_handle_ioctl_ep_owner(struct file *file, unsigned int command, |
13460 |
-+ void __user *buf) |
13461 |
-+{ |
13462 |
-+ struct kdbus_handle *handle = file->private_data; |
13463 |
-+ struct kdbus_ep *ep = handle->ep_owner; |
13464 |
-+ int ret; |
13465 |
-+ |
13466 |
-+ if (!kdbus_node_acquire(&ep->node)) |
13467 |
-+ return -ESHUTDOWN; |
13468 |
-+ |
13469 |
-+ switch (command) { |
13470 |
-+ case KDBUS_CMD_ENDPOINT_UPDATE: |
13471 |
-+ ret = kdbus_cmd_ep_update(ep, buf); |
13472 |
-+ break; |
13473 |
-+ default: |
13474 |
-+ ret = -EBADFD; |
13475 |
-+ break; |
13476 |
-+ } |
13477 |
-+ |
13478 |
-+ kdbus_node_release(&ep->node); |
13479 |
-+ return ret; |
13480 |
-+} |
13481 |
-+ |
13482 |
-+static long kdbus_handle_ioctl_connected(struct file *file, |
13483 |
-+ unsigned int command, void __user *buf) |
13484 |
-+{ |
13485 |
-+ struct kdbus_handle *handle = file->private_data; |
13486 |
-+ struct kdbus_conn *conn = handle->conn; |
13487 |
-+ struct kdbus_conn *release_conn = NULL; |
13488 |
-+ int ret; |
13489 |
-+ |
13490 |
-+ release_conn = conn; |
13491 |
-+ ret = kdbus_conn_acquire(release_conn); |
13492 |
-+ if (ret < 0) |
13493 |
-+ return ret; |
13494 |
-+ |
13495 |
-+ switch (command) { |
13496 |
-+ case KDBUS_CMD_BYEBYE: |
13497 |
-+ /* |
13498 |
-+ * BYEBYE is special; we must not acquire a connection when |
13499 |
-+ * calling into kdbus_conn_disconnect() or we will deadlock, |
13500 |
-+ * because kdbus_conn_disconnect() will wait for all acquired |
13501 |
-+ * references to be dropped. |
13502 |
-+ */ |
13503 |
-+ kdbus_conn_release(release_conn); |
13504 |
-+ release_conn = NULL; |
13505 |
-+ ret = kdbus_cmd_byebye_unlocked(conn, buf); |
13506 |
-+ break; |
13507 |
-+ case KDBUS_CMD_NAME_ACQUIRE: |
13508 |
-+ ret = kdbus_cmd_name_acquire(conn, buf); |
13509 |
-+ break; |
13510 |
-+ case KDBUS_CMD_NAME_RELEASE: |
13511 |
-+ ret = kdbus_cmd_name_release(conn, buf); |
13512 |
-+ break; |
13513 |
-+ case KDBUS_CMD_LIST: |
13514 |
-+ ret = kdbus_cmd_list(conn, buf); |
13515 |
-+ break; |
13516 |
-+ case KDBUS_CMD_CONN_INFO: |
13517 |
-+ ret = kdbus_cmd_conn_info(conn, buf); |
13518 |
-+ break; |
13519 |
-+ case KDBUS_CMD_BUS_CREATOR_INFO: |
13520 |
-+ ret = kdbus_cmd_bus_creator_info(conn, buf); |
13521 |
-+ break; |
13522 |
-+ case KDBUS_CMD_UPDATE: |
13523 |
-+ ret = kdbus_cmd_update(conn, buf); |
13524 |
-+ break; |
13525 |
-+ case KDBUS_CMD_MATCH_ADD: |
13526 |
-+ ret = kdbus_cmd_match_add(conn, buf); |
13527 |
-+ break; |
13528 |
-+ case KDBUS_CMD_MATCH_REMOVE: |
13529 |
-+ ret = kdbus_cmd_match_remove(conn, buf); |
13530 |
-+ break; |
13531 |
-+ case KDBUS_CMD_SEND: |
13532 |
-+ ret = kdbus_cmd_send(conn, file, buf); |
13533 |
-+ break; |
13534 |
-+ case KDBUS_CMD_RECV: |
13535 |
-+ ret = kdbus_cmd_recv(conn, buf); |
13536 |
-+ break; |
13537 |
-+ case KDBUS_CMD_FREE: |
13538 |
-+ ret = kdbus_cmd_free(conn, buf); |
13539 |
-+ break; |
13540 |
-+ default: |
13541 |
-+ ret = -EBADFD; |
13542 |
-+ break; |
13543 |
-+ } |
13544 |
-+ |
13545 |
-+ kdbus_conn_release(release_conn); |
13546 |
-+ return ret; |
13547 |
-+} |
13548 |
-+ |
13549 |
-+static long kdbus_handle_ioctl(struct file *file, unsigned int cmd, |
13550 |
-+ unsigned long arg) |
13551 |
-+{ |
13552 |
-+ struct kdbus_handle *handle = file->private_data; |
13553 |
-+ struct kdbus_node *node = kdbus_node_from_inode(file_inode(file)); |
13554 |
-+ void __user *argp = (void __user *)arg; |
13555 |
-+ long ret = -EBADFD; |
13556 |
-+ |
13557 |
-+ switch (cmd) { |
13558 |
-+ case KDBUS_CMD_BUS_MAKE: |
13559 |
-+ case KDBUS_CMD_ENDPOINT_MAKE: |
13560 |
-+ case KDBUS_CMD_HELLO: |
13561 |
-+ mutex_lock(&handle->lock); |
13562 |
-+ if (handle->type == KDBUS_HANDLE_NONE) { |
13563 |
-+ if (node->type == KDBUS_NODE_CONTROL) |
13564 |
-+ ret = kdbus_handle_ioctl_control(file, cmd, |
13565 |
-+ argp); |
13566 |
-+ else if (node->type == KDBUS_NODE_ENDPOINT) |
13567 |
-+ ret = kdbus_handle_ioctl_ep(file, cmd, argp); |
13568 |
-+ |
13569 |
-+ if (ret > 0) { |
13570 |
-+ /* |
13571 |
-+ * The data given via open() is not sufficient |
13572 |
-+ * to setup a kdbus handle. Hence, we require |
13573 |
-+ * the user to perform a setup ioctl. This setup |
13574 |
-+ * can only be performed once and defines the |
13575 |
-+ * type of the handle. The different setup |
13576 |
-+ * ioctls are locked against each other so they |
13577 |
-+ * cannot race. Once the handle type is set, |
13578 |
-+ * the type-dependent ioctls are enabled. To |
13579 |
-+ * improve performance, we don't lock those via |
13580 |
-+ * handle->lock. Instead, we issue a |
13581 |
-+ * write-barrier before performing the |
13582 |
-+ * type-change, which pairs with smp_rmb() in |
13583 |
-+ * all handlers that access the type field. This |
13584 |
-+ * guarantees the handle is fully setup, if |
13585 |
-+ * handle->type is set. If handle->type is |
13586 |
-+ * unset, you must not make any assumptions |
13587 |
-+ * without taking handle->lock. |
13588 |
-+ * Note that handle->type is only set once. It |
13589 |
-+ * will never change afterwards. |
13590 |
-+ */ |
13591 |
-+ smp_wmb(); |
13592 |
-+ handle->type = ret; |
13593 |
-+ } |
13594 |
-+ } |
13595 |
-+ mutex_unlock(&handle->lock); |
13596 |
-+ break; |
13597 |
-+ |
13598 |
-+ case KDBUS_CMD_ENDPOINT_UPDATE: |
13599 |
-+ case KDBUS_CMD_BYEBYE: |
13600 |
-+ case KDBUS_CMD_NAME_ACQUIRE: |
13601 |
-+ case KDBUS_CMD_NAME_RELEASE: |
13602 |
-+ case KDBUS_CMD_LIST: |
13603 |
-+ case KDBUS_CMD_CONN_INFO: |
13604 |
-+ case KDBUS_CMD_BUS_CREATOR_INFO: |
13605 |
-+ case KDBUS_CMD_UPDATE: |
13606 |
-+ case KDBUS_CMD_MATCH_ADD: |
13607 |
-+ case KDBUS_CMD_MATCH_REMOVE: |
13608 |
-+ case KDBUS_CMD_SEND: |
13609 |
-+ case KDBUS_CMD_RECV: |
13610 |
-+ case KDBUS_CMD_FREE: { |
13611 |
-+ enum kdbus_handle_type type; |
13612 |
-+ |
13613 |
-+ /* |
13614 |
-+ * This read-barrier pairs with smp_wmb() of the handle setup. |
13615 |
-+ * it guarantees the handle is fully written, in case the |
13616 |
-+ * type has been set. It allows us to access the handle without |
13617 |
-+ * taking handle->lock, given the guarantee that the type is |
13618 |
-+ * only ever set once, and stays constant afterwards. |
13619 |
-+ * Furthermore, the handle object itself is not modified in any |
13620 |
-+ * way after the type is set. That is, the type-field is the |
13621 |
-+ * last field that is written on any handle. If it has not been |
13622 |
-+ * set, we must not access the handle here. |
13623 |
-+ */ |
13624 |
-+ type = handle->type; |
13625 |
-+ smp_rmb(); |
13626 |
-+ |
13627 |
-+ if (type == KDBUS_HANDLE_EP_OWNER) |
13628 |
-+ ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp); |
13629 |
-+ else if (type == KDBUS_HANDLE_CONNECTED) |
13630 |
-+ ret = kdbus_handle_ioctl_connected(file, cmd, argp); |
13631 |
-+ |
13632 |
-+ break; |
13633 |
-+ } |
13634 |
-+ default: |
13635 |
-+ ret = -ENOTTY; |
13636 |
-+ break; |
13637 |
-+ } |
13638 |
-+ |
13639 |
-+ return ret < 0 ? ret : 0; |
13640 |
-+} |
13641 |
-+ |
13642 |
-+static unsigned int kdbus_handle_poll(struct file *file, |
13643 |
-+ struct poll_table_struct *wait) |
13644 |
-+{ |
13645 |
-+ struct kdbus_handle *handle = file->private_data; |
13646 |
-+ enum kdbus_handle_type type; |
13647 |
-+ unsigned int mask = POLLOUT | POLLWRNORM; |
13648 |
-+ |
13649 |
-+ /* |
13650 |
-+ * This pairs with smp_wmb() during handle setup. It guarantees that |
13651 |
-+ * _iff_ the handle type is set, handle->conn is valid. Furthermore, |
13652 |
-+ * _iff_ the type is set, the handle object is constant and never |
13653 |
-+ * changed again. If it's not set, we must not access the handle but |
13654 |
-+ * bail out. We also must assume no setup has taken place, yet. |
13655 |
-+ */ |
13656 |
-+ type = handle->type; |
13657 |
-+ smp_rmb(); |
13658 |
-+ |
13659 |
-+ /* Only a connected endpoint can read/write data */ |
13660 |
-+ if (type != KDBUS_HANDLE_CONNECTED) |
13661 |
-+ return POLLERR | POLLHUP; |
13662 |
-+ |
13663 |
-+ poll_wait(file, &handle->conn->wait, wait); |
13664 |
-+ |
13665 |
-+ /* |
13666 |
-+ * Verify the connection hasn't been deactivated _after_ adding the |
13667 |
-+ * wait-queue. This guarantees, that if the connection is deactivated |
13668 |
-+ * after we checked it, the waitqueue is signaled and we're called |
13669 |
-+ * again. |
13670 |
-+ */ |
13671 |
-+ if (!kdbus_conn_active(handle->conn)) |
13672 |
-+ return POLLERR | POLLHUP; |
13673 |
-+ |
13674 |
-+ if (!list_empty(&handle->conn->queue.msg_list) || |
13675 |
-+ atomic_read(&handle->conn->lost_count) > 0) |
13676 |
-+ mask |= POLLIN | POLLRDNORM; |
13677 |
-+ |
13678 |
-+ return mask; |
13679 |
-+} |
13680 |
-+ |
13681 |
-+static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma) |
13682 |
-+{ |
13683 |
-+ struct kdbus_handle *handle = file->private_data; |
13684 |
-+ enum kdbus_handle_type type; |
13685 |
-+ int ret = -EBADFD; |
13686 |
-+ |
13687 |
-+ /* |
13688 |
-+ * This pairs with smp_wmb() during handle setup. It guarantees that |
13689 |
-+ * _iff_ the handle type is set, handle->conn is valid. Furthermore, |
13690 |
-+ * _iff_ the type is set, the handle object is constant and never |
13691 |
-+ * changed again. If it's not set, we must not access the handle but |
13692 |
-+ * bail out. We also must assume no setup has taken place, yet. |
13693 |
-+ */ |
13694 |
-+ type = handle->type; |
13695 |
-+ smp_rmb(); |
13696 |
-+ |
13697 |
-+ /* Only connected handles have a pool we can map */ |
13698 |
-+ if (type == KDBUS_HANDLE_CONNECTED) |
13699 |
-+ ret = kdbus_pool_mmap(handle->conn->pool, vma); |
13700 |
-+ |
13701 |
-+ return ret; |
13702 |
-+} |
13703 |
-+ |
13704 |
-+const struct file_operations kdbus_handle_ops = { |
13705 |
-+ .owner = THIS_MODULE, |
13706 |
-+ .open = kdbus_handle_open, |
13707 |
-+ .release = kdbus_handle_release, |
13708 |
-+ .poll = kdbus_handle_poll, |
13709 |
-+ .llseek = noop_llseek, |
13710 |
-+ .unlocked_ioctl = kdbus_handle_ioctl, |
13711 |
-+ .mmap = kdbus_handle_mmap, |
13712 |
-+#ifdef CONFIG_COMPAT |
13713 |
-+ .compat_ioctl = kdbus_handle_ioctl, |
13714 |
-+#endif |
13715 |
-+}; |
13716 |
-diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h |
13717 |
-new file mode 100644 |
13718 |
-index 0000000..5dde2c1 |
13719 |
---- /dev/null |
13720 |
-+++ b/ipc/kdbus/handle.h |
13721 |
-@@ -0,0 +1,103 @@ |
13722 |
-+/* |
13723 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13724 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13725 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13726 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13727 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13728 |
-+ * |
13729 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13730 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13731 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13732 |
-+ * your option) any later version. |
13733 |
-+ */ |
13734 |
-+ |
13735 |
-+#ifndef __KDBUS_HANDLE_H |
13736 |
-+#define __KDBUS_HANDLE_H |
13737 |
-+ |
13738 |
-+#include <linux/fs.h> |
13739 |
-+#include <uapi/linux/kdbus.h> |
13740 |
-+ |
13741 |
-+extern const struct file_operations kdbus_handle_ops; |
13742 |
-+ |
13743 |
-+/** |
13744 |
-+ * kdbus_arg - information and state of a single ioctl command item |
13745 |
-+ * @type: item type |
13746 |
-+ * @item: set by the parser to the first found item of this type |
13747 |
-+ * @multiple: whether multiple items of this type are allowed |
13748 |
-+ * @mandatory: whether at least one item of this type is required |
13749 |
-+ * |
13750 |
-+ * This structure describes a single item in an ioctl command payload. The |
13751 |
-+ * caller has to pre-fill the type and flags, the parser will then use this |
13752 |
-+ * information to verify the ioctl payload. @item is set by the parser to point |
13753 |
-+ * to the first occurrence of the item. |
13754 |
-+ */ |
13755 |
-+struct kdbus_arg { |
13756 |
-+ u64 type; |
13757 |
-+ struct kdbus_item *item; |
13758 |
-+ bool multiple : 1; |
13759 |
-+ bool mandatory : 1; |
13760 |
-+}; |
13761 |
-+ |
13762 |
-+/** |
13763 |
-+ * kdbus_args - information and state of ioctl command parser |
13764 |
-+ * @allowed_flags: set of flags this command supports |
13765 |
-+ * @argc: number of items in @argv |
13766 |
-+ * @argv: array of items this command supports |
13767 |
-+ * @user: set by parser to user-space location of current command |
13768 |
-+ * @cmd: set by parser to kernel copy of command payload |
13769 |
-+ * @cmd_buf: inline buf to avoid kmalloc() on small cmds |
13770 |
-+ * @items: points to item array in @cmd |
13771 |
-+ * @items_size: size of @items in bytes |
13772 |
-+ * @is_cmd: whether this is a command-payload or msg-payload |
13773 |
-+ * |
13774 |
-+ * This structure is used to parse ioctl command payloads on each invocation. |
13775 |
-+ * The ioctl handler has to pre-fill the flags and allowed items before passing |
13776 |
-+ * the object to kdbus_args_parse(). The parser will copy the command payload |
13777 |
-+ * into kernel-space and verify the correctness of the data. |
13778 |
-+ * |
13779 |
-+ * We use a 256 bytes buffer for small command payloads, to be allocated on |
13780 |
-+ * stack on syscall entrance. |
13781 |
-+ */ |
13782 |
-+struct kdbus_args { |
13783 |
-+ u64 allowed_flags; |
13784 |
-+ size_t argc; |
13785 |
-+ struct kdbus_arg *argv; |
13786 |
-+ |
13787 |
-+ struct kdbus_cmd __user *user; |
13788 |
-+ struct kdbus_cmd *cmd; |
13789 |
-+ u8 cmd_buf[256]; |
13790 |
-+ |
13791 |
-+ struct kdbus_item *items; |
13792 |
-+ size_t items_size; |
13793 |
-+ bool is_cmd : 1; |
13794 |
-+}; |
13795 |
-+ |
13796 |
-+int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp, |
13797 |
-+ size_t type_size, size_t items_offset, void **out); |
13798 |
-+int kdbus_args_clear(struct kdbus_args *args, int ret); |
13799 |
-+ |
13800 |
-+#define kdbus_args_parse(_args, _argp, _v) \ |
13801 |
-+ ({ \ |
13802 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ |
13803 |
-+ offsetof(struct kdbus_cmd, size)); \ |
13804 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ |
13805 |
-+ offsetof(struct kdbus_cmd, flags)); \ |
13806 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), return_flags) != \ |
13807 |
-+ offsetof(struct kdbus_cmd, return_flags)); \ |
13808 |
-+ __kdbus_args_parse((_args), 1, (_argp), sizeof(**(_v)), \ |
13809 |
-+ offsetof(typeof(**(_v)), items), \ |
13810 |
-+ (void **)(_v)); \ |
13811 |
-+ }) |
13812 |
-+ |
13813 |
-+#define kdbus_args_parse_msg(_args, _argp, _v) \ |
13814 |
-+ ({ \ |
13815 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ |
13816 |
-+ offsetof(struct kdbus_cmd, size)); \ |
13817 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ |
13818 |
-+ offsetof(struct kdbus_cmd, flags)); \ |
13819 |
-+ __kdbus_args_parse((_args), 0, (_argp), sizeof(**(_v)), \ |
13820 |
-+ offsetof(typeof(**(_v)), items), \ |
13821 |
-+ (void **)(_v)); \ |
13822 |
-+ }) |
13823 |
-+ |
13824 |
-+#endif |
13825 |
-diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c |
13826 |
-new file mode 100644 |
13827 |
-index 0000000..ce78dba |
13828 |
---- /dev/null |
13829 |
-+++ b/ipc/kdbus/item.c |
13830 |
-@@ -0,0 +1,293 @@ |
13831 |
-+/* |
13832 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13833 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13834 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13835 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13836 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13837 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
13838 |
-+ * |
13839 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13840 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13841 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13842 |
-+ * your option) any later version. |
13843 |
-+ */ |
13844 |
-+ |
13845 |
-+#include <linux/ctype.h> |
13846 |
-+#include <linux/fs.h> |
13847 |
-+#include <linux/string.h> |
13848 |
-+ |
13849 |
-+#include "item.h" |
13850 |
-+#include "limits.h" |
13851 |
-+#include "util.h" |
13852 |
-+ |
13853 |
-+/* |
13854 |
-+ * This verifies the string at position @str with size @size is properly |
13855 |
-+ * zero-terminated and does not contain a 0-byte but at the end. |
13856 |
-+ */ |
13857 |
-+static bool kdbus_str_valid(const char *str, size_t size) |
13858 |
-+{ |
13859 |
-+ return size > 0 && memchr(str, '\0', size) == str + size - 1; |
13860 |
-+} |
13861 |
-+ |
13862 |
-+/** |
13863 |
-+ * kdbus_item_validate_name() - validate an item containing a name |
13864 |
-+ * @item: Item to validate |
13865 |
-+ * |
13866 |
-+ * Return: zero on success or an negative error code on failure |
13867 |
-+ */ |
13868 |
-+int kdbus_item_validate_name(const struct kdbus_item *item) |
13869 |
-+{ |
13870 |
-+ const char *name = item->str; |
13871 |
-+ unsigned int i; |
13872 |
-+ size_t len; |
13873 |
-+ |
13874 |
-+ if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) |
13875 |
-+ return -EINVAL; |
13876 |
-+ |
13877 |
-+ if (item->size > KDBUS_ITEM_HEADER_SIZE + |
13878 |
-+ KDBUS_SYSNAME_MAX_LEN + 1) |
13879 |
-+ return -ENAMETOOLONG; |
13880 |
-+ |
13881 |
-+ if (!kdbus_str_valid(name, KDBUS_ITEM_PAYLOAD_SIZE(item))) |
13882 |
-+ return -EINVAL; |
13883 |
-+ |
13884 |
-+ len = strlen(name); |
13885 |
-+ if (len == 0) |
13886 |
-+ return -EINVAL; |
13887 |
-+ |
13888 |
-+ for (i = 0; i < len; i++) { |
13889 |
-+ if (isalpha(name[i])) |
13890 |
-+ continue; |
13891 |
-+ if (isdigit(name[i])) |
13892 |
-+ continue; |
13893 |
-+ if (name[i] == '_') |
13894 |
-+ continue; |
13895 |
-+ if (i > 0 && i + 1 < len && (name[i] == '-' || name[i] == '.')) |
13896 |
-+ continue; |
13897 |
-+ |
13898 |
-+ return -EINVAL; |
13899 |
-+ } |
13900 |
-+ |
13901 |
-+ return 0; |
13902 |
-+} |
13903 |
-+ |
13904 |
-+/** |
13905 |
-+ * kdbus_item_validate() - validate a single item |
13906 |
-+ * @item: item to validate |
13907 |
-+ * |
13908 |
-+ * Return: 0 if item is valid, negative error code if not. |
13909 |
-+ */ |
13910 |
-+int kdbus_item_validate(const struct kdbus_item *item) |
13911 |
-+{ |
13912 |
-+ size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item); |
13913 |
-+ size_t l; |
13914 |
-+ int ret; |
13915 |
-+ |
13916 |
-+ BUILD_BUG_ON(KDBUS_ITEM_HEADER_SIZE != |
13917 |
-+ sizeof(struct kdbus_item_header)); |
13918 |
-+ |
13919 |
-+ if (item->size < KDBUS_ITEM_HEADER_SIZE) |
13920 |
-+ return -EINVAL; |
13921 |
-+ |
13922 |
-+ switch (item->type) { |
13923 |
-+ case KDBUS_ITEM_NEGOTIATE: |
13924 |
-+ if (payload_size % sizeof(u64) != 0) |
13925 |
-+ return -EINVAL; |
13926 |
-+ break; |
13927 |
-+ |
13928 |
-+ case KDBUS_ITEM_PAYLOAD_VEC: |
13929 |
-+ case KDBUS_ITEM_PAYLOAD_OFF: |
13930 |
-+ if (payload_size != sizeof(struct kdbus_vec)) |
13931 |
-+ return -EINVAL; |
13932 |
-+ if (item->vec.size == 0 || item->vec.size > SIZE_MAX) |
13933 |
-+ return -EINVAL; |
13934 |
-+ break; |
13935 |
-+ |
13936 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: |
13937 |
-+ if (payload_size != sizeof(struct kdbus_memfd)) |
13938 |
-+ return -EINVAL; |
13939 |
-+ if (item->memfd.size == 0 || item->memfd.size > SIZE_MAX) |
13940 |
-+ return -EINVAL; |
13941 |
-+ if (item->memfd.fd < 0) |
13942 |
-+ return -EBADF; |
13943 |
-+ break; |
13944 |
-+ |
13945 |
-+ case KDBUS_ITEM_FDS: |
13946 |
-+ if (payload_size % sizeof(int) != 0) |
13947 |
-+ return -EINVAL; |
13948 |
-+ break; |
13949 |
-+ |
13950 |
-+ case KDBUS_ITEM_CANCEL_FD: |
13951 |
-+ if (payload_size != sizeof(int)) |
13952 |
-+ return -EINVAL; |
13953 |
-+ break; |
13954 |
-+ |
13955 |
-+ case KDBUS_ITEM_BLOOM_PARAMETER: |
13956 |
-+ if (payload_size != sizeof(struct kdbus_bloom_parameter)) |
13957 |
-+ return -EINVAL; |
13958 |
-+ break; |
13959 |
-+ |
13960 |
-+ case KDBUS_ITEM_BLOOM_FILTER: |
13961 |
-+ /* followed by the bloom-mask, depends on the bloom-size */ |
13962 |
-+ if (payload_size < sizeof(struct kdbus_bloom_filter)) |
13963 |
-+ return -EINVAL; |
13964 |
-+ break; |
13965 |
-+ |
13966 |
-+ case KDBUS_ITEM_BLOOM_MASK: |
13967 |
-+ /* size depends on bloom-size of bus */ |
13968 |
-+ break; |
13969 |
-+ |
13970 |
-+ case KDBUS_ITEM_CONN_DESCRIPTION: |
13971 |
-+ case KDBUS_ITEM_MAKE_NAME: |
13972 |
-+ ret = kdbus_item_validate_name(item); |
13973 |
-+ if (ret < 0) |
13974 |
-+ return ret; |
13975 |
-+ break; |
13976 |
-+ |
13977 |
-+ case KDBUS_ITEM_ATTACH_FLAGS_SEND: |
13978 |
-+ case KDBUS_ITEM_ATTACH_FLAGS_RECV: |
13979 |
-+ case KDBUS_ITEM_ID: |
13980 |
-+ case KDBUS_ITEM_DST_ID: |
13981 |
-+ if (payload_size != sizeof(u64)) |
13982 |
-+ return -EINVAL; |
13983 |
-+ break; |
13984 |
-+ |
13985 |
-+ case KDBUS_ITEM_TIMESTAMP: |
13986 |
-+ if (payload_size != sizeof(struct kdbus_timestamp)) |
13987 |
-+ return -EINVAL; |
13988 |
-+ break; |
13989 |
-+ |
13990 |
-+ case KDBUS_ITEM_CREDS: |
13991 |
-+ if (payload_size != sizeof(struct kdbus_creds)) |
13992 |
-+ return -EINVAL; |
13993 |
-+ break; |
13994 |
-+ |
13995 |
-+ case KDBUS_ITEM_AUXGROUPS: |
13996 |
-+ if (payload_size % sizeof(u32) != 0) |
13997 |
-+ return -EINVAL; |
13998 |
-+ break; |
13999 |
-+ |
14000 |
-+ case KDBUS_ITEM_NAME: |
14001 |
-+ case KDBUS_ITEM_DST_NAME: |
14002 |
-+ case KDBUS_ITEM_PID_COMM: |
14003 |
-+ case KDBUS_ITEM_TID_COMM: |
14004 |
-+ case KDBUS_ITEM_EXE: |
14005 |
-+ case KDBUS_ITEM_CMDLINE: |
14006 |
-+ case KDBUS_ITEM_CGROUP: |
14007 |
-+ case KDBUS_ITEM_SECLABEL: |
14008 |
-+ if (!kdbus_str_valid(item->str, payload_size)) |
14009 |
-+ return -EINVAL; |
14010 |
-+ break; |
14011 |
-+ |
14012 |
-+ case KDBUS_ITEM_CAPS: |
14013 |
-+ if (payload_size < sizeof(u32)) |
14014 |
-+ return -EINVAL; |
14015 |
-+ if (payload_size < sizeof(u32) + |
14016 |
-+ 4 * CAP_TO_INDEX(item->caps.last_cap) * sizeof(u32)) |
14017 |
-+ return -EINVAL; |
14018 |
-+ break; |
14019 |
-+ |
14020 |
-+ case KDBUS_ITEM_AUDIT: |
14021 |
-+ if (payload_size != sizeof(struct kdbus_audit)) |
14022 |
-+ return -EINVAL; |
14023 |
-+ break; |
14024 |
-+ |
14025 |
-+ case KDBUS_ITEM_POLICY_ACCESS: |
14026 |
-+ if (payload_size != sizeof(struct kdbus_policy_access)) |
14027 |
-+ return -EINVAL; |
14028 |
-+ break; |
14029 |
-+ |
14030 |
-+ case KDBUS_ITEM_NAME_ADD: |
14031 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14032 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14033 |
-+ if (payload_size < sizeof(struct kdbus_notify_name_change)) |
14034 |
-+ return -EINVAL; |
14035 |
-+ l = payload_size - offsetof(struct kdbus_notify_name_change, |
14036 |
-+ name); |
14037 |
-+ if (l > 0 && !kdbus_str_valid(item->name_change.name, l)) |
14038 |
-+ return -EINVAL; |
14039 |
-+ break; |
14040 |
-+ |
14041 |
-+ case KDBUS_ITEM_ID_ADD: |
14042 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14043 |
-+ if (payload_size != sizeof(struct kdbus_notify_id_change)) |
14044 |
-+ return -EINVAL; |
14045 |
-+ break; |
14046 |
-+ |
14047 |
-+ case KDBUS_ITEM_REPLY_TIMEOUT: |
14048 |
-+ case KDBUS_ITEM_REPLY_DEAD: |
14049 |
-+ if (payload_size != 0) |
14050 |
-+ return -EINVAL; |
14051 |
-+ break; |
14052 |
-+ |
14053 |
-+ default: |
14054 |
-+ break; |
14055 |
-+ } |
14056 |
-+ |
14057 |
-+ return 0; |
14058 |
-+} |
14059 |
-+ |
14060 |
-+/** |
14061 |
-+ * kdbus_items_validate() - validate items passed by user-space |
14062 |
-+ * @items: items to validate |
14063 |
-+ * @items_size: number of items |
14064 |
-+ * |
14065 |
-+ * This verifies that the passed items pointer is consistent and valid. |
14066 |
-+ * Furthermore, each item is checked for: |
14067 |
-+ * - valid "size" value |
14068 |
-+ * - payload is of expected type |
14069 |
-+ * - payload is fully included in the item |
14070 |
-+ * - string payloads are zero-terminated |
14071 |
-+ * |
14072 |
-+ * Return: 0 on success, negative error code on failure. |
14073 |
-+ */ |
14074 |
-+int kdbus_items_validate(const struct kdbus_item *items, size_t items_size) |
14075 |
-+{ |
14076 |
-+ const struct kdbus_item *item; |
14077 |
-+ int ret; |
14078 |
-+ |
14079 |
-+ KDBUS_ITEMS_FOREACH(item, items, items_size) { |
14080 |
-+ if (!KDBUS_ITEM_VALID(item, items, items_size)) |
14081 |
-+ return -EINVAL; |
14082 |
-+ |
14083 |
-+ ret = kdbus_item_validate(item); |
14084 |
-+ if (ret < 0) |
14085 |
-+ return ret; |
14086 |
-+ } |
14087 |
-+ |
14088 |
-+ if (!KDBUS_ITEMS_END(item, items, items_size)) |
14089 |
-+ return -EINVAL; |
14090 |
-+ |
14091 |
-+ return 0; |
14092 |
-+} |
14093 |
-+ |
14094 |
-+/** |
14095 |
-+ * kdbus_item_set() - Set item content |
14096 |
-+ * @item: The item to modify |
14097 |
-+ * @type: The item type to set (KDBUS_ITEM_*) |
14098 |
-+ * @data: Data to copy to item->data, may be %NULL |
14099 |
-+ * @len: Number of bytes in @data |
14100 |
-+ * |
14101 |
-+ * This sets type, size and data fields of an item. If @data is NULL, the data |
14102 |
-+ * memory is cleared. |
14103 |
-+ * |
14104 |
-+ * Note that you must align your @data memory to 8 bytes. Trailing padding (in |
14105 |
-+ * case @len is not 8byte aligned) is cleared by this call. |
14106 |
-+ * |
14107 |
-+ * Returns: Pointer to the following item. |
14108 |
-+ */ |
14109 |
-+struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, |
14110 |
-+ const void *data, size_t len) |
14111 |
-+{ |
14112 |
-+ item->type = type; |
14113 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + len; |
14114 |
-+ |
14115 |
-+ if (data) { |
14116 |
-+ memcpy(item->data, data, len); |
14117 |
-+ memset(item->data + len, 0, KDBUS_ALIGN8(len) - len); |
14118 |
-+ } else { |
14119 |
-+ memset(item->data, 0, KDBUS_ALIGN8(len)); |
14120 |
-+ } |
14121 |
-+ |
14122 |
-+ return KDBUS_ITEM_NEXT(item); |
14123 |
-+} |
14124 |
-diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h |
14125 |
-new file mode 100644 |
14126 |
-index 0000000..3a7e6cc |
14127 |
---- /dev/null |
14128 |
-+++ b/ipc/kdbus/item.h |
14129 |
-@@ -0,0 +1,61 @@ |
14130 |
-+/* |
14131 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14132 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14133 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14134 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14135 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14136 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14137 |
-+ * |
14138 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14139 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14140 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14141 |
-+ * your option) any later version. |
14142 |
-+ */ |
14143 |
-+ |
14144 |
-+#ifndef __KDBUS_ITEM_H |
14145 |
-+#define __KDBUS_ITEM_H |
14146 |
-+ |
14147 |
-+#include <linux/kernel.h> |
14148 |
-+#include <uapi/linux/kdbus.h> |
14149 |
-+ |
14150 |
-+#include "util.h" |
14151 |
-+ |
14152 |
-+/* generic access and iterators over a stream of items */ |
14153 |
-+#define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size)) |
14154 |
-+#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is)) |
14155 |
-+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
14156 |
-+#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s)) |
14157 |
-+#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE) |
14158 |
-+ |
14159 |
-+#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \ |
14160 |
-+ for ((_i) = (_is); \ |
14161 |
-+ ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \ |
14162 |
-+ ((u8 *)(_i) >= (u8 *)(_is)); \ |
14163 |
-+ (_i) = KDBUS_ITEM_NEXT(_i)) |
14164 |
-+ |
14165 |
-+#define KDBUS_ITEM_VALID(_i, _is, _s) \ |
14166 |
-+ ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \ |
14167 |
-+ (u8 *)(_i) + (_i)->size > (u8 *)(_i) && \ |
14168 |
-+ (u8 *)(_i) + (_i)->size <= (u8 *)(_is) + (_s) && \ |
14169 |
-+ (u8 *)(_i) >= (u8 *)(_is)) |
14170 |
-+ |
14171 |
-+#define KDBUS_ITEMS_END(_i, _is, _s) \ |
14172 |
-+ ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s))) |
14173 |
-+ |
14174 |
-+/** |
14175 |
-+ * struct kdbus_item_header - Describes the fix part of an item |
14176 |
-+ * @size: The total size of the item |
14177 |
-+ * @type: The item type, one of KDBUS_ITEM_* |
14178 |
-+ */ |
14179 |
-+struct kdbus_item_header { |
14180 |
-+ u64 size; |
14181 |
-+ u64 type; |
14182 |
-+}; |
14183 |
-+ |
14184 |
-+int kdbus_item_validate_name(const struct kdbus_item *item); |
14185 |
-+int kdbus_item_validate(const struct kdbus_item *item); |
14186 |
-+int kdbus_items_validate(const struct kdbus_item *items, size_t items_size); |
14187 |
-+struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, |
14188 |
-+ const void *data, size_t len); |
14189 |
-+ |
14190 |
-+#endif |
14191 |
-diff --git a/ipc/kdbus/limits.h b/ipc/kdbus/limits.h |
14192 |
-new file mode 100644 |
14193 |
-index 0000000..c54925a |
14194 |
---- /dev/null |
14195 |
-+++ b/ipc/kdbus/limits.h |
14196 |
-@@ -0,0 +1,61 @@ |
14197 |
-+/* |
14198 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14199 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14200 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14201 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14202 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14203 |
-+ * |
14204 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14205 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14206 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14207 |
-+ * your option) any later version. |
14208 |
-+ */ |
14209 |
-+ |
14210 |
-+#ifndef __KDBUS_DEFAULTS_H |
14211 |
-+#define __KDBUS_DEFAULTS_H |
14212 |
-+ |
14213 |
-+#include <linux/kernel.h> |
14214 |
-+ |
14215 |
-+/* maximum size of message header and items */ |
14216 |
-+#define KDBUS_MSG_MAX_SIZE SZ_8K |
14217 |
-+ |
14218 |
-+/* maximum number of memfd items per message */ |
14219 |
-+#define KDBUS_MSG_MAX_MEMFD_ITEMS 16 |
14220 |
-+ |
14221 |
-+/* max size of ioctl command data */ |
14222 |
-+#define KDBUS_CMD_MAX_SIZE SZ_32K |
14223 |
-+ |
14224 |
-+/* maximum number of inflight fds in a target queue per user */ |
14225 |
-+#define KDBUS_CONN_MAX_FDS_PER_USER 16 |
14226 |
-+ |
14227 |
-+/* maximum message payload size */ |
14228 |
-+#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE SZ_2M |
14229 |
-+ |
14230 |
-+/* maximum size of bloom bit field in bytes */ |
14231 |
-+#define KDBUS_BUS_BLOOM_MAX_SIZE SZ_4K |
14232 |
-+ |
14233 |
-+/* maximum length of well-known bus name */ |
14234 |
-+#define KDBUS_NAME_MAX_LEN 255 |
14235 |
-+ |
14236 |
-+/* maximum length of bus, domain, ep name */ |
14237 |
-+#define KDBUS_SYSNAME_MAX_LEN 63 |
14238 |
-+ |
14239 |
-+/* maximum number of matches per connection */ |
14240 |
-+#define KDBUS_MATCH_MAX 256 |
14241 |
-+ |
14242 |
-+/* maximum number of queued messages from the same individual user */ |
14243 |
-+#define KDBUS_CONN_MAX_MSGS 256 |
14244 |
-+ |
14245 |
-+/* maximum number of well-known names per connection */ |
14246 |
-+#define KDBUS_CONN_MAX_NAMES 256 |
14247 |
-+ |
14248 |
-+/* maximum number of queued requests waiting for a reply */ |
14249 |
-+#define KDBUS_CONN_MAX_REQUESTS_PENDING 128 |
14250 |
-+ |
14251 |
-+/* maximum number of connections per user in one domain */ |
14252 |
-+#define KDBUS_USER_MAX_CONN 1024 |
14253 |
-+ |
14254 |
-+/* maximum number of buses per user in one domain */ |
14255 |
-+#define KDBUS_USER_MAX_BUSES 16 |
14256 |
-+ |
14257 |
-+#endif |
14258 |
-diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c |
14259 |
-new file mode 100644 |
14260 |
-index 0000000..1ad4dc8 |
14261 |
---- /dev/null |
14262 |
-+++ b/ipc/kdbus/main.c |
14263 |
-@@ -0,0 +1,114 @@ |
14264 |
-+/* |
14265 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14266 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14267 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14268 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14269 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14270 |
-+ * |
14271 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14272 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14273 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14274 |
-+ * your option) any later version. |
14275 |
-+ */ |
14276 |
-+ |
14277 |
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14278 |
-+#include <linux/fs.h> |
14279 |
-+#include <linux/init.h> |
14280 |
-+#include <linux/module.h> |
14281 |
-+ |
14282 |
-+#include "util.h" |
14283 |
-+#include "fs.h" |
14284 |
-+#include "handle.h" |
14285 |
-+#include "metadata.h" |
14286 |
-+#include "node.h" |
14287 |
-+ |
14288 |
-+/* |
14289 |
-+ * This is a simplified outline of the internal kdbus object relations, for |
14290 |
-+ * those interested in the inner life of the driver implementation. |
14291 |
-+ * |
14292 |
-+ * From a mount point's (domain's) perspective: |
14293 |
-+ * |
14294 |
-+ * struct kdbus_domain |
14295 |
-+ * |» struct kdbus_user *user (many, owned) |
14296 |
-+ * '» struct kdbus_node node (embedded) |
14297 |
-+ * |» struct kdbus_node children (many, referenced) |
14298 |
-+ * |» struct kdbus_node *parent (pinned) |
14299 |
-+ * '» struct kdbus_bus (many, pinned) |
14300 |
-+ * |» struct kdbus_node node (embedded) |
14301 |
-+ * '» struct kdbus_ep (many, pinned) |
14302 |
-+ * |» struct kdbus_node node (embedded) |
14303 |
-+ * |» struct kdbus_bus *bus (pinned) |
14304 |
-+ * |» struct kdbus_conn conn_list (many, pinned) |
14305 |
-+ * | |» struct kdbus_ep *ep (pinned) |
14306 |
-+ * | |» struct kdbus_name_entry *activator_of (owned) |
14307 |
-+ * | |» struct kdbus_match_db *match_db (owned) |
14308 |
-+ * | |» struct kdbus_meta *meta (owned) |
14309 |
-+ * | |» struct kdbus_match_db *match_db (owned) |
14310 |
-+ * | | '» struct kdbus_match_entry (many, owned) |
14311 |
-+ * | | |
14312 |
-+ * | |» struct kdbus_pool *pool (owned) |
14313 |
-+ * | | '» struct kdbus_pool_slice *slices (many, owned) |
14314 |
-+ * | | '» struct kdbus_pool *pool (pinned) |
14315 |
-+ * | | |
14316 |
-+ * | |» struct kdbus_user *user (pinned) |
14317 |
-+ * | `» struct kdbus_queue_entry entries (many, embedded) |
14318 |
-+ * | |» struct kdbus_pool_slice *slice (pinned) |
14319 |
-+ * | |» struct kdbus_conn_reply *reply (owned) |
14320 |
-+ * | '» struct kdbus_user *user (pinned) |
14321 |
-+ * | |
14322 |
-+ * '» struct kdbus_user *user (pinned) |
14323 |
-+ * '» struct kdbus_policy_db policy_db (embedded) |
14324 |
-+ * |» struct kdbus_policy_db_entry (many, owned) |
14325 |
-+ * | |» struct kdbus_conn (pinned) |
14326 |
-+ * | '» struct kdbus_ep (pinned) |
14327 |
-+ * | |
14328 |
-+ * '» struct kdbus_policy_db_cache_entry (many, owned) |
14329 |
-+ * '» struct kdbus_conn (pinned) |
14330 |
-+ * |
14331 |
-+ * For the life-time of a file descriptor derived from calling open() on a file |
14332 |
-+ * inside the mount point: |
14333 |
-+ * |
14334 |
-+ * struct kdbus_handle |
14335 |
-+ * |» struct kdbus_meta *meta (owned) |
14336 |
-+ * |» struct kdbus_ep *ep (pinned) |
14337 |
-+ * |» struct kdbus_conn *conn (owned) |
14338 |
-+ * '» struct kdbus_ep *ep (owned) |
14339 |
-+ */ |
14340 |
-+ |
14341 |
-+/* kdbus mount-point /sys/fs/kdbus */ |
14342 |
-+static struct kobject *kdbus_dir; |
14343 |
-+ |
14344 |
-+static int __init kdbus_init(void) |
14345 |
-+{ |
14346 |
-+ int ret; |
14347 |
-+ |
14348 |
-+ kdbus_dir = kobject_create_and_add(KBUILD_MODNAME, fs_kobj); |
14349 |
-+ if (!kdbus_dir) |
14350 |
-+ return -ENOMEM; |
14351 |
-+ |
14352 |
-+ ret = kdbus_fs_init(); |
14353 |
-+ if (ret < 0) { |
14354 |
-+ pr_err("cannot register filesystem: %d\n", ret); |
14355 |
-+ goto exit_dir; |
14356 |
-+ } |
14357 |
-+ |
14358 |
-+ pr_info("initialized\n"); |
14359 |
-+ return 0; |
14360 |
-+ |
14361 |
-+exit_dir: |
14362 |
-+ kobject_put(kdbus_dir); |
14363 |
-+ return ret; |
14364 |
-+} |
14365 |
-+ |
14366 |
-+static void __exit kdbus_exit(void) |
14367 |
-+{ |
14368 |
-+ kdbus_fs_exit(); |
14369 |
-+ kobject_put(kdbus_dir); |
14370 |
-+ ida_destroy(&kdbus_node_ida); |
14371 |
-+} |
14372 |
-+ |
14373 |
-+module_init(kdbus_init); |
14374 |
-+module_exit(kdbus_exit); |
14375 |
-+MODULE_LICENSE("GPL"); |
14376 |
-+MODULE_DESCRIPTION("D-Bus, powerful, easy to use interprocess communication"); |
14377 |
-+MODULE_ALIAS_FS(KBUILD_MODNAME "fs"); |
14378 |
-diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c |
14379 |
-new file mode 100644 |
14380 |
-index 0000000..4ee6a1f |
14381 |
---- /dev/null |
14382 |
-+++ b/ipc/kdbus/match.c |
14383 |
-@@ -0,0 +1,546 @@ |
14384 |
-+/* |
14385 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14386 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14387 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14388 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14389 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14390 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14391 |
-+ * |
14392 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14393 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14394 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14395 |
-+ * your option) any later version. |
14396 |
-+ */ |
14397 |
-+ |
14398 |
-+#include <linux/fs.h> |
14399 |
-+#include <linux/hash.h> |
14400 |
-+#include <linux/init.h> |
14401 |
-+#include <linux/mutex.h> |
14402 |
-+#include <linux/sched.h> |
14403 |
-+#include <linux/sizes.h> |
14404 |
-+#include <linux/slab.h> |
14405 |
-+#include <linux/uaccess.h> |
14406 |
-+ |
14407 |
-+#include "bus.h" |
14408 |
-+#include "connection.h" |
14409 |
-+#include "endpoint.h" |
14410 |
-+#include "handle.h" |
14411 |
-+#include "item.h" |
14412 |
-+#include "match.h" |
14413 |
-+#include "message.h" |
14414 |
-+#include "names.h" |
14415 |
-+ |
14416 |
-+/** |
14417 |
-+ * struct kdbus_match_db - message filters |
14418 |
-+ * @entries_list: List of matches |
14419 |
-+ * @mdb_rwlock: Match data lock |
14420 |
-+ * @entries_count: Number of entries in database |
14421 |
-+ */ |
14422 |
-+struct kdbus_match_db { |
14423 |
-+ struct list_head entries_list; |
14424 |
-+ struct rw_semaphore mdb_rwlock; |
14425 |
-+ unsigned int entries_count; |
14426 |
-+}; |
14427 |
-+ |
14428 |
-+/** |
14429 |
-+ * struct kdbus_match_entry - a match database entry |
14430 |
-+ * @cookie: User-supplied cookie to lookup the entry |
14431 |
-+ * @list_entry: The list entry element for the db list |
14432 |
-+ * @rules_list: The list head for tracking rules of this entry |
14433 |
-+ */ |
14434 |
-+struct kdbus_match_entry { |
14435 |
-+ u64 cookie; |
14436 |
-+ struct list_head list_entry; |
14437 |
-+ struct list_head rules_list; |
14438 |
-+}; |
14439 |
-+ |
14440 |
-+/** |
14441 |
-+ * struct kdbus_bloom_mask - mask to match against filter |
14442 |
-+ * @generations: Number of generations carried |
14443 |
-+ * @data: Array of bloom bit fields |
14444 |
-+ */ |
14445 |
-+struct kdbus_bloom_mask { |
14446 |
-+ u64 generations; |
14447 |
-+ u64 *data; |
14448 |
-+}; |
14449 |
-+ |
14450 |
-+/** |
14451 |
-+ * struct kdbus_match_rule - a rule appended to a match entry |
14452 |
-+ * @type: An item type to match against |
14453 |
-+ * @bloom_mask: Bloom mask to match a message's filter against, used |
14454 |
-+ * with KDBUS_ITEM_BLOOM_MASK |
14455 |
-+ * @name: Name to match against, used with KDBUS_ITEM_NAME, |
14456 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} |
14457 |
-+ * @old_id: ID to match against, used with |
14458 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}, |
14459 |
-+ * KDBUS_ITEM_ID_REMOVE |
14460 |
-+ * @new_id: ID to match against, used with |
14461 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}, |
14462 |
-+ * KDBUS_ITEM_ID_REMOVE |
14463 |
-+ * @src_id: ID to match against, used with KDBUS_ITEM_ID |
14464 |
-+ * @dst_id: Message destination ID, used with KDBUS_ITEM_DST_ID |
14465 |
-+ * @rules_entry: Entry in the entry's rules list |
14466 |
-+ */ |
14467 |
-+struct kdbus_match_rule { |
14468 |
-+ u64 type; |
14469 |
-+ union { |
14470 |
-+ struct kdbus_bloom_mask bloom_mask; |
14471 |
-+ struct { |
14472 |
-+ char *name; |
14473 |
-+ u64 old_id; |
14474 |
-+ u64 new_id; |
14475 |
-+ }; |
14476 |
-+ u64 src_id; |
14477 |
-+ u64 dst_id; |
14478 |
-+ }; |
14479 |
-+ struct list_head rules_entry; |
14480 |
-+}; |
14481 |
-+ |
14482 |
-+static void kdbus_match_rule_free(struct kdbus_match_rule *rule) |
14483 |
-+{ |
14484 |
-+ if (!rule) |
14485 |
-+ return; |
14486 |
-+ |
14487 |
-+ switch (rule->type) { |
14488 |
-+ case KDBUS_ITEM_BLOOM_MASK: |
14489 |
-+ kfree(rule->bloom_mask.data); |
14490 |
-+ break; |
14491 |
-+ |
14492 |
-+ case KDBUS_ITEM_NAME: |
14493 |
-+ case KDBUS_ITEM_NAME_ADD: |
14494 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14495 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14496 |
-+ kfree(rule->name); |
14497 |
-+ break; |
14498 |
-+ |
14499 |
-+ case KDBUS_ITEM_ID: |
14500 |
-+ case KDBUS_ITEM_DST_ID: |
14501 |
-+ case KDBUS_ITEM_ID_ADD: |
14502 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14503 |
-+ break; |
14504 |
-+ |
14505 |
-+ default: |
14506 |
-+ BUG(); |
14507 |
-+ } |
14508 |
-+ |
14509 |
-+ list_del(&rule->rules_entry); |
14510 |
-+ kfree(rule); |
14511 |
-+} |
14512 |
-+ |
14513 |
-+static void kdbus_match_entry_free(struct kdbus_match_entry *entry) |
14514 |
-+{ |
14515 |
-+ struct kdbus_match_rule *r, *tmp; |
14516 |
-+ |
14517 |
-+ if (!entry) |
14518 |
-+ return; |
14519 |
-+ |
14520 |
-+ list_for_each_entry_safe(r, tmp, &entry->rules_list, rules_entry) |
14521 |
-+ kdbus_match_rule_free(r); |
14522 |
-+ |
14523 |
-+ list_del(&entry->list_entry); |
14524 |
-+ kfree(entry); |
14525 |
-+} |
14526 |
-+ |
14527 |
-+/** |
14528 |
-+ * kdbus_match_db_free() - free match db resources |
14529 |
-+ * @mdb: The match database |
14530 |
-+ */ |
14531 |
-+void kdbus_match_db_free(struct kdbus_match_db *mdb) |
14532 |
-+{ |
14533 |
-+ struct kdbus_match_entry *entry, *tmp; |
14534 |
-+ |
14535 |
-+ if (!mdb) |
14536 |
-+ return; |
14537 |
-+ |
14538 |
-+ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry) |
14539 |
-+ kdbus_match_entry_free(entry); |
14540 |
-+ |
14541 |
-+ kfree(mdb); |
14542 |
-+} |
14543 |
-+ |
14544 |
-+/** |
14545 |
-+ * kdbus_match_db_new() - create a new match database |
14546 |
-+ * |
14547 |
-+ * Return: a new kdbus_match_db on success, ERR_PTR on failure. |
14548 |
-+ */ |
14549 |
-+struct kdbus_match_db *kdbus_match_db_new(void) |
14550 |
-+{ |
14551 |
-+ struct kdbus_match_db *d; |
14552 |
-+ |
14553 |
-+ d = kzalloc(sizeof(*d), GFP_KERNEL); |
14554 |
-+ if (!d) |
14555 |
-+ return ERR_PTR(-ENOMEM); |
14556 |
-+ |
14557 |
-+ init_rwsem(&d->mdb_rwlock); |
14558 |
-+ INIT_LIST_HEAD(&d->entries_list); |
14559 |
-+ |
14560 |
-+ return d; |
14561 |
-+} |
14562 |
-+ |
14563 |
-+static bool kdbus_match_bloom(const struct kdbus_bloom_filter *filter, |
14564 |
-+ const struct kdbus_bloom_mask *mask, |
14565 |
-+ const struct kdbus_conn *conn) |
14566 |
-+{ |
14567 |
-+ size_t n = conn->ep->bus->bloom.size / sizeof(u64); |
14568 |
-+ const u64 *m; |
14569 |
-+ size_t i; |
14570 |
-+ |
14571 |
-+ /* |
14572 |
-+ * The message's filter carries a generation identifier, the |
14573 |
-+ * match's mask possibly carries an array of multiple generations |
14574 |
-+ * of the mask. Select the mask with the closest match of the |
14575 |
-+ * filter's generation. |
14576 |
-+ */ |
14577 |
-+ m = mask->data + (min(filter->generation, mask->generations - 1) * n); |
14578 |
-+ |
14579 |
-+ /* |
14580 |
-+ * The message's filter contains the messages properties, |
14581 |
-+ * the match's mask contains the properties to look for in the |
14582 |
-+ * message. Check the mask bit field against the filter bit field, |
14583 |
-+ * if the message possibly carries the properties the connection |
14584 |
-+ * has subscribed to. |
14585 |
-+ */ |
14586 |
-+ for (i = 0; i < n; i++) |
14587 |
-+ if ((filter->data[i] & m[i]) != m[i]) |
14588 |
-+ return false; |
14589 |
-+ |
14590 |
-+ return true; |
14591 |
-+} |
14592 |
-+ |
14593 |
-+static bool kdbus_match_rule_conn(const struct kdbus_match_rule *r, |
14594 |
-+ struct kdbus_conn *c, |
14595 |
-+ const struct kdbus_staging *s) |
14596 |
-+{ |
14597 |
-+ lockdep_assert_held(&c->ep->bus->name_registry->rwlock); |
14598 |
-+ |
14599 |
-+ switch (r->type) { |
14600 |
-+ case KDBUS_ITEM_BLOOM_MASK: |
14601 |
-+ return kdbus_match_bloom(s->bloom_filter, &r->bloom_mask, c); |
14602 |
-+ case KDBUS_ITEM_ID: |
14603 |
-+ return r->src_id == c->id || r->src_id == KDBUS_MATCH_ID_ANY; |
14604 |
-+ case KDBUS_ITEM_DST_ID: |
14605 |
-+ return r->dst_id == s->msg->dst_id || |
14606 |
-+ r->dst_id == KDBUS_MATCH_ID_ANY; |
14607 |
-+ case KDBUS_ITEM_NAME: |
14608 |
-+ return kdbus_conn_has_name(c, r->name); |
14609 |
-+ default: |
14610 |
-+ return false; |
14611 |
-+ } |
14612 |
-+} |
14613 |
-+ |
14614 |
-+static bool kdbus_match_rule_kernel(const struct kdbus_match_rule *r, |
14615 |
-+ const struct kdbus_staging *s) |
14616 |
-+{ |
14617 |
-+ struct kdbus_item *n = s->notify; |
14618 |
-+ |
14619 |
-+ if (WARN_ON(!n) || n->type != r->type) |
14620 |
-+ return false; |
14621 |
-+ |
14622 |
-+ switch (r->type) { |
14623 |
-+ case KDBUS_ITEM_ID_ADD: |
14624 |
-+ return r->new_id == KDBUS_MATCH_ID_ANY || |
14625 |
-+ r->new_id == n->id_change.id; |
14626 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14627 |
-+ return r->old_id == KDBUS_MATCH_ID_ANY || |
14628 |
-+ r->old_id == n->id_change.id; |
14629 |
-+ case KDBUS_ITEM_NAME_ADD: |
14630 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14631 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14632 |
-+ return (r->old_id == KDBUS_MATCH_ID_ANY || |
14633 |
-+ r->old_id == n->name_change.old_id.id) && |
14634 |
-+ (r->new_id == KDBUS_MATCH_ID_ANY || |
14635 |
-+ r->new_id == n->name_change.new_id.id) && |
14636 |
-+ (!r->name || !strcmp(r->name, n->name_change.name)); |
14637 |
-+ default: |
14638 |
-+ return false; |
14639 |
-+ } |
14640 |
-+} |
14641 |
-+ |
14642 |
-+static bool kdbus_match_rules(const struct kdbus_match_entry *entry, |
14643 |
-+ struct kdbus_conn *c, |
14644 |
-+ const struct kdbus_staging *s) |
14645 |
-+{ |
14646 |
-+ struct kdbus_match_rule *r; |
14647 |
-+ |
14648 |
-+ list_for_each_entry(r, &entry->rules_list, rules_entry) |
14649 |
-+ if ((c && !kdbus_match_rule_conn(r, c, s)) || |
14650 |
-+ (!c && !kdbus_match_rule_kernel(r, s))) |
14651 |
-+ return false; |
14652 |
-+ |
14653 |
-+ return true; |
14654 |
-+} |
14655 |
-+ |
14656 |
-+/** |
14657 |
-+ * kdbus_match_db_match_msg() - match a msg object agains the database entries |
14658 |
-+ * @mdb: The match database |
14659 |
-+ * @conn_src: The connection object originating the message |
14660 |
-+ * @staging: Staging object containing the message to match against |
14661 |
-+ * |
14662 |
-+ * This function will walk through all the database entries previously uploaded |
14663 |
-+ * with kdbus_match_db_add(). As soon as any of them has an all-satisfied rule |
14664 |
-+ * set, this function will return true. |
14665 |
-+ * |
14666 |
-+ * The caller must hold the registry lock of conn_src->ep->bus, in case conn_src |
14667 |
-+ * is non-NULL. |
14668 |
-+ * |
14669 |
-+ * Return: true if there was a matching database entry, false otherwise. |
14670 |
-+ */ |
14671 |
-+bool kdbus_match_db_match_msg(struct kdbus_match_db *mdb, |
14672 |
-+ struct kdbus_conn *conn_src, |
14673 |
-+ const struct kdbus_staging *staging) |
14674 |
-+{ |
14675 |
-+ struct kdbus_match_entry *entry; |
14676 |
-+ bool matched = false; |
14677 |
-+ |
14678 |
-+ down_read(&mdb->mdb_rwlock); |
14679 |
-+ list_for_each_entry(entry, &mdb->entries_list, list_entry) { |
14680 |
-+ matched = kdbus_match_rules(entry, conn_src, staging); |
14681 |
-+ if (matched) |
14682 |
-+ break; |
14683 |
-+ } |
14684 |
-+ up_read(&mdb->mdb_rwlock); |
14685 |
-+ |
14686 |
-+ return matched; |
14687 |
-+} |
14688 |
-+ |
14689 |
-+static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb, |
14690 |
-+ u64 cookie) |
14691 |
-+{ |
14692 |
-+ struct kdbus_match_entry *entry, *tmp; |
14693 |
-+ bool found = false; |
14694 |
-+ |
14695 |
-+ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry) |
14696 |
-+ if (entry->cookie == cookie) { |
14697 |
-+ kdbus_match_entry_free(entry); |
14698 |
-+ --mdb->entries_count; |
14699 |
-+ found = true; |
14700 |
-+ } |
14701 |
-+ |
14702 |
-+ return found ? 0 : -EBADSLT; |
14703 |
-+} |
14704 |
-+ |
14705 |
-+/** |
14706 |
-+ * kdbus_cmd_match_add() - handle KDBUS_CMD_MATCH_ADD |
14707 |
-+ * @conn: connection to operate on |
14708 |
-+ * @argp: command payload |
14709 |
-+ * |
14710 |
-+ * One call to this function (or one ioctl(KDBUS_CMD_MATCH_ADD), respectively, |
14711 |
-+ * adds one new database entry with n rules attached to it. Each rule is |
14712 |
-+ * described with an kdbus_item, and an entry is considered matching if all |
14713 |
-+ * its rules are satisfied. |
14714 |
-+ * |
14715 |
-+ * The items attached to a kdbus_cmd_match struct have the following mapping: |
14716 |
-+ * |
14717 |
-+ * KDBUS_ITEM_BLOOM_MASK: A bloom mask |
14718 |
-+ * KDBUS_ITEM_NAME: A connection's source name |
14719 |
-+ * KDBUS_ITEM_ID: A connection ID |
14720 |
-+ * KDBUS_ITEM_DST_ID: A connection ID |
14721 |
-+ * KDBUS_ITEM_NAME_ADD: |
14722 |
-+ * KDBUS_ITEM_NAME_REMOVE: |
14723 |
-+ * KDBUS_ITEM_NAME_CHANGE: Well-known name changes, carry |
14724 |
-+ * kdbus_notify_name_change |
14725 |
-+ * KDBUS_ITEM_ID_ADD: |
14726 |
-+ * KDBUS_ITEM_ID_REMOVE: Connection ID changes, carry |
14727 |
-+ * kdbus_notify_id_change |
14728 |
-+ * |
14729 |
-+ * For kdbus_notify_{id,name}_change structs, only the ID and name fields |
14730 |
-+ * are looked at when adding an entry. The flags are unused. |
14731 |
-+ * |
14732 |
-+ * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME, KDBUS_ITEM_ID, |
14733 |
-+ * and KDBUS_ITEM_DST_ID are used to match messages from userspace, while the |
14734 |
-+ * others apply to kernel-generated notifications. |
14735 |
-+ * |
14736 |
-+ * Return: >=0 on success, negative error code on failure. |
14737 |
-+ */ |
14738 |
-+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp) |
14739 |
-+{ |
14740 |
-+ struct kdbus_match_db *mdb = conn->match_db; |
14741 |
-+ struct kdbus_match_entry *entry = NULL; |
14742 |
-+ struct kdbus_cmd_match *cmd; |
14743 |
-+ struct kdbus_item *item; |
14744 |
-+ int ret; |
14745 |
-+ |
14746 |
-+ struct kdbus_arg argv[] = { |
14747 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
14748 |
-+ { .type = KDBUS_ITEM_BLOOM_MASK, .multiple = true }, |
14749 |
-+ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
14750 |
-+ { .type = KDBUS_ITEM_ID, .multiple = true }, |
14751 |
-+ { .type = KDBUS_ITEM_DST_ID, .multiple = true }, |
14752 |
-+ { .type = KDBUS_ITEM_NAME_ADD, .multiple = true }, |
14753 |
-+ { .type = KDBUS_ITEM_NAME_REMOVE, .multiple = true }, |
14754 |
-+ { .type = KDBUS_ITEM_NAME_CHANGE, .multiple = true }, |
14755 |
-+ { .type = KDBUS_ITEM_ID_ADD, .multiple = true }, |
14756 |
-+ { .type = KDBUS_ITEM_ID_REMOVE, .multiple = true }, |
14757 |
-+ }; |
14758 |
-+ struct kdbus_args args = { |
14759 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
14760 |
-+ KDBUS_MATCH_REPLACE, |
14761 |
-+ .argv = argv, |
14762 |
-+ .argc = ARRAY_SIZE(argv), |
14763 |
-+ }; |
14764 |
-+ |
14765 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
14766 |
-+ return -EOPNOTSUPP; |
14767 |
-+ |
14768 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
14769 |
-+ if (ret != 0) |
14770 |
-+ return ret; |
14771 |
-+ |
14772 |
-+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
14773 |
-+ if (!entry) { |
14774 |
-+ ret = -ENOMEM; |
14775 |
-+ goto exit; |
14776 |
-+ } |
14777 |
-+ |
14778 |
-+ entry->cookie = cmd->cookie; |
14779 |
-+ INIT_LIST_HEAD(&entry->list_entry); |
14780 |
-+ INIT_LIST_HEAD(&entry->rules_list); |
14781 |
-+ |
14782 |
-+ KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) { |
14783 |
-+ struct kdbus_match_rule *rule; |
14784 |
-+ size_t size = item->size - offsetof(struct kdbus_item, data); |
14785 |
-+ |
14786 |
-+ rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
14787 |
-+ if (!rule) { |
14788 |
-+ ret = -ENOMEM; |
14789 |
-+ goto exit; |
14790 |
-+ } |
14791 |
-+ |
14792 |
-+ rule->type = item->type; |
14793 |
-+ INIT_LIST_HEAD(&rule->rules_entry); |
14794 |
-+ |
14795 |
-+ switch (item->type) { |
14796 |
-+ case KDBUS_ITEM_BLOOM_MASK: { |
14797 |
-+ u64 bsize = conn->ep->bus->bloom.size; |
14798 |
-+ u64 generations; |
14799 |
-+ u64 remainder; |
14800 |
-+ |
14801 |
-+ generations = div64_u64_rem(size, bsize, &remainder); |
14802 |
-+ if (size < bsize || remainder > 0) { |
14803 |
-+ ret = -EDOM; |
14804 |
-+ break; |
14805 |
-+ } |
14806 |
-+ |
14807 |
-+ rule->bloom_mask.data = kmemdup(item->data, |
14808 |
-+ size, GFP_KERNEL); |
14809 |
-+ if (!rule->bloom_mask.data) { |
14810 |
-+ ret = -ENOMEM; |
14811 |
-+ break; |
14812 |
-+ } |
14813 |
-+ |
14814 |
-+ rule->bloom_mask.generations = generations; |
14815 |
-+ break; |
14816 |
-+ } |
14817 |
-+ |
14818 |
-+ case KDBUS_ITEM_NAME: |
14819 |
-+ if (!kdbus_name_is_valid(item->str, false)) { |
14820 |
-+ ret = -EINVAL; |
14821 |
-+ break; |
14822 |
-+ } |
14823 |
-+ |
14824 |
-+ rule->name = kstrdup(item->str, GFP_KERNEL); |
14825 |
-+ if (!rule->name) |
14826 |
-+ ret = -ENOMEM; |
14827 |
-+ |
14828 |
-+ break; |
14829 |
-+ |
14830 |
-+ case KDBUS_ITEM_ID: |
14831 |
-+ rule->src_id = item->id; |
14832 |
-+ break; |
14833 |
-+ |
14834 |
-+ case KDBUS_ITEM_DST_ID: |
14835 |
-+ rule->dst_id = item->id; |
14836 |
-+ break; |
14837 |
-+ |
14838 |
-+ case KDBUS_ITEM_NAME_ADD: |
14839 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14840 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14841 |
-+ rule->old_id = item->name_change.old_id.id; |
14842 |
-+ rule->new_id = item->name_change.new_id.id; |
14843 |
-+ |
14844 |
-+ if (size > sizeof(struct kdbus_notify_name_change)) { |
14845 |
-+ rule->name = kstrdup(item->name_change.name, |
14846 |
-+ GFP_KERNEL); |
14847 |
-+ if (!rule->name) |
14848 |
-+ ret = -ENOMEM; |
14849 |
-+ } |
14850 |
-+ |
14851 |
-+ break; |
14852 |
-+ |
14853 |
-+ case KDBUS_ITEM_ID_ADD: |
14854 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14855 |
-+ if (item->type == KDBUS_ITEM_ID_ADD) |
14856 |
-+ rule->new_id = item->id_change.id; |
14857 |
-+ else |
14858 |
-+ rule->old_id = item->id_change.id; |
14859 |
-+ |
14860 |
-+ break; |
14861 |
-+ } |
14862 |
-+ |
14863 |
-+ if (ret < 0) { |
14864 |
-+ kdbus_match_rule_free(rule); |
14865 |
-+ goto exit; |
14866 |
-+ } |
14867 |
-+ |
14868 |
-+ list_add_tail(&rule->rules_entry, &entry->rules_list); |
14869 |
-+ } |
14870 |
-+ |
14871 |
-+ down_write(&mdb->mdb_rwlock); |
14872 |
-+ |
14873 |
-+ /* Remove any entry that has the same cookie as the current one. */ |
14874 |
-+ if (cmd->flags & KDBUS_MATCH_REPLACE) |
14875 |
-+ kdbus_match_db_remove_unlocked(mdb, entry->cookie); |
14876 |
-+ |
14877 |
-+ /* |
14878 |
-+ * If the above removal caught any entry, there will be room for the |
14879 |
-+ * new one. |
14880 |
-+ */ |
14881 |
-+ if (++mdb->entries_count > KDBUS_MATCH_MAX) { |
14882 |
-+ --mdb->entries_count; |
14883 |
-+ ret = -EMFILE; |
14884 |
-+ } else { |
14885 |
-+ list_add_tail(&entry->list_entry, &mdb->entries_list); |
14886 |
-+ entry = NULL; |
14887 |
-+ } |
14888 |
-+ |
14889 |
-+ up_write(&mdb->mdb_rwlock); |
14890 |
-+ |
14891 |
-+exit: |
14892 |
-+ kdbus_match_entry_free(entry); |
14893 |
-+ return kdbus_args_clear(&args, ret); |
14894 |
-+} |
14895 |
-+ |
14896 |
-+/** |
14897 |
-+ * kdbus_cmd_match_remove() - handle KDBUS_CMD_MATCH_REMOVE |
14898 |
-+ * @conn: connection to operate on |
14899 |
-+ * @argp: command payload |
14900 |
-+ * |
14901 |
-+ * Return: >=0 on success, negative error code on failure. |
14902 |
-+ */ |
14903 |
-+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp) |
14904 |
-+{ |
14905 |
-+ struct kdbus_cmd_match *cmd; |
14906 |
-+ int ret; |
14907 |
-+ |
14908 |
-+ struct kdbus_arg argv[] = { |
14909 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
14910 |
-+ }; |
14911 |
-+ struct kdbus_args args = { |
14912 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
14913 |
-+ .argv = argv, |
14914 |
-+ .argc = ARRAY_SIZE(argv), |
14915 |
-+ }; |
14916 |
-+ |
14917 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
14918 |
-+ return -EOPNOTSUPP; |
14919 |
-+ |
14920 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
14921 |
-+ if (ret != 0) |
14922 |
-+ return ret; |
14923 |
-+ |
14924 |
-+ down_write(&conn->match_db->mdb_rwlock); |
14925 |
-+ ret = kdbus_match_db_remove_unlocked(conn->match_db, cmd->cookie); |
14926 |
-+ up_write(&conn->match_db->mdb_rwlock); |
14927 |
-+ |
14928 |
-+ return kdbus_args_clear(&args, ret); |
14929 |
-+} |
14930 |
-diff --git a/ipc/kdbus/match.h b/ipc/kdbus/match.h |
14931 |
-new file mode 100644 |
14932 |
-index 0000000..ceb492f |
14933 |
---- /dev/null |
14934 |
-+++ b/ipc/kdbus/match.h |
14935 |
-@@ -0,0 +1,35 @@ |
14936 |
-+/* |
14937 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14938 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14939 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14940 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14941 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14942 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14943 |
-+ * |
14944 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14945 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14946 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14947 |
-+ * your option) any later version. |
14948 |
-+ */ |
14949 |
-+ |
14950 |
-+#ifndef __KDBUS_MATCH_H |
14951 |
-+#define __KDBUS_MATCH_H |
14952 |
-+ |
14953 |
-+struct kdbus_conn; |
14954 |
-+struct kdbus_match_db; |
14955 |
-+struct kdbus_staging; |
14956 |
-+ |
14957 |
-+struct kdbus_match_db *kdbus_match_db_new(void); |
14958 |
-+void kdbus_match_db_free(struct kdbus_match_db *db); |
14959 |
-+int kdbus_match_db_add(struct kdbus_conn *conn, |
14960 |
-+ struct kdbus_cmd_match *cmd); |
14961 |
-+int kdbus_match_db_remove(struct kdbus_conn *conn, |
14962 |
-+ struct kdbus_cmd_match *cmd); |
14963 |
-+bool kdbus_match_db_match_msg(struct kdbus_match_db *db, |
14964 |
-+ struct kdbus_conn *conn_src, |
14965 |
-+ const struct kdbus_staging *staging); |
14966 |
-+ |
14967 |
-+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp); |
14968 |
-+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp); |
14969 |
-+ |
14970 |
-+#endif |
14971 |
-diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c |
14972 |
-new file mode 100644 |
14973 |
-index 0000000..ae565cd |
14974 |
---- /dev/null |
14975 |
-+++ b/ipc/kdbus/message.c |
14976 |
-@@ -0,0 +1,1040 @@ |
14977 |
-+/* |
14978 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14979 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14980 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14981 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14982 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14983 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14984 |
-+ * |
14985 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14986 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14987 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14988 |
-+ * your option) any later version. |
14989 |
-+ */ |
14990 |
-+ |
14991 |
-+#include <linux/capability.h> |
14992 |
-+#include <linux/cgroup.h> |
14993 |
-+#include <linux/cred.h> |
14994 |
-+#include <linux/file.h> |
14995 |
-+#include <linux/init.h> |
14996 |
-+#include <linux/module.h> |
14997 |
-+#include <linux/mutex.h> |
14998 |
-+#include <linux/sched.h> |
14999 |
-+#include <linux/shmem_fs.h> |
15000 |
-+#include <linux/sizes.h> |
15001 |
-+#include <linux/slab.h> |
15002 |
-+#include <linux/uaccess.h> |
15003 |
-+#include <net/sock.h> |
15004 |
-+ |
15005 |
-+#include "bus.h" |
15006 |
-+#include "connection.h" |
15007 |
-+#include "domain.h" |
15008 |
-+#include "endpoint.h" |
15009 |
-+#include "handle.h" |
15010 |
-+#include "item.h" |
15011 |
-+#include "match.h" |
15012 |
-+#include "message.h" |
15013 |
-+#include "names.h" |
15014 |
-+#include "policy.h" |
15015 |
-+ |
15016 |
-+static const char * const zeros = "\0\0\0\0\0\0\0"; |
15017 |
-+ |
15018 |
-+static struct kdbus_gaps *kdbus_gaps_new(size_t n_memfds, size_t n_fds) |
15019 |
-+{ |
15020 |
-+ size_t size_offsets, size_memfds, size_fds, size; |
15021 |
-+ struct kdbus_gaps *gaps; |
15022 |
-+ |
15023 |
-+ size_offsets = n_memfds * sizeof(*gaps->memfd_offsets); |
15024 |
-+ size_memfds = n_memfds * sizeof(*gaps->memfd_files); |
15025 |
-+ size_fds = n_fds * sizeof(*gaps->fd_files); |
15026 |
-+ size = sizeof(*gaps) + size_offsets + size_memfds + size_fds; |
15027 |
-+ |
15028 |
-+ gaps = kzalloc(size, GFP_KERNEL); |
15029 |
-+ if (!gaps) |
15030 |
-+ return ERR_PTR(-ENOMEM); |
15031 |
-+ |
15032 |
-+ kref_init(&gaps->kref); |
15033 |
-+ gaps->n_memfds = 0; /* we reserve n_memfds, but don't enforce them */ |
15034 |
-+ gaps->memfd_offsets = (void *)(gaps + 1); |
15035 |
-+ gaps->memfd_files = (void *)((u8 *)gaps->memfd_offsets + size_offsets); |
15036 |
-+ gaps->n_fds = 0; /* we reserve n_fds, but don't enforce them */ |
15037 |
-+ gaps->fd_files = (void *)((u8 *)gaps->memfd_files + size_memfds); |
15038 |
-+ |
15039 |
-+ return gaps; |
15040 |
-+} |
15041 |
-+ |
15042 |
-+static void kdbus_gaps_free(struct kref *kref) |
15043 |
-+{ |
15044 |
-+ struct kdbus_gaps *gaps = container_of(kref, struct kdbus_gaps, kref); |
15045 |
-+ size_t i; |
15046 |
-+ |
15047 |
-+ for (i = 0; i < gaps->n_fds; ++i) |
15048 |
-+ if (gaps->fd_files[i]) |
15049 |
-+ fput(gaps->fd_files[i]); |
15050 |
-+ for (i = 0; i < gaps->n_memfds; ++i) |
15051 |
-+ if (gaps->memfd_files[i]) |
15052 |
-+ fput(gaps->memfd_files[i]); |
15053 |
-+ |
15054 |
-+ kfree(gaps); |
15055 |
-+} |
15056 |
-+ |
15057 |
-+/** |
15058 |
-+ * kdbus_gaps_ref() - gain reference |
15059 |
-+ * @gaps: gaps object |
15060 |
-+ * |
15061 |
-+ * Return: @gaps is returned |
15062 |
-+ */ |
15063 |
-+struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps) |
15064 |
-+{ |
15065 |
-+ if (gaps) |
15066 |
-+ kref_get(&gaps->kref); |
15067 |
-+ return gaps; |
15068 |
-+} |
15069 |
-+ |
15070 |
-+/** |
15071 |
-+ * kdbus_gaps_unref() - drop reference |
15072 |
-+ * @gaps: gaps object |
15073 |
-+ * |
15074 |
-+ * Return: NULL |
15075 |
-+ */ |
15076 |
-+struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps) |
15077 |
-+{ |
15078 |
-+ if (gaps) |
15079 |
-+ kref_put(&gaps->kref, kdbus_gaps_free); |
15080 |
-+ return NULL; |
15081 |
-+} |
15082 |
-+ |
15083 |
-+/** |
15084 |
-+ * kdbus_gaps_install() - install file-descriptors |
15085 |
-+ * @gaps: gaps object, or NULL |
15086 |
-+ * @slice: pool slice that contains the message |
15087 |
-+ * @out_incomplete output variable to note incomplete fds |
15088 |
-+ * |
15089 |
-+ * This function installs all file-descriptors of @gaps into the current |
15090 |
-+ * process and copies the file-descriptor numbers into the target pool slice. |
15091 |
-+ * |
15092 |
-+ * If the file-descriptors were only partially installed, then @out_incomplete |
15093 |
-+ * will be set to true. Otherwise, it's set to false. |
15094 |
-+ * |
15095 |
-+ * Return: 0 on success, negative error code on failure |
15096 |
-+ */ |
15097 |
-+int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice, |
15098 |
-+ bool *out_incomplete) |
15099 |
-+{ |
15100 |
-+ bool incomplete_fds = false; |
15101 |
-+ struct kvec kvec; |
15102 |
-+ size_t i, n_fds; |
15103 |
-+ int ret, *fds; |
15104 |
-+ |
15105 |
-+ if (!gaps) { |
15106 |
-+ /* nothing to do */ |
15107 |
-+ *out_incomplete = incomplete_fds; |
15108 |
-+ return 0; |
15109 |
-+ } |
15110 |
-+ |
15111 |
-+ n_fds = gaps->n_fds + gaps->n_memfds; |
15112 |
-+ if (n_fds < 1) { |
15113 |
-+ /* nothing to do */ |
15114 |
-+ *out_incomplete = incomplete_fds; |
15115 |
-+ return 0; |
15116 |
-+ } |
15117 |
-+ |
15118 |
-+ fds = kmalloc_array(n_fds, sizeof(*fds), GFP_TEMPORARY); |
15119 |
-+ n_fds = 0; |
15120 |
-+ if (!fds) |
15121 |
-+ return -ENOMEM; |
15122 |
-+ |
15123 |
-+ /* 1) allocate fds and copy them over */ |
15124 |
-+ |
15125 |
-+ if (gaps->n_fds > 0) { |
15126 |
-+ for (i = 0; i < gaps->n_fds; ++i) { |
15127 |
-+ int fd; |
15128 |
-+ |
15129 |
-+ fd = get_unused_fd_flags(O_CLOEXEC); |
15130 |
-+ if (fd < 0) |
15131 |
-+ incomplete_fds = true; |
15132 |
-+ |
15133 |
-+ WARN_ON(!gaps->fd_files[i]); |
15134 |
-+ |
15135 |
-+ fds[n_fds++] = fd < 0 ? -1 : fd; |
15136 |
-+ } |
15137 |
-+ |
15138 |
-+ /* |
15139 |
-+ * The file-descriptor array can only be present once per |
15140 |
-+ * message. Hence, prepare all fds and then copy them over with |
15141 |
-+ * a single kvec. |
15142 |
-+ */ |
15143 |
-+ |
15144 |
-+ WARN_ON(!gaps->fd_offset); |
15145 |
-+ |
15146 |
-+ kvec.iov_base = fds; |
15147 |
-+ kvec.iov_len = gaps->n_fds * sizeof(*fds); |
15148 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, gaps->fd_offset, |
15149 |
-+ &kvec, 1, kvec.iov_len); |
15150 |
-+ if (ret < 0) |
15151 |
-+ goto exit; |
15152 |
-+ } |
15153 |
-+ |
15154 |
-+ for (i = 0; i < gaps->n_memfds; ++i) { |
15155 |
-+ int memfd; |
15156 |
-+ |
15157 |
-+ memfd = get_unused_fd_flags(O_CLOEXEC); |
15158 |
-+ if (memfd < 0) { |
15159 |
-+ incomplete_fds = true; |
15160 |
-+ /* memfds are initialized to -1, skip copying it */ |
15161 |
-+ continue; |
15162 |
-+ } |
15163 |
-+ |
15164 |
-+ fds[n_fds++] = memfd; |
15165 |
-+ |
15166 |
-+ /* |
15167 |
-+ * memfds have to be copied individually as they each are put |
15168 |
-+ * into a separate item. This should not be an issue, though, |
15169 |
-+ * as usually there is no need to send more than one memfd per |
15170 |
-+ * message. |
15171 |
-+ */ |
15172 |
-+ |
15173 |
-+ WARN_ON(!gaps->memfd_offsets[i]); |
15174 |
-+ WARN_ON(!gaps->memfd_files[i]); |
15175 |
-+ |
15176 |
-+ kvec.iov_base = &memfd; |
15177 |
-+ kvec.iov_len = sizeof(memfd); |
15178 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, gaps->memfd_offsets[i], |
15179 |
-+ &kvec, 1, kvec.iov_len); |
15180 |
-+ if (ret < 0) |
15181 |
-+ goto exit; |
15182 |
-+ } |
15183 |
-+ |
15184 |
-+ /* 2) install fds now that everything was successful */ |
15185 |
-+ |
15186 |
-+ for (i = 0; i < gaps->n_fds; ++i) |
15187 |
-+ if (fds[i] >= 0) |
15188 |
-+ fd_install(fds[i], get_file(gaps->fd_files[i])); |
15189 |
-+ for (i = 0; i < gaps->n_memfds; ++i) |
15190 |
-+ if (fds[gaps->n_fds + i] >= 0) |
15191 |
-+ fd_install(fds[gaps->n_fds + i], |
15192 |
-+ get_file(gaps->memfd_files[i])); |
15193 |
-+ |
15194 |
-+ ret = 0; |
15195 |
-+ |
15196 |
-+exit: |
15197 |
-+ if (ret < 0) |
15198 |
-+ for (i = 0; i < n_fds; ++i) |
15199 |
-+ put_unused_fd(fds[i]); |
15200 |
-+ kfree(fds); |
15201 |
-+ *out_incomplete = incomplete_fds; |
15202 |
-+ return ret; |
15203 |
-+} |
15204 |
-+ |
15205 |
-+static struct file *kdbus_get_fd(int fd) |
15206 |
-+{ |
15207 |
-+ struct file *f, *ret; |
15208 |
-+ struct inode *inode; |
15209 |
-+ struct socket *sock; |
15210 |
-+ |
15211 |
-+ if (fd < 0) |
15212 |
-+ return ERR_PTR(-EBADF); |
15213 |
-+ |
15214 |
-+ f = fget_raw(fd); |
15215 |
-+ if (!f) |
15216 |
-+ return ERR_PTR(-EBADF); |
15217 |
-+ |
15218 |
-+ inode = file_inode(f); |
15219 |
-+ sock = S_ISSOCK(inode->i_mode) ? SOCKET_I(inode) : NULL; |
15220 |
-+ |
15221 |
-+ if (f->f_mode & FMODE_PATH) |
15222 |
-+ ret = f; /* O_PATH is always allowed */ |
15223 |
-+ else if (f->f_op == &kdbus_handle_ops) |
15224 |
-+ ret = ERR_PTR(-EOPNOTSUPP); /* disallow kdbus-fd over kdbus */ |
15225 |
-+ else if (sock && sock->sk && sock->ops && sock->ops->family == PF_UNIX) |
15226 |
-+ ret = ERR_PTR(-EOPNOTSUPP); /* disallow UDS over kdbus */ |
15227 |
-+ else |
15228 |
-+ ret = f; /* all other are allowed */ |
15229 |
-+ |
15230 |
-+ if (f != ret) |
15231 |
-+ fput(f); |
15232 |
-+ |
15233 |
-+ return ret; |
15234 |
-+} |
15235 |
-+ |
15236 |
-+static struct file *kdbus_get_memfd(const struct kdbus_memfd *memfd) |
15237 |
-+{ |
15238 |
-+ const int m = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL; |
15239 |
-+ struct file *f, *ret; |
15240 |
-+ int s; |
15241 |
-+ |
15242 |
-+ if (memfd->fd < 0) |
15243 |
-+ return ERR_PTR(-EBADF); |
15244 |
-+ |
15245 |
-+ f = fget(memfd->fd); |
15246 |
-+ if (!f) |
15247 |
-+ return ERR_PTR(-EBADF); |
15248 |
-+ |
15249 |
-+ s = shmem_get_seals(f); |
15250 |
-+ if (s < 0) |
15251 |
-+ ret = ERR_PTR(-EMEDIUMTYPE); |
15252 |
-+ else if ((s & m) != m) |
15253 |
-+ ret = ERR_PTR(-ETXTBSY); |
15254 |
-+ else if (memfd->start + memfd->size > (u64)i_size_read(file_inode(f))) |
15255 |
-+ ret = ERR_PTR(-EFAULT); |
15256 |
-+ else |
15257 |
-+ ret = f; |
15258 |
-+ |
15259 |
-+ if (f != ret) |
15260 |
-+ fput(f); |
15261 |
-+ |
15262 |
-+ return ret; |
15263 |
-+} |
15264 |
-+ |
15265 |
-+static int kdbus_msg_examine(struct kdbus_msg *msg, struct kdbus_bus *bus, |
15266 |
-+ struct kdbus_cmd_send *cmd, size_t *out_n_memfds, |
15267 |
-+ size_t *out_n_fds, size_t *out_n_parts) |
15268 |
-+{ |
15269 |
-+ struct kdbus_item *item, *fds = NULL, *bloom = NULL, *dstname = NULL; |
15270 |
-+ u64 n_parts, n_memfds, n_fds, vec_size; |
15271 |
-+ |
15272 |
-+ /* |
15273 |
-+ * Step 1: |
15274 |
-+ * Validate the message and command parameters. |
15275 |
-+ */ |
15276 |
-+ |
15277 |
-+ /* KDBUS_PAYLOAD_KERNEL is reserved to kernel messages */ |
15278 |
-+ if (msg->payload_type == KDBUS_PAYLOAD_KERNEL) |
15279 |
-+ return -EINVAL; |
15280 |
-+ |
15281 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST) { |
15282 |
-+ /* broadcasts must be marked as signals */ |
15283 |
-+ if (!(msg->flags & KDBUS_MSG_SIGNAL)) |
15284 |
-+ return -EBADMSG; |
15285 |
-+ /* broadcasts cannot have timeouts */ |
15286 |
-+ if (msg->timeout_ns > 0) |
15287 |
-+ return -ENOTUNIQ; |
15288 |
-+ } |
15289 |
-+ |
15290 |
-+ if (msg->flags & KDBUS_MSG_EXPECT_REPLY) { |
15291 |
-+ /* if you expect a reply, you must specify a timeout */ |
15292 |
-+ if (msg->timeout_ns == 0) |
15293 |
-+ return -EINVAL; |
15294 |
-+ /* signals cannot have replies */ |
15295 |
-+ if (msg->flags & KDBUS_MSG_SIGNAL) |
15296 |
-+ return -ENOTUNIQ; |
15297 |
-+ } else { |
15298 |
-+ /* must expect reply if sent as synchronous call */ |
15299 |
-+ if (cmd->flags & KDBUS_SEND_SYNC_REPLY) |
15300 |
-+ return -EINVAL; |
15301 |
-+ /* cannot mark replies as signal */ |
15302 |
-+ if (msg->cookie_reply && (msg->flags & KDBUS_MSG_SIGNAL)) |
15303 |
-+ return -EINVAL; |
15304 |
-+ } |
15305 |
-+ |
15306 |
-+ /* |
15307 |
-+ * Step 2: |
15308 |
-+ * Validate all passed items. While at it, select some statistics that |
15309 |
-+ * are required to allocate state objects later on. |
15310 |
-+ * |
15311 |
-+ * Generic item validation has already been done via |
15312 |
-+ * kdbus_item_validate(). Furthermore, the number of items is naturally |
15313 |
-+ * limited by the maximum message size. Hence, only non-generic item |
15314 |
-+ * checks are performed here (mainly integer overflow tests). |
15315 |
-+ */ |
15316 |
-+ |
15317 |
-+ n_parts = 0; |
15318 |
-+ n_memfds = 0; |
15319 |
-+ n_fds = 0; |
15320 |
-+ vec_size = 0; |
15321 |
-+ |
15322 |
-+ KDBUS_ITEMS_FOREACH(item, msg->items, KDBUS_ITEMS_SIZE(msg, items)) { |
15323 |
-+ switch (item->type) { |
15324 |
-+ case KDBUS_ITEM_PAYLOAD_VEC: { |
15325 |
-+ void __force __user *ptr = KDBUS_PTR(item->vec.address); |
15326 |
-+ u64 size = item->vec.size; |
15327 |
-+ |
15328 |
-+ if (vec_size + size < vec_size) |
15329 |
-+ return -EMSGSIZE; |
15330 |
-+ if (vec_size + size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE) |
15331 |
-+ return -EMSGSIZE; |
15332 |
-+ if (ptr && unlikely(!access_ok(VERIFY_READ, ptr, size))) |
15333 |
-+ return -EFAULT; |
15334 |
-+ |
15335 |
-+ if (ptr || size % 8) /* data or padding */ |
15336 |
-+ ++n_parts; |
15337 |
-+ break; |
15338 |
-+ } |
15339 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
15340 |
-+ u64 start = item->memfd.start; |
15341 |
-+ u64 size = item->memfd.size; |
15342 |
-+ |
15343 |
-+ if (start + size < start) |
15344 |
-+ return -EMSGSIZE; |
15345 |
-+ if (n_memfds >= KDBUS_MSG_MAX_MEMFD_ITEMS) |
15346 |
-+ return -E2BIG; |
15347 |
-+ |
15348 |
-+ ++n_memfds; |
15349 |
-+ if (size % 8) /* vec-padding required */ |
15350 |
-+ ++n_parts; |
15351 |
-+ break; |
15352 |
-+ } |
15353 |
-+ case KDBUS_ITEM_FDS: { |
15354 |
-+ if (fds) |
15355 |
-+ return -EEXIST; |
15356 |
-+ |
15357 |
-+ fds = item; |
15358 |
-+ n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int); |
15359 |
-+ if (n_fds > KDBUS_CONN_MAX_FDS_PER_USER) |
15360 |
-+ return -EMFILE; |
15361 |
-+ |
15362 |
-+ break; |
15363 |
-+ } |
15364 |
-+ case KDBUS_ITEM_BLOOM_FILTER: { |
15365 |
-+ u64 bloom_size; |
15366 |
-+ |
15367 |
-+ if (bloom) |
15368 |
-+ return -EEXIST; |
15369 |
-+ |
15370 |
-+ bloom = item; |
15371 |
-+ bloom_size = KDBUS_ITEM_PAYLOAD_SIZE(item) - |
15372 |
-+ offsetof(struct kdbus_bloom_filter, data); |
15373 |
-+ if (!KDBUS_IS_ALIGNED8(bloom_size)) |
15374 |
-+ return -EFAULT; |
15375 |
-+ if (bloom_size != bus->bloom.size) |
15376 |
-+ return -EDOM; |
15377 |
-+ |
15378 |
-+ break; |
15379 |
-+ } |
15380 |
-+ case KDBUS_ITEM_DST_NAME: { |
15381 |
-+ if (dstname) |
15382 |
-+ return -EEXIST; |
15383 |
-+ |
15384 |
-+ dstname = item; |
15385 |
-+ if (!kdbus_name_is_valid(item->str, false)) |
15386 |
-+ return -EINVAL; |
15387 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST) |
15388 |
-+ return -EBADMSG; |
15389 |
-+ |
15390 |
-+ break; |
15391 |
-+ } |
15392 |
-+ default: |
15393 |
-+ return -EINVAL; |
15394 |
-+ } |
15395 |
-+ } |
15396 |
-+ |
15397 |
-+ /* |
15398 |
-+ * Step 3: |
15399 |
-+ * Validate that required items were actually passed, and that no item |
15400 |
-+ * contradicts the message flags. |
15401 |
-+ */ |
15402 |
-+ |
15403 |
-+ /* bloom filters must be attached _iff_ it's a signal */ |
15404 |
-+ if (!(msg->flags & KDBUS_MSG_SIGNAL) != !bloom) |
15405 |
-+ return -EBADMSG; |
15406 |
-+ /* destination name is required if no ID is given */ |
15407 |
-+ if (msg->dst_id == KDBUS_DST_ID_NAME && !dstname) |
15408 |
-+ return -EDESTADDRREQ; |
15409 |
-+ /* cannot send file-descriptors attached to broadcasts */ |
15410 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST && fds) |
15411 |
-+ return -ENOTUNIQ; |
15412 |
-+ |
15413 |
-+ *out_n_memfds = n_memfds; |
15414 |
-+ *out_n_fds = n_fds; |
15415 |
-+ *out_n_parts = n_parts; |
15416 |
-+ |
15417 |
-+ return 0; |
15418 |
-+} |
15419 |
-+ |
15420 |
-+static bool kdbus_staging_merge_vecs(struct kdbus_staging *staging, |
15421 |
-+ struct kdbus_item **prev_item, |
15422 |
-+ struct iovec **prev_vec, |
15423 |
-+ const struct kdbus_item *merge) |
15424 |
-+{ |
15425 |
-+ void __user *ptr = (void __user *)KDBUS_PTR(merge->vec.address); |
15426 |
-+ u64 padding = merge->vec.size % 8; |
15427 |
-+ struct kdbus_item *prev = *prev_item; |
15428 |
-+ struct iovec *vec = *prev_vec; |
15429 |
-+ |
15430 |
-+ /* XXX: merging is disabled so far */ |
15431 |
-+ if (0 && prev && prev->type == KDBUS_ITEM_PAYLOAD_OFF && |
15432 |
-+ !merge->vec.address == !prev->vec.address) { |
15433 |
-+ /* |
15434 |
-+ * If we merge two VECs, we can always drop the second |
15435 |
-+ * PAYLOAD_VEC item. Hence, include its size in the previous |
15436 |
-+ * one. |
15437 |
-+ */ |
15438 |
-+ prev->vec.size += merge->vec.size; |
15439 |
-+ |
15440 |
-+ if (ptr) { |
15441 |
-+ /* |
15442 |
-+ * If we merge two data VECs, we need two iovecs to copy |
15443 |
-+ * the data. But the items can be easily merged by |
15444 |
-+ * summing their lengths. |
15445 |
-+ */ |
15446 |
-+ vec = &staging->parts[staging->n_parts++]; |
15447 |
-+ vec->iov_len = merge->vec.size; |
15448 |
-+ vec->iov_base = ptr; |
15449 |
-+ staging->n_payload += vec->iov_len; |
15450 |
-+ } else if (padding) { |
15451 |
-+ /* |
15452 |
-+ * If we merge two 0-vecs with the second 0-vec |
15453 |
-+ * requiring padding, we need to insert an iovec to copy |
15454 |
-+ * the 0-padding. We try merging it with the previous |
15455 |
-+ * 0-padding iovec. This might end up with an |
15456 |
-+ * iov_len==0, in which case we simply drop the iovec. |
15457 |
-+ */ |
15458 |
-+ if (vec) { |
15459 |
-+ staging->n_payload -= vec->iov_len; |
15460 |
-+ vec->iov_len = prev->vec.size % 8; |
15461 |
-+ if (!vec->iov_len) { |
15462 |
-+ --staging->n_parts; |
15463 |
-+ vec = NULL; |
15464 |
-+ } else { |
15465 |
-+ staging->n_payload += vec->iov_len; |
15466 |
-+ } |
15467 |
-+ } else { |
15468 |
-+ vec = &staging->parts[staging->n_parts++]; |
15469 |
-+ vec->iov_len = padding; |
15470 |
-+ vec->iov_base = (char __user *)zeros; |
15471 |
-+ staging->n_payload += vec->iov_len; |
15472 |
-+ } |
15473 |
-+ } else { |
15474 |
-+ /* |
15475 |
-+ * If we merge two 0-vecs with the second 0-vec having |
15476 |
-+ * no padding, we know the padding of the first stays |
15477 |
-+ * the same. Hence, @vec needs no adjustment. |
15478 |
-+ */ |
15479 |
-+ } |
15480 |
-+ |
15481 |
-+ /* successfully merged with previous item */ |
15482 |
-+ merge = prev; |
15483 |
-+ } else { |
15484 |
-+ /* |
15485 |
-+ * If we cannot merge the payload item with the previous one, |
15486 |
-+ * we simply insert a new iovec for the data/padding. |
15487 |
-+ */ |
15488 |
-+ if (ptr) { |
15489 |
-+ vec = &staging->parts[staging->n_parts++]; |
15490 |
-+ vec->iov_len = merge->vec.size; |
15491 |
-+ vec->iov_base = ptr; |
15492 |
-+ staging->n_payload += vec->iov_len; |
15493 |
-+ } else if (padding) { |
15494 |
-+ vec = &staging->parts[staging->n_parts++]; |
15495 |
-+ vec->iov_len = padding; |
15496 |
-+ vec->iov_base = (char __user *)zeros; |
15497 |
-+ staging->n_payload += vec->iov_len; |
15498 |
-+ } else { |
15499 |
-+ vec = NULL; |
15500 |
-+ } |
15501 |
-+ } |
15502 |
-+ |
15503 |
-+ *prev_item = (struct kdbus_item *)merge; |
15504 |
-+ *prev_vec = vec; |
15505 |
-+ |
15506 |
-+ return merge == prev; |
15507 |
-+} |
15508 |
-+ |
15509 |
-+static int kdbus_staging_import(struct kdbus_staging *staging) |
15510 |
-+{ |
15511 |
-+ struct kdbus_item *it, *item, *last, *prev_payload; |
15512 |
-+ struct kdbus_gaps *gaps = staging->gaps; |
15513 |
-+ struct kdbus_msg *msg = staging->msg; |
15514 |
-+ struct iovec *part, *prev_part; |
15515 |
-+ bool drop_item; |
15516 |
-+ |
15517 |
-+ drop_item = false; |
15518 |
-+ last = NULL; |
15519 |
-+ prev_payload = NULL; |
15520 |
-+ prev_part = NULL; |
15521 |
-+ |
15522 |
-+ /* |
15523 |
-+ * We modify msg->items along the way; make sure to use @item as offset |
15524 |
-+ * to the next item (instead of the iterator @it). |
15525 |
-+ */ |
15526 |
-+ for (it = item = msg->items; |
15527 |
-+ it >= msg->items && |
15528 |
-+ (u8 *)it < (u8 *)msg + msg->size && |
15529 |
-+ (u8 *)it + it->size <= (u8 *)msg + msg->size; ) { |
15530 |
-+ /* |
15531 |
-+ * If we dropped items along the way, move current item to |
15532 |
-+ * front. We must not access @it afterwards, but use @item |
15533 |
-+ * instead! |
15534 |
-+ */ |
15535 |
-+ if (it != item) |
15536 |
-+ memmove(item, it, it->size); |
15537 |
-+ it = (void *)((u8 *)it + KDBUS_ALIGN8(item->size)); |
15538 |
-+ |
15539 |
-+ switch (item->type) { |
15540 |
-+ case KDBUS_ITEM_PAYLOAD_VEC: { |
15541 |
-+ size_t offset = staging->n_payload; |
15542 |
-+ |
15543 |
-+ if (kdbus_staging_merge_vecs(staging, &prev_payload, |
15544 |
-+ &prev_part, item)) { |
15545 |
-+ drop_item = true; |
15546 |
-+ } else if (item->vec.address) { |
15547 |
-+ /* real offset is patched later on */ |
15548 |
-+ item->type = KDBUS_ITEM_PAYLOAD_OFF; |
15549 |
-+ item->vec.offset = offset; |
15550 |
-+ } else { |
15551 |
-+ item->type = KDBUS_ITEM_PAYLOAD_OFF; |
15552 |
-+ item->vec.offset = ~0ULL; |
15553 |
-+ } |
15554 |
-+ |
15555 |
-+ break; |
15556 |
-+ } |
15557 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
15558 |
-+ struct file *f; |
15559 |
-+ |
15560 |
-+ f = kdbus_get_memfd(&item->memfd); |
15561 |
-+ if (IS_ERR(f)) |
15562 |
-+ return PTR_ERR(f); |
15563 |
-+ |
15564 |
-+ gaps->memfd_files[gaps->n_memfds] = f; |
15565 |
-+ gaps->memfd_offsets[gaps->n_memfds] = |
15566 |
-+ (u8 *)&item->memfd.fd - (u8 *)msg; |
15567 |
-+ ++gaps->n_memfds; |
15568 |
-+ |
15569 |
-+ /* memfds cannot be merged */ |
15570 |
-+ prev_payload = item; |
15571 |
-+ prev_part = NULL; |
15572 |
-+ |
15573 |
-+ /* insert padding to make following VECs aligned */ |
15574 |
-+ if (item->memfd.size % 8) { |
15575 |
-+ part = &staging->parts[staging->n_parts++]; |
15576 |
-+ part->iov_len = item->memfd.size % 8; |
15577 |
-+ part->iov_base = (char __user *)zeros; |
15578 |
-+ staging->n_payload += part->iov_len; |
15579 |
-+ } |
15580 |
-+ |
15581 |
-+ break; |
15582 |
-+ } |
15583 |
-+ case KDBUS_ITEM_FDS: { |
15584 |
-+ size_t i, n_fds; |
15585 |
-+ |
15586 |
-+ n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int); |
15587 |
-+ for (i = 0; i < n_fds; ++i) { |
15588 |
-+ struct file *f; |
15589 |
-+ |
15590 |
-+ f = kdbus_get_fd(item->fds[i]); |
15591 |
-+ if (IS_ERR(f)) |
15592 |
-+ return PTR_ERR(f); |
15593 |
-+ |
15594 |
-+ gaps->fd_files[gaps->n_fds++] = f; |
15595 |
-+ } |
15596 |
-+ |
15597 |
-+ gaps->fd_offset = (u8 *)item->fds - (u8 *)msg; |
15598 |
-+ |
15599 |
-+ break; |
15600 |
-+ } |
15601 |
-+ case KDBUS_ITEM_BLOOM_FILTER: |
15602 |
-+ staging->bloom_filter = &item->bloom_filter; |
15603 |
-+ break; |
15604 |
-+ case KDBUS_ITEM_DST_NAME: |
15605 |
-+ staging->dst_name = item->str; |
15606 |
-+ break; |
15607 |
-+ } |
15608 |
-+ |
15609 |
-+ /* drop item if we merged it with a previous one */ |
15610 |
-+ if (drop_item) { |
15611 |
-+ drop_item = false; |
15612 |
-+ } else { |
15613 |
-+ last = item; |
15614 |
-+ item = KDBUS_ITEM_NEXT(item); |
15615 |
-+ } |
15616 |
-+ } |
15617 |
-+ |
15618 |
-+ /* adjust message size regarding dropped items */ |
15619 |
-+ msg->size = offsetof(struct kdbus_msg, items); |
15620 |
-+ if (last) |
15621 |
-+ msg->size += ((u8 *)last - (u8 *)msg->items) + last->size; |
15622 |
-+ |
15623 |
-+ return 0; |
15624 |
-+} |
15625 |
-+ |
15626 |
-+static void kdbus_staging_reserve(struct kdbus_staging *staging) |
15627 |
-+{ |
15628 |
-+ struct iovec *part; |
15629 |
-+ |
15630 |
-+ part = &staging->parts[staging->n_parts++]; |
15631 |
-+ part->iov_base = (void __user *)zeros; |
15632 |
-+ part->iov_len = 0; |
15633 |
-+} |
15634 |
-+ |
15635 |
-+static struct kdbus_staging *kdbus_staging_new(struct kdbus_bus *bus, |
15636 |
-+ size_t n_parts, |
15637 |
-+ size_t msg_extra_size) |
15638 |
-+{ |
15639 |
-+ const size_t reserved_parts = 5; /* see below for explanation */ |
15640 |
-+ struct kdbus_staging *staging; |
15641 |
-+ int ret; |
15642 |
-+ |
15643 |
-+ n_parts += reserved_parts; |
15644 |
-+ |
15645 |
-+ staging = kzalloc(sizeof(*staging) + n_parts * sizeof(*staging->parts) + |
15646 |
-+ msg_extra_size, GFP_TEMPORARY); |
15647 |
-+ if (!staging) |
15648 |
-+ return ERR_PTR(-ENOMEM); |
15649 |
-+ |
15650 |
-+ staging->msg_seqnum = atomic64_inc_return(&bus->last_message_id); |
15651 |
-+ staging->n_parts = 0; /* we reserve n_parts, but don't enforce them */ |
15652 |
-+ staging->parts = (void *)(staging + 1); |
15653 |
-+ |
15654 |
-+ if (msg_extra_size) /* if requested, allocate message, too */ |
15655 |
-+ staging->msg = (void *)((u8 *)staging->parts + |
15656 |
-+ n_parts * sizeof(*staging->parts)); |
15657 |
-+ |
15658 |
-+ staging->meta_proc = kdbus_meta_proc_new(); |
15659 |
-+ if (IS_ERR(staging->meta_proc)) { |
15660 |
-+ ret = PTR_ERR(staging->meta_proc); |
15661 |
-+ staging->meta_proc = NULL; |
15662 |
-+ goto error; |
15663 |
-+ } |
15664 |
-+ |
15665 |
-+ staging->meta_conn = kdbus_meta_conn_new(); |
15666 |
-+ if (IS_ERR(staging->meta_conn)) { |
15667 |
-+ ret = PTR_ERR(staging->meta_conn); |
15668 |
-+ staging->meta_conn = NULL; |
15669 |
-+ goto error; |
15670 |
-+ } |
15671 |
-+ |
15672 |
-+ /* |
15673 |
-+ * Prepare iovecs to copy the message into the target pool. We use the |
15674 |
-+ * following iovecs: |
15675 |
-+ * * iovec to copy "kdbus_msg.size" |
15676 |
-+ * * iovec to copy "struct kdbus_msg" (minus size) plus items |
15677 |
-+ * * iovec for possible padding after the items |
15678 |
-+ * * iovec for metadata items |
15679 |
-+ * * iovec for possible padding after the items |
15680 |
-+ * |
15681 |
-+ * Make sure to update @reserved_parts if you add more parts here. |
15682 |
-+ */ |
15683 |
-+ |
15684 |
-+ kdbus_staging_reserve(staging); /* msg.size */ |
15685 |
-+ kdbus_staging_reserve(staging); /* msg (minus msg.size) plus items */ |
15686 |
-+ kdbus_staging_reserve(staging); /* msg padding */ |
15687 |
-+ kdbus_staging_reserve(staging); /* meta */ |
15688 |
-+ kdbus_staging_reserve(staging); /* meta padding */ |
15689 |
-+ |
15690 |
-+ return staging; |
15691 |
-+ |
15692 |
-+error: |
15693 |
-+ kdbus_staging_free(staging); |
15694 |
-+ return ERR_PTR(ret); |
15695 |
-+} |
15696 |
-+ |
15697 |
-+struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus, |
15698 |
-+ u64 dst, u64 cookie_timeout, |
15699 |
-+ size_t it_size, size_t it_type) |
15700 |
-+{ |
15701 |
-+ struct kdbus_staging *staging; |
15702 |
-+ size_t size; |
15703 |
-+ |
15704 |
-+ size = offsetof(struct kdbus_msg, items) + |
15705 |
-+ KDBUS_ITEM_HEADER_SIZE + it_size; |
15706 |
-+ |
15707 |
-+ staging = kdbus_staging_new(bus, 0, KDBUS_ALIGN8(size)); |
15708 |
-+ if (IS_ERR(staging)) |
15709 |
-+ return ERR_CAST(staging); |
15710 |
-+ |
15711 |
-+ staging->msg->size = size; |
15712 |
-+ staging->msg->flags = (dst == KDBUS_DST_ID_BROADCAST) ? |
15713 |
-+ KDBUS_MSG_SIGNAL : 0; |
15714 |
-+ staging->msg->dst_id = dst; |
15715 |
-+ staging->msg->src_id = KDBUS_SRC_ID_KERNEL; |
15716 |
-+ staging->msg->payload_type = KDBUS_PAYLOAD_KERNEL; |
15717 |
-+ staging->msg->cookie_reply = cookie_timeout; |
15718 |
-+ staging->notify = staging->msg->items; |
15719 |
-+ staging->notify->size = KDBUS_ITEM_HEADER_SIZE + it_size; |
15720 |
-+ staging->notify->type = it_type; |
15721 |
-+ |
15722 |
-+ return staging; |
15723 |
-+} |
15724 |
-+ |
15725 |
-+struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus, |
15726 |
-+ struct kdbus_cmd_send *cmd, |
15727 |
-+ struct kdbus_msg *msg) |
15728 |
-+{ |
15729 |
-+ const size_t reserved_parts = 1; /* see below for explanation */ |
15730 |
-+ size_t n_memfds, n_fds, n_parts; |
15731 |
-+ struct kdbus_staging *staging; |
15732 |
-+ int ret; |
15733 |
-+ |
15734 |
-+ /* |
15735 |
-+ * Examine user-supplied message and figure out how many resources we |
15736 |
-+ * need to allocate in our staging area. This requires us to iterate |
15737 |
-+ * the message twice, but saves us from re-allocating our resources |
15738 |
-+ * all the time. |
15739 |
-+ */ |
15740 |
-+ |
15741 |
-+ ret = kdbus_msg_examine(msg, bus, cmd, &n_memfds, &n_fds, &n_parts); |
15742 |
-+ if (ret < 0) |
15743 |
-+ return ERR_PTR(ret); |
15744 |
-+ |
15745 |
-+ n_parts += reserved_parts; |
15746 |
-+ |
15747 |
-+ /* |
15748 |
-+ * Allocate staging area with the number of required resources. Make |
15749 |
-+ * sure that we have enough iovecs for all required parts pre-allocated |
15750 |
-+ * so this will hopefully be the only memory allocation for this |
15751 |
-+ * message transaction. |
15752 |
-+ */ |
15753 |
-+ |
15754 |
-+ staging = kdbus_staging_new(bus, n_parts, 0); |
15755 |
-+ if (IS_ERR(staging)) |
15756 |
-+ return ERR_CAST(staging); |
15757 |
-+ |
15758 |
-+ staging->msg = msg; |
15759 |
-+ |
15760 |
-+ /* |
15761 |
-+ * If the message contains memfds or fd items, we need to remember some |
15762 |
-+ * state so we can fill in the requested information at RECV time. |
15763 |
-+ * File-descriptors cannot be passed at SEND time. Hence, allocate a |
15764 |
-+ * gaps-object to remember that state. That gaps object is linked to |
15765 |
-+ * from the staging area, but will also be linked to from the message |
15766 |
-+ * queue of each peer. Hence, each receiver owns a reference to it, and |
15767 |
-+ * it will later be used to fill the 'gaps' in message that couldn't be |
15768 |
-+ * filled at SEND time. |
15769 |
-+ * Note that the 'gaps' object is read-only once the staging-allocator |
15770 |
-+ * returns. There might be connections receiving a queued message while |
15771 |
-+ * the sender still broadcasts the message to other receivers. |
15772 |
-+ */ |
15773 |
-+ |
15774 |
-+ if (n_memfds > 0 || n_fds > 0) { |
15775 |
-+ staging->gaps = kdbus_gaps_new(n_memfds, n_fds); |
15776 |
-+ if (IS_ERR(staging->gaps)) { |
15777 |
-+ ret = PTR_ERR(staging->gaps); |
15778 |
-+ staging->gaps = NULL; |
15779 |
-+ kdbus_staging_free(staging); |
15780 |
-+ return ERR_PTR(ret); |
15781 |
-+ } |
15782 |
-+ } |
15783 |
-+ |
15784 |
-+ /* |
15785 |
-+ * kdbus_staging_new() already reserves parts for message setup. For |
15786 |
-+ * user-supplied messages, we add the following iovecs: |
15787 |
-+ * ... variable number of iovecs for payload ... |
15788 |
-+ * * final iovec for possible padding of payload |
15789 |
-+ * |
15790 |
-+ * Make sure to update @reserved_parts if you add more parts here. |
15791 |
-+ */ |
15792 |
-+ |
15793 |
-+ ret = kdbus_staging_import(staging); /* payload */ |
15794 |
-+ kdbus_staging_reserve(staging); /* payload padding */ |
15795 |
-+ |
15796 |
-+ if (ret < 0) |
15797 |
-+ goto error; |
15798 |
-+ |
15799 |
-+ return staging; |
15800 |
-+ |
15801 |
-+error: |
15802 |
-+ kdbus_staging_free(staging); |
15803 |
-+ return ERR_PTR(ret); |
15804 |
-+} |
15805 |
-+ |
15806 |
-+struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging) |
15807 |
-+{ |
15808 |
-+ if (!staging) |
15809 |
-+ return NULL; |
15810 |
-+ |
15811 |
-+ kdbus_meta_conn_unref(staging->meta_conn); |
15812 |
-+ kdbus_meta_proc_unref(staging->meta_proc); |
15813 |
-+ kdbus_gaps_unref(staging->gaps); |
15814 |
-+ kfree(staging); |
15815 |
-+ |
15816 |
-+ return NULL; |
15817 |
-+} |
15818 |
-+ |
15819 |
-+static int kdbus_staging_collect_metadata(struct kdbus_staging *staging, |
15820 |
-+ struct kdbus_conn *src, |
15821 |
-+ struct kdbus_conn *dst, |
15822 |
-+ u64 *out_attach) |
15823 |
-+{ |
15824 |
-+ u64 attach; |
15825 |
-+ int ret; |
15826 |
-+ |
15827 |
-+ if (src) |
15828 |
-+ attach = kdbus_meta_msg_mask(src, dst); |
15829 |
-+ else |
15830 |
-+ attach = KDBUS_ATTACH_TIMESTAMP; /* metadata for kernel msgs */ |
15831 |
-+ |
15832 |
-+ if (src && !src->meta_fake) { |
15833 |
-+ ret = kdbus_meta_proc_collect(staging->meta_proc, attach); |
15834 |
-+ if (ret < 0) |
15835 |
-+ return ret; |
15836 |
-+ } |
15837 |
-+ |
15838 |
-+ ret = kdbus_meta_conn_collect(staging->meta_conn, src, |
15839 |
-+ staging->msg_seqnum, attach); |
15840 |
-+ if (ret < 0) |
15841 |
-+ return ret; |
15842 |
-+ |
15843 |
-+ *out_attach = attach; |
15844 |
-+ return 0; |
15845 |
-+} |
15846 |
-+ |
15847 |
-+/** |
15848 |
-+ * kdbus_staging_emit() - emit linearized message in target pool |
15849 |
-+ * @staging: staging object to create message from |
15850 |
-+ * @src: sender of the message (or NULL) |
15851 |
-+ * @dst: target connection to allocate message for |
15852 |
-+ * |
15853 |
-+ * This allocates a pool-slice for @dst and copies the message provided by |
15854 |
-+ * @staging into it. The new slice is then returned to the caller for further |
15855 |
-+ * processing. It's not linked into any queue, yet. |
15856 |
-+ * |
15857 |
-+ * Return: Newly allocated slice or ERR_PTR on failure. |
15858 |
-+ */ |
15859 |
-+struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging, |
15860 |
-+ struct kdbus_conn *src, |
15861 |
-+ struct kdbus_conn *dst) |
15862 |
-+{ |
15863 |
-+ struct kdbus_item *item, *meta_items = NULL; |
15864 |
-+ struct kdbus_pool_slice *slice = NULL; |
15865 |
-+ size_t off, size, meta_size; |
15866 |
-+ struct iovec *v; |
15867 |
-+ u64 attach, msg_size; |
15868 |
-+ int ret; |
15869 |
-+ |
15870 |
-+ /* |
15871 |
-+ * Step 1: |
15872 |
-+ * Collect metadata from @src depending on the attach-flags allowed for |
15873 |
-+ * @dst. Translate it into the namespaces pinned by @dst. |
15874 |
-+ */ |
15875 |
-+ |
15876 |
-+ ret = kdbus_staging_collect_metadata(staging, src, dst, &attach); |
15877 |
-+ if (ret < 0) |
15878 |
-+ goto error; |
15879 |
-+ |
15880 |
-+ ret = kdbus_meta_emit(staging->meta_proc, NULL, staging->meta_conn, |
15881 |
-+ dst, attach, &meta_items, &meta_size); |
15882 |
-+ if (ret < 0) |
15883 |
-+ goto error; |
15884 |
-+ |
15885 |
-+ /* |
15886 |
-+ * Step 2: |
15887 |
-+ * Setup iovecs for the message. See kdbus_staging_new() for allocation |
15888 |
-+ * of those iovecs. All reserved iovecs have been initialized with |
15889 |
-+ * iov_len=0 + iov_base=zeros. Furthermore, the iovecs to copy the |
15890 |
-+ * actual message payload have already been initialized and need not be |
15891 |
-+ * touched. |
15892 |
-+ */ |
15893 |
-+ |
15894 |
-+ v = staging->parts; |
15895 |
-+ msg_size = staging->msg->size; |
15896 |
-+ |
15897 |
-+ /* msg.size */ |
15898 |
-+ v->iov_len = sizeof(msg_size); |
15899 |
-+ v->iov_base = (void __user *)&msg_size; |
15900 |
-+ ++v; |
15901 |
-+ |
15902 |
-+ /* msg (after msg.size) plus items */ |
15903 |
-+ v->iov_len = staging->msg->size - sizeof(staging->msg->size); |
15904 |
-+ v->iov_base = (void __user *)((u8 *)staging->msg + |
15905 |
-+ sizeof(staging->msg->size)); |
15906 |
-+ ++v; |
15907 |
-+ |
15908 |
-+ /* padding after msg */ |
15909 |
-+ v->iov_len = KDBUS_ALIGN8(staging->msg->size) - staging->msg->size; |
15910 |
-+ v->iov_base = (void __user *)zeros; |
15911 |
-+ ++v; |
15912 |
-+ |
15913 |
-+ if (meta_size > 0) { |
15914 |
-+ /* metadata items */ |
15915 |
-+ v->iov_len = meta_size; |
15916 |
-+ v->iov_base = (void __user *)meta_items; |
15917 |
-+ ++v; |
15918 |
-+ |
15919 |
-+ /* padding after metadata */ |
15920 |
-+ v->iov_len = KDBUS_ALIGN8(meta_size) - meta_size; |
15921 |
-+ v->iov_base = (void __user *)zeros; |
15922 |
-+ ++v; |
15923 |
-+ |
15924 |
-+ msg_size = KDBUS_ALIGN8(msg_size) + meta_size; |
15925 |
-+ } else { |
15926 |
-+ /* metadata items */ |
15927 |
-+ v->iov_len = 0; |
15928 |
-+ v->iov_base = (void __user *)zeros; |
15929 |
-+ ++v; |
15930 |
-+ |
15931 |
-+ /* padding after metadata */ |
15932 |
-+ v->iov_len = 0; |
15933 |
-+ v->iov_base = (void __user *)zeros; |
15934 |
-+ ++v; |
15935 |
-+ } |
15936 |
-+ |
15937 |
-+ /* ... payload iovecs are already filled in ... */ |
15938 |
-+ |
15939 |
-+ /* compute overall size and fill in padding after payload */ |
15940 |
-+ size = KDBUS_ALIGN8(msg_size); |
15941 |
-+ |
15942 |
-+ if (staging->n_payload > 0) { |
15943 |
-+ size += staging->n_payload; |
15944 |
-+ |
15945 |
-+ v = &staging->parts[staging->n_parts - 1]; |
15946 |
-+ v->iov_len = KDBUS_ALIGN8(size) - size; |
15947 |
-+ v->iov_base = (void __user *)zeros; |
15948 |
-+ |
15949 |
-+ size = KDBUS_ALIGN8(size); |
15950 |
-+ } |
15951 |
-+ |
15952 |
-+ /* |
15953 |
-+ * Step 3: |
15954 |
-+ * The PAYLOAD_OFF items in the message contain a relative 'offset' |
15955 |
-+ * field that tells the receiver where to find the actual payload. This |
15956 |
-+ * offset is relative to the start of the message, and as such depends |
15957 |
-+ * on the size of the metadata items we inserted. This size is variable |
15958 |
-+ * and changes for each peer we send the message to. Hence, we remember |
15959 |
-+ * the last relative offset that was used to calculate the 'offset' |
15960 |
-+ * fields. For each message, we re-calculate it and patch all items, in |
15961 |
-+ * case it changed. |
15962 |
-+ */ |
15963 |
-+ |
15964 |
-+ off = KDBUS_ALIGN8(msg_size); |
15965 |
-+ |
15966 |
-+ if (off != staging->i_payload) { |
15967 |
-+ KDBUS_ITEMS_FOREACH(item, staging->msg->items, |
15968 |
-+ KDBUS_ITEMS_SIZE(staging->msg, items)) { |
15969 |
-+ if (item->type != KDBUS_ITEM_PAYLOAD_OFF) |
15970 |
-+ continue; |
15971 |
-+ |
15972 |
-+ item->vec.offset -= staging->i_payload; |
15973 |
-+ item->vec.offset += off; |
15974 |
-+ } |
15975 |
-+ |
15976 |
-+ staging->i_payload = off; |
15977 |
-+ } |
15978 |
-+ |
15979 |
-+ /* |
15980 |
-+ * Step 4: |
15981 |
-+ * Allocate pool slice and copy over all data. Make sure to properly |
15982 |
-+ * account on user quota. |
15983 |
-+ */ |
15984 |
-+ |
15985 |
-+ ret = kdbus_conn_quota_inc(dst, src ? src->user : NULL, size, |
15986 |
-+ staging->gaps ? staging->gaps->n_fds : 0); |
15987 |
-+ if (ret < 0) |
15988 |
-+ goto error; |
15989 |
-+ |
15990 |
-+ slice = kdbus_pool_slice_alloc(dst->pool, size, true); |
15991 |
-+ if (IS_ERR(slice)) { |
15992 |
-+ ret = PTR_ERR(slice); |
15993 |
-+ slice = NULL; |
15994 |
-+ goto error; |
15995 |
-+ } |
15996 |
-+ |
15997 |
-+ WARN_ON(kdbus_pool_slice_size(slice) != size); |
15998 |
-+ |
15999 |
-+ ret = kdbus_pool_slice_copy_iovec(slice, 0, staging->parts, |
16000 |
-+ staging->n_parts, size); |
16001 |
-+ if (ret < 0) |
16002 |
-+ goto error; |
16003 |
-+ |
16004 |
-+ /* all done, return slice to caller */ |
16005 |
-+ goto exit; |
16006 |
-+ |
16007 |
-+error: |
16008 |
-+ if (slice) |
16009 |
-+ kdbus_conn_quota_dec(dst, src ? src->user : NULL, size, |
16010 |
-+ staging->gaps ? staging->gaps->n_fds : 0); |
16011 |
-+ kdbus_pool_slice_release(slice); |
16012 |
-+ slice = ERR_PTR(ret); |
16013 |
-+exit: |
16014 |
-+ kfree(meta_items); |
16015 |
-+ return slice; |
16016 |
-+} |
16017 |
-diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h |
16018 |
-new file mode 100644 |
16019 |
-index 0000000..298f9c9 |
16020 |
---- /dev/null |
16021 |
-+++ b/ipc/kdbus/message.h |
16022 |
-@@ -0,0 +1,120 @@ |
16023 |
-+/* |
16024 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
16025 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
16026 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
16027 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
16028 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
16029 |
-+ * |
16030 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
16031 |
-+ * the terms of the GNU Lesser General Public License as published by the |
16032 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
16033 |
-+ * your option) any later version. |
16034 |
-+ */ |
16035 |
-+ |
16036 |
-+#ifndef __KDBUS_MESSAGE_H |
16037 |
-+#define __KDBUS_MESSAGE_H |
16038 |
-+ |
16039 |
-+#include <linux/fs.h> |
16040 |
-+#include <linux/kref.h> |
16041 |
-+#include <uapi/linux/kdbus.h> |
16042 |
-+ |
16043 |
-+struct kdbus_bus; |
16044 |
-+struct kdbus_conn; |
16045 |
-+struct kdbus_meta_conn; |
16046 |
-+struct kdbus_meta_proc; |
16047 |
-+struct kdbus_pool_slice; |
16048 |
-+ |
16049 |
-+/** |
16050 |
-+ * struct kdbus_gaps - gaps in message to be filled later |
16051 |
-+ * @kref: Reference counter |
16052 |
-+ * @n_memfd_offs: Number of memfds |
16053 |
-+ * @memfd_offs: Offsets of kdbus_memfd items in target slice |
16054 |
-+ * @n_fds: Number of fds |
16055 |
-+ * @fds: Array of sent fds |
16056 |
-+ * @fds_offset: Offset of fd-array in target slice |
16057 |
-+ * |
16058 |
-+ * The 'gaps' object is used to track data that is needed to fill gaps in a |
16059 |
-+ * message at RECV time. Usually, we try to compile the whole message at SEND |
16060 |
-+ * time. This has the advantage, that we don't have to cache any information and |
16061 |
-+ * can keep the memory consumption small. Furthermore, all copy operations can |
16062 |
-+ * be combined into a single function call, which speeds up transactions |
16063 |
-+ * considerably. |
16064 |
-+ * However, things like file-descriptors can only be fully installed at RECV |
16065 |
-+ * time. The gaps object tracks this data and pins it until a message is |
16066 |
-+ * received. The gaps object is shared between all receivers of the same |
16067 |
-+ * message. |
16068 |
-+ */ |
16069 |
-+struct kdbus_gaps { |
16070 |
-+ struct kref kref; |
16071 |
-+ |
16072 |
-+ /* state tracking for KDBUS_ITEM_PAYLOAD_MEMFD entries */ |
16073 |
-+ size_t n_memfds; |
16074 |
-+ u64 *memfd_offsets; |
16075 |
-+ struct file **memfd_files; |
16076 |
-+ |
16077 |
-+ /* state tracking for KDBUS_ITEM_FDS */ |
16078 |
-+ size_t n_fds; |
16079 |
-+ struct file **fd_files; |
16080 |
-+ u64 fd_offset; |
16081 |
-+}; |
16082 |
-+ |
16083 |
-+struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps); |
16084 |
-+struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps); |
16085 |
-+int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice, |
16086 |
-+ bool *out_incomplete); |
16087 |
-+ |
16088 |
-+/** |
16089 |
-+ * struct kdbus_staging - staging area to import messages |
16090 |
-+ * @msg: User-supplied message |
16091 |
-+ * @gaps: Gaps-object created during import (or NULL if empty) |
16092 |
-+ * @msg_seqnum: Message sequence number |
16093 |
-+ * @notify_entry: Entry into list of kernel-generated notifications |
16094 |
-+ * @i_payload: Current relative index of start of payload |
16095 |
-+ * @n_payload: Total number of bytes needed for payload |
16096 |
-+ * @n_parts: Number of parts |
16097 |
-+ * @parts: Array of iovecs that make up the whole message |
16098 |
-+ * @meta_proc: Process metadata of the sender (or NULL if empty) |
16099 |
-+ * @meta_conn: Connection metadata of the sender (or NULL if empty) |
16100 |
-+ * @bloom_filter: Pointer to the bloom-item in @msg, or NULL |
16101 |
-+ * @dst_name: Pointer to the dst-name-item in @msg, or NULL |
16102 |
-+ * @notify: Pointer to the notification item in @msg, or NULL |
16103 |
-+ * |
16104 |
-+ * The kdbus_staging object is a temporary staging area to import user-supplied |
16105 |
-+ * messages into the kernel. It is only used during SEND and dropped once the |
16106 |
-+ * message is queued. Any data that cannot be collected during SEND, is |
16107 |
-+ * collected in a kdbus_gaps object and attached to the message queue. |
16108 |
-+ */ |
16109 |
-+struct kdbus_staging { |
16110 |
-+ struct kdbus_msg *msg; |
16111 |
-+ struct kdbus_gaps *gaps; |
16112 |
-+ u64 msg_seqnum; |
16113 |
-+ struct list_head notify_entry; |
16114 |
-+ |
16115 |
-+ /* crafted iovecs to copy the message */ |
16116 |
-+ size_t i_payload; |
16117 |
-+ size_t n_payload; |
16118 |
-+ size_t n_parts; |
16119 |
-+ struct iovec *parts; |
16120 |
-+ |
16121 |
-+ /* metadata state */ |
16122 |
-+ struct kdbus_meta_proc *meta_proc; |
16123 |
-+ struct kdbus_meta_conn *meta_conn; |
16124 |
-+ |
16125 |
-+ /* cached pointers into @msg */ |
16126 |
-+ const struct kdbus_bloom_filter *bloom_filter; |
16127 |
-+ const char *dst_name; |
16128 |
-+ struct kdbus_item *notify; |
16129 |
-+}; |
16130 |
-+ |
16131 |
-+struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus, |
16132 |
-+ u64 dst, u64 cookie_timeout, |
16133 |
-+ size_t it_size, size_t it_type); |
16134 |
-+struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus, |
16135 |
-+ struct kdbus_cmd_send *cmd, |
16136 |
-+ struct kdbus_msg *msg); |
16137 |
-+struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging); |
16138 |
-+struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging, |
16139 |
-+ struct kdbus_conn *src, |
16140 |
-+ struct kdbus_conn *dst); |
16141 |
-+ |
16142 |
-+#endif |
16143 |
-diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c |
16144 |
-new file mode 100644 |
16145 |
-index 0000000..71ca475 |
16146 |
---- /dev/null |
16147 |
-+++ b/ipc/kdbus/metadata.c |
16148 |
-@@ -0,0 +1,1347 @@ |
16149 |
-+/* |
16150 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
16151 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
16152 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
16153 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
16154 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
16155 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
16156 |
-+ * |
16157 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
16158 |
-+ * the terms of the GNU Lesser General Public License as published by the |
16159 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
16160 |
-+ * your option) any later version. |
16161 |
-+ */ |
16162 |
-+ |
16163 |
-+#include <linux/audit.h> |
16164 |
-+#include <linux/capability.h> |
16165 |
-+#include <linux/cgroup.h> |
16166 |
-+#include <linux/cred.h> |
16167 |
-+#include <linux/file.h> |
16168 |
-+#include <linux/fs_struct.h> |
16169 |
-+#include <linux/init.h> |
16170 |
-+#include <linux/kref.h> |
16171 |
-+#include <linux/mutex.h> |
16172 |
-+#include <linux/sched.h> |
16173 |
-+#include <linux/security.h> |
16174 |
-+#include <linux/sizes.h> |
16175 |
-+#include <linux/slab.h> |
16176 |
-+#include <linux/uaccess.h> |
16177 |
-+#include <linux/uidgid.h> |
16178 |
-+#include <linux/uio.h> |
16179 |
-+#include <linux/user_namespace.h> |
16180 |
-+ |
16181 |
-+#include "bus.h" |
16182 |
-+#include "connection.h" |
16183 |
-+#include "endpoint.h" |
16184 |
-+#include "item.h" |
16185 |
-+#include "message.h" |
16186 |
-+#include "metadata.h" |
16187 |
-+#include "names.h" |
16188 |
-+ |
16189 |
-+/** |
16190 |
-+ * struct kdbus_meta_proc - Process metadata |
16191 |
-+ * @kref: Reference counting |
16192 |
-+ * @lock: Object lock |
16193 |
-+ * @collected: Bitmask of collected items |
16194 |
-+ * @valid: Bitmask of collected and valid items |
16195 |
-+ * @cred: Credentials |
16196 |
-+ * @pid: PID of process |
16197 |
-+ * @tgid: TGID of process |
16198 |
-+ * @ppid: PPID of process |
16199 |
-+ * @tid_comm: TID comm line |
16200 |
-+ * @pid_comm: PID comm line |
16201 |
-+ * @exe_path: Executable path |
16202 |
-+ * @root_path: Root-FS path |
16203 |
-+ * @cmdline: Command-line |
16204 |
-+ * @cgroup: Full cgroup path |
16205 |
-+ * @seclabel: Seclabel |
16206 |
-+ * @audit_loginuid: Audit login-UID |
16207 |
-+ * @audit_sessionid: Audit session-ID |
16208 |
-+ */ |
16209 |
-+struct kdbus_meta_proc { |
16210 |
-+ struct kref kref; |
16211 |
-+ struct mutex lock; |
16212 |
-+ u64 collected; |
16213 |
-+ u64 valid; |
16214 |
-+ |
16215 |
-+ /* KDBUS_ITEM_CREDS */ |
16216 |
-+ /* KDBUS_ITEM_AUXGROUPS */ |
16217 |
-+ /* KDBUS_ITEM_CAPS */ |
16218 |
-+ const struct cred *cred; |
16219 |
-+ |
16220 |
-+ /* KDBUS_ITEM_PIDS */ |
16221 |
-+ struct pid *pid; |
16222 |
-+ struct pid *tgid; |
16223 |
-+ struct pid *ppid; |
16224 |
-+ |
16225 |
-+ /* KDBUS_ITEM_TID_COMM */ |
16226 |
-+ char tid_comm[TASK_COMM_LEN]; |
16227 |
-+ /* KDBUS_ITEM_PID_COMM */ |
16228 |
-+ char pid_comm[TASK_COMM_LEN]; |
16229 |
-+ |
16230 |
-+ /* KDBUS_ITEM_EXE */ |
16231 |
-+ struct path exe_path; |
16232 |
-+ struct path root_path; |
16233 |
-+ |
16234 |
-+ /* KDBUS_ITEM_CMDLINE */ |
16235 |
-+ char *cmdline; |
16236 |
-+ |
16237 |
-+ /* KDBUS_ITEM_CGROUP */ |
16238 |
-+ char *cgroup; |
16239 |
-+ |
16240 |
-+ /* KDBUS_ITEM_SECLABEL */ |
16241 |
-+ char *seclabel; |
16242 |
-+ |
16243 |
-+ /* KDBUS_ITEM_AUDIT */ |
16244 |
-+ kuid_t audit_loginuid; |
16245 |
-+ unsigned int audit_sessionid; |
16246 |
-+}; |
16247 |
-+ |
16248 |
-+/** |
16249 |
-+ * struct kdbus_meta_conn |
16250 |
-+ * @kref: Reference counting |
16251 |
-+ * @lock: Object lock |
16252 |
-+ * @collected: Bitmask of collected items |
16253 |
-+ * @valid: Bitmask of collected and valid items |
16254 |
-+ * @ts: Timestamp values |
16255 |
-+ * @owned_names_items: Serialized items for owned names |
16256 |
-+ * @owned_names_size: Size of @owned_names_items |
16257 |
-+ * @conn_description: Connection description |
16258 |
-+ */ |
16259 |
-+struct kdbus_meta_conn { |
16260 |
-+ struct kref kref; |
16261 |
-+ struct mutex lock; |
16262 |
-+ u64 collected; |
16263 |
-+ u64 valid; |
16264 |
-+ |
16265 |
-+ /* KDBUS_ITEM_TIMESTAMP */ |
16266 |
-+ struct kdbus_timestamp ts; |
16267 |
-+ |
16268 |
-+ /* KDBUS_ITEM_OWNED_NAME */ |
16269 |
-+ struct kdbus_item *owned_names_items; |
16270 |
-+ size_t owned_names_size; |
16271 |
-+ |
16272 |
-+ /* KDBUS_ITEM_CONN_DESCRIPTION */ |
16273 |
-+ char *conn_description; |
16274 |
-+}; |
16275 |
-+ |
16276 |
-+/* fixed size equivalent of "kdbus_caps" */ |
16277 |
-+struct kdbus_meta_caps { |
16278 |
-+ u32 last_cap; |
16279 |
-+ struct { |
16280 |
-+ u32 caps[_KERNEL_CAPABILITY_U32S]; |
16281 |
-+ } set[4]; |
16282 |
-+}; |
16283 |
-+ |
16284 |
-+/** |
16285 |
-+ * kdbus_meta_proc_new() - Create process metadata object |
16286 |
-+ * |
16287 |
-+ * Return: Pointer to new object on success, ERR_PTR on failure. |
16288 |
-+ */ |
16289 |
-+struct kdbus_meta_proc *kdbus_meta_proc_new(void) |
16290 |
-+{ |
16291 |
-+ struct kdbus_meta_proc *mp; |
16292 |
-+ |
16293 |
-+ mp = kzalloc(sizeof(*mp), GFP_KERNEL); |
16294 |
-+ if (!mp) |
16295 |
-+ return ERR_PTR(-ENOMEM); |
16296 |
-+ |
16297 |
-+ kref_init(&mp->kref); |
16298 |
-+ mutex_init(&mp->lock); |
16299 |
-+ |
16300 |
-+ return mp; |
16301 |
-+} |
16302 |
-+ |
16303 |
-+static void kdbus_meta_proc_free(struct kref *kref) |
16304 |
-+{ |
16305 |
-+ struct kdbus_meta_proc *mp = container_of(kref, struct kdbus_meta_proc, |
16306 |
-+ kref); |
16307 |
-+ |
16308 |
-+ path_put(&mp->exe_path); |
16309 |
-+ path_put(&mp->root_path); |
16310 |
-+ if (mp->cred) |
16311 |
-+ put_cred(mp->cred); |
16312 |
-+ put_pid(mp->ppid); |
16313 |
-+ put_pid(mp->tgid); |
16314 |
-+ put_pid(mp->pid); |
16315 |
-+ |
16316 |
-+ kfree(mp->seclabel); |
16317 |
-+ kfree(mp->cmdline); |
16318 |
-+ kfree(mp->cgroup); |
16319 |
-+ kfree(mp); |
16320 |
-+} |
16321 |
-+ |
16322 |
-+/** |
16323 |
-+ * kdbus_meta_proc_ref() - Gain reference |
16324 |
-+ * @mp: Process metadata object |
16325 |
-+ * |
16326 |
-+ * Return: @mp is returned |
16327 |
-+ */ |
16328 |
-+struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp) |
16329 |
-+{ |
16330 |
-+ if (mp) |
16331 |
-+ kref_get(&mp->kref); |
16332 |
-+ return mp; |
16333 |
-+} |
16334 |
-+ |
16335 |
-+/** |
16336 |
-+ * kdbus_meta_proc_unref() - Drop reference |
16337 |
-+ * @mp: Process metadata object |
16338 |
-+ * |
16339 |
-+ * Return: NULL |
16340 |
-+ */ |
16341 |
-+struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp) |
16342 |
-+{ |
16343 |
-+ if (mp) |
16344 |
-+ kref_put(&mp->kref, kdbus_meta_proc_free); |
16345 |
-+ return NULL; |
16346 |
-+} |
16347 |
-+ |
16348 |
-+static void kdbus_meta_proc_collect_pids(struct kdbus_meta_proc *mp) |
16349 |
-+{ |
16350 |
-+ struct task_struct *parent; |
16351 |
-+ |
16352 |
-+ mp->pid = get_pid(task_pid(current)); |
16353 |
-+ mp->tgid = get_pid(task_tgid(current)); |
16354 |
-+ |
16355 |
-+ rcu_read_lock(); |
16356 |
-+ parent = rcu_dereference(current->real_parent); |
16357 |
-+ mp->ppid = get_pid(task_tgid(parent)); |
16358 |
-+ rcu_read_unlock(); |
16359 |
-+ |
16360 |
-+ mp->valid |= KDBUS_ATTACH_PIDS; |
16361 |
-+} |
16362 |
-+ |
16363 |
-+static void kdbus_meta_proc_collect_tid_comm(struct kdbus_meta_proc *mp) |
16364 |
-+{ |
16365 |
-+ get_task_comm(mp->tid_comm, current); |
16366 |
-+ mp->valid |= KDBUS_ATTACH_TID_COMM; |
16367 |
-+} |
16368 |
-+ |
16369 |
-+static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp) |
16370 |
-+{ |
16371 |
-+ get_task_comm(mp->pid_comm, current->group_leader); |
16372 |
-+ mp->valid |= KDBUS_ATTACH_PID_COMM; |
16373 |
-+} |
16374 |
-+ |
16375 |
-+static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp) |
16376 |
-+{ |
16377 |
-+ struct file *exe_file; |
16378 |
-+ |
16379 |
-+ rcu_read_lock(); |
16380 |
-+ exe_file = rcu_dereference(current->mm->exe_file); |
16381 |
-+ if (exe_file) { |
16382 |
-+ mp->exe_path = exe_file->f_path; |
16383 |
-+ path_get(&mp->exe_path); |
16384 |
-+ get_fs_root(current->fs, &mp->root_path); |
16385 |
-+ mp->valid |= KDBUS_ATTACH_EXE; |
16386 |
-+ } |
16387 |
-+ rcu_read_unlock(); |
16388 |
-+} |
16389 |
-+ |
16390 |
-+static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp) |
16391 |
-+{ |
16392 |
-+ struct mm_struct *mm = current->mm; |
16393 |
-+ char *cmdline; |
16394 |
-+ |
16395 |
-+ if (!mm->arg_end) |
16396 |
-+ return 0; |
16397 |
-+ |
16398 |
-+ cmdline = strndup_user((const char __user *)mm->arg_start, |
16399 |
-+ mm->arg_end - mm->arg_start); |
16400 |
-+ if (IS_ERR(cmdline)) |
16401 |
-+ return PTR_ERR(cmdline); |
16402 |
-+ |
16403 |
-+ mp->cmdline = cmdline; |
16404 |
-+ mp->valid |= KDBUS_ATTACH_CMDLINE; |
16405 |
-+ |
16406 |
-+ return 0; |
16407 |
-+} |
16408 |
-+ |
16409 |
-+static int kdbus_meta_proc_collect_cgroup(struct kdbus_meta_proc *mp) |
16410 |
-+{ |
16411 |
-+#ifdef CONFIG_CGROUPS |
16412 |
-+ void *page; |
16413 |
-+ char *s; |
16414 |
-+ |
16415 |
-+ page = (void *)__get_free_page(GFP_TEMPORARY); |
16416 |
-+ if (!page) |
16417 |
-+ return -ENOMEM; |
16418 |
-+ |
16419 |
-+ s = task_cgroup_path(current, page, PAGE_SIZE); |
16420 |
-+ if (s) { |
16421 |
-+ mp->cgroup = kstrdup(s, GFP_KERNEL); |
16422 |
-+ if (!mp->cgroup) { |
16423 |
-+ free_page((unsigned long)page); |
16424 |
-+ return -ENOMEM; |
16425 |
-+ } |
16426 |
-+ } |
16427 |
-+ |
16428 |
-+ free_page((unsigned long)page); |
16429 |
-+ mp->valid |= KDBUS_ATTACH_CGROUP; |
16430 |
-+#endif |
16431 |
-+ |
16432 |
-+ return 0; |
16433 |
-+} |
16434 |
-+ |
16435 |
-+static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp) |
16436 |
-+{ |
16437 |
-+#ifdef CONFIG_SECURITY |
16438 |
-+ char *ctx = NULL; |
16439 |
-+ u32 sid, len; |
16440 |
-+ int ret; |
16441 |
-+ |
16442 |
-+ security_task_getsecid(current, &sid); |
16443 |
-+ ret = security_secid_to_secctx(sid, &ctx, &len); |
16444 |
-+ if (ret < 0) { |
16445 |
-+ /* |
16446 |
-+ * EOPNOTSUPP means no security module is active, |
16447 |
-+ * lets skip adding the seclabel then. This effectively |
16448 |
-+ * drops the SECLABEL item. |
16449 |
-+ */ |
16450 |
-+ return (ret == -EOPNOTSUPP) ? 0 : ret; |
16451 |
-+ } |
16452 |
-+ |
16453 |
-+ mp->seclabel = kstrdup(ctx, GFP_KERNEL); |
16454 |
-+ security_release_secctx(ctx, len); |
16455 |
-+ if (!mp->seclabel) |
16456 |
-+ return -ENOMEM; |
16457 |
-+ |
16458 |
-+ mp->valid |= KDBUS_ATTACH_SECLABEL; |
16459 |
-+#endif |
16460 |
-+ |
16461 |
-+ return 0; |
16462 |
-+} |
16463 |
-+ |
16464 |
-+static void kdbus_meta_proc_collect_audit(struct kdbus_meta_proc *mp) |
16465 |
-+{ |
16466 |
-+#ifdef CONFIG_AUDITSYSCALL |
16467 |
-+ mp->audit_loginuid = audit_get_loginuid(current); |
16468 |
-+ mp->audit_sessionid = audit_get_sessionid(current); |
16469 |
-+ mp->valid |= KDBUS_ATTACH_AUDIT; |
16470 |
-+#endif |
16471 |
-+} |
16472 |
-+ |
16473 |
-+/** |
16474 |
-+ * kdbus_meta_proc_collect() - Collect process metadata |
16475 |
-+ * @mp: Process metadata object |
16476 |
-+ * @what: Attach flags to collect |
16477 |
-+ * |
16478 |
-+ * This collects process metadata from current and saves it in @mp. |
16479 |
-+ * |
16480 |
-+ * Return: 0 on success, negative error code on failure. |
16481 |
-+ */ |
16482 |
-+int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what) |
16483 |
-+{ |
16484 |
-+ int ret; |
16485 |
-+ |
16486 |
-+ if (!mp || !(what & (KDBUS_ATTACH_CREDS | |
16487 |
-+ KDBUS_ATTACH_PIDS | |
16488 |
-+ KDBUS_ATTACH_AUXGROUPS | |
16489 |
-+ KDBUS_ATTACH_TID_COMM | |
16490 |
-+ KDBUS_ATTACH_PID_COMM | |
16491 |
-+ KDBUS_ATTACH_EXE | |
16492 |
-+ KDBUS_ATTACH_CMDLINE | |
16493 |
-+ KDBUS_ATTACH_CGROUP | |
16494 |
-+ KDBUS_ATTACH_CAPS | |
16495 |
-+ KDBUS_ATTACH_SECLABEL | |
16496 |
-+ KDBUS_ATTACH_AUDIT))) |
16497 |
-+ return 0; |
16498 |
-+ |
16499 |
-+ mutex_lock(&mp->lock); |
16500 |
-+ |
16501 |
-+ /* creds, auxgrps and caps share "struct cred" as context */ |
16502 |
-+ { |
16503 |
-+ const u64 m_cred = KDBUS_ATTACH_CREDS | |
16504 |
-+ KDBUS_ATTACH_AUXGROUPS | |
16505 |
-+ KDBUS_ATTACH_CAPS; |
16506 |
-+ |
16507 |
-+ if ((what & m_cred) && !(mp->collected & m_cred)) { |
16508 |
-+ mp->cred = get_current_cred(); |
16509 |
-+ mp->valid |= m_cred; |
16510 |
-+ mp->collected |= m_cred; |
16511 |
-+ } |
16512 |
-+ } |
16513 |
-+ |
16514 |
-+ if ((what & KDBUS_ATTACH_PIDS) && |
16515 |
-+ !(mp->collected & KDBUS_ATTACH_PIDS)) { |
16516 |
-+ kdbus_meta_proc_collect_pids(mp); |
16517 |
-+ mp->collected |= KDBUS_ATTACH_PIDS; |
16518 |
-+ } |
16519 |
-+ |
16520 |
-+ if ((what & KDBUS_ATTACH_TID_COMM) && |
16521 |
-+ !(mp->collected & KDBUS_ATTACH_TID_COMM)) { |
16522 |
-+ kdbus_meta_proc_collect_tid_comm(mp); |
16523 |
-+ mp->collected |= KDBUS_ATTACH_TID_COMM; |
16524 |
-+ } |
16525 |
-+ |
16526 |
-+ if ((what & KDBUS_ATTACH_PID_COMM) && |
16527 |
-+ !(mp->collected & KDBUS_ATTACH_PID_COMM)) { |
16528 |
-+ kdbus_meta_proc_collect_pid_comm(mp); |
16529 |
-+ mp->collected |= KDBUS_ATTACH_PID_COMM; |
16530 |
-+ } |
16531 |
-+ |
16532 |
-+ if ((what & KDBUS_ATTACH_EXE) && |
16533 |
-+ !(mp->collected & KDBUS_ATTACH_EXE)) { |
16534 |
-+ kdbus_meta_proc_collect_exe(mp); |
16535 |
-+ mp->collected |= KDBUS_ATTACH_EXE; |
16536 |
-+ } |
16537 |
-+ |
16538 |
-+ if ((what & KDBUS_ATTACH_CMDLINE) && |
16539 |
-+ !(mp->collected & KDBUS_ATTACH_CMDLINE)) { |
16540 |
-+ ret = kdbus_meta_proc_collect_cmdline(mp); |
16541 |
-+ if (ret < 0) |
16542 |
-+ goto exit_unlock; |
16543 |
-+ mp->collected |= KDBUS_ATTACH_CMDLINE; |
16544 |
-+ } |
16545 |
-+ |
16546 |
-+ if ((what & KDBUS_ATTACH_CGROUP) && |
16547 |
-+ !(mp->collected & KDBUS_ATTACH_CGROUP)) { |
16548 |
-+ ret = kdbus_meta_proc_collect_cgroup(mp); |
16549 |
-+ if (ret < 0) |
16550 |
-+ goto exit_unlock; |
16551 |
-+ mp->collected |= KDBUS_ATTACH_CGROUP; |
16552 |
-+ } |
16553 |
-+ |
16554 |
-+ if ((what & KDBUS_ATTACH_SECLABEL) && |
16555 |
-+ !(mp->collected & KDBUS_ATTACH_SECLABEL)) { |
16556 |
-+ ret = kdbus_meta_proc_collect_seclabel(mp); |
16557 |
-+ if (ret < 0) |
16558 |
-+ goto exit_unlock; |
16559 |
-+ mp->collected |= KDBUS_ATTACH_SECLABEL; |
16560 |
-+ } |
16561 |
-+ |
16562 |
-+ if ((what & KDBUS_ATTACH_AUDIT) && |
16563 |
-+ !(mp->collected & KDBUS_ATTACH_AUDIT)) { |
16564 |
-+ kdbus_meta_proc_collect_audit(mp); |
16565 |
-+ mp->collected |= KDBUS_ATTACH_AUDIT; |
16566 |
-+ } |
16567 |
-+ |
16568 |
-+ ret = 0; |
16569 |
-+ |
16570 |
-+exit_unlock: |
16571 |
-+ mutex_unlock(&mp->lock); |
16572 |
-+ return ret; |
16573 |
-+} |
16574 |
-+ |
16575 |
-+/** |
16576 |
-+ * kdbus_meta_fake_new() - Create fake metadata object |
16577 |
-+ * |
16578 |
-+ * Return: Pointer to new object on success, ERR_PTR on failure. |
16579 |
-+ */ |
16580 |
-+struct kdbus_meta_fake *kdbus_meta_fake_new(void) |
16581 |
-+{ |
16582 |
-+ struct kdbus_meta_fake *mf; |
16583 |
-+ |
16584 |
-+ mf = kzalloc(sizeof(*mf), GFP_KERNEL); |
16585 |
-+ if (!mf) |
16586 |
-+ return ERR_PTR(-ENOMEM); |
16587 |
-+ |
16588 |
-+ return mf; |
16589 |
-+} |
16590 |
-+ |
16591 |
-+/** |
16592 |
-+ * kdbus_meta_fake_free() - Free fake metadata object |
16593 |
-+ * @mf: Fake metadata object |
16594 |
-+ * |
16595 |
-+ * Return: NULL |
16596 |
-+ */ |
16597 |
-+struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf) |
16598 |
-+{ |
16599 |
-+ if (mf) { |
16600 |
-+ put_pid(mf->ppid); |
16601 |
-+ put_pid(mf->tgid); |
16602 |
-+ put_pid(mf->pid); |
16603 |
-+ kfree(mf->seclabel); |
16604 |
-+ kfree(mf); |
16605 |
-+ } |
16606 |
-+ |
16607 |
-+ return NULL; |
16608 |
-+} |
16609 |
-+ |
16610 |
-+/** |
16611 |
-+ * kdbus_meta_fake_collect() - Fill fake metadata from faked credentials |
16612 |
-+ * @mf: Fake metadata object |
16613 |
-+ * @creds: Creds to set, may be %NULL |
16614 |
-+ * @pids: PIDs to set, may be %NULL |
16615 |
-+ * @seclabel: Seclabel to set, may be %NULL |
16616 |
-+ * |
16617 |
-+ * This function takes information stored in @creds, @pids and @seclabel and |
16618 |
-+ * resolves them to kernel-representations, if possible. This call uses the |
16619 |
-+ * current task's namespaces to resolve the given information. |
16620 |
-+ * |
16621 |
-+ * Return: 0 on success, negative error code on failure. |
16622 |
-+ */ |
16623 |
-+int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf, |
16624 |
-+ const struct kdbus_creds *creds, |
16625 |
-+ const struct kdbus_pids *pids, |
16626 |
-+ const char *seclabel) |
16627 |
-+{ |
16628 |
-+ if (mf->valid) |
16629 |
-+ return -EALREADY; |
16630 |
-+ |
16631 |
-+ if (creds) { |
16632 |
-+ struct user_namespace *ns = current_user_ns(); |
16633 |
-+ |
16634 |
-+ mf->uid = make_kuid(ns, creds->uid); |
16635 |
-+ mf->euid = make_kuid(ns, creds->euid); |
16636 |
-+ mf->suid = make_kuid(ns, creds->suid); |
16637 |
-+ mf->fsuid = make_kuid(ns, creds->fsuid); |
16638 |
-+ |
16639 |
-+ mf->gid = make_kgid(ns, creds->gid); |
16640 |
-+ mf->egid = make_kgid(ns, creds->egid); |
16641 |
-+ mf->sgid = make_kgid(ns, creds->sgid); |
16642 |
-+ mf->fsgid = make_kgid(ns, creds->fsgid); |
16643 |
-+ |
16644 |
-+ if ((creds->uid != (uid_t)-1 && !uid_valid(mf->uid)) || |
16645 |
-+ (creds->euid != (uid_t)-1 && !uid_valid(mf->euid)) || |
16646 |
-+ (creds->suid != (uid_t)-1 && !uid_valid(mf->suid)) || |
16647 |
-+ (creds->fsuid != (uid_t)-1 && !uid_valid(mf->fsuid)) || |
16648 |
-+ (creds->gid != (gid_t)-1 && !gid_valid(mf->gid)) || |
16649 |
-+ (creds->egid != (gid_t)-1 && !gid_valid(mf->egid)) || |
16650 |
-+ (creds->sgid != (gid_t)-1 && !gid_valid(mf->sgid)) || |
16651 |
-+ (creds->fsgid != (gid_t)-1 && !gid_valid(mf->fsgid))) |
16652 |
-+ return -EINVAL; |
16653 |
-+ |
16654 |
-+ mf->valid |= KDBUS_ATTACH_CREDS; |
16655 |
-+ } |
16656 |
-+ |
16657 |
-+ if (pids) { |
16658 |
-+ mf->pid = get_pid(find_vpid(pids->tid)); |
16659 |
-+ mf->tgid = get_pid(find_vpid(pids->pid)); |
16660 |
-+ mf->ppid = get_pid(find_vpid(pids->ppid)); |
16661 |
-+ |
16662 |
-+ if ((pids->tid != 0 && !mf->pid) || |
16663 |
-+ (pids->pid != 0 && !mf->tgid) || |
16664 |
-+ (pids->ppid != 0 && !mf->ppid)) { |
16665 |
-+ put_pid(mf->pid); |
16666 |
-+ put_pid(mf->tgid); |
16667 |
-+ put_pid(mf->ppid); |
16668 |
-+ mf->pid = NULL; |
16669 |
-+ mf->tgid = NULL; |
16670 |
-+ mf->ppid = NULL; |
16671 |
-+ return -EINVAL; |
16672 |
-+ } |
16673 |
-+ |
16674 |
-+ mf->valid |= KDBUS_ATTACH_PIDS; |
16675 |
-+ } |
16676 |
-+ |
16677 |
-+ if (seclabel) { |
16678 |
-+ mf->seclabel = kstrdup(seclabel, GFP_KERNEL); |
16679 |
-+ if (!mf->seclabel) |
16680 |
-+ return -ENOMEM; |
16681 |
-+ |
16682 |
-+ mf->valid |= KDBUS_ATTACH_SECLABEL; |
16683 |
-+ } |
16684 |
-+ |
16685 |
-+ return 0; |
16686 |
-+} |
16687 |
-+ |
16688 |
-+/** |
16689 |
-+ * kdbus_meta_conn_new() - Create connection metadata object |
16690 |
-+ * |
16691 |
-+ * Return: Pointer to new object on success, ERR_PTR on failure. |
16692 |
-+ */ |
16693 |
-+struct kdbus_meta_conn *kdbus_meta_conn_new(void) |
16694 |
-+{ |
16695 |
-+ struct kdbus_meta_conn *mc; |
16696 |
-+ |
16697 |
-+ mc = kzalloc(sizeof(*mc), GFP_KERNEL); |
16698 |
-+ if (!mc) |
16699 |
-+ return ERR_PTR(-ENOMEM); |
16700 |
-+ |
16701 |
-+ kref_init(&mc->kref); |
16702 |
-+ mutex_init(&mc->lock); |
16703 |
-+ |
16704 |
-+ return mc; |
16705 |
-+} |
16706 |
-+ |
16707 |
-+static void kdbus_meta_conn_free(struct kref *kref) |
16708 |
-+{ |
16709 |
-+ struct kdbus_meta_conn *mc = |
16710 |
-+ container_of(kref, struct kdbus_meta_conn, kref); |
16711 |
-+ |
16712 |
-+ kfree(mc->conn_description); |
16713 |
-+ kfree(mc->owned_names_items); |
16714 |
-+ kfree(mc); |
16715 |
-+} |
16716 |
-+ |
16717 |
-+/** |
16718 |
-+ * kdbus_meta_conn_ref() - Gain reference |
16719 |
-+ * @mc: Connection metadata object |
16720 |
-+ */ |
16721 |
-+struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc) |
16722 |
-+{ |
16723 |
-+ if (mc) |
16724 |
-+ kref_get(&mc->kref); |
16725 |
-+ return mc; |
16726 |
-+} |
16727 |
-+ |
16728 |
-+/** |
16729 |
-+ * kdbus_meta_conn_unref() - Drop reference |
16730 |
-+ * @mc: Connection metadata object |
16731 |
-+ */ |
16732 |
-+struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc) |
16733 |
-+{ |
16734 |
-+ if (mc) |
16735 |
-+ kref_put(&mc->kref, kdbus_meta_conn_free); |
16736 |
-+ return NULL; |
16737 |
-+} |
16738 |
-+ |
16739 |
-+static void kdbus_meta_conn_collect_timestamp(struct kdbus_meta_conn *mc, |
16740 |
-+ u64 msg_seqnum) |
16741 |
-+{ |
16742 |
-+ mc->ts.monotonic_ns = ktime_get_ns(); |
16743 |
-+ mc->ts.realtime_ns = ktime_get_real_ns(); |
16744 |
-+ |
16745 |
-+ if (msg_seqnum) |
16746 |
-+ mc->ts.seqnum = msg_seqnum; |
16747 |
-+ |
16748 |
-+ mc->valid |= KDBUS_ATTACH_TIMESTAMP; |
16749 |
-+} |
16750 |
-+ |
16751 |
-+static int kdbus_meta_conn_collect_names(struct kdbus_meta_conn *mc, |
16752 |
-+ struct kdbus_conn *conn) |
16753 |
-+{ |
16754 |
-+ const struct kdbus_name_owner *owner; |
16755 |
-+ struct kdbus_item *item; |
16756 |
-+ size_t slen, size; |
16757 |
-+ |
16758 |
-+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
16759 |
-+ |
16760 |
-+ size = 0; |
16761 |
-+ /* open-code length calculation to avoid final padding */ |
16762 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) |
16763 |
-+ if (!(owner->flags & KDBUS_NAME_IN_QUEUE)) |
16764 |
-+ size = KDBUS_ALIGN8(size) + KDBUS_ITEM_HEADER_SIZE + |
16765 |
-+ sizeof(struct kdbus_name) + |
16766 |
-+ strlen(owner->name->name) + 1; |
16767 |
-+ |
16768 |
-+ if (!size) |
16769 |
-+ return 0; |
16770 |
-+ |
16771 |
-+ /* make sure we include zeroed padding for convenience helpers */ |
16772 |
-+ item = kmalloc(KDBUS_ALIGN8(size), GFP_KERNEL); |
16773 |
-+ if (!item) |
16774 |
-+ return -ENOMEM; |
16775 |
-+ |
16776 |
-+ mc->owned_names_items = item; |
16777 |
-+ mc->owned_names_size = size; |
16778 |
-+ |
16779 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) { |
16780 |
-+ if (owner->flags & KDBUS_NAME_IN_QUEUE) |
16781 |
-+ continue; |
16782 |
-+ |
16783 |
-+ slen = strlen(owner->name->name) + 1; |
16784 |
-+ kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL, |
16785 |
-+ sizeof(struct kdbus_name) + slen); |
16786 |
-+ item->name.flags = owner->flags; |
16787 |
-+ memcpy(item->name.name, owner->name->name, slen); |
16788 |
-+ item = KDBUS_ITEM_NEXT(item); |
16789 |
-+ } |
16790 |
-+ |
16791 |
-+ /* sanity check: the buffer should be completely written now */ |
16792 |
-+ WARN_ON((u8 *)item != |
16793 |
-+ (u8 *)mc->owned_names_items + KDBUS_ALIGN8(size)); |
16794 |
-+ |
16795 |
-+ mc->valid |= KDBUS_ATTACH_NAMES; |
16796 |
-+ return 0; |
16797 |
-+} |
16798 |
-+ |
16799 |
-+static int kdbus_meta_conn_collect_description(struct kdbus_meta_conn *mc, |
16800 |
-+ struct kdbus_conn *conn) |
16801 |
-+{ |
16802 |
-+ if (!conn->description) |
16803 |
-+ return 0; |
16804 |
-+ |
16805 |
-+ mc->conn_description = kstrdup(conn->description, GFP_KERNEL); |
16806 |
-+ if (!mc->conn_description) |
16807 |
-+ return -ENOMEM; |
16808 |
-+ |
16809 |
-+ mc->valid |= KDBUS_ATTACH_CONN_DESCRIPTION; |
16810 |
-+ return 0; |
16811 |
-+} |
16812 |
-+ |
16813 |
-+/** |
16814 |
-+ * kdbus_meta_conn_collect() - Collect connection metadata |
16815 |
-+ * @mc: Message metadata object |
16816 |
-+ * @conn: Connection to collect data from |
16817 |
-+ * @msg_seqnum: Sequence number of the message to send |
16818 |
-+ * @what: Attach flags to collect |
16819 |
-+ * |
16820 |
-+ * This collects connection metadata from @msg_seqnum and @conn and saves it |
16821 |
-+ * in @mc. |
16822 |
-+ * |
16823 |
-+ * If KDBUS_ATTACH_NAMES is set in @what and @conn is non-NULL, the caller must |
16824 |
-+ * hold the name-registry read-lock of conn->ep->bus->registry. |
16825 |
-+ * |
16826 |
-+ * Return: 0 on success, negative error code on failure. |
16827 |
-+ */ |
16828 |
-+int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, |
16829 |
-+ struct kdbus_conn *conn, |
16830 |
-+ u64 msg_seqnum, u64 what) |
16831 |
-+{ |
16832 |
-+ int ret; |
16833 |
-+ |
16834 |
-+ if (!mc || !(what & (KDBUS_ATTACH_TIMESTAMP | |
16835 |
-+ KDBUS_ATTACH_NAMES | |
16836 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION))) |
16837 |
-+ return 0; |
16838 |
-+ |
16839 |
-+ mutex_lock(&mc->lock); |
16840 |
-+ |
16841 |
-+ if (msg_seqnum && (what & KDBUS_ATTACH_TIMESTAMP) && |
16842 |
-+ !(mc->collected & KDBUS_ATTACH_TIMESTAMP)) { |
16843 |
-+ kdbus_meta_conn_collect_timestamp(mc, msg_seqnum); |
16844 |
-+ mc->collected |= KDBUS_ATTACH_TIMESTAMP; |
16845 |
-+ } |
16846 |
-+ |
16847 |
-+ if (conn && (what & KDBUS_ATTACH_NAMES) && |
16848 |
-+ !(mc->collected & KDBUS_ATTACH_NAMES)) { |
16849 |
-+ ret = kdbus_meta_conn_collect_names(mc, conn); |
16850 |
-+ if (ret < 0) |
16851 |
-+ goto exit_unlock; |
16852 |
-+ mc->collected |= KDBUS_ATTACH_NAMES; |
16853 |
-+ } |
16854 |
-+ |
16855 |
-+ if (conn && (what & KDBUS_ATTACH_CONN_DESCRIPTION) && |
16856 |
-+ !(mc->collected & KDBUS_ATTACH_CONN_DESCRIPTION)) { |
16857 |
-+ ret = kdbus_meta_conn_collect_description(mc, conn); |
16858 |
-+ if (ret < 0) |
16859 |
-+ goto exit_unlock; |
16860 |
-+ mc->collected |= KDBUS_ATTACH_CONN_DESCRIPTION; |
16861 |
-+ } |
16862 |
-+ |
16863 |
-+ ret = 0; |
16864 |
-+ |
16865 |
-+exit_unlock: |
16866 |
-+ mutex_unlock(&mc->lock); |
16867 |
-+ return ret; |
16868 |
-+} |
16869 |
-+ |
16870 |
-+static void kdbus_meta_export_caps(struct kdbus_meta_caps *out, |
16871 |
-+ const struct kdbus_meta_proc *mp, |
16872 |
-+ struct user_namespace *user_ns) |
16873 |
-+{ |
16874 |
-+ struct user_namespace *iter; |
16875 |
-+ const struct cred *cred = mp->cred; |
16876 |
-+ bool parent = false, owner = false; |
16877 |
-+ int i; |
16878 |
-+ |
16879 |
-+ /* |
16880 |
-+ * This translates the effective capabilities of 'cred' into the given |
16881 |
-+ * user-namespace. If the given user-namespace is a child-namespace of |
16882 |
-+ * the user-namespace of 'cred', the mask can be copied verbatim. If |
16883 |
-+ * not, the mask is cleared. |
16884 |
-+ * There's one exception: If 'cred' is the owner of any user-namespace |
16885 |
-+ * in the path between the given user-namespace and the user-namespace |
16886 |
-+ * of 'cred', then it has all effective capabilities set. This means, |
16887 |
-+ * the user who created a user-namespace always has all effective |
16888 |
-+ * capabilities in any child namespaces. Note that this is based on the |
16889 |
-+ * uid of the namespace creator, not the task hierarchy. |
16890 |
-+ */ |
16891 |
-+ for (iter = user_ns; iter; iter = iter->parent) { |
16892 |
-+ if (iter == cred->user_ns) { |
16893 |
-+ parent = true; |
16894 |
-+ break; |
16895 |
-+ } |
16896 |
-+ |
16897 |
-+ if (iter == &init_user_ns) |
16898 |
-+ break; |
16899 |
-+ |
16900 |
-+ if ((iter->parent == cred->user_ns) && |
16901 |
-+ uid_eq(iter->owner, cred->euid)) { |
16902 |
-+ owner = true; |
16903 |
-+ break; |
16904 |
-+ } |
16905 |
-+ } |
16906 |
-+ |
16907 |
-+ out->last_cap = CAP_LAST_CAP; |
16908 |
-+ |
16909 |
-+ CAP_FOR_EACH_U32(i) { |
16910 |
-+ if (parent) { |
16911 |
-+ out->set[0].caps[i] = cred->cap_inheritable.cap[i]; |
16912 |
-+ out->set[1].caps[i] = cred->cap_permitted.cap[i]; |
16913 |
-+ out->set[2].caps[i] = cred->cap_effective.cap[i]; |
16914 |
-+ out->set[3].caps[i] = cred->cap_bset.cap[i]; |
16915 |
-+ } else if (owner) { |
16916 |
-+ out->set[0].caps[i] = 0U; |
16917 |
-+ out->set[1].caps[i] = ~0U; |
16918 |
-+ out->set[2].caps[i] = ~0U; |
16919 |
-+ out->set[3].caps[i] = ~0U; |
16920 |
-+ } else { |
16921 |
-+ out->set[0].caps[i] = 0U; |
16922 |
-+ out->set[1].caps[i] = 0U; |
16923 |
-+ out->set[2].caps[i] = 0U; |
16924 |
-+ out->set[3].caps[i] = 0U; |
16925 |
-+ } |
16926 |
-+ } |
16927 |
-+ |
16928 |
-+ /* clear unused bits */ |
16929 |
-+ for (i = 0; i < 4; i++) |
16930 |
-+ out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &= |
16931 |
-+ CAP_LAST_U32_VALID_MASK; |
16932 |
-+} |
16933 |
-+ |
16934 |
-+/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */ |
16935 |
-+static uid_t kdbus_from_kuid_keep(struct user_namespace *ns, kuid_t uid) |
16936 |
-+{ |
16937 |
-+ return uid_valid(uid) ? from_kuid_munged(ns, uid) : ((uid_t)-1); |
16938 |
-+} |
16939 |
-+ |
16940 |
-+/* This is equivalent to from_kgid_munged(), but maps INVALID_GID to itself */ |
16941 |
-+static gid_t kdbus_from_kgid_keep(struct user_namespace *ns, kgid_t gid) |
16942 |
-+{ |
16943 |
-+ return gid_valid(gid) ? from_kgid_munged(ns, gid) : ((gid_t)-1); |
16944 |
-+} |
16945 |
-+ |
16946 |
-+struct kdbus_meta_staging { |
16947 |
-+ const struct kdbus_meta_proc *mp; |
16948 |
-+ const struct kdbus_meta_fake *mf; |
16949 |
-+ const struct kdbus_meta_conn *mc; |
16950 |
-+ const struct kdbus_conn *conn; |
16951 |
-+ u64 mask; |
16952 |
-+ |
16953 |
-+ void *exe; |
16954 |
-+ const char *exe_path; |
16955 |
-+}; |
16956 |
-+ |
16957 |
-+static size_t kdbus_meta_measure(struct kdbus_meta_staging *staging) |
16958 |
-+{ |
16959 |
-+ const struct kdbus_meta_proc *mp = staging->mp; |
16960 |
-+ const struct kdbus_meta_fake *mf = staging->mf; |
16961 |
-+ const struct kdbus_meta_conn *mc = staging->mc; |
16962 |
-+ const u64 mask = staging->mask; |
16963 |
-+ size_t size = 0; |
16964 |
-+ |
16965 |
-+ /* process metadata */ |
16966 |
-+ |
16967 |
-+ if (mf && (mask & KDBUS_ATTACH_CREDS)) |
16968 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds)); |
16969 |
-+ else if (mp && (mask & KDBUS_ATTACH_CREDS)) |
16970 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds)); |
16971 |
-+ |
16972 |
-+ if (mf && (mask & KDBUS_ATTACH_PIDS)) |
16973 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids)); |
16974 |
-+ else if (mp && (mask & KDBUS_ATTACH_PIDS)) |
16975 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids)); |
16976 |
-+ |
16977 |
-+ if (mp && (mask & KDBUS_ATTACH_AUXGROUPS)) |
16978 |
-+ size += KDBUS_ITEM_SIZE(mp->cred->group_info->ngroups * |
16979 |
-+ sizeof(u64)); |
16980 |
-+ |
16981 |
-+ if (mp && (mask & KDBUS_ATTACH_TID_COMM)) |
16982 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->tid_comm) + 1); |
16983 |
-+ |
16984 |
-+ if (mp && (mask & KDBUS_ATTACH_PID_COMM)) |
16985 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->pid_comm) + 1); |
16986 |
-+ |
16987 |
-+ if (staging->exe_path && (mask & KDBUS_ATTACH_EXE)) |
16988 |
-+ size += KDBUS_ITEM_SIZE(strlen(staging->exe_path) + 1); |
16989 |
-+ |
16990 |
-+ if (mp && (mask & KDBUS_ATTACH_CMDLINE)) |
16991 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->cmdline) + 1); |
16992 |
-+ |
16993 |
-+ if (mp && (mask & KDBUS_ATTACH_CGROUP)) |
16994 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1); |
16995 |
-+ |
16996 |
-+ if (mp && (mask & KDBUS_ATTACH_CAPS)) |
16997 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps)); |
16998 |
-+ |
16999 |
-+ if (mf && (mask & KDBUS_ATTACH_SECLABEL)) |
17000 |
-+ size += KDBUS_ITEM_SIZE(strlen(mf->seclabel) + 1); |
17001 |
-+ else if (mp && (mask & KDBUS_ATTACH_SECLABEL)) |
17002 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1); |
17003 |
-+ |
17004 |
-+ if (mp && (mask & KDBUS_ATTACH_AUDIT)) |
17005 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit)); |
17006 |
-+ |
17007 |
-+ /* connection metadata */ |
17008 |
-+ |
17009 |
-+ if (mc && (mask & KDBUS_ATTACH_NAMES)) |
17010 |
-+ size += KDBUS_ALIGN8(mc->owned_names_size); |
17011 |
-+ |
17012 |
-+ if (mc && (mask & KDBUS_ATTACH_CONN_DESCRIPTION)) |
17013 |
-+ size += KDBUS_ITEM_SIZE(strlen(mc->conn_description) + 1); |
17014 |
-+ |
17015 |
-+ if (mc && (mask & KDBUS_ATTACH_TIMESTAMP)) |
17016 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_timestamp)); |
17017 |
-+ |
17018 |
-+ return size; |
17019 |
-+} |
17020 |
-+ |
17021 |
-+static struct kdbus_item *kdbus_write_head(struct kdbus_item **iter, |
17022 |
-+ u64 type, u64 size) |
17023 |
-+{ |
17024 |
-+ struct kdbus_item *item = *iter; |
17025 |
-+ size_t padding; |
17026 |
-+ |
17027 |
-+ item->type = type; |
17028 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + size; |
17029 |
-+ |
17030 |
-+ /* clear padding */ |
17031 |
-+ padding = KDBUS_ALIGN8(item->size) - item->size; |
17032 |
-+ if (padding) |
17033 |
-+ memset(item->data + size, 0, padding); |
17034 |
-+ |
17035 |
-+ *iter = KDBUS_ITEM_NEXT(item); |
17036 |
-+ return item; |
17037 |
-+} |
17038 |
-+ |
17039 |
-+static struct kdbus_item *kdbus_write_full(struct kdbus_item **iter, |
17040 |
-+ u64 type, u64 size, const void *data) |
17041 |
-+{ |
17042 |
-+ struct kdbus_item *item; |
17043 |
-+ |
17044 |
-+ item = kdbus_write_head(iter, type, size); |
17045 |
-+ memcpy(item->data, data, size); |
17046 |
-+ return item; |
17047 |
-+} |
17048 |
-+ |
17049 |
-+static size_t kdbus_meta_write(struct kdbus_meta_staging *staging, void *mem, |
17050 |
-+ size_t size) |
17051 |
-+{ |
17052 |
-+ struct user_namespace *user_ns = staging->conn->cred->user_ns; |
17053 |
-+ struct pid_namespace *pid_ns = ns_of_pid(staging->conn->pid); |
17054 |
-+ struct kdbus_item *item = NULL, *items = mem; |
17055 |
-+ u8 *end, *owned_names_end = NULL; |
17056 |
-+ |
17057 |
-+ /* process metadata */ |
17058 |
-+ |
17059 |
-+ if (staging->mf && (staging->mask & KDBUS_ATTACH_CREDS)) { |
17060 |
-+ const struct kdbus_meta_fake *mf = staging->mf; |
17061 |
-+ |
17062 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_CREDS, |
17063 |
-+ sizeof(struct kdbus_creds)); |
17064 |
-+ item->creds = (struct kdbus_creds){ |
17065 |
-+ .uid = kdbus_from_kuid_keep(user_ns, mf->uid), |
17066 |
-+ .euid = kdbus_from_kuid_keep(user_ns, mf->euid), |
17067 |
-+ .suid = kdbus_from_kuid_keep(user_ns, mf->suid), |
17068 |
-+ .fsuid = kdbus_from_kuid_keep(user_ns, mf->fsuid), |
17069 |
-+ .gid = kdbus_from_kgid_keep(user_ns, mf->gid), |
17070 |
-+ .egid = kdbus_from_kgid_keep(user_ns, mf->egid), |
17071 |
-+ .sgid = kdbus_from_kgid_keep(user_ns, mf->sgid), |
17072 |
-+ .fsgid = kdbus_from_kgid_keep(user_ns, mf->fsgid), |
17073 |
-+ }; |
17074 |
-+ } else if (staging->mp && (staging->mask & KDBUS_ATTACH_CREDS)) { |
17075 |
-+ const struct cred *c = staging->mp->cred; |
17076 |
-+ |
17077 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_CREDS, |
17078 |
-+ sizeof(struct kdbus_creds)); |
17079 |
-+ item->creds = (struct kdbus_creds){ |
17080 |
-+ .uid = kdbus_from_kuid_keep(user_ns, c->uid), |
17081 |
-+ .euid = kdbus_from_kuid_keep(user_ns, c->euid), |
17082 |
-+ .suid = kdbus_from_kuid_keep(user_ns, c->suid), |
17083 |
-+ .fsuid = kdbus_from_kuid_keep(user_ns, c->fsuid), |
17084 |
-+ .gid = kdbus_from_kgid_keep(user_ns, c->gid), |
17085 |
-+ .egid = kdbus_from_kgid_keep(user_ns, c->egid), |
17086 |
-+ .sgid = kdbus_from_kgid_keep(user_ns, c->sgid), |
17087 |
-+ .fsgid = kdbus_from_kgid_keep(user_ns, c->fsgid), |
17088 |
-+ }; |
17089 |
-+ } |
17090 |
-+ |
17091 |
-+ if (staging->mf && (staging->mask & KDBUS_ATTACH_PIDS)) { |
17092 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_PIDS, |
17093 |
-+ sizeof(struct kdbus_pids)); |
17094 |
-+ item->pids = (struct kdbus_pids){ |
17095 |
-+ .pid = pid_nr_ns(staging->mf->tgid, pid_ns), |
17096 |
-+ .tid = pid_nr_ns(staging->mf->pid, pid_ns), |
17097 |
-+ .ppid = pid_nr_ns(staging->mf->ppid, pid_ns), |
17098 |
-+ }; |
17099 |
-+ } else if (staging->mp && (staging->mask & KDBUS_ATTACH_PIDS)) { |
17100 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_PIDS, |
17101 |
-+ sizeof(struct kdbus_pids)); |
17102 |
-+ item->pids = (struct kdbus_pids){ |
17103 |
-+ .pid = pid_nr_ns(staging->mp->tgid, pid_ns), |
17104 |
-+ .tid = pid_nr_ns(staging->mp->pid, pid_ns), |
17105 |
-+ .ppid = pid_nr_ns(staging->mp->ppid, pid_ns), |
17106 |
-+ }; |
17107 |
-+ } |
17108 |
-+ |
17109 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_AUXGROUPS)) { |
17110 |
-+ const struct group_info *info = staging->mp->cred->group_info; |
17111 |
-+ size_t i; |
17112 |
-+ |
17113 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_AUXGROUPS, |
17114 |
-+ info->ngroups * sizeof(u64)); |
17115 |
-+ for (i = 0; i < info->ngroups; ++i) |
17116 |
-+ item->data64[i] = from_kgid_munged(user_ns, |
17117 |
-+ GROUP_AT(info, i)); |
17118 |
-+ } |
17119 |
-+ |
17120 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_TID_COMM)) |
17121 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_TID_COMM, |
17122 |
-+ strlen(staging->mp->tid_comm) + 1, |
17123 |
-+ staging->mp->tid_comm); |
17124 |
-+ |
17125 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_PID_COMM)) |
17126 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_PID_COMM, |
17127 |
-+ strlen(staging->mp->pid_comm) + 1, |
17128 |
-+ staging->mp->pid_comm); |
17129 |
-+ |
17130 |
-+ if (staging->exe_path && (staging->mask & KDBUS_ATTACH_EXE)) |
17131 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_EXE, |
17132 |
-+ strlen(staging->exe_path) + 1, |
17133 |
-+ staging->exe_path); |
17134 |
-+ |
17135 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_CMDLINE)) |
17136 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_CMDLINE, |
17137 |
-+ strlen(staging->mp->cmdline) + 1, |
17138 |
-+ staging->mp->cmdline); |
17139 |
-+ |
17140 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_CGROUP)) |
17141 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_CGROUP, |
17142 |
-+ strlen(staging->mp->cgroup) + 1, |
17143 |
-+ staging->mp->cgroup); |
17144 |
-+ |
17145 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_CAPS)) { |
17146 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_CAPS, |
17147 |
-+ sizeof(struct kdbus_meta_caps)); |
17148 |
-+ kdbus_meta_export_caps((void*)&item->caps, staging->mp, |
17149 |
-+ user_ns); |
17150 |
-+ } |
17151 |
-+ |
17152 |
-+ if (staging->mf && (staging->mask & KDBUS_ATTACH_SECLABEL)) |
17153 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL, |
17154 |
-+ strlen(staging->mf->seclabel) + 1, |
17155 |
-+ staging->mf->seclabel); |
17156 |
-+ else if (staging->mp && (staging->mask & KDBUS_ATTACH_SECLABEL)) |
17157 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL, |
17158 |
-+ strlen(staging->mp->seclabel) + 1, |
17159 |
-+ staging->mp->seclabel); |
17160 |
-+ |
17161 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_AUDIT)) { |
17162 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_AUDIT, |
17163 |
-+ sizeof(struct kdbus_audit)); |
17164 |
-+ item->audit = (struct kdbus_audit){ |
17165 |
-+ .loginuid = from_kuid(user_ns, |
17166 |
-+ staging->mp->audit_loginuid), |
17167 |
-+ .sessionid = staging->mp->audit_sessionid, |
17168 |
-+ }; |
17169 |
-+ } |
17170 |
-+ |
17171 |
-+ /* connection metadata */ |
17172 |
-+ |
17173 |
-+ if (staging->mc && (staging->mask & KDBUS_ATTACH_NAMES)) { |
17174 |
-+ memcpy(items, staging->mc->owned_names_items, |
17175 |
-+ KDBUS_ALIGN8(staging->mc->owned_names_size)); |
17176 |
-+ owned_names_end = (u8 *)items + staging->mc->owned_names_size; |
17177 |
-+ items = (void *)KDBUS_ALIGN8((unsigned long)owned_names_end); |
17178 |
-+ } |
17179 |
-+ |
17180 |
-+ if (staging->mc && (staging->mask & KDBUS_ATTACH_CONN_DESCRIPTION)) |
17181 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_CONN_DESCRIPTION, |
17182 |
-+ strlen(staging->mc->conn_description) + 1, |
17183 |
-+ staging->mc->conn_description); |
17184 |
-+ |
17185 |
-+ if (staging->mc && (staging->mask & KDBUS_ATTACH_TIMESTAMP)) |
17186 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_TIMESTAMP, |
17187 |
-+ sizeof(staging->mc->ts), |
17188 |
-+ &staging->mc->ts); |
17189 |
-+ |
17190 |
-+ /* |
17191 |
-+ * Return real size (minus trailing padding). In case of 'owned_names' |
17192 |
-+ * we cannot deduce it from item->size, so treat it special. |
17193 |
-+ */ |
17194 |
-+ |
17195 |
-+ if (items == (void *)KDBUS_ALIGN8((unsigned long)owned_names_end)) |
17196 |
-+ end = owned_names_end; |
17197 |
-+ else if (item) |
17198 |
-+ end = (u8 *)item + item->size; |
17199 |
-+ else |
17200 |
-+ end = mem; |
17201 |
-+ |
17202 |
-+ WARN_ON((u8 *)items - (u8 *)mem != size); |
17203 |
-+ WARN_ON((void *)KDBUS_ALIGN8((unsigned long)end) != (void *)items); |
17204 |
-+ |
17205 |
-+ return end - (u8 *)mem; |
17206 |
-+} |
17207 |
-+ |
17208 |
-+int kdbus_meta_emit(struct kdbus_meta_proc *mp, |
17209 |
-+ struct kdbus_meta_fake *mf, |
17210 |
-+ struct kdbus_meta_conn *mc, |
17211 |
-+ struct kdbus_conn *conn, |
17212 |
-+ u64 mask, |
17213 |
-+ struct kdbus_item **out_items, |
17214 |
-+ size_t *out_size) |
17215 |
-+{ |
17216 |
-+ struct kdbus_meta_staging staging = {}; |
17217 |
-+ struct kdbus_item *items = NULL; |
17218 |
-+ size_t size = 0; |
17219 |
-+ int ret; |
17220 |
-+ |
17221 |
-+ if (WARN_ON(mf && mp)) |
17222 |
-+ mp = NULL; |
17223 |
-+ |
17224 |
-+ staging.mp = mp; |
17225 |
-+ staging.mf = mf; |
17226 |
-+ staging.mc = mc; |
17227 |
-+ staging.conn = conn; |
17228 |
-+ |
17229 |
-+ /* get mask of valid items */ |
17230 |
-+ if (mf) |
17231 |
-+ staging.mask |= mf->valid; |
17232 |
-+ if (mp) { |
17233 |
-+ mutex_lock(&mp->lock); |
17234 |
-+ staging.mask |= mp->valid; |
17235 |
-+ mutex_unlock(&mp->lock); |
17236 |
-+ } |
17237 |
-+ if (mc) { |
17238 |
-+ mutex_lock(&mc->lock); |
17239 |
-+ staging.mask |= mc->valid; |
17240 |
-+ mutex_unlock(&mc->lock); |
17241 |
-+ } |
17242 |
-+ |
17243 |
-+ staging.mask &= mask; |
17244 |
-+ |
17245 |
-+ if (!staging.mask) { /* bail out if nothing to do */ |
17246 |
-+ ret = 0; |
17247 |
-+ goto exit; |
17248 |
-+ } |
17249 |
-+ |
17250 |
-+ /* EXE is special as it needs a temporary page to assemble */ |
17251 |
-+ if (mp && (staging.mask & KDBUS_ATTACH_EXE)) { |
17252 |
-+ struct path p; |
17253 |
-+ |
17254 |
-+ /* |
17255 |
-+ * XXX: We need access to __d_path() so we can write the path |
17256 |
-+ * relative to conn->root_path. Once upstream, we need |
17257 |
-+ * EXPORT_SYMBOL(__d_path) or an equivalent of d_path() that |
17258 |
-+ * takes the root path directly. Until then, we drop this item |
17259 |
-+ * if the root-paths differ. |
17260 |
-+ */ |
17261 |
-+ |
17262 |
-+ get_fs_root(current->fs, &p); |
17263 |
-+ if (path_equal(&p, &conn->root_path)) { |
17264 |
-+ staging.exe = (void *)__get_free_page(GFP_TEMPORARY); |
17265 |
-+ if (!staging.exe) { |
17266 |
-+ path_put(&p); |
17267 |
-+ ret = -ENOMEM; |
17268 |
-+ goto exit; |
17269 |
-+ } |
17270 |
-+ |
17271 |
-+ staging.exe_path = d_path(&mp->exe_path, staging.exe, |
17272 |
-+ PAGE_SIZE); |
17273 |
-+ if (IS_ERR(staging.exe_path)) { |
17274 |
-+ path_put(&p); |
17275 |
-+ ret = PTR_ERR(staging.exe_path); |
17276 |
-+ goto exit; |
17277 |
-+ } |
17278 |
-+ } |
17279 |
-+ path_put(&p); |
17280 |
-+ } |
17281 |
-+ |
17282 |
-+ size = kdbus_meta_measure(&staging); |
17283 |
-+ if (!size) { /* bail out if nothing to do */ |
17284 |
-+ ret = 0; |
17285 |
-+ goto exit; |
17286 |
-+ } |
17287 |
-+ |
17288 |
-+ items = kmalloc(size, GFP_KERNEL); |
17289 |
-+ if (!items) { |
17290 |
-+ ret = -ENOMEM; |
17291 |
-+ goto exit; |
17292 |
-+ } |
17293 |
-+ |
17294 |
-+ size = kdbus_meta_write(&staging, items, size); |
17295 |
-+ if (!size) { |
17296 |
-+ kfree(items); |
17297 |
-+ items = NULL; |
17298 |
-+ } |
17299 |
-+ |
17300 |
-+ ret = 0; |
17301 |
-+ |
17302 |
-+exit: |
17303 |
-+ if (staging.exe) |
17304 |
-+ free_page((unsigned long)staging.exe); |
17305 |
-+ if (ret >= 0) { |
17306 |
-+ *out_items = items; |
17307 |
-+ *out_size = size; |
17308 |
-+ } |
17309 |
-+ return ret; |
17310 |
-+} |
17311 |
-+ |
17312 |
-+enum { |
17313 |
-+ KDBUS_META_PROC_NONE, |
17314 |
-+ KDBUS_META_PROC_NORMAL, |
17315 |
-+}; |
17316 |
-+ |
17317 |
-+/** |
17318 |
-+ * kdbus_proc_permission() - check /proc permissions on target pid |
17319 |
-+ * @pid_ns: namespace we operate in |
17320 |
-+ * @cred: credentials of requestor |
17321 |
-+ * @target: target process |
17322 |
-+ * |
17323 |
-+ * This checks whether a process with credentials @cred can access information |
17324 |
-+ * of @target in the namespace @pid_ns. This tries to follow /proc permissions, |
17325 |
-+ * but is slightly more restrictive. |
17326 |
-+ * |
17327 |
-+ * Return: The /proc access level (KDBUS_META_PROC_*) is returned. |
17328 |
-+ */ |
17329 |
-+static unsigned int kdbus_proc_permission(const struct pid_namespace *pid_ns, |
17330 |
-+ const struct cred *cred, |
17331 |
-+ struct pid *target) |
17332 |
-+{ |
17333 |
-+ if (pid_ns->hide_pid < 1) |
17334 |
-+ return KDBUS_META_PROC_NORMAL; |
17335 |
-+ |
17336 |
-+ /* XXX: we need groups_search() exported for aux-groups */ |
17337 |
-+ if (gid_eq(cred->egid, pid_ns->pid_gid)) |
17338 |
-+ return KDBUS_META_PROC_NORMAL; |
17339 |
-+ |
17340 |
-+ /* |
17341 |
-+ * XXX: If ptrace_may_access(PTRACE_MODE_READ) is granted, you can |
17342 |
-+ * overwrite hide_pid. However, ptrace_may_access() only supports |
17343 |
-+ * checking 'current', hence, we cannot use this here. But we |
17344 |
-+ * simply decide to not support this override, so no need to worry. |
17345 |
-+ */ |
17346 |
-+ |
17347 |
-+ return KDBUS_META_PROC_NONE; |
17348 |
-+} |
17349 |
-+ |
17350 |
-+/** |
17351 |
-+ * kdbus_meta_proc_mask() - calculate which metadata would be visible to |
17352 |
-+ * a connection via /proc |
17353 |
-+ * @prv_pid: pid of metadata provider |
17354 |
-+ * @req_pid: pid of metadata requestor |
17355 |
-+ * @req_cred: credentials of metadata reqeuestor |
17356 |
-+ * @wanted: metadata that is requested |
17357 |
-+ * |
17358 |
-+ * This checks which metadata items of @prv_pid can be read via /proc by the |
17359 |
-+ * requestor @req_pid. |
17360 |
-+ * |
17361 |
-+ * Return: Set of metadata flags the requestor can see (limited by @wanted). |
17362 |
-+ */ |
17363 |
-+static u64 kdbus_meta_proc_mask(struct pid *prv_pid, |
17364 |
-+ struct pid *req_pid, |
17365 |
-+ const struct cred *req_cred, |
17366 |
-+ u64 wanted) |
17367 |
-+{ |
17368 |
-+ struct pid_namespace *prv_ns, *req_ns; |
17369 |
-+ unsigned int proc; |
17370 |
-+ |
17371 |
-+ prv_ns = ns_of_pid(prv_pid); |
17372 |
-+ req_ns = ns_of_pid(req_pid); |
17373 |
-+ |
17374 |
-+ /* |
17375 |
-+ * If the sender is not visible in the receiver namespace, then the |
17376 |
-+ * receiver cannot access the sender via its own procfs. Hence, we do |
17377 |
-+ * not attach any additional metadata. |
17378 |
-+ */ |
17379 |
-+ if (!pid_nr_ns(prv_pid, req_ns)) |
17380 |
-+ return 0; |
17381 |
-+ |
17382 |
-+ /* |
17383 |
-+ * If the pid-namespace of the receiver has hide_pid set, it cannot see |
17384 |
-+ * any process but its own. We shortcut this /proc permission check if |
17385 |
-+ * provider and requestor are the same. If not, we perform rather |
17386 |
-+ * expensive /proc permission checks. |
17387 |
-+ */ |
17388 |
-+ if (prv_pid == req_pid) |
17389 |
-+ proc = KDBUS_META_PROC_NORMAL; |
17390 |
-+ else |
17391 |
-+ proc = kdbus_proc_permission(req_ns, req_cred, prv_pid); |
17392 |
-+ |
17393 |
-+ /* you need /proc access to read standard process attributes */ |
17394 |
-+ if (proc < KDBUS_META_PROC_NORMAL) |
17395 |
-+ wanted &= ~(KDBUS_ATTACH_TID_COMM | |
17396 |
-+ KDBUS_ATTACH_PID_COMM | |
17397 |
-+ KDBUS_ATTACH_SECLABEL | |
17398 |
-+ KDBUS_ATTACH_CMDLINE | |
17399 |
-+ KDBUS_ATTACH_CGROUP | |
17400 |
-+ KDBUS_ATTACH_AUDIT | |
17401 |
-+ KDBUS_ATTACH_CAPS | |
17402 |
-+ KDBUS_ATTACH_EXE); |
17403 |
-+ |
17404 |
-+ /* clear all non-/proc flags */ |
17405 |
-+ return wanted & (KDBUS_ATTACH_TID_COMM | |
17406 |
-+ KDBUS_ATTACH_PID_COMM | |
17407 |
-+ KDBUS_ATTACH_SECLABEL | |
17408 |
-+ KDBUS_ATTACH_CMDLINE | |
17409 |
-+ KDBUS_ATTACH_CGROUP | |
17410 |
-+ KDBUS_ATTACH_AUDIT | |
17411 |
-+ KDBUS_ATTACH_CAPS | |
17412 |
-+ KDBUS_ATTACH_EXE); |
17413 |
-+} |
17414 |
-+ |
17415 |
-+/** |
17416 |
-+ * kdbus_meta_get_mask() - calculate attach flags mask for metadata request |
17417 |
-+ * @prv_pid: pid of metadata provider |
17418 |
-+ * @prv_mask: mask of metadata the provide grants unchecked |
17419 |
-+ * @req_pid: pid of metadata requestor |
17420 |
-+ * @req_cred: credentials of metadata requestor |
17421 |
-+ * @req_mask: mask of metadata that is requested |
17422 |
-+ * |
17423 |
-+ * This calculates the metadata items that the requestor @req_pid can access |
17424 |
-+ * from the metadata provider @prv_pid. This permission check consists of |
17425 |
-+ * several different parts: |
17426 |
-+ * - Providers can grant metadata items unchecked. Regardless of their type, |
17427 |
-+ * they're always granted to the requestor. This mask is passed as @prv_mask. |
17428 |
-+ * - Basic items (credentials and connection metadata) are granted implicitly |
17429 |
-+ * to everyone. They're publicly available to any bus-user that can see the |
17430 |
-+ * provider. |
17431 |
-+ * - Process credentials that are not granted implicitly follow the same |
17432 |
-+ * permission checks as /proc. This means, we always assume a requestor |
17433 |
-+ * process has access to their *own* /proc mount, if they have access to |
17434 |
-+ * kdbusfs. |
17435 |
-+ * |
17436 |
-+ * Return: Mask of metadata that is granted. |
17437 |
-+ */ |
17438 |
-+static u64 kdbus_meta_get_mask(struct pid *prv_pid, u64 prv_mask, |
17439 |
-+ struct pid *req_pid, |
17440 |
-+ const struct cred *req_cred, u64 req_mask) |
17441 |
-+{ |
17442 |
-+ u64 missing, impl_mask, proc_mask = 0; |
17443 |
-+ |
17444 |
-+ /* |
17445 |
-+ * Connection metadata and basic unix process credentials are |
17446 |
-+ * transmitted implicitly, and cannot be suppressed. Both are required |
17447 |
-+ * to perform user-space policies on the receiver-side. Furthermore, |
17448 |
-+ * connection metadata is public state, anyway, and unix credentials |
17449 |
-+ * are needed for UDS-compatibility. We extend them slightly by |
17450 |
-+ * auxiliary groups and additional uids/gids/pids. |
17451 |
-+ */ |
17452 |
-+ impl_mask = /* connection metadata */ |
17453 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION | |
17454 |
-+ KDBUS_ATTACH_TIMESTAMP | |
17455 |
-+ KDBUS_ATTACH_NAMES | |
17456 |
-+ /* credentials and pids */ |
17457 |
-+ KDBUS_ATTACH_AUXGROUPS | |
17458 |
-+ KDBUS_ATTACH_CREDS | |
17459 |
-+ KDBUS_ATTACH_PIDS; |
17460 |
-+ |
17461 |
-+ /* |
17462 |
-+ * Calculate the set of metadata that is not granted implicitly nor by |
17463 |
-+ * the sender, but still requested by the receiver. If any are left, |
17464 |
-+ * perform rather expensive /proc access checks for them. |
17465 |
-+ */ |
17466 |
-+ missing = req_mask & ~((prv_mask | impl_mask) & req_mask); |
17467 |
-+ if (missing) |
17468 |
-+ proc_mask = kdbus_meta_proc_mask(prv_pid, req_pid, req_cred, |
17469 |
-+ missing); |
17470 |
-+ |
17471 |
-+ return (prv_mask | impl_mask | proc_mask) & req_mask; |
17472 |
-+} |
17473 |
-+ |
17474 |
-+/** |
17475 |
-+ */ |
17476 |
-+u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask) |
17477 |
-+{ |
17478 |
-+ return kdbus_meta_get_mask(conn->pid, |
17479 |
-+ atomic64_read(&conn->attach_flags_send), |
17480 |
-+ task_pid(current), |
17481 |
-+ current_cred(), |
17482 |
-+ mask); |
17483 |
-+} |
17484 |
-+ |
17485 |
-+/** |
17486 |
-+ */ |
17487 |
-+u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd, |
17488 |
-+ const struct kdbus_conn *rcv) |
17489 |
-+{ |
17490 |
-+ return kdbus_meta_get_mask(task_pid(current), |
17491 |
-+ atomic64_read(&snd->attach_flags_send), |
17492 |
-+ rcv->pid, |
17493 |
-+ rcv->cred, |
17494 |
-+ atomic64_read(&rcv->attach_flags_recv)); |
17495 |
-+} |
17496 |
-diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h |
17497 |
-new file mode 100644 |
17498 |
-index 0000000..dba7cc7 |
17499 |
---- /dev/null |
17500 |
-+++ b/ipc/kdbus/metadata.h |
17501 |
-@@ -0,0 +1,86 @@ |
17502 |
-+/* |
17503 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
17504 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
17505 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
17506 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
17507 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
17508 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
17509 |
-+ * |
17510 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
17511 |
-+ * the terms of the GNU Lesser General Public License as published by the |
17512 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
17513 |
-+ * your option) any later version. |
17514 |
-+ */ |
17515 |
-+ |
17516 |
-+#ifndef __KDBUS_METADATA_H |
17517 |
-+#define __KDBUS_METADATA_H |
17518 |
-+ |
17519 |
-+#include <linux/kernel.h> |
17520 |
-+ |
17521 |
-+struct kdbus_conn; |
17522 |
-+struct kdbus_pool_slice; |
17523 |
-+ |
17524 |
-+struct kdbus_meta_proc; |
17525 |
-+struct kdbus_meta_conn; |
17526 |
-+ |
17527 |
-+/** |
17528 |
-+ * struct kdbus_meta_fake - Fake metadata |
17529 |
-+ * @valid: Bitmask of collected and valid items |
17530 |
-+ * @uid: UID of process |
17531 |
-+ * @euid: EUID of process |
17532 |
-+ * @suid: SUID of process |
17533 |
-+ * @fsuid: FSUID of process |
17534 |
-+ * @gid: GID of process |
17535 |
-+ * @egid: EGID of process |
17536 |
-+ * @sgid: SGID of process |
17537 |
-+ * @fsgid: FSGID of process |
17538 |
-+ * @pid: PID of process |
17539 |
-+ * @tgid: TGID of process |
17540 |
-+ * @ppid: PPID of process |
17541 |
-+ * @seclabel: Seclabel |
17542 |
-+ */ |
17543 |
-+struct kdbus_meta_fake { |
17544 |
-+ u64 valid; |
17545 |
-+ |
17546 |
-+ /* KDBUS_ITEM_CREDS */ |
17547 |
-+ kuid_t uid, euid, suid, fsuid; |
17548 |
-+ kgid_t gid, egid, sgid, fsgid; |
17549 |
-+ |
17550 |
-+ /* KDBUS_ITEM_PIDS */ |
17551 |
-+ struct pid *pid, *tgid, *ppid; |
17552 |
-+ |
17553 |
-+ /* KDBUS_ITEM_SECLABEL */ |
17554 |
-+ char *seclabel; |
17555 |
-+}; |
17556 |
-+ |
17557 |
-+struct kdbus_meta_proc *kdbus_meta_proc_new(void); |
17558 |
-+struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp); |
17559 |
-+struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp); |
17560 |
-+int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what); |
17561 |
-+ |
17562 |
-+struct kdbus_meta_fake *kdbus_meta_fake_new(void); |
17563 |
-+struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf); |
17564 |
-+int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf, |
17565 |
-+ const struct kdbus_creds *creds, |
17566 |
-+ const struct kdbus_pids *pids, |
17567 |
-+ const char *seclabel); |
17568 |
-+ |
17569 |
-+struct kdbus_meta_conn *kdbus_meta_conn_new(void); |
17570 |
-+struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc); |
17571 |
-+struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc); |
17572 |
-+int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, |
17573 |
-+ struct kdbus_conn *conn, |
17574 |
-+ u64 msg_seqnum, u64 what); |
17575 |
-+ |
17576 |
-+int kdbus_meta_emit(struct kdbus_meta_proc *mp, |
17577 |
-+ struct kdbus_meta_fake *mf, |
17578 |
-+ struct kdbus_meta_conn *mc, |
17579 |
-+ struct kdbus_conn *conn, |
17580 |
-+ u64 mask, |
17581 |
-+ struct kdbus_item **out_items, |
17582 |
-+ size_t *out_size); |
17583 |
-+u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask); |
17584 |
-+u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd, |
17585 |
-+ const struct kdbus_conn *rcv); |
17586 |
-+ |
17587 |
-+#endif |
17588 |
-diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c |
17589 |
-new file mode 100644 |
17590 |
-index 0000000..bf44ca3 |
17591 |
---- /dev/null |
17592 |
-+++ b/ipc/kdbus/names.c |
17593 |
-@@ -0,0 +1,854 @@ |
17594 |
-+/* |
17595 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
17596 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
17597 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
17598 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
17599 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
17600 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
17601 |
-+ * |
17602 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
17603 |
-+ * the terms of the GNU Lesser General Public License as published by the |
17604 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
17605 |
-+ * your option) any later version. |
17606 |
-+ */ |
17607 |
-+ |
17608 |
-+#include <linux/ctype.h> |
17609 |
-+#include <linux/fs.h> |
17610 |
-+#include <linux/hash.h> |
17611 |
-+#include <linux/idr.h> |
17612 |
-+#include <linux/init.h> |
17613 |
-+#include <linux/module.h> |
17614 |
-+#include <linux/mutex.h> |
17615 |
-+#include <linux/rwsem.h> |
17616 |
-+#include <linux/sched.h> |
17617 |
-+#include <linux/slab.h> |
17618 |
-+#include <linux/uaccess.h> |
17619 |
-+#include <linux/uio.h> |
17620 |
-+ |
17621 |
-+#include "bus.h" |
17622 |
-+#include "connection.h" |
17623 |
-+#include "endpoint.h" |
17624 |
-+#include "handle.h" |
17625 |
-+#include "item.h" |
17626 |
-+#include "names.h" |
17627 |
-+#include "notify.h" |
17628 |
-+#include "policy.h" |
17629 |
-+ |
17630 |
-+#define KDBUS_NAME_SAVED_MASK (KDBUS_NAME_ALLOW_REPLACEMENT | \ |
17631 |
-+ KDBUS_NAME_QUEUE) |
17632 |
-+ |
17633 |
-+static bool kdbus_name_owner_is_used(struct kdbus_name_owner *owner) |
17634 |
-+{ |
17635 |
-+ return !list_empty(&owner->name_entry) || |
17636 |
-+ owner == owner->name->activator; |
17637 |
-+} |
17638 |
-+ |
17639 |
-+static struct kdbus_name_owner * |
17640 |
-+kdbus_name_owner_new(struct kdbus_conn *conn, struct kdbus_name_entry *name, |
17641 |
-+ u64 flags) |
17642 |
-+{ |
17643 |
-+ struct kdbus_name_owner *owner; |
17644 |
-+ |
17645 |
-+ kdbus_conn_assert_active(conn); |
17646 |
-+ |
17647 |
-+ if (conn->name_count >= KDBUS_CONN_MAX_NAMES) |
17648 |
-+ return ERR_PTR(-E2BIG); |
17649 |
-+ |
17650 |
-+ owner = kmalloc(sizeof(*owner), GFP_KERNEL); |
17651 |
-+ if (!owner) |
17652 |
-+ return ERR_PTR(-ENOMEM); |
17653 |
-+ |
17654 |
-+ owner->flags = flags & KDBUS_NAME_SAVED_MASK; |
17655 |
-+ owner->conn = conn; |
17656 |
-+ owner->name = name; |
17657 |
-+ list_add_tail(&owner->conn_entry, &conn->names_list); |
17658 |
-+ INIT_LIST_HEAD(&owner->name_entry); |
17659 |
-+ |
17660 |
-+ ++conn->name_count; |
17661 |
-+ return owner; |
17662 |
-+} |
17663 |
-+ |
17664 |
-+static void kdbus_name_owner_free(struct kdbus_name_owner *owner) |
17665 |
-+{ |
17666 |
-+ if (!owner) |
17667 |
-+ return; |
17668 |
-+ |
17669 |
-+ WARN_ON(kdbus_name_owner_is_used(owner)); |
17670 |
-+ --owner->conn->name_count; |
17671 |
-+ list_del(&owner->conn_entry); |
17672 |
-+ kfree(owner); |
17673 |
-+} |
17674 |
-+ |
17675 |
-+static struct kdbus_name_owner * |
17676 |
-+kdbus_name_owner_find(struct kdbus_name_entry *name, struct kdbus_conn *conn) |
17677 |
-+{ |
17678 |
-+ struct kdbus_name_owner *owner; |
17679 |
-+ |
17680 |
-+ /* |
17681 |
-+ * Use conn->names_list over name->queue to make sure boundaries of |
17682 |
-+ * this linear search are controlled by the connection itself. |
17683 |
-+ * Furthermore, this will find normal owners as well as activators |
17684 |
-+ * without any additional code. |
17685 |
-+ */ |
17686 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) |
17687 |
-+ if (owner->name == name) |
17688 |
-+ return owner; |
17689 |
-+ |
17690 |
-+ return NULL; |
17691 |
-+} |
17692 |
-+ |
17693 |
-+static bool kdbus_name_entry_is_used(struct kdbus_name_entry *name) |
17694 |
-+{ |
17695 |
-+ return !list_empty(&name->queue) || name->activator; |
17696 |
-+} |
17697 |
-+ |
17698 |
-+static struct kdbus_name_owner * |
17699 |
-+kdbus_name_entry_first(struct kdbus_name_entry *name) |
17700 |
-+{ |
17701 |
-+ return list_first_entry_or_null(&name->queue, struct kdbus_name_owner, |
17702 |
-+ name_entry); |
17703 |
-+} |
17704 |
-+ |
17705 |
-+static struct kdbus_name_entry * |
17706 |
-+kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash, |
17707 |
-+ const char *name_str) |
17708 |
-+{ |
17709 |
-+ struct kdbus_name_entry *name; |
17710 |
-+ size_t namelen; |
17711 |
-+ |
17712 |
-+ lockdep_assert_held(&r->rwlock); |
17713 |
-+ |
17714 |
-+ namelen = strlen(name_str); |
17715 |
-+ |
17716 |
-+ name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL); |
17717 |
-+ if (!name) |
17718 |
-+ return ERR_PTR(-ENOMEM); |
17719 |
-+ |
17720 |
-+ name->name_id = ++r->name_seq_last; |
17721 |
-+ name->activator = NULL; |
17722 |
-+ INIT_LIST_HEAD(&name->queue); |
17723 |
-+ hash_add(r->entries_hash, &name->hentry, hash); |
17724 |
-+ memcpy(name->name, name_str, namelen + 1); |
17725 |
-+ |
17726 |
-+ return name; |
17727 |
-+} |
17728 |
-+ |
17729 |
-+static void kdbus_name_entry_free(struct kdbus_name_entry *name) |
17730 |
-+{ |
17731 |
-+ if (!name) |
17732 |
-+ return; |
17733 |
-+ |
17734 |
-+ WARN_ON(kdbus_name_entry_is_used(name)); |
17735 |
-+ hash_del(&name->hentry); |
17736 |
-+ kfree(name); |
17737 |
-+} |
17738 |
-+ |
17739 |
-+static struct kdbus_name_entry * |
17740 |
-+kdbus_name_entry_find(struct kdbus_name_registry *r, u32 hash, |
17741 |
-+ const char *name_str) |
17742 |
-+{ |
17743 |
-+ struct kdbus_name_entry *name; |
17744 |
-+ |
17745 |
-+ lockdep_assert_held(&r->rwlock); |
17746 |
-+ |
17747 |
-+ hash_for_each_possible(r->entries_hash, name, hentry, hash) |
17748 |
-+ if (!strcmp(name->name, name_str)) |
17749 |
-+ return name; |
17750 |
-+ |
17751 |
-+ return NULL; |
17752 |
-+} |
17753 |
-+ |
17754 |
-+/** |
17755 |
-+ * kdbus_name_registry_new() - create a new name registry |
17756 |
-+ * |
17757 |
-+ * Return: a new kdbus_name_registry on success, ERR_PTR on failure. |
17758 |
-+ */ |
17759 |
-+struct kdbus_name_registry *kdbus_name_registry_new(void) |
17760 |
-+{ |
17761 |
-+ struct kdbus_name_registry *r; |
17762 |
-+ |
17763 |
-+ r = kmalloc(sizeof(*r), GFP_KERNEL); |
17764 |
-+ if (!r) |
17765 |
-+ return ERR_PTR(-ENOMEM); |
17766 |
-+ |
17767 |
-+ hash_init(r->entries_hash); |
17768 |
-+ init_rwsem(&r->rwlock); |
17769 |
-+ r->name_seq_last = 0; |
17770 |
-+ |
17771 |
-+ return r; |
17772 |
-+} |
17773 |
-+ |
17774 |
-+/** |
17775 |
-+ * kdbus_name_registry_free() - free name registry |
17776 |
-+ * @r: name registry to free, or NULL |
17777 |
-+ * |
17778 |
-+ * Free a name registry and cleanup all internal objects. This is a no-op if |
17779 |
-+ * you pass NULL as registry. |
17780 |
-+ */ |
17781 |
-+void kdbus_name_registry_free(struct kdbus_name_registry *r) |
17782 |
-+{ |
17783 |
-+ if (!r) |
17784 |
-+ return; |
17785 |
-+ |
17786 |
-+ WARN_ON(!hash_empty(r->entries_hash)); |
17787 |
-+ kfree(r); |
17788 |
-+} |
17789 |
-+ |
17790 |
-+/** |
17791 |
-+ * kdbus_name_lookup_unlocked() - lookup name in registry |
17792 |
-+ * @reg: name registry |
17793 |
-+ * @name: name to lookup |
17794 |
-+ * |
17795 |
-+ * This looks up @name in the given name-registry and returns the |
17796 |
-+ * kdbus_name_entry object. The caller must hold the registry-lock and must not |
17797 |
-+ * access the returned object after releasing the lock. |
17798 |
-+ * |
17799 |
-+ * Return: Pointer to name-entry, or NULL if not found. |
17800 |
-+ */ |
17801 |
-+struct kdbus_name_entry * |
17802 |
-+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name) |
17803 |
-+{ |
17804 |
-+ return kdbus_name_entry_find(reg, kdbus_strhash(name), name); |
17805 |
-+} |
17806 |
-+ |
17807 |
-+static int kdbus_name_become_activator(struct kdbus_name_owner *owner, |
17808 |
-+ u64 *return_flags) |
17809 |
-+{ |
17810 |
-+ if (kdbus_name_owner_is_used(owner)) |
17811 |
-+ return -EALREADY; |
17812 |
-+ if (owner->name->activator) |
17813 |
-+ return -EEXIST; |
17814 |
-+ |
17815 |
-+ owner->name->activator = owner; |
17816 |
-+ owner->flags |= KDBUS_NAME_ACTIVATOR; |
17817 |
-+ |
17818 |
-+ if (kdbus_name_entry_first(owner->name)) { |
17819 |
-+ owner->flags |= KDBUS_NAME_IN_QUEUE; |
17820 |
-+ } else { |
17821 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17822 |
-+ kdbus_notify_name_change(owner->conn->ep->bus, |
17823 |
-+ KDBUS_ITEM_NAME_ADD, |
17824 |
-+ 0, owner->conn->id, |
17825 |
-+ 0, owner->flags, |
17826 |
-+ owner->name->name); |
17827 |
-+ } |
17828 |
-+ |
17829 |
-+ if (return_flags) |
17830 |
-+ *return_flags = owner->flags | KDBUS_NAME_ACQUIRED; |
17831 |
-+ |
17832 |
-+ return 0; |
17833 |
-+} |
17834 |
-+ |
17835 |
-+static int kdbus_name_update(struct kdbus_name_owner *owner, u64 flags, |
17836 |
-+ u64 *return_flags) |
17837 |
-+{ |
17838 |
-+ struct kdbus_name_owner *primary, *activator; |
17839 |
-+ struct kdbus_name_entry *name; |
17840 |
-+ struct kdbus_bus *bus; |
17841 |
-+ u64 nflags = 0; |
17842 |
-+ int ret = 0; |
17843 |
-+ |
17844 |
-+ name = owner->name; |
17845 |
-+ bus = owner->conn->ep->bus; |
17846 |
-+ primary = kdbus_name_entry_first(name); |
17847 |
-+ activator = name->activator; |
17848 |
-+ |
17849 |
-+ /* cannot be activator and acquire a name */ |
17850 |
-+ if (owner == activator) |
17851 |
-+ return -EUCLEAN; |
17852 |
-+ |
17853 |
-+ /* update saved flags */ |
17854 |
-+ owner->flags = flags & KDBUS_NAME_SAVED_MASK; |
17855 |
-+ |
17856 |
-+ if (!primary) { |
17857 |
-+ /* |
17858 |
-+ * No primary owner (but maybe an activator). Take over the |
17859 |
-+ * name. |
17860 |
-+ */ |
17861 |
-+ |
17862 |
-+ list_add(&owner->name_entry, &name->queue); |
17863 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17864 |
-+ nflags |= KDBUS_NAME_ACQUIRED; |
17865 |
-+ |
17866 |
-+ /* move messages to new owner on activation */ |
17867 |
-+ if (activator) { |
17868 |
-+ kdbus_conn_move_messages(owner->conn, activator->conn, |
17869 |
-+ name->name_id); |
17870 |
-+ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE, |
17871 |
-+ activator->conn->id, owner->conn->id, |
17872 |
-+ activator->flags, owner->flags, |
17873 |
-+ name->name); |
17874 |
-+ activator->flags &= ~KDBUS_NAME_PRIMARY; |
17875 |
-+ activator->flags |= KDBUS_NAME_IN_QUEUE; |
17876 |
-+ } else { |
17877 |
-+ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_ADD, |
17878 |
-+ 0, owner->conn->id, |
17879 |
-+ 0, owner->flags, |
17880 |
-+ name->name); |
17881 |
-+ } |
17882 |
-+ |
17883 |
-+ } else if (owner == primary) { |
17884 |
-+ /* |
17885 |
-+ * Already the primary owner of the name, flags were already |
17886 |
-+ * updated. Nothing to do. |
17887 |
-+ */ |
17888 |
-+ |
17889 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17890 |
-+ |
17891 |
-+ } else if ((primary->flags & KDBUS_NAME_ALLOW_REPLACEMENT) && |
17892 |
-+ (flags & KDBUS_NAME_REPLACE_EXISTING)) { |
17893 |
-+ /* |
17894 |
-+ * We're not the primary owner but can replace it. Move us |
17895 |
-+ * ahead of the primary owner and acquire the name (possibly |
17896 |
-+ * skipping queued owners ahead of us). |
17897 |
-+ */ |
17898 |
-+ |
17899 |
-+ list_del_init(&owner->name_entry); |
17900 |
-+ list_add(&owner->name_entry, &name->queue); |
17901 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17902 |
-+ nflags |= KDBUS_NAME_ACQUIRED; |
17903 |
-+ |
17904 |
-+ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE, |
17905 |
-+ primary->conn->id, owner->conn->id, |
17906 |
-+ primary->flags, owner->flags, |
17907 |
-+ name->name); |
17908 |
-+ |
17909 |
-+ /* requeue old primary, or drop if queueing not wanted */ |
17910 |
-+ if (primary->flags & KDBUS_NAME_QUEUE) { |
17911 |
-+ primary->flags &= ~KDBUS_NAME_PRIMARY; |
17912 |
-+ primary->flags |= KDBUS_NAME_IN_QUEUE; |
17913 |
-+ } else { |
17914 |
-+ list_del_init(&primary->name_entry); |
17915 |
-+ kdbus_name_owner_free(primary); |
17916 |
-+ } |
17917 |
-+ |
17918 |
-+ } else if (flags & KDBUS_NAME_QUEUE) { |
17919 |
-+ /* |
17920 |
-+ * Name is already occupied and we cannot take it over, but |
17921 |
-+ * queuing is allowed. Put us silently on the queue, if not |
17922 |
-+ * already there. |
17923 |
-+ */ |
17924 |
-+ |
17925 |
-+ owner->flags |= KDBUS_NAME_IN_QUEUE; |
17926 |
-+ if (!kdbus_name_owner_is_used(owner)) { |
17927 |
-+ list_add_tail(&owner->name_entry, &name->queue); |
17928 |
-+ nflags |= KDBUS_NAME_ACQUIRED; |
17929 |
-+ } |
17930 |
-+ } else if (kdbus_name_owner_is_used(owner)) { |
17931 |
-+ /* |
17932 |
-+ * Already queued on name, but re-queueing was not requested. |
17933 |
-+ * Make sure to unlink it from the name, the caller is |
17934 |
-+ * responsible for releasing it. |
17935 |
-+ */ |
17936 |
-+ |
17937 |
-+ list_del_init(&owner->name_entry); |
17938 |
-+ } else { |
17939 |
-+ /* |
17940 |
-+ * Name is already claimed and queueing is not requested. |
17941 |
-+ * Return error to the caller. |
17942 |
-+ */ |
17943 |
-+ |
17944 |
-+ ret = -EEXIST; |
17945 |
-+ } |
17946 |
-+ |
17947 |
-+ if (return_flags) |
17948 |
-+ *return_flags = owner->flags | nflags; |
17949 |
-+ |
17950 |
-+ return ret; |
17951 |
-+} |
17952 |
-+ |
17953 |
-+int kdbus_name_acquire(struct kdbus_name_registry *reg, |
17954 |
-+ struct kdbus_conn *conn, const char *name_str, |
17955 |
-+ u64 flags, u64 *return_flags) |
17956 |
-+{ |
17957 |
-+ struct kdbus_name_entry *name = NULL; |
17958 |
-+ struct kdbus_name_owner *owner = NULL; |
17959 |
-+ u32 hash; |
17960 |
-+ int ret; |
17961 |
-+ |
17962 |
-+ kdbus_conn_assert_active(conn); |
17963 |
-+ |
17964 |
-+ down_write(®->rwlock); |
17965 |
-+ |
17966 |
-+ /* |
17967 |
-+ * Verify the connection has access to the name. Do this before testing |
17968 |
-+ * for double-acquisitions and other errors to make sure we do not leak |
17969 |
-+ * information about this name through possible custom endpoints. |
17970 |
-+ */ |
17971 |
-+ if (!kdbus_conn_policy_own_name(conn, current_cred(), name_str)) { |
17972 |
-+ ret = -EPERM; |
17973 |
-+ goto exit; |
17974 |
-+ } |
17975 |
-+ |
17976 |
-+ /* |
17977 |
-+ * Lookup the name entry. If it already exists, search for an owner |
17978 |
-+ * entry as we might already own that name. If either does not exist, |
17979 |
-+ * we will allocate a fresh one. |
17980 |
-+ */ |
17981 |
-+ hash = kdbus_strhash(name_str); |
17982 |
-+ name = kdbus_name_entry_find(reg, hash, name_str); |
17983 |
-+ if (name) { |
17984 |
-+ owner = kdbus_name_owner_find(name, conn); |
17985 |
-+ } else { |
17986 |
-+ name = kdbus_name_entry_new(reg, hash, name_str); |
17987 |
-+ if (IS_ERR(name)) { |
17988 |
-+ ret = PTR_ERR(name); |
17989 |
-+ name = NULL; |
17990 |
-+ goto exit; |
17991 |
-+ } |
17992 |
-+ } |
17993 |
-+ |
17994 |
-+ /* create name owner object if not already queued */ |
17995 |
-+ if (!owner) { |
17996 |
-+ owner = kdbus_name_owner_new(conn, name, flags); |
17997 |
-+ if (IS_ERR(owner)) { |
17998 |
-+ ret = PTR_ERR(owner); |
17999 |
-+ owner = NULL; |
18000 |
-+ goto exit; |
18001 |
-+ } |
18002 |
-+ } |
18003 |
-+ |
18004 |
-+ if (flags & KDBUS_NAME_ACTIVATOR) |
18005 |
-+ ret = kdbus_name_become_activator(owner, return_flags); |
18006 |
-+ else |
18007 |
-+ ret = kdbus_name_update(owner, flags, return_flags); |
18008 |
-+ if (ret < 0) |
18009 |
-+ goto exit; |
18010 |
-+ |
18011 |
-+exit: |
18012 |
-+ if (owner && !kdbus_name_owner_is_used(owner)) |
18013 |
-+ kdbus_name_owner_free(owner); |
18014 |
-+ if (name && !kdbus_name_entry_is_used(name)) |
18015 |
-+ kdbus_name_entry_free(name); |
18016 |
-+ up_write(®->rwlock); |
18017 |
-+ kdbus_notify_flush(conn->ep->bus); |
18018 |
-+ return ret; |
18019 |
-+} |
18020 |
-+ |
18021 |
-+static void kdbus_name_release_unlocked(struct kdbus_name_owner *owner) |
18022 |
-+{ |
18023 |
-+ struct kdbus_name_owner *primary, *next; |
18024 |
-+ struct kdbus_name_entry *name; |
18025 |
-+ |
18026 |
-+ name = owner->name; |
18027 |
-+ primary = kdbus_name_entry_first(name); |
18028 |
-+ |
18029 |
-+ list_del_init(&owner->name_entry); |
18030 |
-+ if (owner == name->activator) |
18031 |
-+ name->activator = NULL; |
18032 |
-+ |
18033 |
-+ if (!primary || owner == primary) { |
18034 |
-+ next = kdbus_name_entry_first(name); |
18035 |
-+ if (!next) |
18036 |
-+ next = name->activator; |
18037 |
-+ |
18038 |
-+ if (next) { |
18039 |
-+ /* hand to next in queue */ |
18040 |
-+ next->flags &= ~KDBUS_NAME_IN_QUEUE; |
18041 |
-+ next->flags |= KDBUS_NAME_PRIMARY; |
18042 |
-+ if (next == name->activator) |
18043 |
-+ kdbus_conn_move_messages(next->conn, |
18044 |
-+ owner->conn, |
18045 |
-+ name->name_id); |
18046 |
-+ |
18047 |
-+ kdbus_notify_name_change(owner->conn->ep->bus, |
18048 |
-+ KDBUS_ITEM_NAME_CHANGE, |
18049 |
-+ owner->conn->id, next->conn->id, |
18050 |
-+ owner->flags, next->flags, |
18051 |
-+ name->name); |
18052 |
-+ } else { |
18053 |
-+ kdbus_notify_name_change(owner->conn->ep->bus, |
18054 |
-+ KDBUS_ITEM_NAME_REMOVE, |
18055 |
-+ owner->conn->id, 0, |
18056 |
-+ owner->flags, 0, |
18057 |
-+ name->name); |
18058 |
-+ } |
18059 |
-+ } |
18060 |
-+ |
18061 |
-+ kdbus_name_owner_free(owner); |
18062 |
-+ if (!kdbus_name_entry_is_used(name)) |
18063 |
-+ kdbus_name_entry_free(name); |
18064 |
-+} |
18065 |
-+ |
18066 |
-+static int kdbus_name_release(struct kdbus_name_registry *reg, |
18067 |
-+ struct kdbus_conn *conn, |
18068 |
-+ const char *name_str) |
18069 |
-+{ |
18070 |
-+ struct kdbus_name_owner *owner; |
18071 |
-+ struct kdbus_name_entry *name; |
18072 |
-+ int ret = 0; |
18073 |
-+ |
18074 |
-+ down_write(®->rwlock); |
18075 |
-+ name = kdbus_name_entry_find(reg, kdbus_strhash(name_str), name_str); |
18076 |
-+ if (name) { |
18077 |
-+ owner = kdbus_name_owner_find(name, conn); |
18078 |
-+ if (owner) |
18079 |
-+ kdbus_name_release_unlocked(owner); |
18080 |
-+ else |
18081 |
-+ ret = -EADDRINUSE; |
18082 |
-+ } else { |
18083 |
-+ ret = -ESRCH; |
18084 |
-+ } |
18085 |
-+ up_write(®->rwlock); |
18086 |
-+ |
18087 |
-+ kdbus_notify_flush(conn->ep->bus); |
18088 |
-+ return ret; |
18089 |
-+} |
18090 |
-+ |
18091 |
-+/** |
18092 |
-+ * kdbus_name_release_all() - remove all name entries of a given connection |
18093 |
-+ * @reg: name registry |
18094 |
-+ * @conn: connection |
18095 |
-+ */ |
18096 |
-+void kdbus_name_release_all(struct kdbus_name_registry *reg, |
18097 |
-+ struct kdbus_conn *conn) |
18098 |
-+{ |
18099 |
-+ struct kdbus_name_owner *owner; |
18100 |
-+ |
18101 |
-+ down_write(®->rwlock); |
18102 |
-+ |
18103 |
-+ while ((owner = list_first_entry_or_null(&conn->names_list, |
18104 |
-+ struct kdbus_name_owner, |
18105 |
-+ conn_entry))) |
18106 |
-+ kdbus_name_release_unlocked(owner); |
18107 |
-+ |
18108 |
-+ up_write(®->rwlock); |
18109 |
-+ |
18110 |
-+ kdbus_notify_flush(conn->ep->bus); |
18111 |
-+} |
18112 |
-+ |
18113 |
-+/** |
18114 |
-+ * kdbus_name_is_valid() - check if a name is valid |
18115 |
-+ * @p: The name to check |
18116 |
-+ * @allow_wildcard: Whether or not to allow a wildcard name |
18117 |
-+ * |
18118 |
-+ * A name is valid if all of the following criterias are met: |
18119 |
-+ * |
18120 |
-+ * - The name has two or more elements separated by a period ('.') character. |
18121 |
-+ * - All elements must contain at least one character. |
18122 |
-+ * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-" |
18123 |
-+ * and must not begin with a digit. |
18124 |
-+ * - The name must not exceed KDBUS_NAME_MAX_LEN. |
18125 |
-+ * - If @allow_wildcard is true, the name may end on '.*' |
18126 |
-+ */ |
18127 |
-+bool kdbus_name_is_valid(const char *p, bool allow_wildcard) |
18128 |
-+{ |
18129 |
-+ bool dot, found_dot = false; |
18130 |
-+ const char *q; |
18131 |
-+ |
18132 |
-+ for (dot = true, q = p; *q; q++) { |
18133 |
-+ if (*q == '.') { |
18134 |
-+ if (dot) |
18135 |
-+ return false; |
18136 |
-+ |
18137 |
-+ found_dot = true; |
18138 |
-+ dot = true; |
18139 |
-+ } else { |
18140 |
-+ bool good; |
18141 |
-+ |
18142 |
-+ good = isalpha(*q) || (!dot && isdigit(*q)) || |
18143 |
-+ *q == '_' || *q == '-' || |
18144 |
-+ (allow_wildcard && dot && |
18145 |
-+ *q == '*' && *(q + 1) == '\0'); |
18146 |
-+ |
18147 |
-+ if (!good) |
18148 |
-+ return false; |
18149 |
-+ |
18150 |
-+ dot = false; |
18151 |
-+ } |
18152 |
-+ } |
18153 |
-+ |
18154 |
-+ if (q - p > KDBUS_NAME_MAX_LEN) |
18155 |
-+ return false; |
18156 |
-+ |
18157 |
-+ if (dot) |
18158 |
-+ return false; |
18159 |
-+ |
18160 |
-+ if (!found_dot) |
18161 |
-+ return false; |
18162 |
-+ |
18163 |
-+ return true; |
18164 |
-+} |
18165 |
-+ |
18166 |
-+/** |
18167 |
-+ * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE |
18168 |
-+ * @conn: connection to operate on |
18169 |
-+ * @argp: command payload |
18170 |
-+ * |
18171 |
-+ * Return: >=0 on success, negative error code on failure. |
18172 |
-+ */ |
18173 |
-+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp) |
18174 |
-+{ |
18175 |
-+ const char *item_name; |
18176 |
-+ struct kdbus_cmd *cmd; |
18177 |
-+ int ret; |
18178 |
-+ |
18179 |
-+ struct kdbus_arg argv[] = { |
18180 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
18181 |
-+ { .type = KDBUS_ITEM_NAME, .mandatory = true }, |
18182 |
-+ }; |
18183 |
-+ struct kdbus_args args = { |
18184 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
18185 |
-+ KDBUS_NAME_REPLACE_EXISTING | |
18186 |
-+ KDBUS_NAME_ALLOW_REPLACEMENT | |
18187 |
-+ KDBUS_NAME_QUEUE, |
18188 |
-+ .argv = argv, |
18189 |
-+ .argc = ARRAY_SIZE(argv), |
18190 |
-+ }; |
18191 |
-+ |
18192 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
18193 |
-+ return -EOPNOTSUPP; |
18194 |
-+ |
18195 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
18196 |
-+ if (ret != 0) |
18197 |
-+ return ret; |
18198 |
-+ |
18199 |
-+ item_name = argv[1].item->str; |
18200 |
-+ if (!kdbus_name_is_valid(item_name, false)) { |
18201 |
-+ ret = -EINVAL; |
18202 |
-+ goto exit; |
18203 |
-+ } |
18204 |
-+ |
18205 |
-+ ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name, |
18206 |
-+ cmd->flags, &cmd->return_flags); |
18207 |
-+ |
18208 |
-+exit: |
18209 |
-+ return kdbus_args_clear(&args, ret); |
18210 |
-+} |
18211 |
-+ |
18212 |
-+/** |
18213 |
-+ * kdbus_cmd_name_release() - handle KDBUS_CMD_NAME_RELEASE |
18214 |
-+ * @conn: connection to operate on |
18215 |
-+ * @argp: command payload |
18216 |
-+ * |
18217 |
-+ * Return: >=0 on success, negative error code on failure. |
18218 |
-+ */ |
18219 |
-+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp) |
18220 |
-+{ |
18221 |
-+ struct kdbus_cmd *cmd; |
18222 |
-+ int ret; |
18223 |
-+ |
18224 |
-+ struct kdbus_arg argv[] = { |
18225 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
18226 |
-+ { .type = KDBUS_ITEM_NAME, .mandatory = true }, |
18227 |
-+ }; |
18228 |
-+ struct kdbus_args args = { |
18229 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
18230 |
-+ .argv = argv, |
18231 |
-+ .argc = ARRAY_SIZE(argv), |
18232 |
-+ }; |
18233 |
-+ |
18234 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
18235 |
-+ return -EOPNOTSUPP; |
18236 |
-+ |
18237 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
18238 |
-+ if (ret != 0) |
18239 |
-+ return ret; |
18240 |
-+ |
18241 |
-+ ret = kdbus_name_release(conn->ep->bus->name_registry, conn, |
18242 |
-+ argv[1].item->str); |
18243 |
-+ return kdbus_args_clear(&args, ret); |
18244 |
-+} |
18245 |
-+ |
18246 |
-+static int kdbus_list_write(struct kdbus_conn *conn, |
18247 |
-+ struct kdbus_conn *c, |
18248 |
-+ struct kdbus_pool_slice *slice, |
18249 |
-+ size_t *pos, |
18250 |
-+ struct kdbus_name_owner *o, |
18251 |
-+ bool write) |
18252 |
-+{ |
18253 |
-+ struct kvec kvec[4]; |
18254 |
-+ size_t cnt = 0; |
18255 |
-+ int ret; |
18256 |
-+ |
18257 |
-+ /* info header */ |
18258 |
-+ struct kdbus_info info = { |
18259 |
-+ .size = 0, |
18260 |
-+ .id = c->id, |
18261 |
-+ .flags = c->flags, |
18262 |
-+ }; |
18263 |
-+ |
18264 |
-+ /* fake the header of a kdbus_name item */ |
18265 |
-+ struct { |
18266 |
-+ u64 size; |
18267 |
-+ u64 type; |
18268 |
-+ u64 flags; |
18269 |
-+ } h = {}; |
18270 |
-+ |
18271 |
-+ if (o && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(), |
18272 |
-+ o->name->name)) |
18273 |
-+ return 0; |
18274 |
-+ |
18275 |
-+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size); |
18276 |
-+ |
18277 |
-+ /* append name */ |
18278 |
-+ if (o) { |
18279 |
-+ size_t slen = strlen(o->name->name) + 1; |
18280 |
-+ |
18281 |
-+ h.size = offsetof(struct kdbus_item, name.name) + slen; |
18282 |
-+ h.type = KDBUS_ITEM_OWNED_NAME; |
18283 |
-+ h.flags = o->flags; |
18284 |
-+ |
18285 |
-+ kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size); |
18286 |
-+ kdbus_kvec_set(&kvec[cnt++], o->name->name, slen, &info.size); |
18287 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size); |
18288 |
-+ } |
18289 |
-+ |
18290 |
-+ if (write) { |
18291 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, *pos, kvec, |
18292 |
-+ cnt, info.size); |
18293 |
-+ if (ret < 0) |
18294 |
-+ return ret; |
18295 |
-+ } |
18296 |
-+ |
18297 |
-+ *pos += info.size; |
18298 |
-+ return 0; |
18299 |
-+} |
18300 |
-+ |
18301 |
-+static int kdbus_list_all(struct kdbus_conn *conn, u64 flags, |
18302 |
-+ struct kdbus_pool_slice *slice, |
18303 |
-+ size_t *pos, bool write) |
18304 |
-+{ |
18305 |
-+ struct kdbus_conn *c; |
18306 |
-+ size_t p = *pos; |
18307 |
-+ int ret, i; |
18308 |
-+ |
18309 |
-+ hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) { |
18310 |
-+ bool added = false; |
18311 |
-+ |
18312 |
-+ /* skip monitors */ |
18313 |
-+ if (kdbus_conn_is_monitor(c)) |
18314 |
-+ continue; |
18315 |
-+ |
18316 |
-+ /* all names the connection owns */ |
18317 |
-+ if (flags & (KDBUS_LIST_NAMES | |
18318 |
-+ KDBUS_LIST_ACTIVATORS | |
18319 |
-+ KDBUS_LIST_QUEUED)) { |
18320 |
-+ struct kdbus_name_owner *o; |
18321 |
-+ |
18322 |
-+ list_for_each_entry(o, &c->names_list, conn_entry) { |
18323 |
-+ if (o->flags & KDBUS_NAME_ACTIVATOR) { |
18324 |
-+ if (!(flags & KDBUS_LIST_ACTIVATORS)) |
18325 |
-+ continue; |
18326 |
-+ |
18327 |
-+ ret = kdbus_list_write(conn, c, slice, |
18328 |
-+ &p, o, write); |
18329 |
-+ if (ret < 0) { |
18330 |
-+ mutex_unlock(&c->lock); |
18331 |
-+ return ret; |
18332 |
-+ } |
18333 |
-+ |
18334 |
-+ added = true; |
18335 |
-+ } else if (o->flags & KDBUS_NAME_IN_QUEUE) { |
18336 |
-+ if (!(flags & KDBUS_LIST_QUEUED)) |
18337 |
-+ continue; |
18338 |
-+ |
18339 |
-+ ret = kdbus_list_write(conn, c, slice, |
18340 |
-+ &p, o, write); |
18341 |
-+ if (ret < 0) { |
18342 |
-+ mutex_unlock(&c->lock); |
18343 |
-+ return ret; |
18344 |
-+ } |
18345 |
-+ |
18346 |
-+ added = true; |
18347 |
-+ } else if (flags & KDBUS_LIST_NAMES) { |
18348 |
-+ ret = kdbus_list_write(conn, c, slice, |
18349 |
-+ &p, o, write); |
18350 |
-+ if (ret < 0) { |
18351 |
-+ mutex_unlock(&c->lock); |
18352 |
-+ return ret; |
18353 |
-+ } |
18354 |
-+ |
18355 |
-+ added = true; |
18356 |
-+ } |
18357 |
-+ } |
18358 |
-+ } |
18359 |
-+ |
18360 |
-+ /* nothing added so far, just add the unique ID */ |
18361 |
-+ if (!added && (flags & KDBUS_LIST_UNIQUE)) { |
18362 |
-+ ret = kdbus_list_write(conn, c, slice, &p, NULL, write); |
18363 |
-+ if (ret < 0) |
18364 |
-+ return ret; |
18365 |
-+ } |
18366 |
-+ } |
18367 |
-+ |
18368 |
-+ *pos = p; |
18369 |
-+ return 0; |
18370 |
-+} |
18371 |
-+ |
18372 |
-+/** |
18373 |
-+ * kdbus_cmd_list() - handle KDBUS_CMD_LIST |
18374 |
-+ * @conn: connection to operate on |
18375 |
-+ * @argp: command payload |
18376 |
-+ * |
18377 |
-+ * Return: >=0 on success, negative error code on failure. |
18378 |
-+ */ |
18379 |
-+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp) |
18380 |
-+{ |
18381 |
-+ struct kdbus_name_registry *reg = conn->ep->bus->name_registry; |
18382 |
-+ struct kdbus_pool_slice *slice = NULL; |
18383 |
-+ struct kdbus_cmd_list *cmd; |
18384 |
-+ size_t pos, size; |
18385 |
-+ int ret; |
18386 |
-+ |
18387 |
-+ struct kdbus_arg argv[] = { |
18388 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
18389 |
-+ }; |
18390 |
-+ struct kdbus_args args = { |
18391 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
18392 |
-+ KDBUS_LIST_UNIQUE | |
18393 |
-+ KDBUS_LIST_NAMES | |
18394 |
-+ KDBUS_LIST_ACTIVATORS | |
18395 |
-+ KDBUS_LIST_QUEUED, |
18396 |
-+ .argv = argv, |
18397 |
-+ .argc = ARRAY_SIZE(argv), |
18398 |
-+ }; |
18399 |
-+ |
18400 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
18401 |
-+ if (ret != 0) |
18402 |
-+ return ret; |
18403 |
-+ |
18404 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
18405 |
-+ down_read(®->rwlock); |
18406 |
-+ down_read(&conn->ep->bus->conn_rwlock); |
18407 |
-+ down_read(&conn->ep->policy_db.entries_rwlock); |
18408 |
-+ |
18409 |
-+ /* size of records */ |
18410 |
-+ size = 0; |
18411 |
-+ ret = kdbus_list_all(conn, cmd->flags, NULL, &size, false); |
18412 |
-+ if (ret < 0) |
18413 |
-+ goto exit_unlock; |
18414 |
-+ |
18415 |
-+ if (size == 0) { |
18416 |
-+ kdbus_pool_publish_empty(conn->pool, &cmd->offset, |
18417 |
-+ &cmd->list_size); |
18418 |
-+ } else { |
18419 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
18420 |
-+ if (IS_ERR(slice)) { |
18421 |
-+ ret = PTR_ERR(slice); |
18422 |
-+ slice = NULL; |
18423 |
-+ goto exit_unlock; |
18424 |
-+ } |
18425 |
-+ |
18426 |
-+ /* copy the records */ |
18427 |
-+ pos = 0; |
18428 |
-+ ret = kdbus_list_all(conn, cmd->flags, slice, &pos, true); |
18429 |
-+ if (ret < 0) |
18430 |
-+ goto exit_unlock; |
18431 |
-+ |
18432 |
-+ WARN_ON(pos != size); |
18433 |
-+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->list_size); |
18434 |
-+ } |
18435 |
-+ |
18436 |
-+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
18437 |
-+ kdbus_member_set_user(&cmd->list_size, argp, |
18438 |
-+ typeof(*cmd), list_size)) |
18439 |
-+ ret = -EFAULT; |
18440 |
-+ |
18441 |
-+exit_unlock: |
18442 |
-+ up_read(&conn->ep->policy_db.entries_rwlock); |
18443 |
-+ up_read(&conn->ep->bus->conn_rwlock); |
18444 |
-+ up_read(®->rwlock); |
18445 |
-+ kdbus_pool_slice_release(slice); |
18446 |
-+ return kdbus_args_clear(&args, ret); |
18447 |
-+} |
18448 |
-diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h |
18449 |
-new file mode 100644 |
18450 |
-index 0000000..edac59d |
18451 |
---- /dev/null |
18452 |
-+++ b/ipc/kdbus/names.h |
18453 |
-@@ -0,0 +1,105 @@ |
18454 |
-+/* |
18455 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
18456 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
18457 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
18458 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
18459 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
18460 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
18461 |
-+ * |
18462 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
18463 |
-+ * the terms of the GNU Lesser General Public License as published by the |
18464 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
18465 |
-+ * your option) any later version. |
18466 |
-+ */ |
18467 |
-+ |
18468 |
-+#ifndef __KDBUS_NAMES_H |
18469 |
-+#define __KDBUS_NAMES_H |
18470 |
-+ |
18471 |
-+#include <linux/hashtable.h> |
18472 |
-+#include <linux/rwsem.h> |
18473 |
-+ |
18474 |
-+struct kdbus_name_entry; |
18475 |
-+struct kdbus_name_owner; |
18476 |
-+struct kdbus_name_registry; |
18477 |
-+ |
18478 |
-+/** |
18479 |
-+ * struct kdbus_name_registry - names registered for a bus |
18480 |
-+ * @entries_hash: Map of entries |
18481 |
-+ * @lock: Registry data lock |
18482 |
-+ * @name_seq_last: Last used sequence number to assign to a name entry |
18483 |
-+ */ |
18484 |
-+struct kdbus_name_registry { |
18485 |
-+ DECLARE_HASHTABLE(entries_hash, 8); |
18486 |
-+ struct rw_semaphore rwlock; |
18487 |
-+ u64 name_seq_last; |
18488 |
-+}; |
18489 |
-+ |
18490 |
-+/** |
18491 |
-+ * struct kdbus_name_entry - well-know name entry |
18492 |
-+ * @name_id: sequence number of name entry to be able to uniquely |
18493 |
-+ * identify a name over its registration lifetime |
18494 |
-+ * @activator: activator of this name, or NULL |
18495 |
-+ * @queue: list of queued owners |
18496 |
-+ * @hentry: entry in registry map |
18497 |
-+ * @name: well-known name |
18498 |
-+ */ |
18499 |
-+struct kdbus_name_entry { |
18500 |
-+ u64 name_id; |
18501 |
-+ struct kdbus_name_owner *activator; |
18502 |
-+ struct list_head queue; |
18503 |
-+ struct hlist_node hentry; |
18504 |
-+ char name[]; |
18505 |
-+}; |
18506 |
-+ |
18507 |
-+/** |
18508 |
-+ * struct kdbus_name_owner - owner of a well-known name |
18509 |
-+ * @flags: KDBUS_NAME_* flags of this owner |
18510 |
-+ * @conn: connection owning the name |
18511 |
-+ * @name: name that is owned |
18512 |
-+ * @conn_entry: link into @conn |
18513 |
-+ * @name_entry: link into @name |
18514 |
-+ */ |
18515 |
-+struct kdbus_name_owner { |
18516 |
-+ u64 flags; |
18517 |
-+ struct kdbus_conn *conn; |
18518 |
-+ struct kdbus_name_entry *name; |
18519 |
-+ struct list_head conn_entry; |
18520 |
-+ struct list_head name_entry; |
18521 |
-+}; |
18522 |
-+ |
18523 |
-+bool kdbus_name_is_valid(const char *p, bool allow_wildcard); |
18524 |
-+ |
18525 |
-+struct kdbus_name_registry *kdbus_name_registry_new(void); |
18526 |
-+void kdbus_name_registry_free(struct kdbus_name_registry *reg); |
18527 |
-+ |
18528 |
-+struct kdbus_name_entry * |
18529 |
-+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name); |
18530 |
-+ |
18531 |
-+int kdbus_name_acquire(struct kdbus_name_registry *reg, |
18532 |
-+ struct kdbus_conn *conn, const char *name, |
18533 |
-+ u64 flags, u64 *return_flags); |
18534 |
-+void kdbus_name_release_all(struct kdbus_name_registry *reg, |
18535 |
-+ struct kdbus_conn *conn); |
18536 |
-+ |
18537 |
-+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp); |
18538 |
-+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp); |
18539 |
-+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp); |
18540 |
-+ |
18541 |
-+/** |
18542 |
-+ * kdbus_name_get_owner() - get current owner of a name |
18543 |
-+ * @name: name to get current owner of |
18544 |
-+ * |
18545 |
-+ * This returns a pointer to the current owner of a name (or its activator if |
18546 |
-+ * there is no owner). The caller must make sure @name is valid and does not |
18547 |
-+ * vanish. |
18548 |
-+ * |
18549 |
-+ * Return: Pointer to current owner or NULL if there is none. |
18550 |
-+ */ |
18551 |
-+static inline struct kdbus_name_owner * |
18552 |
-+kdbus_name_get_owner(struct kdbus_name_entry *name) |
18553 |
-+{ |
18554 |
-+ return list_first_entry_or_null(&name->queue, struct kdbus_name_owner, |
18555 |
-+ name_entry) ? : name->activator; |
18556 |
-+} |
18557 |
-+ |
18558 |
-+#endif |
18559 |
-diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c |
18560 |
-new file mode 100644 |
18561 |
-index 0000000..89f58bc |
18562 |
---- /dev/null |
18563 |
-+++ b/ipc/kdbus/node.c |
18564 |
-@@ -0,0 +1,897 @@ |
18565 |
-+/* |
18566 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
18567 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
18568 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
18569 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
18570 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
18571 |
-+ * |
18572 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
18573 |
-+ * the terms of the GNU Lesser General Public License as published by the |
18574 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
18575 |
-+ * your option) any later version. |
18576 |
-+ */ |
18577 |
-+ |
18578 |
-+#include <linux/atomic.h> |
18579 |
-+#include <linux/fs.h> |
18580 |
-+#include <linux/idr.h> |
18581 |
-+#include <linux/kdev_t.h> |
18582 |
-+#include <linux/rbtree.h> |
18583 |
-+#include <linux/rwsem.h> |
18584 |
-+#include <linux/sched.h> |
18585 |
-+#include <linux/slab.h> |
18586 |
-+#include <linux/wait.h> |
18587 |
-+ |
18588 |
-+#include "bus.h" |
18589 |
-+#include "domain.h" |
18590 |
-+#include "endpoint.h" |
18591 |
-+#include "fs.h" |
18592 |
-+#include "handle.h" |
18593 |
-+#include "node.h" |
18594 |
-+#include "util.h" |
18595 |
-+ |
18596 |
-+/** |
18597 |
-+ * DOC: kdbus nodes |
18598 |
-+ * |
18599 |
-+ * Nodes unify lifetime management across exposed kdbus objects and provide a |
18600 |
-+ * hierarchy. Each kdbus object, that might be exposed to user-space, has a |
18601 |
-+ * kdbus_node object embedded and is linked into the hierarchy. Each node can |
18602 |
-+ * have any number (0-n) of child nodes linked. Each child retains a reference |
18603 |
-+ * to its parent node. For root-nodes, the parent is NULL. |
18604 |
-+ * |
18605 |
-+ * Each node object goes through a bunch of states during it's lifetime: |
18606 |
-+ * * NEW |
18607 |
-+ * * LINKED (can be skipped by NEW->FREED transition) |
18608 |
-+ * * ACTIVE (can be skipped by LINKED->INACTIVE transition) |
18609 |
-+ * * INACTIVE |
18610 |
-+ * * DRAINED |
18611 |
-+ * * FREED |
18612 |
-+ * |
18613 |
-+ * Each node is allocated by the caller and initialized via kdbus_node_init(). |
18614 |
-+ * This never fails and sets the object into state NEW. From now on, ref-counts |
18615 |
-+ * on the node manage its lifetime. During init, the ref-count is set to 1. Once |
18616 |
-+ * it drops to 0, the node goes to state FREED and the node->free_cb() callback |
18617 |
-+ * is called to deallocate any memory. |
18618 |
-+ * |
18619 |
-+ * After initializing a node, you usually link it into the hierarchy. You need |
18620 |
-+ * to provide a parent node and a name. The node will be linked as child to the |
18621 |
-+ * parent and a globally unique ID is assigned to the child. The name of the |
18622 |
-+ * child must be unique for all children of this parent. Otherwise, linking the |
18623 |
-+ * child will fail with -EEXIST. |
18624 |
-+ * Note that the child is not marked active, yet. Admittedly, it prevents any |
18625 |
-+ * other node from being linked with the same name (thus, it reserves that |
18626 |
-+ * name), but any child-lookup (via name or unique ID) will never return this |
18627 |
-+ * child unless it has been marked active. |
18628 |
-+ * |
18629 |
-+ * Once successfully linked, you can use kdbus_node_activate() to activate a |
18630 |
-+ * child. This will mark the child active. This state can be skipped by directly |
18631 |
-+ * deactivating the child via kdbus_node_deactivate() (see below). |
18632 |
-+ * By activating a child, you enable any lookups on this child to succeed from |
18633 |
-+ * now on. Furthermore, any code that got its hands on a reference to the node, |
18634 |
-+ * can from now on "acquire" the node. |
18635 |
-+ * |
18636 |
-+ * Active References (or: 'acquiring' and 'releasing' a node) |
18637 |
-+ * Additionally to normal object references, nodes support something we call |
18638 |
-+ * "active references". An active reference can be acquired via |
18639 |
-+ * kdbus_node_acquire() and released via kdbus_node_release(). A caller |
18640 |
-+ * _must_ own a normal object reference whenever calling those functions. |
18641 |
-+ * Unlike object references, acquiring an active reference can fail (by |
18642 |
-+ * returning 'false' from kdbus_node_acquire()). An active reference can |
18643 |
-+ * only be acquired if the node is marked active. If it is not marked |
18644 |
-+ * active, yet, or if it was already deactivated, no more active references |
18645 |
-+ * can be acquired, ever! |
18646 |
-+ * Active references are used to track tasks working on a node. Whenever a |
18647 |
-+ * task enters kernel-space to perform an action on a node, it acquires an |
18648 |
-+ * active reference, performs the action and releases the reference again. |
18649 |
-+ * While holding an active reference, the node is guaranteed to stay active. |
18650 |
-+ * If the node is deactivated in parallel, the node is marked as |
18651 |
-+ * deactivated, then we wait for all active references to be dropped, before |
18652 |
-+ * we finally proceed with any cleanups. That is, if you hold an active |
18653 |
-+ * reference to a node, any resources that are bound to the "active" state |
18654 |
-+ * are guaranteed to stay accessible until you release your reference. |
18655 |
-+ * |
18656 |
-+ * Active-references are very similar to rw-locks, where acquiring a node is |
18657 |
-+ * equal to try-read-lock and releasing to read-unlock. Deactivating a node |
18658 |
-+ * means write-lock and never releasing it again. |
18659 |
-+ * Unlike rw-locks, the 'active reference' concept is more versatile and |
18660 |
-+ * avoids unusual rw-lock usage (never releasing a write-lock..). |
18661 |
-+ * |
18662 |
-+ * It is safe to acquire multiple active-references recursively. But you |
18663 |
-+ * need to check the return value of kdbus_node_acquire() on _each_ call. It |
18664 |
-+ * may stop granting references at _any_ time. |
18665 |
-+ * |
18666 |
-+ * You're free to perform any operations you want while holding an active |
18667 |
-+ * reference, except sleeping for an indefinite period. Sleeping for a fixed |
18668 |
-+ * amount of time is fine, but you usually should not wait on wait-queues |
18669 |
-+ * without a timeout. |
18670 |
-+ * For example, if you wait for I/O to happen, you should gather all data |
18671 |
-+ * and schedule the I/O operation, then release your active reference and |
18672 |
-+ * wait for it to complete. Then try to acquire a new reference. If it |
18673 |
-+ * fails, perform any cleanup (the node is now dead). Otherwise, you can |
18674 |
-+ * finish your operation. |
18675 |
-+ * |
18676 |
-+ * All nodes can be deactivated via kdbus_node_deactivate() at any time. You can |
18677 |
-+ * call this multiple times, even in parallel or on nodes that were never |
18678 |
-+ * linked, and it will just work. The only restriction is, you must not hold an |
18679 |
-+ * active reference when calling kdbus_node_deactivate(). |
18680 |
-+ * By deactivating a node, it is immediately marked inactive. Then, we wait for |
18681 |
-+ * all active references to be released (called 'draining' the node). This |
18682 |
-+ * shouldn't take very long as we don't perform long-lasting operations while |
18683 |
-+ * holding an active reference. Note that once the node is marked inactive, no |
18684 |
-+ * new active references can be acquired. |
18685 |
-+ * Once all active references are dropped, the node is considered 'drained'. Now |
18686 |
-+ * kdbus_node_deactivate() is called on each child of the node before we |
18687 |
-+ * continue deactivating our node. That is, once all children are entirely |
18688 |
-+ * deactivated, we call ->release_cb() of our node. ->release_cb() can release |
18689 |
-+ * any resources on that node which are bound to the "active" state of a node. |
18690 |
-+ * When done, we unlink the node from its parent rb-tree, mark it as |
18691 |
-+ * 'released' and return. |
18692 |
-+ * If kdbus_node_deactivate() is called multiple times (even in parallel), all |
18693 |
-+ * but one caller will just wait until the node is fully deactivated. That is, |
18694 |
-+ * one random caller of kdbus_node_deactivate() is selected to call |
18695 |
-+ * ->release_cb() and cleanup the node. Only once all this is done, all other |
18696 |
-+ * callers will return from kdbus_node_deactivate(). That is, it doesn't matter |
18697 |
-+ * whether you're the selected caller or not, it will only return after |
18698 |
-+ * everything is fully done. |
18699 |
-+ * |
18700 |
-+ * When a node is activated, we acquire a normal object reference to the node. |
18701 |
-+ * This reference is dropped after deactivation is fully done (and only iff the |
18702 |
-+ * node really was activated). This allows callers to link+activate a child node |
18703 |
-+ * and then drop all refs. The node will be deactivated together with the |
18704 |
-+ * parent, and then be freed when this reference is dropped. |
18705 |
-+ * |
18706 |
-+ * Currently, nodes provide a bunch of resources that external code can use |
18707 |
-+ * directly. This includes: |
18708 |
-+ * |
18709 |
-+ * * node->waitq: Each node has its own wait-queue that is used to manage |
18710 |
-+ * the 'active' state. When a node is deactivated, we wait on |
18711 |
-+ * this queue until all active refs are dropped. Analogously, |
18712 |
-+ * when you release an active reference on a deactivated |
18713 |
-+ * node, and the active ref-count drops to 0, we wake up a |
18714 |
-+ * single thread on this queue. Furthermore, once the |
18715 |
-+ * ->release_cb() callback finished, we wake up all waiters. |
18716 |
-+ * The node-owner is free to re-use this wait-queue for other |
18717 |
-+ * purposes. As node-management uses this queue only during |
18718 |
-+ * deactivation, it is usually totally fine to re-use the |
18719 |
-+ * queue for other, preferably low-overhead, use-cases. |
18720 |
-+ * |
18721 |
-+ * * node->type: This field defines the type of the owner of this node. It |
18722 |
-+ * must be set during node initialization and must remain |
18723 |
-+ * constant. The node management never looks at this value, |
18724 |
-+ * but external users might use to gain access to the owner |
18725 |
-+ * object of a node. |
18726 |
-+ * It is totally up to the owner of the node to define what |
18727 |
-+ * their type means. Usually it means you can access the |
18728 |
-+ * parent structure via container_of(), as long as you hold an |
18729 |
-+ * active reference to the node. |
18730 |
-+ * |
18731 |
-+ * * node->free_cb: callback after all references are dropped |
18732 |
-+ * node->release_cb: callback during node deactivation |
18733 |
-+ * These fields must be set by the node owner during |
18734 |
-+ * node initialization. They must remain constant. If |
18735 |
-+ * NULL, they're skipped. |
18736 |
-+ * |
18737 |
-+ * * node->mode: filesystem access modes |
18738 |
-+ * node->uid: filesystem owner uid |
18739 |
-+ * node->gid: filesystem owner gid |
18740 |
-+ * These fields must be set by the node owner during node |
18741 |
-+ * initialization. They must remain constant and may be |
18742 |
-+ * accessed by other callers to properly initialize |
18743 |
-+ * filesystem nodes. |
18744 |
-+ * |
18745 |
-+ * * node->id: This is an unsigned 32bit integer allocated by an IDA. It is |
18746 |
-+ * always kept as small as possible during allocation and is |
18747 |
-+ * globally unique across all nodes allocated by this module. 0 |
18748 |
-+ * is reserved as "not assigned" and is the default. |
18749 |
-+ * The ID is assigned during kdbus_node_link() and is kept until |
18750 |
-+ * the object is freed. Thus, the ID surpasses the active |
18751 |
-+ * lifetime of a node. As long as you hold an object reference |
18752 |
-+ * to a node (and the node was linked once), the ID is valid and |
18753 |
-+ * unique. |
18754 |
-+ * |
18755 |
-+ * * node->name: name of this node |
18756 |
-+ * node->hash: 31bit hash-value of @name (range [2..INT_MAX-1]) |
18757 |
-+ * These values follow the same lifetime rules as node->id. |
18758 |
-+ * They're initialized when the node is linked and then remain |
18759 |
-+ * constant until the last object reference is dropped. |
18760 |
-+ * Unlike the id, the name is only unique across all siblings |
18761 |
-+ * and only until the node is deactivated. Currently, the name |
18762 |
-+ * is even unique if linked but not activated, yet. This might |
18763 |
-+ * change in the future, though. Code should not rely on this. |
18764 |
-+ * |
18765 |
-+ * * node->lock: lock to protect node->children, node->rb, node->parent |
18766 |
-+ * * node->parent: Reference to parent node. This is set during LINK time |
18767 |
-+ * and is dropped during destruction. You must not access |
18768 |
-+ * it unless you hold an active reference to the node or if |
18769 |
-+ * you know the node is dead. |
18770 |
-+ * * node->children: rb-tree of all linked children of this node. You must |
18771 |
-+ * not access this directly, but use one of the iterator |
18772 |
-+ * or lookup helpers. |
18773 |
-+ */ |
18774 |
-+ |
18775 |
-+/* |
18776 |
-+ * Bias values track states of "active references". They're all negative. If a |
18777 |
-+ * node is active, its active-ref-counter is >=0 and tracks all active |
18778 |
-+ * references. Once a node is deactivaed, we subtract NODE_BIAS. This means, the |
18779 |
-+ * counter is now negative but still counts the active references. Once it drops |
18780 |
-+ * to exactly NODE_BIAS, we know all active references were dropped. Exactly one |
18781 |
-+ * thread will change it to NODE_RELEASE now, perform cleanup and then put it |
18782 |
-+ * into NODE_DRAINED. Once drained, all other threads that tried deactivating |
18783 |
-+ * the node will now be woken up (thus, they wait until the node is fully done). |
18784 |
-+ * The initial state during node-setup is NODE_NEW. If a node is directly |
18785 |
-+ * deactivated without having ever been active, it is put into |
18786 |
-+ * NODE_RELEASE_DIRECT instead of NODE_BIAS. This tracks this one-bit state |
18787 |
-+ * across node-deactivation. The task putting it into NODE_RELEASE now knows |
18788 |
-+ * whether the node was active before or not. |
18789 |
-+ * |
18790 |
-+ * Some archs implement atomic_sub(v) with atomic_add(-v), so reserve INT_MIN |
18791 |
-+ * to avoid overflows if multiplied by -1. |
18792 |
-+ */ |
18793 |
-+#define KDBUS_NODE_BIAS (INT_MIN + 5) |
18794 |
-+#define KDBUS_NODE_RELEASE_DIRECT (KDBUS_NODE_BIAS - 1) |
18795 |
-+#define KDBUS_NODE_RELEASE (KDBUS_NODE_BIAS - 2) |
18796 |
-+#define KDBUS_NODE_DRAINED (KDBUS_NODE_BIAS - 3) |
18797 |
-+#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4) |
18798 |
-+ |
18799 |
-+/* global unique ID mapping for kdbus nodes */ |
18800 |
-+DEFINE_IDA(kdbus_node_ida); |
18801 |
-+ |
18802 |
-+/** |
18803 |
-+ * kdbus_node_name_hash() - hash a name |
18804 |
-+ * @name: The string to hash |
18805 |
-+ * |
18806 |
-+ * This computes the hash of @name. It is guaranteed to be in the range |
18807 |
-+ * [2..INT_MAX-1]. The values 1, 2 and INT_MAX are unused as they are reserved |
18808 |
-+ * for the filesystem code. |
18809 |
-+ * |
18810 |
-+ * Return: hash value of the passed string |
18811 |
-+ */ |
18812 |
-+static unsigned int kdbus_node_name_hash(const char *name) |
18813 |
-+{ |
18814 |
-+ unsigned int hash; |
18815 |
-+ |
18816 |
-+ /* reserve hash numbers 0, 1 and >=INT_MAX for magic directories */ |
18817 |
-+ hash = kdbus_strhash(name) & INT_MAX; |
18818 |
-+ if (hash < 2) |
18819 |
-+ hash += 2; |
18820 |
-+ if (hash >= INT_MAX) |
18821 |
-+ hash = INT_MAX - 1; |
18822 |
-+ |
18823 |
-+ return hash; |
18824 |
-+} |
18825 |
-+ |
18826 |
-+/** |
18827 |
-+ * kdbus_node_name_compare() - compare a name with a node's name |
18828 |
-+ * @hash: hash of the string to compare the node with |
18829 |
-+ * @name: name to compare the node with |
18830 |
-+ * @node: node to compare the name with |
18831 |
-+ * |
18832 |
-+ * Return: 0 if @name and @hash exactly match the information in @node, or |
18833 |
-+ * an integer less than or greater than zero if @name is found, respectively, |
18834 |
-+ * to be less than or be greater than the string stored in @node. |
18835 |
-+ */ |
18836 |
-+static int kdbus_node_name_compare(unsigned int hash, const char *name, |
18837 |
-+ const struct kdbus_node *node) |
18838 |
-+{ |
18839 |
-+ if (hash != node->hash) |
18840 |
-+ return hash - node->hash; |
18841 |
-+ |
18842 |
-+ return strcmp(name, node->name); |
18843 |
-+} |
18844 |
-+ |
18845 |
-+/** |
18846 |
-+ * kdbus_node_init() - initialize a kdbus_node |
18847 |
-+ * @node: Pointer to the node to initialize |
18848 |
-+ * @type: The type the node will have (KDBUS_NODE_*) |
18849 |
-+ * |
18850 |
-+ * The caller is responsible of allocating @node and initializating it to zero. |
18851 |
-+ * Once this call returns, you must use the node_ref() and node_unref() |
18852 |
-+ * functions to manage this node. |
18853 |
-+ */ |
18854 |
-+void kdbus_node_init(struct kdbus_node *node, unsigned int type) |
18855 |
-+{ |
18856 |
-+ atomic_set(&node->refcnt, 1); |
18857 |
-+ mutex_init(&node->lock); |
18858 |
-+ node->id = 0; |
18859 |
-+ node->type = type; |
18860 |
-+ RB_CLEAR_NODE(&node->rb); |
18861 |
-+ node->children = RB_ROOT; |
18862 |
-+ init_waitqueue_head(&node->waitq); |
18863 |
-+ atomic_set(&node->active, KDBUS_NODE_NEW); |
18864 |
-+} |
18865 |
-+ |
18866 |
-+/** |
18867 |
-+ * kdbus_node_link() - link a node into the nodes system |
18868 |
-+ * @node: Pointer to the node to initialize |
18869 |
-+ * @parent: Pointer to a parent node, may be %NULL |
18870 |
-+ * @name: The name of the node (or NULL if root node) |
18871 |
-+ * |
18872 |
-+ * This links a node into the hierarchy. This must not be called multiple times. |
18873 |
-+ * If @parent is NULL, the node becomes a new root node. |
18874 |
-+ * |
18875 |
-+ * This call will fail if @name is not unique across all its siblings or if no |
18876 |
-+ * ID could be allocated. You must not activate a node if linking failed! It is |
18877 |
-+ * safe to deactivate it, though. |
18878 |
-+ * |
18879 |
-+ * Once you linked a node, you must call kdbus_node_deactivate() before you drop |
18880 |
-+ * the last reference (even if you never activate the node). |
18881 |
-+ * |
18882 |
-+ * Return: 0 on success. negative error otherwise. |
18883 |
-+ */ |
18884 |
-+int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, |
18885 |
-+ const char *name) |
18886 |
-+{ |
18887 |
-+ int ret; |
18888 |
-+ |
18889 |
-+ if (WARN_ON(node->type != KDBUS_NODE_DOMAIN && !parent)) |
18890 |
-+ return -EINVAL; |
18891 |
-+ |
18892 |
-+ if (WARN_ON(parent && !name)) |
18893 |
-+ return -EINVAL; |
18894 |
-+ |
18895 |
-+ if (name) { |
18896 |
-+ node->name = kstrdup(name, GFP_KERNEL); |
18897 |
-+ if (!node->name) |
18898 |
-+ return -ENOMEM; |
18899 |
-+ |
18900 |
-+ node->hash = kdbus_node_name_hash(name); |
18901 |
-+ } |
18902 |
-+ |
18903 |
-+ ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL); |
18904 |
-+ if (ret < 0) |
18905 |
-+ return ret; |
18906 |
-+ |
18907 |
-+ node->id = ret; |
18908 |
-+ ret = 0; |
18909 |
-+ |
18910 |
-+ if (parent) { |
18911 |
-+ struct rb_node **n, *prev; |
18912 |
-+ |
18913 |
-+ if (!kdbus_node_acquire(parent)) |
18914 |
-+ return -ESHUTDOWN; |
18915 |
-+ |
18916 |
-+ mutex_lock(&parent->lock); |
18917 |
-+ |
18918 |
-+ n = &parent->children.rb_node; |
18919 |
-+ prev = NULL; |
18920 |
-+ |
18921 |
-+ while (*n) { |
18922 |
-+ struct kdbus_node *pos; |
18923 |
-+ int result; |
18924 |
-+ |
18925 |
-+ pos = kdbus_node_from_rb(*n); |
18926 |
-+ prev = *n; |
18927 |
-+ result = kdbus_node_name_compare(node->hash, |
18928 |
-+ node->name, |
18929 |
-+ pos); |
18930 |
-+ if (result == 0) { |
18931 |
-+ ret = -EEXIST; |
18932 |
-+ goto exit_unlock; |
18933 |
-+ } |
18934 |
-+ |
18935 |
-+ if (result < 0) |
18936 |
-+ n = &pos->rb.rb_left; |
18937 |
-+ else |
18938 |
-+ n = &pos->rb.rb_right; |
18939 |
-+ } |
18940 |
-+ |
18941 |
-+ /* add new node and rebalance the tree */ |
18942 |
-+ rb_link_node(&node->rb, prev, n); |
18943 |
-+ rb_insert_color(&node->rb, &parent->children); |
18944 |
-+ node->parent = kdbus_node_ref(parent); |
18945 |
-+ |
18946 |
-+exit_unlock: |
18947 |
-+ mutex_unlock(&parent->lock); |
18948 |
-+ kdbus_node_release(parent); |
18949 |
-+ } |
18950 |
-+ |
18951 |
-+ return ret; |
18952 |
-+} |
18953 |
-+ |
18954 |
-+/** |
18955 |
-+ * kdbus_node_ref() - Acquire object reference |
18956 |
-+ * @node: node to acquire reference to (or NULL) |
18957 |
-+ * |
18958 |
-+ * This acquires a new reference to @node. You must already own a reference when |
18959 |
-+ * calling this! |
18960 |
-+ * If @node is NULL, this is a no-op. |
18961 |
-+ * |
18962 |
-+ * Return: @node is returned |
18963 |
-+ */ |
18964 |
-+struct kdbus_node *kdbus_node_ref(struct kdbus_node *node) |
18965 |
-+{ |
18966 |
-+ if (node) |
18967 |
-+ atomic_inc(&node->refcnt); |
18968 |
-+ return node; |
18969 |
-+} |
18970 |
-+ |
18971 |
-+/** |
18972 |
-+ * kdbus_node_unref() - Drop object reference |
18973 |
-+ * @node: node to drop reference to (or NULL) |
18974 |
-+ * |
18975 |
-+ * This drops an object reference to @node. You must not access the node if you |
18976 |
-+ * no longer own a reference. |
18977 |
-+ * If the ref-count drops to 0, the object will be destroyed (->free_cb will be |
18978 |
-+ * called). |
18979 |
-+ * |
18980 |
-+ * If you linked or activated the node, you must deactivate the node before you |
18981 |
-+ * drop your last reference! If you didn't link or activate the node, you can |
18982 |
-+ * drop any reference you want. |
18983 |
-+ * |
18984 |
-+ * Note that this calls into ->free_cb() and thus _might_ sleep. The ->free_cb() |
18985 |
-+ * callbacks must not acquire any outer locks, though. So you can safely drop |
18986 |
-+ * references while holding locks. |
18987 |
-+ * |
18988 |
-+ * If @node is NULL, this is a no-op. |
18989 |
-+ * |
18990 |
-+ * Return: This always returns NULL |
18991 |
-+ */ |
18992 |
-+struct kdbus_node *kdbus_node_unref(struct kdbus_node *node) |
18993 |
-+{ |
18994 |
-+ if (node && atomic_dec_and_test(&node->refcnt)) { |
18995 |
-+ struct kdbus_node safe = *node; |
18996 |
-+ |
18997 |
-+ WARN_ON(atomic_read(&node->active) != KDBUS_NODE_DRAINED); |
18998 |
-+ WARN_ON(!RB_EMPTY_NODE(&node->rb)); |
18999 |
-+ |
19000 |
-+ if (node->free_cb) |
19001 |
-+ node->free_cb(node); |
19002 |
-+ if (safe.id > 0) |
19003 |
-+ ida_simple_remove(&kdbus_node_ida, safe.id); |
19004 |
-+ |
19005 |
-+ kfree(safe.name); |
19006 |
-+ |
19007 |
-+ /* |
19008 |
-+ * kdbusfs relies on the parent to be available even after the |
19009 |
-+ * node was deactivated and unlinked. Therefore, we pin it |
19010 |
-+ * until a node is destroyed. |
19011 |
-+ */ |
19012 |
-+ kdbus_node_unref(safe.parent); |
19013 |
-+ } |
19014 |
-+ |
19015 |
-+ return NULL; |
19016 |
-+} |
19017 |
-+ |
19018 |
-+/** |
19019 |
-+ * kdbus_node_is_active() - test whether a node is active |
19020 |
-+ * @node: node to test |
19021 |
-+ * |
19022 |
-+ * This checks whether @node is active. That means, @node was linked and |
19023 |
-+ * activated by the node owner and hasn't been deactivated, yet. If, and only |
19024 |
-+ * if, a node is active, kdbus_node_acquire() will be able to acquire active |
19025 |
-+ * references. |
19026 |
-+ * |
19027 |
-+ * Note that this function does not give any lifetime guarantees. After this |
19028 |
-+ * call returns, the node might be deactivated immediately. Normally, what you |
19029 |
-+ * want is to acquire a real active reference via kdbus_node_acquire(). |
19030 |
-+ * |
19031 |
-+ * Return: true if @node is active, false otherwise |
19032 |
-+ */ |
19033 |
-+bool kdbus_node_is_active(struct kdbus_node *node) |
19034 |
-+{ |
19035 |
-+ return atomic_read(&node->active) >= 0; |
19036 |
-+} |
19037 |
-+ |
19038 |
-+/** |
19039 |
-+ * kdbus_node_is_deactivated() - test whether a node was already deactivated |
19040 |
-+ * @node: node to test |
19041 |
-+ * |
19042 |
-+ * This checks whether kdbus_node_deactivate() was called on @node. Note that |
19043 |
-+ * this might be true even if you never deactivated the node directly, but only |
19044 |
-+ * one of its ancestors. |
19045 |
-+ * |
19046 |
-+ * Note that even if this returns 'false', the node might get deactivated |
19047 |
-+ * immediately after the call returns. |
19048 |
-+ * |
19049 |
-+ * Return: true if @node was already deactivated, false if not |
19050 |
-+ */ |
19051 |
-+bool kdbus_node_is_deactivated(struct kdbus_node *node) |
19052 |
-+{ |
19053 |
-+ int v; |
19054 |
-+ |
19055 |
-+ v = atomic_read(&node->active); |
19056 |
-+ return v != KDBUS_NODE_NEW && v < 0; |
19057 |
-+} |
19058 |
-+ |
19059 |
-+/** |
19060 |
-+ * kdbus_node_activate() - activate a node |
19061 |
-+ * @node: node to activate |
19062 |
-+ * |
19063 |
-+ * This marks @node as active if, and only if, the node wasn't activated nor |
19064 |
-+ * deactivated, yet, and the parent is still active. Any but the first call to |
19065 |
-+ * kdbus_node_activate() is a no-op. |
19066 |
-+ * If you called kdbus_node_deactivate() before, then even the first call to |
19067 |
-+ * kdbus_node_activate() will be a no-op. |
19068 |
-+ * |
19069 |
-+ * This call doesn't give any lifetime guarantees. The node might get |
19070 |
-+ * deactivated immediately after this call returns. Or the parent might already |
19071 |
-+ * be deactivated, which will make this call a no-op. |
19072 |
-+ * |
19073 |
-+ * If this call successfully activated a node, it will take an object reference |
19074 |
-+ * to it. This reference is dropped after the node is deactivated. Therefore, |
19075 |
-+ * the object owner can safely drop their reference to @node iff they know that |
19076 |
-+ * its parent node will get deactivated at some point. Once the parent node is |
19077 |
-+ * deactivated, it will deactivate all its child and thus drop this reference |
19078 |
-+ * again. |
19079 |
-+ * |
19080 |
-+ * Return: True if this call successfully activated the node, otherwise false. |
19081 |
-+ * Note that this might return false, even if the node is still active |
19082 |
-+ * (eg., if you called this a second time). |
19083 |
-+ */ |
19084 |
-+bool kdbus_node_activate(struct kdbus_node *node) |
19085 |
-+{ |
19086 |
-+ bool res = false; |
19087 |
-+ |
19088 |
-+ mutex_lock(&node->lock); |
19089 |
-+ if (atomic_read(&node->active) == KDBUS_NODE_NEW) { |
19090 |
-+ atomic_sub(KDBUS_NODE_NEW, &node->active); |
19091 |
-+ /* activated nodes have ref +1 */ |
19092 |
-+ kdbus_node_ref(node); |
19093 |
-+ res = true; |
19094 |
-+ } |
19095 |
-+ mutex_unlock(&node->lock); |
19096 |
-+ |
19097 |
-+ return res; |
19098 |
-+} |
19099 |
-+ |
19100 |
-+/** |
19101 |
-+ * kdbus_node_deactivate() - deactivate a node |
19102 |
-+ * @node: The node to deactivate. |
19103 |
-+ * |
19104 |
-+ * This function recursively deactivates this node and all its children. It |
19105 |
-+ * returns only once all children and the node itself were recursively disabled |
19106 |
-+ * (even if you call this function multiple times in parallel). |
19107 |
-+ * |
19108 |
-+ * It is safe to call this function on _any_ node that was initialized _any_ |
19109 |
-+ * number of times. |
19110 |
-+ * |
19111 |
-+ * This call may sleep, as it waits for all active references to be dropped. |
19112 |
-+ */ |
19113 |
-+void kdbus_node_deactivate(struct kdbus_node *node) |
19114 |
-+{ |
19115 |
-+ struct kdbus_node *pos, *child; |
19116 |
-+ struct rb_node *rb; |
19117 |
-+ int v_pre, v_post; |
19118 |
-+ |
19119 |
-+ pos = node; |
19120 |
-+ |
19121 |
-+ /* |
19122 |
-+ * To avoid recursion, we perform back-tracking while deactivating |
19123 |
-+ * nodes. For each node we enter, we first mark the active-counter as |
19124 |
-+ * deactivated by adding BIAS. If the node as children, we set the first |
19125 |
-+ * child as current position and start over. If the node has no |
19126 |
-+ * children, we drain the node by waiting for all active refs to be |
19127 |
-+ * dropped and then releasing the node. |
19128 |
-+ * |
19129 |
-+ * After the node is released, we set its parent as current position |
19130 |
-+ * and start over. If the current position was the initial node, we're |
19131 |
-+ * done. |
19132 |
-+ * |
19133 |
-+ * Note that this function can be called in parallel by multiple |
19134 |
-+ * callers. We make sure that each node is only released once, and any |
19135 |
-+ * racing caller will wait until the other thread fully released that |
19136 |
-+ * node. |
19137 |
-+ */ |
19138 |
-+ |
19139 |
-+ for (;;) { |
19140 |
-+ /* |
19141 |
-+ * Add BIAS to node->active to mark it as inactive. If it was |
19142 |
-+ * never active before, immediately mark it as RELEASE_INACTIVE |
19143 |
-+ * so we remember this state. |
19144 |
-+ * We cannot remember v_pre as we might iterate into the |
19145 |
-+ * children, overwriting v_pre, before we can release our node. |
19146 |
-+ */ |
19147 |
-+ mutex_lock(&pos->lock); |
19148 |
-+ v_pre = atomic_read(&pos->active); |
19149 |
-+ if (v_pre >= 0) |
19150 |
-+ atomic_add_return(KDBUS_NODE_BIAS, &pos->active); |
19151 |
-+ else if (v_pre == KDBUS_NODE_NEW) |
19152 |
-+ atomic_set(&pos->active, KDBUS_NODE_RELEASE_DIRECT); |
19153 |
-+ mutex_unlock(&pos->lock); |
19154 |
-+ |
19155 |
-+ /* wait until all active references were dropped */ |
19156 |
-+ wait_event(pos->waitq, |
19157 |
-+ atomic_read(&pos->active) <= KDBUS_NODE_BIAS); |
19158 |
-+ |
19159 |
-+ mutex_lock(&pos->lock); |
19160 |
-+ /* recurse into first child if any */ |
19161 |
-+ rb = rb_first(&pos->children); |
19162 |
-+ if (rb) { |
19163 |
-+ child = kdbus_node_ref(kdbus_node_from_rb(rb)); |
19164 |
-+ mutex_unlock(&pos->lock); |
19165 |
-+ pos = child; |
19166 |
-+ continue; |
19167 |
-+ } |
19168 |
-+ |
19169 |
-+ /* mark object as RELEASE */ |
19170 |
-+ v_post = atomic_read(&pos->active); |
19171 |
-+ if (v_post == KDBUS_NODE_BIAS || |
19172 |
-+ v_post == KDBUS_NODE_RELEASE_DIRECT) |
19173 |
-+ atomic_set(&pos->active, KDBUS_NODE_RELEASE); |
19174 |
-+ mutex_unlock(&pos->lock); |
19175 |
-+ |
19176 |
-+ /* |
19177 |
-+ * If this is the thread that marked the object as RELEASE, we |
19178 |
-+ * perform the actual release. Otherwise, we wait until the |
19179 |
-+ * release is done and the node is marked as DRAINED. |
19180 |
-+ */ |
19181 |
-+ if (v_post == KDBUS_NODE_BIAS || |
19182 |
-+ v_post == KDBUS_NODE_RELEASE_DIRECT) { |
19183 |
-+ if (pos->release_cb) |
19184 |
-+ pos->release_cb(pos, v_post == KDBUS_NODE_BIAS); |
19185 |
-+ |
19186 |
-+ if (pos->parent) { |
19187 |
-+ mutex_lock(&pos->parent->lock); |
19188 |
-+ if (!RB_EMPTY_NODE(&pos->rb)) { |
19189 |
-+ rb_erase(&pos->rb, |
19190 |
-+ &pos->parent->children); |
19191 |
-+ RB_CLEAR_NODE(&pos->rb); |
19192 |
-+ } |
19193 |
-+ mutex_unlock(&pos->parent->lock); |
19194 |
-+ } |
19195 |
-+ |
19196 |
-+ /* mark as DRAINED */ |
19197 |
-+ atomic_set(&pos->active, KDBUS_NODE_DRAINED); |
19198 |
-+ wake_up_all(&pos->waitq); |
19199 |
-+ |
19200 |
-+ /* drop VFS cache */ |
19201 |
-+ kdbus_fs_flush(pos); |
19202 |
-+ |
19203 |
-+ /* |
19204 |
-+ * If the node was activated and someone subtracted BIAS |
19205 |
-+ * from it to deactivate it, we, and only us, are |
19206 |
-+ * responsible to release the extra ref-count that was |
19207 |
-+ * taken once in kdbus_node_activate(). |
19208 |
-+ * If the node was never activated, no-one ever |
19209 |
-+ * subtracted BIAS, but instead skipped that state and |
19210 |
-+ * immediately went to NODE_RELEASE_DIRECT. In that case |
19211 |
-+ * we must not drop the reference. |
19212 |
-+ */ |
19213 |
-+ if (v_post == KDBUS_NODE_BIAS) |
19214 |
-+ kdbus_node_unref(pos); |
19215 |
-+ } else { |
19216 |
-+ /* wait until object is DRAINED */ |
19217 |
-+ wait_event(pos->waitq, |
19218 |
-+ atomic_read(&pos->active) == KDBUS_NODE_DRAINED); |
19219 |
-+ } |
19220 |
-+ |
19221 |
-+ /* |
19222 |
-+ * We're done with the current node. Continue on its parent |
19223 |
-+ * again, which will try deactivating its next child, or itself |
19224 |
-+ * if no child is left. |
19225 |
-+ * If we've reached our initial node again, we are done and |
19226 |
-+ * can safely return. |
19227 |
-+ */ |
19228 |
-+ if (pos == node) |
19229 |
-+ break; |
19230 |
-+ |
19231 |
-+ child = pos; |
19232 |
-+ pos = pos->parent; |
19233 |
-+ kdbus_node_unref(child); |
19234 |
-+ } |
19235 |
-+} |
19236 |
-+ |
19237 |
-+/** |
19238 |
-+ * kdbus_node_acquire() - Acquire an active ref on a node |
19239 |
-+ * @node: The node |
19240 |
-+ * |
19241 |
-+ * This acquires an active-reference to @node. This will only succeed if the |
19242 |
-+ * node is active. You must release this active reference via |
19243 |
-+ * kdbus_node_release() again. |
19244 |
-+ * |
19245 |
-+ * See the introduction to "active references" for more details. |
19246 |
-+ * |
19247 |
-+ * Return: %true if @node was non-NULL and active |
19248 |
-+ */ |
19249 |
-+bool kdbus_node_acquire(struct kdbus_node *node) |
19250 |
-+{ |
19251 |
-+ return node && atomic_inc_unless_negative(&node->active); |
19252 |
-+} |
19253 |
-+ |
19254 |
-+/** |
19255 |
-+ * kdbus_node_release() - Release an active ref on a node |
19256 |
-+ * @node: The node |
19257 |
-+ * |
19258 |
-+ * This releases an active reference that was previously acquired via |
19259 |
-+ * kdbus_node_acquire(). See kdbus_node_acquire() for details. |
19260 |
-+ */ |
19261 |
-+void kdbus_node_release(struct kdbus_node *node) |
19262 |
-+{ |
19263 |
-+ if (node && atomic_dec_return(&node->active) == KDBUS_NODE_BIAS) |
19264 |
-+ wake_up(&node->waitq); |
19265 |
-+} |
19266 |
-+ |
19267 |
-+/** |
19268 |
-+ * kdbus_node_find_child() - Find child by name |
19269 |
-+ * @node: parent node to search through |
19270 |
-+ * @name: name of child node |
19271 |
-+ * |
19272 |
-+ * This searches through all children of @node for a child-node with name @name. |
19273 |
-+ * If not found, or if the child is deactivated, NULL is returned. Otherwise, |
19274 |
-+ * the child is acquired and a new reference is returned. |
19275 |
-+ * |
19276 |
-+ * If you're done with the child, you need to release it and drop your |
19277 |
-+ * reference. |
19278 |
-+ * |
19279 |
-+ * This function does not acquire the parent node. However, if the parent was |
19280 |
-+ * already deactivated, then kdbus_node_deactivate() will, at some point, also |
19281 |
-+ * deactivate the child. Therefore, we can rely on the explicit ordering during |
19282 |
-+ * deactivation. |
19283 |
-+ * |
19284 |
-+ * Return: Reference to acquired child node, or NULL if not found / not active. |
19285 |
-+ */ |
19286 |
-+struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, |
19287 |
-+ const char *name) |
19288 |
-+{ |
19289 |
-+ struct kdbus_node *child; |
19290 |
-+ struct rb_node *rb; |
19291 |
-+ unsigned int hash; |
19292 |
-+ int ret; |
19293 |
-+ |
19294 |
-+ hash = kdbus_node_name_hash(name); |
19295 |
-+ |
19296 |
-+ mutex_lock(&node->lock); |
19297 |
-+ rb = node->children.rb_node; |
19298 |
-+ while (rb) { |
19299 |
-+ child = kdbus_node_from_rb(rb); |
19300 |
-+ ret = kdbus_node_name_compare(hash, name, child); |
19301 |
-+ if (ret < 0) |
19302 |
-+ rb = rb->rb_left; |
19303 |
-+ else if (ret > 0) |
19304 |
-+ rb = rb->rb_right; |
19305 |
-+ else |
19306 |
-+ break; |
19307 |
-+ } |
19308 |
-+ if (rb && kdbus_node_acquire(child)) |
19309 |
-+ kdbus_node_ref(child); |
19310 |
-+ else |
19311 |
-+ child = NULL; |
19312 |
-+ mutex_unlock(&node->lock); |
19313 |
-+ |
19314 |
-+ return child; |
19315 |
-+} |
19316 |
-+ |
19317 |
-+static struct kdbus_node *node_find_closest_unlocked(struct kdbus_node *node, |
19318 |
-+ unsigned int hash, |
19319 |
-+ const char *name) |
19320 |
-+{ |
19321 |
-+ struct kdbus_node *n, *pos = NULL; |
19322 |
-+ struct rb_node *rb; |
19323 |
-+ int res; |
19324 |
-+ |
19325 |
-+ /* |
19326 |
-+ * Find the closest child with ``node->hash >= hash'', or, if @name is |
19327 |
-+ * valid, ``node->name >= name'' (where '>=' is the lex. order). |
19328 |
-+ */ |
19329 |
-+ |
19330 |
-+ rb = node->children.rb_node; |
19331 |
-+ while (rb) { |
19332 |
-+ n = kdbus_node_from_rb(rb); |
19333 |
-+ |
19334 |
-+ if (name) |
19335 |
-+ res = kdbus_node_name_compare(hash, name, n); |
19336 |
-+ else |
19337 |
-+ res = hash - n->hash; |
19338 |
-+ |
19339 |
-+ if (res <= 0) { |
19340 |
-+ rb = rb->rb_left; |
19341 |
-+ pos = n; |
19342 |
-+ } else { /* ``hash > n->hash'', ``name > n->name'' */ |
19343 |
-+ rb = rb->rb_right; |
19344 |
-+ } |
19345 |
-+ } |
19346 |
-+ |
19347 |
-+ return pos; |
19348 |
-+} |
19349 |
-+ |
19350 |
-+/** |
19351 |
-+ * kdbus_node_find_closest() - Find closest child-match |
19352 |
-+ * @node: parent node to search through |
19353 |
-+ * @hash: hash value to find closest match for |
19354 |
-+ * |
19355 |
-+ * Find the closest child of @node with a hash greater than or equal to @hash. |
19356 |
-+ * The closest match is the left-most child of @node with this property. Which |
19357 |
-+ * means, it is the first child with that hash returned by |
19358 |
-+ * kdbus_node_next_child(), if you'd iterate the whole parent node. |
19359 |
-+ * |
19360 |
-+ * Return: Reference to acquired child, or NULL if none found. |
19361 |
-+ */ |
19362 |
-+struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, |
19363 |
-+ unsigned int hash) |
19364 |
-+{ |
19365 |
-+ struct kdbus_node *child; |
19366 |
-+ struct rb_node *rb; |
19367 |
-+ |
19368 |
-+ mutex_lock(&node->lock); |
19369 |
-+ |
19370 |
-+ child = node_find_closest_unlocked(node, hash, NULL); |
19371 |
-+ while (child && !kdbus_node_acquire(child)) { |
19372 |
-+ rb = rb_next(&child->rb); |
19373 |
-+ if (rb) |
19374 |
-+ child = kdbus_node_from_rb(rb); |
19375 |
-+ else |
19376 |
-+ child = NULL; |
19377 |
-+ } |
19378 |
-+ kdbus_node_ref(child); |
19379 |
-+ |
19380 |
-+ mutex_unlock(&node->lock); |
19381 |
-+ |
19382 |
-+ return child; |
19383 |
-+} |
19384 |
-+ |
19385 |
-+/** |
19386 |
-+ * kdbus_node_next_child() - Acquire next child |
19387 |
-+ * @node: parent node |
19388 |
-+ * @prev: previous child-node position or NULL |
19389 |
-+ * |
19390 |
-+ * This function returns a reference to the next active child of @node, after |
19391 |
-+ * the passed position @prev. If @prev is NULL, a reference to the first active |
19392 |
-+ * child is returned. If no more active children are found, NULL is returned. |
19393 |
-+ * |
19394 |
-+ * This function acquires the next child it returns. If you're done with the |
19395 |
-+ * returned pointer, you need to release _and_ unref it. |
19396 |
-+ * |
19397 |
-+ * The passed in pointer @prev is not modified by this function, and it does |
19398 |
-+ * *not* have to be active. If @prev was acquired via different means, or if it |
19399 |
-+ * was unlinked from its parent before you pass it in, then this iterator will |
19400 |
-+ * still return the next active child (it will have to search through the |
19401 |
-+ * rb-tree based on the node-name, though). |
19402 |
-+ * However, @prev must not be linked to a different parent than @node! |
19403 |
-+ * |
19404 |
-+ * Return: Reference to next acquired child, or NULL if at the end. |
19405 |
-+ */ |
19406 |
-+struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, |
19407 |
-+ struct kdbus_node *prev) |
19408 |
-+{ |
19409 |
-+ struct kdbus_node *pos = NULL; |
19410 |
-+ struct rb_node *rb; |
19411 |
-+ |
19412 |
-+ mutex_lock(&node->lock); |
19413 |
-+ |
19414 |
-+ if (!prev) { |
19415 |
-+ /* |
19416 |
-+ * New iteration; find first node in rb-tree and try to acquire |
19417 |
-+ * it. If we got it, directly return it as first element. |
19418 |
-+ * Otherwise, the loop below will find the next active node. |
19419 |
-+ */ |
19420 |
-+ rb = rb_first(&node->children); |
19421 |
-+ if (!rb) |
19422 |
-+ goto exit; |
19423 |
-+ pos = kdbus_node_from_rb(rb); |
19424 |
-+ if (kdbus_node_acquire(pos)) |
19425 |
-+ goto exit; |
19426 |
-+ } else if (RB_EMPTY_NODE(&prev->rb)) { |
19427 |
-+ /* |
19428 |
-+ * The current iterator is no longer linked to the rb-tree. Use |
19429 |
-+ * its hash value and name to find the next _higher_ node and |
19430 |
-+ * acquire it. If we got it, return it as next element. |
19431 |
-+ * Otherwise, the loop below will find the next active node. |
19432 |
-+ */ |
19433 |
-+ pos = node_find_closest_unlocked(node, prev->hash, prev->name); |
19434 |
-+ if (!pos) |
19435 |
-+ goto exit; |
19436 |
-+ if (kdbus_node_acquire(pos)) |
19437 |
-+ goto exit; |
19438 |
-+ } else { |
19439 |
-+ /* |
19440 |
-+ * The current iterator is still linked to the parent. Set it |
19441 |
-+ * as current position and use the loop below to find the next |
19442 |
-+ * active element. |
19443 |
-+ */ |
19444 |
-+ pos = prev; |
19445 |
-+ } |
19446 |
-+ |
19447 |
-+ /* @pos was already returned or is inactive; find next active node */ |
19448 |
-+ do { |
19449 |
-+ rb = rb_next(&pos->rb); |
19450 |
-+ if (rb) |
19451 |
-+ pos = kdbus_node_from_rb(rb); |
19452 |
-+ else |
19453 |
-+ pos = NULL; |
19454 |
-+ } while (pos && !kdbus_node_acquire(pos)); |
19455 |
-+ |
19456 |
-+exit: |
19457 |
-+ /* @pos is NULL or acquired. Take ref if non-NULL and return it */ |
19458 |
-+ kdbus_node_ref(pos); |
19459 |
-+ mutex_unlock(&node->lock); |
19460 |
-+ return pos; |
19461 |
-+} |
19462 |
-diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h |
19463 |
-new file mode 100644 |
19464 |
-index 0000000..970e02b |
19465 |
---- /dev/null |
19466 |
-+++ b/ipc/kdbus/node.h |
19467 |
-@@ -0,0 +1,86 @@ |
19468 |
-+/* |
19469 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19470 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19471 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19472 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19473 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19474 |
-+ * |
19475 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19476 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19477 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19478 |
-+ * your option) any later version. |
19479 |
-+ */ |
19480 |
-+ |
19481 |
-+#ifndef __KDBUS_NODE_H |
19482 |
-+#define __KDBUS_NODE_H |
19483 |
-+ |
19484 |
-+#include <linux/atomic.h> |
19485 |
-+#include <linux/kernel.h> |
19486 |
-+#include <linux/mutex.h> |
19487 |
-+#include <linux/wait.h> |
19488 |
-+ |
19489 |
-+struct kdbus_node; |
19490 |
-+ |
19491 |
-+enum kdbus_node_type { |
19492 |
-+ KDBUS_NODE_DOMAIN, |
19493 |
-+ KDBUS_NODE_CONTROL, |
19494 |
-+ KDBUS_NODE_BUS, |
19495 |
-+ KDBUS_NODE_ENDPOINT, |
19496 |
-+}; |
19497 |
-+ |
19498 |
-+typedef void (*kdbus_node_free_t) (struct kdbus_node *node); |
19499 |
-+typedef void (*kdbus_node_release_t) (struct kdbus_node *node, bool was_active); |
19500 |
-+ |
19501 |
-+struct kdbus_node { |
19502 |
-+ atomic_t refcnt; |
19503 |
-+ atomic_t active; |
19504 |
-+ wait_queue_head_t waitq; |
19505 |
-+ |
19506 |
-+ /* static members */ |
19507 |
-+ unsigned int type; |
19508 |
-+ kdbus_node_free_t free_cb; |
19509 |
-+ kdbus_node_release_t release_cb; |
19510 |
-+ umode_t mode; |
19511 |
-+ kuid_t uid; |
19512 |
-+ kgid_t gid; |
19513 |
-+ |
19514 |
-+ /* valid once linked */ |
19515 |
-+ char *name; |
19516 |
-+ unsigned int hash; |
19517 |
-+ unsigned int id; |
19518 |
-+ struct kdbus_node *parent; /* may be NULL */ |
19519 |
-+ |
19520 |
-+ /* valid iff active */ |
19521 |
-+ struct mutex lock; |
19522 |
-+ struct rb_node rb; |
19523 |
-+ struct rb_root children; |
19524 |
-+}; |
19525 |
-+ |
19526 |
-+#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb) |
19527 |
-+ |
19528 |
-+extern struct ida kdbus_node_ida; |
19529 |
-+ |
19530 |
-+void kdbus_node_init(struct kdbus_node *node, unsigned int type); |
19531 |
-+ |
19532 |
-+int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, |
19533 |
-+ const char *name); |
19534 |
-+ |
19535 |
-+struct kdbus_node *kdbus_node_ref(struct kdbus_node *node); |
19536 |
-+struct kdbus_node *kdbus_node_unref(struct kdbus_node *node); |
19537 |
-+ |
19538 |
-+bool kdbus_node_is_active(struct kdbus_node *node); |
19539 |
-+bool kdbus_node_is_deactivated(struct kdbus_node *node); |
19540 |
-+bool kdbus_node_activate(struct kdbus_node *node); |
19541 |
-+void kdbus_node_deactivate(struct kdbus_node *node); |
19542 |
-+ |
19543 |
-+bool kdbus_node_acquire(struct kdbus_node *node); |
19544 |
-+void kdbus_node_release(struct kdbus_node *node); |
19545 |
-+ |
19546 |
-+struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, |
19547 |
-+ const char *name); |
19548 |
-+struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, |
19549 |
-+ unsigned int hash); |
19550 |
-+struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, |
19551 |
-+ struct kdbus_node *prev); |
19552 |
-+ |
19553 |
-+#endif |
19554 |
-diff --git a/ipc/kdbus/notify.c b/ipc/kdbus/notify.c |
19555 |
-new file mode 100644 |
19556 |
-index 0000000..375758c |
19557 |
---- /dev/null |
19558 |
-+++ b/ipc/kdbus/notify.c |
19559 |
-@@ -0,0 +1,204 @@ |
19560 |
-+/* |
19561 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19562 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19563 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19564 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19565 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19566 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
19567 |
-+ * |
19568 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19569 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19570 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19571 |
-+ * your option) any later version. |
19572 |
-+ */ |
19573 |
-+ |
19574 |
-+#include <linux/fs.h> |
19575 |
-+#include <linux/init.h> |
19576 |
-+#include <linux/module.h> |
19577 |
-+#include <linux/mutex.h> |
19578 |
-+#include <linux/spinlock.h> |
19579 |
-+#include <linux/sched.h> |
19580 |
-+#include <linux/slab.h> |
19581 |
-+ |
19582 |
-+#include "bus.h" |
19583 |
-+#include "connection.h" |
19584 |
-+#include "domain.h" |
19585 |
-+#include "endpoint.h" |
19586 |
-+#include "item.h" |
19587 |
-+#include "message.h" |
19588 |
-+#include "notify.h" |
19589 |
-+ |
19590 |
-+static inline void kdbus_notify_add_tail(struct kdbus_staging *staging, |
19591 |
-+ struct kdbus_bus *bus) |
19592 |
-+{ |
19593 |
-+ spin_lock(&bus->notify_lock); |
19594 |
-+ list_add_tail(&staging->notify_entry, &bus->notify_list); |
19595 |
-+ spin_unlock(&bus->notify_lock); |
19596 |
-+} |
19597 |
-+ |
19598 |
-+static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id, |
19599 |
-+ u64 cookie, u64 msg_type) |
19600 |
-+{ |
19601 |
-+ struct kdbus_staging *s; |
19602 |
-+ |
19603 |
-+ s = kdbus_staging_new_kernel(bus, id, cookie, 0, msg_type); |
19604 |
-+ if (IS_ERR(s)) |
19605 |
-+ return PTR_ERR(s); |
19606 |
-+ |
19607 |
-+ kdbus_notify_add_tail(s, bus); |
19608 |
-+ return 0; |
19609 |
-+} |
19610 |
-+ |
19611 |
-+/** |
19612 |
-+ * kdbus_notify_reply_timeout() - queue a timeout reply |
19613 |
-+ * @bus: Bus which queues the messages |
19614 |
-+ * @id: The destination's connection ID |
19615 |
-+ * @cookie: The cookie to set in the reply. |
19616 |
-+ * |
19617 |
-+ * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached. |
19618 |
-+ * |
19619 |
-+ * Return: 0 on success, negative errno on failure. |
19620 |
-+ */ |
19621 |
-+int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie) |
19622 |
-+{ |
19623 |
-+ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT); |
19624 |
-+} |
19625 |
-+ |
19626 |
-+/** |
19627 |
-+ * kdbus_notify_reply_dead() - queue a 'dead' reply |
19628 |
-+ * @bus: Bus which queues the messages |
19629 |
-+ * @id: The destination's connection ID |
19630 |
-+ * @cookie: The cookie to set in the reply. |
19631 |
-+ * |
19632 |
-+ * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached. |
19633 |
-+ * |
19634 |
-+ * Return: 0 on success, negative errno on failure. |
19635 |
-+ */ |
19636 |
-+int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie) |
19637 |
-+{ |
19638 |
-+ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD); |
19639 |
-+} |
19640 |
-+ |
19641 |
-+/** |
19642 |
-+ * kdbus_notify_name_change() - queue a notification about a name owner change |
19643 |
-+ * @bus: Bus which queues the messages |
19644 |
-+ * @type: The type if the notification; KDBUS_ITEM_NAME_ADD, |
19645 |
-+ * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE |
19646 |
-+ * @old_id: The id of the connection that used to own the name |
19647 |
-+ * @new_id: The id of the new owner connection |
19648 |
-+ * @old_flags: The flags to pass in the KDBUS_ITEM flags field for |
19649 |
-+ * the old owner |
19650 |
-+ * @new_flags: The flags to pass in the KDBUS_ITEM flags field for |
19651 |
-+ * the new owner |
19652 |
-+ * @name: The name that was removed or assigned to a new owner |
19653 |
-+ * |
19654 |
-+ * Return: 0 on success, negative errno on failure. |
19655 |
-+ */ |
19656 |
-+int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, |
19657 |
-+ u64 old_id, u64 new_id, |
19658 |
-+ u64 old_flags, u64 new_flags, |
19659 |
-+ const char *name) |
19660 |
-+{ |
19661 |
-+ size_t name_len, extra_size; |
19662 |
-+ struct kdbus_staging *s; |
19663 |
-+ |
19664 |
-+ name_len = strlen(name) + 1; |
19665 |
-+ extra_size = sizeof(struct kdbus_notify_name_change) + name_len; |
19666 |
-+ |
19667 |
-+ s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0, |
19668 |
-+ extra_size, type); |
19669 |
-+ if (IS_ERR(s)) |
19670 |
-+ return PTR_ERR(s); |
19671 |
-+ |
19672 |
-+ s->notify->name_change.old_id.id = old_id; |
19673 |
-+ s->notify->name_change.old_id.flags = old_flags; |
19674 |
-+ s->notify->name_change.new_id.id = new_id; |
19675 |
-+ s->notify->name_change.new_id.flags = new_flags; |
19676 |
-+ memcpy(s->notify->name_change.name, name, name_len); |
19677 |
-+ |
19678 |
-+ kdbus_notify_add_tail(s, bus); |
19679 |
-+ return 0; |
19680 |
-+} |
19681 |
-+ |
19682 |
-+/** |
19683 |
-+ * kdbus_notify_id_change() - queue a notification about a unique ID change |
19684 |
-+ * @bus: Bus which queues the messages |
19685 |
-+ * @type: The type if the notification; KDBUS_ITEM_ID_ADD or |
19686 |
-+ * KDBUS_ITEM_ID_REMOVE |
19687 |
-+ * @id: The id of the connection that was added or removed |
19688 |
-+ * @flags: The flags to pass in the KDBUS_ITEM flags field |
19689 |
-+ * |
19690 |
-+ * Return: 0 on success, negative errno on failure. |
19691 |
-+ */ |
19692 |
-+int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags) |
19693 |
-+{ |
19694 |
-+ struct kdbus_staging *s; |
19695 |
-+ size_t extra_size; |
19696 |
-+ |
19697 |
-+ extra_size = sizeof(struct kdbus_notify_id_change); |
19698 |
-+ s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0, |
19699 |
-+ extra_size, type); |
19700 |
-+ if (IS_ERR(s)) |
19701 |
-+ return PTR_ERR(s); |
19702 |
-+ |
19703 |
-+ s->notify->id_change.id = id; |
19704 |
-+ s->notify->id_change.flags = flags; |
19705 |
-+ |
19706 |
-+ kdbus_notify_add_tail(s, bus); |
19707 |
-+ return 0; |
19708 |
-+} |
19709 |
-+ |
19710 |
-+/** |
19711 |
-+ * kdbus_notify_flush() - send a list of collected messages |
19712 |
-+ * @bus: Bus which queues the messages |
19713 |
-+ * |
19714 |
-+ * The list is empty after sending the messages. |
19715 |
-+ */ |
19716 |
-+void kdbus_notify_flush(struct kdbus_bus *bus) |
19717 |
-+{ |
19718 |
-+ LIST_HEAD(notify_list); |
19719 |
-+ struct kdbus_staging *s, *tmp; |
19720 |
-+ |
19721 |
-+ mutex_lock(&bus->notify_flush_lock); |
19722 |
-+ down_read(&bus->name_registry->rwlock); |
19723 |
-+ |
19724 |
-+ spin_lock(&bus->notify_lock); |
19725 |
-+ list_splice_init(&bus->notify_list, ¬ify_list); |
19726 |
-+ spin_unlock(&bus->notify_lock); |
19727 |
-+ |
19728 |
-+ list_for_each_entry_safe(s, tmp, ¬ify_list, notify_entry) { |
19729 |
-+ if (s->msg->dst_id != KDBUS_DST_ID_BROADCAST) { |
19730 |
-+ struct kdbus_conn *conn; |
19731 |
-+ |
19732 |
-+ conn = kdbus_bus_find_conn_by_id(bus, s->msg->dst_id); |
19733 |
-+ if (conn) { |
19734 |
-+ kdbus_bus_eavesdrop(bus, NULL, s); |
19735 |
-+ kdbus_conn_entry_insert(NULL, conn, s, NULL, |
19736 |
-+ NULL); |
19737 |
-+ kdbus_conn_unref(conn); |
19738 |
-+ } |
19739 |
-+ } else { |
19740 |
-+ kdbus_bus_broadcast(bus, NULL, s); |
19741 |
-+ } |
19742 |
-+ |
19743 |
-+ list_del(&s->notify_entry); |
19744 |
-+ kdbus_staging_free(s); |
19745 |
-+ } |
19746 |
-+ |
19747 |
-+ up_read(&bus->name_registry->rwlock); |
19748 |
-+ mutex_unlock(&bus->notify_flush_lock); |
19749 |
-+} |
19750 |
-+ |
19751 |
-+/** |
19752 |
-+ * kdbus_notify_free() - free a list of collected messages |
19753 |
-+ * @bus: Bus which queues the messages |
19754 |
-+ */ |
19755 |
-+void kdbus_notify_free(struct kdbus_bus *bus) |
19756 |
-+{ |
19757 |
-+ struct kdbus_staging *s, *tmp; |
19758 |
-+ |
19759 |
-+ list_for_each_entry_safe(s, tmp, &bus->notify_list, notify_entry) { |
19760 |
-+ list_del(&s->notify_entry); |
19761 |
-+ kdbus_staging_free(s); |
19762 |
-+ } |
19763 |
-+} |
19764 |
-diff --git a/ipc/kdbus/notify.h b/ipc/kdbus/notify.h |
19765 |
-new file mode 100644 |
19766 |
-index 0000000..03df464 |
19767 |
---- /dev/null |
19768 |
-+++ b/ipc/kdbus/notify.h |
19769 |
-@@ -0,0 +1,30 @@ |
19770 |
-+/* |
19771 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19772 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19773 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19774 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19775 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19776 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
19777 |
-+ * |
19778 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19779 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19780 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19781 |
-+ * your option) any later version. |
19782 |
-+ */ |
19783 |
-+ |
19784 |
-+#ifndef __KDBUS_NOTIFY_H |
19785 |
-+#define __KDBUS_NOTIFY_H |
19786 |
-+ |
19787 |
-+struct kdbus_bus; |
19788 |
-+ |
19789 |
-+int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags); |
19790 |
-+int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie); |
19791 |
-+int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie); |
19792 |
-+int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, |
19793 |
-+ u64 old_id, u64 new_id, |
19794 |
-+ u64 old_flags, u64 new_flags, |
19795 |
-+ const char *name); |
19796 |
-+void kdbus_notify_flush(struct kdbus_bus *bus); |
19797 |
-+void kdbus_notify_free(struct kdbus_bus *bus); |
19798 |
-+ |
19799 |
-+#endif |
19800 |
-diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c |
19801 |
-new file mode 100644 |
19802 |
-index 0000000..f2618e15 |
19803 |
---- /dev/null |
19804 |
-+++ b/ipc/kdbus/policy.c |
19805 |
-@@ -0,0 +1,489 @@ |
19806 |
-+/* |
19807 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19808 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19809 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19810 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19811 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19812 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
19813 |
-+ * |
19814 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19815 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19816 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19817 |
-+ * your option) any later version. |
19818 |
-+ */ |
19819 |
-+ |
19820 |
-+#include <linux/dcache.h> |
19821 |
-+#include <linux/fs.h> |
19822 |
-+#include <linux/init.h> |
19823 |
-+#include <linux/mutex.h> |
19824 |
-+#include <linux/sched.h> |
19825 |
-+#include <linux/sizes.h> |
19826 |
-+#include <linux/slab.h> |
19827 |
-+#include <linux/uaccess.h> |
19828 |
-+ |
19829 |
-+#include "bus.h" |
19830 |
-+#include "connection.h" |
19831 |
-+#include "domain.h" |
19832 |
-+#include "item.h" |
19833 |
-+#include "names.h" |
19834 |
-+#include "policy.h" |
19835 |
-+ |
19836 |
-+#define KDBUS_POLICY_HASH_SIZE 64 |
19837 |
-+ |
19838 |
-+/** |
19839 |
-+ * struct kdbus_policy_db_entry_access - a database entry access item |
19840 |
-+ * @type: One of KDBUS_POLICY_ACCESS_* types |
19841 |
-+ * @access: Access to grant. One of KDBUS_POLICY_* |
19842 |
-+ * @uid: For KDBUS_POLICY_ACCESS_USER, the global uid |
19843 |
-+ * @gid: For KDBUS_POLICY_ACCESS_GROUP, the global gid |
19844 |
-+ * @list: List entry item for the entry's list |
19845 |
-+ * |
19846 |
-+ * This is the internal version of struct kdbus_policy_db_access. |
19847 |
-+ */ |
19848 |
-+struct kdbus_policy_db_entry_access { |
19849 |
-+ u8 type; /* USER, GROUP, WORLD */ |
19850 |
-+ u8 access; /* OWN, TALK, SEE */ |
19851 |
-+ union { |
19852 |
-+ kuid_t uid; /* global uid */ |
19853 |
-+ kgid_t gid; /* global gid */ |
19854 |
-+ }; |
19855 |
-+ struct list_head list; |
19856 |
-+}; |
19857 |
-+ |
19858 |
-+/** |
19859 |
-+ * struct kdbus_policy_db_entry - a policy database entry |
19860 |
-+ * @name: The name to match the policy entry against |
19861 |
-+ * @hentry: The hash entry for the database's entries_hash |
19862 |
-+ * @access_list: List head for keeping tracks of the entry's |
19863 |
-+ * access items. |
19864 |
-+ * @owner: The owner of this entry. Can be a kdbus_conn or |
19865 |
-+ * a kdbus_ep object. |
19866 |
-+ * @wildcard: The name is a wildcard, such as ending on '.*' |
19867 |
-+ */ |
19868 |
-+struct kdbus_policy_db_entry { |
19869 |
-+ char *name; |
19870 |
-+ struct hlist_node hentry; |
19871 |
-+ struct list_head access_list; |
19872 |
-+ const void *owner; |
19873 |
-+ bool wildcard:1; |
19874 |
-+}; |
19875 |
-+ |
19876 |
-+static void kdbus_policy_entry_free(struct kdbus_policy_db_entry *e) |
19877 |
-+{ |
19878 |
-+ struct kdbus_policy_db_entry_access *a, *tmp; |
19879 |
-+ |
19880 |
-+ list_for_each_entry_safe(a, tmp, &e->access_list, list) { |
19881 |
-+ list_del(&a->list); |
19882 |
-+ kfree(a); |
19883 |
-+ } |
19884 |
-+ |
19885 |
-+ kfree(e->name); |
19886 |
-+ kfree(e); |
19887 |
-+} |
19888 |
-+ |
19889 |
-+static unsigned int kdbus_strnhash(const char *str, size_t len) |
19890 |
-+{ |
19891 |
-+ unsigned long hash = init_name_hash(); |
19892 |
-+ |
19893 |
-+ while (len--) |
19894 |
-+ hash = partial_name_hash(*str++, hash); |
19895 |
-+ |
19896 |
-+ return end_name_hash(hash); |
19897 |
-+} |
19898 |
-+ |
19899 |
-+static const struct kdbus_policy_db_entry * |
19900 |
-+kdbus_policy_lookup(struct kdbus_policy_db *db, const char *name, u32 hash) |
19901 |
-+{ |
19902 |
-+ struct kdbus_policy_db_entry *e; |
19903 |
-+ const char *dot; |
19904 |
-+ size_t len; |
19905 |
-+ |
19906 |
-+ /* find exact match */ |
19907 |
-+ hash_for_each_possible(db->entries_hash, e, hentry, hash) |
19908 |
-+ if (strcmp(e->name, name) == 0 && !e->wildcard) |
19909 |
-+ return e; |
19910 |
-+ |
19911 |
-+ /* find wildcard match */ |
19912 |
-+ |
19913 |
-+ dot = strrchr(name, '.'); |
19914 |
-+ if (!dot) |
19915 |
-+ return NULL; |
19916 |
-+ |
19917 |
-+ len = dot - name; |
19918 |
-+ hash = kdbus_strnhash(name, len); |
19919 |
-+ |
19920 |
-+ hash_for_each_possible(db->entries_hash, e, hentry, hash) |
19921 |
-+ if (e->wildcard && !strncmp(e->name, name, len) && |
19922 |
-+ !e->name[len]) |
19923 |
-+ return e; |
19924 |
-+ |
19925 |
-+ return NULL; |
19926 |
-+} |
19927 |
-+ |
19928 |
-+/** |
19929 |
-+ * kdbus_policy_db_clear - release all memory from a policy db |
19930 |
-+ * @db: The policy database |
19931 |
-+ */ |
19932 |
-+void kdbus_policy_db_clear(struct kdbus_policy_db *db) |
19933 |
-+{ |
19934 |
-+ struct kdbus_policy_db_entry *e; |
19935 |
-+ struct hlist_node *tmp; |
19936 |
-+ unsigned int i; |
19937 |
-+ |
19938 |
-+ /* purge entries */ |
19939 |
-+ down_write(&db->entries_rwlock); |
19940 |
-+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) { |
19941 |
-+ hash_del(&e->hentry); |
19942 |
-+ kdbus_policy_entry_free(e); |
19943 |
-+ } |
19944 |
-+ up_write(&db->entries_rwlock); |
19945 |
-+} |
19946 |
-+ |
19947 |
-+/** |
19948 |
-+ * kdbus_policy_db_init() - initialize a new policy database |
19949 |
-+ * @db: The location of the database |
19950 |
-+ * |
19951 |
-+ * This initializes a new policy-db. The underlying memory must have been |
19952 |
-+ * cleared to zero by the caller. |
19953 |
-+ */ |
19954 |
-+void kdbus_policy_db_init(struct kdbus_policy_db *db) |
19955 |
-+{ |
19956 |
-+ hash_init(db->entries_hash); |
19957 |
-+ init_rwsem(&db->entries_rwlock); |
19958 |
-+} |
19959 |
-+ |
19960 |
-+/** |
19961 |
-+ * kdbus_policy_query_unlocked() - Query the policy database |
19962 |
-+ * @db: Policy database |
19963 |
-+ * @cred: Credentials to test against |
19964 |
-+ * @name: Name to query |
19965 |
-+ * @hash: Hash value of @name |
19966 |
-+ * |
19967 |
-+ * Same as kdbus_policy_query() but requires the caller to lock the policy |
19968 |
-+ * database against concurrent writes. |
19969 |
-+ * |
19970 |
-+ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. |
19971 |
-+ */ |
19972 |
-+int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, |
19973 |
-+ const struct cred *cred, const char *name, |
19974 |
-+ unsigned int hash) |
19975 |
-+{ |
19976 |
-+ struct kdbus_policy_db_entry_access *a; |
19977 |
-+ const struct kdbus_policy_db_entry *e; |
19978 |
-+ int i, highest = -EPERM; |
19979 |
-+ |
19980 |
-+ e = kdbus_policy_lookup(db, name, hash); |
19981 |
-+ if (!e) |
19982 |
-+ return -EPERM; |
19983 |
-+ |
19984 |
-+ list_for_each_entry(a, &e->access_list, list) { |
19985 |
-+ if ((int)a->access <= highest) |
19986 |
-+ continue; |
19987 |
-+ |
19988 |
-+ switch (a->type) { |
19989 |
-+ case KDBUS_POLICY_ACCESS_USER: |
19990 |
-+ if (uid_eq(cred->euid, a->uid)) |
19991 |
-+ highest = a->access; |
19992 |
-+ break; |
19993 |
-+ case KDBUS_POLICY_ACCESS_GROUP: |
19994 |
-+ if (gid_eq(cred->egid, a->gid)) { |
19995 |
-+ highest = a->access; |
19996 |
-+ break; |
19997 |
-+ } |
19998 |
-+ |
19999 |
-+ for (i = 0; i < cred->group_info->ngroups; i++) { |
20000 |
-+ kgid_t gid = GROUP_AT(cred->group_info, i); |
20001 |
-+ |
20002 |
-+ if (gid_eq(gid, a->gid)) { |
20003 |
-+ highest = a->access; |
20004 |
-+ break; |
20005 |
-+ } |
20006 |
-+ } |
20007 |
-+ |
20008 |
-+ break; |
20009 |
-+ case KDBUS_POLICY_ACCESS_WORLD: |
20010 |
-+ highest = a->access; |
20011 |
-+ break; |
20012 |
-+ } |
20013 |
-+ |
20014 |
-+ /* OWN is the highest possible policy */ |
20015 |
-+ if (highest >= KDBUS_POLICY_OWN) |
20016 |
-+ break; |
20017 |
-+ } |
20018 |
-+ |
20019 |
-+ return highest; |
20020 |
-+} |
20021 |
-+ |
20022 |
-+/** |
20023 |
-+ * kdbus_policy_query() - Query the policy database |
20024 |
-+ * @db: Policy database |
20025 |
-+ * @cred: Credentials to test against |
20026 |
-+ * @name: Name to query |
20027 |
-+ * @hash: Hash value of @name |
20028 |
-+ * |
20029 |
-+ * Query the policy database @db for the access rights of @cred to the name |
20030 |
-+ * @name. The access rights of @cred are returned, or -EPERM if no access is |
20031 |
-+ * granted. |
20032 |
-+ * |
20033 |
-+ * This call effectively searches for the highest access-right granted to |
20034 |
-+ * @cred. The caller should really cache those as policy lookups are rather |
20035 |
-+ * expensive. |
20036 |
-+ * |
20037 |
-+ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. |
20038 |
-+ */ |
20039 |
-+int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, |
20040 |
-+ const char *name, unsigned int hash) |
20041 |
-+{ |
20042 |
-+ int ret; |
20043 |
-+ |
20044 |
-+ down_read(&db->entries_rwlock); |
20045 |
-+ ret = kdbus_policy_query_unlocked(db, cred, name, hash); |
20046 |
-+ up_read(&db->entries_rwlock); |
20047 |
-+ |
20048 |
-+ return ret; |
20049 |
-+} |
20050 |
-+ |
20051 |
-+static void __kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
20052 |
-+ const void *owner) |
20053 |
-+{ |
20054 |
-+ struct kdbus_policy_db_entry *e; |
20055 |
-+ struct hlist_node *tmp; |
20056 |
-+ int i; |
20057 |
-+ |
20058 |
-+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) |
20059 |
-+ if (e->owner == owner) { |
20060 |
-+ hash_del(&e->hentry); |
20061 |
-+ kdbus_policy_entry_free(e); |
20062 |
-+ } |
20063 |
-+} |
20064 |
-+ |
20065 |
-+/** |
20066 |
-+ * kdbus_policy_remove_owner() - remove all entries related to a connection |
20067 |
-+ * @db: The policy database |
20068 |
-+ * @owner: The connection which items to remove |
20069 |
-+ */ |
20070 |
-+void kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
20071 |
-+ const void *owner) |
20072 |
-+{ |
20073 |
-+ down_write(&db->entries_rwlock); |
20074 |
-+ __kdbus_policy_remove_owner(db, owner); |
20075 |
-+ up_write(&db->entries_rwlock); |
20076 |
-+} |
20077 |
-+ |
20078 |
-+/* |
20079 |
-+ * Convert user provided policy access to internal kdbus policy |
20080 |
-+ * access |
20081 |
-+ */ |
20082 |
-+static struct kdbus_policy_db_entry_access * |
20083 |
-+kdbus_policy_make_access(const struct kdbus_policy_access *uaccess) |
20084 |
-+{ |
20085 |
-+ int ret; |
20086 |
-+ struct kdbus_policy_db_entry_access *a; |
20087 |
-+ |
20088 |
-+ a = kzalloc(sizeof(*a), GFP_KERNEL); |
20089 |
-+ if (!a) |
20090 |
-+ return ERR_PTR(-ENOMEM); |
20091 |
-+ |
20092 |
-+ ret = -EINVAL; |
20093 |
-+ switch (uaccess->access) { |
20094 |
-+ case KDBUS_POLICY_SEE: |
20095 |
-+ case KDBUS_POLICY_TALK: |
20096 |
-+ case KDBUS_POLICY_OWN: |
20097 |
-+ a->access = uaccess->access; |
20098 |
-+ break; |
20099 |
-+ default: |
20100 |
-+ goto err; |
20101 |
-+ } |
20102 |
-+ |
20103 |
-+ switch (uaccess->type) { |
20104 |
-+ case KDBUS_POLICY_ACCESS_USER: |
20105 |
-+ a->uid = make_kuid(current_user_ns(), uaccess->id); |
20106 |
-+ if (!uid_valid(a->uid)) |
20107 |
-+ goto err; |
20108 |
-+ |
20109 |
-+ break; |
20110 |
-+ case KDBUS_POLICY_ACCESS_GROUP: |
20111 |
-+ a->gid = make_kgid(current_user_ns(), uaccess->id); |
20112 |
-+ if (!gid_valid(a->gid)) |
20113 |
-+ goto err; |
20114 |
-+ |
20115 |
-+ break; |
20116 |
-+ case KDBUS_POLICY_ACCESS_WORLD: |
20117 |
-+ break; |
20118 |
-+ default: |
20119 |
-+ goto err; |
20120 |
-+ } |
20121 |
-+ |
20122 |
-+ a->type = uaccess->type; |
20123 |
-+ |
20124 |
-+ return a; |
20125 |
-+ |
20126 |
-+err: |
20127 |
-+ kfree(a); |
20128 |
-+ return ERR_PTR(ret); |
20129 |
-+} |
20130 |
-+ |
20131 |
-+/** |
20132 |
-+ * kdbus_policy_set() - set a connection's policy rules |
20133 |
-+ * @db: The policy database |
20134 |
-+ * @items: A list of kdbus_item elements that contain both |
20135 |
-+ * names and access rules to set. |
20136 |
-+ * @items_size: The total size of the items. |
20137 |
-+ * @max_policies: The maximum number of policy entries to allow. |
20138 |
-+ * Pass 0 for no limit. |
20139 |
-+ * @allow_wildcards: Boolean value whether wildcard entries (such |
20140 |
-+ * ending on '.*') should be allowed. |
20141 |
-+ * @owner: The owner of the new policy items. |
20142 |
-+ * |
20143 |
-+ * This function sets a new set of policies for a given owner. The names and |
20144 |
-+ * access rules are gathered by walking the list of items passed in as |
20145 |
-+ * argument. An item of type KDBUS_ITEM_NAME is expected before any number of |
20146 |
-+ * KDBUS_ITEM_POLICY_ACCESS items. If there are more repetitions of this |
20147 |
-+ * pattern than denoted in @max_policies, -EINVAL is returned. |
20148 |
-+ * |
20149 |
-+ * In order to allow atomic replacement of rules, the function first removes |
20150 |
-+ * all entries that have been created for the given owner previously. |
20151 |
-+ * |
20152 |
-+ * Callers to this function must make sure that the owner is a custom |
20153 |
-+ * endpoint, or if the endpoint is a default endpoint, then it must be |
20154 |
-+ * either a policy holder or an activator. |
20155 |
-+ * |
20156 |
-+ * Return: 0 on success, negative errno on failure. |
20157 |
-+ */ |
20158 |
-+int kdbus_policy_set(struct kdbus_policy_db *db, |
20159 |
-+ const struct kdbus_item *items, |
20160 |
-+ size_t items_size, |
20161 |
-+ size_t max_policies, |
20162 |
-+ bool allow_wildcards, |
20163 |
-+ const void *owner) |
20164 |
-+{ |
20165 |
-+ struct kdbus_policy_db_entry_access *a; |
20166 |
-+ struct kdbus_policy_db_entry *e, *p; |
20167 |
-+ const struct kdbus_item *item; |
20168 |
-+ struct hlist_node *tmp; |
20169 |
-+ HLIST_HEAD(entries); |
20170 |
-+ HLIST_HEAD(restore); |
20171 |
-+ size_t count = 0; |
20172 |
-+ int i, ret = 0; |
20173 |
-+ u32 hash; |
20174 |
-+ |
20175 |
-+ /* Walk the list of items and look for new policies */ |
20176 |
-+ e = NULL; |
20177 |
-+ KDBUS_ITEMS_FOREACH(item, items, items_size) { |
20178 |
-+ switch (item->type) { |
20179 |
-+ case KDBUS_ITEM_NAME: { |
20180 |
-+ size_t len; |
20181 |
-+ |
20182 |
-+ if (max_policies && ++count > max_policies) { |
20183 |
-+ ret = -E2BIG; |
20184 |
-+ goto exit; |
20185 |
-+ } |
20186 |
-+ |
20187 |
-+ if (!kdbus_name_is_valid(item->str, true)) { |
20188 |
-+ ret = -EINVAL; |
20189 |
-+ goto exit; |
20190 |
-+ } |
20191 |
-+ |
20192 |
-+ e = kzalloc(sizeof(*e), GFP_KERNEL); |
20193 |
-+ if (!e) { |
20194 |
-+ ret = -ENOMEM; |
20195 |
-+ goto exit; |
20196 |
-+ } |
20197 |
-+ |
20198 |
-+ INIT_LIST_HEAD(&e->access_list); |
20199 |
-+ e->owner = owner; |
20200 |
-+ hlist_add_head(&e->hentry, &entries); |
20201 |
-+ |
20202 |
-+ e->name = kstrdup(item->str, GFP_KERNEL); |
20203 |
-+ if (!e->name) { |
20204 |
-+ ret = -ENOMEM; |
20205 |
-+ goto exit; |
20206 |
-+ } |
20207 |
-+ |
20208 |
-+ /* |
20209 |
-+ * If a supplied name ends with an '.*', cut off that |
20210 |
-+ * part, only store anything before it, and mark the |
20211 |
-+ * entry as wildcard. |
20212 |
-+ */ |
20213 |
-+ len = strlen(e->name); |
20214 |
-+ if (len > 2 && |
20215 |
-+ e->name[len - 3] == '.' && |
20216 |
-+ e->name[len - 2] == '*') { |
20217 |
-+ if (!allow_wildcards) { |
20218 |
-+ ret = -EINVAL; |
20219 |
-+ goto exit; |
20220 |
-+ } |
20221 |
-+ |
20222 |
-+ e->name[len - 3] = '\0'; |
20223 |
-+ e->wildcard = true; |
20224 |
-+ } |
20225 |
-+ |
20226 |
-+ break; |
20227 |
-+ } |
20228 |
-+ |
20229 |
-+ case KDBUS_ITEM_POLICY_ACCESS: |
20230 |
-+ if (!e) { |
20231 |
-+ ret = -EINVAL; |
20232 |
-+ goto exit; |
20233 |
-+ } |
20234 |
-+ |
20235 |
-+ a = kdbus_policy_make_access(&item->policy_access); |
20236 |
-+ if (IS_ERR(a)) { |
20237 |
-+ ret = PTR_ERR(a); |
20238 |
-+ goto exit; |
20239 |
-+ } |
20240 |
-+ |
20241 |
-+ list_add_tail(&a->list, &e->access_list); |
20242 |
-+ break; |
20243 |
-+ } |
20244 |
-+ } |
20245 |
-+ |
20246 |
-+ down_write(&db->entries_rwlock); |
20247 |
-+ |
20248 |
-+ /* remember previous entries to restore in case of failure */ |
20249 |
-+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) |
20250 |
-+ if (e->owner == owner) { |
20251 |
-+ hash_del(&e->hentry); |
20252 |
-+ hlist_add_head(&e->hentry, &restore); |
20253 |
-+ } |
20254 |
-+ |
20255 |
-+ hlist_for_each_entry_safe(e, tmp, &entries, hentry) { |
20256 |
-+ /* prevent duplicates */ |
20257 |
-+ hash = kdbus_strhash(e->name); |
20258 |
-+ hash_for_each_possible(db->entries_hash, p, hentry, hash) |
20259 |
-+ if (strcmp(e->name, p->name) == 0 && |
20260 |
-+ e->wildcard == p->wildcard) { |
20261 |
-+ ret = -EEXIST; |
20262 |
-+ goto restore; |
20263 |
-+ } |
20264 |
-+ |
20265 |
-+ hlist_del(&e->hentry); |
20266 |
-+ hash_add(db->entries_hash, &e->hentry, hash); |
20267 |
-+ } |
20268 |
-+ |
20269 |
-+restore: |
20270 |
-+ /* if we failed, flush all entries we added so far */ |
20271 |
-+ if (ret < 0) |
20272 |
-+ __kdbus_policy_remove_owner(db, owner); |
20273 |
-+ |
20274 |
-+ /* if we failed, restore entries, otherwise release them */ |
20275 |
-+ hlist_for_each_entry_safe(e, tmp, &restore, hentry) { |
20276 |
-+ hlist_del(&e->hentry); |
20277 |
-+ if (ret < 0) { |
20278 |
-+ hash = kdbus_strhash(e->name); |
20279 |
-+ hash_add(db->entries_hash, &e->hentry, hash); |
20280 |
-+ } else { |
20281 |
-+ kdbus_policy_entry_free(e); |
20282 |
-+ } |
20283 |
-+ } |
20284 |
-+ |
20285 |
-+ up_write(&db->entries_rwlock); |
20286 |
-+ |
20287 |
-+exit: |
20288 |
-+ hlist_for_each_entry_safe(e, tmp, &entries, hentry) { |
20289 |
-+ hlist_del(&e->hentry); |
20290 |
-+ kdbus_policy_entry_free(e); |
20291 |
-+ } |
20292 |
-+ |
20293 |
-+ return ret; |
20294 |
-+} |
20295 |
-diff --git a/ipc/kdbus/policy.h b/ipc/kdbus/policy.h |
20296 |
-new file mode 100644 |
20297 |
-index 0000000..15dd7bc |
20298 |
---- /dev/null |
20299 |
-+++ b/ipc/kdbus/policy.h |
20300 |
-@@ -0,0 +1,51 @@ |
20301 |
-+/* |
20302 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
20303 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
20304 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
20305 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
20306 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
20307 |
-+ * |
20308 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
20309 |
-+ * the terms of the GNU Lesser General Public License as published by the |
20310 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
20311 |
-+ * your option) any later version. |
20312 |
-+ */ |
20313 |
-+ |
20314 |
-+#ifndef __KDBUS_POLICY_H |
20315 |
-+#define __KDBUS_POLICY_H |
20316 |
-+ |
20317 |
-+#include <linux/hashtable.h> |
20318 |
-+#include <linux/rwsem.h> |
20319 |
-+ |
20320 |
-+struct kdbus_conn; |
20321 |
-+struct kdbus_item; |
20322 |
-+ |
20323 |
-+/** |
20324 |
-+ * struct kdbus_policy_db - policy database |
20325 |
-+ * @entries_hash: Hashtable of entries |
20326 |
-+ * @entries_rwlock: Mutex to protect the database's access entries |
20327 |
-+ */ |
20328 |
-+struct kdbus_policy_db { |
20329 |
-+ DECLARE_HASHTABLE(entries_hash, 6); |
20330 |
-+ struct rw_semaphore entries_rwlock; |
20331 |
-+}; |
20332 |
-+ |
20333 |
-+void kdbus_policy_db_init(struct kdbus_policy_db *db); |
20334 |
-+void kdbus_policy_db_clear(struct kdbus_policy_db *db); |
20335 |
-+ |
20336 |
-+int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, |
20337 |
-+ const struct cred *cred, const char *name, |
20338 |
-+ unsigned int hash); |
20339 |
-+int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, |
20340 |
-+ const char *name, unsigned int hash); |
20341 |
-+ |
20342 |
-+void kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
20343 |
-+ const void *owner); |
20344 |
-+int kdbus_policy_set(struct kdbus_policy_db *db, |
20345 |
-+ const struct kdbus_item *items, |
20346 |
-+ size_t items_size, |
20347 |
-+ size_t max_policies, |
20348 |
-+ bool allow_wildcards, |
20349 |
-+ const void *owner); |
20350 |
-+ |
20351 |
-+#endif |
20352 |
-diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c |
20353 |
-new file mode 100644 |
20354 |
-index 0000000..63ccd55 |
20355 |
---- /dev/null |
20356 |
-+++ b/ipc/kdbus/pool.c |
20357 |
-@@ -0,0 +1,728 @@ |
20358 |
-+/* |
20359 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
20360 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
20361 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
20362 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
20363 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
20364 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
20365 |
-+ * |
20366 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
20367 |
-+ * the terms of the GNU Lesser General Public License as published by the |
20368 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
20369 |
-+ * your option) any later version. |
20370 |
-+ */ |
20371 |
-+ |
20372 |
-+#include <linux/aio.h> |
20373 |
-+#include <linux/file.h> |
20374 |
-+#include <linux/fs.h> |
20375 |
-+#include <linux/highmem.h> |
20376 |
-+#include <linux/init.h> |
20377 |
-+#include <linux/mm.h> |
20378 |
-+#include <linux/module.h> |
20379 |
-+#include <linux/pagemap.h> |
20380 |
-+#include <linux/rbtree.h> |
20381 |
-+#include <linux/sched.h> |
20382 |
-+#include <linux/shmem_fs.h> |
20383 |
-+#include <linux/sizes.h> |
20384 |
-+#include <linux/slab.h> |
20385 |
-+#include <linux/uaccess.h> |
20386 |
-+#include <linux/uio.h> |
20387 |
-+ |
20388 |
-+#include "pool.h" |
20389 |
-+#include "util.h" |
20390 |
-+ |
20391 |
-+/** |
20392 |
-+ * struct kdbus_pool - the receiver's buffer |
20393 |
-+ * @f: The backing shmem file |
20394 |
-+ * @size: The size of the file |
20395 |
-+ * @accounted_size: Currently accounted memory in bytes |
20396 |
-+ * @lock: Pool data lock |
20397 |
-+ * @slices: All slices sorted by address |
20398 |
-+ * @slices_busy: Tree of allocated slices |
20399 |
-+ * @slices_free: Tree of free slices |
20400 |
-+ * |
20401 |
-+ * The receiver's buffer, managed as a pool of allocated and free |
20402 |
-+ * slices containing the queued messages. |
20403 |
-+ * |
20404 |
-+ * Messages sent with KDBUS_CMD_SEND are copied directly by the |
20405 |
-+ * sending process into the receiver's pool. |
20406 |
-+ * |
20407 |
-+ * Messages received with KDBUS_CMD_RECV just return the offset |
20408 |
-+ * to the data placed in the pool. |
20409 |
-+ * |
20410 |
-+ * The internally allocated memory needs to be returned by the receiver |
20411 |
-+ * with KDBUS_CMD_FREE. |
20412 |
-+ */ |
20413 |
-+struct kdbus_pool { |
20414 |
-+ struct file *f; |
20415 |
-+ size_t size; |
20416 |
-+ size_t accounted_size; |
20417 |
-+ struct mutex lock; |
20418 |
-+ |
20419 |
-+ struct list_head slices; |
20420 |
-+ struct rb_root slices_busy; |
20421 |
-+ struct rb_root slices_free; |
20422 |
-+}; |
20423 |
-+ |
20424 |
-+/** |
20425 |
-+ * struct kdbus_pool_slice - allocated element in kdbus_pool |
20426 |
-+ * @pool: Pool this slice belongs to |
20427 |
-+ * @off: Offset of slice in the shmem file |
20428 |
-+ * @size: Size of slice |
20429 |
-+ * @entry: Entry in "all slices" list |
20430 |
-+ * @rb_node: Entry in free or busy list |
20431 |
-+ * @free: Unused slice |
20432 |
-+ * @accounted: Accounted as queue slice |
20433 |
-+ * @ref_kernel: Kernel holds a reference |
20434 |
-+ * @ref_user: Userspace holds a reference |
20435 |
-+ * |
20436 |
-+ * The pool has one or more slices, always spanning the entire size of the |
20437 |
-+ * pool. |
20438 |
-+ * |
20439 |
-+ * Every slice is an element in a list sorted by the buffer address, to |
20440 |
-+ * provide access to the next neighbor slice. |
20441 |
-+ * |
20442 |
-+ * Every slice is member in either the busy or the free tree. The free |
20443 |
-+ * tree is organized by slice size, the busy tree organized by buffer |
20444 |
-+ * offset. |
20445 |
-+ */ |
20446 |
-+struct kdbus_pool_slice { |
20447 |
-+ struct kdbus_pool *pool; |
20448 |
-+ size_t off; |
20449 |
-+ size_t size; |
20450 |
-+ |
20451 |
-+ struct list_head entry; |
20452 |
-+ struct rb_node rb_node; |
20453 |
-+ |
20454 |
-+ bool free:1; |
20455 |
-+ bool accounted:1; |
20456 |
-+ bool ref_kernel:1; |
20457 |
-+ bool ref_user:1; |
20458 |
-+}; |
20459 |
-+ |
20460 |
-+static struct kdbus_pool_slice *kdbus_pool_slice_new(struct kdbus_pool *pool, |
20461 |
-+ size_t off, size_t size) |
20462 |
-+{ |
20463 |
-+ struct kdbus_pool_slice *slice; |
20464 |
-+ |
20465 |
-+ slice = kzalloc(sizeof(*slice), GFP_KERNEL); |
20466 |
-+ if (!slice) |
20467 |
-+ return NULL; |
20468 |
-+ |
20469 |
-+ slice->pool = pool; |
20470 |
-+ slice->off = off; |
20471 |
-+ slice->size = size; |
20472 |
-+ slice->free = true; |
20473 |
-+ return slice; |
20474 |
-+} |
20475 |
-+ |
20476 |
-+/* insert a slice into the free tree */ |
20477 |
-+static void kdbus_pool_add_free_slice(struct kdbus_pool *pool, |
20478 |
-+ struct kdbus_pool_slice *slice) |
20479 |
-+{ |
20480 |
-+ struct rb_node **n; |
20481 |
-+ struct rb_node *pn = NULL; |
20482 |
-+ |
20483 |
-+ n = &pool->slices_free.rb_node; |
20484 |
-+ while (*n) { |
20485 |
-+ struct kdbus_pool_slice *pslice; |
20486 |
-+ |
20487 |
-+ pn = *n; |
20488 |
-+ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node); |
20489 |
-+ if (slice->size < pslice->size) |
20490 |
-+ n = &pn->rb_left; |
20491 |
-+ else |
20492 |
-+ n = &pn->rb_right; |
20493 |
-+ } |
20494 |
-+ |
20495 |
-+ rb_link_node(&slice->rb_node, pn, n); |
20496 |
-+ rb_insert_color(&slice->rb_node, &pool->slices_free); |
20497 |
-+} |
20498 |
-+ |
20499 |
-+/* insert a slice into the busy tree */ |
20500 |
-+static void kdbus_pool_add_busy_slice(struct kdbus_pool *pool, |
20501 |
-+ struct kdbus_pool_slice *slice) |
20502 |
-+{ |
20503 |
-+ struct rb_node **n; |
20504 |
-+ struct rb_node *pn = NULL; |
20505 |
-+ |
20506 |
-+ n = &pool->slices_busy.rb_node; |
20507 |
-+ while (*n) { |
20508 |
-+ struct kdbus_pool_slice *pslice; |
20509 |
-+ |
20510 |
-+ pn = *n; |
20511 |
-+ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node); |
20512 |
-+ if (slice->off < pslice->off) |
20513 |
-+ n = &pn->rb_left; |
20514 |
-+ else if (slice->off > pslice->off) |
20515 |
-+ n = &pn->rb_right; |
20516 |
-+ else |
20517 |
-+ BUG(); |
20518 |
-+ } |
20519 |
-+ |
20520 |
-+ rb_link_node(&slice->rb_node, pn, n); |
20521 |
-+ rb_insert_color(&slice->rb_node, &pool->slices_busy); |
20522 |
-+} |
20523 |
-+ |
20524 |
-+static struct kdbus_pool_slice *kdbus_pool_find_slice(struct kdbus_pool *pool, |
20525 |
-+ size_t off) |
20526 |
-+{ |
20527 |
-+ struct rb_node *n; |
20528 |
-+ |
20529 |
-+ n = pool->slices_busy.rb_node; |
20530 |
-+ while (n) { |
20531 |
-+ struct kdbus_pool_slice *s; |
20532 |
-+ |
20533 |
-+ s = rb_entry(n, struct kdbus_pool_slice, rb_node); |
20534 |
-+ if (off < s->off) |
20535 |
-+ n = n->rb_left; |
20536 |
-+ else if (off > s->off) |
20537 |
-+ n = n->rb_right; |
20538 |
-+ else |
20539 |
-+ return s; |
20540 |
-+ } |
20541 |
-+ |
20542 |
-+ return NULL; |
20543 |
-+} |
20544 |
-+ |
20545 |
-+/** |
20546 |
-+ * kdbus_pool_slice_alloc() - allocate memory from a pool |
20547 |
-+ * @pool: The receiver's pool |
20548 |
-+ * @size: The number of bytes to allocate |
20549 |
-+ * @accounted: Whether this slice should be accounted for |
20550 |
-+ * |
20551 |
-+ * The returned slice is used for kdbus_pool_slice_release() to |
20552 |
-+ * free the allocated memory. If either @kvec or @iovec is non-NULL, the data |
20553 |
-+ * will be copied from kernel or userspace memory into the new slice at |
20554 |
-+ * offset 0. |
20555 |
-+ * |
20556 |
-+ * Return: the allocated slice on success, ERR_PTR on failure. |
20557 |
-+ */ |
20558 |
-+struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, |
20559 |
-+ size_t size, bool accounted) |
20560 |
-+{ |
20561 |
-+ size_t slice_size = KDBUS_ALIGN8(size); |
20562 |
-+ struct rb_node *n, *found = NULL; |
20563 |
-+ struct kdbus_pool_slice *s; |
20564 |
-+ int ret = 0; |
20565 |
-+ |
20566 |
-+ if (WARN_ON(!size)) |
20567 |
-+ return ERR_PTR(-EINVAL); |
20568 |
-+ |
20569 |
-+ /* search a free slice with the closest matching size */ |
20570 |
-+ mutex_lock(&pool->lock); |
20571 |
-+ n = pool->slices_free.rb_node; |
20572 |
-+ while (n) { |
20573 |
-+ s = rb_entry(n, struct kdbus_pool_slice, rb_node); |
20574 |
-+ if (slice_size < s->size) { |
20575 |
-+ found = n; |
20576 |
-+ n = n->rb_left; |
20577 |
-+ } else if (slice_size > s->size) { |
20578 |
-+ n = n->rb_right; |
20579 |
-+ } else { |
20580 |
-+ found = n; |
20581 |
-+ break; |
20582 |
-+ } |
20583 |
-+ } |
20584 |
-+ |
20585 |
-+ /* no slice with the minimum size found in the pool */ |
20586 |
-+ if (!found) { |
20587 |
-+ ret = -EXFULL; |
20588 |
-+ goto exit_unlock; |
20589 |
-+ } |
20590 |
-+ |
20591 |
-+ /* no exact match, use the closest one */ |
20592 |
-+ if (!n) { |
20593 |
-+ struct kdbus_pool_slice *s_new; |
20594 |
-+ |
20595 |
-+ s = rb_entry(found, struct kdbus_pool_slice, rb_node); |
20596 |
-+ |
20597 |
-+ /* split-off the remainder of the size to its own slice */ |
20598 |
-+ s_new = kdbus_pool_slice_new(pool, s->off + slice_size, |
20599 |
-+ s->size - slice_size); |
20600 |
-+ if (!s_new) { |
20601 |
-+ ret = -ENOMEM; |
20602 |
-+ goto exit_unlock; |
20603 |
-+ } |
20604 |
-+ |
20605 |
-+ list_add(&s_new->entry, &s->entry); |
20606 |
-+ kdbus_pool_add_free_slice(pool, s_new); |
20607 |
-+ |
20608 |
-+ /* adjust our size now that we split-off another slice */ |
20609 |
-+ s->size = slice_size; |
20610 |
-+ } |
20611 |
-+ |
20612 |
-+ /* move slice from free to the busy tree */ |
20613 |
-+ rb_erase(found, &pool->slices_free); |
20614 |
-+ kdbus_pool_add_busy_slice(pool, s); |
20615 |
-+ |
20616 |
-+ WARN_ON(s->ref_kernel || s->ref_user); |
20617 |
-+ |
20618 |
-+ s->ref_kernel = true; |
20619 |
-+ s->free = false; |
20620 |
-+ s->accounted = accounted; |
20621 |
-+ if (accounted) |
20622 |
-+ pool->accounted_size += s->size; |
20623 |
-+ mutex_unlock(&pool->lock); |
20624 |
-+ |
20625 |
-+ return s; |
20626 |
-+ |
20627 |
-+exit_unlock: |
20628 |
-+ mutex_unlock(&pool->lock); |
20629 |
-+ return ERR_PTR(ret); |
20630 |
-+} |
20631 |
-+ |
20632 |
-+static void __kdbus_pool_slice_release(struct kdbus_pool_slice *slice) |
20633 |
-+{ |
20634 |
-+ struct kdbus_pool *pool = slice->pool; |
20635 |
-+ |
20636 |
-+ /* don't free the slice if either has a reference */ |
20637 |
-+ if (slice->ref_kernel || slice->ref_user) |
20638 |
-+ return; |
20639 |
-+ |
20640 |
-+ if (WARN_ON(slice->free)) |
20641 |
-+ return; |
20642 |
-+ |
20643 |
-+ rb_erase(&slice->rb_node, &pool->slices_busy); |
20644 |
-+ |
20645 |
-+ /* merge with the next free slice */ |
20646 |
-+ if (!list_is_last(&slice->entry, &pool->slices)) { |
20647 |
-+ struct kdbus_pool_slice *s; |
20648 |
-+ |
20649 |
-+ s = list_entry(slice->entry.next, |
20650 |
-+ struct kdbus_pool_slice, entry); |
20651 |
-+ if (s->free) { |
20652 |
-+ rb_erase(&s->rb_node, &pool->slices_free); |
20653 |
-+ list_del(&s->entry); |
20654 |
-+ slice->size += s->size; |
20655 |
-+ kfree(s); |
20656 |
-+ } |
20657 |
-+ } |
20658 |
-+ |
20659 |
-+ /* merge with previous free slice */ |
20660 |
-+ if (pool->slices.next != &slice->entry) { |
20661 |
-+ struct kdbus_pool_slice *s; |
20662 |
-+ |
20663 |
-+ s = list_entry(slice->entry.prev, |
20664 |
-+ struct kdbus_pool_slice, entry); |
20665 |
-+ if (s->free) { |
20666 |
-+ rb_erase(&s->rb_node, &pool->slices_free); |
20667 |
-+ list_del(&slice->entry); |
20668 |
-+ s->size += slice->size; |
20669 |
-+ kfree(slice); |
20670 |
-+ slice = s; |
20671 |
-+ } |
20672 |
-+ } |
20673 |
-+ |
20674 |
-+ slice->free = true; |
20675 |
-+ kdbus_pool_add_free_slice(pool, slice); |
20676 |
-+} |
20677 |
-+ |
20678 |
-+/** |
20679 |
-+ * kdbus_pool_slice_release() - drop kernel-reference on allocated slice |
20680 |
-+ * @slice: Slice allocated from the pool |
20681 |
-+ * |
20682 |
-+ * This releases the kernel-reference on the given slice. If the |
20683 |
-+ * kernel-reference and the user-reference on a slice are dropped, the slice is |
20684 |
-+ * returned to the pool. |
20685 |
-+ * |
20686 |
-+ * So far, we do not implement full ref-counting on slices. Each, kernel and |
20687 |
-+ * user-space can have exactly one reference to a slice. If both are dropped at |
20688 |
-+ * the same time, the slice is released. |
20689 |
-+ */ |
20690 |
-+void kdbus_pool_slice_release(struct kdbus_pool_slice *slice) |
20691 |
-+{ |
20692 |
-+ struct kdbus_pool *pool; |
20693 |
-+ |
20694 |
-+ if (!slice) |
20695 |
-+ return; |
20696 |
-+ |
20697 |
-+ /* @slice may be freed, so keep local ptr to @pool */ |
20698 |
-+ pool = slice->pool; |
20699 |
-+ |
20700 |
-+ mutex_lock(&pool->lock); |
20701 |
-+ /* kernel must own a ref to @slice to drop it */ |
20702 |
-+ WARN_ON(!slice->ref_kernel); |
20703 |
-+ slice->ref_kernel = false; |
20704 |
-+ /* no longer kernel-owned, de-account slice */ |
20705 |
-+ if (slice->accounted && !WARN_ON(pool->accounted_size < slice->size)) |
20706 |
-+ pool->accounted_size -= slice->size; |
20707 |
-+ __kdbus_pool_slice_release(slice); |
20708 |
-+ mutex_unlock(&pool->lock); |
20709 |
-+} |
20710 |
-+ |
20711 |
-+/** |
20712 |
-+ * kdbus_pool_release_offset() - release a public offset |
20713 |
-+ * @pool: pool to operate on |
20714 |
-+ * @off: offset to release |
20715 |
-+ * |
20716 |
-+ * This should be called whenever user-space frees a slice given to them. It |
20717 |
-+ * verifies the slice is available and public, and then drops it. It ensures |
20718 |
-+ * correct locking and barriers against queues. |
20719 |
-+ * |
20720 |
-+ * Return: 0 on success, ENXIO if the offset is invalid or not public. |
20721 |
-+ */ |
20722 |
-+int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off) |
20723 |
-+{ |
20724 |
-+ struct kdbus_pool_slice *slice; |
20725 |
-+ int ret = 0; |
20726 |
-+ |
20727 |
-+ /* 'pool->size' is used as dummy offset for empty slices */ |
20728 |
-+ if (off == pool->size) |
20729 |
-+ return 0; |
20730 |
-+ |
20731 |
-+ mutex_lock(&pool->lock); |
20732 |
-+ slice = kdbus_pool_find_slice(pool, off); |
20733 |
-+ if (slice && slice->ref_user) { |
20734 |
-+ slice->ref_user = false; |
20735 |
-+ __kdbus_pool_slice_release(slice); |
20736 |
-+ } else { |
20737 |
-+ ret = -ENXIO; |
20738 |
-+ } |
20739 |
-+ mutex_unlock(&pool->lock); |
20740 |
-+ |
20741 |
-+ return ret; |
20742 |
-+} |
20743 |
-+ |
20744 |
-+/** |
20745 |
-+ * kdbus_pool_publish_empty() - publish empty slice to user-space |
20746 |
-+ * @pool: pool to operate on |
20747 |
-+ * @off: output storage for offset, or NULL |
20748 |
-+ * @size: output storage for size, or NULL |
20749 |
-+ * |
20750 |
-+ * This is the same as kdbus_pool_slice_publish(), but uses a dummy slice with |
20751 |
-+ * size 0. The returned offset points to the end of the pool and is never |
20752 |
-+ * returned on real slices. |
20753 |
-+ */ |
20754 |
-+void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size) |
20755 |
-+{ |
20756 |
-+ if (off) |
20757 |
-+ *off = pool->size; |
20758 |
-+ if (size) |
20759 |
-+ *size = 0; |
20760 |
-+} |
20761 |
-+ |
20762 |
-+/** |
20763 |
-+ * kdbus_pool_slice_publish() - publish slice to user-space |
20764 |
-+ * @slice: The slice |
20765 |
-+ * @out_offset: Output storage for offset, or NULL |
20766 |
-+ * @out_size: Output storage for size, or NULL |
20767 |
-+ * |
20768 |
-+ * This prepares a slice to be published to user-space. |
20769 |
-+ * |
20770 |
-+ * This call combines the following operations: |
20771 |
-+ * * the memory region is flushed so the user's memory view is consistent |
20772 |
-+ * * the slice is marked as referenced by user-space, so user-space has to |
20773 |
-+ * call KDBUS_CMD_FREE to release it |
20774 |
-+ * * the offset and size of the slice are written to the given output |
20775 |
-+ * arguments, if non-NULL |
20776 |
-+ */ |
20777 |
-+void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, |
20778 |
-+ u64 *out_offset, u64 *out_size) |
20779 |
-+{ |
20780 |
-+ mutex_lock(&slice->pool->lock); |
20781 |
-+ /* kernel must own a ref to @slice to gain a user-space ref */ |
20782 |
-+ WARN_ON(!slice->ref_kernel); |
20783 |
-+ slice->ref_user = true; |
20784 |
-+ mutex_unlock(&slice->pool->lock); |
20785 |
-+ |
20786 |
-+ if (out_offset) |
20787 |
-+ *out_offset = slice->off; |
20788 |
-+ if (out_size) |
20789 |
-+ *out_size = slice->size; |
20790 |
-+} |
20791 |
-+ |
20792 |
-+/** |
20793 |
-+ * kdbus_pool_slice_offset() - Get a slice's offset inside the pool |
20794 |
-+ * @slice: Slice to return the offset of |
20795 |
-+ * |
20796 |
-+ * Return: The internal offset @slice inside the pool. |
20797 |
-+ */ |
20798 |
-+off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice) |
20799 |
-+{ |
20800 |
-+ return slice->off; |
20801 |
-+} |
20802 |
-+ |
20803 |
-+/** |
20804 |
-+ * kdbus_pool_slice_size() - get size of a pool slice |
20805 |
-+ * @slice: slice to query |
20806 |
-+ * |
20807 |
-+ * Return: size of the given slice |
20808 |
-+ */ |
20809 |
-+size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice) |
20810 |
-+{ |
20811 |
-+ return slice->size; |
20812 |
-+} |
20813 |
-+ |
20814 |
-+/** |
20815 |
-+ * kdbus_pool_new() - create a new pool |
20816 |
-+ * @name: Name of the (deleted) file which shows up in |
20817 |
-+ * /proc, used for debugging |
20818 |
-+ * @size: Maximum size of the pool |
20819 |
-+ * |
20820 |
-+ * Return: a new kdbus_pool on success, ERR_PTR on failure. |
20821 |
-+ */ |
20822 |
-+struct kdbus_pool *kdbus_pool_new(const char *name, size_t size) |
20823 |
-+{ |
20824 |
-+ struct kdbus_pool_slice *s; |
20825 |
-+ struct kdbus_pool *p; |
20826 |
-+ struct file *f; |
20827 |
-+ char *n = NULL; |
20828 |
-+ int ret; |
20829 |
-+ |
20830 |
-+ p = kzalloc(sizeof(*p), GFP_KERNEL); |
20831 |
-+ if (!p) |
20832 |
-+ return ERR_PTR(-ENOMEM); |
20833 |
-+ |
20834 |
-+ if (name) { |
20835 |
-+ n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name); |
20836 |
-+ if (!n) { |
20837 |
-+ ret = -ENOMEM; |
20838 |
-+ goto exit_free; |
20839 |
-+ } |
20840 |
-+ } |
20841 |
-+ |
20842 |
-+ f = shmem_file_setup(n ?: KBUILD_MODNAME "-conn", size, 0); |
20843 |
-+ kfree(n); |
20844 |
-+ |
20845 |
-+ if (IS_ERR(f)) { |
20846 |
-+ ret = PTR_ERR(f); |
20847 |
-+ goto exit_free; |
20848 |
-+ } |
20849 |
-+ |
20850 |
-+ ret = get_write_access(file_inode(f)); |
20851 |
-+ if (ret < 0) |
20852 |
-+ goto exit_put_shmem; |
20853 |
-+ |
20854 |
-+ /* allocate first slice spanning the entire pool */ |
20855 |
-+ s = kdbus_pool_slice_new(p, 0, size); |
20856 |
-+ if (!s) { |
20857 |
-+ ret = -ENOMEM; |
20858 |
-+ goto exit_put_write; |
20859 |
-+ } |
20860 |
-+ |
20861 |
-+ p->f = f; |
20862 |
-+ p->size = size; |
20863 |
-+ p->slices_free = RB_ROOT; |
20864 |
-+ p->slices_busy = RB_ROOT; |
20865 |
-+ mutex_init(&p->lock); |
20866 |
-+ |
20867 |
-+ INIT_LIST_HEAD(&p->slices); |
20868 |
-+ list_add(&s->entry, &p->slices); |
20869 |
-+ |
20870 |
-+ kdbus_pool_add_free_slice(p, s); |
20871 |
-+ return p; |
20872 |
-+ |
20873 |
-+exit_put_write: |
20874 |
-+ put_write_access(file_inode(f)); |
20875 |
-+exit_put_shmem: |
20876 |
-+ fput(f); |
20877 |
-+exit_free: |
20878 |
-+ kfree(p); |
20879 |
-+ return ERR_PTR(ret); |
20880 |
-+} |
20881 |
-+ |
20882 |
-+/** |
20883 |
-+ * kdbus_pool_free() - destroy pool |
20884 |
-+ * @pool: The receiver's pool |
20885 |
-+ */ |
20886 |
-+void kdbus_pool_free(struct kdbus_pool *pool) |
20887 |
-+{ |
20888 |
-+ struct kdbus_pool_slice *s, *tmp; |
20889 |
-+ |
20890 |
-+ if (!pool) |
20891 |
-+ return; |
20892 |
-+ |
20893 |
-+ list_for_each_entry_safe(s, tmp, &pool->slices, entry) { |
20894 |
-+ list_del(&s->entry); |
20895 |
-+ kfree(s); |
20896 |
-+ } |
20897 |
-+ |
20898 |
-+ put_write_access(file_inode(pool->f)); |
20899 |
-+ fput(pool->f); |
20900 |
-+ kfree(pool); |
20901 |
-+} |
20902 |
-+ |
20903 |
-+/** |
20904 |
-+ * kdbus_pool_accounted() - retrieve accounting information |
20905 |
-+ * @pool: pool to query |
20906 |
-+ * @size: output for overall pool size |
20907 |
-+ * @acc: output for currently accounted size |
20908 |
-+ * |
20909 |
-+ * This returns accounting information of the pool. Note that the data might |
20910 |
-+ * change after the function returns, as the pool lock is dropped. You need to |
20911 |
-+ * protect the data via other means, if you need reliable accounting. |
20912 |
-+ */ |
20913 |
-+void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc) |
20914 |
-+{ |
20915 |
-+ mutex_lock(&pool->lock); |
20916 |
-+ if (size) |
20917 |
-+ *size = pool->size; |
20918 |
-+ if (acc) |
20919 |
-+ *acc = pool->accounted_size; |
20920 |
-+ mutex_unlock(&pool->lock); |
20921 |
-+} |
20922 |
-+ |
20923 |
-+/** |
20924 |
-+ * kdbus_pool_slice_copy_iovec() - copy user memory to a slice |
20925 |
-+ * @slice: The slice to write to |
20926 |
-+ * @off: Offset in the slice to write to |
20927 |
-+ * @iov: iovec array, pointing to data to copy |
20928 |
-+ * @iov_len: Number of elements in @iov |
20929 |
-+ * @total_len: Total number of bytes described in members of @iov |
20930 |
-+ * |
20931 |
-+ * User memory referenced by @iov will be copied into @slice at offset @off. |
20932 |
-+ * |
20933 |
-+ * Return: the numbers of bytes copied, negative errno on failure. |
20934 |
-+ */ |
20935 |
-+ssize_t |
20936 |
-+kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, loff_t off, |
20937 |
-+ struct iovec *iov, size_t iov_len, size_t total_len) |
20938 |
-+{ |
20939 |
-+ struct iov_iter iter; |
20940 |
-+ ssize_t len; |
20941 |
-+ |
20942 |
-+ if (WARN_ON(off + total_len > slice->size)) |
20943 |
-+ return -EFAULT; |
20944 |
-+ |
20945 |
-+ off += slice->off; |
20946 |
-+ iov_iter_init(&iter, WRITE, iov, iov_len, total_len); |
20947 |
-+ len = vfs_iter_write(slice->pool->f, &iter, &off); |
20948 |
-+ |
20949 |
-+ return (len >= 0 && len != total_len) ? -EFAULT : len; |
20950 |
-+} |
20951 |
-+ |
20952 |
-+/** |
20953 |
-+ * kdbus_pool_slice_copy_kvec() - copy kernel memory to a slice |
20954 |
-+ * @slice: The slice to write to |
20955 |
-+ * @off: Offset in the slice to write to |
20956 |
-+ * @kvec: kvec array, pointing to data to copy |
20957 |
-+ * @kvec_len: Number of elements in @kvec |
20958 |
-+ * @total_len: Total number of bytes described in members of @kvec |
20959 |
-+ * |
20960 |
-+ * Kernel memory referenced by @kvec will be copied into @slice at offset @off. |
20961 |
-+ * |
20962 |
-+ * Return: the numbers of bytes copied, negative errno on failure. |
20963 |
-+ */ |
20964 |
-+ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, |
20965 |
-+ loff_t off, struct kvec *kvec, |
20966 |
-+ size_t kvec_len, size_t total_len) |
20967 |
-+{ |
20968 |
-+ struct iov_iter iter; |
20969 |
-+ mm_segment_t old_fs; |
20970 |
-+ ssize_t len; |
20971 |
-+ |
20972 |
-+ if (WARN_ON(off + total_len > slice->size)) |
20973 |
-+ return -EFAULT; |
20974 |
-+ |
20975 |
-+ off += slice->off; |
20976 |
-+ iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len); |
20977 |
-+ |
20978 |
-+ old_fs = get_fs(); |
20979 |
-+ set_fs(get_ds()); |
20980 |
-+ len = vfs_iter_write(slice->pool->f, &iter, &off); |
20981 |
-+ set_fs(old_fs); |
20982 |
-+ |
20983 |
-+ return (len >= 0 && len != total_len) ? -EFAULT : len; |
20984 |
-+} |
20985 |
-+ |
20986 |
-+/** |
20987 |
-+ * kdbus_pool_slice_copy() - copy data from one slice into another |
20988 |
-+ * @slice_dst: destination slice |
20989 |
-+ * @slice_src: source slice |
20990 |
-+ * |
20991 |
-+ * Return: 0 on success, negative error number on failure. |
20992 |
-+ */ |
20993 |
-+int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, |
20994 |
-+ const struct kdbus_pool_slice *slice_src) |
20995 |
-+{ |
20996 |
-+ struct file *f_src = slice_src->pool->f; |
20997 |
-+ struct file *f_dst = slice_dst->pool->f; |
20998 |
-+ struct inode *i_dst = file_inode(f_dst); |
20999 |
-+ struct address_space *mapping_dst = f_dst->f_mapping; |
21000 |
-+ const struct address_space_operations *aops = mapping_dst->a_ops; |
21001 |
-+ unsigned long len = slice_src->size; |
21002 |
-+ loff_t off_src = slice_src->off; |
21003 |
-+ loff_t off_dst = slice_dst->off; |
21004 |
-+ mm_segment_t old_fs; |
21005 |
-+ int ret = 0; |
21006 |
-+ |
21007 |
-+ if (WARN_ON(slice_src->size != slice_dst->size) || |
21008 |
-+ WARN_ON(slice_src->free || slice_dst->free)) |
21009 |
-+ return -EINVAL; |
21010 |
-+ |
21011 |
-+ mutex_lock(&i_dst->i_mutex); |
21012 |
-+ old_fs = get_fs(); |
21013 |
-+ set_fs(get_ds()); |
21014 |
-+ while (len > 0) { |
21015 |
-+ unsigned long page_off; |
21016 |
-+ unsigned long copy_len; |
21017 |
-+ char __user *kaddr; |
21018 |
-+ struct page *page; |
21019 |
-+ ssize_t n_read; |
21020 |
-+ void *fsdata; |
21021 |
-+ long status; |
21022 |
-+ |
21023 |
-+ page_off = off_dst & (PAGE_CACHE_SIZE - 1); |
21024 |
-+ copy_len = min_t(unsigned long, |
21025 |
-+ PAGE_CACHE_SIZE - page_off, len); |
21026 |
-+ |
21027 |
-+ status = aops->write_begin(f_dst, mapping_dst, off_dst, |
21028 |
-+ copy_len, 0, &page, &fsdata); |
21029 |
-+ if (unlikely(status < 0)) { |
21030 |
-+ ret = status; |
21031 |
-+ break; |
21032 |
-+ } |
21033 |
-+ |
21034 |
-+ kaddr = (char __force __user *)kmap(page) + page_off; |
21035 |
-+ n_read = __vfs_read(f_src, kaddr, copy_len, &off_src); |
21036 |
-+ kunmap(page); |
21037 |
-+ mark_page_accessed(page); |
21038 |
-+ flush_dcache_page(page); |
21039 |
-+ |
21040 |
-+ if (unlikely(n_read != copy_len)) { |
21041 |
-+ ret = -EFAULT; |
21042 |
-+ break; |
21043 |
-+ } |
21044 |
-+ |
21045 |
-+ status = aops->write_end(f_dst, mapping_dst, off_dst, |
21046 |
-+ copy_len, copy_len, page, fsdata); |
21047 |
-+ if (unlikely(status != copy_len)) { |
21048 |
-+ ret = -EFAULT; |
21049 |
-+ break; |
21050 |
-+ } |
21051 |
-+ |
21052 |
-+ off_dst += copy_len; |
21053 |
-+ len -= copy_len; |
21054 |
-+ } |
21055 |
-+ set_fs(old_fs); |
21056 |
-+ mutex_unlock(&i_dst->i_mutex); |
21057 |
-+ |
21058 |
-+ return ret; |
21059 |
-+} |
21060 |
-+ |
21061 |
-+/** |
21062 |
-+ * kdbus_pool_mmap() - map the pool into the process |
21063 |
-+ * @pool: The receiver's pool |
21064 |
-+ * @vma: passed by mmap() syscall |
21065 |
-+ * |
21066 |
-+ * Return: the result of the mmap() call, negative errno on failure. |
21067 |
-+ */ |
21068 |
-+int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma) |
21069 |
-+{ |
21070 |
-+ /* deny write access to the pool */ |
21071 |
-+ if (vma->vm_flags & VM_WRITE) |
21072 |
-+ return -EPERM; |
21073 |
-+ vma->vm_flags &= ~VM_MAYWRITE; |
21074 |
-+ |
21075 |
-+ /* do not allow to map more than the size of the file */ |
21076 |
-+ if ((vma->vm_end - vma->vm_start) > pool->size) |
21077 |
-+ return -EFAULT; |
21078 |
-+ |
21079 |
-+ /* replace the connection file with our shmem file */ |
21080 |
-+ if (vma->vm_file) |
21081 |
-+ fput(vma->vm_file); |
21082 |
-+ vma->vm_file = get_file(pool->f); |
21083 |
-+ |
21084 |
-+ return pool->f->f_op->mmap(pool->f, vma); |
21085 |
-+} |
21086 |
-diff --git a/ipc/kdbus/pool.h b/ipc/kdbus/pool.h |
21087 |
-new file mode 100644 |
21088 |
-index 0000000..a903821 |
21089 |
---- /dev/null |
21090 |
-+++ b/ipc/kdbus/pool.h |
21091 |
-@@ -0,0 +1,46 @@ |
21092 |
-+/* |
21093 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21094 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21095 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21096 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21097 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21098 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21099 |
-+ * |
21100 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21101 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21102 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21103 |
-+ * your option) any later version. |
21104 |
-+ */ |
21105 |
-+ |
21106 |
-+#ifndef __KDBUS_POOL_H |
21107 |
-+#define __KDBUS_POOL_H |
21108 |
-+ |
21109 |
-+#include <linux/uio.h> |
21110 |
-+ |
21111 |
-+struct kdbus_pool; |
21112 |
-+struct kdbus_pool_slice; |
21113 |
-+ |
21114 |
-+struct kdbus_pool *kdbus_pool_new(const char *name, size_t size); |
21115 |
-+void kdbus_pool_free(struct kdbus_pool *pool); |
21116 |
-+void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc); |
21117 |
-+int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma); |
21118 |
-+int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off); |
21119 |
-+void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size); |
21120 |
-+ |
21121 |
-+struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, |
21122 |
-+ size_t size, bool accounted); |
21123 |
-+void kdbus_pool_slice_release(struct kdbus_pool_slice *slice); |
21124 |
-+void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, |
21125 |
-+ u64 *out_offset, u64 *out_size); |
21126 |
-+off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice); |
21127 |
-+size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice); |
21128 |
-+int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, |
21129 |
-+ const struct kdbus_pool_slice *slice_src); |
21130 |
-+ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, |
21131 |
-+ loff_t off, struct kvec *kvec, |
21132 |
-+ size_t kvec_count, size_t total_len); |
21133 |
-+ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, |
21134 |
-+ loff_t off, struct iovec *iov, |
21135 |
-+ size_t iov_count, size_t total_len); |
21136 |
-+ |
21137 |
-+#endif |
21138 |
-diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c |
21139 |
-new file mode 100644 |
21140 |
-index 0000000..f9c44d7 |
21141 |
---- /dev/null |
21142 |
-+++ b/ipc/kdbus/queue.c |
21143 |
-@@ -0,0 +1,363 @@ |
21144 |
-+/* |
21145 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21146 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21147 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21148 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21149 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21150 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21151 |
-+ * |
21152 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21153 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21154 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21155 |
-+ * your option) any later version. |
21156 |
-+ */ |
21157 |
-+ |
21158 |
-+#include <linux/audit.h> |
21159 |
-+#include <linux/file.h> |
21160 |
-+#include <linux/fs.h> |
21161 |
-+#include <linux/hashtable.h> |
21162 |
-+#include <linux/idr.h> |
21163 |
-+#include <linux/init.h> |
21164 |
-+#include <linux/math64.h> |
21165 |
-+#include <linux/mm.h> |
21166 |
-+#include <linux/module.h> |
21167 |
-+#include <linux/mutex.h> |
21168 |
-+#include <linux/poll.h> |
21169 |
-+#include <linux/sched.h> |
21170 |
-+#include <linux/sizes.h> |
21171 |
-+#include <linux/slab.h> |
21172 |
-+#include <linux/syscalls.h> |
21173 |
-+#include <linux/uio.h> |
21174 |
-+ |
21175 |
-+#include "util.h" |
21176 |
-+#include "domain.h" |
21177 |
-+#include "connection.h" |
21178 |
-+#include "item.h" |
21179 |
-+#include "message.h" |
21180 |
-+#include "metadata.h" |
21181 |
-+#include "queue.h" |
21182 |
-+#include "reply.h" |
21183 |
-+ |
21184 |
-+/** |
21185 |
-+ * kdbus_queue_init() - initialize data structure related to a queue |
21186 |
-+ * @queue: The queue to initialize |
21187 |
-+ */ |
21188 |
-+void kdbus_queue_init(struct kdbus_queue *queue) |
21189 |
-+{ |
21190 |
-+ INIT_LIST_HEAD(&queue->msg_list); |
21191 |
-+ queue->msg_prio_queue = RB_ROOT; |
21192 |
-+} |
21193 |
-+ |
21194 |
-+/** |
21195 |
-+ * kdbus_queue_peek() - Retrieves an entry from a queue |
21196 |
-+ * @queue: The queue |
21197 |
-+ * @priority: The minimum priority of the entry to peek |
21198 |
-+ * @use_priority: Boolean flag whether or not to peek by priority |
21199 |
-+ * |
21200 |
-+ * Look for a entry in a queue, either by priority, or the oldest one (FIFO). |
21201 |
-+ * The entry is not freed, put off the queue's lists or anything else. |
21202 |
-+ * |
21203 |
-+ * Return: the peeked queue entry on success, NULL if no suitable msg is found |
21204 |
-+ */ |
21205 |
-+struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, |
21206 |
-+ s64 priority, bool use_priority) |
21207 |
-+{ |
21208 |
-+ struct kdbus_queue_entry *e; |
21209 |
-+ |
21210 |
-+ if (list_empty(&queue->msg_list)) |
21211 |
-+ return NULL; |
21212 |
-+ |
21213 |
-+ if (use_priority) { |
21214 |
-+ /* get next entry with highest priority */ |
21215 |
-+ e = rb_entry(queue->msg_prio_highest, |
21216 |
-+ struct kdbus_queue_entry, prio_node); |
21217 |
-+ |
21218 |
-+ /* no entry with the requested priority */ |
21219 |
-+ if (e->priority > priority) |
21220 |
-+ return NULL; |
21221 |
-+ } else { |
21222 |
-+ /* ignore the priority, return the next entry in the entry */ |
21223 |
-+ e = list_first_entry(&queue->msg_list, |
21224 |
-+ struct kdbus_queue_entry, entry); |
21225 |
-+ } |
21226 |
-+ |
21227 |
-+ return e; |
21228 |
-+} |
21229 |
-+ |
21230 |
-+static void kdbus_queue_entry_link(struct kdbus_queue_entry *entry) |
21231 |
-+{ |
21232 |
-+ struct kdbus_queue *queue = &entry->conn->queue; |
21233 |
-+ struct rb_node **n, *pn = NULL; |
21234 |
-+ bool highest = true; |
21235 |
-+ |
21236 |
-+ lockdep_assert_held(&entry->conn->lock); |
21237 |
-+ if (WARN_ON(!list_empty(&entry->entry))) |
21238 |
-+ return; |
21239 |
-+ |
21240 |
-+ /* sort into priority entry tree */ |
21241 |
-+ n = &queue->msg_prio_queue.rb_node; |
21242 |
-+ while (*n) { |
21243 |
-+ struct kdbus_queue_entry *e; |
21244 |
-+ |
21245 |
-+ pn = *n; |
21246 |
-+ e = rb_entry(pn, struct kdbus_queue_entry, prio_node); |
21247 |
-+ |
21248 |
-+ /* existing node for this priority, add to its list */ |
21249 |
-+ if (likely(entry->priority == e->priority)) { |
21250 |
-+ list_add_tail(&entry->prio_entry, &e->prio_entry); |
21251 |
-+ goto prio_done; |
21252 |
-+ } |
21253 |
-+ |
21254 |
-+ if (entry->priority < e->priority) { |
21255 |
-+ n = &pn->rb_left; |
21256 |
-+ } else { |
21257 |
-+ n = &pn->rb_right; |
21258 |
-+ highest = false; |
21259 |
-+ } |
21260 |
-+ } |
21261 |
-+ |
21262 |
-+ /* cache highest-priority entry */ |
21263 |
-+ if (highest) |
21264 |
-+ queue->msg_prio_highest = &entry->prio_node; |
21265 |
-+ |
21266 |
-+ /* new node for this priority */ |
21267 |
-+ rb_link_node(&entry->prio_node, pn, n); |
21268 |
-+ rb_insert_color(&entry->prio_node, &queue->msg_prio_queue); |
21269 |
-+ INIT_LIST_HEAD(&entry->prio_entry); |
21270 |
-+ |
21271 |
-+prio_done: |
21272 |
-+ /* add to unsorted fifo list */ |
21273 |
-+ list_add_tail(&entry->entry, &queue->msg_list); |
21274 |
-+} |
21275 |
-+ |
21276 |
-+static void kdbus_queue_entry_unlink(struct kdbus_queue_entry *entry) |
21277 |
-+{ |
21278 |
-+ struct kdbus_queue *queue = &entry->conn->queue; |
21279 |
-+ |
21280 |
-+ lockdep_assert_held(&entry->conn->lock); |
21281 |
-+ if (list_empty(&entry->entry)) |
21282 |
-+ return; |
21283 |
-+ |
21284 |
-+ list_del_init(&entry->entry); |
21285 |
-+ |
21286 |
-+ if (list_empty(&entry->prio_entry)) { |
21287 |
-+ /* |
21288 |
-+ * Single entry for this priority, update cached |
21289 |
-+ * highest-priority entry, remove the tree node. |
21290 |
-+ */ |
21291 |
-+ if (queue->msg_prio_highest == &entry->prio_node) |
21292 |
-+ queue->msg_prio_highest = rb_next(&entry->prio_node); |
21293 |
-+ |
21294 |
-+ rb_erase(&entry->prio_node, &queue->msg_prio_queue); |
21295 |
-+ } else { |
21296 |
-+ struct kdbus_queue_entry *q; |
21297 |
-+ |
21298 |
-+ /* |
21299 |
-+ * Multiple entries for this priority entry, get next one in |
21300 |
-+ * the list. Update cached highest-priority entry, store the |
21301 |
-+ * new one as the tree node. |
21302 |
-+ */ |
21303 |
-+ q = list_first_entry(&entry->prio_entry, |
21304 |
-+ struct kdbus_queue_entry, prio_entry); |
21305 |
-+ list_del(&entry->prio_entry); |
21306 |
-+ |
21307 |
-+ if (queue->msg_prio_highest == &entry->prio_node) |
21308 |
-+ queue->msg_prio_highest = &q->prio_node; |
21309 |
-+ |
21310 |
-+ rb_replace_node(&entry->prio_node, &q->prio_node, |
21311 |
-+ &queue->msg_prio_queue); |
21312 |
-+ } |
21313 |
-+} |
21314 |
-+ |
21315 |
-+/** |
21316 |
-+ * kdbus_queue_entry_new() - allocate a queue entry |
21317 |
-+ * @src: source connection, or NULL |
21318 |
-+ * @dst: destination connection |
21319 |
-+ * @s: staging object carrying the message |
21320 |
-+ * |
21321 |
-+ * Allocates a queue entry based on a given msg and allocate space for |
21322 |
-+ * the message payload and the requested metadata in the connection's pool. |
21323 |
-+ * The entry is not actually added to the queue's lists at this point. |
21324 |
-+ * |
21325 |
-+ * Return: the allocated entry on success, or an ERR_PTR on failures. |
21326 |
-+ */ |
21327 |
-+struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src, |
21328 |
-+ struct kdbus_conn *dst, |
21329 |
-+ struct kdbus_staging *s) |
21330 |
-+{ |
21331 |
-+ struct kdbus_queue_entry *entry; |
21332 |
-+ int ret; |
21333 |
-+ |
21334 |
-+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
21335 |
-+ if (!entry) |
21336 |
-+ return ERR_PTR(-ENOMEM); |
21337 |
-+ |
21338 |
-+ INIT_LIST_HEAD(&entry->entry); |
21339 |
-+ entry->priority = s->msg->priority; |
21340 |
-+ entry->conn = kdbus_conn_ref(dst); |
21341 |
-+ entry->gaps = kdbus_gaps_ref(s->gaps); |
21342 |
-+ |
21343 |
-+ entry->slice = kdbus_staging_emit(s, src, dst); |
21344 |
-+ if (IS_ERR(entry->slice)) { |
21345 |
-+ ret = PTR_ERR(entry->slice); |
21346 |
-+ entry->slice = NULL; |
21347 |
-+ goto error; |
21348 |
-+ } |
21349 |
-+ |
21350 |
-+ entry->user = src ? kdbus_user_ref(src->user) : NULL; |
21351 |
-+ return entry; |
21352 |
-+ |
21353 |
-+error: |
21354 |
-+ kdbus_queue_entry_free(entry); |
21355 |
-+ return ERR_PTR(ret); |
21356 |
-+} |
21357 |
-+ |
21358 |
-+/** |
21359 |
-+ * kdbus_queue_entry_free() - free resources of an entry |
21360 |
-+ * @entry: The entry to free |
21361 |
-+ * |
21362 |
-+ * Removes resources allocated by a queue entry, along with the entry itself. |
21363 |
-+ * Note that the entry's slice is not freed at this point. |
21364 |
-+ */ |
21365 |
-+void kdbus_queue_entry_free(struct kdbus_queue_entry *entry) |
21366 |
-+{ |
21367 |
-+ if (!entry) |
21368 |
-+ return; |
21369 |
-+ |
21370 |
-+ lockdep_assert_held(&entry->conn->lock); |
21371 |
-+ |
21372 |
-+ kdbus_queue_entry_unlink(entry); |
21373 |
-+ kdbus_reply_unref(entry->reply); |
21374 |
-+ |
21375 |
-+ if (entry->slice) { |
21376 |
-+ kdbus_conn_quota_dec(entry->conn, entry->user, |
21377 |
-+ kdbus_pool_slice_size(entry->slice), |
21378 |
-+ entry->gaps ? entry->gaps->n_fds : 0); |
21379 |
-+ kdbus_pool_slice_release(entry->slice); |
21380 |
-+ } |
21381 |
-+ |
21382 |
-+ kdbus_user_unref(entry->user); |
21383 |
-+ kdbus_gaps_unref(entry->gaps); |
21384 |
-+ kdbus_conn_unref(entry->conn); |
21385 |
-+ kfree(entry); |
21386 |
-+} |
21387 |
-+ |
21388 |
-+/** |
21389 |
-+ * kdbus_queue_entry_install() - install message components into the |
21390 |
-+ * receiver's process |
21391 |
-+ * @entry: The queue entry to install |
21392 |
-+ * @return_flags: Pointer to store the return flags for userspace |
21393 |
-+ * @install_fds: Whether or not to install associated file descriptors |
21394 |
-+ * |
21395 |
-+ * Return: 0 on success. |
21396 |
-+ */ |
21397 |
-+int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, |
21398 |
-+ u64 *return_flags, bool install_fds) |
21399 |
-+{ |
21400 |
-+ bool incomplete_fds = false; |
21401 |
-+ int ret; |
21402 |
-+ |
21403 |
-+ lockdep_assert_held(&entry->conn->lock); |
21404 |
-+ |
21405 |
-+ ret = kdbus_gaps_install(entry->gaps, entry->slice, &incomplete_fds); |
21406 |
-+ if (ret < 0) |
21407 |
-+ return ret; |
21408 |
-+ |
21409 |
-+ if (incomplete_fds) |
21410 |
-+ *return_flags |= KDBUS_RECV_RETURN_INCOMPLETE_FDS; |
21411 |
-+ return 0; |
21412 |
-+} |
21413 |
-+ |
21414 |
-+/** |
21415 |
-+ * kdbus_queue_entry_enqueue() - enqueue an entry |
21416 |
-+ * @entry: entry to enqueue |
21417 |
-+ * @reply: reply to link to this entry (or NULL if none) |
21418 |
-+ * |
21419 |
-+ * This enqueues an unqueued entry into the message queue of the linked |
21420 |
-+ * connection. It also binds a reply object to the entry so we can remember it |
21421 |
-+ * when the message is moved. |
21422 |
-+ * |
21423 |
-+ * Once this call returns (and the connection lock is released), this entry can |
21424 |
-+ * be dequeued by the target connection. Note that the entry will not be removed |
21425 |
-+ * from the queue until it is destroyed. |
21426 |
-+ */ |
21427 |
-+void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, |
21428 |
-+ struct kdbus_reply *reply) |
21429 |
-+{ |
21430 |
-+ lockdep_assert_held(&entry->conn->lock); |
21431 |
-+ |
21432 |
-+ if (WARN_ON(entry->reply) || WARN_ON(!list_empty(&entry->entry))) |
21433 |
-+ return; |
21434 |
-+ |
21435 |
-+ entry->reply = kdbus_reply_ref(reply); |
21436 |
-+ kdbus_queue_entry_link(entry); |
21437 |
-+} |
21438 |
-+ |
21439 |
-+/** |
21440 |
-+ * kdbus_queue_entry_move() - move queue entry |
21441 |
-+ * @e: queue entry to move |
21442 |
-+ * @dst: destination connection to queue the entry on |
21443 |
-+ * |
21444 |
-+ * This moves a queue entry onto a different connection. It allocates a new |
21445 |
-+ * slice on the target connection and copies the message over. If the copy |
21446 |
-+ * succeeded, we move the entry from @src to @dst. |
21447 |
-+ * |
21448 |
-+ * On failure, the entry is left untouched. |
21449 |
-+ * |
21450 |
-+ * The queue entry must be queued right now, and after the call succeeds it will |
21451 |
-+ * be queued on the destination, but no longer on the source. |
21452 |
-+ * |
21453 |
-+ * The caller must hold the connection lock of the source *and* destination. |
21454 |
-+ * |
21455 |
-+ * Return: 0 on success, negative error code on failure. |
21456 |
-+ */ |
21457 |
-+int kdbus_queue_entry_move(struct kdbus_queue_entry *e, |
21458 |
-+ struct kdbus_conn *dst) |
21459 |
-+{ |
21460 |
-+ struct kdbus_pool_slice *slice = NULL; |
21461 |
-+ struct kdbus_conn *src = e->conn; |
21462 |
-+ size_t size, fds; |
21463 |
-+ int ret; |
21464 |
-+ |
21465 |
-+ lockdep_assert_held(&src->lock); |
21466 |
-+ lockdep_assert_held(&dst->lock); |
21467 |
-+ |
21468 |
-+ if (WARN_ON(list_empty(&e->entry))) |
21469 |
-+ return -EINVAL; |
21470 |
-+ if (src == dst) |
21471 |
-+ return 0; |
21472 |
-+ |
21473 |
-+ size = kdbus_pool_slice_size(e->slice); |
21474 |
-+ fds = e->gaps ? e->gaps->n_fds : 0; |
21475 |
-+ |
21476 |
-+ ret = kdbus_conn_quota_inc(dst, e->user, size, fds); |
21477 |
-+ if (ret < 0) |
21478 |
-+ return ret; |
21479 |
-+ |
21480 |
-+ slice = kdbus_pool_slice_alloc(dst->pool, size, true); |
21481 |
-+ if (IS_ERR(slice)) { |
21482 |
-+ ret = PTR_ERR(slice); |
21483 |
-+ slice = NULL; |
21484 |
-+ goto error; |
21485 |
-+ } |
21486 |
-+ |
21487 |
-+ ret = kdbus_pool_slice_copy(slice, e->slice); |
21488 |
-+ if (ret < 0) |
21489 |
-+ goto error; |
21490 |
-+ |
21491 |
-+ kdbus_queue_entry_unlink(e); |
21492 |
-+ kdbus_conn_quota_dec(src, e->user, size, fds); |
21493 |
-+ kdbus_pool_slice_release(e->slice); |
21494 |
-+ kdbus_conn_unref(e->conn); |
21495 |
-+ |
21496 |
-+ e->slice = slice; |
21497 |
-+ e->conn = kdbus_conn_ref(dst); |
21498 |
-+ kdbus_queue_entry_link(e); |
21499 |
-+ |
21500 |
-+ return 0; |
21501 |
-+ |
21502 |
-+error: |
21503 |
-+ kdbus_pool_slice_release(slice); |
21504 |
-+ kdbus_conn_quota_dec(dst, e->user, size, fds); |
21505 |
-+ return ret; |
21506 |
-+} |
21507 |
-diff --git a/ipc/kdbus/queue.h b/ipc/kdbus/queue.h |
21508 |
-new file mode 100644 |
21509 |
-index 0000000..bf686d1 |
21510 |
---- /dev/null |
21511 |
-+++ b/ipc/kdbus/queue.h |
21512 |
-@@ -0,0 +1,84 @@ |
21513 |
-+/* |
21514 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21515 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21516 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21517 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21518 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21519 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21520 |
-+ * |
21521 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21522 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21523 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21524 |
-+ * your option) any later version. |
21525 |
-+ */ |
21526 |
-+ |
21527 |
-+#ifndef __KDBUS_QUEUE_H |
21528 |
-+#define __KDBUS_QUEUE_H |
21529 |
-+ |
21530 |
-+#include <linux/list.h> |
21531 |
-+#include <linux/rbtree.h> |
21532 |
-+ |
21533 |
-+struct kdbus_conn; |
21534 |
-+struct kdbus_pool_slice; |
21535 |
-+struct kdbus_reply; |
21536 |
-+struct kdbus_staging; |
21537 |
-+struct kdbus_user; |
21538 |
-+ |
21539 |
-+/** |
21540 |
-+ * struct kdbus_queue - a connection's message queue |
21541 |
-+ * @msg_list: List head for kdbus_queue_entry objects |
21542 |
-+ * @msg_prio_queue: RB tree root for messages, sorted by priority |
21543 |
-+ * @msg_prio_highest: Link to the RB node referencing the message with the |
21544 |
-+ * highest priority in the tree. |
21545 |
-+ */ |
21546 |
-+struct kdbus_queue { |
21547 |
-+ struct list_head msg_list; |
21548 |
-+ struct rb_root msg_prio_queue; |
21549 |
-+ struct rb_node *msg_prio_highest; |
21550 |
-+}; |
21551 |
-+ |
21552 |
-+/** |
21553 |
-+ * struct kdbus_queue_entry - messages waiting to be read |
21554 |
-+ * @entry: Entry in the connection's list |
21555 |
-+ * @prio_node: Entry in the priority queue tree |
21556 |
-+ * @prio_entry: Queue tree node entry in the list of one priority |
21557 |
-+ * @priority: Message priority |
21558 |
-+ * @dst_name_id: The sequence number of the name this message is |
21559 |
-+ * addressed to, 0 for messages sent to an ID |
21560 |
-+ * @conn: Connection this entry is queued on |
21561 |
-+ * @gaps: Gaps object to fill message gaps at RECV time |
21562 |
-+ * @user: User used for accounting |
21563 |
-+ * @slice: Slice in the receiver's pool for the message |
21564 |
-+ * @reply: The reply block if a reply to this message is expected |
21565 |
-+ */ |
21566 |
-+struct kdbus_queue_entry { |
21567 |
-+ struct list_head entry; |
21568 |
-+ struct rb_node prio_node; |
21569 |
-+ struct list_head prio_entry; |
21570 |
-+ |
21571 |
-+ s64 priority; |
21572 |
-+ u64 dst_name_id; |
21573 |
-+ |
21574 |
-+ struct kdbus_conn *conn; |
21575 |
-+ struct kdbus_gaps *gaps; |
21576 |
-+ struct kdbus_user *user; |
21577 |
-+ struct kdbus_pool_slice *slice; |
21578 |
-+ struct kdbus_reply *reply; |
21579 |
-+}; |
21580 |
-+ |
21581 |
-+void kdbus_queue_init(struct kdbus_queue *queue); |
21582 |
-+struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, |
21583 |
-+ s64 priority, bool use_priority); |
21584 |
-+ |
21585 |
-+struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src, |
21586 |
-+ struct kdbus_conn *dst, |
21587 |
-+ struct kdbus_staging *s); |
21588 |
-+void kdbus_queue_entry_free(struct kdbus_queue_entry *entry); |
21589 |
-+int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, |
21590 |
-+ u64 *return_flags, bool install_fds); |
21591 |
-+void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, |
21592 |
-+ struct kdbus_reply *reply); |
21593 |
-+int kdbus_queue_entry_move(struct kdbus_queue_entry *entry, |
21594 |
-+ struct kdbus_conn *dst); |
21595 |
-+ |
21596 |
-+#endif /* __KDBUS_QUEUE_H */ |
21597 |
-diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c |
21598 |
-new file mode 100644 |
21599 |
-index 0000000..e6791d8 |
21600 |
---- /dev/null |
21601 |
-+++ b/ipc/kdbus/reply.c |
21602 |
-@@ -0,0 +1,252 @@ |
21603 |
-+#include <linux/init.h> |
21604 |
-+#include <linux/mm.h> |
21605 |
-+#include <linux/module.h> |
21606 |
-+#include <linux/mutex.h> |
21607 |
-+#include <linux/slab.h> |
21608 |
-+#include <linux/uio.h> |
21609 |
-+ |
21610 |
-+#include "bus.h" |
21611 |
-+#include "connection.h" |
21612 |
-+#include "endpoint.h" |
21613 |
-+#include "message.h" |
21614 |
-+#include "metadata.h" |
21615 |
-+#include "names.h" |
21616 |
-+#include "domain.h" |
21617 |
-+#include "item.h" |
21618 |
-+#include "notify.h" |
21619 |
-+#include "policy.h" |
21620 |
-+#include "reply.h" |
21621 |
-+#include "util.h" |
21622 |
-+ |
21623 |
-+/** |
21624 |
-+ * kdbus_reply_new() - Allocate and set up a new kdbus_reply object |
21625 |
-+ * @reply_src: The connection a reply is expected from |
21626 |
-+ * @reply_dst: The connection this reply object belongs to |
21627 |
-+ * @msg: Message associated with the reply |
21628 |
-+ * @name_entry: Name entry used to send the message |
21629 |
-+ * @sync: Whether or not to make this reply synchronous |
21630 |
-+ * |
21631 |
-+ * Allocate and fill a new kdbus_reply object. |
21632 |
-+ * |
21633 |
-+ * Return: New kdbus_conn object on success, ERR_PTR on error. |
21634 |
-+ */ |
21635 |
-+struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, |
21636 |
-+ struct kdbus_conn *reply_dst, |
21637 |
-+ const struct kdbus_msg *msg, |
21638 |
-+ struct kdbus_name_entry *name_entry, |
21639 |
-+ bool sync) |
21640 |
-+{ |
21641 |
-+ struct kdbus_reply *r; |
21642 |
-+ int ret; |
21643 |
-+ |
21644 |
-+ if (atomic_inc_return(&reply_dst->request_count) > |
21645 |
-+ KDBUS_CONN_MAX_REQUESTS_PENDING) { |
21646 |
-+ ret = -EMLINK; |
21647 |
-+ goto exit_dec_request_count; |
21648 |
-+ } |
21649 |
-+ |
21650 |
-+ r = kzalloc(sizeof(*r), GFP_KERNEL); |
21651 |
-+ if (!r) { |
21652 |
-+ ret = -ENOMEM; |
21653 |
-+ goto exit_dec_request_count; |
21654 |
-+ } |
21655 |
-+ |
21656 |
-+ kref_init(&r->kref); |
21657 |
-+ INIT_LIST_HEAD(&r->entry); |
21658 |
-+ r->reply_src = kdbus_conn_ref(reply_src); |
21659 |
-+ r->reply_dst = kdbus_conn_ref(reply_dst); |
21660 |
-+ r->cookie = msg->cookie; |
21661 |
-+ r->name_id = name_entry ? name_entry->name_id : 0; |
21662 |
-+ r->deadline_ns = msg->timeout_ns; |
21663 |
-+ |
21664 |
-+ if (sync) { |
21665 |
-+ r->sync = true; |
21666 |
-+ r->waiting = true; |
21667 |
-+ } |
21668 |
-+ |
21669 |
-+ return r; |
21670 |
-+ |
21671 |
-+exit_dec_request_count: |
21672 |
-+ atomic_dec(&reply_dst->request_count); |
21673 |
-+ return ERR_PTR(ret); |
21674 |
-+} |
21675 |
-+ |
21676 |
-+static void __kdbus_reply_free(struct kref *kref) |
21677 |
-+{ |
21678 |
-+ struct kdbus_reply *reply = |
21679 |
-+ container_of(kref, struct kdbus_reply, kref); |
21680 |
-+ |
21681 |
-+ atomic_dec(&reply->reply_dst->request_count); |
21682 |
-+ kdbus_conn_unref(reply->reply_src); |
21683 |
-+ kdbus_conn_unref(reply->reply_dst); |
21684 |
-+ kfree(reply); |
21685 |
-+} |
21686 |
-+ |
21687 |
-+/** |
21688 |
-+ * kdbus_reply_ref() - Increase reference on kdbus_reply |
21689 |
-+ * @r: The reply, may be %NULL |
21690 |
-+ * |
21691 |
-+ * Return: The reply object with an extra reference |
21692 |
-+ */ |
21693 |
-+struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r) |
21694 |
-+{ |
21695 |
-+ if (r) |
21696 |
-+ kref_get(&r->kref); |
21697 |
-+ return r; |
21698 |
-+} |
21699 |
-+ |
21700 |
-+/** |
21701 |
-+ * kdbus_reply_unref() - Decrease reference on kdbus_reply |
21702 |
-+ * @r: The reply, may be %NULL |
21703 |
-+ * |
21704 |
-+ * Return: NULL |
21705 |
-+ */ |
21706 |
-+struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r) |
21707 |
-+{ |
21708 |
-+ if (r) |
21709 |
-+ kref_put(&r->kref, __kdbus_reply_free); |
21710 |
-+ return NULL; |
21711 |
-+} |
21712 |
-+ |
21713 |
-+/** |
21714 |
-+ * kdbus_reply_link() - Link reply object into target connection |
21715 |
-+ * @r: Reply to link |
21716 |
-+ */ |
21717 |
-+void kdbus_reply_link(struct kdbus_reply *r) |
21718 |
-+{ |
21719 |
-+ if (WARN_ON(!list_empty(&r->entry))) |
21720 |
-+ return; |
21721 |
-+ |
21722 |
-+ list_add(&r->entry, &r->reply_dst->reply_list); |
21723 |
-+ kdbus_reply_ref(r); |
21724 |
-+} |
21725 |
-+ |
21726 |
-+/** |
21727 |
-+ * kdbus_reply_unlink() - Unlink reply object from target connection |
21728 |
-+ * @r: Reply to unlink |
21729 |
-+ */ |
21730 |
-+void kdbus_reply_unlink(struct kdbus_reply *r) |
21731 |
-+{ |
21732 |
-+ if (!list_empty(&r->entry)) { |
21733 |
-+ list_del_init(&r->entry); |
21734 |
-+ kdbus_reply_unref(r); |
21735 |
-+ } |
21736 |
-+} |
21737 |
-+ |
21738 |
-+/** |
21739 |
-+ * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply |
21740 |
-+ * @reply: The reply object |
21741 |
-+ * @err: Error code to set on the remote side |
21742 |
-+ * |
21743 |
-+ * Wake up remote peer (method origin) with the appropriate synchronous reply |
21744 |
-+ * code. |
21745 |
-+ */ |
21746 |
-+void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err) |
21747 |
-+{ |
21748 |
-+ if (WARN_ON(!reply->sync)) |
21749 |
-+ return; |
21750 |
-+ |
21751 |
-+ reply->waiting = false; |
21752 |
-+ reply->err = err; |
21753 |
-+ wake_up_interruptible(&reply->reply_dst->wait); |
21754 |
-+} |
21755 |
-+ |
21756 |
-+/** |
21757 |
-+ * kdbus_reply_find() - Find the corresponding reply object |
21758 |
-+ * @replying: The replying connection or NULL |
21759 |
-+ * @reply_dst: The connection the reply will be sent to |
21760 |
-+ * (method origin) |
21761 |
-+ * @cookie: The cookie of the requesting message |
21762 |
-+ * |
21763 |
-+ * Lookup a reply object that should be sent as a reply by |
21764 |
-+ * @replying to @reply_dst with the given cookie. |
21765 |
-+ * |
21766 |
-+ * Callers must take the @reply_dst lock. |
21767 |
-+ * |
21768 |
-+ * Return: the corresponding reply object or NULL if not found |
21769 |
-+ */ |
21770 |
-+struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, |
21771 |
-+ struct kdbus_conn *reply_dst, |
21772 |
-+ u64 cookie) |
21773 |
-+{ |
21774 |
-+ struct kdbus_reply *r; |
21775 |
-+ |
21776 |
-+ list_for_each_entry(r, &reply_dst->reply_list, entry) { |
21777 |
-+ if (r->cookie == cookie && |
21778 |
-+ (!replying || r->reply_src == replying)) |
21779 |
-+ return r; |
21780 |
-+ } |
21781 |
-+ |
21782 |
-+ return NULL; |
21783 |
-+} |
21784 |
-+ |
21785 |
-+/** |
21786 |
-+ * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a |
21787 |
-+ * connection for exceeded timeouts |
21788 |
-+ * @work: Work struct of the connection to scan |
21789 |
-+ * |
21790 |
-+ * Walk the list of replies stored with a connection and look for entries |
21791 |
-+ * that have exceeded their timeout. If such an entry is found, a timeout |
21792 |
-+ * notification is sent to the waiting peer, and the reply is removed from |
21793 |
-+ * the list. |
21794 |
-+ * |
21795 |
-+ * The work is rescheduled to the nearest timeout found during the list |
21796 |
-+ * iteration. |
21797 |
-+ */ |
21798 |
-+void kdbus_reply_list_scan_work(struct work_struct *work) |
21799 |
-+{ |
21800 |
-+ struct kdbus_conn *conn = |
21801 |
-+ container_of(work, struct kdbus_conn, work.work); |
21802 |
-+ struct kdbus_reply *reply, *reply_tmp; |
21803 |
-+ u64 deadline = ~0ULL; |
21804 |
-+ u64 now; |
21805 |
-+ |
21806 |
-+ now = ktime_get_ns(); |
21807 |
-+ |
21808 |
-+ mutex_lock(&conn->lock); |
21809 |
-+ if (!kdbus_conn_active(conn)) { |
21810 |
-+ mutex_unlock(&conn->lock); |
21811 |
-+ return; |
21812 |
-+ } |
21813 |
-+ |
21814 |
-+ list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) { |
21815 |
-+ /* |
21816 |
-+ * If the reply block is waiting for synchronous I/O, |
21817 |
-+ * the timeout is handled by wait_event_*_timeout(), |
21818 |
-+ * so we don't have to care for it here. |
21819 |
-+ */ |
21820 |
-+ if (reply->sync && !reply->interrupted) |
21821 |
-+ continue; |
21822 |
-+ |
21823 |
-+ WARN_ON(reply->reply_dst != conn); |
21824 |
-+ |
21825 |
-+ if (reply->deadline_ns > now) { |
21826 |
-+ /* remember next timeout */ |
21827 |
-+ if (deadline > reply->deadline_ns) |
21828 |
-+ deadline = reply->deadline_ns; |
21829 |
-+ |
21830 |
-+ continue; |
21831 |
-+ } |
21832 |
-+ |
21833 |
-+ /* |
21834 |
-+ * A zero deadline means the connection died, was |
21835 |
-+ * cleaned up already and the notification was sent. |
21836 |
-+ * Don't send notifications for reply trackers that were |
21837 |
-+ * left in an interrupted syscall state. |
21838 |
-+ */ |
21839 |
-+ if (reply->deadline_ns != 0 && !reply->interrupted) |
21840 |
-+ kdbus_notify_reply_timeout(conn->ep->bus, conn->id, |
21841 |
-+ reply->cookie); |
21842 |
-+ |
21843 |
-+ kdbus_reply_unlink(reply); |
21844 |
-+ } |
21845 |
-+ |
21846 |
-+ /* rearm delayed work with next timeout */ |
21847 |
-+ if (deadline != ~0ULL) |
21848 |
-+ schedule_delayed_work(&conn->work, |
21849 |
-+ nsecs_to_jiffies(deadline - now)); |
21850 |
-+ |
21851 |
-+ mutex_unlock(&conn->lock); |
21852 |
-+ |
21853 |
-+ kdbus_notify_flush(conn->ep->bus); |
21854 |
-+} |
21855 |
-diff --git a/ipc/kdbus/reply.h b/ipc/kdbus/reply.h |
21856 |
-new file mode 100644 |
21857 |
-index 0000000..68d5232 |
21858 |
---- /dev/null |
21859 |
-+++ b/ipc/kdbus/reply.h |
21860 |
-@@ -0,0 +1,68 @@ |
21861 |
-+/* |
21862 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21863 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21864 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21865 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21866 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21867 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21868 |
-+ * |
21869 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21870 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21871 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21872 |
-+ * your option) any later version. |
21873 |
-+ */ |
21874 |
-+ |
21875 |
-+#ifndef __KDBUS_REPLY_H |
21876 |
-+#define __KDBUS_REPLY_H |
21877 |
-+ |
21878 |
-+/** |
21879 |
-+ * struct kdbus_reply - an entry of kdbus_conn's list of replies |
21880 |
-+ * @kref: Ref-count of this object |
21881 |
-+ * @entry: The entry of the connection's reply_list |
21882 |
-+ * @reply_src: The connection the reply will be sent from |
21883 |
-+ * @reply_dst: The connection the reply will be sent to |
21884 |
-+ * @queue_entry: The queue entry item that is prepared by the replying |
21885 |
-+ * connection |
21886 |
-+ * @deadline_ns: The deadline of the reply, in nanoseconds |
21887 |
-+ * @cookie: The cookie of the requesting message |
21888 |
-+ * @name_id: ID of the well-known name the original msg was sent to |
21889 |
-+ * @sync: The reply block is waiting for synchronous I/O |
21890 |
-+ * @waiting: The condition to synchronously wait for |
21891 |
-+ * @interrupted: The sync reply was left in an interrupted state |
21892 |
-+ * @err: The error code for the synchronous reply |
21893 |
-+ */ |
21894 |
-+struct kdbus_reply { |
21895 |
-+ struct kref kref; |
21896 |
-+ struct list_head entry; |
21897 |
-+ struct kdbus_conn *reply_src; |
21898 |
-+ struct kdbus_conn *reply_dst; |
21899 |
-+ struct kdbus_queue_entry *queue_entry; |
21900 |
-+ u64 deadline_ns; |
21901 |
-+ u64 cookie; |
21902 |
-+ u64 name_id; |
21903 |
-+ bool sync:1; |
21904 |
-+ bool waiting:1; |
21905 |
-+ bool interrupted:1; |
21906 |
-+ int err; |
21907 |
-+}; |
21908 |
-+ |
21909 |
-+struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, |
21910 |
-+ struct kdbus_conn *reply_dst, |
21911 |
-+ const struct kdbus_msg *msg, |
21912 |
-+ struct kdbus_name_entry *name_entry, |
21913 |
-+ bool sync); |
21914 |
-+ |
21915 |
-+struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r); |
21916 |
-+struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r); |
21917 |
-+ |
21918 |
-+void kdbus_reply_link(struct kdbus_reply *r); |
21919 |
-+void kdbus_reply_unlink(struct kdbus_reply *r); |
21920 |
-+ |
21921 |
-+struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, |
21922 |
-+ struct kdbus_conn *reply_dst, |
21923 |
-+ u64 cookie); |
21924 |
-+ |
21925 |
-+void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err); |
21926 |
-+void kdbus_reply_list_scan_work(struct work_struct *work); |
21927 |
-+ |
21928 |
-+#endif /* __KDBUS_REPLY_H */ |
21929 |
-diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c |
21930 |
-new file mode 100644 |
21931 |
-index 0000000..72b1883 |
21932 |
---- /dev/null |
21933 |
-+++ b/ipc/kdbus/util.c |
21934 |
-@@ -0,0 +1,156 @@ |
21935 |
-+/* |
21936 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21937 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21938 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21939 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21940 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21941 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21942 |
-+ * |
21943 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21944 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21945 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21946 |
-+ * your option) any later version. |
21947 |
-+ */ |
21948 |
-+ |
21949 |
-+#include <linux/capability.h> |
21950 |
-+#include <linux/cred.h> |
21951 |
-+#include <linux/ctype.h> |
21952 |
-+#include <linux/err.h> |
21953 |
-+#include <linux/file.h> |
21954 |
-+#include <linux/slab.h> |
21955 |
-+#include <linux/string.h> |
21956 |
-+#include <linux/uaccess.h> |
21957 |
-+#include <linux/uio.h> |
21958 |
-+#include <linux/user_namespace.h> |
21959 |
-+ |
21960 |
-+#include "limits.h" |
21961 |
-+#include "util.h" |
21962 |
-+ |
21963 |
-+/** |
21964 |
-+ * kdbus_copy_from_user() - copy aligned data from user-space |
21965 |
-+ * @dest: target buffer in kernel memory |
21966 |
-+ * @user_ptr: user-provided source buffer |
21967 |
-+ * @size: memory size to copy from user |
21968 |
-+ * |
21969 |
-+ * This copies @size bytes from @user_ptr into the kernel, just like |
21970 |
-+ * copy_from_user() does. But we enforce an 8-byte alignment and reject any |
21971 |
-+ * unaligned user-space pointers. |
21972 |
-+ * |
21973 |
-+ * Return: 0 on success, negative error code on failure. |
21974 |
-+ */ |
21975 |
-+int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size) |
21976 |
-+{ |
21977 |
-+ if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr)) |
21978 |
-+ return -EFAULT; |
21979 |
-+ |
21980 |
-+ if (copy_from_user(dest, user_ptr, size)) |
21981 |
-+ return -EFAULT; |
21982 |
-+ |
21983 |
-+ return 0; |
21984 |
-+} |
21985 |
-+ |
21986 |
-+/** |
21987 |
-+ * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name |
21988 |
-+ * @name: user-supplied name to verify |
21989 |
-+ * @user_ns: user-namespace to act in |
21990 |
-+ * @kuid: Kernel internal uid of user |
21991 |
-+ * |
21992 |
-+ * This verifies that the user-supplied name @name has their UID as prefix. This |
21993 |
-+ * is the default name-spacing policy we enforce on user-supplied names for |
21994 |
-+ * public kdbus entities like buses and endpoints. |
21995 |
-+ * |
21996 |
-+ * The user must supply names prefixed with "<UID>-", whereas the UID is |
21997 |
-+ * interpreted in the user-namespace of the domain. If the user fails to supply |
21998 |
-+ * such a prefixed name, we reject it. |
21999 |
-+ * |
22000 |
-+ * Return: 0 on success, negative error code on failure |
22001 |
-+ */ |
22002 |
-+int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, |
22003 |
-+ kuid_t kuid) |
22004 |
-+{ |
22005 |
-+ uid_t uid; |
22006 |
-+ char prefix[16]; |
22007 |
-+ |
22008 |
-+ /* |
22009 |
-+ * The kuid must have a mapping into the userns of the domain |
22010 |
-+ * otherwise do not allow creation of buses nor endpoints. |
22011 |
-+ */ |
22012 |
-+ uid = from_kuid(user_ns, kuid); |
22013 |
-+ if (uid == (uid_t) -1) |
22014 |
-+ return -EINVAL; |
22015 |
-+ |
22016 |
-+ snprintf(prefix, sizeof(prefix), "%u-", uid); |
22017 |
-+ if (strncmp(name, prefix, strlen(prefix)) != 0) |
22018 |
-+ return -EINVAL; |
22019 |
-+ |
22020 |
-+ return 0; |
22021 |
-+} |
22022 |
-+ |
22023 |
-+/** |
22024 |
-+ * kdbus_sanitize_attach_flags() - Sanitize attach flags from user-space |
22025 |
-+ * @flags: Attach flags provided by userspace |
22026 |
-+ * @attach_flags: A pointer where to store the valid attach flags |
22027 |
-+ * |
22028 |
-+ * Convert attach-flags provided by user-space into a valid mask. If the mask |
22029 |
-+ * is invalid, an error is returned. The sanitized attach flags are stored in |
22030 |
-+ * the output parameter. |
22031 |
-+ * |
22032 |
-+ * Return: 0 on success, negative error on failure. |
22033 |
-+ */ |
22034 |
-+int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags) |
22035 |
-+{ |
22036 |
-+ /* 'any' degrades to 'all' for compatibility */ |
22037 |
-+ if (flags == _KDBUS_ATTACH_ANY) |
22038 |
-+ flags = _KDBUS_ATTACH_ALL; |
22039 |
-+ |
22040 |
-+ /* reject unknown attach flags */ |
22041 |
-+ if (flags & ~_KDBUS_ATTACH_ALL) |
22042 |
-+ return -EINVAL; |
22043 |
-+ |
22044 |
-+ *attach_flags = flags; |
22045 |
-+ return 0; |
22046 |
-+} |
22047 |
-+ |
22048 |
-+/** |
22049 |
-+ * kdbus_kvec_set - helper utility to assemble kvec arrays |
22050 |
-+ * @kvec: kvec entry to use |
22051 |
-+ * @src: Source address to set in @kvec |
22052 |
-+ * @len: Number of bytes in @src |
22053 |
-+ * @total_len: Pointer to total length variable |
22054 |
-+ * |
22055 |
-+ * Set @src and @len in @kvec, and increase @total_len by @len. |
22056 |
-+ */ |
22057 |
-+void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len) |
22058 |
-+{ |
22059 |
-+ kvec->iov_base = src; |
22060 |
-+ kvec->iov_len = len; |
22061 |
-+ *total_len += len; |
22062 |
-+} |
22063 |
-+ |
22064 |
-+static const char * const zeros = "\0\0\0\0\0\0\0"; |
22065 |
-+ |
22066 |
-+/** |
22067 |
-+ * kdbus_kvec_pad - conditionally write a padding kvec |
22068 |
-+ * @kvec: kvec entry to use |
22069 |
-+ * @len: Total length used for kvec array |
22070 |
-+ * |
22071 |
-+ * Check if the current total byte length of the array in @len is aligned to |
22072 |
-+ * 8 bytes. If it isn't, fill @kvec with padding information and increase @len |
22073 |
-+ * by the number of bytes stored in @kvec. |
22074 |
-+ * |
22075 |
-+ * Return: the number of added padding bytes. |
22076 |
-+ */ |
22077 |
-+size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len) |
22078 |
-+{ |
22079 |
-+ size_t pad = KDBUS_ALIGN8(*len) - *len; |
22080 |
-+ |
22081 |
-+ if (!pad) |
22082 |
-+ return 0; |
22083 |
-+ |
22084 |
-+ kvec->iov_base = (void *)zeros; |
22085 |
-+ kvec->iov_len = pad; |
22086 |
-+ |
22087 |
-+ *len += pad; |
22088 |
-+ |
22089 |
-+ return pad; |
22090 |
-+} |
22091 |
-diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h |
22092 |
-new file mode 100644 |
22093 |
-index 0000000..5297166 |
22094 |
---- /dev/null |
22095 |
-+++ b/ipc/kdbus/util.h |
22096 |
-@@ -0,0 +1,73 @@ |
22097 |
-+/* |
22098 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
22099 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
22100 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
22101 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
22102 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
22103 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
22104 |
-+ * |
22105 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
22106 |
-+ * the terms of the GNU Lesser General Public License as published by the |
22107 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
22108 |
-+ * your option) any later version. |
22109 |
-+ */ |
22110 |
-+ |
22111 |
-+#ifndef __KDBUS_UTIL_H |
22112 |
-+#define __KDBUS_UTIL_H |
22113 |
-+ |
22114 |
-+#include <linux/dcache.h> |
22115 |
-+#include <linux/ioctl.h> |
22116 |
-+ |
22117 |
-+#include <uapi/linux/kdbus.h> |
22118 |
-+ |
22119 |
-+/* all exported addresses are 64 bit */ |
22120 |
-+#define KDBUS_PTR(addr) ((void __user *)(uintptr_t)(addr)) |
22121 |
-+ |
22122 |
-+/* all exported sizes are 64 bit and data aligned to 64 bit */ |
22123 |
-+#define KDBUS_ALIGN8(s) ALIGN((s), 8) |
22124 |
-+#define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8)) |
22125 |
-+ |
22126 |
-+/** |
22127 |
-+ * kdbus_member_set_user - write a structure member to user memory |
22128 |
-+ * @_s: Variable to copy from |
22129 |
-+ * @_b: Buffer to write to |
22130 |
-+ * @_t: Structure type |
22131 |
-+ * @_m: Member name in the passed structure |
22132 |
-+ * |
22133 |
-+ * Return: the result of copy_to_user() |
22134 |
-+ */ |
22135 |
-+#define kdbus_member_set_user(_s, _b, _t, _m) \ |
22136 |
-+({ \ |
22137 |
-+ u64 __user *_sz = \ |
22138 |
-+ (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \ |
22139 |
-+ copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \ |
22140 |
-+}) |
22141 |
-+ |
22142 |
-+/** |
22143 |
-+ * kdbus_strhash - calculate a hash |
22144 |
-+ * @str: String |
22145 |
-+ * |
22146 |
-+ * Return: hash value |
22147 |
-+ */ |
22148 |
-+static inline unsigned int kdbus_strhash(const char *str) |
22149 |
-+{ |
22150 |
-+ unsigned long hash = init_name_hash(); |
22151 |
-+ |
22152 |
-+ while (*str) |
22153 |
-+ hash = partial_name_hash(*str++, hash); |
22154 |
-+ |
22155 |
-+ return end_name_hash(hash); |
22156 |
-+} |
22157 |
-+ |
22158 |
-+int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, |
22159 |
-+ kuid_t kuid); |
22160 |
-+int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags); |
22161 |
-+ |
22162 |
-+int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size); |
22163 |
-+ |
22164 |
-+struct kvec; |
22165 |
-+ |
22166 |
-+void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len); |
22167 |
-+size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len); |
22168 |
-+ |
22169 |
-+#endif |
22170 |
-diff --git a/samples/Kconfig b/samples/Kconfig |
22171 |
-index 224ebb4..a4c6b2f 100644 |
22172 |
---- a/samples/Kconfig |
22173 |
-+++ b/samples/Kconfig |
22174 |
-@@ -55,6 +55,13 @@ config SAMPLE_KDB |
22175 |
- Build an example of how to dynamically add the hello |
22176 |
- command to the kdb shell. |
22177 |
- |
22178 |
-+config SAMPLE_KDBUS |
22179 |
-+ bool "Build kdbus API example" |
22180 |
-+ depends on KDBUS |
22181 |
-+ help |
22182 |
-+ Build an example of how the kdbus API can be used from |
22183 |
-+ userspace. |
22184 |
-+ |
22185 |
- config SAMPLE_RPMSG_CLIENT |
22186 |
- tristate "Build rpmsg client sample -- loadable modules only" |
22187 |
- depends on RPMSG && m |
22188 |
-diff --git a/samples/Makefile b/samples/Makefile |
22189 |
-index f00257b..f0ad51e 100644 |
22190 |
---- a/samples/Makefile |
22191 |
-+++ b/samples/Makefile |
22192 |
-@@ -1,4 +1,5 @@ |
22193 |
- # Makefile for Linux samples code |
22194 |
- |
22195 |
- obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ |
22196 |
-- hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ |
22197 |
-+ hw_breakpoint/ kfifo/ kdb/ kdbus/ hidraw/ rpmsg/ \ |
22198 |
-+ seccomp/ |
22199 |
-diff --git a/samples/kdbus/.gitignore b/samples/kdbus/.gitignore |
22200 |
-new file mode 100644 |
22201 |
-index 0000000..ee07d98 |
22202 |
---- /dev/null |
22203 |
-+++ b/samples/kdbus/.gitignore |
22204 |
-@@ -0,0 +1 @@ |
22205 |
-+kdbus-workers |
22206 |
-diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile |
22207 |
-new file mode 100644 |
22208 |
-index 0000000..137f842 |
22209 |
---- /dev/null |
22210 |
-+++ b/samples/kdbus/Makefile |
22211 |
-@@ -0,0 +1,9 @@ |
22212 |
-+# kbuild trick to avoid linker error. Can be omitted if a module is built. |
22213 |
-+obj- := dummy.o |
22214 |
-+ |
22215 |
-+hostprogs-$(CONFIG_SAMPLE_KDBUS) += kdbus-workers |
22216 |
-+ |
22217 |
-+always := $(hostprogs-y) |
22218 |
-+ |
22219 |
-+HOSTCFLAGS_kdbus-workers.o += -I$(objtree)/usr/include |
22220 |
-+HOSTLOADLIBES_kdbus-workers := -lrt |
22221 |
-diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h |
22222 |
-new file mode 100644 |
22223 |
-index 0000000..7f3abae |
22224 |
---- /dev/null |
22225 |
-+++ b/samples/kdbus/kdbus-api.h |
22226 |
-@@ -0,0 +1,114 @@ |
22227 |
-+#ifndef KDBUS_API_H |
22228 |
-+#define KDBUS_API_H |
22229 |
-+ |
22230 |
-+#include <sys/ioctl.h> |
22231 |
-+#include <linux/kdbus.h> |
22232 |
-+ |
22233 |
-+#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) |
22234 |
-+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
22235 |
-+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) |
22236 |
-+#define KDBUS_ITEM_NEXT(item) \ |
22237 |
-+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) |
22238 |
-+#define KDBUS_FOREACH(iter, first, _size) \ |
22239 |
-+ for ((iter) = (first); \ |
22240 |
-+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ |
22241 |
-+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ |
22242 |
-+ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size))) |
22243 |
-+ |
22244 |
-+static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd) |
22245 |
-+{ |
22246 |
-+ int ret = ioctl(control_fd, KDBUS_CMD_BUS_MAKE, cmd); |
22247 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22248 |
-+} |
22249 |
-+ |
22250 |
-+static inline int kdbus_cmd_endpoint_make(int bus_fd, struct kdbus_cmd *cmd) |
22251 |
-+{ |
22252 |
-+ int ret = ioctl(bus_fd, KDBUS_CMD_ENDPOINT_MAKE, cmd); |
22253 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22254 |
-+} |
22255 |
-+ |
22256 |
-+static inline int kdbus_cmd_endpoint_update(int ep_fd, struct kdbus_cmd *cmd) |
22257 |
-+{ |
22258 |
-+ int ret = ioctl(ep_fd, KDBUS_CMD_ENDPOINT_UPDATE, cmd); |
22259 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22260 |
-+} |
22261 |
-+ |
22262 |
-+static inline int kdbus_cmd_hello(int bus_fd, struct kdbus_cmd_hello *cmd) |
22263 |
-+{ |
22264 |
-+ int ret = ioctl(bus_fd, KDBUS_CMD_HELLO, cmd); |
22265 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22266 |
-+} |
22267 |
-+ |
22268 |
-+static inline int kdbus_cmd_update(int fd, struct kdbus_cmd *cmd) |
22269 |
-+{ |
22270 |
-+ int ret = ioctl(fd, KDBUS_CMD_UPDATE, cmd); |
22271 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22272 |
-+} |
22273 |
-+ |
22274 |
-+static inline int kdbus_cmd_byebye(int conn_fd, struct kdbus_cmd *cmd) |
22275 |
-+{ |
22276 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_BYEBYE, cmd); |
22277 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22278 |
-+} |
22279 |
-+ |
22280 |
-+static inline int kdbus_cmd_free(int conn_fd, struct kdbus_cmd_free *cmd) |
22281 |
-+{ |
22282 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_FREE, cmd); |
22283 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22284 |
-+} |
22285 |
-+ |
22286 |
-+static inline int kdbus_cmd_conn_info(int conn_fd, struct kdbus_cmd_info *cmd) |
22287 |
-+{ |
22288 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_CONN_INFO, cmd); |
22289 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22290 |
-+} |
22291 |
-+ |
22292 |
-+static inline int kdbus_cmd_bus_creator_info(int conn_fd, struct kdbus_cmd_info *cmd) |
22293 |
-+{ |
22294 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_BUS_CREATOR_INFO, cmd); |
22295 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22296 |
-+} |
22297 |
-+ |
22298 |
-+static inline int kdbus_cmd_list(int fd, struct kdbus_cmd_list *cmd) |
22299 |
-+{ |
22300 |
-+ int ret = ioctl(fd, KDBUS_CMD_LIST, cmd); |
22301 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22302 |
-+} |
22303 |
-+ |
22304 |
-+static inline int kdbus_cmd_send(int conn_fd, struct kdbus_cmd_send *cmd) |
22305 |
-+{ |
22306 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_SEND, cmd); |
22307 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22308 |
-+} |
22309 |
-+ |
22310 |
-+static inline int kdbus_cmd_recv(int conn_fd, struct kdbus_cmd_recv *cmd) |
22311 |
-+{ |
22312 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_RECV, cmd); |
22313 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22314 |
-+} |
22315 |
-+ |
22316 |
-+static inline int kdbus_cmd_name_acquire(int conn_fd, struct kdbus_cmd *cmd) |
22317 |
-+{ |
22318 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_ACQUIRE, cmd); |
22319 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22320 |
-+} |
22321 |
-+ |
22322 |
-+static inline int kdbus_cmd_name_release(int conn_fd, struct kdbus_cmd *cmd) |
22323 |
-+{ |
22324 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_RELEASE, cmd); |
22325 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22326 |
-+} |
22327 |
-+ |
22328 |
-+static inline int kdbus_cmd_match_add(int conn_fd, struct kdbus_cmd_match *cmd) |
22329 |
-+{ |
22330 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_ADD, cmd); |
22331 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22332 |
-+} |
22333 |
-+ |
22334 |
-+static inline int kdbus_cmd_match_remove(int conn_fd, struct kdbus_cmd_match *cmd) |
22335 |
-+{ |
22336 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_REMOVE, cmd); |
22337 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22338 |
-+} |
22339 |
-+ |
22340 |
-+#endif /* KDBUS_API_H */ |
22341 |
-diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c |
22342 |
-new file mode 100644 |
22343 |
-index 0000000..5a6dfdc |
22344 |
---- /dev/null |
22345 |
-+++ b/samples/kdbus/kdbus-workers.c |
22346 |
-@@ -0,0 +1,1346 @@ |
22347 |
-+/* |
22348 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
22349 |
-+ * |
22350 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
22351 |
-+ * the terms of the GNU Lesser General Public License as published by the |
22352 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
22353 |
-+ * your option) any later version. |
22354 |
-+ */ |
22355 |
-+ |
22356 |
-+/* |
22357 |
-+ * Example: Workers |
22358 |
-+ * This program computes prime-numbers based on the sieve of Eratosthenes. The |
22359 |
-+ * master sets up a shared memory region and spawns workers which clear out the |
22360 |
-+ * non-primes. The master reacts to keyboard input and to client-requests to |
22361 |
-+ * control what each worker does. Note that this is in no way meant as efficient |
22362 |
-+ * way to compute primes. It should only serve as example how a master/worker |
22363 |
-+ * concept can be implemented with kdbus used as control messages. |
22364 |
-+ * |
22365 |
-+ * The main process is called the 'master'. It creates a new, private bus which |
22366 |
-+ * will be used between the master and its workers to communicate. The master |
22367 |
-+ * then spawns a fixed number of workers. Whenever a worker dies (detected via |
22368 |
-+ * SIGCHLD), the master spawns a new worker. When done, the master waits for all |
22369 |
-+ * workers to exit, prints a status report and exits itself. |
22370 |
-+ * |
22371 |
-+ * The master process does *not* keep track of its workers. Instead, this |
22372 |
-+ * example implements a PULL model. That is, the master acquires a well-known |
22373 |
-+ * name on the bus which each worker uses to request tasks from the master. If |
22374 |
-+ * there are no more tasks, the master will return an empty task-list, which |
22375 |
-+ * casues a worker to exit immediately. |
22376 |
-+ * |
22377 |
-+ * As tasks can be computationally expensive, we support cancellation. Whenever |
22378 |
-+ * the master process is interrupted, it will drop its well-known name on the |
22379 |
-+ * bus. This causes kdbus to broadcast a name-change notification. The workers |
22380 |
-+ * check for broadcast messages regularly and will exit if they receive one. |
22381 |
-+ * |
22382 |
-+ * This example exists of 4 objects: |
22383 |
-+ * * master: The master object contains the context of the master process. This |
22384 |
-+ * process manages the prime-context, spawns workers and assigns |
22385 |
-+ * prime-ranges to each worker to compute. |
22386 |
-+ * The master itself does not do any prime-computations itself. |
22387 |
-+ * * child: The child object contains the context of a worker. It inherits the |
22388 |
-+ * prime context from its parent (the master) and then creates a new |
22389 |
-+ * bus context to request prime-ranges to compute. |
22390 |
-+ * * prime: The "prime" object is used to abstract how we compute primes. When |
22391 |
-+ * allocated, it prepares a memory region to hold 1 bit for each |
22392 |
-+ * natural number up to a fixed maximum ('MAX_PRIMES'). |
22393 |
-+ * The memory region is backed by a memfd which we share between |
22394 |
-+ * processes. Each worker now gets assigned a range of natural |
22395 |
-+ * numbers which it clears multiples of off the memory region. The |
22396 |
-+ * master process is responsible of distributing all natural numbers |
22397 |
-+ * up to the fixed maximum to its workers. |
22398 |
-+ * * bus: The bus object is an abstraction of the kdbus API. It is pretty |
22399 |
-+ * straightfoward and only manages the connection-fd plus the |
22400 |
-+ * memory-mapped pool in a single object. |
22401 |
-+ * |
22402 |
-+ * This example is in reversed order, which should make it easier to read |
22403 |
-+ * top-down, but requires some forward-declarations. Just ignore those. |
22404 |
-+ */ |
22405 |
-+ |
22406 |
-+#include <stdio.h> |
22407 |
-+#include <stdlib.h> |
22408 |
-+#include <sys/syscall.h> |
22409 |
-+ |
22410 |
-+/* glibc < 2.7 does not ship sys/signalfd.h */ |
22411 |
-+/* we require kernels with __NR_memfd_create */ |
22412 |
-+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7 && defined(__NR_memfd_create) |
22413 |
-+ |
22414 |
-+#include <ctype.h> |
22415 |
-+#include <errno.h> |
22416 |
-+#include <fcntl.h> |
22417 |
-+#include <linux/memfd.h> |
22418 |
-+#include <signal.h> |
22419 |
-+#include <stdbool.h> |
22420 |
-+#include <stddef.h> |
22421 |
-+#include <stdint.h> |
22422 |
-+#include <string.h> |
22423 |
-+#include <sys/mman.h> |
22424 |
-+#include <sys/poll.h> |
22425 |
-+#include <sys/signalfd.h> |
22426 |
-+#include <sys/time.h> |
22427 |
-+#include <sys/wait.h> |
22428 |
-+#include <time.h> |
22429 |
-+#include <unistd.h> |
22430 |
-+#include "kdbus-api.h" |
22431 |
-+ |
22432 |
-+/* FORWARD DECLARATIONS */ |
22433 |
-+ |
22434 |
-+#define POOL_SIZE (16 * 1024 * 1024) |
22435 |
-+#define MAX_PRIMES (2UL << 24) |
22436 |
-+#define WORKER_COUNT (16) |
22437 |
-+#define PRIME_STEPS (65536 * 4) |
22438 |
-+ |
22439 |
-+static const char *arg_busname = "example-workers"; |
22440 |
-+static const char *arg_modname = "kdbus"; |
22441 |
-+static const char *arg_master = "org.freedesktop.master"; |
22442 |
-+ |
22443 |
-+static int err_assert(int r_errno, const char *msg, const char *func, int line, |
22444 |
-+ const char *file) |
22445 |
-+{ |
22446 |
-+ r_errno = (r_errno != 0) ? -abs(r_errno) : -EFAULT; |
22447 |
-+ if (r_errno < 0) { |
22448 |
-+ errno = -r_errno; |
22449 |
-+ fprintf(stderr, "ERR: %s: %m (%s:%d in %s)\n", |
22450 |
-+ msg, func, line, file); |
22451 |
-+ } |
22452 |
-+ return r_errno; |
22453 |
-+} |
22454 |
-+ |
22455 |
-+#define err_r(_r, _msg) err_assert((_r), (_msg), __func__, __LINE__, __FILE__) |
22456 |
-+#define err(_msg) err_r(errno, (_msg)) |
22457 |
-+ |
22458 |
-+struct prime; |
22459 |
-+struct bus; |
22460 |
-+struct master; |
22461 |
-+struct child; |
22462 |
-+ |
22463 |
-+struct prime { |
22464 |
-+ int fd; |
22465 |
-+ uint8_t *area; |
22466 |
-+ size_t max; |
22467 |
-+ size_t done; |
22468 |
-+ size_t status; |
22469 |
-+}; |
22470 |
-+ |
22471 |
-+static int prime_new(struct prime **out); |
22472 |
-+static void prime_free(struct prime *p); |
22473 |
-+static bool prime_done(struct prime *p); |
22474 |
-+static void prime_consume(struct prime *p, size_t amount); |
22475 |
-+static int prime_run(struct prime *p, struct bus *cancel, size_t number); |
22476 |
-+static void prime_print(struct prime *p); |
22477 |
-+ |
22478 |
-+struct bus { |
22479 |
-+ int fd; |
22480 |
-+ uint8_t *pool; |
22481 |
-+}; |
22482 |
-+ |
22483 |
-+static int bus_open_connection(struct bus **out, uid_t uid, const char *name, |
22484 |
-+ uint64_t recv_flags); |
22485 |
-+static void bus_close_connection(struct bus *b); |
22486 |
-+static void bus_poool_free_slice(struct bus *b, uint64_t offset); |
22487 |
-+static int bus_acquire_name(struct bus *b, const char *name); |
22488 |
-+static int bus_install_name_loss_match(struct bus *b, const char *name); |
22489 |
-+static int bus_poll(struct bus *b); |
22490 |
-+static int bus_make(uid_t uid, const char *name); |
22491 |
-+ |
22492 |
-+struct master { |
22493 |
-+ size_t n_workers; |
22494 |
-+ size_t max_workers; |
22495 |
-+ |
22496 |
-+ int signal_fd; |
22497 |
-+ int control_fd; |
22498 |
-+ |
22499 |
-+ struct prime *prime; |
22500 |
-+ struct bus *bus; |
22501 |
-+}; |
22502 |
-+ |
22503 |
-+static int master_new(struct master **out); |
22504 |
-+static void master_free(struct master *m); |
22505 |
-+static int master_run(struct master *m); |
22506 |
-+static int master_poll(struct master *m); |
22507 |
-+static int master_handle_stdin(struct master *m); |
22508 |
-+static int master_handle_signal(struct master *m); |
22509 |
-+static int master_handle_bus(struct master *m); |
22510 |
-+static int master_reply(struct master *m, const struct kdbus_msg *msg); |
22511 |
-+static int master_waitpid(struct master *m); |
22512 |
-+static int master_spawn(struct master *m); |
22513 |
-+ |
22514 |
-+struct child { |
22515 |
-+ struct bus *bus; |
22516 |
-+ struct prime *prime; |
22517 |
-+}; |
22518 |
-+ |
22519 |
-+static int child_new(struct child **out, struct prime *p); |
22520 |
-+static void child_free(struct child *c); |
22521 |
-+static int child_run(struct child *c); |
22522 |
-+ |
22523 |
-+/* END OF FORWARD DECLARATIONS */ |
22524 |
-+ |
22525 |
-+/* |
22526 |
-+ * This is the main entrypoint of this example. It is pretty straightforward. We |
22527 |
-+ * create a master object, run the computation, print a status report and then |
22528 |
-+ * exit. Nothing particularly interesting here, so lets look into the master |
22529 |
-+ * object... |
22530 |
-+ */ |
22531 |
-+int main(int argc, char **argv) |
22532 |
-+{ |
22533 |
-+ struct master *m = NULL; |
22534 |
-+ int r; |
22535 |
-+ |
22536 |
-+ r = master_new(&m); |
22537 |
-+ if (r < 0) |
22538 |
-+ goto out; |
22539 |
-+ |
22540 |
-+ r = master_run(m); |
22541 |
-+ if (r < 0) |
22542 |
-+ goto out; |
22543 |
-+ |
22544 |
-+ if (0) |
22545 |
-+ prime_print(m->prime); |
22546 |
-+ |
22547 |
-+out: |
22548 |
-+ master_free(m); |
22549 |
-+ if (r < 0 && r != -EINTR) |
22550 |
-+ fprintf(stderr, "failed\n"); |
22551 |
-+ else |
22552 |
-+ fprintf(stderr, "done\n"); |
22553 |
-+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
22554 |
-+} |
22555 |
-+ |
22556 |
-+/* |
22557 |
-+ * ...this will allocate a new master context. It keeps track of the current |
22558 |
-+ * number of children/workers that are running, manages a signalfd to track |
22559 |
-+ * SIGCHLD, and creates a private kdbus bus. Afterwards, it opens its connection |
22560 |
-+ * to the bus and acquires a well known-name (arg_master). |
22561 |
-+ */ |
22562 |
-+static int master_new(struct master **out) |
22563 |
-+{ |
22564 |
-+ struct master *m; |
22565 |
-+ sigset_t smask; |
22566 |
-+ int r; |
22567 |
-+ |
22568 |
-+ m = calloc(1, sizeof(*m)); |
22569 |
-+ if (!m) |
22570 |
-+ return err("cannot allocate master"); |
22571 |
-+ |
22572 |
-+ m->max_workers = WORKER_COUNT; |
22573 |
-+ m->signal_fd = -1; |
22574 |
-+ m->control_fd = -1; |
22575 |
-+ |
22576 |
-+ /* Block SIGINT and SIGCHLD signals */ |
22577 |
-+ sigemptyset(&smask); |
22578 |
-+ sigaddset(&smask, SIGINT); |
22579 |
-+ sigaddset(&smask, SIGCHLD); |
22580 |
-+ sigprocmask(SIG_BLOCK, &smask, NULL); |
22581 |
-+ |
22582 |
-+ m->signal_fd = signalfd(-1, &smask, SFD_CLOEXEC); |
22583 |
-+ if (m->signal_fd < 0) { |
22584 |
-+ r = err("cannot create signalfd"); |
22585 |
-+ goto error; |
22586 |
-+ } |
22587 |
-+ |
22588 |
-+ r = prime_new(&m->prime); |
22589 |
-+ if (r < 0) |
22590 |
-+ goto error; |
22591 |
-+ |
22592 |
-+ m->control_fd = bus_make(getuid(), arg_busname); |
22593 |
-+ if (m->control_fd < 0) { |
22594 |
-+ r = m->control_fd; |
22595 |
-+ goto error; |
22596 |
-+ } |
22597 |
-+ |
22598 |
-+ /* |
22599 |
-+ * Open a bus connection for the master, and require each received |
22600 |
-+ * message to have a metadata item of type KDBUS_ITEM_PIDS attached. |
22601 |
-+ * The current UID is needed to compute the name of the bus node to |
22602 |
-+ * connect to. |
22603 |
-+ */ |
22604 |
-+ r = bus_open_connection(&m->bus, getuid(), |
22605 |
-+ arg_busname, KDBUS_ATTACH_PIDS); |
22606 |
-+ if (r < 0) |
22607 |
-+ goto error; |
22608 |
-+ |
22609 |
-+ /* |
22610 |
-+ * Acquire a well-known name on the bus, so children can address |
22611 |
-+ * messages to the master using KDBUS_DST_ID_NAME as destination-ID |
22612 |
-+ * of messages. |
22613 |
-+ */ |
22614 |
-+ r = bus_acquire_name(m->bus, arg_master); |
22615 |
-+ if (r < 0) |
22616 |
-+ goto error; |
22617 |
-+ |
22618 |
-+ *out = m; |
22619 |
-+ return 0; |
22620 |
-+ |
22621 |
-+error: |
22622 |
-+ master_free(m); |
22623 |
-+ return r; |
22624 |
-+} |
22625 |
-+ |
22626 |
-+/* pretty straightforward destructor of a master object */ |
22627 |
-+static void master_free(struct master *m) |
22628 |
-+{ |
22629 |
-+ if (!m) |
22630 |
-+ return; |
22631 |
-+ |
22632 |
-+ bus_close_connection(m->bus); |
22633 |
-+ if (m->control_fd >= 0) |
22634 |
-+ close(m->control_fd); |
22635 |
-+ prime_free(m->prime); |
22636 |
-+ if (m->signal_fd >= 0) |
22637 |
-+ close(m->signal_fd); |
22638 |
-+ free(m); |
22639 |
-+} |
22640 |
-+ |
22641 |
-+static int master_run(struct master *m) |
22642 |
-+{ |
22643 |
-+ int res, r = 0; |
22644 |
-+ |
22645 |
-+ while (!prime_done(m->prime)) { |
22646 |
-+ while (m->n_workers < m->max_workers) { |
22647 |
-+ r = master_spawn(m); |
22648 |
-+ if (r < 0) |
22649 |
-+ break; |
22650 |
-+ } |
22651 |
-+ |
22652 |
-+ r = master_poll(m); |
22653 |
-+ if (r < 0) |
22654 |
-+ break; |
22655 |
-+ } |
22656 |
-+ |
22657 |
-+ if (r < 0) { |
22658 |
-+ bus_close_connection(m->bus); |
22659 |
-+ m->bus = NULL; |
22660 |
-+ } |
22661 |
-+ |
22662 |
-+ while (m->n_workers > 0) { |
22663 |
-+ res = master_poll(m); |
22664 |
-+ if (res < 0) { |
22665 |
-+ if (m->bus) { |
22666 |
-+ bus_close_connection(m->bus); |
22667 |
-+ m->bus = NULL; |
22668 |
-+ } |
22669 |
-+ r = res; |
22670 |
-+ } |
22671 |
-+ } |
22672 |
-+ |
22673 |
-+ return r == -EINTR ? 0 : r; |
22674 |
-+} |
22675 |
-+ |
22676 |
-+static int master_poll(struct master *m) |
22677 |
-+{ |
22678 |
-+ struct pollfd fds[3] = {}; |
22679 |
-+ int r = 0, n = 0; |
22680 |
-+ |
22681 |
-+ /* |
22682 |
-+ * Add stdin, the eventfd and the connection owner file descriptor to |
22683 |
-+ * the pollfd table, and handle incoming traffic on the latter in |
22684 |
-+ * master_handle_bus(). |
22685 |
-+ */ |
22686 |
-+ fds[n].fd = STDIN_FILENO; |
22687 |
-+ fds[n++].events = POLLIN; |
22688 |
-+ fds[n].fd = m->signal_fd; |
22689 |
-+ fds[n++].events = POLLIN; |
22690 |
-+ if (m->bus) { |
22691 |
-+ fds[n].fd = m->bus->fd; |
22692 |
-+ fds[n++].events = POLLIN; |
22693 |
-+ } |
22694 |
-+ |
22695 |
-+ r = poll(fds, n, -1); |
22696 |
-+ if (r < 0) |
22697 |
-+ return err("poll() failed"); |
22698 |
-+ |
22699 |
-+ if (fds[0].revents & POLLIN) |
22700 |
-+ r = master_handle_stdin(m); |
22701 |
-+ else if (fds[0].revents) |
22702 |
-+ r = err("ERR/HUP on stdin"); |
22703 |
-+ if (r < 0) |
22704 |
-+ return r; |
22705 |
-+ |
22706 |
-+ if (fds[1].revents & POLLIN) |
22707 |
-+ r = master_handle_signal(m); |
22708 |
-+ else if (fds[1].revents) |
22709 |
-+ r = err("ERR/HUP on signalfd"); |
22710 |
-+ if (r < 0) |
22711 |
-+ return r; |
22712 |
-+ |
22713 |
-+ if (fds[2].revents & POLLIN) |
22714 |
-+ r = master_handle_bus(m); |
22715 |
-+ else if (fds[2].revents) |
22716 |
-+ r = err("ERR/HUP on bus"); |
22717 |
-+ |
22718 |
-+ return r; |
22719 |
-+} |
22720 |
-+ |
22721 |
-+static int master_handle_stdin(struct master *m) |
22722 |
-+{ |
22723 |
-+ char buf[128]; |
22724 |
-+ ssize_t l; |
22725 |
-+ int r = 0; |
22726 |
-+ |
22727 |
-+ l = read(STDIN_FILENO, buf, sizeof(buf)); |
22728 |
-+ if (l < 0) |
22729 |
-+ return err("cannot read stdin"); |
22730 |
-+ if (l == 0) |
22731 |
-+ return err_r(-EINVAL, "EOF on stdin"); |
22732 |
-+ |
22733 |
-+ while (l-- > 0) { |
22734 |
-+ switch (buf[l]) { |
22735 |
-+ case 'q': |
22736 |
-+ /* quit */ |
22737 |
-+ r = -EINTR; |
22738 |
-+ break; |
22739 |
-+ case '\n': |
22740 |
-+ case ' ': |
22741 |
-+ /* ignore */ |
22742 |
-+ break; |
22743 |
-+ default: |
22744 |
-+ if (isgraph(buf[l])) |
22745 |
-+ fprintf(stderr, "invalid input '%c'\n", buf[l]); |
22746 |
-+ else |
22747 |
-+ fprintf(stderr, "invalid input 0x%x\n", buf[l]); |
22748 |
-+ break; |
22749 |
-+ } |
22750 |
-+ } |
22751 |
-+ |
22752 |
-+ return r; |
22753 |
-+} |
22754 |
-+ |
22755 |
-+static int master_handle_signal(struct master *m) |
22756 |
-+{ |
22757 |
-+ struct signalfd_siginfo val; |
22758 |
-+ ssize_t l; |
22759 |
-+ |
22760 |
-+ l = read(m->signal_fd, &val, sizeof(val)); |
22761 |
-+ if (l < 0) |
22762 |
-+ return err("cannot read signalfd"); |
22763 |
-+ if (l != sizeof(val)) |
22764 |
-+ return err_r(-EINVAL, "invalid data from signalfd"); |
22765 |
-+ |
22766 |
-+ switch (val.ssi_signo) { |
22767 |
-+ case SIGCHLD: |
22768 |
-+ return master_waitpid(m); |
22769 |
-+ case SIGINT: |
22770 |
-+ return err_r(-EINTR, "interrupted"); |
22771 |
-+ default: |
22772 |
-+ return err_r(-EINVAL, "caught invalid signal"); |
22773 |
-+ } |
22774 |
-+} |
22775 |
-+ |
22776 |
-+static int master_handle_bus(struct master *m) |
22777 |
-+{ |
22778 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
22779 |
-+ const struct kdbus_msg *msg = NULL; |
22780 |
-+ const struct kdbus_item *item; |
22781 |
-+ const struct kdbus_vec *vec = NULL; |
22782 |
-+ int r = 0; |
22783 |
-+ |
22784 |
-+ /* |
22785 |
-+ * To receive a message, the KDBUS_CMD_RECV ioctl is used. |
22786 |
-+ * It takes an argument of type 'struct kdbus_cmd_recv', which |
22787 |
-+ * will contain information on the received message when the call |
22788 |
-+ * returns. See kdbus.message(7). |
22789 |
-+ */ |
22790 |
-+ r = kdbus_cmd_recv(m->bus->fd, &recv); |
22791 |
-+ /* |
22792 |
-+ * EAGAIN is returned when there is no message waiting on this |
22793 |
-+ * connection. This is not an error - simply bail out. |
22794 |
-+ */ |
22795 |
-+ if (r == -EAGAIN) |
22796 |
-+ return 0; |
22797 |
-+ if (r < 0) |
22798 |
-+ return err_r(r, "cannot receive message"); |
22799 |
-+ |
22800 |
-+ /* |
22801 |
-+ * Messages received by a connection are stored inside the connection's |
22802 |
-+ * pool, at an offset that has been returned in the 'recv' command |
22803 |
-+ * struct above. The value describes the relative offset from the |
22804 |
-+ * start address of the pool. A message is described with |
22805 |
-+ * 'struct kdbus_msg'. See kdbus.message(7). |
22806 |
-+ */ |
22807 |
-+ msg = (void *)(m->bus->pool + recv.msg.offset); |
22808 |
-+ |
22809 |
-+ /* |
22810 |
-+ * A messages describes its actual payload in an array of items. |
22811 |
-+ * KDBUS_FOREACH() is a simple iterator that walks such an array. |
22812 |
-+ * struct kdbus_msg has a field to denote its total size, which is |
22813 |
-+ * needed to determine the number of items in the array. |
22814 |
-+ */ |
22815 |
-+ KDBUS_FOREACH(item, msg->items, |
22816 |
-+ msg->size - offsetof(struct kdbus_msg, items)) { |
22817 |
-+ /* |
22818 |
-+ * An item of type PAYLOAD_OFF describes in-line memory |
22819 |
-+ * stored in the pool at a described offset. That offset is |
22820 |
-+ * relative to the start address of the message header. |
22821 |
-+ * This example program only expects one single item of that |
22822 |
-+ * type, remembers the struct kdbus_vec member of the item |
22823 |
-+ * when it sees it, and bails out if there is more than one |
22824 |
-+ * of them. |
22825 |
-+ */ |
22826 |
-+ if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { |
22827 |
-+ if (vec) { |
22828 |
-+ r = err_r(-EEXIST, |
22829 |
-+ "message with multiple vecs"); |
22830 |
-+ break; |
22831 |
-+ } |
22832 |
-+ vec = &item->vec; |
22833 |
-+ if (vec->size != 1) { |
22834 |
-+ r = err_r(-EINVAL, "invalid message size"); |
22835 |
-+ break; |
22836 |
-+ } |
22837 |
-+ |
22838 |
-+ /* |
22839 |
-+ * MEMFDs are transported as items of type PAYLOAD_MEMFD. |
22840 |
-+ * If such an item is attached, a new file descriptor was |
22841 |
-+ * installed into the task when KDBUS_CMD_RECV was called, and |
22842 |
-+ * its number is stored in item->memfd.fd. |
22843 |
-+ * Implementers *must* handle this item type and close the |
22844 |
-+ * file descriptor when no longer needed in order to prevent |
22845 |
-+ * file descriptor exhaustion. This example program just bails |
22846 |
-+ * out with an error in this case, as memfds are not expected |
22847 |
-+ * in this context. |
22848 |
-+ */ |
22849 |
-+ } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) { |
22850 |
-+ r = err_r(-EINVAL, "message with memfd"); |
22851 |
-+ break; |
22852 |
-+ } |
22853 |
-+ } |
22854 |
-+ if (r < 0) |
22855 |
-+ goto exit; |
22856 |
-+ if (!vec) { |
22857 |
-+ r = err_r(-EINVAL, "empty message"); |
22858 |
-+ goto exit; |
22859 |
-+ } |
22860 |
-+ |
22861 |
-+ switch (*((const uint8_t *)msg + vec->offset)) { |
22862 |
-+ case 'r': { |
22863 |
-+ r = master_reply(m, msg); |
22864 |
-+ break; |
22865 |
-+ } |
22866 |
-+ default: |
22867 |
-+ r = err_r(-EINVAL, "invalid message type"); |
22868 |
-+ break; |
22869 |
-+ } |
22870 |
-+ |
22871 |
-+exit: |
22872 |
-+ /* |
22873 |
-+ * We are done with the memory slice that was given to us through |
22874 |
-+ * recv.msg.offset. Tell the kernel it can use it for other content |
22875 |
-+ * in the future. See kdbus.pool(7). |
22876 |
-+ */ |
22877 |
-+ bus_poool_free_slice(m->bus, recv.msg.offset); |
22878 |
-+ return r; |
22879 |
-+} |
22880 |
-+ |
22881 |
-+static int master_reply(struct master *m, const struct kdbus_msg *msg) |
22882 |
-+{ |
22883 |
-+ struct kdbus_cmd_send cmd; |
22884 |
-+ struct kdbus_item *item; |
22885 |
-+ struct kdbus_msg *reply; |
22886 |
-+ size_t size, status, p[2]; |
22887 |
-+ int r; |
22888 |
-+ |
22889 |
-+ /* |
22890 |
-+ * This functions sends a message over kdbus. To do this, it uses the |
22891 |
-+ * KDBUS_CMD_SEND ioctl, which takes a command struct argument of type |
22892 |
-+ * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual |
22893 |
-+ * message to send. See kdbus.message(7). |
22894 |
-+ */ |
22895 |
-+ p[0] = m->prime->done; |
22896 |
-+ p[1] = prime_done(m->prime) ? 0 : PRIME_STEPS; |
22897 |
-+ |
22898 |
-+ size = sizeof(*reply); |
22899 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
22900 |
-+ |
22901 |
-+ /* Prepare the message to send */ |
22902 |
-+ reply = alloca(size); |
22903 |
-+ memset(reply, 0, size); |
22904 |
-+ reply->size = size; |
22905 |
-+ |
22906 |
-+ /* Each message has a cookie that can be used to send replies */ |
22907 |
-+ reply->cookie = 1; |
22908 |
-+ |
22909 |
-+ /* The payload_type is arbitrary, but it must be non-zero */ |
22910 |
-+ reply->payload_type = 0xdeadbeef; |
22911 |
-+ |
22912 |
-+ /* |
22913 |
-+ * We are sending a reply. Let the kernel know the cookie of the |
22914 |
-+ * message we are replying to. |
22915 |
-+ */ |
22916 |
-+ reply->cookie_reply = msg->cookie; |
22917 |
-+ |
22918 |
-+ /* |
22919 |
-+ * Messages can either be directed to a well-known name (stored as |
22920 |
-+ * string) or to a unique name (stored as number). This example does |
22921 |
-+ * the latter. If the message would be directed to a well-known name |
22922 |
-+ * instead, the message's dst_id field would be set to |
22923 |
-+ * KDBUS_DST_ID_NAME, and the name would be attaches in an item of type |
22924 |
-+ * KDBUS_ITEM_DST_NAME. See below for an example, and also refer to |
22925 |
-+ * kdbus.message(7). |
22926 |
-+ */ |
22927 |
-+ reply->dst_id = msg->src_id; |
22928 |
-+ |
22929 |
-+ /* Our message has exactly one item to store its payload */ |
22930 |
-+ item = reply->items; |
22931 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
22932 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
22933 |
-+ item->vec.address = (uintptr_t)p; |
22934 |
-+ item->vec.size = sizeof(p); |
22935 |
-+ |
22936 |
-+ /* |
22937 |
-+ * Now prepare the command struct, and reference the message we want |
22938 |
-+ * to send. |
22939 |
-+ */ |
22940 |
-+ memset(&cmd, 0, sizeof(cmd)); |
22941 |
-+ cmd.size = sizeof(cmd); |
22942 |
-+ cmd.msg_address = (uintptr_t)reply; |
22943 |
-+ |
22944 |
-+ /* |
22945 |
-+ * Finally, employ the command on the connection owner |
22946 |
-+ * file descriptor. |
22947 |
-+ */ |
22948 |
-+ r = kdbus_cmd_send(m->bus->fd, &cmd); |
22949 |
-+ if (r < 0) |
22950 |
-+ return err_r(r, "cannot send reply"); |
22951 |
-+ |
22952 |
-+ if (p[1]) { |
22953 |
-+ prime_consume(m->prime, p[1]); |
22954 |
-+ status = m->prime->done * 10000 / m->prime->max; |
22955 |
-+ if (status != m->prime->status) { |
22956 |
-+ m->prime->status = status; |
22957 |
-+ fprintf(stderr, "status: %7.3lf%%\n", |
22958 |
-+ (double)status / 100); |
22959 |
-+ } |
22960 |
-+ } |
22961 |
-+ |
22962 |
-+ return 0; |
22963 |
-+} |
22964 |
-+ |
22965 |
-+static int master_waitpid(struct master *m) |
22966 |
-+{ |
22967 |
-+ pid_t pid; |
22968 |
-+ int r; |
22969 |
-+ |
22970 |
-+ while ((pid = waitpid(-1, &r, WNOHANG)) > 0) { |
22971 |
-+ if (m->n_workers > 0) |
22972 |
-+ --m->n_workers; |
22973 |
-+ if (!WIFEXITED(r)) |
22974 |
-+ r = err_r(-EINVAL, "child died unexpectedly"); |
22975 |
-+ else if (WEXITSTATUS(r) != 0) |
22976 |
-+ r = err_r(-WEXITSTATUS(r), "child failed"); |
22977 |
-+ } |
22978 |
-+ |
22979 |
-+ return r; |
22980 |
-+} |
22981 |
-+ |
22982 |
-+static int master_spawn(struct master *m) |
22983 |
-+{ |
22984 |
-+ struct child *c = NULL; |
22985 |
-+ struct prime *p = NULL; |
22986 |
-+ pid_t pid; |
22987 |
-+ int r; |
22988 |
-+ |
22989 |
-+ /* Spawn off one child and call child_run() inside it */ |
22990 |
-+ |
22991 |
-+ pid = fork(); |
22992 |
-+ if (pid < 0) |
22993 |
-+ return err("cannot fork"); |
22994 |
-+ if (pid > 0) { |
22995 |
-+ /* parent */ |
22996 |
-+ ++m->n_workers; |
22997 |
-+ return 0; |
22998 |
-+ } |
22999 |
-+ |
23000 |
-+ /* child */ |
23001 |
-+ |
23002 |
-+ p = m->prime; |
23003 |
-+ m->prime = NULL; |
23004 |
-+ master_free(m); |
23005 |
-+ |
23006 |
-+ r = child_new(&c, p); |
23007 |
-+ if (r < 0) |
23008 |
-+ goto exit; |
23009 |
-+ |
23010 |
-+ r = child_run(c); |
23011 |
-+ |
23012 |
-+exit: |
23013 |
-+ child_free(c); |
23014 |
-+ exit(abs(r)); |
23015 |
-+} |
23016 |
-+ |
23017 |
-+static int child_new(struct child **out, struct prime *p) |
23018 |
-+{ |
23019 |
-+ struct child *c; |
23020 |
-+ int r; |
23021 |
-+ |
23022 |
-+ c = calloc(1, sizeof(*c)); |
23023 |
-+ if (!c) |
23024 |
-+ return err("cannot allocate child"); |
23025 |
-+ |
23026 |
-+ c->prime = p; |
23027 |
-+ |
23028 |
-+ /* |
23029 |
-+ * Open a connection to the bus and require each received message to |
23030 |
-+ * carry a list of the well-known names the sendind connection currently |
23031 |
-+ * owns. The current UID is needed in order to determine the name of the |
23032 |
-+ * bus node to connect to. |
23033 |
-+ */ |
23034 |
-+ r = bus_open_connection(&c->bus, getuid(), |
23035 |
-+ arg_busname, KDBUS_ATTACH_NAMES); |
23036 |
-+ if (r < 0) |
23037 |
-+ goto error; |
23038 |
-+ |
23039 |
-+ /* |
23040 |
-+ * Install a kdbus match so the child's connection gets notified when |
23041 |
-+ * the master loses its well-known name. |
23042 |
-+ */ |
23043 |
-+ r = bus_install_name_loss_match(c->bus, arg_master); |
23044 |
-+ if (r < 0) |
23045 |
-+ goto error; |
23046 |
-+ |
23047 |
-+ *out = c; |
23048 |
-+ return 0; |
23049 |
-+ |
23050 |
-+error: |
23051 |
-+ child_free(c); |
23052 |
-+ return r; |
23053 |
-+} |
23054 |
-+ |
23055 |
-+static void child_free(struct child *c) |
23056 |
-+{ |
23057 |
-+ if (!c) |
23058 |
-+ return; |
23059 |
-+ |
23060 |
-+ bus_close_connection(c->bus); |
23061 |
-+ prime_free(c->prime); |
23062 |
-+ free(c); |
23063 |
-+} |
23064 |
-+ |
23065 |
-+static int child_run(struct child *c) |
23066 |
-+{ |
23067 |
-+ struct kdbus_cmd_send cmd; |
23068 |
-+ struct kdbus_item *item; |
23069 |
-+ struct kdbus_vec *vec = NULL; |
23070 |
-+ struct kdbus_msg *msg; |
23071 |
-+ struct timespec spec; |
23072 |
-+ size_t n, steps, size; |
23073 |
-+ int r = 0; |
23074 |
-+ |
23075 |
-+ /* |
23076 |
-+ * Let's send a message to the master and ask for work. To do this, |
23077 |
-+ * we use the KDBUS_CMD_SEND ioctl, which takes an argument of type |
23078 |
-+ * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual |
23079 |
-+ * message to send. See kdbus.message(7). |
23080 |
-+ */ |
23081 |
-+ size = sizeof(*msg); |
23082 |
-+ size += KDBUS_ITEM_SIZE(strlen(arg_master) + 1); |
23083 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
23084 |
-+ |
23085 |
-+ msg = alloca(size); |
23086 |
-+ memset(msg, 0, size); |
23087 |
-+ msg->size = size; |
23088 |
-+ |
23089 |
-+ /* |
23090 |
-+ * Tell the kernel that we expect a reply to this message. This means |
23091 |
-+ * that |
23092 |
-+ * |
23093 |
-+ * a) The remote peer will gain temporary permission to talk to us |
23094 |
-+ * even if it would not be allowed to normally. |
23095 |
-+ * |
23096 |
-+ * b) A timeout value is required. |
23097 |
-+ * |
23098 |
-+ * For asynchronous send commands, if no reply is received, we will |
23099 |
-+ * get a kernel notification with an item of type |
23100 |
-+ * KDBUS_ITEM_REPLY_TIMEOUT attached. |
23101 |
-+ * |
23102 |
-+ * For synchronous send commands (which this example does), the |
23103 |
-+ * ioctl will block until a reply is received or the timeout is |
23104 |
-+ * exceeded. |
23105 |
-+ */ |
23106 |
-+ msg->flags = KDBUS_MSG_EXPECT_REPLY; |
23107 |
-+ |
23108 |
-+ /* Set our cookie. Replies must use this cookie to send their reply. */ |
23109 |
-+ msg->cookie = 1; |
23110 |
-+ |
23111 |
-+ /* The payload_type is arbitrary, but it must be non-zero */ |
23112 |
-+ msg->payload_type = 0xdeadbeef; |
23113 |
-+ |
23114 |
-+ /* |
23115 |
-+ * We are sending our message to the current owner of a well-known |
23116 |
-+ * name. This makes an item of type KDBUS_ITEM_DST_NAME mandatory. |
23117 |
-+ */ |
23118 |
-+ msg->dst_id = KDBUS_DST_ID_NAME; |
23119 |
-+ |
23120 |
-+ /* |
23121 |
-+ * Set the reply timeout to 5 seconds. Timeouts are always set in |
23122 |
-+ * absolute timestamps, based con CLOCK_MONOTONIC. See kdbus.message(7). |
23123 |
-+ */ |
23124 |
-+ clock_gettime(CLOCK_MONOTONIC_COARSE, &spec); |
23125 |
-+ msg->timeout_ns += (5 + spec.tv_sec) * 1000ULL * 1000ULL * 1000ULL; |
23126 |
-+ msg->timeout_ns += spec.tv_nsec; |
23127 |
-+ |
23128 |
-+ /* |
23129 |
-+ * Fill the appended items. First, set the well-known name of the |
23130 |
-+ * destination we want to talk to. |
23131 |
-+ */ |
23132 |
-+ item = msg->items; |
23133 |
-+ item->type = KDBUS_ITEM_DST_NAME; |
23134 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(arg_master) + 1; |
23135 |
-+ strcpy(item->str, arg_master); |
23136 |
-+ |
23137 |
-+ /* |
23138 |
-+ * The 2nd item contains a vector to memory we want to send. It |
23139 |
-+ * can be content of any type. In our case, we're sending a one-byte |
23140 |
-+ * string only. The memory referenced by this item will be copied into |
23141 |
-+ * the pool of the receiver connection, and does not need to be valid |
23142 |
-+ * after the command is employed. |
23143 |
-+ */ |
23144 |
-+ item = KDBUS_ITEM_NEXT(item); |
23145 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
23146 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
23147 |
-+ item->vec.address = (uintptr_t)"r"; |
23148 |
-+ item->vec.size = 1; |
23149 |
-+ |
23150 |
-+ /* Set up the command struct and reference the message we prepared */ |
23151 |
-+ memset(&cmd, 0, sizeof(cmd)); |
23152 |
-+ cmd.size = sizeof(cmd); |
23153 |
-+ cmd.msg_address = (uintptr_t)msg; |
23154 |
-+ |
23155 |
-+ /* |
23156 |
-+ * The send commands knows a mode in which it will block until a |
23157 |
-+ * reply to a message is received. This example uses that mode. |
23158 |
-+ * The pool offset to the received reply will be stored in the command |
23159 |
-+ * struct after the send command returned. See below. |
23160 |
-+ */ |
23161 |
-+ cmd.flags = KDBUS_SEND_SYNC_REPLY; |
23162 |
-+ |
23163 |
-+ /* |
23164 |
-+ * Finally, employ the command on the connection owner |
23165 |
-+ * file descriptor. |
23166 |
-+ */ |
23167 |
-+ r = kdbus_cmd_send(c->bus->fd, &cmd); |
23168 |
-+ if (r == -ESRCH || r == -EPIPE || r == -ECONNRESET) |
23169 |
-+ return 0; |
23170 |
-+ if (r < 0) |
23171 |
-+ return err_r(r, "cannot send request to master"); |
23172 |
-+ |
23173 |
-+ /* |
23174 |
-+ * The command was sent with the KDBUS_SEND_SYNC_REPLY flag set, |
23175 |
-+ * and returned successfully, which means that cmd.reply.offset now |
23176 |
-+ * points to a message inside our connection's pool where the reply |
23177 |
-+ * is found. This is equivalent to receiving the reply with |
23178 |
-+ * KDBUS_CMD_RECV, but it doesn't require waiting for the reply with |
23179 |
-+ * poll() and also saves the ioctl to receive the message. |
23180 |
-+ */ |
23181 |
-+ msg = (void *)(c->bus->pool + cmd.reply.offset); |
23182 |
-+ |
23183 |
-+ /* |
23184 |
-+ * A messages describes its actual payload in an array of items. |
23185 |
-+ * KDBUS_FOREACH() is a simple iterator that walks such an array. |
23186 |
-+ * struct kdbus_msg has a field to denote its total size, which is |
23187 |
-+ * needed to determine the number of items in the array. |
23188 |
-+ */ |
23189 |
-+ KDBUS_FOREACH(item, msg->items, |
23190 |
-+ msg->size - offsetof(struct kdbus_msg, items)) { |
23191 |
-+ /* |
23192 |
-+ * An item of type PAYLOAD_OFF describes in-line memory |
23193 |
-+ * stored in the pool at a described offset. That offset is |
23194 |
-+ * relative to the start address of the message header. |
23195 |
-+ * This example program only expects one single item of that |
23196 |
-+ * type, remembers the struct kdbus_vec member of the item |
23197 |
-+ * when it sees it, and bails out if there is more than one |
23198 |
-+ * of them. |
23199 |
-+ */ |
23200 |
-+ if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { |
23201 |
-+ if (vec) { |
23202 |
-+ r = err_r(-EEXIST, |
23203 |
-+ "message with multiple vecs"); |
23204 |
-+ break; |
23205 |
-+ } |
23206 |
-+ vec = &item->vec; |
23207 |
-+ if (vec->size != 2 * sizeof(size_t)) { |
23208 |
-+ r = err_r(-EINVAL, "invalid message size"); |
23209 |
-+ break; |
23210 |
-+ } |
23211 |
-+ /* |
23212 |
-+ * MEMFDs are transported as items of type PAYLOAD_MEMFD. |
23213 |
-+ * If such an item is attached, a new file descriptor was |
23214 |
-+ * installed into the task when KDBUS_CMD_RECV was called, and |
23215 |
-+ * its number is stored in item->memfd.fd. |
23216 |
-+ * Implementers *must* handle this item type close the |
23217 |
-+ * file descriptor when no longer needed in order to prevent |
23218 |
-+ * file descriptor exhaustion. This example program just bails |
23219 |
-+ * out with an error in this case, as memfds are not expected |
23220 |
-+ * in this context. |
23221 |
-+ */ |
23222 |
-+ } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) { |
23223 |
-+ r = err_r(-EINVAL, "message with memfd"); |
23224 |
-+ break; |
23225 |
-+ } |
23226 |
-+ } |
23227 |
-+ if (r < 0) |
23228 |
-+ goto exit; |
23229 |
-+ if (!vec) { |
23230 |
-+ r = err_r(-EINVAL, "empty message"); |
23231 |
-+ goto exit; |
23232 |
-+ } |
23233 |
-+ |
23234 |
-+ n = ((size_t *)((const uint8_t *)msg + vec->offset))[0]; |
23235 |
-+ steps = ((size_t *)((const uint8_t *)msg + vec->offset))[1]; |
23236 |
-+ |
23237 |
-+ while (steps-- > 0) { |
23238 |
-+ ++n; |
23239 |
-+ r = prime_run(c->prime, c->bus, n); |
23240 |
-+ if (r < 0) |
23241 |
-+ break; |
23242 |
-+ r = bus_poll(c->bus); |
23243 |
-+ if (r != 0) { |
23244 |
-+ r = r < 0 ? r : -EINTR; |
23245 |
-+ break; |
23246 |
-+ } |
23247 |
-+ } |
23248 |
-+ |
23249 |
-+exit: |
23250 |
-+ /* |
23251 |
-+ * We are done with the memory slice that was given to us through |
23252 |
-+ * cmd.reply.offset. Tell the kernel it can use it for other content |
23253 |
-+ * in the future. See kdbus.pool(7). |
23254 |
-+ */ |
23255 |
-+ bus_poool_free_slice(c->bus, cmd.reply.offset); |
23256 |
-+ return r; |
23257 |
-+} |
23258 |
-+ |
23259 |
-+/* |
23260 |
-+ * Prime Computation |
23261 |
-+ * |
23262 |
-+ */ |
23263 |
-+ |
23264 |
-+static int prime_new(struct prime **out) |
23265 |
-+{ |
23266 |
-+ struct prime *p; |
23267 |
-+ int r; |
23268 |
-+ |
23269 |
-+ p = calloc(1, sizeof(*p)); |
23270 |
-+ if (!p) |
23271 |
-+ return err("cannot allocate prime memory"); |
23272 |
-+ |
23273 |
-+ p->fd = -1; |
23274 |
-+ p->area = MAP_FAILED; |
23275 |
-+ p->max = MAX_PRIMES; |
23276 |
-+ |
23277 |
-+ /* |
23278 |
-+ * Prepare and map a memfd to store the bit-fields for the number |
23279 |
-+ * ranges we want to perform the prime detection on. |
23280 |
-+ */ |
23281 |
-+ p->fd = syscall(__NR_memfd_create, "prime-area", MFD_CLOEXEC); |
23282 |
-+ if (p->fd < 0) { |
23283 |
-+ r = err("cannot create memfd"); |
23284 |
-+ goto error; |
23285 |
-+ } |
23286 |
-+ |
23287 |
-+ r = ftruncate(p->fd, p->max / 8 + 1); |
23288 |
-+ if (r < 0) { |
23289 |
-+ r = err("cannot ftruncate area"); |
23290 |
-+ goto error; |
23291 |
-+ } |
23292 |
-+ |
23293 |
-+ p->area = mmap(NULL, p->max / 8 + 1, PROT_READ | PROT_WRITE, |
23294 |
-+ MAP_SHARED, p->fd, 0); |
23295 |
-+ if (p->area == MAP_FAILED) { |
23296 |
-+ r = err("cannot mmap memfd"); |
23297 |
-+ goto error; |
23298 |
-+ } |
23299 |
-+ |
23300 |
-+ *out = p; |
23301 |
-+ return 0; |
23302 |
-+ |
23303 |
-+error: |
23304 |
-+ prime_free(p); |
23305 |
-+ return r; |
23306 |
-+} |
23307 |
-+ |
23308 |
-+static void prime_free(struct prime *p) |
23309 |
-+{ |
23310 |
-+ if (!p) |
23311 |
-+ return; |
23312 |
-+ |
23313 |
-+ if (p->area != MAP_FAILED) |
23314 |
-+ munmap(p->area, p->max / 8 + 1); |
23315 |
-+ if (p->fd >= 0) |
23316 |
-+ close(p->fd); |
23317 |
-+ free(p); |
23318 |
-+} |
23319 |
-+ |
23320 |
-+static bool prime_done(struct prime *p) |
23321 |
-+{ |
23322 |
-+ return p->done >= p->max; |
23323 |
-+} |
23324 |
-+ |
23325 |
-+static void prime_consume(struct prime *p, size_t amount) |
23326 |
-+{ |
23327 |
-+ p->done += amount; |
23328 |
-+} |
23329 |
-+ |
23330 |
-+static int prime_run(struct prime *p, struct bus *cancel, size_t number) |
23331 |
-+{ |
23332 |
-+ size_t i, n = 0; |
23333 |
-+ int r; |
23334 |
-+ |
23335 |
-+ if (number < 2 || number > 65535) |
23336 |
-+ return 0; |
23337 |
-+ |
23338 |
-+ for (i = number * number; |
23339 |
-+ i < p->max && i > number; |
23340 |
-+ i += number) { |
23341 |
-+ p->area[i / 8] |= 1 << (i % 8); |
23342 |
-+ |
23343 |
-+ if (!(++n % (1 << 20))) { |
23344 |
-+ r = bus_poll(cancel); |
23345 |
-+ if (r != 0) |
23346 |
-+ return r < 0 ? r : -EINTR; |
23347 |
-+ } |
23348 |
-+ } |
23349 |
-+ |
23350 |
-+ return 0; |
23351 |
-+} |
23352 |
-+ |
23353 |
-+static void prime_print(struct prime *p) |
23354 |
-+{ |
23355 |
-+ size_t i, l = 0; |
23356 |
-+ |
23357 |
-+ fprintf(stderr, "PRIMES:"); |
23358 |
-+ for (i = 0; i < p->max; ++i) { |
23359 |
-+ if (!(p->area[i / 8] & (1 << (i % 8)))) |
23360 |
-+ fprintf(stderr, "%c%7zu", !(l++ % 16) ? '\n' : ' ', i); |
23361 |
-+ } |
23362 |
-+ fprintf(stderr, "\nEND\n"); |
23363 |
-+} |
23364 |
-+ |
23365 |
-+static int bus_open_connection(struct bus **out, uid_t uid, const char *name, |
23366 |
-+ uint64_t recv_flags) |
23367 |
-+{ |
23368 |
-+ struct kdbus_cmd_hello hello; |
23369 |
-+ char path[128]; |
23370 |
-+ struct bus *b; |
23371 |
-+ int r; |
23372 |
-+ |
23373 |
-+ /* |
23374 |
-+ * The 'bus' object is our representation of a kdbus connection which |
23375 |
-+ * stores two details: the connection owner file descriptor, and the |
23376 |
-+ * mmap()ed memory of its associated pool. See kdbus.connection(7) and |
23377 |
-+ * kdbus.pool(7). |
23378 |
-+ */ |
23379 |
-+ b = calloc(1, sizeof(*b)); |
23380 |
-+ if (!b) |
23381 |
-+ return err("cannot allocate bus memory"); |
23382 |
-+ |
23383 |
-+ b->fd = -1; |
23384 |
-+ b->pool = MAP_FAILED; |
23385 |
-+ |
23386 |
-+ /* Compute the name of the bus node to connect to. */ |
23387 |
-+ snprintf(path, sizeof(path), "/sys/fs/%s/%lu-%s/bus", |
23388 |
-+ arg_modname, (unsigned long)uid, name); |
23389 |
-+ b->fd = open(path, O_RDWR | O_CLOEXEC); |
23390 |
-+ if (b->fd < 0) { |
23391 |
-+ r = err("cannot open bus"); |
23392 |
-+ goto error; |
23393 |
-+ } |
23394 |
-+ |
23395 |
-+ /* |
23396 |
-+ * To make a connection to the bus, the KDBUS_CMD_HELLO ioctl is used. |
23397 |
-+ * It takes an argument of type 'struct kdbus_cmd_hello'. |
23398 |
-+ */ |
23399 |
-+ memset(&hello, 0, sizeof(hello)); |
23400 |
-+ hello.size = sizeof(hello); |
23401 |
-+ |
23402 |
-+ /* |
23403 |
-+ * Specify a mask of metadata attach flags, describing metadata items |
23404 |
-+ * that this new connection allows to be sent. |
23405 |
-+ */ |
23406 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
23407 |
-+ |
23408 |
-+ /* |
23409 |
-+ * Specify a mask of metadata attach flags, describing metadata items |
23410 |
-+ * that this new connection wants to be receive along with each message. |
23411 |
-+ */ |
23412 |
-+ hello.attach_flags_recv = recv_flags; |
23413 |
-+ |
23414 |
-+ /* |
23415 |
-+ * A connection may choose the size of its pool, but the number has to |
23416 |
-+ * comply with two rules: a) it must be greater than 0, and b) it must |
23417 |
-+ * be a mulitple of PAGE_SIZE. See kdbus.pool(7). |
23418 |
-+ */ |
23419 |
-+ hello.pool_size = POOL_SIZE; |
23420 |
-+ |
23421 |
-+ /* |
23422 |
-+ * Now employ the command on the file descriptor opened above. |
23423 |
-+ * This command will turn the file descriptor into a connection-owner |
23424 |
-+ * file descriptor that controls the life-time of the connection; once |
23425 |
-+ * it's closed, the connection is shut down. |
23426 |
-+ */ |
23427 |
-+ r = kdbus_cmd_hello(b->fd, &hello); |
23428 |
-+ if (r < 0) { |
23429 |
-+ err_r(r, "HELLO failed"); |
23430 |
-+ goto error; |
23431 |
-+ } |
23432 |
-+ |
23433 |
-+ bus_poool_free_slice(b, hello.offset); |
23434 |
-+ |
23435 |
-+ /* |
23436 |
-+ * Map the pool of the connection. Its size has been set in the |
23437 |
-+ * command struct above. See kdbus.pool(7). |
23438 |
-+ */ |
23439 |
-+ b->pool = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, b->fd, 0); |
23440 |
-+ if (b->pool == MAP_FAILED) { |
23441 |
-+ r = err("cannot mmap pool"); |
23442 |
-+ goto error; |
23443 |
-+ } |
23444 |
-+ |
23445 |
-+ *out = b; |
23446 |
-+ return 0; |
23447 |
-+ |
23448 |
-+error: |
23449 |
-+ bus_close_connection(b); |
23450 |
-+ return r; |
23451 |
-+} |
23452 |
-+ |
23453 |
-+static void bus_close_connection(struct bus *b) |
23454 |
-+{ |
23455 |
-+ if (!b) |
23456 |
-+ return; |
23457 |
-+ |
23458 |
-+ /* |
23459 |
-+ * A bus connection is closed by simply calling close() on the |
23460 |
-+ * connection owner file descriptor. The unique name and all owned |
23461 |
-+ * well-known names of the conneciton will disappear. |
23462 |
-+ * See kdbus.connection(7). |
23463 |
-+ */ |
23464 |
-+ if (b->pool != MAP_FAILED) |
23465 |
-+ munmap(b->pool, POOL_SIZE); |
23466 |
-+ if (b->fd >= 0) |
23467 |
-+ close(b->fd); |
23468 |
-+ free(b); |
23469 |
-+} |
23470 |
-+ |
23471 |
-+static void bus_poool_free_slice(struct bus *b, uint64_t offset) |
23472 |
-+{ |
23473 |
-+ struct kdbus_cmd_free cmd = { |
23474 |
-+ .size = sizeof(cmd), |
23475 |
-+ .offset = offset, |
23476 |
-+ }; |
23477 |
-+ int r; |
23478 |
-+ |
23479 |
-+ /* |
23480 |
-+ * Once we're done with a piece of pool memory that was returned |
23481 |
-+ * by a command, we have to call the KDBUS_CMD_FREE ioctl on it so it |
23482 |
-+ * can be reused. The command takes an argument of type |
23483 |
-+ * 'struct kdbus_cmd_free', in which the pool offset of the slice to |
23484 |
-+ * free is stored. The ioctl is employed on the connection owner |
23485 |
-+ * file descriptor. See kdbus.pool(7), |
23486 |
-+ */ |
23487 |
-+ r = kdbus_cmd_free(b->fd, &cmd); |
23488 |
-+ if (r < 0) |
23489 |
-+ err_r(r, "cannot free pool slice"); |
23490 |
-+} |
23491 |
-+ |
23492 |
-+static int bus_acquire_name(struct bus *b, const char *name) |
23493 |
-+{ |
23494 |
-+ struct kdbus_item *item; |
23495 |
-+ struct kdbus_cmd *cmd; |
23496 |
-+ size_t size; |
23497 |
-+ int r; |
23498 |
-+ |
23499 |
-+ /* |
23500 |
-+ * This function acquires a well-known name on the bus through the |
23501 |
-+ * KDBUS_CMD_NAME_ACQUIRE ioctl. This ioctl takes an argument of type |
23502 |
-+ * 'struct kdbus_cmd', which is assembled below. See kdbus.name(7). |
23503 |
-+ */ |
23504 |
-+ size = sizeof(*cmd); |
23505 |
-+ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
23506 |
-+ |
23507 |
-+ cmd = alloca(size); |
23508 |
-+ memset(cmd, 0, size); |
23509 |
-+ cmd->size = size; |
23510 |
-+ |
23511 |
-+ /* |
23512 |
-+ * The command requires an item of type KDBUS_ITEM_NAME, and its |
23513 |
-+ * content must be a valid bus name. |
23514 |
-+ */ |
23515 |
-+ item = cmd->items; |
23516 |
-+ item->type = KDBUS_ITEM_NAME; |
23517 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
23518 |
-+ strcpy(item->str, name); |
23519 |
-+ |
23520 |
-+ /* |
23521 |
-+ * Employ the command on the connection owner file descriptor. |
23522 |
-+ */ |
23523 |
-+ r = kdbus_cmd_name_acquire(b->fd, cmd); |
23524 |
-+ if (r < 0) |
23525 |
-+ return err_r(r, "cannot acquire name"); |
23526 |
-+ |
23527 |
-+ return 0; |
23528 |
-+} |
23529 |
-+ |
23530 |
-+static int bus_install_name_loss_match(struct bus *b, const char *name) |
23531 |
-+{ |
23532 |
-+ struct kdbus_cmd_match *match; |
23533 |
-+ struct kdbus_item *item; |
23534 |
-+ size_t size; |
23535 |
-+ int r; |
23536 |
-+ |
23537 |
-+ /* |
23538 |
-+ * In order to install a match for signal messages, we have to |
23539 |
-+ * assemble a 'struct kdbus_cmd_match' and use it along with the |
23540 |
-+ * KDBUS_CMD_MATCH_ADD ioctl. See kdbus.match(7). |
23541 |
-+ */ |
23542 |
-+ size = sizeof(*match); |
23543 |
-+ size += KDBUS_ITEM_SIZE(sizeof(item->name_change) + strlen(name) + 1); |
23544 |
-+ |
23545 |
-+ match = alloca(size); |
23546 |
-+ memset(match, 0, size); |
23547 |
-+ match->size = size; |
23548 |
-+ |
23549 |
-+ /* |
23550 |
-+ * A match is comprised of many 'rules', each of which describes a |
23551 |
-+ * mandatory detail of the message. All rules of a match must be |
23552 |
-+ * satified in order to make a message pass. |
23553 |
-+ */ |
23554 |
-+ item = match->items; |
23555 |
-+ |
23556 |
-+ /* |
23557 |
-+ * In this case, we're interested in notifications that inform us |
23558 |
-+ * about a well-known name being removed from the bus. |
23559 |
-+ */ |
23560 |
-+ item->type = KDBUS_ITEM_NAME_REMOVE; |
23561 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
23562 |
-+ sizeof(item->name_change) + strlen(name) + 1; |
23563 |
-+ |
23564 |
-+ /* |
23565 |
-+ * We could limit the match further and require a specific unique-ID |
23566 |
-+ * to be the new or the old owner of the name. In this case, however, |
23567 |
-+ * we don't, and allow 'any' id. |
23568 |
-+ */ |
23569 |
-+ item->name_change.old_id.id = KDBUS_MATCH_ID_ANY; |
23570 |
-+ item->name_change.new_id.id = KDBUS_MATCH_ID_ANY; |
23571 |
-+ |
23572 |
-+ /* Copy in the well-known name we're interested in */ |
23573 |
-+ strcpy(item->name_change.name, name); |
23574 |
-+ |
23575 |
-+ /* |
23576 |
-+ * Add the match through the KDBUS_CMD_MATCH_ADD ioctl, employed on |
23577 |
-+ * the connection owner fd. |
23578 |
-+ */ |
23579 |
-+ r = kdbus_cmd_match_add(b->fd, match); |
23580 |
-+ if (r < 0) |
23581 |
-+ return err_r(r, "cannot add match"); |
23582 |
-+ |
23583 |
-+ return 0; |
23584 |
-+} |
23585 |
-+ |
23586 |
-+static int bus_poll(struct bus *b) |
23587 |
-+{ |
23588 |
-+ struct pollfd fds[1] = {}; |
23589 |
-+ int r; |
23590 |
-+ |
23591 |
-+ /* |
23592 |
-+ * A connection endpoint supports poll() and will wake-up the |
23593 |
-+ * task with POLLIN set once a message has arrived. |
23594 |
-+ */ |
23595 |
-+ fds[0].fd = b->fd; |
23596 |
-+ fds[0].events = POLLIN; |
23597 |
-+ r = poll(fds, sizeof(fds) / sizeof(*fds), 0); |
23598 |
-+ if (r < 0) |
23599 |
-+ return err("cannot poll bus"); |
23600 |
-+ return !!(fds[0].revents & POLLIN); |
23601 |
-+} |
23602 |
-+ |
23603 |
-+static int bus_make(uid_t uid, const char *name) |
23604 |
-+{ |
23605 |
-+ struct kdbus_item *item; |
23606 |
-+ struct kdbus_cmd *make; |
23607 |
-+ char path[128], busname[128]; |
23608 |
-+ size_t size; |
23609 |
-+ int r, fd; |
23610 |
-+ |
23611 |
-+ /* |
23612 |
-+ * Compute the full path to the 'control' node. 'arg_modname' may be |
23613 |
-+ * set to a different value than 'kdbus' for development purposes. |
23614 |
-+ * The 'control' node is the primary entry point to kdbus that must be |
23615 |
-+ * used in order to create a bus. See kdbus(7) and kdbus.bus(7). |
23616 |
-+ */ |
23617 |
-+ snprintf(path, sizeof(path), "/sys/fs/%s/control", arg_modname); |
23618 |
-+ |
23619 |
-+ /* |
23620 |
-+ * Compute the bus name. A valid bus name must always be prefixed with |
23621 |
-+ * the EUID of the currently running process in order to avoid name |
23622 |
-+ * conflicts. See kdbus.bus(7). |
23623 |
-+ */ |
23624 |
-+ snprintf(busname, sizeof(busname), "%lu-%s", (unsigned long)uid, name); |
23625 |
-+ |
23626 |
-+ fd = open(path, O_RDWR | O_CLOEXEC); |
23627 |
-+ if (fd < 0) |
23628 |
-+ return err("cannot open control file"); |
23629 |
-+ |
23630 |
-+ /* |
23631 |
-+ * The KDBUS_CMD_BUS_MAKE ioctl takes an argument of type |
23632 |
-+ * 'struct kdbus_cmd', and expects at least two items attached to |
23633 |
-+ * it: one to decribe the bloom parameters to be propagated to |
23634 |
-+ * connections of the bus, and the name of the bus that was computed |
23635 |
-+ * above. Assemble this struct now, and fill it with values. |
23636 |
-+ */ |
23637 |
-+ size = sizeof(*make); |
23638 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_parameter)); |
23639 |
-+ size += KDBUS_ITEM_SIZE(strlen(busname) + 1); |
23640 |
-+ |
23641 |
-+ make = alloca(size); |
23642 |
-+ memset(make, 0, size); |
23643 |
-+ make->size = size; |
23644 |
-+ |
23645 |
-+ /* |
23646 |
-+ * Each item has a 'type' and 'size' field, and must be stored at an |
23647 |
-+ * 8-byte aligned address. The KDBUS_ITEM_NEXT macro is used to advance |
23648 |
-+ * the pointer. See kdbus.item(7) for more details. |
23649 |
-+ */ |
23650 |
-+ item = make->items; |
23651 |
-+ item->type = KDBUS_ITEM_BLOOM_PARAMETER; |
23652 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->bloom_parameter); |
23653 |
-+ item->bloom_parameter.size = 8; |
23654 |
-+ item->bloom_parameter.n_hash = 1; |
23655 |
-+ |
23656 |
-+ /* The name of the new bus is stored in the next item. */ |
23657 |
-+ item = KDBUS_ITEM_NEXT(item); |
23658 |
-+ item->type = KDBUS_ITEM_MAKE_NAME; |
23659 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(busname) + 1; |
23660 |
-+ strcpy(item->str, busname); |
23661 |
-+ |
23662 |
-+ /* |
23663 |
-+ * Now create the bus via the KDBUS_CMD_BUS_MAKE ioctl and return the |
23664 |
-+ * fd that was used back to the caller of this function. This fd is now |
23665 |
-+ * called a 'bus owner file descriptor', and it controls the life-time |
23666 |
-+ * of the newly created bus; once the file descriptor is closed, the |
23667 |
-+ * bus goes away, and all connections are shut down. See kdbus.bus(7). |
23668 |
-+ */ |
23669 |
-+ r = kdbus_cmd_bus_make(fd, make); |
23670 |
-+ if (r < 0) { |
23671 |
-+ err_r(r, "cannot make bus"); |
23672 |
-+ close(fd); |
23673 |
-+ return r; |
23674 |
-+ } |
23675 |
-+ |
23676 |
-+ return fd; |
23677 |
-+} |
23678 |
-+ |
23679 |
-+#else |
23680 |
-+ |
23681 |
-+#warning "Skipping compilation due to unsupported libc version" |
23682 |
-+ |
23683 |
-+int main(int argc, char **argv) |
23684 |
-+{ |
23685 |
-+ fprintf(stderr, |
23686 |
-+ "Compilation of %s was skipped due to unsupported libc.\n", |
23687 |
-+ argv[0]); |
23688 |
-+ |
23689 |
-+ return EXIT_FAILURE; |
23690 |
-+} |
23691 |
-+ |
23692 |
-+#endif /* libc sanity check */ |
23693 |
-diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile |
23694 |
-index 95abddc..b57100c 100644 |
23695 |
---- a/tools/testing/selftests/Makefile |
23696 |
-+++ b/tools/testing/selftests/Makefile |
23697 |
-@@ -5,6 +5,7 @@ TARGETS += exec |
23698 |
- TARGETS += firmware |
23699 |
- TARGETS += ftrace |
23700 |
- TARGETS += kcmp |
23701 |
-+TARGETS += kdbus |
23702 |
- TARGETS += memfd |
23703 |
- TARGETS += memory-hotplug |
23704 |
- TARGETS += mount |
23705 |
-diff --git a/tools/testing/selftests/kdbus/.gitignore b/tools/testing/selftests/kdbus/.gitignore |
23706 |
-new file mode 100644 |
23707 |
-index 0000000..d3ef42f |
23708 |
---- /dev/null |
23709 |
-+++ b/tools/testing/selftests/kdbus/.gitignore |
23710 |
-@@ -0,0 +1 @@ |
23711 |
-+kdbus-test |
23712 |
-diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile |
23713 |
-new file mode 100644 |
23714 |
-index 0000000..8f36cb5 |
23715 |
---- /dev/null |
23716 |
-+++ b/tools/testing/selftests/kdbus/Makefile |
23717 |
-@@ -0,0 +1,49 @@ |
23718 |
-+CFLAGS += -I../../../../usr/include/ |
23719 |
-+CFLAGS += -I../../../../samples/kdbus/ |
23720 |
-+CFLAGS += -I../../../../include/uapi/ |
23721 |
-+CFLAGS += -std=gnu99 |
23722 |
-+CFLAGS += -DKBUILD_MODNAME=\"kdbus\" -D_GNU_SOURCE |
23723 |
-+LDLIBS = -pthread -lcap -lm |
23724 |
-+ |
23725 |
-+OBJS= \ |
23726 |
-+ kdbus-enum.o \ |
23727 |
-+ kdbus-util.o \ |
23728 |
-+ kdbus-test.o \ |
23729 |
-+ kdbus-test.o \ |
23730 |
-+ test-activator.o \ |
23731 |
-+ test-benchmark.o \ |
23732 |
-+ test-bus.o \ |
23733 |
-+ test-chat.o \ |
23734 |
-+ test-connection.o \ |
23735 |
-+ test-daemon.o \ |
23736 |
-+ test-endpoint.o \ |
23737 |
-+ test-fd.o \ |
23738 |
-+ test-free.o \ |
23739 |
-+ test-match.o \ |
23740 |
-+ test-message.o \ |
23741 |
-+ test-metadata-ns.o \ |
23742 |
-+ test-monitor.o \ |
23743 |
-+ test-names.o \ |
23744 |
-+ test-policy.o \ |
23745 |
-+ test-policy-ns.o \ |
23746 |
-+ test-policy-priv.o \ |
23747 |
-+ test-sync.o \ |
23748 |
-+ test-timeout.o |
23749 |
-+ |
23750 |
-+all: kdbus-test |
23751 |
-+ |
23752 |
-+include ../lib.mk |
23753 |
-+ |
23754 |
-+%.o: %.c kdbus-enum.h kdbus-test.h kdbus-util.h |
23755 |
-+ $(CC) $(CFLAGS) -c $< -o $@ |
23756 |
-+ |
23757 |
-+kdbus-test: $(OBJS) |
23758 |
-+ $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@ |
23759 |
-+ |
23760 |
-+TEST_PROGS := kdbus-test |
23761 |
-+ |
23762 |
-+run_tests: |
23763 |
-+ ./kdbus-test --tap |
23764 |
-+ |
23765 |
-+clean: |
23766 |
-+ rm -f *.o kdbus-test |
23767 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-enum.c b/tools/testing/selftests/kdbus/kdbus-enum.c |
23768 |
-new file mode 100644 |
23769 |
-index 0000000..4f1e579 |
23770 |
---- /dev/null |
23771 |
-+++ b/tools/testing/selftests/kdbus/kdbus-enum.c |
23772 |
-@@ -0,0 +1,94 @@ |
23773 |
-+/* |
23774 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
23775 |
-+ * |
23776 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
23777 |
-+ * the terms of the GNU Lesser General Public License as published by the |
23778 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
23779 |
-+ * your option) any later version. |
23780 |
-+ */ |
23781 |
-+ |
23782 |
-+#include <stdio.h> |
23783 |
-+#include <string.h> |
23784 |
-+#include <fcntl.h> |
23785 |
-+#include <stdlib.h> |
23786 |
-+#include <stddef.h> |
23787 |
-+#include <unistd.h> |
23788 |
-+#include <stdint.h> |
23789 |
-+#include <errno.h> |
23790 |
-+ |
23791 |
-+#include "kdbus-util.h" |
23792 |
-+#include "kdbus-enum.h" |
23793 |
-+ |
23794 |
-+struct kdbus_enum_table { |
23795 |
-+ long long id; |
23796 |
-+ const char *name; |
23797 |
-+}; |
23798 |
-+ |
23799 |
-+#define TABLE(what) static struct kdbus_enum_table kdbus_table_##what[] |
23800 |
-+#define ENUM(_id) { .id = _id, .name = STRINGIFY(_id) } |
23801 |
-+#define LOOKUP(what) \ |
23802 |
-+ const char *enum_##what(long long id) \ |
23803 |
-+ { \ |
23804 |
-+ for (size_t i = 0; i < ELEMENTSOF(kdbus_table_##what); i++) \ |
23805 |
-+ if (id == kdbus_table_##what[i].id) \ |
23806 |
-+ return kdbus_table_##what[i].name; \ |
23807 |
-+ return "UNKNOWN"; \ |
23808 |
-+ } |
23809 |
-+ |
23810 |
-+TABLE(CMD) = { |
23811 |
-+ ENUM(KDBUS_CMD_BUS_MAKE), |
23812 |
-+ ENUM(KDBUS_CMD_ENDPOINT_MAKE), |
23813 |
-+ ENUM(KDBUS_CMD_HELLO), |
23814 |
-+ ENUM(KDBUS_CMD_SEND), |
23815 |
-+ ENUM(KDBUS_CMD_RECV), |
23816 |
-+ ENUM(KDBUS_CMD_LIST), |
23817 |
-+ ENUM(KDBUS_CMD_NAME_RELEASE), |
23818 |
-+ ENUM(KDBUS_CMD_CONN_INFO), |
23819 |
-+ ENUM(KDBUS_CMD_MATCH_ADD), |
23820 |
-+ ENUM(KDBUS_CMD_MATCH_REMOVE), |
23821 |
-+}; |
23822 |
-+LOOKUP(CMD); |
23823 |
-+ |
23824 |
-+TABLE(MSG) = { |
23825 |
-+ ENUM(_KDBUS_ITEM_NULL), |
23826 |
-+ ENUM(KDBUS_ITEM_PAYLOAD_VEC), |
23827 |
-+ ENUM(KDBUS_ITEM_PAYLOAD_OFF), |
23828 |
-+ ENUM(KDBUS_ITEM_PAYLOAD_MEMFD), |
23829 |
-+ ENUM(KDBUS_ITEM_FDS), |
23830 |
-+ ENUM(KDBUS_ITEM_BLOOM_PARAMETER), |
23831 |
-+ ENUM(KDBUS_ITEM_BLOOM_FILTER), |
23832 |
-+ ENUM(KDBUS_ITEM_DST_NAME), |
23833 |
-+ ENUM(KDBUS_ITEM_MAKE_NAME), |
23834 |
-+ ENUM(KDBUS_ITEM_ATTACH_FLAGS_SEND), |
23835 |
-+ ENUM(KDBUS_ITEM_ATTACH_FLAGS_RECV), |
23836 |
-+ ENUM(KDBUS_ITEM_ID), |
23837 |
-+ ENUM(KDBUS_ITEM_NAME), |
23838 |
-+ ENUM(KDBUS_ITEM_TIMESTAMP), |
23839 |
-+ ENUM(KDBUS_ITEM_CREDS), |
23840 |
-+ ENUM(KDBUS_ITEM_PIDS), |
23841 |
-+ ENUM(KDBUS_ITEM_AUXGROUPS), |
23842 |
-+ ENUM(KDBUS_ITEM_OWNED_NAME), |
23843 |
-+ ENUM(KDBUS_ITEM_TID_COMM), |
23844 |
-+ ENUM(KDBUS_ITEM_PID_COMM), |
23845 |
-+ ENUM(KDBUS_ITEM_EXE), |
23846 |
-+ ENUM(KDBUS_ITEM_CMDLINE), |
23847 |
-+ ENUM(KDBUS_ITEM_CGROUP), |
23848 |
-+ ENUM(KDBUS_ITEM_CAPS), |
23849 |
-+ ENUM(KDBUS_ITEM_SECLABEL), |
23850 |
-+ ENUM(KDBUS_ITEM_AUDIT), |
23851 |
-+ ENUM(KDBUS_ITEM_CONN_DESCRIPTION), |
23852 |
-+ ENUM(KDBUS_ITEM_NAME_ADD), |
23853 |
-+ ENUM(KDBUS_ITEM_NAME_REMOVE), |
23854 |
-+ ENUM(KDBUS_ITEM_NAME_CHANGE), |
23855 |
-+ ENUM(KDBUS_ITEM_ID_ADD), |
23856 |
-+ ENUM(KDBUS_ITEM_ID_REMOVE), |
23857 |
-+ ENUM(KDBUS_ITEM_REPLY_TIMEOUT), |
23858 |
-+ ENUM(KDBUS_ITEM_REPLY_DEAD), |
23859 |
-+}; |
23860 |
-+LOOKUP(MSG); |
23861 |
-+ |
23862 |
-+TABLE(PAYLOAD) = { |
23863 |
-+ ENUM(KDBUS_PAYLOAD_KERNEL), |
23864 |
-+ ENUM(KDBUS_PAYLOAD_DBUS), |
23865 |
-+}; |
23866 |
-+LOOKUP(PAYLOAD); |
23867 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-enum.h b/tools/testing/selftests/kdbus/kdbus-enum.h |
23868 |
-new file mode 100644 |
23869 |
-index 0000000..ed28cca |
23870 |
---- /dev/null |
23871 |
-+++ b/tools/testing/selftests/kdbus/kdbus-enum.h |
23872 |
-@@ -0,0 +1,15 @@ |
23873 |
-+/* |
23874 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
23875 |
-+ * |
23876 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
23877 |
-+ * the terms of the GNU Lesser General Public License as published by the |
23878 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
23879 |
-+ * your option) any later version. |
23880 |
-+ */ |
23881 |
-+ |
23882 |
-+#pragma once |
23883 |
-+ |
23884 |
-+const char *enum_CMD(long long id); |
23885 |
-+const char *enum_MSG(long long id); |
23886 |
-+const char *enum_MATCH(long long id); |
23887 |
-+const char *enum_PAYLOAD(long long id); |
23888 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-test.c b/tools/testing/selftests/kdbus/kdbus-test.c |
23889 |
-new file mode 100644 |
23890 |
-index 0000000..db57381 |
23891 |
---- /dev/null |
23892 |
-+++ b/tools/testing/selftests/kdbus/kdbus-test.c |
23893 |
-@@ -0,0 +1,905 @@ |
23894 |
-+#include <errno.h> |
23895 |
-+#include <stdio.h> |
23896 |
-+#include <string.h> |
23897 |
-+#include <fcntl.h> |
23898 |
-+#include <stdlib.h> |
23899 |
-+#include <stddef.h> |
23900 |
-+#include <time.h> |
23901 |
-+#include <unistd.h> |
23902 |
-+#include <stdint.h> |
23903 |
-+#include <assert.h> |
23904 |
-+#include <getopt.h> |
23905 |
-+#include <stdbool.h> |
23906 |
-+#include <signal.h> |
23907 |
-+#include <sys/mount.h> |
23908 |
-+#include <sys/prctl.h> |
23909 |
-+#include <sys/wait.h> |
23910 |
-+#include <sys/syscall.h> |
23911 |
-+#include <sys/eventfd.h> |
23912 |
-+#include <linux/sched.h> |
23913 |
-+ |
23914 |
-+#include "kdbus-util.h" |
23915 |
-+#include "kdbus-enum.h" |
23916 |
-+#include "kdbus-test.h" |
23917 |
-+ |
23918 |
-+enum { |
23919 |
-+ TEST_CREATE_BUS = 1 << 0, |
23920 |
-+ TEST_CREATE_CONN = 1 << 1, |
23921 |
-+}; |
23922 |
-+ |
23923 |
-+struct kdbus_test { |
23924 |
-+ const char *name; |
23925 |
-+ const char *desc; |
23926 |
-+ int (*func)(struct kdbus_test_env *env); |
23927 |
-+ unsigned int flags; |
23928 |
-+}; |
23929 |
-+ |
23930 |
-+struct kdbus_test_args { |
23931 |
-+ bool mntns; |
23932 |
-+ bool pidns; |
23933 |
-+ bool userns; |
23934 |
-+ char *uid_map; |
23935 |
-+ char *gid_map; |
23936 |
-+ int loop; |
23937 |
-+ int wait; |
23938 |
-+ int fork; |
23939 |
-+ int tap_output; |
23940 |
-+ char *module; |
23941 |
-+ char *root; |
23942 |
-+ char *test; |
23943 |
-+ char *busname; |
23944 |
-+}; |
23945 |
-+ |
23946 |
-+static const struct kdbus_test tests[] = { |
23947 |
-+ { |
23948 |
-+ .name = "bus-make", |
23949 |
-+ .desc = "bus make functions", |
23950 |
-+ .func = kdbus_test_bus_make, |
23951 |
-+ .flags = 0, |
23952 |
-+ }, |
23953 |
-+ { |
23954 |
-+ .name = "hello", |
23955 |
-+ .desc = "the HELLO command", |
23956 |
-+ .func = kdbus_test_hello, |
23957 |
-+ .flags = TEST_CREATE_BUS, |
23958 |
-+ }, |
23959 |
-+ { |
23960 |
-+ .name = "byebye", |
23961 |
-+ .desc = "the BYEBYE command", |
23962 |
-+ .func = kdbus_test_byebye, |
23963 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23964 |
-+ }, |
23965 |
-+ { |
23966 |
-+ .name = "chat", |
23967 |
-+ .desc = "a chat pattern", |
23968 |
-+ .func = kdbus_test_chat, |
23969 |
-+ .flags = TEST_CREATE_BUS, |
23970 |
-+ }, |
23971 |
-+ { |
23972 |
-+ .name = "daemon", |
23973 |
-+ .desc = "a simple daemon", |
23974 |
-+ .func = kdbus_test_daemon, |
23975 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23976 |
-+ }, |
23977 |
-+ { |
23978 |
-+ .name = "fd-passing", |
23979 |
-+ .desc = "file descriptor passing", |
23980 |
-+ .func = kdbus_test_fd_passing, |
23981 |
-+ .flags = TEST_CREATE_BUS, |
23982 |
-+ }, |
23983 |
-+ { |
23984 |
-+ .name = "endpoint", |
23985 |
-+ .desc = "custom endpoint", |
23986 |
-+ .func = kdbus_test_custom_endpoint, |
23987 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23988 |
-+ }, |
23989 |
-+ { |
23990 |
-+ .name = "monitor", |
23991 |
-+ .desc = "monitor functionality", |
23992 |
-+ .func = kdbus_test_monitor, |
23993 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23994 |
-+ }, |
23995 |
-+ { |
23996 |
-+ .name = "name-basics", |
23997 |
-+ .desc = "basic name registry functions", |
23998 |
-+ .func = kdbus_test_name_basic, |
23999 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24000 |
-+ }, |
24001 |
-+ { |
24002 |
-+ .name = "name-conflict", |
24003 |
-+ .desc = "name registry conflict details", |
24004 |
-+ .func = kdbus_test_name_conflict, |
24005 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24006 |
-+ }, |
24007 |
-+ { |
24008 |
-+ .name = "name-queue", |
24009 |
-+ .desc = "queuing of names", |
24010 |
-+ .func = kdbus_test_name_queue, |
24011 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24012 |
-+ }, |
24013 |
-+ { |
24014 |
-+ .name = "name-takeover", |
24015 |
-+ .desc = "takeover of names", |
24016 |
-+ .func = kdbus_test_name_takeover, |
24017 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24018 |
-+ }, |
24019 |
-+ { |
24020 |
-+ .name = "message-basic", |
24021 |
-+ .desc = "basic message handling", |
24022 |
-+ .func = kdbus_test_message_basic, |
24023 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24024 |
-+ }, |
24025 |
-+ { |
24026 |
-+ .name = "message-prio", |
24027 |
-+ .desc = "handling of messages with priority", |
24028 |
-+ .func = kdbus_test_message_prio, |
24029 |
-+ .flags = TEST_CREATE_BUS, |
24030 |
-+ }, |
24031 |
-+ { |
24032 |
-+ .name = "message-quota", |
24033 |
-+ .desc = "message quotas are enforced", |
24034 |
-+ .func = kdbus_test_message_quota, |
24035 |
-+ .flags = TEST_CREATE_BUS, |
24036 |
-+ }, |
24037 |
-+ { |
24038 |
-+ .name = "memory-access", |
24039 |
-+ .desc = "memory access", |
24040 |
-+ .func = kdbus_test_memory_access, |
24041 |
-+ .flags = TEST_CREATE_BUS, |
24042 |
-+ }, |
24043 |
-+ { |
24044 |
-+ .name = "timeout", |
24045 |
-+ .desc = "timeout", |
24046 |
-+ .func = kdbus_test_timeout, |
24047 |
-+ .flags = TEST_CREATE_BUS, |
24048 |
-+ }, |
24049 |
-+ { |
24050 |
-+ .name = "sync-byebye", |
24051 |
-+ .desc = "synchronous replies vs. BYEBYE", |
24052 |
-+ .func = kdbus_test_sync_byebye, |
24053 |
-+ .flags = TEST_CREATE_BUS, |
24054 |
-+ }, |
24055 |
-+ { |
24056 |
-+ .name = "sync-reply", |
24057 |
-+ .desc = "synchronous replies", |
24058 |
-+ .func = kdbus_test_sync_reply, |
24059 |
-+ .flags = TEST_CREATE_BUS, |
24060 |
-+ }, |
24061 |
-+ { |
24062 |
-+ .name = "message-free", |
24063 |
-+ .desc = "freeing of memory", |
24064 |
-+ .func = kdbus_test_free, |
24065 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24066 |
-+ }, |
24067 |
-+ { |
24068 |
-+ .name = "connection-info", |
24069 |
-+ .desc = "retrieving connection information", |
24070 |
-+ .func = kdbus_test_conn_info, |
24071 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24072 |
-+ }, |
24073 |
-+ { |
24074 |
-+ .name = "connection-update", |
24075 |
-+ .desc = "updating connection information", |
24076 |
-+ .func = kdbus_test_conn_update, |
24077 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24078 |
-+ }, |
24079 |
-+ { |
24080 |
-+ .name = "writable-pool", |
24081 |
-+ .desc = "verifying pools are never writable", |
24082 |
-+ .func = kdbus_test_writable_pool, |
24083 |
-+ .flags = TEST_CREATE_BUS, |
24084 |
-+ }, |
24085 |
-+ { |
24086 |
-+ .name = "policy", |
24087 |
-+ .desc = "policy", |
24088 |
-+ .func = kdbus_test_policy, |
24089 |
-+ .flags = TEST_CREATE_BUS, |
24090 |
-+ }, |
24091 |
-+ { |
24092 |
-+ .name = "policy-priv", |
24093 |
-+ .desc = "unprivileged bus access", |
24094 |
-+ .func = kdbus_test_policy_priv, |
24095 |
-+ .flags = TEST_CREATE_BUS, |
24096 |
-+ }, |
24097 |
-+ { |
24098 |
-+ .name = "policy-ns", |
24099 |
-+ .desc = "policy in user namespaces", |
24100 |
-+ .func = kdbus_test_policy_ns, |
24101 |
-+ .flags = TEST_CREATE_BUS, |
24102 |
-+ }, |
24103 |
-+ { |
24104 |
-+ .name = "metadata-ns", |
24105 |
-+ .desc = "metadata in different namespaces", |
24106 |
-+ .func = kdbus_test_metadata_ns, |
24107 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24108 |
-+ }, |
24109 |
-+ { |
24110 |
-+ .name = "match-id-add", |
24111 |
-+ .desc = "adding of matches by id", |
24112 |
-+ .func = kdbus_test_match_id_add, |
24113 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24114 |
-+ }, |
24115 |
-+ { |
24116 |
-+ .name = "match-id-remove", |
24117 |
-+ .desc = "removing of matches by id", |
24118 |
-+ .func = kdbus_test_match_id_remove, |
24119 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24120 |
-+ }, |
24121 |
-+ { |
24122 |
-+ .name = "match-replace", |
24123 |
-+ .desc = "replace of matches with the same cookie", |
24124 |
-+ .func = kdbus_test_match_replace, |
24125 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24126 |
-+ }, |
24127 |
-+ { |
24128 |
-+ .name = "match-name-add", |
24129 |
-+ .desc = "adding of matches by name", |
24130 |
-+ .func = kdbus_test_match_name_add, |
24131 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24132 |
-+ }, |
24133 |
-+ { |
24134 |
-+ .name = "match-name-remove", |
24135 |
-+ .desc = "removing of matches by name", |
24136 |
-+ .func = kdbus_test_match_name_remove, |
24137 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24138 |
-+ }, |
24139 |
-+ { |
24140 |
-+ .name = "match-name-change", |
24141 |
-+ .desc = "matching for name changes", |
24142 |
-+ .func = kdbus_test_match_name_change, |
24143 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24144 |
-+ }, |
24145 |
-+ { |
24146 |
-+ .name = "match-bloom", |
24147 |
-+ .desc = "matching with bloom filters", |
24148 |
-+ .func = kdbus_test_match_bloom, |
24149 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24150 |
-+ }, |
24151 |
-+ { |
24152 |
-+ .name = "activator", |
24153 |
-+ .desc = "activator connections", |
24154 |
-+ .func = kdbus_test_activator, |
24155 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24156 |
-+ }, |
24157 |
-+ { |
24158 |
-+ .name = "benchmark", |
24159 |
-+ .desc = "benchmark", |
24160 |
-+ .func = kdbus_test_benchmark, |
24161 |
-+ .flags = TEST_CREATE_BUS, |
24162 |
-+ }, |
24163 |
-+ { |
24164 |
-+ .name = "benchmark-nomemfds", |
24165 |
-+ .desc = "benchmark without using memfds", |
24166 |
-+ .func = kdbus_test_benchmark_nomemfds, |
24167 |
-+ .flags = TEST_CREATE_BUS, |
24168 |
-+ }, |
24169 |
-+ { |
24170 |
-+ .name = "benchmark-uds", |
24171 |
-+ .desc = "benchmark comparison to UDS", |
24172 |
-+ .func = kdbus_test_benchmark_uds, |
24173 |
-+ .flags = TEST_CREATE_BUS, |
24174 |
-+ }, |
24175 |
-+}; |
24176 |
-+ |
24177 |
-+#define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0]))) |
24178 |
-+ |
24179 |
-+static int test_prepare_env(const struct kdbus_test *t, |
24180 |
-+ const struct kdbus_test_args *args, |
24181 |
-+ struct kdbus_test_env *env) |
24182 |
-+{ |
24183 |
-+ if (t->flags & TEST_CREATE_BUS) { |
24184 |
-+ char *s; |
24185 |
-+ char *n = NULL; |
24186 |
-+ int ret; |
24187 |
-+ |
24188 |
-+ asprintf(&s, "%s/control", args->root); |
24189 |
-+ |
24190 |
-+ env->control_fd = open(s, O_RDWR); |
24191 |
-+ free(s); |
24192 |
-+ ASSERT_RETURN(env->control_fd >= 0); |
24193 |
-+ |
24194 |
-+ if (!args->busname) { |
24195 |
-+ n = unique_name("test-bus"); |
24196 |
-+ ASSERT_RETURN(n); |
24197 |
-+ } |
24198 |
-+ |
24199 |
-+ ret = kdbus_create_bus(env->control_fd, |
24200 |
-+ args->busname ?: n, |
24201 |
-+ _KDBUS_ATTACH_ALL, &s); |
24202 |
-+ free(n); |
24203 |
-+ ASSERT_RETURN(ret == 0); |
24204 |
-+ |
24205 |
-+ asprintf(&env->buspath, "%s/%s/bus", args->root, s); |
24206 |
-+ free(s); |
24207 |
-+ } |
24208 |
-+ |
24209 |
-+ if (t->flags & TEST_CREATE_CONN) { |
24210 |
-+ env->conn = kdbus_hello(env->buspath, 0, NULL, 0); |
24211 |
-+ ASSERT_RETURN(env->conn); |
24212 |
-+ } |
24213 |
-+ |
24214 |
-+ env->root = args->root; |
24215 |
-+ env->module = args->module; |
24216 |
-+ |
24217 |
-+ return 0; |
24218 |
-+} |
24219 |
-+ |
24220 |
-+void test_unprepare_env(const struct kdbus_test *t, struct kdbus_test_env *env) |
24221 |
-+{ |
24222 |
-+ if (env->conn) { |
24223 |
-+ kdbus_conn_free(env->conn); |
24224 |
-+ env->conn = NULL; |
24225 |
-+ } |
24226 |
-+ |
24227 |
-+ if (env->control_fd >= 0) { |
24228 |
-+ close(env->control_fd); |
24229 |
-+ env->control_fd = -1; |
24230 |
-+ } |
24231 |
-+ |
24232 |
-+ if (env->buspath) { |
24233 |
-+ free(env->buspath); |
24234 |
-+ env->buspath = NULL; |
24235 |
-+ } |
24236 |
-+} |
24237 |
-+ |
24238 |
-+static int test_run(const struct kdbus_test *t, |
24239 |
-+ const struct kdbus_test_args *kdbus_args, |
24240 |
-+ int wait) |
24241 |
-+{ |
24242 |
-+ int ret; |
24243 |
-+ struct kdbus_test_env env = {}; |
24244 |
-+ |
24245 |
-+ ret = test_prepare_env(t, kdbus_args, &env); |
24246 |
-+ if (ret != TEST_OK) |
24247 |
-+ return ret; |
24248 |
-+ |
24249 |
-+ if (wait > 0) { |
24250 |
-+ printf("Sleeping %d seconds before running test ...\n", wait); |
24251 |
-+ sleep(wait); |
24252 |
-+ } |
24253 |
-+ |
24254 |
-+ ret = t->func(&env); |
24255 |
-+ test_unprepare_env(t, &env); |
24256 |
-+ return ret; |
24257 |
-+} |
24258 |
-+ |
24259 |
-+static int test_run_forked(const struct kdbus_test *t, |
24260 |
-+ const struct kdbus_test_args *kdbus_args, |
24261 |
-+ int wait) |
24262 |
-+{ |
24263 |
-+ int ret; |
24264 |
-+ pid_t pid; |
24265 |
-+ |
24266 |
-+ pid = fork(); |
24267 |
-+ if (pid < 0) { |
24268 |
-+ return TEST_ERR; |
24269 |
-+ } else if (pid == 0) { |
24270 |
-+ ret = test_run(t, kdbus_args, wait); |
24271 |
-+ _exit(ret); |
24272 |
-+ } |
24273 |
-+ |
24274 |
-+ pid = waitpid(pid, &ret, 0); |
24275 |
-+ if (pid <= 0) |
24276 |
-+ return TEST_ERR; |
24277 |
-+ else if (!WIFEXITED(ret)) |
24278 |
-+ return TEST_ERR; |
24279 |
-+ else |
24280 |
-+ return WEXITSTATUS(ret); |
24281 |
-+} |
24282 |
-+ |
24283 |
-+static void print_test_result(int ret) |
24284 |
-+{ |
24285 |
-+ switch (ret) { |
24286 |
-+ case TEST_OK: |
24287 |
-+ printf("OK"); |
24288 |
-+ break; |
24289 |
-+ case TEST_SKIP: |
24290 |
-+ printf("SKIPPED"); |
24291 |
-+ break; |
24292 |
-+ case TEST_ERR: |
24293 |
-+ printf("ERROR"); |
24294 |
-+ break; |
24295 |
-+ } |
24296 |
-+} |
24297 |
-+ |
24298 |
-+static int start_all_tests(struct kdbus_test_args *kdbus_args) |
24299 |
-+{ |
24300 |
-+ int ret; |
24301 |
-+ unsigned int fail_cnt = 0; |
24302 |
-+ unsigned int skip_cnt = 0; |
24303 |
-+ unsigned int ok_cnt = 0; |
24304 |
-+ unsigned int i; |
24305 |
-+ |
24306 |
-+ if (kdbus_args->tap_output) { |
24307 |
-+ printf("1..%d\n", N_TESTS); |
24308 |
-+ fflush(stdout); |
24309 |
-+ } |
24310 |
-+ |
24311 |
-+ kdbus_util_verbose = false; |
24312 |
-+ |
24313 |
-+ for (i = 0; i < N_TESTS; i++) { |
24314 |
-+ const struct kdbus_test *t = tests + i; |
24315 |
-+ |
24316 |
-+ if (!kdbus_args->tap_output) { |
24317 |
-+ unsigned int n; |
24318 |
-+ |
24319 |
-+ printf("Testing %s (%s) ", t->desc, t->name); |
24320 |
-+ for (n = 0; n < 60 - strlen(t->desc) - strlen(t->name); n++) |
24321 |
-+ printf("."); |
24322 |
-+ printf(" "); |
24323 |
-+ } |
24324 |
-+ |
24325 |
-+ ret = test_run_forked(t, kdbus_args, 0); |
24326 |
-+ switch (ret) { |
24327 |
-+ case TEST_OK: |
24328 |
-+ ok_cnt++; |
24329 |
-+ break; |
24330 |
-+ case TEST_SKIP: |
24331 |
-+ skip_cnt++; |
24332 |
-+ break; |
24333 |
-+ case TEST_ERR: |
24334 |
-+ fail_cnt++; |
24335 |
-+ break; |
24336 |
-+ } |
24337 |
-+ |
24338 |
-+ if (kdbus_args->tap_output) { |
24339 |
-+ printf("%sok %d - %s%s (%s)\n", |
24340 |
-+ (ret == TEST_ERR) ? "not " : "", i + 1, |
24341 |
-+ (ret == TEST_SKIP) ? "# SKIP " : "", |
24342 |
-+ t->desc, t->name); |
24343 |
-+ fflush(stdout); |
24344 |
-+ } else { |
24345 |
-+ print_test_result(ret); |
24346 |
-+ printf("\n"); |
24347 |
-+ } |
24348 |
-+ } |
24349 |
-+ |
24350 |
-+ if (kdbus_args->tap_output) |
24351 |
-+ printf("Failed %d/%d tests, %.2f%% okay\n", fail_cnt, N_TESTS, |
24352 |
-+ 100.0 - (fail_cnt * 100.0) / ((float) N_TESTS)); |
24353 |
-+ else |
24354 |
-+ printf("\nSUMMARY: %u tests passed, %u skipped, %u failed\n", |
24355 |
-+ ok_cnt, skip_cnt, fail_cnt); |
24356 |
-+ |
24357 |
-+ return fail_cnt > 0 ? TEST_ERR : TEST_OK; |
24358 |
-+} |
24359 |
-+ |
24360 |
-+static int start_one_test(struct kdbus_test_args *kdbus_args) |
24361 |
-+{ |
24362 |
-+ int i, ret; |
24363 |
-+ bool test_found = false; |
24364 |
-+ |
24365 |
-+ for (i = 0; i < N_TESTS; i++) { |
24366 |
-+ const struct kdbus_test *t = tests + i; |
24367 |
-+ |
24368 |
-+ if (strcmp(t->name, kdbus_args->test)) |
24369 |
-+ continue; |
24370 |
-+ |
24371 |
-+ do { |
24372 |
-+ test_found = true; |
24373 |
-+ if (kdbus_args->fork) |
24374 |
-+ ret = test_run_forked(t, kdbus_args, |
24375 |
-+ kdbus_args->wait); |
24376 |
-+ else |
24377 |
-+ ret = test_run(t, kdbus_args, |
24378 |
-+ kdbus_args->wait); |
24379 |
-+ |
24380 |
-+ printf("Testing %s: ", t->desc); |
24381 |
-+ print_test_result(ret); |
24382 |
-+ printf("\n"); |
24383 |
-+ |
24384 |
-+ if (ret != TEST_OK) |
24385 |
-+ break; |
24386 |
-+ } while (kdbus_args->loop); |
24387 |
-+ |
24388 |
-+ return ret; |
24389 |
-+ } |
24390 |
-+ |
24391 |
-+ if (!test_found) { |
24392 |
-+ printf("Unknown test-id '%s'\n", kdbus_args->test); |
24393 |
-+ return TEST_ERR; |
24394 |
-+ } |
24395 |
-+ |
24396 |
-+ return TEST_OK; |
24397 |
-+} |
24398 |
-+ |
24399 |
-+static void usage(const char *argv0) |
24400 |
-+{ |
24401 |
-+ unsigned int i, j; |
24402 |
-+ |
24403 |
-+ printf("Usage: %s [options]\n" |
24404 |
-+ "Options:\n" |
24405 |
-+ "\t-a, --tap Output test results in TAP format\n" |
24406 |
-+ "\t-m, --module <module> Kdbus module name\n" |
24407 |
-+ "\t-x, --loop Run in a loop\n" |
24408 |
-+ "\t-f, --fork Fork before running a test\n" |
24409 |
-+ "\t-h, --help Print this help\n" |
24410 |
-+ "\t-r, --root <root> Toplevel of the kdbus hierarchy\n" |
24411 |
-+ "\t-t, --test <test-id> Run one specific test only, in verbose mode\n" |
24412 |
-+ "\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n" |
24413 |
-+ "\t-w, --wait <secs> Wait <secs> before actually starting test\n" |
24414 |
-+ "\t --mntns New mount namespace\n" |
24415 |
-+ "\t --pidns New PID namespace\n" |
24416 |
-+ "\t --userns New user namespace\n" |
24417 |
-+ "\t --uidmap uid_map UID map for user namespace\n" |
24418 |
-+ "\t --gidmap gid_map GID map for user namespace\n" |
24419 |
-+ "\n", argv0); |
24420 |
-+ |
24421 |
-+ printf("By default, all test are run once, and a summary is printed.\n" |
24422 |
-+ "Available tests for --test:\n\n"); |
24423 |
-+ |
24424 |
-+ for (i = 0; i < N_TESTS; i++) { |
24425 |
-+ const struct kdbus_test *t = tests + i; |
24426 |
-+ |
24427 |
-+ printf("\t%s", t->name); |
24428 |
-+ |
24429 |
-+ for (j = 0; j < 24 - strlen(t->name); j++) |
24430 |
-+ printf(" "); |
24431 |
-+ |
24432 |
-+ printf("Test %s\n", t->desc); |
24433 |
-+ } |
24434 |
-+ |
24435 |
-+ printf("\n"); |
24436 |
-+ printf("Note that some tests may, if run specifically by --test, " |
24437 |
-+ "behave differently, and not terminate by themselves.\n"); |
24438 |
-+ |
24439 |
-+ exit(EXIT_FAILURE); |
24440 |
-+} |
24441 |
-+ |
24442 |
-+void print_kdbus_test_args(struct kdbus_test_args *args) |
24443 |
-+{ |
24444 |
-+ if (args->userns || args->pidns || args->mntns) |
24445 |
-+ printf("# Starting tests in new %s%s%s namespaces%s\n", |
24446 |
-+ args->mntns ? "MOUNT " : "", |
24447 |
-+ args->pidns ? "PID " : "", |
24448 |
-+ args->userns ? "USER " : "", |
24449 |
-+ args->mntns ? ", kdbusfs will be remounted" : ""); |
24450 |
-+ else |
24451 |
-+ printf("# Starting tests in the same namespaces\n"); |
24452 |
-+} |
24453 |
-+ |
24454 |
-+void print_metadata_support(void) |
24455 |
-+{ |
24456 |
-+ bool no_meta_audit, no_meta_cgroups, no_meta_seclabel; |
24457 |
-+ |
24458 |
-+ /* |
24459 |
-+ * KDBUS_ATTACH_CGROUP, KDBUS_ATTACH_AUDIT and |
24460 |
-+ * KDBUS_ATTACH_SECLABEL |
24461 |
-+ */ |
24462 |
-+ no_meta_audit = !config_auditsyscall_is_enabled(); |
24463 |
-+ no_meta_cgroups = !config_cgroups_is_enabled(); |
24464 |
-+ no_meta_seclabel = !config_security_is_enabled(); |
24465 |
-+ |
24466 |
-+ if (no_meta_audit | no_meta_cgroups | no_meta_seclabel) |
24467 |
-+ printf("# Starting tests without %s%s%s metadata support\n", |
24468 |
-+ no_meta_audit ? "AUDIT " : "", |
24469 |
-+ no_meta_cgroups ? "CGROUP " : "", |
24470 |
-+ no_meta_seclabel ? "SECLABEL " : ""); |
24471 |
-+ else |
24472 |
-+ printf("# Starting tests with full metadata support\n"); |
24473 |
-+} |
24474 |
-+ |
24475 |
-+int run_tests(struct kdbus_test_args *kdbus_args) |
24476 |
-+{ |
24477 |
-+ int ret; |
24478 |
-+ static char control[4096]; |
24479 |
-+ |
24480 |
-+ snprintf(control, sizeof(control), "%s/control", kdbus_args->root); |
24481 |
-+ |
24482 |
-+ if (access(control, W_OK) < 0) { |
24483 |
-+ printf("Unable to locate control node at '%s'.\n", |
24484 |
-+ control); |
24485 |
-+ return TEST_ERR; |
24486 |
-+ } |
24487 |
-+ |
24488 |
-+ if (kdbus_args->test) { |
24489 |
-+ ret = start_one_test(kdbus_args); |
24490 |
-+ } else { |
24491 |
-+ do { |
24492 |
-+ ret = start_all_tests(kdbus_args); |
24493 |
-+ if (ret != TEST_OK) |
24494 |
-+ break; |
24495 |
-+ } while (kdbus_args->loop); |
24496 |
-+ } |
24497 |
-+ |
24498 |
-+ return ret; |
24499 |
-+} |
24500 |
-+ |
24501 |
-+static void nop_handler(int sig) {} |
24502 |
-+ |
24503 |
-+static int test_prepare_mounts(struct kdbus_test_args *kdbus_args) |
24504 |
-+{ |
24505 |
-+ int ret; |
24506 |
-+ char kdbusfs[64] = {'\0'}; |
24507 |
-+ |
24508 |
-+ snprintf(kdbusfs, sizeof(kdbusfs), "%sfs", kdbus_args->module); |
24509 |
-+ |
24510 |
-+ /* make current mount slave */ |
24511 |
-+ ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); |
24512 |
-+ if (ret < 0) { |
24513 |
-+ ret = -errno; |
24514 |
-+ printf("error mount() root: %d (%m)\n", ret); |
24515 |
-+ return ret; |
24516 |
-+ } |
24517 |
-+ |
24518 |
-+ /* Remount procfs since we need it in our tests */ |
24519 |
-+ if (kdbus_args->pidns) { |
24520 |
-+ ret = mount("proc", "/proc", "proc", |
24521 |
-+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); |
24522 |
-+ if (ret < 0) { |
24523 |
-+ ret = -errno; |
24524 |
-+ printf("error mount() /proc : %d (%m)\n", ret); |
24525 |
-+ return ret; |
24526 |
-+ } |
24527 |
-+ } |
24528 |
-+ |
24529 |
-+ /* Remount kdbusfs */ |
24530 |
-+ ret = mount(kdbusfs, kdbus_args->root, kdbusfs, |
24531 |
-+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); |
24532 |
-+ if (ret < 0) { |
24533 |
-+ ret = -errno; |
24534 |
-+ printf("error mount() %s :%d (%m)\n", kdbusfs, ret); |
24535 |
-+ return ret; |
24536 |
-+ } |
24537 |
-+ |
24538 |
-+ return 0; |
24539 |
-+} |
24540 |
-+ |
24541 |
-+int run_tests_in_namespaces(struct kdbus_test_args *kdbus_args) |
24542 |
-+{ |
24543 |
-+ int ret; |
24544 |
-+ int efd = -1; |
24545 |
-+ int status; |
24546 |
-+ pid_t pid, rpid; |
24547 |
-+ struct sigaction oldsa; |
24548 |
-+ struct sigaction sa = { |
24549 |
-+ .sa_handler = nop_handler, |
24550 |
-+ .sa_flags = SA_NOCLDSTOP, |
24551 |
-+ }; |
24552 |
-+ |
24553 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
24554 |
-+ if (efd < 0) { |
24555 |
-+ ret = -errno; |
24556 |
-+ printf("eventfd() failed: %d (%m)\n", ret); |
24557 |
-+ return TEST_ERR; |
24558 |
-+ } |
24559 |
-+ |
24560 |
-+ ret = sigaction(SIGCHLD, &sa, &oldsa); |
24561 |
-+ if (ret < 0) { |
24562 |
-+ ret = -errno; |
24563 |
-+ printf("sigaction() failed: %d (%m)\n", ret); |
24564 |
-+ return TEST_ERR; |
24565 |
-+ } |
24566 |
-+ |
24567 |
-+ /* setup namespaces */ |
24568 |
-+ pid = syscall(__NR_clone, SIGCHLD| |
24569 |
-+ (kdbus_args->userns ? CLONE_NEWUSER : 0) | |
24570 |
-+ (kdbus_args->mntns ? CLONE_NEWNS : 0) | |
24571 |
-+ (kdbus_args->pidns ? CLONE_NEWPID : 0), NULL); |
24572 |
-+ if (pid < 0) { |
24573 |
-+ printf("clone() failed: %d (%m)\n", -errno); |
24574 |
-+ return TEST_ERR; |
24575 |
-+ } |
24576 |
-+ |
24577 |
-+ if (pid == 0) { |
24578 |
-+ eventfd_t event_status = 0; |
24579 |
-+ |
24580 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
24581 |
-+ if (ret < 0) { |
24582 |
-+ ret = -errno; |
24583 |
-+ printf("error prctl(): %d (%m)\n", ret); |
24584 |
-+ _exit(TEST_ERR); |
24585 |
-+ } |
24586 |
-+ |
24587 |
-+ /* reset sighandlers of childs */ |
24588 |
-+ ret = sigaction(SIGCHLD, &oldsa, NULL); |
24589 |
-+ if (ret < 0) { |
24590 |
-+ ret = -errno; |
24591 |
-+ printf("sigaction() failed: %d (%m)\n", ret); |
24592 |
-+ _exit(TEST_ERR); |
24593 |
-+ } |
24594 |
-+ |
24595 |
-+ ret = eventfd_read(efd, &event_status); |
24596 |
-+ if (ret < 0 || event_status != 1) { |
24597 |
-+ printf("error eventfd_read()\n"); |
24598 |
-+ _exit(TEST_ERR); |
24599 |
-+ } |
24600 |
-+ |
24601 |
-+ if (kdbus_args->mntns) { |
24602 |
-+ ret = test_prepare_mounts(kdbus_args); |
24603 |
-+ if (ret < 0) { |
24604 |
-+ printf("error preparing mounts\n"); |
24605 |
-+ _exit(TEST_ERR); |
24606 |
-+ } |
24607 |
-+ } |
24608 |
-+ |
24609 |
-+ ret = run_tests(kdbus_args); |
24610 |
-+ _exit(ret); |
24611 |
-+ } |
24612 |
-+ |
24613 |
-+ /* Setup userns mapping */ |
24614 |
-+ if (kdbus_args->userns) { |
24615 |
-+ ret = userns_map_uid_gid(pid, kdbus_args->uid_map, |
24616 |
-+ kdbus_args->gid_map); |
24617 |
-+ if (ret < 0) { |
24618 |
-+ printf("error mapping uid and gid in userns\n"); |
24619 |
-+ eventfd_write(efd, 2); |
24620 |
-+ return TEST_ERR; |
24621 |
-+ } |
24622 |
-+ } |
24623 |
-+ |
24624 |
-+ ret = eventfd_write(efd, 1); |
24625 |
-+ if (ret < 0) { |
24626 |
-+ ret = -errno; |
24627 |
-+ printf("error eventfd_write(): %d (%m)\n", ret); |
24628 |
-+ return TEST_ERR; |
24629 |
-+ } |
24630 |
-+ |
24631 |
-+ rpid = waitpid(pid, &status, 0); |
24632 |
-+ ASSERT_RETURN_VAL(rpid == pid, TEST_ERR); |
24633 |
-+ |
24634 |
-+ close(efd); |
24635 |
-+ |
24636 |
-+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) |
24637 |
-+ return TEST_ERR; |
24638 |
-+ |
24639 |
-+ return TEST_OK; |
24640 |
-+} |
24641 |
-+ |
24642 |
-+int start_tests(struct kdbus_test_args *kdbus_args) |
24643 |
-+{ |
24644 |
-+ int ret; |
24645 |
-+ bool namespaces; |
24646 |
-+ static char fspath[4096]; |
24647 |
-+ |
24648 |
-+ namespaces = (kdbus_args->mntns || kdbus_args->pidns || |
24649 |
-+ kdbus_args->userns); |
24650 |
-+ |
24651 |
-+ /* for pidns we need mntns set */ |
24652 |
-+ if (kdbus_args->pidns && !kdbus_args->mntns) { |
24653 |
-+ printf("Failed: please set both pid and mnt namesapces\n"); |
24654 |
-+ return TEST_ERR; |
24655 |
-+ } |
24656 |
-+ |
24657 |
-+ if (kdbus_args->userns) { |
24658 |
-+ if (!config_user_ns_is_enabled()) { |
24659 |
-+ printf("User namespace not supported\n"); |
24660 |
-+ return TEST_ERR; |
24661 |
-+ } |
24662 |
-+ |
24663 |
-+ if (!kdbus_args->uid_map || !kdbus_args->gid_map) { |
24664 |
-+ printf("Failed: please specify uid or gid mapping\n"); |
24665 |
-+ return TEST_ERR; |
24666 |
-+ } |
24667 |
-+ } |
24668 |
-+ |
24669 |
-+ print_kdbus_test_args(kdbus_args); |
24670 |
-+ print_metadata_support(); |
24671 |
-+ |
24672 |
-+ /* setup kdbus paths */ |
24673 |
-+ if (!kdbus_args->module) |
24674 |
-+ kdbus_args->module = "kdbus"; |
24675 |
-+ |
24676 |
-+ if (!kdbus_args->root) { |
24677 |
-+ snprintf(fspath, sizeof(fspath), "/sys/fs/%s", |
24678 |
-+ kdbus_args->module); |
24679 |
-+ kdbus_args->root = fspath; |
24680 |
-+ } |
24681 |
-+ |
24682 |
-+ /* Start tests */ |
24683 |
-+ if (namespaces) |
24684 |
-+ ret = run_tests_in_namespaces(kdbus_args); |
24685 |
-+ else |
24686 |
-+ ret = run_tests(kdbus_args); |
24687 |
-+ |
24688 |
-+ return ret; |
24689 |
-+} |
24690 |
-+ |
24691 |
-+int main(int argc, char *argv[]) |
24692 |
-+{ |
24693 |
-+ int t, ret = 0; |
24694 |
-+ struct kdbus_test_args *kdbus_args; |
24695 |
-+ enum { |
24696 |
-+ ARG_MNTNS = 0x100, |
24697 |
-+ ARG_PIDNS, |
24698 |
-+ ARG_USERNS, |
24699 |
-+ ARG_UIDMAP, |
24700 |
-+ ARG_GIDMAP, |
24701 |
-+ }; |
24702 |
-+ |
24703 |
-+ kdbus_args = malloc(sizeof(*kdbus_args)); |
24704 |
-+ if (!kdbus_args) { |
24705 |
-+ printf("unable to malloc() kdbus_args\n"); |
24706 |
-+ return EXIT_FAILURE; |
24707 |
-+ } |
24708 |
-+ |
24709 |
-+ memset(kdbus_args, 0, sizeof(*kdbus_args)); |
24710 |
-+ |
24711 |
-+ static const struct option options[] = { |
24712 |
-+ { "loop", no_argument, NULL, 'x' }, |
24713 |
-+ { "help", no_argument, NULL, 'h' }, |
24714 |
-+ { "root", required_argument, NULL, 'r' }, |
24715 |
-+ { "test", required_argument, NULL, 't' }, |
24716 |
-+ { "bus", required_argument, NULL, 'b' }, |
24717 |
-+ { "wait", required_argument, NULL, 'w' }, |
24718 |
-+ { "fork", no_argument, NULL, 'f' }, |
24719 |
-+ { "module", required_argument, NULL, 'm' }, |
24720 |
-+ { "tap", no_argument, NULL, 'a' }, |
24721 |
-+ { "mntns", no_argument, NULL, ARG_MNTNS }, |
24722 |
-+ { "pidns", no_argument, NULL, ARG_PIDNS }, |
24723 |
-+ { "userns", no_argument, NULL, ARG_USERNS }, |
24724 |
-+ { "uidmap", required_argument, NULL, ARG_UIDMAP }, |
24725 |
-+ { "gidmap", required_argument, NULL, ARG_GIDMAP }, |
24726 |
-+ {} |
24727 |
-+ }; |
24728 |
-+ |
24729 |
-+ srand(time(NULL)); |
24730 |
-+ |
24731 |
-+ while ((t = getopt_long(argc, argv, "hxfm:r:t:b:w:a", options, NULL)) >= 0) { |
24732 |
-+ switch (t) { |
24733 |
-+ case 'x': |
24734 |
-+ kdbus_args->loop = 1; |
24735 |
-+ break; |
24736 |
-+ |
24737 |
-+ case 'm': |
24738 |
-+ kdbus_args->module = optarg; |
24739 |
-+ break; |
24740 |
-+ |
24741 |
-+ case 'r': |
24742 |
-+ kdbus_args->root = optarg; |
24743 |
-+ break; |
24744 |
-+ |
24745 |
-+ case 't': |
24746 |
-+ kdbus_args->test = optarg; |
24747 |
-+ break; |
24748 |
-+ |
24749 |
-+ case 'b': |
24750 |
-+ kdbus_args->busname = optarg; |
24751 |
-+ break; |
24752 |
-+ |
24753 |
-+ case 'w': |
24754 |
-+ kdbus_args->wait = strtol(optarg, NULL, 10); |
24755 |
-+ break; |
24756 |
-+ |
24757 |
-+ case 'f': |
24758 |
-+ kdbus_args->fork = 1; |
24759 |
-+ break; |
24760 |
-+ |
24761 |
-+ case 'a': |
24762 |
-+ kdbus_args->tap_output = 1; |
24763 |
-+ break; |
24764 |
-+ |
24765 |
-+ case ARG_MNTNS: |
24766 |
-+ kdbus_args->mntns = true; |
24767 |
-+ break; |
24768 |
-+ |
24769 |
-+ case ARG_PIDNS: |
24770 |
-+ kdbus_args->pidns = true; |
24771 |
-+ break; |
24772 |
-+ |
24773 |
-+ case ARG_USERNS: |
24774 |
-+ kdbus_args->userns = true; |
24775 |
-+ break; |
24776 |
-+ |
24777 |
-+ case ARG_UIDMAP: |
24778 |
-+ kdbus_args->uid_map = optarg; |
24779 |
-+ break; |
24780 |
-+ |
24781 |
-+ case ARG_GIDMAP: |
24782 |
-+ kdbus_args->gid_map = optarg; |
24783 |
-+ break; |
24784 |
-+ |
24785 |
-+ default: |
24786 |
-+ case 'h': |
24787 |
-+ usage(argv[0]); |
24788 |
-+ } |
24789 |
-+ } |
24790 |
-+ |
24791 |
-+ ret = start_tests(kdbus_args); |
24792 |
-+ if (ret == TEST_ERR) |
24793 |
-+ return EXIT_FAILURE; |
24794 |
-+ |
24795 |
-+ free(kdbus_args); |
24796 |
-+ |
24797 |
-+ return 0; |
24798 |
-+} |
24799 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-test.h b/tools/testing/selftests/kdbus/kdbus-test.h |
24800 |
-new file mode 100644 |
24801 |
-index 0000000..ee937f9 |
24802 |
---- /dev/null |
24803 |
-+++ b/tools/testing/selftests/kdbus/kdbus-test.h |
24804 |
-@@ -0,0 +1,84 @@ |
24805 |
-+#ifndef _TEST_KDBUS_H_ |
24806 |
-+#define _TEST_KDBUS_H_ |
24807 |
-+ |
24808 |
-+struct kdbus_test_env { |
24809 |
-+ char *buspath; |
24810 |
-+ const char *root; |
24811 |
-+ const char *module; |
24812 |
-+ int control_fd; |
24813 |
-+ struct kdbus_conn *conn; |
24814 |
-+}; |
24815 |
-+ |
24816 |
-+enum { |
24817 |
-+ TEST_OK, |
24818 |
-+ TEST_SKIP, |
24819 |
-+ TEST_ERR, |
24820 |
-+}; |
24821 |
-+ |
24822 |
-+#define ASSERT_RETURN_VAL(cond, val) \ |
24823 |
-+ if (!(cond)) { \ |
24824 |
-+ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24825 |
-+ #cond, __func__, __FILE__, __LINE__); \ |
24826 |
-+ return val; \ |
24827 |
-+ } |
24828 |
-+ |
24829 |
-+#define ASSERT_EXIT_VAL(cond, val) \ |
24830 |
-+ if (!(cond)) { \ |
24831 |
-+ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24832 |
-+ #cond, __func__, __FILE__, __LINE__); \ |
24833 |
-+ _exit(val); \ |
24834 |
-+ } |
24835 |
-+ |
24836 |
-+#define ASSERT_BREAK(cond) \ |
24837 |
-+ if (!(cond)) { \ |
24838 |
-+ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24839 |
-+ #cond, __func__, __FILE__, __LINE__); \ |
24840 |
-+ break; \ |
24841 |
-+ } |
24842 |
-+ |
24843 |
-+#define ASSERT_RETURN(cond) \ |
24844 |
-+ ASSERT_RETURN_VAL(cond, TEST_ERR) |
24845 |
-+ |
24846 |
-+#define ASSERT_EXIT(cond) \ |
24847 |
-+ ASSERT_EXIT_VAL(cond, EXIT_FAILURE) |
24848 |
-+ |
24849 |
-+int kdbus_test_activator(struct kdbus_test_env *env); |
24850 |
-+int kdbus_test_benchmark(struct kdbus_test_env *env); |
24851 |
-+int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env); |
24852 |
-+int kdbus_test_benchmark_uds(struct kdbus_test_env *env); |
24853 |
-+int kdbus_test_bus_make(struct kdbus_test_env *env); |
24854 |
-+int kdbus_test_byebye(struct kdbus_test_env *env); |
24855 |
-+int kdbus_test_chat(struct kdbus_test_env *env); |
24856 |
-+int kdbus_test_conn_info(struct kdbus_test_env *env); |
24857 |
-+int kdbus_test_conn_update(struct kdbus_test_env *env); |
24858 |
-+int kdbus_test_daemon(struct kdbus_test_env *env); |
24859 |
-+int kdbus_test_custom_endpoint(struct kdbus_test_env *env); |
24860 |
-+int kdbus_test_fd_passing(struct kdbus_test_env *env); |
24861 |
-+int kdbus_test_free(struct kdbus_test_env *env); |
24862 |
-+int kdbus_test_hello(struct kdbus_test_env *env); |
24863 |
-+int kdbus_test_match_bloom(struct kdbus_test_env *env); |
24864 |
-+int kdbus_test_match_id_add(struct kdbus_test_env *env); |
24865 |
-+int kdbus_test_match_id_remove(struct kdbus_test_env *env); |
24866 |
-+int kdbus_test_match_replace(struct kdbus_test_env *env); |
24867 |
-+int kdbus_test_match_name_add(struct kdbus_test_env *env); |
24868 |
-+int kdbus_test_match_name_change(struct kdbus_test_env *env); |
24869 |
-+int kdbus_test_match_name_remove(struct kdbus_test_env *env); |
24870 |
-+int kdbus_test_message_basic(struct kdbus_test_env *env); |
24871 |
-+int kdbus_test_message_prio(struct kdbus_test_env *env); |
24872 |
-+int kdbus_test_message_quota(struct kdbus_test_env *env); |
24873 |
-+int kdbus_test_memory_access(struct kdbus_test_env *env); |
24874 |
-+int kdbus_test_metadata_ns(struct kdbus_test_env *env); |
24875 |
-+int kdbus_test_monitor(struct kdbus_test_env *env); |
24876 |
-+int kdbus_test_name_basic(struct kdbus_test_env *env); |
24877 |
-+int kdbus_test_name_conflict(struct kdbus_test_env *env); |
24878 |
-+int kdbus_test_name_queue(struct kdbus_test_env *env); |
24879 |
-+int kdbus_test_name_takeover(struct kdbus_test_env *env); |
24880 |
-+int kdbus_test_policy(struct kdbus_test_env *env); |
24881 |
-+int kdbus_test_policy_ns(struct kdbus_test_env *env); |
24882 |
-+int kdbus_test_policy_priv(struct kdbus_test_env *env); |
24883 |
-+int kdbus_test_sync_byebye(struct kdbus_test_env *env); |
24884 |
-+int kdbus_test_sync_reply(struct kdbus_test_env *env); |
24885 |
-+int kdbus_test_timeout(struct kdbus_test_env *env); |
24886 |
-+int kdbus_test_writable_pool(struct kdbus_test_env *env); |
24887 |
-+ |
24888 |
-+#endif /* _TEST_KDBUS_H_ */ |
24889 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c |
24890 |
-new file mode 100644 |
24891 |
-index 0000000..82fa89b |
24892 |
---- /dev/null |
24893 |
-+++ b/tools/testing/selftests/kdbus/kdbus-util.c |
24894 |
-@@ -0,0 +1,1612 @@ |
24895 |
-+/* |
24896 |
-+ * Copyright (C) 2013-2015 Daniel Mack |
24897 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
24898 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
24899 |
-+ * |
24900 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
24901 |
-+ * the terms of the GNU Lesser General Public License as published by the |
24902 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
24903 |
-+ * your option) any later version. |
24904 |
-+ */ |
24905 |
-+ |
24906 |
-+#include <stdio.h> |
24907 |
-+#include <stdarg.h> |
24908 |
-+#include <string.h> |
24909 |
-+#include <time.h> |
24910 |
-+#include <inttypes.h> |
24911 |
-+#include <fcntl.h> |
24912 |
-+#include <stdlib.h> |
24913 |
-+#include <stddef.h> |
24914 |
-+#include <unistd.h> |
24915 |
-+#include <stdint.h> |
24916 |
-+#include <stdbool.h> |
24917 |
-+#include <errno.h> |
24918 |
-+#include <assert.h> |
24919 |
-+#include <poll.h> |
24920 |
-+#include <grp.h> |
24921 |
-+#include <sys/capability.h> |
24922 |
-+#include <sys/mman.h> |
24923 |
-+#include <sys/stat.h> |
24924 |
-+#include <sys/time.h> |
24925 |
-+#include <linux/unistd.h> |
24926 |
-+#include <linux/memfd.h> |
24927 |
-+ |
24928 |
-+#ifndef __NR_memfd_create |
24929 |
-+ #ifdef __x86_64__ |
24930 |
-+ #define __NR_memfd_create 319 |
24931 |
-+ #elif defined __arm__ |
24932 |
-+ #define __NR_memfd_create 385 |
24933 |
-+ #else |
24934 |
-+ #define __NR_memfd_create 356 |
24935 |
-+ #endif |
24936 |
-+#endif |
24937 |
-+ |
24938 |
-+#include "kdbus-api.h" |
24939 |
-+#include "kdbus-util.h" |
24940 |
-+#include "kdbus-enum.h" |
24941 |
-+ |
24942 |
-+#ifndef F_ADD_SEALS |
24943 |
-+#define F_LINUX_SPECIFIC_BASE 1024 |
24944 |
-+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) |
24945 |
-+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) |
24946 |
-+ |
24947 |
-+#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ |
24948 |
-+#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ |
24949 |
-+#define F_SEAL_GROW 0x0004 /* prevent file from growing */ |
24950 |
-+#define F_SEAL_WRITE 0x0008 /* prevent writes */ |
24951 |
-+#endif |
24952 |
-+ |
24953 |
-+int kdbus_util_verbose = true; |
24954 |
-+ |
24955 |
-+int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask) |
24956 |
-+{ |
24957 |
-+ int ret; |
24958 |
-+ FILE *file; |
24959 |
-+ unsigned long long value; |
24960 |
-+ |
24961 |
-+ file = fopen(path, "r"); |
24962 |
-+ if (!file) { |
24963 |
-+ ret = -errno; |
24964 |
-+ kdbus_printf("--- error fopen(): %d (%m)\n", ret); |
24965 |
-+ return ret; |
24966 |
-+ } |
24967 |
-+ |
24968 |
-+ ret = fscanf(file, "%llu", &value); |
24969 |
-+ if (ret != 1) { |
24970 |
-+ if (ferror(file)) |
24971 |
-+ ret = -errno; |
24972 |
-+ else |
24973 |
-+ ret = -EIO; |
24974 |
-+ |
24975 |
-+ kdbus_printf("--- error fscanf(): %d\n", ret); |
24976 |
-+ fclose(file); |
24977 |
-+ return ret; |
24978 |
-+ } |
24979 |
-+ |
24980 |
-+ *mask = (uint64_t)value; |
24981 |
-+ |
24982 |
-+ fclose(file); |
24983 |
-+ |
24984 |
-+ return 0; |
24985 |
-+} |
24986 |
-+ |
24987 |
-+int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask) |
24988 |
-+{ |
24989 |
-+ int ret; |
24990 |
-+ FILE *file; |
24991 |
-+ |
24992 |
-+ file = fopen(path, "w"); |
24993 |
-+ if (!file) { |
24994 |
-+ ret = -errno; |
24995 |
-+ kdbus_printf("--- error open(): %d (%m)\n", ret); |
24996 |
-+ return ret; |
24997 |
-+ } |
24998 |
-+ |
24999 |
-+ ret = fprintf(file, "%llu", (unsigned long long)mask); |
25000 |
-+ if (ret <= 0) { |
25001 |
-+ ret = -EIO; |
25002 |
-+ kdbus_printf("--- error fprintf(): %d\n", ret); |
25003 |
-+ } |
25004 |
-+ |
25005 |
-+ fclose(file); |
25006 |
-+ |
25007 |
-+ return ret > 0 ? 0 : ret; |
25008 |
-+} |
25009 |
-+ |
25010 |
-+int kdbus_create_bus(int control_fd, const char *name, |
25011 |
-+ uint64_t owner_meta, char **path) |
25012 |
-+{ |
25013 |
-+ struct { |
25014 |
-+ struct kdbus_cmd cmd; |
25015 |
-+ |
25016 |
-+ /* bloom size item */ |
25017 |
-+ struct { |
25018 |
-+ uint64_t size; |
25019 |
-+ uint64_t type; |
25020 |
-+ struct kdbus_bloom_parameter bloom; |
25021 |
-+ } bp; |
25022 |
-+ |
25023 |
-+ /* owner metadata items */ |
25024 |
-+ struct { |
25025 |
-+ uint64_t size; |
25026 |
-+ uint64_t type; |
25027 |
-+ uint64_t flags; |
25028 |
-+ } attach; |
25029 |
-+ |
25030 |
-+ /* name item */ |
25031 |
-+ struct { |
25032 |
-+ uint64_t size; |
25033 |
-+ uint64_t type; |
25034 |
-+ char str[64]; |
25035 |
-+ } name; |
25036 |
-+ } bus_make; |
25037 |
-+ int ret; |
25038 |
-+ |
25039 |
-+ memset(&bus_make, 0, sizeof(bus_make)); |
25040 |
-+ bus_make.bp.size = sizeof(bus_make.bp); |
25041 |
-+ bus_make.bp.type = KDBUS_ITEM_BLOOM_PARAMETER; |
25042 |
-+ bus_make.bp.bloom.size = 64; |
25043 |
-+ bus_make.bp.bloom.n_hash = 1; |
25044 |
-+ |
25045 |
-+ snprintf(bus_make.name.str, sizeof(bus_make.name.str), |
25046 |
-+ "%u-%s", getuid(), name); |
25047 |
-+ |
25048 |
-+ bus_make.attach.type = KDBUS_ITEM_ATTACH_FLAGS_SEND; |
25049 |
-+ bus_make.attach.size = sizeof(bus_make.attach); |
25050 |
-+ bus_make.attach.flags = owner_meta; |
25051 |
-+ |
25052 |
-+ bus_make.name.type = KDBUS_ITEM_MAKE_NAME; |
25053 |
-+ bus_make.name.size = KDBUS_ITEM_HEADER_SIZE + |
25054 |
-+ strlen(bus_make.name.str) + 1; |
25055 |
-+ |
25056 |
-+ bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD; |
25057 |
-+ bus_make.cmd.size = sizeof(bus_make.cmd) + |
25058 |
-+ bus_make.bp.size + |
25059 |
-+ bus_make.attach.size + |
25060 |
-+ bus_make.name.size; |
25061 |
-+ |
25062 |
-+ kdbus_printf("Creating bus with name >%s< on control fd %d ...\n", |
25063 |
-+ name, control_fd); |
25064 |
-+ |
25065 |
-+ ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd); |
25066 |
-+ if (ret < 0) { |
25067 |
-+ kdbus_printf("--- error when making bus: %d (%m)\n", ret); |
25068 |
-+ return ret; |
25069 |
-+ } |
25070 |
-+ |
25071 |
-+ if (ret == 0 && path) |
25072 |
-+ *path = strdup(bus_make.name.str); |
25073 |
-+ |
25074 |
-+ return ret; |
25075 |
-+} |
25076 |
-+ |
25077 |
-+struct kdbus_conn * |
25078 |
-+kdbus_hello(const char *path, uint64_t flags, |
25079 |
-+ const struct kdbus_item *item, size_t item_size) |
25080 |
-+{ |
25081 |
-+ struct kdbus_cmd_free cmd_free = {}; |
25082 |
-+ int fd, ret; |
25083 |
-+ struct { |
25084 |
-+ struct kdbus_cmd_hello hello; |
25085 |
-+ |
25086 |
-+ struct { |
25087 |
-+ uint64_t size; |
25088 |
-+ uint64_t type; |
25089 |
-+ char str[16]; |
25090 |
-+ } conn_name; |
25091 |
-+ |
25092 |
-+ uint8_t extra_items[item_size]; |
25093 |
-+ } h; |
25094 |
-+ struct kdbus_conn *conn; |
25095 |
-+ |
25096 |
-+ memset(&h, 0, sizeof(h)); |
25097 |
-+ |
25098 |
-+ if (item_size > 0) |
25099 |
-+ memcpy(h.extra_items, item, item_size); |
25100 |
-+ |
25101 |
-+ kdbus_printf("-- opening bus connection %s\n", path); |
25102 |
-+ fd = open(path, O_RDWR|O_CLOEXEC); |
25103 |
-+ if (fd < 0) { |
25104 |
-+ kdbus_printf("--- error %d (%m)\n", fd); |
25105 |
-+ return NULL; |
25106 |
-+ } |
25107 |
-+ |
25108 |
-+ h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD; |
25109 |
-+ h.hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
25110 |
-+ h.hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
25111 |
-+ h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION; |
25112 |
-+ strcpy(h.conn_name.str, "this-is-my-name"); |
25113 |
-+ h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1; |
25114 |
-+ |
25115 |
-+ h.hello.size = sizeof(h); |
25116 |
-+ h.hello.pool_size = POOL_SIZE; |
25117 |
-+ |
25118 |
-+ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello); |
25119 |
-+ if (ret < 0) { |
25120 |
-+ kdbus_printf("--- error when saying hello: %d (%m)\n", ret); |
25121 |
-+ return NULL; |
25122 |
-+ } |
25123 |
-+ kdbus_printf("-- Our peer ID for %s: %llu -- bus uuid: '%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'\n", |
25124 |
-+ path, (unsigned long long)h.hello.id, |
25125 |
-+ h.hello.id128[0], h.hello.id128[1], h.hello.id128[2], |
25126 |
-+ h.hello.id128[3], h.hello.id128[4], h.hello.id128[5], |
25127 |
-+ h.hello.id128[6], h.hello.id128[7], h.hello.id128[8], |
25128 |
-+ h.hello.id128[9], h.hello.id128[10], h.hello.id128[11], |
25129 |
-+ h.hello.id128[12], h.hello.id128[13], h.hello.id128[14], |
25130 |
-+ h.hello.id128[15]); |
25131 |
-+ |
25132 |
-+ cmd_free.size = sizeof(cmd_free); |
25133 |
-+ cmd_free.offset = h.hello.offset; |
25134 |
-+ kdbus_cmd_free(fd, &cmd_free); |
25135 |
-+ |
25136 |
-+ conn = malloc(sizeof(*conn)); |
25137 |
-+ if (!conn) { |
25138 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25139 |
-+ return NULL; |
25140 |
-+ } |
25141 |
-+ |
25142 |
-+ conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
25143 |
-+ if (conn->buf == MAP_FAILED) { |
25144 |
-+ free(conn); |
25145 |
-+ close(fd); |
25146 |
-+ kdbus_printf("--- error mmap (%m)\n"); |
25147 |
-+ return NULL; |
25148 |
-+ } |
25149 |
-+ |
25150 |
-+ conn->fd = fd; |
25151 |
-+ conn->id = h.hello.id; |
25152 |
-+ return conn; |
25153 |
-+} |
25154 |
-+ |
25155 |
-+struct kdbus_conn * |
25156 |
-+kdbus_hello_registrar(const char *path, const char *name, |
25157 |
-+ const struct kdbus_policy_access *access, |
25158 |
-+ size_t num_access, uint64_t flags) |
25159 |
-+{ |
25160 |
-+ struct kdbus_item *item, *items; |
25161 |
-+ size_t i, size; |
25162 |
-+ |
25163 |
-+ size = KDBUS_ITEM_SIZE(strlen(name) + 1) + |
25164 |
-+ num_access * KDBUS_ITEM_SIZE(sizeof(*access)); |
25165 |
-+ |
25166 |
-+ items = alloca(size); |
25167 |
-+ |
25168 |
-+ item = items; |
25169 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25170 |
-+ item->type = KDBUS_ITEM_NAME; |
25171 |
-+ strcpy(item->str, name); |
25172 |
-+ item = KDBUS_ITEM_NEXT(item); |
25173 |
-+ |
25174 |
-+ for (i = 0; i < num_access; i++) { |
25175 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
25176 |
-+ sizeof(struct kdbus_policy_access); |
25177 |
-+ item->type = KDBUS_ITEM_POLICY_ACCESS; |
25178 |
-+ |
25179 |
-+ item->policy_access.type = access[i].type; |
25180 |
-+ item->policy_access.access = access[i].access; |
25181 |
-+ item->policy_access.id = access[i].id; |
25182 |
-+ |
25183 |
-+ item = KDBUS_ITEM_NEXT(item); |
25184 |
-+ } |
25185 |
-+ |
25186 |
-+ return kdbus_hello(path, flags, items, size); |
25187 |
-+} |
25188 |
-+ |
25189 |
-+struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, |
25190 |
-+ const struct kdbus_policy_access *access, |
25191 |
-+ size_t num_access) |
25192 |
-+{ |
25193 |
-+ return kdbus_hello_registrar(path, name, access, num_access, |
25194 |
-+ KDBUS_HELLO_ACTIVATOR); |
25195 |
-+} |
25196 |
-+ |
25197 |
-+bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type) |
25198 |
-+{ |
25199 |
-+ const struct kdbus_item *item; |
25200 |
-+ |
25201 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) |
25202 |
-+ if (item->type == type) |
25203 |
-+ return true; |
25204 |
-+ |
25205 |
-+ return false; |
25206 |
-+} |
25207 |
-+ |
25208 |
-+int kdbus_bus_creator_info(struct kdbus_conn *conn, |
25209 |
-+ uint64_t flags, |
25210 |
-+ uint64_t *offset) |
25211 |
-+{ |
25212 |
-+ struct kdbus_cmd_info *cmd; |
25213 |
-+ size_t size = sizeof(*cmd); |
25214 |
-+ int ret; |
25215 |
-+ |
25216 |
-+ cmd = alloca(size); |
25217 |
-+ memset(cmd, 0, size); |
25218 |
-+ cmd->size = size; |
25219 |
-+ cmd->attach_flags = flags; |
25220 |
-+ |
25221 |
-+ ret = kdbus_cmd_bus_creator_info(conn->fd, cmd); |
25222 |
-+ if (ret < 0) { |
25223 |
-+ kdbus_printf("--- error when requesting info: %d (%m)\n", ret); |
25224 |
-+ return ret; |
25225 |
-+ } |
25226 |
-+ |
25227 |
-+ if (offset) |
25228 |
-+ *offset = cmd->offset; |
25229 |
-+ else |
25230 |
-+ kdbus_free(conn, cmd->offset); |
25231 |
-+ |
25232 |
-+ return 0; |
25233 |
-+} |
25234 |
-+ |
25235 |
-+int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, |
25236 |
-+ const char *name, uint64_t flags, |
25237 |
-+ uint64_t *offset) |
25238 |
-+{ |
25239 |
-+ struct kdbus_cmd_info *cmd; |
25240 |
-+ size_t size = sizeof(*cmd); |
25241 |
-+ struct kdbus_info *info; |
25242 |
-+ int ret; |
25243 |
-+ |
25244 |
-+ if (name) |
25245 |
-+ size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25246 |
-+ |
25247 |
-+ cmd = alloca(size); |
25248 |
-+ memset(cmd, 0, size); |
25249 |
-+ cmd->size = size; |
25250 |
-+ cmd->attach_flags = flags; |
25251 |
-+ |
25252 |
-+ if (name) { |
25253 |
-+ cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25254 |
-+ cmd->items[0].type = KDBUS_ITEM_NAME; |
25255 |
-+ strcpy(cmd->items[0].str, name); |
25256 |
-+ } else { |
25257 |
-+ cmd->id = id; |
25258 |
-+ } |
25259 |
-+ |
25260 |
-+ ret = kdbus_cmd_conn_info(conn->fd, cmd); |
25261 |
-+ if (ret < 0) { |
25262 |
-+ kdbus_printf("--- error when requesting info: %d (%m)\n", ret); |
25263 |
-+ return ret; |
25264 |
-+ } |
25265 |
-+ |
25266 |
-+ info = (struct kdbus_info *) (conn->buf + cmd->offset); |
25267 |
-+ if (info->size != cmd->info_size) { |
25268 |
-+ kdbus_printf("%s(): size mismatch: %d != %d\n", __func__, |
25269 |
-+ (int) info->size, (int) cmd->info_size); |
25270 |
-+ return -EIO; |
25271 |
-+ } |
25272 |
-+ |
25273 |
-+ if (offset) |
25274 |
-+ *offset = cmd->offset; |
25275 |
-+ else |
25276 |
-+ kdbus_free(conn, cmd->offset); |
25277 |
-+ |
25278 |
-+ return 0; |
25279 |
-+} |
25280 |
-+ |
25281 |
-+void kdbus_conn_free(struct kdbus_conn *conn) |
25282 |
-+{ |
25283 |
-+ if (!conn) |
25284 |
-+ return; |
25285 |
-+ |
25286 |
-+ if (conn->buf) |
25287 |
-+ munmap(conn->buf, POOL_SIZE); |
25288 |
-+ |
25289 |
-+ if (conn->fd >= 0) |
25290 |
-+ close(conn->fd); |
25291 |
-+ |
25292 |
-+ free(conn); |
25293 |
-+} |
25294 |
-+ |
25295 |
-+int sys_memfd_create(const char *name, __u64 size) |
25296 |
-+{ |
25297 |
-+ int ret, fd; |
25298 |
-+ |
25299 |
-+ fd = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING); |
25300 |
-+ if (fd < 0) |
25301 |
-+ return fd; |
25302 |
-+ |
25303 |
-+ ret = ftruncate(fd, size); |
25304 |
-+ if (ret < 0) { |
25305 |
-+ close(fd); |
25306 |
-+ return ret; |
25307 |
-+ } |
25308 |
-+ |
25309 |
-+ return fd; |
25310 |
-+} |
25311 |
-+ |
25312 |
-+int sys_memfd_seal_set(int fd) |
25313 |
-+{ |
25314 |
-+ return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | |
25315 |
-+ F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); |
25316 |
-+} |
25317 |
-+ |
25318 |
-+off_t sys_memfd_get_size(int fd, off_t *size) |
25319 |
-+{ |
25320 |
-+ struct stat stat; |
25321 |
-+ int ret; |
25322 |
-+ |
25323 |
-+ ret = fstat(fd, &stat); |
25324 |
-+ if (ret < 0) { |
25325 |
-+ kdbus_printf("stat() failed: %m\n"); |
25326 |
-+ return ret; |
25327 |
-+ } |
25328 |
-+ |
25329 |
-+ *size = stat.st_size; |
25330 |
-+ return 0; |
25331 |
-+} |
25332 |
-+ |
25333 |
-+static int __kdbus_msg_send(const struct kdbus_conn *conn, |
25334 |
-+ const char *name, |
25335 |
-+ uint64_t cookie, |
25336 |
-+ uint64_t flags, |
25337 |
-+ uint64_t timeout, |
25338 |
-+ int64_t priority, |
25339 |
-+ uint64_t dst_id, |
25340 |
-+ uint64_t cmd_flags, |
25341 |
-+ int cancel_fd) |
25342 |
-+{ |
25343 |
-+ struct kdbus_cmd_send *cmd = NULL; |
25344 |
-+ struct kdbus_msg *msg = NULL; |
25345 |
-+ const char ref1[1024 * 128 + 3] = "0123456789_0"; |
25346 |
-+ const char ref2[] = "0123456789_1"; |
25347 |
-+ struct kdbus_item *item; |
25348 |
-+ struct timespec now; |
25349 |
-+ uint64_t size; |
25350 |
-+ int memfd = -1; |
25351 |
-+ int ret; |
25352 |
-+ |
25353 |
-+ size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25354 |
-+ |
25355 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
25356 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
25357 |
-+ else { |
25358 |
-+ memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024); |
25359 |
-+ if (memfd < 0) { |
25360 |
-+ kdbus_printf("failed to create memfd: %m\n"); |
25361 |
-+ return memfd; |
25362 |
-+ } |
25363 |
-+ |
25364 |
-+ if (write(memfd, "kdbus memfd 1234567", 19) != 19) { |
25365 |
-+ ret = -errno; |
25366 |
-+ kdbus_printf("writing to memfd failed: %m\n"); |
25367 |
-+ goto out; |
25368 |
-+ } |
25369 |
-+ |
25370 |
-+ ret = sys_memfd_seal_set(memfd); |
25371 |
-+ if (ret < 0) { |
25372 |
-+ ret = -errno; |
25373 |
-+ kdbus_printf("memfd sealing failed: %m\n"); |
25374 |
-+ goto out; |
25375 |
-+ } |
25376 |
-+ |
25377 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
25378 |
-+ } |
25379 |
-+ |
25380 |
-+ if (name) |
25381 |
-+ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
25382 |
-+ |
25383 |
-+ msg = malloc(size); |
25384 |
-+ if (!msg) { |
25385 |
-+ ret = -errno; |
25386 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25387 |
-+ goto out; |
25388 |
-+ } |
25389 |
-+ |
25390 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
25391 |
-+ flags |= KDBUS_MSG_SIGNAL; |
25392 |
-+ |
25393 |
-+ memset(msg, 0, size); |
25394 |
-+ msg->flags = flags; |
25395 |
-+ msg->priority = priority; |
25396 |
-+ msg->size = size; |
25397 |
-+ msg->src_id = conn->id; |
25398 |
-+ msg->dst_id = name ? 0 : dst_id; |
25399 |
-+ msg->cookie = cookie; |
25400 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
25401 |
-+ |
25402 |
-+ if (timeout) { |
25403 |
-+ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); |
25404 |
-+ if (ret < 0) |
25405 |
-+ goto out; |
25406 |
-+ |
25407 |
-+ msg->timeout_ns = now.tv_sec * 1000000000ULL + |
25408 |
-+ now.tv_nsec + timeout; |
25409 |
-+ } |
25410 |
-+ |
25411 |
-+ item = msg->items; |
25412 |
-+ |
25413 |
-+ if (name) { |
25414 |
-+ item->type = KDBUS_ITEM_DST_NAME; |
25415 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25416 |
-+ strcpy(item->str, name); |
25417 |
-+ item = KDBUS_ITEM_NEXT(item); |
25418 |
-+ } |
25419 |
-+ |
25420 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25421 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25422 |
-+ item->vec.address = (uintptr_t)&ref1; |
25423 |
-+ item->vec.size = sizeof(ref1); |
25424 |
-+ item = KDBUS_ITEM_NEXT(item); |
25425 |
-+ |
25426 |
-+ /* data padding for ref1 */ |
25427 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25428 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25429 |
-+ item->vec.address = (uintptr_t)NULL; |
25430 |
-+ item->vec.size = KDBUS_ALIGN8(sizeof(ref1)) - sizeof(ref1); |
25431 |
-+ item = KDBUS_ITEM_NEXT(item); |
25432 |
-+ |
25433 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25434 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25435 |
-+ item->vec.address = (uintptr_t)&ref2; |
25436 |
-+ item->vec.size = sizeof(ref2); |
25437 |
-+ item = KDBUS_ITEM_NEXT(item); |
25438 |
-+ |
25439 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
25440 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
25441 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
25442 |
-+ item->bloom_filter.generation = 0; |
25443 |
-+ } else { |
25444 |
-+ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
25445 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd); |
25446 |
-+ item->memfd.size = 16; |
25447 |
-+ item->memfd.fd = memfd; |
25448 |
-+ } |
25449 |
-+ item = KDBUS_ITEM_NEXT(item); |
25450 |
-+ |
25451 |
-+ size = sizeof(*cmd); |
25452 |
-+ if (cancel_fd != -1) |
25453 |
-+ size += KDBUS_ITEM_SIZE(sizeof(cancel_fd)); |
25454 |
-+ |
25455 |
-+ cmd = malloc(size); |
25456 |
-+ if (!cmd) { |
25457 |
-+ ret = -errno; |
25458 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25459 |
-+ goto out; |
25460 |
-+ } |
25461 |
-+ |
25462 |
-+ cmd->size = size; |
25463 |
-+ cmd->flags = cmd_flags; |
25464 |
-+ cmd->msg_address = (uintptr_t)msg; |
25465 |
-+ |
25466 |
-+ item = cmd->items; |
25467 |
-+ |
25468 |
-+ if (cancel_fd != -1) { |
25469 |
-+ item->type = KDBUS_ITEM_CANCEL_FD; |
25470 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(cancel_fd); |
25471 |
-+ item->fds[0] = cancel_fd; |
25472 |
-+ item = KDBUS_ITEM_NEXT(item); |
25473 |
-+ } |
25474 |
-+ |
25475 |
-+ ret = kdbus_cmd_send(conn->fd, cmd); |
25476 |
-+ if (ret < 0) { |
25477 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
25478 |
-+ goto out; |
25479 |
-+ } |
25480 |
-+ |
25481 |
-+ if (cmd_flags & KDBUS_SEND_SYNC_REPLY) { |
25482 |
-+ struct kdbus_msg *reply; |
25483 |
-+ |
25484 |
-+ kdbus_printf("SYNC REPLY @offset %llu:\n", cmd->reply.offset); |
25485 |
-+ reply = (struct kdbus_msg *)(conn->buf + cmd->reply.offset); |
25486 |
-+ kdbus_msg_dump(conn, reply); |
25487 |
-+ |
25488 |
-+ kdbus_msg_free(reply); |
25489 |
-+ |
25490 |
-+ ret = kdbus_free(conn, cmd->reply.offset); |
25491 |
-+ if (ret < 0) |
25492 |
-+ goto out; |
25493 |
-+ } |
25494 |
-+ |
25495 |
-+out: |
25496 |
-+ free(msg); |
25497 |
-+ free(cmd); |
25498 |
-+ |
25499 |
-+ if (memfd >= 0) |
25500 |
-+ close(memfd); |
25501 |
-+ |
25502 |
-+ return ret < 0 ? ret : 0; |
25503 |
-+} |
25504 |
-+ |
25505 |
-+int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, |
25506 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
25507 |
-+ int64_t priority, uint64_t dst_id) |
25508 |
-+{ |
25509 |
-+ return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority, |
25510 |
-+ dst_id, 0, -1); |
25511 |
-+} |
25512 |
-+ |
25513 |
-+int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, |
25514 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
25515 |
-+ int64_t priority, uint64_t dst_id, int cancel_fd) |
25516 |
-+{ |
25517 |
-+ return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority, |
25518 |
-+ dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd); |
25519 |
-+} |
25520 |
-+ |
25521 |
-+int kdbus_msg_send_reply(const struct kdbus_conn *conn, |
25522 |
-+ uint64_t reply_cookie, |
25523 |
-+ uint64_t dst_id) |
25524 |
-+{ |
25525 |
-+ struct kdbus_cmd_send cmd = {}; |
25526 |
-+ struct kdbus_msg *msg; |
25527 |
-+ const char ref1[1024 * 128 + 3] = "0123456789_0"; |
25528 |
-+ struct kdbus_item *item; |
25529 |
-+ uint64_t size; |
25530 |
-+ int ret; |
25531 |
-+ |
25532 |
-+ size = sizeof(struct kdbus_msg); |
25533 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25534 |
-+ |
25535 |
-+ msg = malloc(size); |
25536 |
-+ if (!msg) { |
25537 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25538 |
-+ return -ENOMEM; |
25539 |
-+ } |
25540 |
-+ |
25541 |
-+ memset(msg, 0, size); |
25542 |
-+ msg->size = size; |
25543 |
-+ msg->src_id = conn->id; |
25544 |
-+ msg->dst_id = dst_id; |
25545 |
-+ msg->cookie_reply = reply_cookie; |
25546 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
25547 |
-+ |
25548 |
-+ item = msg->items; |
25549 |
-+ |
25550 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25551 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25552 |
-+ item->vec.address = (uintptr_t)&ref1; |
25553 |
-+ item->vec.size = sizeof(ref1); |
25554 |
-+ item = KDBUS_ITEM_NEXT(item); |
25555 |
-+ |
25556 |
-+ cmd.size = sizeof(cmd); |
25557 |
-+ cmd.msg_address = (uintptr_t)msg; |
25558 |
-+ |
25559 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
25560 |
-+ if (ret < 0) |
25561 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
25562 |
-+ |
25563 |
-+ free(msg); |
25564 |
-+ |
25565 |
-+ return ret; |
25566 |
-+} |
25567 |
-+ |
25568 |
-+static char *msg_id(uint64_t id, char *buf) |
25569 |
-+{ |
25570 |
-+ if (id == 0) |
25571 |
-+ return "KERNEL"; |
25572 |
-+ if (id == ~0ULL) |
25573 |
-+ return "BROADCAST"; |
25574 |
-+ sprintf(buf, "%llu", (unsigned long long)id); |
25575 |
-+ return buf; |
25576 |
-+} |
25577 |
-+ |
25578 |
-+int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg) |
25579 |
-+{ |
25580 |
-+ const struct kdbus_item *item = msg->items; |
25581 |
-+ char buf_src[32]; |
25582 |
-+ char buf_dst[32]; |
25583 |
-+ uint64_t timeout = 0; |
25584 |
-+ uint64_t cookie_reply = 0; |
25585 |
-+ int ret = 0; |
25586 |
-+ |
25587 |
-+ if (msg->flags & KDBUS_MSG_EXPECT_REPLY) |
25588 |
-+ timeout = msg->timeout_ns; |
25589 |
-+ else |
25590 |
-+ cookie_reply = msg->cookie_reply; |
25591 |
-+ |
25592 |
-+ kdbus_printf("MESSAGE: %s (%llu bytes) flags=0x%08llx, %s → %s, " |
25593 |
-+ "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n", |
25594 |
-+ enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size, |
25595 |
-+ (unsigned long long)msg->flags, |
25596 |
-+ msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst), |
25597 |
-+ (unsigned long long)msg->cookie, (unsigned long long)timeout, |
25598 |
-+ (unsigned long long)cookie_reply, (long long)msg->priority); |
25599 |
-+ |
25600 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
25601 |
-+ if (item->size < KDBUS_ITEM_HEADER_SIZE) { |
25602 |
-+ kdbus_printf(" +%s (%llu bytes) invalid data record\n", |
25603 |
-+ enum_MSG(item->type), item->size); |
25604 |
-+ ret = -EINVAL; |
25605 |
-+ break; |
25606 |
-+ } |
25607 |
-+ |
25608 |
-+ switch (item->type) { |
25609 |
-+ case KDBUS_ITEM_PAYLOAD_OFF: { |
25610 |
-+ char *s; |
25611 |
-+ |
25612 |
-+ if (item->vec.offset == ~0ULL) |
25613 |
-+ s = "[\\0-bytes]"; |
25614 |
-+ else |
25615 |
-+ s = (char *)msg + item->vec.offset; |
25616 |
-+ |
25617 |
-+ kdbus_printf(" +%s (%llu bytes) off=%llu size=%llu '%s'\n", |
25618 |
-+ enum_MSG(item->type), item->size, |
25619 |
-+ (unsigned long long)item->vec.offset, |
25620 |
-+ (unsigned long long)item->vec.size, s); |
25621 |
-+ break; |
25622 |
-+ } |
25623 |
-+ |
25624 |
-+ case KDBUS_ITEM_FDS: { |
25625 |
-+ int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25626 |
-+ sizeof(int); |
25627 |
-+ |
25628 |
-+ kdbus_printf(" +%s (%llu bytes, %d fds)\n", |
25629 |
-+ enum_MSG(item->type), item->size, n); |
25630 |
-+ |
25631 |
-+ for (i = 0; i < n; i++) |
25632 |
-+ kdbus_printf(" fd[%d] = %d\n", |
25633 |
-+ i, item->fds[i]); |
25634 |
-+ |
25635 |
-+ break; |
25636 |
-+ } |
25637 |
-+ |
25638 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
25639 |
-+ char *buf; |
25640 |
-+ off_t size; |
25641 |
-+ |
25642 |
-+ buf = mmap(NULL, item->memfd.size, PROT_READ, |
25643 |
-+ MAP_PRIVATE, item->memfd.fd, 0); |
25644 |
-+ if (buf == MAP_FAILED) { |
25645 |
-+ kdbus_printf("mmap() fd=%i size=%llu failed: %m\n", |
25646 |
-+ item->memfd.fd, item->memfd.size); |
25647 |
-+ break; |
25648 |
-+ } |
25649 |
-+ |
25650 |
-+ if (sys_memfd_get_size(item->memfd.fd, &size) < 0) { |
25651 |
-+ kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n"); |
25652 |
-+ break; |
25653 |
-+ } |
25654 |
-+ |
25655 |
-+ kdbus_printf(" +%s (%llu bytes) fd=%i size=%llu filesize=%llu '%s'\n", |
25656 |
-+ enum_MSG(item->type), item->size, item->memfd.fd, |
25657 |
-+ (unsigned long long)item->memfd.size, |
25658 |
-+ (unsigned long long)size, buf); |
25659 |
-+ munmap(buf, item->memfd.size); |
25660 |
-+ break; |
25661 |
-+ } |
25662 |
-+ |
25663 |
-+ case KDBUS_ITEM_CREDS: |
25664 |
-+ kdbus_printf(" +%s (%llu bytes) uid=%lld, euid=%lld, suid=%lld, fsuid=%lld, " |
25665 |
-+ "gid=%lld, egid=%lld, sgid=%lld, fsgid=%lld\n", |
25666 |
-+ enum_MSG(item->type), item->size, |
25667 |
-+ item->creds.uid, item->creds.euid, |
25668 |
-+ item->creds.suid, item->creds.fsuid, |
25669 |
-+ item->creds.gid, item->creds.egid, |
25670 |
-+ item->creds.sgid, item->creds.fsgid); |
25671 |
-+ break; |
25672 |
-+ |
25673 |
-+ case KDBUS_ITEM_PIDS: |
25674 |
-+ kdbus_printf(" +%s (%llu bytes) pid=%lld, tid=%lld, ppid=%lld\n", |
25675 |
-+ enum_MSG(item->type), item->size, |
25676 |
-+ item->pids.pid, item->pids.tid, |
25677 |
-+ item->pids.ppid); |
25678 |
-+ break; |
25679 |
-+ |
25680 |
-+ case KDBUS_ITEM_AUXGROUPS: { |
25681 |
-+ int i, n; |
25682 |
-+ |
25683 |
-+ kdbus_printf(" +%s (%llu bytes)\n", |
25684 |
-+ enum_MSG(item->type), item->size); |
25685 |
-+ n = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25686 |
-+ sizeof(uint64_t); |
25687 |
-+ |
25688 |
-+ for (i = 0; i < n; i++) |
25689 |
-+ kdbus_printf(" gid[%d] = %lld\n", |
25690 |
-+ i, item->data64[i]); |
25691 |
-+ break; |
25692 |
-+ } |
25693 |
-+ |
25694 |
-+ case KDBUS_ITEM_NAME: |
25695 |
-+ case KDBUS_ITEM_PID_COMM: |
25696 |
-+ case KDBUS_ITEM_TID_COMM: |
25697 |
-+ case KDBUS_ITEM_EXE: |
25698 |
-+ case KDBUS_ITEM_CGROUP: |
25699 |
-+ case KDBUS_ITEM_SECLABEL: |
25700 |
-+ case KDBUS_ITEM_DST_NAME: |
25701 |
-+ case KDBUS_ITEM_CONN_DESCRIPTION: |
25702 |
-+ kdbus_printf(" +%s (%llu bytes) '%s' (%zu)\n", |
25703 |
-+ enum_MSG(item->type), item->size, |
25704 |
-+ item->str, strlen(item->str)); |
25705 |
-+ break; |
25706 |
-+ |
25707 |
-+ case KDBUS_ITEM_OWNED_NAME: { |
25708 |
-+ kdbus_printf(" +%s (%llu bytes) '%s' (%zu) flags=0x%08llx\n", |
25709 |
-+ enum_MSG(item->type), item->size, |
25710 |
-+ item->name.name, strlen(item->name.name), |
25711 |
-+ item->name.flags); |
25712 |
-+ break; |
25713 |
-+ } |
25714 |
-+ |
25715 |
-+ case KDBUS_ITEM_CMDLINE: { |
25716 |
-+ size_t size = item->size - KDBUS_ITEM_HEADER_SIZE; |
25717 |
-+ const char *str = item->str; |
25718 |
-+ int count = 0; |
25719 |
-+ |
25720 |
-+ kdbus_printf(" +%s (%llu bytes) ", |
25721 |
-+ enum_MSG(item->type), item->size); |
25722 |
-+ while (size) { |
25723 |
-+ kdbus_printf("'%s' ", str); |
25724 |
-+ size -= strlen(str) + 1; |
25725 |
-+ str += strlen(str) + 1; |
25726 |
-+ count++; |
25727 |
-+ } |
25728 |
-+ |
25729 |
-+ kdbus_printf("(%d string%s)\n", |
25730 |
-+ count, (count == 1) ? "" : "s"); |
25731 |
-+ break; |
25732 |
-+ } |
25733 |
-+ |
25734 |
-+ case KDBUS_ITEM_AUDIT: |
25735 |
-+ kdbus_printf(" +%s (%llu bytes) loginuid=%u sessionid=%u\n", |
25736 |
-+ enum_MSG(item->type), item->size, |
25737 |
-+ item->audit.loginuid, item->audit.sessionid); |
25738 |
-+ break; |
25739 |
-+ |
25740 |
-+ case KDBUS_ITEM_CAPS: { |
25741 |
-+ const uint32_t *cap; |
25742 |
-+ int n, i; |
25743 |
-+ |
25744 |
-+ kdbus_printf(" +%s (%llu bytes) len=%llu bytes, last_cap %d\n", |
25745 |
-+ enum_MSG(item->type), item->size, |
25746 |
-+ (unsigned long long)item->size - |
25747 |
-+ KDBUS_ITEM_HEADER_SIZE, |
25748 |
-+ (int) item->caps.last_cap); |
25749 |
-+ |
25750 |
-+ cap = item->caps.caps; |
25751 |
-+ n = (item->size - offsetof(struct kdbus_item, caps.caps)) |
25752 |
-+ / 4 / sizeof(uint32_t); |
25753 |
-+ |
25754 |
-+ kdbus_printf(" CapInh="); |
25755 |
-+ for (i = 0; i < n; i++) |
25756 |
-+ kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]); |
25757 |
-+ |
25758 |
-+ kdbus_printf(" CapPrm="); |
25759 |
-+ for (i = 0; i < n; i++) |
25760 |
-+ kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]); |
25761 |
-+ |
25762 |
-+ kdbus_printf(" CapEff="); |
25763 |
-+ for (i = 0; i < n; i++) |
25764 |
-+ kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]); |
25765 |
-+ |
25766 |
-+ kdbus_printf(" CapBnd="); |
25767 |
-+ for (i = 0; i < n; i++) |
25768 |
-+ kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]); |
25769 |
-+ kdbus_printf("\n"); |
25770 |
-+ break; |
25771 |
-+ } |
25772 |
-+ |
25773 |
-+ case KDBUS_ITEM_TIMESTAMP: |
25774 |
-+ kdbus_printf(" +%s (%llu bytes) seq=%llu realtime=%lluns monotonic=%lluns\n", |
25775 |
-+ enum_MSG(item->type), item->size, |
25776 |
-+ (unsigned long long)item->timestamp.seqnum, |
25777 |
-+ (unsigned long long)item->timestamp.realtime_ns, |
25778 |
-+ (unsigned long long)item->timestamp.monotonic_ns); |
25779 |
-+ break; |
25780 |
-+ |
25781 |
-+ case KDBUS_ITEM_REPLY_TIMEOUT: |
25782 |
-+ kdbus_printf(" +%s (%llu bytes) cookie=%llu\n", |
25783 |
-+ enum_MSG(item->type), item->size, |
25784 |
-+ msg->cookie_reply); |
25785 |
-+ break; |
25786 |
-+ |
25787 |
-+ case KDBUS_ITEM_NAME_ADD: |
25788 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
25789 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
25790 |
-+ kdbus_printf(" +%s (%llu bytes) '%s', old id=%lld, now id=%lld, old_flags=0x%llx new_flags=0x%llx\n", |
25791 |
-+ enum_MSG(item->type), |
25792 |
-+ (unsigned long long) item->size, |
25793 |
-+ item->name_change.name, |
25794 |
-+ item->name_change.old_id.id, |
25795 |
-+ item->name_change.new_id.id, |
25796 |
-+ item->name_change.old_id.flags, |
25797 |
-+ item->name_change.new_id.flags); |
25798 |
-+ break; |
25799 |
-+ |
25800 |
-+ case KDBUS_ITEM_ID_ADD: |
25801 |
-+ case KDBUS_ITEM_ID_REMOVE: |
25802 |
-+ kdbus_printf(" +%s (%llu bytes) id=%llu flags=%llu\n", |
25803 |
-+ enum_MSG(item->type), |
25804 |
-+ (unsigned long long) item->size, |
25805 |
-+ (unsigned long long) item->id_change.id, |
25806 |
-+ (unsigned long long) item->id_change.flags); |
25807 |
-+ break; |
25808 |
-+ |
25809 |
-+ default: |
25810 |
-+ kdbus_printf(" +%s (%llu bytes)\n", |
25811 |
-+ enum_MSG(item->type), item->size); |
25812 |
-+ break; |
25813 |
-+ } |
25814 |
-+ } |
25815 |
-+ |
25816 |
-+ if ((char *)item - ((char *)msg + msg->size) >= 8) { |
25817 |
-+ kdbus_printf("invalid padding at end of message\n"); |
25818 |
-+ ret = -EINVAL; |
25819 |
-+ } |
25820 |
-+ |
25821 |
-+ kdbus_printf("\n"); |
25822 |
-+ |
25823 |
-+ return ret; |
25824 |
-+} |
25825 |
-+ |
25826 |
-+void kdbus_msg_free(struct kdbus_msg *msg) |
25827 |
-+{ |
25828 |
-+ const struct kdbus_item *item; |
25829 |
-+ int nfds, i; |
25830 |
-+ |
25831 |
-+ if (!msg) |
25832 |
-+ return; |
25833 |
-+ |
25834 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
25835 |
-+ switch (item->type) { |
25836 |
-+ /* close all memfds */ |
25837 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: |
25838 |
-+ close(item->memfd.fd); |
25839 |
-+ break; |
25840 |
-+ case KDBUS_ITEM_FDS: |
25841 |
-+ nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25842 |
-+ sizeof(int); |
25843 |
-+ |
25844 |
-+ for (i = 0; i < nfds; i++) |
25845 |
-+ close(item->fds[i]); |
25846 |
-+ |
25847 |
-+ break; |
25848 |
-+ } |
25849 |
-+ } |
25850 |
-+} |
25851 |
-+ |
25852 |
-+int kdbus_msg_recv(struct kdbus_conn *conn, |
25853 |
-+ struct kdbus_msg **msg_out, |
25854 |
-+ uint64_t *offset) |
25855 |
-+{ |
25856 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
25857 |
-+ struct kdbus_msg *msg; |
25858 |
-+ int ret; |
25859 |
-+ |
25860 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
25861 |
-+ if (ret < 0) |
25862 |
-+ return ret; |
25863 |
-+ |
25864 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
25865 |
-+ ret = kdbus_msg_dump(conn, msg); |
25866 |
-+ if (ret < 0) { |
25867 |
-+ kdbus_msg_free(msg); |
25868 |
-+ return ret; |
25869 |
-+ } |
25870 |
-+ |
25871 |
-+ if (msg_out) { |
25872 |
-+ *msg_out = msg; |
25873 |
-+ |
25874 |
-+ if (offset) |
25875 |
-+ *offset = recv.msg.offset; |
25876 |
-+ } else { |
25877 |
-+ kdbus_msg_free(msg); |
25878 |
-+ |
25879 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
25880 |
-+ if (ret < 0) |
25881 |
-+ return ret; |
25882 |
-+ } |
25883 |
-+ |
25884 |
-+ return 0; |
25885 |
-+} |
25886 |
-+ |
25887 |
-+/* |
25888 |
-+ * Returns: 0 on success, negative errno on failure. |
25889 |
-+ * |
25890 |
-+ * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors. |
25891 |
-+ * We must return the result of kdbus_msg_recv() |
25892 |
-+ */ |
25893 |
-+int kdbus_msg_recv_poll(struct kdbus_conn *conn, |
25894 |
-+ int timeout_ms, |
25895 |
-+ struct kdbus_msg **msg_out, |
25896 |
-+ uint64_t *offset) |
25897 |
-+{ |
25898 |
-+ int ret; |
25899 |
-+ |
25900 |
-+ do { |
25901 |
-+ struct timeval before, after, diff; |
25902 |
-+ struct pollfd fd; |
25903 |
-+ |
25904 |
-+ fd.fd = conn->fd; |
25905 |
-+ fd.events = POLLIN | POLLPRI | POLLHUP; |
25906 |
-+ fd.revents = 0; |
25907 |
-+ |
25908 |
-+ gettimeofday(&before, NULL); |
25909 |
-+ ret = poll(&fd, 1, timeout_ms); |
25910 |
-+ gettimeofday(&after, NULL); |
25911 |
-+ |
25912 |
-+ if (ret == 0) { |
25913 |
-+ ret = -ETIMEDOUT; |
25914 |
-+ break; |
25915 |
-+ } |
25916 |
-+ |
25917 |
-+ if (ret > 0) { |
25918 |
-+ if (fd.revents & POLLIN) |
25919 |
-+ ret = kdbus_msg_recv(conn, msg_out, offset); |
25920 |
-+ |
25921 |
-+ if (fd.revents & (POLLHUP | POLLERR)) |
25922 |
-+ ret = -ECONNRESET; |
25923 |
-+ } |
25924 |
-+ |
25925 |
-+ if (ret == 0 || ret != -EAGAIN) |
25926 |
-+ break; |
25927 |
-+ |
25928 |
-+ timersub(&after, &before, &diff); |
25929 |
-+ timeout_ms -= diff.tv_sec * 1000UL + |
25930 |
-+ diff.tv_usec / 1000UL; |
25931 |
-+ } while (timeout_ms > 0); |
25932 |
-+ |
25933 |
-+ return ret; |
25934 |
-+} |
25935 |
-+ |
25936 |
-+int kdbus_free(const struct kdbus_conn *conn, uint64_t offset) |
25937 |
-+{ |
25938 |
-+ struct kdbus_cmd_free cmd_free = {}; |
25939 |
-+ int ret; |
25940 |
-+ |
25941 |
-+ cmd_free.size = sizeof(cmd_free); |
25942 |
-+ cmd_free.offset = offset; |
25943 |
-+ cmd_free.flags = 0; |
25944 |
-+ |
25945 |
-+ ret = kdbus_cmd_free(conn->fd, &cmd_free); |
25946 |
-+ if (ret < 0) { |
25947 |
-+ kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret); |
25948 |
-+ return ret; |
25949 |
-+ } |
25950 |
-+ |
25951 |
-+ return 0; |
25952 |
-+} |
25953 |
-+ |
25954 |
-+int kdbus_name_acquire(struct kdbus_conn *conn, |
25955 |
-+ const char *name, uint64_t *flags) |
25956 |
-+{ |
25957 |
-+ struct kdbus_cmd *cmd_name; |
25958 |
-+ size_t name_len = strlen(name) + 1; |
25959 |
-+ uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len); |
25960 |
-+ struct kdbus_item *item; |
25961 |
-+ int ret; |
25962 |
-+ |
25963 |
-+ cmd_name = alloca(size); |
25964 |
-+ |
25965 |
-+ memset(cmd_name, 0, size); |
25966 |
-+ |
25967 |
-+ item = cmd_name->items; |
25968 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + name_len; |
25969 |
-+ item->type = KDBUS_ITEM_NAME; |
25970 |
-+ strcpy(item->str, name); |
25971 |
-+ |
25972 |
-+ cmd_name->size = size; |
25973 |
-+ if (flags) |
25974 |
-+ cmd_name->flags = *flags; |
25975 |
-+ |
25976 |
-+ ret = kdbus_cmd_name_acquire(conn->fd, cmd_name); |
25977 |
-+ if (ret < 0) { |
25978 |
-+ kdbus_printf("error aquiring name: %s\n", strerror(-ret)); |
25979 |
-+ return ret; |
25980 |
-+ } |
25981 |
-+ |
25982 |
-+ kdbus_printf("%s(): flags after call: 0x%llx\n", __func__, |
25983 |
-+ cmd_name->return_flags); |
25984 |
-+ |
25985 |
-+ if (flags) |
25986 |
-+ *flags = cmd_name->return_flags; |
25987 |
-+ |
25988 |
-+ return 0; |
25989 |
-+} |
25990 |
-+ |
25991 |
-+int kdbus_name_release(struct kdbus_conn *conn, const char *name) |
25992 |
-+{ |
25993 |
-+ struct kdbus_cmd *cmd_name; |
25994 |
-+ size_t name_len = strlen(name) + 1; |
25995 |
-+ uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len); |
25996 |
-+ struct kdbus_item *item; |
25997 |
-+ int ret; |
25998 |
-+ |
25999 |
-+ cmd_name = alloca(size); |
26000 |
-+ |
26001 |
-+ memset(cmd_name, 0, size); |
26002 |
-+ |
26003 |
-+ item = cmd_name->items; |
26004 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + name_len; |
26005 |
-+ item->type = KDBUS_ITEM_NAME; |
26006 |
-+ strcpy(item->str, name); |
26007 |
-+ |
26008 |
-+ cmd_name->size = size; |
26009 |
-+ |
26010 |
-+ kdbus_printf("conn %lld giving up name '%s'\n", |
26011 |
-+ (unsigned long long) conn->id, name); |
26012 |
-+ |
26013 |
-+ ret = kdbus_cmd_name_release(conn->fd, cmd_name); |
26014 |
-+ if (ret < 0) { |
26015 |
-+ kdbus_printf("error releasing name: %s\n", strerror(-ret)); |
26016 |
-+ return ret; |
26017 |
-+ } |
26018 |
-+ |
26019 |
-+ return 0; |
26020 |
-+} |
26021 |
-+ |
26022 |
-+int kdbus_list(struct kdbus_conn *conn, uint64_t flags) |
26023 |
-+{ |
26024 |
-+ struct kdbus_cmd_list cmd_list = {}; |
26025 |
-+ struct kdbus_info *list, *name; |
26026 |
-+ int ret; |
26027 |
-+ |
26028 |
-+ cmd_list.size = sizeof(cmd_list); |
26029 |
-+ cmd_list.flags = flags; |
26030 |
-+ |
26031 |
-+ ret = kdbus_cmd_list(conn->fd, &cmd_list); |
26032 |
-+ if (ret < 0) { |
26033 |
-+ kdbus_printf("error listing names: %d (%m)\n", ret); |
26034 |
-+ return ret; |
26035 |
-+ } |
26036 |
-+ |
26037 |
-+ kdbus_printf("REGISTRY:\n"); |
26038 |
-+ list = (struct kdbus_info *)(conn->buf + cmd_list.offset); |
26039 |
-+ |
26040 |
-+ KDBUS_FOREACH(name, list, cmd_list.list_size) { |
26041 |
-+ uint64_t flags = 0; |
26042 |
-+ struct kdbus_item *item; |
26043 |
-+ const char *n = "MISSING-NAME"; |
26044 |
-+ |
26045 |
-+ if (name->size == sizeof(struct kdbus_cmd)) |
26046 |
-+ continue; |
26047 |
-+ |
26048 |
-+ KDBUS_ITEM_FOREACH(item, name, items) |
26049 |
-+ if (item->type == KDBUS_ITEM_OWNED_NAME) { |
26050 |
-+ n = item->name.name; |
26051 |
-+ flags = item->name.flags; |
26052 |
-+ |
26053 |
-+ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n", |
26054 |
-+ name->id, |
26055 |
-+ (unsigned long long) flags, |
26056 |
-+ name->flags, n); |
26057 |
-+ } |
26058 |
-+ } |
26059 |
-+ kdbus_printf("\n"); |
26060 |
-+ |
26061 |
-+ ret = kdbus_free(conn, cmd_list.offset); |
26062 |
-+ |
26063 |
-+ return ret; |
26064 |
-+} |
26065 |
-+ |
26066 |
-+int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, |
26067 |
-+ uint64_t attach_flags_send, |
26068 |
-+ uint64_t attach_flags_recv) |
26069 |
-+{ |
26070 |
-+ int ret; |
26071 |
-+ size_t size; |
26072 |
-+ struct kdbus_cmd *update; |
26073 |
-+ struct kdbus_item *item; |
26074 |
-+ |
26075 |
-+ size = sizeof(struct kdbus_cmd); |
26076 |
-+ size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2; |
26077 |
-+ |
26078 |
-+ update = malloc(size); |
26079 |
-+ if (!update) { |
26080 |
-+ kdbus_printf("error malloc: %m\n"); |
26081 |
-+ return -ENOMEM; |
26082 |
-+ } |
26083 |
-+ |
26084 |
-+ memset(update, 0, size); |
26085 |
-+ update->size = size; |
26086 |
-+ |
26087 |
-+ item = update->items; |
26088 |
-+ |
26089 |
-+ item->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; |
26090 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); |
26091 |
-+ item->data64[0] = attach_flags_send; |
26092 |
-+ item = KDBUS_ITEM_NEXT(item); |
26093 |
-+ |
26094 |
-+ item->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; |
26095 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); |
26096 |
-+ item->data64[0] = attach_flags_recv; |
26097 |
-+ item = KDBUS_ITEM_NEXT(item); |
26098 |
-+ |
26099 |
-+ ret = kdbus_cmd_update(conn->fd, update); |
26100 |
-+ if (ret < 0) |
26101 |
-+ kdbus_printf("error conn update: %d (%m)\n", ret); |
26102 |
-+ |
26103 |
-+ free(update); |
26104 |
-+ |
26105 |
-+ return ret; |
26106 |
-+} |
26107 |
-+ |
26108 |
-+int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, |
26109 |
-+ const struct kdbus_policy_access *access, |
26110 |
-+ size_t num_access) |
26111 |
-+{ |
26112 |
-+ struct kdbus_cmd *update; |
26113 |
-+ struct kdbus_item *item; |
26114 |
-+ size_t i, size; |
26115 |
-+ int ret; |
26116 |
-+ |
26117 |
-+ size = sizeof(struct kdbus_cmd); |
26118 |
-+ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
26119 |
-+ size += num_access * KDBUS_ITEM_SIZE(sizeof(struct kdbus_policy_access)); |
26120 |
-+ |
26121 |
-+ update = malloc(size); |
26122 |
-+ if (!update) { |
26123 |
-+ kdbus_printf("error malloc: %m\n"); |
26124 |
-+ return -ENOMEM; |
26125 |
-+ } |
26126 |
-+ |
26127 |
-+ memset(update, 0, size); |
26128 |
-+ update->size = size; |
26129 |
-+ |
26130 |
-+ item = update->items; |
26131 |
-+ |
26132 |
-+ item->type = KDBUS_ITEM_NAME; |
26133 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
26134 |
-+ strcpy(item->str, name); |
26135 |
-+ item = KDBUS_ITEM_NEXT(item); |
26136 |
-+ |
26137 |
-+ for (i = 0; i < num_access; i++) { |
26138 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
26139 |
-+ sizeof(struct kdbus_policy_access); |
26140 |
-+ item->type = KDBUS_ITEM_POLICY_ACCESS; |
26141 |
-+ |
26142 |
-+ item->policy_access.type = access[i].type; |
26143 |
-+ item->policy_access.access = access[i].access; |
26144 |
-+ item->policy_access.id = access[i].id; |
26145 |
-+ |
26146 |
-+ item = KDBUS_ITEM_NEXT(item); |
26147 |
-+ } |
26148 |
-+ |
26149 |
-+ ret = kdbus_cmd_update(conn->fd, update); |
26150 |
-+ if (ret < 0) |
26151 |
-+ kdbus_printf("error conn update: %d (%m)\n", ret); |
26152 |
-+ |
26153 |
-+ free(update); |
26154 |
-+ |
26155 |
-+ return ret; |
26156 |
-+} |
26157 |
-+ |
26158 |
-+int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, |
26159 |
-+ uint64_t type, uint64_t id) |
26160 |
-+{ |
26161 |
-+ struct { |
26162 |
-+ struct kdbus_cmd_match cmd; |
26163 |
-+ struct { |
26164 |
-+ uint64_t size; |
26165 |
-+ uint64_t type; |
26166 |
-+ struct kdbus_notify_id_change chg; |
26167 |
-+ } item; |
26168 |
-+ } buf; |
26169 |
-+ int ret; |
26170 |
-+ |
26171 |
-+ memset(&buf, 0, sizeof(buf)); |
26172 |
-+ |
26173 |
-+ buf.cmd.size = sizeof(buf); |
26174 |
-+ buf.cmd.cookie = cookie; |
26175 |
-+ buf.item.size = sizeof(buf.item); |
26176 |
-+ buf.item.type = type; |
26177 |
-+ buf.item.chg.id = id; |
26178 |
-+ |
26179 |
-+ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
26180 |
-+ if (ret < 0) |
26181 |
-+ kdbus_printf("--- error adding conn match: %d (%m)\n", ret); |
26182 |
-+ |
26183 |
-+ return ret; |
26184 |
-+} |
26185 |
-+ |
26186 |
-+int kdbus_add_match_empty(struct kdbus_conn *conn) |
26187 |
-+{ |
26188 |
-+ struct { |
26189 |
-+ struct kdbus_cmd_match cmd; |
26190 |
-+ struct kdbus_item item; |
26191 |
-+ } buf; |
26192 |
-+ int ret; |
26193 |
-+ |
26194 |
-+ memset(&buf, 0, sizeof(buf)); |
26195 |
-+ |
26196 |
-+ buf.item.size = sizeof(uint64_t) * 3; |
26197 |
-+ buf.item.type = KDBUS_ITEM_ID; |
26198 |
-+ buf.item.id = KDBUS_MATCH_ID_ANY; |
26199 |
-+ |
26200 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
26201 |
-+ |
26202 |
-+ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
26203 |
-+ if (ret < 0) |
26204 |
-+ kdbus_printf("--- error adding conn match: %d (%m)\n", ret); |
26205 |
-+ |
26206 |
-+ return ret; |
26207 |
-+} |
26208 |
-+ |
26209 |
-+static int all_ids_are_mapped(const char *path) |
26210 |
-+{ |
26211 |
-+ int ret; |
26212 |
-+ FILE *file; |
26213 |
-+ uint32_t inside_id, length; |
26214 |
-+ |
26215 |
-+ file = fopen(path, "r"); |
26216 |
-+ if (!file) { |
26217 |
-+ ret = -errno; |
26218 |
-+ kdbus_printf("error fopen() %s: %d (%m)\n", |
26219 |
-+ path, ret); |
26220 |
-+ return ret; |
26221 |
-+ } |
26222 |
-+ |
26223 |
-+ ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length); |
26224 |
-+ if (ret != 2) { |
26225 |
-+ if (ferror(file)) |
26226 |
-+ ret = -errno; |
26227 |
-+ else |
26228 |
-+ ret = -EIO; |
26229 |
-+ |
26230 |
-+ kdbus_printf("--- error fscanf(): %d\n", ret); |
26231 |
-+ fclose(file); |
26232 |
-+ return ret; |
26233 |
-+ } |
26234 |
-+ |
26235 |
-+ fclose(file); |
26236 |
-+ |
26237 |
-+ /* |
26238 |
-+ * If length is 4294967295 which means the invalid uid |
26239 |
-+ * (uid_t) -1 then we are able to map all uid/gids |
26240 |
-+ */ |
26241 |
-+ if (inside_id == 0 && length == (uid_t) -1) |
26242 |
-+ return 1; |
26243 |
-+ |
26244 |
-+ return 0; |
26245 |
-+} |
26246 |
-+ |
26247 |
-+int all_uids_gids_are_mapped(void) |
26248 |
-+{ |
26249 |
-+ int ret; |
26250 |
-+ |
26251 |
-+ ret = all_ids_are_mapped("/proc/self/uid_map"); |
26252 |
-+ if (ret <= 0) { |
26253 |
-+ kdbus_printf("--- error not all uids are mapped\n"); |
26254 |
-+ return 0; |
26255 |
-+ } |
26256 |
-+ |
26257 |
-+ ret = all_ids_are_mapped("/proc/self/gid_map"); |
26258 |
-+ if (ret <= 0) { |
26259 |
-+ kdbus_printf("--- error not all gids are mapped\n"); |
26260 |
-+ return 0; |
26261 |
-+ } |
26262 |
-+ |
26263 |
-+ return 1; |
26264 |
-+} |
26265 |
-+ |
26266 |
-+int drop_privileges(uid_t uid, gid_t gid) |
26267 |
-+{ |
26268 |
-+ int ret; |
26269 |
-+ |
26270 |
-+ ret = setgroups(0, NULL); |
26271 |
-+ if (ret < 0) { |
26272 |
-+ ret = -errno; |
26273 |
-+ kdbus_printf("error setgroups: %d (%m)\n", ret); |
26274 |
-+ return ret; |
26275 |
-+ } |
26276 |
-+ |
26277 |
-+ ret = setresgid(gid, gid, gid); |
26278 |
-+ if (ret < 0) { |
26279 |
-+ ret = -errno; |
26280 |
-+ kdbus_printf("error setresgid: %d (%m)\n", ret); |
26281 |
-+ return ret; |
26282 |
-+ } |
26283 |
-+ |
26284 |
-+ ret = setresuid(uid, uid, uid); |
26285 |
-+ if (ret < 0) { |
26286 |
-+ ret = -errno; |
26287 |
-+ kdbus_printf("error setresuid: %d (%m)\n", ret); |
26288 |
-+ return ret; |
26289 |
-+ } |
26290 |
-+ |
26291 |
-+ return ret; |
26292 |
-+} |
26293 |
-+ |
26294 |
-+uint64_t now(clockid_t clock) |
26295 |
-+{ |
26296 |
-+ struct timespec spec; |
26297 |
-+ |
26298 |
-+ clock_gettime(clock, &spec); |
26299 |
-+ return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec; |
26300 |
-+} |
26301 |
-+ |
26302 |
-+char *unique_name(const char *prefix) |
26303 |
-+{ |
26304 |
-+ unsigned int i; |
26305 |
-+ uint64_t u_now; |
26306 |
-+ char n[17]; |
26307 |
-+ char *str; |
26308 |
-+ int r; |
26309 |
-+ |
26310 |
-+ /* |
26311 |
-+ * This returns a random string which is guaranteed to be |
26312 |
-+ * globally unique across all calls to unique_name(). We |
26313 |
-+ * compose the string as: |
26314 |
-+ * <prefix>-<random>-<time> |
26315 |
-+ * With: |
26316 |
-+ * <prefix>: string provided by the caller |
26317 |
-+ * <random>: a random alpha string of 16 characters |
26318 |
-+ * <time>: the current time in micro-seconds since last boot |
26319 |
-+ * |
26320 |
-+ * The <random> part makes the string always look vastly different, |
26321 |
-+ * the <time> part makes sure no two calls return the same string. |
26322 |
-+ */ |
26323 |
-+ |
26324 |
-+ u_now = now(CLOCK_MONOTONIC); |
26325 |
-+ |
26326 |
-+ for (i = 0; i < sizeof(n) - 1; ++i) |
26327 |
-+ n[i] = 'a' + (rand() % ('z' - 'a')); |
26328 |
-+ n[sizeof(n) - 1] = 0; |
26329 |
-+ |
26330 |
-+ r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now); |
26331 |
-+ if (r < 0) |
26332 |
-+ return NULL; |
26333 |
-+ |
26334 |
-+ return str; |
26335 |
-+} |
26336 |
-+ |
26337 |
-+static int do_userns_map_id(pid_t pid, |
26338 |
-+ const char *map_file, |
26339 |
-+ const char *map_id) |
26340 |
-+{ |
26341 |
-+ int ret; |
26342 |
-+ int fd; |
26343 |
-+ char *map; |
26344 |
-+ unsigned int i; |
26345 |
-+ |
26346 |
-+ map = strndupa(map_id, strlen(map_id)); |
26347 |
-+ if (!map) { |
26348 |
-+ ret = -errno; |
26349 |
-+ kdbus_printf("error strndupa %s: %d (%m)\n", |
26350 |
-+ map_file, ret); |
26351 |
-+ return ret; |
26352 |
-+ } |
26353 |
-+ |
26354 |
-+ for (i = 0; i < strlen(map); i++) |
26355 |
-+ if (map[i] == ',') |
26356 |
-+ map[i] = '\n'; |
26357 |
-+ |
26358 |
-+ fd = open(map_file, O_RDWR); |
26359 |
-+ if (fd < 0) { |
26360 |
-+ ret = -errno; |
26361 |
-+ kdbus_printf("error open %s: %d (%m)\n", |
26362 |
-+ map_file, ret); |
26363 |
-+ return ret; |
26364 |
-+ } |
26365 |
-+ |
26366 |
-+ ret = write(fd, map, strlen(map)); |
26367 |
-+ if (ret < 0) { |
26368 |
-+ ret = -errno; |
26369 |
-+ kdbus_printf("error write to %s: %d (%m)\n", |
26370 |
-+ map_file, ret); |
26371 |
-+ goto out; |
26372 |
-+ } |
26373 |
-+ |
26374 |
-+ ret = 0; |
26375 |
-+ |
26376 |
-+out: |
26377 |
-+ close(fd); |
26378 |
-+ return ret; |
26379 |
-+} |
26380 |
-+ |
26381 |
-+int userns_map_uid_gid(pid_t pid, |
26382 |
-+ const char *map_uid, |
26383 |
-+ const char *map_gid) |
26384 |
-+{ |
26385 |
-+ int fd, ret; |
26386 |
-+ char file_id[128] = {'\0'}; |
26387 |
-+ |
26388 |
-+ snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map", |
26389 |
-+ (long) pid); |
26390 |
-+ |
26391 |
-+ ret = do_userns_map_id(pid, file_id, map_uid); |
26392 |
-+ if (ret < 0) |
26393 |
-+ return ret; |
26394 |
-+ |
26395 |
-+ snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups", |
26396 |
-+ (long) pid); |
26397 |
-+ |
26398 |
-+ fd = open(file_id, O_WRONLY); |
26399 |
-+ if (fd >= 0) { |
26400 |
-+ write(fd, "deny\n", 5); |
26401 |
-+ close(fd); |
26402 |
-+ } |
26403 |
-+ |
26404 |
-+ snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map", |
26405 |
-+ (long) pid); |
26406 |
-+ |
26407 |
-+ return do_userns_map_id(pid, file_id, map_gid); |
26408 |
-+} |
26409 |
-+ |
26410 |
-+static int do_cap_get_flag(cap_t caps, cap_value_t cap) |
26411 |
-+{ |
26412 |
-+ int ret; |
26413 |
-+ cap_flag_value_t flag_set; |
26414 |
-+ |
26415 |
-+ ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set); |
26416 |
-+ if (ret < 0) { |
26417 |
-+ ret = -errno; |
26418 |
-+ kdbus_printf("error cap_get_flag(): %d (%m)\n", ret); |
26419 |
-+ return ret; |
26420 |
-+ } |
26421 |
-+ |
26422 |
-+ return (flag_set == CAP_SET); |
26423 |
-+} |
26424 |
-+ |
26425 |
-+/* |
26426 |
-+ * Returns: |
26427 |
-+ * 1 in case all the requested effective capabilities are set. |
26428 |
-+ * 0 in case we do not have the requested capabilities. This value |
26429 |
-+ * will be used to abort tests with TEST_SKIP |
26430 |
-+ * Negative errno on failure. |
26431 |
-+ * |
26432 |
-+ * Terminate args with a negative value. |
26433 |
-+ */ |
26434 |
-+int test_is_capable(int cap, ...) |
26435 |
-+{ |
26436 |
-+ int ret; |
26437 |
-+ va_list ap; |
26438 |
-+ cap_t caps; |
26439 |
-+ |
26440 |
-+ caps = cap_get_proc(); |
26441 |
-+ if (!caps) { |
26442 |
-+ ret = -errno; |
26443 |
-+ kdbus_printf("error cap_get_proc(): %d (%m)\n", ret); |
26444 |
-+ return ret; |
26445 |
-+ } |
26446 |
-+ |
26447 |
-+ ret = do_cap_get_flag(caps, (cap_value_t)cap); |
26448 |
-+ if (ret <= 0) |
26449 |
-+ goto out; |
26450 |
-+ |
26451 |
-+ va_start(ap, cap); |
26452 |
-+ while ((cap = va_arg(ap, int)) > 0) { |
26453 |
-+ ret = do_cap_get_flag(caps, (cap_value_t)cap); |
26454 |
-+ if (ret <= 0) |
26455 |
-+ break; |
26456 |
-+ } |
26457 |
-+ va_end(ap); |
26458 |
-+ |
26459 |
-+out: |
26460 |
-+ cap_free(caps); |
26461 |
-+ return ret; |
26462 |
-+} |
26463 |
-+ |
26464 |
-+int config_user_ns_is_enabled(void) |
26465 |
-+{ |
26466 |
-+ return (access("/proc/self/uid_map", F_OK) == 0); |
26467 |
-+} |
26468 |
-+ |
26469 |
-+int config_auditsyscall_is_enabled(void) |
26470 |
-+{ |
26471 |
-+ return (access("/proc/self/loginuid", F_OK) == 0); |
26472 |
-+} |
26473 |
-+ |
26474 |
-+int config_cgroups_is_enabled(void) |
26475 |
-+{ |
26476 |
-+ return (access("/proc/self/cgroup", F_OK) == 0); |
26477 |
-+} |
26478 |
-+ |
26479 |
-+int config_security_is_enabled(void) |
26480 |
-+{ |
26481 |
-+ int fd; |
26482 |
-+ int ret; |
26483 |
-+ char buf[128]; |
26484 |
-+ |
26485 |
-+ /* CONFIG_SECURITY is disabled */ |
26486 |
-+ if (access("/proc/self/attr/current", F_OK) != 0) |
26487 |
-+ return 0; |
26488 |
-+ |
26489 |
-+ /* |
26490 |
-+ * Now only if read() fails with -EINVAL then we assume |
26491 |
-+ * that SECLABEL and LSM are disabled |
26492 |
-+ */ |
26493 |
-+ fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC); |
26494 |
-+ if (fd < 0) |
26495 |
-+ return 1; |
26496 |
-+ |
26497 |
-+ ret = read(fd, buf, sizeof(buf)); |
26498 |
-+ if (ret == -1 && errno == EINVAL) |
26499 |
-+ ret = 0; |
26500 |
-+ else |
26501 |
-+ ret = 1; |
26502 |
-+ |
26503 |
-+ close(fd); |
26504 |
-+ |
26505 |
-+ return ret; |
26506 |
-+} |
26507 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h |
26508 |
-new file mode 100644 |
26509 |
-index 0000000..e1e18b9 |
26510 |
---- /dev/null |
26511 |
-+++ b/tools/testing/selftests/kdbus/kdbus-util.h |
26512 |
-@@ -0,0 +1,218 @@ |
26513 |
-+/* |
26514 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
26515 |
-+ * Copyright (C) 2013-2015 Daniel Mack |
26516 |
-+ * |
26517 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
26518 |
-+ * the terms of the GNU Lesser General Public License as published by the |
26519 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
26520 |
-+ * your option) any later version. |
26521 |
-+ */ |
26522 |
-+ |
26523 |
-+#pragma once |
26524 |
-+ |
26525 |
-+#define BIT(X) (1 << (X)) |
26526 |
-+ |
26527 |
-+#include <time.h> |
26528 |
-+#include <stdbool.h> |
26529 |
-+#include <linux/kdbus.h> |
26530 |
-+ |
26531 |
-+#define _STRINGIFY(x) #x |
26532 |
-+#define STRINGIFY(x) _STRINGIFY(x) |
26533 |
-+#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) |
26534 |
-+ |
26535 |
-+#define KDBUS_PTR(addr) ((void *)(uintptr_t)(addr)) |
26536 |
-+ |
26537 |
-+#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) |
26538 |
-+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
26539 |
-+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) |
26540 |
-+ |
26541 |
-+#define KDBUS_ITEM_NEXT(item) \ |
26542 |
-+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) |
26543 |
-+#define KDBUS_ITEM_FOREACH(item, head, first) \ |
26544 |
-+ for ((item) = (head)->first; \ |
26545 |
-+ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ |
26546 |
-+ ((uint8_t *)(item) >= (uint8_t *)(head)); \ |
26547 |
-+ (item) = KDBUS_ITEM_NEXT(item)) |
26548 |
-+#define KDBUS_FOREACH(iter, first, _size) \ |
26549 |
-+ for ((iter) = (first); \ |
26550 |
-+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ |
26551 |
-+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ |
26552 |
-+ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size))) |
26553 |
-+ |
26554 |
-+#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL)) |
26555 |
-+ |
26556 |
-+/* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */ |
26557 |
-+#define KDBUS_ATTACH_ITEMS_TYPE_SUM \ |
26558 |
-+ ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \ |
26559 |
-+ ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2) + \ |
26560 |
-+ (_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR)) |
26561 |
-+ |
26562 |
-+#define POOL_SIZE (16 * 1024LU * 1024LU) |
26563 |
-+ |
26564 |
-+#define UNPRIV_UID 65534 |
26565 |
-+#define UNPRIV_GID 65534 |
26566 |
-+ |
26567 |
-+/* Dump as user of process, useful for user namespace testing */ |
26568 |
-+#define SUID_DUMP_USER 1 |
26569 |
-+ |
26570 |
-+extern int kdbus_util_verbose; |
26571 |
-+ |
26572 |
-+#define kdbus_printf(X...) \ |
26573 |
-+ if (kdbus_util_verbose) \ |
26574 |
-+ printf(X) |
26575 |
-+ |
26576 |
-+#define RUN_UNPRIVILEGED(child_uid, child_gid, _child_, _parent_) ({ \ |
26577 |
-+ pid_t pid, rpid; \ |
26578 |
-+ int ret; \ |
26579 |
-+ \ |
26580 |
-+ pid = fork(); \ |
26581 |
-+ if (pid == 0) { \ |
26582 |
-+ ret = drop_privileges(child_uid, child_gid); \ |
26583 |
-+ ASSERT_EXIT_VAL(ret == 0, ret); \ |
26584 |
-+ \ |
26585 |
-+ _child_; \ |
26586 |
-+ _exit(0); \ |
26587 |
-+ } else if (pid > 0) { \ |
26588 |
-+ _parent_; \ |
26589 |
-+ rpid = waitpid(pid, &ret, 0); \ |
26590 |
-+ ASSERT_RETURN(rpid == pid); \ |
26591 |
-+ ASSERT_RETURN(WIFEXITED(ret)); \ |
26592 |
-+ ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ |
26593 |
-+ ret = TEST_OK; \ |
26594 |
-+ } else { \ |
26595 |
-+ ret = pid; \ |
26596 |
-+ } \ |
26597 |
-+ \ |
26598 |
-+ ret; \ |
26599 |
-+ }) |
26600 |
-+ |
26601 |
-+#define RUN_UNPRIVILEGED_CONN(_var_, _bus_, _code_) \ |
26602 |
-+ RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ \ |
26603 |
-+ struct kdbus_conn *_var_; \ |
26604 |
-+ _var_ = kdbus_hello(_bus_, 0, NULL, 0); \ |
26605 |
-+ ASSERT_EXIT(_var_); \ |
26606 |
-+ _code_; \ |
26607 |
-+ kdbus_conn_free(_var_); \ |
26608 |
-+ }), ({ 0; })) |
26609 |
-+ |
26610 |
-+#define RUN_CLONE_CHILD(clone_ret, flags, _setup_, _child_body_, \ |
26611 |
-+ _parent_setup_, _parent_body_) ({ \ |
26612 |
-+ pid_t pid, rpid; \ |
26613 |
-+ int ret; \ |
26614 |
-+ int efd = -1; \ |
26615 |
-+ \ |
26616 |
-+ _setup_; \ |
26617 |
-+ efd = eventfd(0, EFD_CLOEXEC); \ |
26618 |
-+ ASSERT_RETURN(efd >= 0); \ |
26619 |
-+ *(clone_ret) = 0; \ |
26620 |
-+ pid = syscall(__NR_clone, flags, NULL); \ |
26621 |
-+ if (pid == 0) { \ |
26622 |
-+ eventfd_t event_status = 0; \ |
26623 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); \ |
26624 |
-+ ASSERT_EXIT(ret == 0); \ |
26625 |
-+ ret = eventfd_read(efd, &event_status); \ |
26626 |
-+ if (ret < 0 || event_status != 1) { \ |
26627 |
-+ kdbus_printf("error eventfd_read()\n"); \ |
26628 |
-+ _exit(EXIT_FAILURE); \ |
26629 |
-+ } \ |
26630 |
-+ _child_body_; \ |
26631 |
-+ _exit(0); \ |
26632 |
-+ } else if (pid > 0) { \ |
26633 |
-+ _parent_setup_; \ |
26634 |
-+ ret = eventfd_write(efd, 1); \ |
26635 |
-+ ASSERT_RETURN(ret >= 0); \ |
26636 |
-+ _parent_body_; \ |
26637 |
-+ rpid = waitpid(pid, &ret, 0); \ |
26638 |
-+ ASSERT_RETURN(rpid == pid); \ |
26639 |
-+ ASSERT_RETURN(WIFEXITED(ret)); \ |
26640 |
-+ ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ |
26641 |
-+ ret = TEST_OK; \ |
26642 |
-+ } else { \ |
26643 |
-+ ret = -errno; \ |
26644 |
-+ *(clone_ret) = -errno; \ |
26645 |
-+ } \ |
26646 |
-+ close(efd); \ |
26647 |
-+ ret; \ |
26648 |
-+}) |
26649 |
-+ |
26650 |
-+/* Enums for parent if it should drop privs or not */ |
26651 |
-+enum kdbus_drop_parent { |
26652 |
-+ DO_NOT_DROP, |
26653 |
-+ DROP_SAME_UNPRIV, |
26654 |
-+ DROP_OTHER_UNPRIV, |
26655 |
-+}; |
26656 |
-+ |
26657 |
-+struct kdbus_conn { |
26658 |
-+ int fd; |
26659 |
-+ uint64_t id; |
26660 |
-+ unsigned char *buf; |
26661 |
-+}; |
26662 |
-+ |
26663 |
-+int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask); |
26664 |
-+int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask); |
26665 |
-+ |
26666 |
-+int sys_memfd_create(const char *name, __u64 size); |
26667 |
-+int sys_memfd_seal_set(int fd); |
26668 |
-+off_t sys_memfd_get_size(int fd, off_t *size); |
26669 |
-+ |
26670 |
-+int kdbus_list(struct kdbus_conn *conn, uint64_t flags); |
26671 |
-+int kdbus_name_release(struct kdbus_conn *conn, const char *name); |
26672 |
-+int kdbus_name_acquire(struct kdbus_conn *conn, const char *name, |
26673 |
-+ uint64_t *flags); |
26674 |
-+void kdbus_msg_free(struct kdbus_msg *msg); |
26675 |
-+int kdbus_msg_recv(struct kdbus_conn *conn, |
26676 |
-+ struct kdbus_msg **msg, uint64_t *offset); |
26677 |
-+int kdbus_msg_recv_poll(struct kdbus_conn *conn, int timeout_ms, |
26678 |
-+ struct kdbus_msg **msg_out, uint64_t *offset); |
26679 |
-+int kdbus_free(const struct kdbus_conn *conn, uint64_t offset); |
26680 |
-+int kdbus_msg_dump(const struct kdbus_conn *conn, |
26681 |
-+ const struct kdbus_msg *msg); |
26682 |
-+int kdbus_create_bus(int control_fd, const char *name, |
26683 |
-+ uint64_t owner_meta, char **path); |
26684 |
-+int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, |
26685 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
26686 |
-+ int64_t priority, uint64_t dst_id); |
26687 |
-+int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, |
26688 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
26689 |
-+ int64_t priority, uint64_t dst_id, int cancel_fd); |
26690 |
-+int kdbus_msg_send_reply(const struct kdbus_conn *conn, |
26691 |
-+ uint64_t reply_cookie, |
26692 |
-+ uint64_t dst_id); |
26693 |
-+struct kdbus_conn *kdbus_hello(const char *path, uint64_t hello_flags, |
26694 |
-+ const struct kdbus_item *item, |
26695 |
-+ size_t item_size); |
26696 |
-+struct kdbus_conn *kdbus_hello_registrar(const char *path, const char *name, |
26697 |
-+ const struct kdbus_policy_access *access, |
26698 |
-+ size_t num_access, uint64_t flags); |
26699 |
-+struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, |
26700 |
-+ const struct kdbus_policy_access *access, |
26701 |
-+ size_t num_access); |
26702 |
-+bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type); |
26703 |
-+int kdbus_bus_creator_info(struct kdbus_conn *conn, |
26704 |
-+ uint64_t flags, |
26705 |
-+ uint64_t *offset); |
26706 |
-+int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, |
26707 |
-+ const char *name, uint64_t flags, uint64_t *offset); |
26708 |
-+void kdbus_conn_free(struct kdbus_conn *conn); |
26709 |
-+int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, |
26710 |
-+ uint64_t attach_flags_send, |
26711 |
-+ uint64_t attach_flags_recv); |
26712 |
-+int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, |
26713 |
-+ const struct kdbus_policy_access *access, |
26714 |
-+ size_t num_access); |
26715 |
-+ |
26716 |
-+int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, |
26717 |
-+ uint64_t type, uint64_t id); |
26718 |
-+int kdbus_add_match_empty(struct kdbus_conn *conn); |
26719 |
-+ |
26720 |
-+int all_uids_gids_are_mapped(void); |
26721 |
-+int drop_privileges(uid_t uid, gid_t gid); |
26722 |
-+uint64_t now(clockid_t clock); |
26723 |
-+char *unique_name(const char *prefix); |
26724 |
-+ |
26725 |
-+int userns_map_uid_gid(pid_t pid, const char *map_uid, const char *map_gid); |
26726 |
-+int test_is_capable(int cap, ...); |
26727 |
-+int config_user_ns_is_enabled(void); |
26728 |
-+int config_auditsyscall_is_enabled(void); |
26729 |
-+int config_cgroups_is_enabled(void); |
26730 |
-+int config_security_is_enabled(void); |
26731 |
-diff --git a/tools/testing/selftests/kdbus/test-activator.c b/tools/testing/selftests/kdbus/test-activator.c |
26732 |
-new file mode 100644 |
26733 |
-index 0000000..3d1b763 |
26734 |
---- /dev/null |
26735 |
-+++ b/tools/testing/selftests/kdbus/test-activator.c |
26736 |
-@@ -0,0 +1,318 @@ |
26737 |
-+#include <stdio.h> |
26738 |
-+#include <string.h> |
26739 |
-+#include <time.h> |
26740 |
-+#include <fcntl.h> |
26741 |
-+#include <stdlib.h> |
26742 |
-+#include <stdbool.h> |
26743 |
-+#include <stddef.h> |
26744 |
-+#include <unistd.h> |
26745 |
-+#include <stdint.h> |
26746 |
-+#include <errno.h> |
26747 |
-+#include <assert.h> |
26748 |
-+#include <poll.h> |
26749 |
-+#include <sys/capability.h> |
26750 |
-+#include <sys/types.h> |
26751 |
-+#include <sys/wait.h> |
26752 |
-+ |
26753 |
-+#include "kdbus-test.h" |
26754 |
-+#include "kdbus-util.h" |
26755 |
-+#include "kdbus-enum.h" |
26756 |
-+ |
26757 |
-+static int kdbus_starter_poll(struct kdbus_conn *conn) |
26758 |
-+{ |
26759 |
-+ int ret; |
26760 |
-+ struct pollfd fd; |
26761 |
-+ |
26762 |
-+ fd.fd = conn->fd; |
26763 |
-+ fd.events = POLLIN | POLLPRI | POLLHUP; |
26764 |
-+ fd.revents = 0; |
26765 |
-+ |
26766 |
-+ ret = poll(&fd, 1, 100); |
26767 |
-+ if (ret == 0) |
26768 |
-+ return -ETIMEDOUT; |
26769 |
-+ else if (ret > 0) { |
26770 |
-+ if (fd.revents & POLLIN) |
26771 |
-+ return 0; |
26772 |
-+ |
26773 |
-+ if (fd.revents & (POLLHUP | POLLERR)) |
26774 |
-+ ret = -ECONNRESET; |
26775 |
-+ } |
26776 |
-+ |
26777 |
-+ return ret; |
26778 |
-+} |
26779 |
-+ |
26780 |
-+/* Ensure that kdbus activator logic is safe */ |
26781 |
-+static int kdbus_priv_activator(struct kdbus_test_env *env) |
26782 |
-+{ |
26783 |
-+ int ret; |
26784 |
-+ struct kdbus_msg *msg = NULL; |
26785 |
-+ uint64_t cookie = 0xdeadbeef; |
26786 |
-+ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
26787 |
-+ struct kdbus_conn *activator; |
26788 |
-+ struct kdbus_conn *service; |
26789 |
-+ struct kdbus_conn *client; |
26790 |
-+ struct kdbus_conn *holder; |
26791 |
-+ struct kdbus_policy_access *access; |
26792 |
-+ |
26793 |
-+ access = (struct kdbus_policy_access[]){ |
26794 |
-+ { |
26795 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
26796 |
-+ .id = getuid(), |
26797 |
-+ .access = KDBUS_POLICY_OWN, |
26798 |
-+ }, |
26799 |
-+ { |
26800 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
26801 |
-+ .id = getuid(), |
26802 |
-+ .access = KDBUS_POLICY_TALK, |
26803 |
-+ }, |
26804 |
-+ }; |
26805 |
-+ |
26806 |
-+ activator = kdbus_hello_activator(env->buspath, "foo.priv.activator", |
26807 |
-+ access, 2); |
26808 |
-+ ASSERT_RETURN(activator); |
26809 |
-+ |
26810 |
-+ service = kdbus_hello(env->buspath, 0, NULL, 0); |
26811 |
-+ ASSERT_RETURN(service); |
26812 |
-+ |
26813 |
-+ client = kdbus_hello(env->buspath, 0, NULL, 0); |
26814 |
-+ ASSERT_RETURN(client); |
26815 |
-+ |
26816 |
-+ /* |
26817 |
-+ * Make sure that other users can't TALK to the activator |
26818 |
-+ */ |
26819 |
-+ |
26820 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26821 |
-+ /* Try to talk using the ID */ |
26822 |
-+ ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0, |
26823 |
-+ 0, activator->id); |
26824 |
-+ ASSERT_EXIT(ret == -ENXIO); |
26825 |
-+ |
26826 |
-+ /* Try to talk to the name */ |
26827 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26828 |
-+ 0xdeadbeef, 0, 0, 0, |
26829 |
-+ KDBUS_DST_ID_NAME); |
26830 |
-+ ASSERT_EXIT(ret == -EPERM); |
26831 |
-+ })); |
26832 |
-+ ASSERT_RETURN(ret >= 0); |
26833 |
-+ |
26834 |
-+ /* |
26835 |
-+ * Make sure that we did not receive anything, so the |
26836 |
-+ * service will not be started automatically |
26837 |
-+ */ |
26838 |
-+ |
26839 |
-+ ret = kdbus_starter_poll(activator); |
26840 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
26841 |
-+ |
26842 |
-+ /* |
26843 |
-+ * Now try to emulate the starter/service logic and |
26844 |
-+ * acquire the name. |
26845 |
-+ */ |
26846 |
-+ |
26847 |
-+ cookie++; |
26848 |
-+ ret = kdbus_msg_send(service, "foo.priv.activator", cookie, |
26849 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26850 |
-+ ASSERT_RETURN(ret == 0); |
26851 |
-+ |
26852 |
-+ ret = kdbus_starter_poll(activator); |
26853 |
-+ ASSERT_RETURN(ret == 0); |
26854 |
-+ |
26855 |
-+ /* Policies are still checked, access denied */ |
26856 |
-+ |
26857 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26858 |
-+ ret = kdbus_name_acquire(unpriv, "foo.priv.activator", |
26859 |
-+ &flags); |
26860 |
-+ ASSERT_RETURN(ret == -EPERM); |
26861 |
-+ })); |
26862 |
-+ ASSERT_RETURN(ret >= 0); |
26863 |
-+ |
26864 |
-+ ret = kdbus_name_acquire(service, "foo.priv.activator", |
26865 |
-+ &flags); |
26866 |
-+ ASSERT_RETURN(ret == 0); |
26867 |
-+ |
26868 |
-+ /* We read our previous starter message */ |
26869 |
-+ |
26870 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26871 |
-+ ASSERT_RETURN(ret == 0); |
26872 |
-+ |
26873 |
-+ /* Try to talk, we still fail */ |
26874 |
-+ |
26875 |
-+ cookie++; |
26876 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26877 |
-+ /* Try to talk to the name */ |
26878 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26879 |
-+ cookie, 0, 0, 0, |
26880 |
-+ KDBUS_DST_ID_NAME); |
26881 |
-+ ASSERT_EXIT(ret == -EPERM); |
26882 |
-+ })); |
26883 |
-+ ASSERT_RETURN(ret >= 0); |
26884 |
-+ |
26885 |
-+ /* Still nothing to read */ |
26886 |
-+ |
26887 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26888 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
26889 |
-+ |
26890 |
-+ /* We receive every thing now */ |
26891 |
-+ |
26892 |
-+ cookie++; |
26893 |
-+ ret = kdbus_msg_send(client, "foo.priv.activator", cookie, |
26894 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26895 |
-+ ASSERT_RETURN(ret == 0); |
26896 |
-+ ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); |
26897 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
26898 |
-+ |
26899 |
-+ kdbus_msg_free(msg); |
26900 |
-+ |
26901 |
-+ /* Policies default to deny TALK now */ |
26902 |
-+ kdbus_conn_free(activator); |
26903 |
-+ |
26904 |
-+ cookie++; |
26905 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26906 |
-+ /* Try to talk to the name */ |
26907 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26908 |
-+ cookie, 0, 0, 0, |
26909 |
-+ KDBUS_DST_ID_NAME); |
26910 |
-+ ASSERT_EXIT(ret == -EPERM); |
26911 |
-+ })); |
26912 |
-+ ASSERT_RETURN(ret >= 0); |
26913 |
-+ |
26914 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26915 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
26916 |
-+ |
26917 |
-+ /* Same user is able to TALK */ |
26918 |
-+ cookie++; |
26919 |
-+ ret = kdbus_msg_send(client, "foo.priv.activator", cookie, |
26920 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26921 |
-+ ASSERT_RETURN(ret == 0); |
26922 |
-+ ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); |
26923 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
26924 |
-+ |
26925 |
-+ kdbus_msg_free(msg); |
26926 |
-+ |
26927 |
-+ access = (struct kdbus_policy_access []){ |
26928 |
-+ { |
26929 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
26930 |
-+ .id = getuid(), |
26931 |
-+ .access = KDBUS_POLICY_TALK, |
26932 |
-+ }, |
26933 |
-+ }; |
26934 |
-+ |
26935 |
-+ holder = kdbus_hello_registrar(env->buspath, "foo.priv.activator", |
26936 |
-+ access, 1, KDBUS_HELLO_POLICY_HOLDER); |
26937 |
-+ ASSERT_RETURN(holder); |
26938 |
-+ |
26939 |
-+ /* Now we are able to TALK to the name */ |
26940 |
-+ |
26941 |
-+ cookie++; |
26942 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26943 |
-+ /* Try to talk to the name */ |
26944 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26945 |
-+ cookie, 0, 0, 0, |
26946 |
-+ KDBUS_DST_ID_NAME); |
26947 |
-+ ASSERT_EXIT(ret == 0); |
26948 |
-+ })); |
26949 |
-+ ASSERT_RETURN(ret >= 0); |
26950 |
-+ |
26951 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26952 |
-+ ASSERT_RETURN(ret == 0); |
26953 |
-+ |
26954 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26955 |
-+ ret = kdbus_name_acquire(unpriv, "foo.priv.activator", |
26956 |
-+ &flags); |
26957 |
-+ ASSERT_RETURN(ret == -EPERM); |
26958 |
-+ })); |
26959 |
-+ ASSERT_RETURN(ret >= 0); |
26960 |
-+ |
26961 |
-+ kdbus_conn_free(service); |
26962 |
-+ kdbus_conn_free(client); |
26963 |
-+ kdbus_conn_free(holder); |
26964 |
-+ |
26965 |
-+ return 0; |
26966 |
-+} |
26967 |
-+ |
26968 |
-+int kdbus_test_activator(struct kdbus_test_env *env) |
26969 |
-+{ |
26970 |
-+ int ret; |
26971 |
-+ struct kdbus_conn *activator; |
26972 |
-+ struct pollfd fds[2]; |
26973 |
-+ bool activator_done = false; |
26974 |
-+ struct kdbus_policy_access access[2]; |
26975 |
-+ |
26976 |
-+ access[0].type = KDBUS_POLICY_ACCESS_USER; |
26977 |
-+ access[0].id = getuid(); |
26978 |
-+ access[0].access = KDBUS_POLICY_OWN; |
26979 |
-+ |
26980 |
-+ access[1].type = KDBUS_POLICY_ACCESS_WORLD; |
26981 |
-+ access[1].access = KDBUS_POLICY_TALK; |
26982 |
-+ |
26983 |
-+ activator = kdbus_hello_activator(env->buspath, "foo.test.activator", |
26984 |
-+ access, 2); |
26985 |
-+ ASSERT_RETURN(activator); |
26986 |
-+ |
26987 |
-+ ret = kdbus_add_match_empty(env->conn); |
26988 |
-+ ASSERT_RETURN(ret == 0); |
26989 |
-+ |
26990 |
-+ ret = kdbus_list(env->conn, KDBUS_LIST_NAMES | |
26991 |
-+ KDBUS_LIST_UNIQUE | |
26992 |
-+ KDBUS_LIST_ACTIVATORS | |
26993 |
-+ KDBUS_LIST_QUEUED); |
26994 |
-+ ASSERT_RETURN(ret == 0); |
26995 |
-+ |
26996 |
-+ ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef, |
26997 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26998 |
-+ ASSERT_RETURN(ret == 0); |
26999 |
-+ |
27000 |
-+ fds[0].fd = activator->fd; |
27001 |
-+ fds[1].fd = env->conn->fd; |
27002 |
-+ |
27003 |
-+ kdbus_printf("-- entering poll loop ...\n"); |
27004 |
-+ |
27005 |
-+ for (;;) { |
27006 |
-+ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
27007 |
-+ |
27008 |
-+ for (i = 0; i < nfds; i++) { |
27009 |
-+ fds[i].events = POLLIN | POLLPRI; |
27010 |
-+ fds[i].revents = 0; |
27011 |
-+ } |
27012 |
-+ |
27013 |
-+ ret = poll(fds, nfds, 3000); |
27014 |
-+ ASSERT_RETURN(ret >= 0); |
27015 |
-+ |
27016 |
-+ ret = kdbus_list(env->conn, KDBUS_LIST_NAMES); |
27017 |
-+ ASSERT_RETURN(ret == 0); |
27018 |
-+ |
27019 |
-+ if ((fds[0].revents & POLLIN) && !activator_done) { |
27020 |
-+ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
27021 |
-+ |
27022 |
-+ kdbus_printf("Starter was called back!\n"); |
27023 |
-+ |
27024 |
-+ ret = kdbus_name_acquire(env->conn, |
27025 |
-+ "foo.test.activator", &flags); |
27026 |
-+ ASSERT_RETURN(ret == 0); |
27027 |
-+ |
27028 |
-+ activator_done = true; |
27029 |
-+ } |
27030 |
-+ |
27031 |
-+ if (fds[1].revents & POLLIN) { |
27032 |
-+ kdbus_msg_recv(env->conn, NULL, NULL); |
27033 |
-+ break; |
27034 |
-+ } |
27035 |
-+ } |
27036 |
-+ |
27037 |
-+ /* Check if all uids/gids are mapped */ |
27038 |
-+ if (!all_uids_gids_are_mapped()) |
27039 |
-+ return TEST_SKIP; |
27040 |
-+ |
27041 |
-+ /* Check now capabilities, so we run the previous tests */ |
27042 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
27043 |
-+ ASSERT_RETURN(ret >= 0); |
27044 |
-+ |
27045 |
-+ if (!ret) |
27046 |
-+ return TEST_SKIP; |
27047 |
-+ |
27048 |
-+ ret = kdbus_priv_activator(env); |
27049 |
-+ ASSERT_RETURN(ret == 0); |
27050 |
-+ |
27051 |
-+ kdbus_conn_free(activator); |
27052 |
-+ |
27053 |
-+ return TEST_OK; |
27054 |
-+} |
27055 |
-diff --git a/tools/testing/selftests/kdbus/test-benchmark.c b/tools/testing/selftests/kdbus/test-benchmark.c |
27056 |
-new file mode 100644 |
27057 |
-index 0000000..8a9744b |
27058 |
---- /dev/null |
27059 |
-+++ b/tools/testing/selftests/kdbus/test-benchmark.c |
27060 |
-@@ -0,0 +1,451 @@ |
27061 |
-+#include <stdio.h> |
27062 |
-+#include <string.h> |
27063 |
-+#include <time.h> |
27064 |
-+#include <fcntl.h> |
27065 |
-+#include <locale.h> |
27066 |
-+#include <stdlib.h> |
27067 |
-+#include <stddef.h> |
27068 |
-+#include <unistd.h> |
27069 |
-+#include <stdint.h> |
27070 |
-+#include <stdbool.h> |
27071 |
-+#include <errno.h> |
27072 |
-+#include <assert.h> |
27073 |
-+#include <poll.h> |
27074 |
-+#include <sys/time.h> |
27075 |
-+#include <sys/mman.h> |
27076 |
-+#include <sys/socket.h> |
27077 |
-+#include <math.h> |
27078 |
-+ |
27079 |
-+#include "kdbus-api.h" |
27080 |
-+#include "kdbus-test.h" |
27081 |
-+#include "kdbus-util.h" |
27082 |
-+#include "kdbus-enum.h" |
27083 |
-+ |
27084 |
-+#define SERVICE_NAME "foo.bar.echo" |
27085 |
-+ |
27086 |
-+/* |
27087 |
-+ * To have a banchmark comparison with unix socket, set: |
27088 |
-+ * user_memfd = false; |
27089 |
-+ * compare_uds = true; |
27090 |
-+ * attach_none = true; do not attached metadata |
27091 |
-+ */ |
27092 |
-+ |
27093 |
-+static bool use_memfd = true; /* transmit memfd? */ |
27094 |
-+static bool compare_uds = false; /* unix-socket comparison? */ |
27095 |
-+static bool attach_none = false; /* clear attach-flags? */ |
27096 |
-+static char stress_payload[8192]; |
27097 |
-+ |
27098 |
-+struct stats { |
27099 |
-+ uint64_t count; |
27100 |
-+ uint64_t latency_acc; |
27101 |
-+ uint64_t latency_low; |
27102 |
-+ uint64_t latency_high; |
27103 |
-+ uint64_t latency_avg; |
27104 |
-+ uint64_t latency_ssquares; |
27105 |
-+}; |
27106 |
-+ |
27107 |
-+static struct stats stats; |
27108 |
-+ |
27109 |
-+static void reset_stats(void) |
27110 |
-+{ |
27111 |
-+ stats.count = 0; |
27112 |
-+ stats.latency_acc = 0; |
27113 |
-+ stats.latency_low = UINT64_MAX; |
27114 |
-+ stats.latency_high = 0; |
27115 |
-+ stats.latency_avg = 0; |
27116 |
-+ stats.latency_ssquares = 0; |
27117 |
-+} |
27118 |
-+ |
27119 |
-+static void dump_stats(bool is_uds) |
27120 |
-+{ |
27121 |
-+ if (stats.count > 0) { |
27122 |
-+ kdbus_printf("stats %s: %'llu packets processed, latency (nsecs) min/max/avg/dev %'7llu // %'7llu // %'7llu // %'7.f\n", |
27123 |
-+ is_uds ? " (UNIX)" : "(KDBUS)", |
27124 |
-+ (unsigned long long) stats.count, |
27125 |
-+ (unsigned long long) stats.latency_low, |
27126 |
-+ (unsigned long long) stats.latency_high, |
27127 |
-+ (unsigned long long) stats.latency_avg, |
27128 |
-+ sqrt(stats.latency_ssquares / stats.count)); |
27129 |
-+ } else { |
27130 |
-+ kdbus_printf("*** no packets received. bus stuck?\n"); |
27131 |
-+ } |
27132 |
-+} |
27133 |
-+ |
27134 |
-+static void add_stats(uint64_t prev) |
27135 |
-+{ |
27136 |
-+ uint64_t diff, latency_avg_prev; |
27137 |
-+ |
27138 |
-+ diff = now(CLOCK_THREAD_CPUTIME_ID) - prev; |
27139 |
-+ |
27140 |
-+ stats.count++; |
27141 |
-+ stats.latency_acc += diff; |
27142 |
-+ |
27143 |
-+ /* see Welford62 */ |
27144 |
-+ latency_avg_prev = stats.latency_avg; |
27145 |
-+ stats.latency_avg = stats.latency_acc / stats.count; |
27146 |
-+ stats.latency_ssquares += (diff - latency_avg_prev) * (diff - stats.latency_avg); |
27147 |
-+ |
27148 |
-+ if (stats.latency_low > diff) |
27149 |
-+ stats.latency_low = diff; |
27150 |
-+ |
27151 |
-+ if (stats.latency_high < diff) |
27152 |
-+ stats.latency_high = diff; |
27153 |
-+} |
27154 |
-+ |
27155 |
-+static int setup_simple_kdbus_msg(struct kdbus_conn *conn, |
27156 |
-+ uint64_t dst_id, |
27157 |
-+ struct kdbus_msg **msg_out) |
27158 |
-+{ |
27159 |
-+ struct kdbus_msg *msg; |
27160 |
-+ struct kdbus_item *item; |
27161 |
-+ uint64_t size; |
27162 |
-+ |
27163 |
-+ size = sizeof(struct kdbus_msg); |
27164 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
27165 |
-+ |
27166 |
-+ msg = malloc(size); |
27167 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
27168 |
-+ |
27169 |
-+ memset(msg, 0, size); |
27170 |
-+ msg->size = size; |
27171 |
-+ msg->src_id = conn->id; |
27172 |
-+ msg->dst_id = dst_id; |
27173 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
27174 |
-+ |
27175 |
-+ item = msg->items; |
27176 |
-+ |
27177 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
27178 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
27179 |
-+ item->vec.address = (uintptr_t) stress_payload; |
27180 |
-+ item->vec.size = sizeof(stress_payload); |
27181 |
-+ item = KDBUS_ITEM_NEXT(item); |
27182 |
-+ |
27183 |
-+ *msg_out = msg; |
27184 |
-+ |
27185 |
-+ return 0; |
27186 |
-+} |
27187 |
-+ |
27188 |
-+static int setup_memfd_kdbus_msg(struct kdbus_conn *conn, |
27189 |
-+ uint64_t dst_id, |
27190 |
-+ off_t *memfd_item_offset, |
27191 |
-+ struct kdbus_msg **msg_out) |
27192 |
-+{ |
27193 |
-+ struct kdbus_msg *msg; |
27194 |
-+ struct kdbus_item *item; |
27195 |
-+ uint64_t size; |
27196 |
-+ |
27197 |
-+ size = sizeof(struct kdbus_msg); |
27198 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
27199 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
27200 |
-+ |
27201 |
-+ msg = malloc(size); |
27202 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
27203 |
-+ |
27204 |
-+ memset(msg, 0, size); |
27205 |
-+ msg->size = size; |
27206 |
-+ msg->src_id = conn->id; |
27207 |
-+ msg->dst_id = dst_id; |
27208 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
27209 |
-+ |
27210 |
-+ item = msg->items; |
27211 |
-+ |
27212 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
27213 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
27214 |
-+ item->vec.address = (uintptr_t) stress_payload; |
27215 |
-+ item->vec.size = sizeof(stress_payload); |
27216 |
-+ item = KDBUS_ITEM_NEXT(item); |
27217 |
-+ |
27218 |
-+ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
27219 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd); |
27220 |
-+ item->memfd.size = sizeof(uint64_t); |
27221 |
-+ |
27222 |
-+ *memfd_item_offset = (unsigned char *)item - (unsigned char *)msg; |
27223 |
-+ *msg_out = msg; |
27224 |
-+ |
27225 |
-+ return 0; |
27226 |
-+} |
27227 |
-+ |
27228 |
-+static int |
27229 |
-+send_echo_request(struct kdbus_conn *conn, uint64_t dst_id, |
27230 |
-+ void *kdbus_msg, off_t memfd_item_offset) |
27231 |
-+{ |
27232 |
-+ struct kdbus_cmd_send cmd = {}; |
27233 |
-+ int memfd = -1; |
27234 |
-+ int ret; |
27235 |
-+ |
27236 |
-+ if (use_memfd) { |
27237 |
-+ uint64_t now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27238 |
-+ struct kdbus_item *item = memfd_item_offset + kdbus_msg; |
27239 |
-+ memfd = sys_memfd_create("memfd-name", 0); |
27240 |
-+ ASSERT_RETURN_VAL(memfd >= 0, memfd); |
27241 |
-+ |
27242 |
-+ ret = write(memfd, &now_ns, sizeof(now_ns)); |
27243 |
-+ ASSERT_RETURN_VAL(ret == sizeof(now_ns), -EAGAIN); |
27244 |
-+ |
27245 |
-+ ret = sys_memfd_seal_set(memfd); |
27246 |
-+ ASSERT_RETURN_VAL(ret == 0, -errno); |
27247 |
-+ |
27248 |
-+ item->memfd.fd = memfd; |
27249 |
-+ } |
27250 |
-+ |
27251 |
-+ cmd.size = sizeof(cmd); |
27252 |
-+ cmd.msg_address = (uintptr_t)kdbus_msg; |
27253 |
-+ |
27254 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
27255 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
27256 |
-+ |
27257 |
-+ close(memfd); |
27258 |
-+ |
27259 |
-+ return 0; |
27260 |
-+} |
27261 |
-+ |
27262 |
-+static int |
27263 |
-+handle_echo_reply(struct kdbus_conn *conn, uint64_t send_ns) |
27264 |
-+{ |
27265 |
-+ int ret; |
27266 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
27267 |
-+ struct kdbus_msg *msg; |
27268 |
-+ const struct kdbus_item *item; |
27269 |
-+ bool has_memfd = false; |
27270 |
-+ |
27271 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
27272 |
-+ if (ret == -EAGAIN) |
27273 |
-+ return ret; |
27274 |
-+ |
27275 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
27276 |
-+ |
27277 |
-+ if (!use_memfd) |
27278 |
-+ goto out; |
27279 |
-+ |
27280 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
27281 |
-+ |
27282 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
27283 |
-+ switch (item->type) { |
27284 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
27285 |
-+ char *buf; |
27286 |
-+ |
27287 |
-+ buf = mmap(NULL, item->memfd.size, PROT_READ, |
27288 |
-+ MAP_PRIVATE, item->memfd.fd, 0); |
27289 |
-+ ASSERT_RETURN_VAL(buf != MAP_FAILED, -EINVAL); |
27290 |
-+ ASSERT_RETURN_VAL(item->memfd.size == sizeof(uint64_t), |
27291 |
-+ -EINVAL); |
27292 |
-+ |
27293 |
-+ add_stats(*(uint64_t*)buf); |
27294 |
-+ munmap(buf, item->memfd.size); |
27295 |
-+ close(item->memfd.fd); |
27296 |
-+ has_memfd = true; |
27297 |
-+ break; |
27298 |
-+ } |
27299 |
-+ |
27300 |
-+ case KDBUS_ITEM_PAYLOAD_OFF: |
27301 |
-+ /* ignore */ |
27302 |
-+ break; |
27303 |
-+ } |
27304 |
-+ } |
27305 |
-+ |
27306 |
-+out: |
27307 |
-+ if (!has_memfd) |
27308 |
-+ add_stats(send_ns); |
27309 |
-+ |
27310 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
27311 |
-+ ASSERT_RETURN_VAL(ret == 0, -errno); |
27312 |
-+ |
27313 |
-+ return 0; |
27314 |
-+} |
27315 |
-+ |
27316 |
-+static int benchmark(struct kdbus_test_env *env) |
27317 |
-+{ |
27318 |
-+ static char buf[sizeof(stress_payload)]; |
27319 |
-+ struct kdbus_msg *kdbus_msg = NULL; |
27320 |
-+ off_t memfd_cached_offset = 0; |
27321 |
-+ int ret; |
27322 |
-+ struct kdbus_conn *conn_a, *conn_b; |
27323 |
-+ struct pollfd fds[2]; |
27324 |
-+ uint64_t start, send_ns, now_ns, diff; |
27325 |
-+ unsigned int i; |
27326 |
-+ int uds[2]; |
27327 |
-+ |
27328 |
-+ setlocale(LC_ALL, ""); |
27329 |
-+ |
27330 |
-+ for (i = 0; i < sizeof(stress_payload); i++) |
27331 |
-+ stress_payload[i] = i; |
27332 |
-+ |
27333 |
-+ /* setup kdbus pair */ |
27334 |
-+ |
27335 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
27336 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
27337 |
-+ ASSERT_RETURN(conn_a && conn_b); |
27338 |
-+ |
27339 |
-+ ret = kdbus_add_match_empty(conn_a); |
27340 |
-+ ASSERT_RETURN(ret == 0); |
27341 |
-+ |
27342 |
-+ ret = kdbus_add_match_empty(conn_b); |
27343 |
-+ ASSERT_RETURN(ret == 0); |
27344 |
-+ |
27345 |
-+ ret = kdbus_name_acquire(conn_a, SERVICE_NAME, NULL); |
27346 |
-+ ASSERT_RETURN(ret == 0); |
27347 |
-+ |
27348 |
-+ if (attach_none) { |
27349 |
-+ ret = kdbus_conn_update_attach_flags(conn_a, |
27350 |
-+ _KDBUS_ATTACH_ALL, |
27351 |
-+ 0); |
27352 |
-+ ASSERT_RETURN(ret == 0); |
27353 |
-+ } |
27354 |
-+ |
27355 |
-+ /* setup UDS pair */ |
27356 |
-+ |
27357 |
-+ ret = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, uds); |
27358 |
-+ ASSERT_RETURN(ret == 0); |
27359 |
-+ |
27360 |
-+ /* setup a kdbus msg now */ |
27361 |
-+ if (use_memfd) { |
27362 |
-+ ret = setup_memfd_kdbus_msg(conn_b, conn_a->id, |
27363 |
-+ &memfd_cached_offset, |
27364 |
-+ &kdbus_msg); |
27365 |
-+ ASSERT_RETURN(ret == 0); |
27366 |
-+ } else { |
27367 |
-+ ret = setup_simple_kdbus_msg(conn_b, conn_a->id, &kdbus_msg); |
27368 |
-+ ASSERT_RETURN(ret == 0); |
27369 |
-+ } |
27370 |
-+ |
27371 |
-+ /* start benchmark */ |
27372 |
-+ |
27373 |
-+ kdbus_printf("-- entering poll loop ...\n"); |
27374 |
-+ |
27375 |
-+ do { |
27376 |
-+ /* run kdbus benchmark */ |
27377 |
-+ fds[0].fd = conn_a->fd; |
27378 |
-+ fds[1].fd = conn_b->fd; |
27379 |
-+ |
27380 |
-+ /* cancel any pending message */ |
27381 |
-+ handle_echo_reply(conn_a, 0); |
27382 |
-+ |
27383 |
-+ start = now(CLOCK_THREAD_CPUTIME_ID); |
27384 |
-+ reset_stats(); |
27385 |
-+ |
27386 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27387 |
-+ ret = send_echo_request(conn_b, conn_a->id, |
27388 |
-+ kdbus_msg, memfd_cached_offset); |
27389 |
-+ ASSERT_RETURN(ret == 0); |
27390 |
-+ |
27391 |
-+ while (1) { |
27392 |
-+ unsigned int nfds = sizeof(fds) / sizeof(fds[0]); |
27393 |
-+ unsigned int i; |
27394 |
-+ |
27395 |
-+ for (i = 0; i < nfds; i++) { |
27396 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27397 |
-+ fds[i].revents = 0; |
27398 |
-+ } |
27399 |
-+ |
27400 |
-+ ret = poll(fds, nfds, 10); |
27401 |
-+ if (ret < 0) |
27402 |
-+ break; |
27403 |
-+ |
27404 |
-+ if (fds[0].revents & POLLIN) { |
27405 |
-+ ret = handle_echo_reply(conn_a, send_ns); |
27406 |
-+ ASSERT_RETURN(ret == 0); |
27407 |
-+ |
27408 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27409 |
-+ ret = send_echo_request(conn_b, conn_a->id, |
27410 |
-+ kdbus_msg, |
27411 |
-+ memfd_cached_offset); |
27412 |
-+ ASSERT_RETURN(ret == 0); |
27413 |
-+ } |
27414 |
-+ |
27415 |
-+ now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27416 |
-+ diff = now_ns - start; |
27417 |
-+ if (diff > 1000000000ULL) { |
27418 |
-+ start = now_ns; |
27419 |
-+ |
27420 |
-+ dump_stats(false); |
27421 |
-+ break; |
27422 |
-+ } |
27423 |
-+ } |
27424 |
-+ |
27425 |
-+ if (!compare_uds) |
27426 |
-+ continue; |
27427 |
-+ |
27428 |
-+ /* run unix-socket benchmark as comparison */ |
27429 |
-+ |
27430 |
-+ fds[0].fd = uds[0]; |
27431 |
-+ fds[1].fd = uds[1]; |
27432 |
-+ |
27433 |
-+ /* cancel any pendign message */ |
27434 |
-+ read(uds[1], buf, sizeof(buf)); |
27435 |
-+ |
27436 |
-+ start = now(CLOCK_THREAD_CPUTIME_ID); |
27437 |
-+ reset_stats(); |
27438 |
-+ |
27439 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27440 |
-+ ret = write(uds[0], stress_payload, sizeof(stress_payload)); |
27441 |
-+ ASSERT_RETURN(ret == sizeof(stress_payload)); |
27442 |
-+ |
27443 |
-+ while (1) { |
27444 |
-+ unsigned int nfds = sizeof(fds) / sizeof(fds[0]); |
27445 |
-+ unsigned int i; |
27446 |
-+ |
27447 |
-+ for (i = 0; i < nfds; i++) { |
27448 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27449 |
-+ fds[i].revents = 0; |
27450 |
-+ } |
27451 |
-+ |
27452 |
-+ ret = poll(fds, nfds, 10); |
27453 |
-+ if (ret < 0) |
27454 |
-+ break; |
27455 |
-+ |
27456 |
-+ if (fds[1].revents & POLLIN) { |
27457 |
-+ ret = read(uds[1], buf, sizeof(buf)); |
27458 |
-+ ASSERT_RETURN(ret == sizeof(buf)); |
27459 |
-+ |
27460 |
-+ add_stats(send_ns); |
27461 |
-+ |
27462 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27463 |
-+ ret = write(uds[0], buf, sizeof(buf)); |
27464 |
-+ ASSERT_RETURN(ret == sizeof(buf)); |
27465 |
-+ } |
27466 |
-+ |
27467 |
-+ now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27468 |
-+ diff = now_ns - start; |
27469 |
-+ if (diff > 1000000000ULL) { |
27470 |
-+ start = now_ns; |
27471 |
-+ |
27472 |
-+ dump_stats(true); |
27473 |
-+ break; |
27474 |
-+ } |
27475 |
-+ } |
27476 |
-+ |
27477 |
-+ } while (kdbus_util_verbose); |
27478 |
-+ |
27479 |
-+ kdbus_printf("-- closing bus connections\n"); |
27480 |
-+ |
27481 |
-+ free(kdbus_msg); |
27482 |
-+ |
27483 |
-+ kdbus_conn_free(conn_a); |
27484 |
-+ kdbus_conn_free(conn_b); |
27485 |
-+ |
27486 |
-+ return (stats.count > 1) ? TEST_OK : TEST_ERR; |
27487 |
-+} |
27488 |
-+ |
27489 |
-+int kdbus_test_benchmark(struct kdbus_test_env *env) |
27490 |
-+{ |
27491 |
-+ use_memfd = true; |
27492 |
-+ attach_none = false; |
27493 |
-+ compare_uds = false; |
27494 |
-+ return benchmark(env); |
27495 |
-+} |
27496 |
-+ |
27497 |
-+int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env) |
27498 |
-+{ |
27499 |
-+ use_memfd = false; |
27500 |
-+ attach_none = false; |
27501 |
-+ compare_uds = false; |
27502 |
-+ return benchmark(env); |
27503 |
-+} |
27504 |
-+ |
27505 |
-+int kdbus_test_benchmark_uds(struct kdbus_test_env *env) |
27506 |
-+{ |
27507 |
-+ use_memfd = false; |
27508 |
-+ attach_none = true; |
27509 |
-+ compare_uds = true; |
27510 |
-+ return benchmark(env); |
27511 |
-+} |
27512 |
-diff --git a/tools/testing/selftests/kdbus/test-bus.c b/tools/testing/selftests/kdbus/test-bus.c |
27513 |
-new file mode 100644 |
27514 |
-index 0000000..762fb30 |
27515 |
---- /dev/null |
27516 |
-+++ b/tools/testing/selftests/kdbus/test-bus.c |
27517 |
-@@ -0,0 +1,175 @@ |
27518 |
-+#include <stdio.h> |
27519 |
-+#include <string.h> |
27520 |
-+#include <fcntl.h> |
27521 |
-+#include <stdlib.h> |
27522 |
-+#include <stddef.h> |
27523 |
-+#include <unistd.h> |
27524 |
-+#include <stdint.h> |
27525 |
-+#include <errno.h> |
27526 |
-+#include <assert.h> |
27527 |
-+#include <limits.h> |
27528 |
-+#include <sys/mman.h> |
27529 |
-+#include <stdbool.h> |
27530 |
-+ |
27531 |
-+#include "kdbus-api.h" |
27532 |
-+#include "kdbus-util.h" |
27533 |
-+#include "kdbus-enum.h" |
27534 |
-+#include "kdbus-test.h" |
27535 |
-+ |
27536 |
-+static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, |
27537 |
-+ uint64_t type) |
27538 |
-+{ |
27539 |
-+ struct kdbus_item *item; |
27540 |
-+ |
27541 |
-+ KDBUS_ITEM_FOREACH(item, info, items) |
27542 |
-+ if (item->type == type) |
27543 |
-+ return item; |
27544 |
-+ |
27545 |
-+ return NULL; |
27546 |
-+} |
27547 |
-+ |
27548 |
-+static int test_bus_creator_info(const char *bus_path) |
27549 |
-+{ |
27550 |
-+ int ret; |
27551 |
-+ uint64_t offset; |
27552 |
-+ struct kdbus_conn *conn; |
27553 |
-+ struct kdbus_info *info; |
27554 |
-+ struct kdbus_item *item; |
27555 |
-+ char *tmp, *busname; |
27556 |
-+ |
27557 |
-+ /* extract the bus-name from @bus_path */ |
27558 |
-+ tmp = strdup(bus_path); |
27559 |
-+ ASSERT_RETURN(tmp); |
27560 |
-+ busname = strrchr(tmp, '/'); |
27561 |
-+ ASSERT_RETURN(busname); |
27562 |
-+ *busname = 0; |
27563 |
-+ busname = strrchr(tmp, '/'); |
27564 |
-+ ASSERT_RETURN(busname); |
27565 |
-+ ++busname; |
27566 |
-+ |
27567 |
-+ conn = kdbus_hello(bus_path, 0, NULL, 0); |
27568 |
-+ ASSERT_RETURN(conn); |
27569 |
-+ |
27570 |
-+ ret = kdbus_bus_creator_info(conn, _KDBUS_ATTACH_ALL, &offset); |
27571 |
-+ ASSERT_RETURN(ret == 0); |
27572 |
-+ |
27573 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
27574 |
-+ |
27575 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_MAKE_NAME); |
27576 |
-+ ASSERT_RETURN(item); |
27577 |
-+ ASSERT_RETURN(!strcmp(item->str, busname)); |
27578 |
-+ |
27579 |
-+ ret = kdbus_free(conn, offset); |
27580 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
27581 |
-+ |
27582 |
-+ free(tmp); |
27583 |
-+ kdbus_conn_free(conn); |
27584 |
-+ return 0; |
27585 |
-+} |
27586 |
-+ |
27587 |
-+int kdbus_test_bus_make(struct kdbus_test_env *env) |
27588 |
-+{ |
27589 |
-+ struct { |
27590 |
-+ struct kdbus_cmd cmd; |
27591 |
-+ |
27592 |
-+ /* bloom size item */ |
27593 |
-+ struct { |
27594 |
-+ uint64_t size; |
27595 |
-+ uint64_t type; |
27596 |
-+ struct kdbus_bloom_parameter bloom; |
27597 |
-+ } bs; |
27598 |
-+ |
27599 |
-+ /* name item */ |
27600 |
-+ uint64_t n_size; |
27601 |
-+ uint64_t n_type; |
27602 |
-+ char name[64]; |
27603 |
-+ } bus_make; |
27604 |
-+ char s[PATH_MAX], *name; |
27605 |
-+ int ret, control_fd2; |
27606 |
-+ uid_t uid; |
27607 |
-+ |
27608 |
-+ name = unique_name(""); |
27609 |
-+ ASSERT_RETURN(name); |
27610 |
-+ |
27611 |
-+ snprintf(s, sizeof(s), "%s/control", env->root); |
27612 |
-+ env->control_fd = open(s, O_RDWR|O_CLOEXEC); |
27613 |
-+ ASSERT_RETURN(env->control_fd >= 0); |
27614 |
-+ |
27615 |
-+ control_fd2 = open(s, O_RDWR|O_CLOEXEC); |
27616 |
-+ ASSERT_RETURN(control_fd2 >= 0); |
27617 |
-+ |
27618 |
-+ memset(&bus_make, 0, sizeof(bus_make)); |
27619 |
-+ |
27620 |
-+ bus_make.bs.size = sizeof(bus_make.bs); |
27621 |
-+ bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER; |
27622 |
-+ bus_make.bs.bloom.size = 64; |
27623 |
-+ bus_make.bs.bloom.n_hash = 1; |
27624 |
-+ |
27625 |
-+ bus_make.n_type = KDBUS_ITEM_MAKE_NAME; |
27626 |
-+ |
27627 |
-+ uid = getuid(); |
27628 |
-+ |
27629 |
-+ /* missing uid prefix */ |
27630 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "foo"); |
27631 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27632 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27633 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27634 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27635 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27636 |
-+ |
27637 |
-+ /* non alphanumeric character */ |
27638 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid); |
27639 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27640 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27641 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27642 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27643 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27644 |
-+ |
27645 |
-+ /* '-' at the end */ |
27646 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid); |
27647 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27648 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27649 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27650 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27651 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27652 |
-+ |
27653 |
-+ /* create a new bus */ |
27654 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-1", uid, name); |
27655 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27656 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27657 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27658 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27659 |
-+ ASSERT_RETURN(ret == 0); |
27660 |
-+ |
27661 |
-+ ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); |
27662 |
-+ ASSERT_RETURN(ret == -EEXIST); |
27663 |
-+ |
27664 |
-+ snprintf(s, sizeof(s), "%s/%u-%s-1/bus", env->root, uid, name); |
27665 |
-+ ASSERT_RETURN(access(s, F_OK) == 0); |
27666 |
-+ |
27667 |
-+ ret = test_bus_creator_info(s); |
27668 |
-+ ASSERT_RETURN(ret == 0); |
27669 |
-+ |
27670 |
-+ /* can't use the same fd for bus make twice, even though a different |
27671 |
-+ * bus name is used |
27672 |
-+ */ |
27673 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); |
27674 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27675 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27676 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27677 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27678 |
-+ ASSERT_RETURN(ret == -EBADFD); |
27679 |
-+ |
27680 |
-+ /* create a new bus, with different fd and different bus name */ |
27681 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); |
27682 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27683 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27684 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27685 |
-+ ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); |
27686 |
-+ ASSERT_RETURN(ret == 0); |
27687 |
-+ |
27688 |
-+ close(control_fd2); |
27689 |
-+ free(name); |
27690 |
-+ |
27691 |
-+ return TEST_OK; |
27692 |
-+} |
27693 |
-diff --git a/tools/testing/selftests/kdbus/test-chat.c b/tools/testing/selftests/kdbus/test-chat.c |
27694 |
-new file mode 100644 |
27695 |
-index 0000000..41e5b53 |
27696 |
---- /dev/null |
27697 |
-+++ b/tools/testing/selftests/kdbus/test-chat.c |
27698 |
-@@ -0,0 +1,124 @@ |
27699 |
-+#include <stdio.h> |
27700 |
-+#include <string.h> |
27701 |
-+#include <time.h> |
27702 |
-+#include <fcntl.h> |
27703 |
-+#include <stdlib.h> |
27704 |
-+#include <stddef.h> |
27705 |
-+#include <unistd.h> |
27706 |
-+#include <stdint.h> |
27707 |
-+#include <errno.h> |
27708 |
-+#include <assert.h> |
27709 |
-+#include <poll.h> |
27710 |
-+#include <stdbool.h> |
27711 |
-+ |
27712 |
-+#include "kdbus-test.h" |
27713 |
-+#include "kdbus-util.h" |
27714 |
-+#include "kdbus-enum.h" |
27715 |
-+ |
27716 |
-+int kdbus_test_chat(struct kdbus_test_env *env) |
27717 |
-+{ |
27718 |
-+ int ret, cookie; |
27719 |
-+ struct kdbus_conn *conn_a, *conn_b; |
27720 |
-+ struct pollfd fds[2]; |
27721 |
-+ uint64_t flags; |
27722 |
-+ int count; |
27723 |
-+ |
27724 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
27725 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
27726 |
-+ ASSERT_RETURN(conn_a && conn_b); |
27727 |
-+ |
27728 |
-+ flags = KDBUS_NAME_ALLOW_REPLACEMENT; |
27729 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.test", &flags); |
27730 |
-+ ASSERT_RETURN(ret == 0); |
27731 |
-+ |
27732 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.baz", NULL); |
27733 |
-+ ASSERT_RETURN(ret == 0); |
27734 |
-+ |
27735 |
-+ flags = KDBUS_NAME_QUEUE; |
27736 |
-+ ret = kdbus_name_acquire(conn_b, "foo.bar.baz", &flags); |
27737 |
-+ ASSERT_RETURN(ret == 0); |
27738 |
-+ |
27739 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL); |
27740 |
-+ ASSERT_RETURN(ret == 0); |
27741 |
-+ |
27742 |
-+ flags = 0; |
27743 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.double", &flags); |
27744 |
-+ ASSERT_RETURN(ret == 0); |
27745 |
-+ ASSERT_RETURN(!(flags & KDBUS_NAME_ACQUIRED)); |
27746 |
-+ |
27747 |
-+ ret = kdbus_name_release(conn_a, "foo.bar.double"); |
27748 |
-+ ASSERT_RETURN(ret == 0); |
27749 |
-+ |
27750 |
-+ ret = kdbus_name_release(conn_a, "foo.bar.double"); |
27751 |
-+ ASSERT_RETURN(ret == -ESRCH); |
27752 |
-+ |
27753 |
-+ ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | |
27754 |
-+ KDBUS_LIST_NAMES | |
27755 |
-+ KDBUS_LIST_QUEUED | |
27756 |
-+ KDBUS_LIST_ACTIVATORS); |
27757 |
-+ ASSERT_RETURN(ret == 0); |
27758 |
-+ |
27759 |
-+ ret = kdbus_add_match_empty(conn_a); |
27760 |
-+ ASSERT_RETURN(ret == 0); |
27761 |
-+ |
27762 |
-+ ret = kdbus_add_match_empty(conn_b); |
27763 |
-+ ASSERT_RETURN(ret == 0); |
27764 |
-+ |
27765 |
-+ cookie = 0; |
27766 |
-+ ret = kdbus_msg_send(conn_b, NULL, 0xc0000000 | cookie, 0, 0, 0, |
27767 |
-+ KDBUS_DST_ID_BROADCAST); |
27768 |
-+ ASSERT_RETURN(ret == 0); |
27769 |
-+ |
27770 |
-+ fds[0].fd = conn_a->fd; |
27771 |
-+ fds[1].fd = conn_b->fd; |
27772 |
-+ |
27773 |
-+ kdbus_printf("-- entering poll loop ...\n"); |
27774 |
-+ |
27775 |
-+ for (count = 0;; count++) { |
27776 |
-+ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
27777 |
-+ |
27778 |
-+ for (i = 0; i < nfds; i++) { |
27779 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27780 |
-+ fds[i].revents = 0; |
27781 |
-+ } |
27782 |
-+ |
27783 |
-+ ret = poll(fds, nfds, 3000); |
27784 |
-+ ASSERT_RETURN(ret >= 0); |
27785 |
-+ |
27786 |
-+ if (fds[0].revents & POLLIN) { |
27787 |
-+ if (count > 2) |
27788 |
-+ kdbus_name_release(conn_a, "foo.bar.baz"); |
27789 |
-+ |
27790 |
-+ ret = kdbus_msg_recv(conn_a, NULL, NULL); |
27791 |
-+ ASSERT_RETURN(ret == 0); |
27792 |
-+ ret = kdbus_msg_send(conn_a, NULL, |
27793 |
-+ 0xc0000000 | cookie++, |
27794 |
-+ 0, 0, 0, conn_b->id); |
27795 |
-+ ASSERT_RETURN(ret == 0); |
27796 |
-+ } |
27797 |
-+ |
27798 |
-+ if (fds[1].revents & POLLIN) { |
27799 |
-+ ret = kdbus_msg_recv(conn_b, NULL, NULL); |
27800 |
-+ ASSERT_RETURN(ret == 0); |
27801 |
-+ ret = kdbus_msg_send(conn_b, NULL, |
27802 |
-+ 0xc0000000 | cookie++, |
27803 |
-+ 0, 0, 0, conn_a->id); |
27804 |
-+ ASSERT_RETURN(ret == 0); |
27805 |
-+ } |
27806 |
-+ |
27807 |
-+ ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | |
27808 |
-+ KDBUS_LIST_NAMES | |
27809 |
-+ KDBUS_LIST_QUEUED | |
27810 |
-+ KDBUS_LIST_ACTIVATORS); |
27811 |
-+ ASSERT_RETURN(ret == 0); |
27812 |
-+ |
27813 |
-+ if (count > 10) |
27814 |
-+ break; |
27815 |
-+ } |
27816 |
-+ |
27817 |
-+ kdbus_printf("-- closing bus connections\n"); |
27818 |
-+ kdbus_conn_free(conn_a); |
27819 |
-+ kdbus_conn_free(conn_b); |
27820 |
-+ |
27821 |
-+ return TEST_OK; |
27822 |
-+} |
27823 |
-diff --git a/tools/testing/selftests/kdbus/test-connection.c b/tools/testing/selftests/kdbus/test-connection.c |
27824 |
-new file mode 100644 |
27825 |
-index 0000000..4688ce8 |
27826 |
---- /dev/null |
27827 |
-+++ b/tools/testing/selftests/kdbus/test-connection.c |
27828 |
-@@ -0,0 +1,597 @@ |
27829 |
-+#include <stdio.h> |
27830 |
-+#include <string.h> |
27831 |
-+#include <fcntl.h> |
27832 |
-+#include <stdlib.h> |
27833 |
-+#include <stddef.h> |
27834 |
-+#include <unistd.h> |
27835 |
-+#include <stdint.h> |
27836 |
-+#include <errno.h> |
27837 |
-+#include <assert.h> |
27838 |
-+#include <limits.h> |
27839 |
-+#include <sys/types.h> |
27840 |
-+#include <sys/capability.h> |
27841 |
-+#include <sys/mman.h> |
27842 |
-+#include <sys/syscall.h> |
27843 |
-+#include <sys/wait.h> |
27844 |
-+#include <stdbool.h> |
27845 |
-+ |
27846 |
-+#include "kdbus-api.h" |
27847 |
-+#include "kdbus-util.h" |
27848 |
-+#include "kdbus-enum.h" |
27849 |
-+#include "kdbus-test.h" |
27850 |
-+ |
27851 |
-+int kdbus_test_hello(struct kdbus_test_env *env) |
27852 |
-+{ |
27853 |
-+ struct kdbus_cmd_free cmd_free = {}; |
27854 |
-+ struct kdbus_cmd_hello hello; |
27855 |
-+ int fd, ret; |
27856 |
-+ |
27857 |
-+ memset(&hello, 0, sizeof(hello)); |
27858 |
-+ |
27859 |
-+ fd = open(env->buspath, O_RDWR|O_CLOEXEC); |
27860 |
-+ ASSERT_RETURN(fd >= 0); |
27861 |
-+ |
27862 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
27863 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27864 |
-+ hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
27865 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
27866 |
-+ hello.pool_size = POOL_SIZE; |
27867 |
-+ |
27868 |
-+ /* an unaligned hello must result in -EFAULT */ |
27869 |
-+ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) ((char *) &hello + 1)); |
27870 |
-+ ASSERT_RETURN(ret == -EFAULT); |
27871 |
-+ |
27872 |
-+ /* a size of 0 must return EMSGSIZE */ |
27873 |
-+ hello.size = 1; |
27874 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
27875 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27876 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27877 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27878 |
-+ |
27879 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
27880 |
-+ |
27881 |
-+ /* check faulty flags */ |
27882 |
-+ hello.flags = 1ULL << 32; |
27883 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27884 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27885 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27886 |
-+ |
27887 |
-+ /* check for faulty pool sizes */ |
27888 |
-+ hello.pool_size = 0; |
27889 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
27890 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27891 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27892 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27893 |
-+ |
27894 |
-+ hello.pool_size = 4097; |
27895 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27896 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27897 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27898 |
-+ |
27899 |
-+ hello.pool_size = POOL_SIZE; |
27900 |
-+ |
27901 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27902 |
-+ hello.offset = (__u64)-1; |
27903 |
-+ |
27904 |
-+ /* success test */ |
27905 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27906 |
-+ ASSERT_RETURN(ret == 0); |
27907 |
-+ |
27908 |
-+ /* The kernel should have returned some items */ |
27909 |
-+ ASSERT_RETURN(hello.offset != (__u64)-1); |
27910 |
-+ cmd_free.size = sizeof(cmd_free); |
27911 |
-+ cmd_free.offset = hello.offset; |
27912 |
-+ ret = kdbus_cmd_free(fd, &cmd_free); |
27913 |
-+ ASSERT_RETURN(ret >= 0); |
27914 |
-+ |
27915 |
-+ close(fd); |
27916 |
-+ |
27917 |
-+ fd = open(env->buspath, O_RDWR|O_CLOEXEC); |
27918 |
-+ ASSERT_RETURN(fd >= 0); |
27919 |
-+ |
27920 |
-+ /* no ACTIVATOR flag without a name */ |
27921 |
-+ hello.flags = KDBUS_HELLO_ACTIVATOR; |
27922 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27923 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27924 |
-+ |
27925 |
-+ close(fd); |
27926 |
-+ |
27927 |
-+ return TEST_OK; |
27928 |
-+} |
27929 |
-+ |
27930 |
-+int kdbus_test_byebye(struct kdbus_test_env *env) |
27931 |
-+{ |
27932 |
-+ struct kdbus_conn *conn; |
27933 |
-+ struct kdbus_cmd_recv cmd_recv = { .size = sizeof(cmd_recv) }; |
27934 |
-+ struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; |
27935 |
-+ int ret; |
27936 |
-+ |
27937 |
-+ /* create a 2nd connection */ |
27938 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
27939 |
-+ ASSERT_RETURN(conn != NULL); |
27940 |
-+ |
27941 |
-+ ret = kdbus_add_match_empty(conn); |
27942 |
-+ ASSERT_RETURN(ret == 0); |
27943 |
-+ |
27944 |
-+ ret = kdbus_add_match_empty(env->conn); |
27945 |
-+ ASSERT_RETURN(ret == 0); |
27946 |
-+ |
27947 |
-+ /* send over 1st connection */ |
27948 |
-+ ret = kdbus_msg_send(env->conn, NULL, 0, 0, 0, 0, |
27949 |
-+ KDBUS_DST_ID_BROADCAST); |
27950 |
-+ ASSERT_RETURN(ret == 0); |
27951 |
-+ |
27952 |
-+ /* say byebye on the 2nd, which must fail */ |
27953 |
-+ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
27954 |
-+ ASSERT_RETURN(ret == -EBUSY); |
27955 |
-+ |
27956 |
-+ /* receive the message */ |
27957 |
-+ ret = kdbus_cmd_recv(conn->fd, &cmd_recv); |
27958 |
-+ ASSERT_RETURN(ret == 0); |
27959 |
-+ |
27960 |
-+ ret = kdbus_free(conn, cmd_recv.msg.offset); |
27961 |
-+ ASSERT_RETURN(ret == 0); |
27962 |
-+ |
27963 |
-+ /* and try again */ |
27964 |
-+ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
27965 |
-+ ASSERT_RETURN(ret == 0); |
27966 |
-+ |
27967 |
-+ /* a 2nd try should result in -ECONNRESET */ |
27968 |
-+ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
27969 |
-+ ASSERT_RETURN(ret == -ECONNRESET); |
27970 |
-+ |
27971 |
-+ kdbus_conn_free(conn); |
27972 |
-+ |
27973 |
-+ return TEST_OK; |
27974 |
-+} |
27975 |
-+ |
27976 |
-+/* Get only the first item */ |
27977 |
-+static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, |
27978 |
-+ uint64_t type) |
27979 |
-+{ |
27980 |
-+ struct kdbus_item *item; |
27981 |
-+ |
27982 |
-+ KDBUS_ITEM_FOREACH(item, info, items) |
27983 |
-+ if (item->type == type) |
27984 |
-+ return item; |
27985 |
-+ |
27986 |
-+ return NULL; |
27987 |
-+} |
27988 |
-+ |
27989 |
-+static unsigned int kdbus_count_item(struct kdbus_info *info, |
27990 |
-+ uint64_t type) |
27991 |
-+{ |
27992 |
-+ unsigned int i = 0; |
27993 |
-+ const struct kdbus_item *item; |
27994 |
-+ |
27995 |
-+ KDBUS_ITEM_FOREACH(item, info, items) |
27996 |
-+ if (item->type == type) |
27997 |
-+ i++; |
27998 |
-+ |
27999 |
-+ return i; |
28000 |
-+} |
28001 |
-+ |
28002 |
-+static int kdbus_fuzz_conn_info(struct kdbus_test_env *env, int capable) |
28003 |
-+{ |
28004 |
-+ int ret; |
28005 |
-+ unsigned int cnt = 0; |
28006 |
-+ uint64_t offset = 0; |
28007 |
-+ struct kdbus_info *info; |
28008 |
-+ struct kdbus_conn *conn; |
28009 |
-+ struct kdbus_conn *privileged; |
28010 |
-+ const struct kdbus_item *item; |
28011 |
-+ uint64_t valid_flags = KDBUS_ATTACH_NAMES | |
28012 |
-+ KDBUS_ATTACH_CREDS | |
28013 |
-+ KDBUS_ATTACH_PIDS | |
28014 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION; |
28015 |
-+ |
28016 |
-+ uint64_t invalid_flags = KDBUS_ATTACH_NAMES | |
28017 |
-+ KDBUS_ATTACH_CREDS | |
28018 |
-+ KDBUS_ATTACH_PIDS | |
28019 |
-+ KDBUS_ATTACH_CAPS | |
28020 |
-+ KDBUS_ATTACH_CGROUP | |
28021 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION; |
28022 |
-+ |
28023 |
-+ struct kdbus_creds cached_creds; |
28024 |
-+ uid_t ruid, euid, suid; |
28025 |
-+ gid_t rgid, egid, sgid; |
28026 |
-+ |
28027 |
-+ getresuid(&ruid, &euid, &suid); |
28028 |
-+ getresgid(&rgid, &egid, &sgid); |
28029 |
-+ |
28030 |
-+ cached_creds.uid = ruid; |
28031 |
-+ cached_creds.euid = euid; |
28032 |
-+ cached_creds.suid = suid; |
28033 |
-+ cached_creds.fsuid = ruid; |
28034 |
-+ |
28035 |
-+ cached_creds.gid = rgid; |
28036 |
-+ cached_creds.egid = egid; |
28037 |
-+ cached_creds.sgid = sgid; |
28038 |
-+ cached_creds.fsgid = rgid; |
28039 |
-+ |
28040 |
-+ struct kdbus_pids cached_pids = { |
28041 |
-+ .pid = getpid(), |
28042 |
-+ .tid = syscall(SYS_gettid), |
28043 |
-+ .ppid = getppid(), |
28044 |
-+ }; |
28045 |
-+ |
28046 |
-+ ret = kdbus_conn_info(env->conn, env->conn->id, NULL, |
28047 |
-+ valid_flags, &offset); |
28048 |
-+ ASSERT_RETURN(ret == 0); |
28049 |
-+ |
28050 |
-+ info = (struct kdbus_info *)(env->conn->buf + offset); |
28051 |
-+ ASSERT_RETURN(info->id == env->conn->id); |
28052 |
-+ |
28053 |
-+ /* We do not have any well-known name */ |
28054 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_NAME); |
28055 |
-+ ASSERT_RETURN(item == NULL); |
28056 |
-+ |
28057 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CONN_DESCRIPTION); |
28058 |
-+ if (valid_flags & KDBUS_ATTACH_CONN_DESCRIPTION) { |
28059 |
-+ ASSERT_RETURN(item); |
28060 |
-+ } else { |
28061 |
-+ ASSERT_RETURN(item == NULL); |
28062 |
-+ } |
28063 |
-+ |
28064 |
-+ kdbus_free(env->conn, offset); |
28065 |
-+ |
28066 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28067 |
-+ ASSERT_RETURN(conn); |
28068 |
-+ |
28069 |
-+ privileged = kdbus_hello(env->buspath, 0, NULL, 0); |
28070 |
-+ ASSERT_RETURN(privileged); |
28071 |
-+ |
28072 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28073 |
-+ ASSERT_RETURN(ret == 0); |
28074 |
-+ |
28075 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28076 |
-+ ASSERT_RETURN(info->id == conn->id); |
28077 |
-+ |
28078 |
-+ /* We do not have any well-known name */ |
28079 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_NAME); |
28080 |
-+ ASSERT_RETURN(item == NULL); |
28081 |
-+ |
28082 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); |
28083 |
-+ if (valid_flags & KDBUS_ATTACH_CREDS) { |
28084 |
-+ ASSERT_RETURN(cnt == 1); |
28085 |
-+ |
28086 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28087 |
-+ ASSERT_RETURN(item); |
28088 |
-+ |
28089 |
-+ /* Compare received items with cached creds */ |
28090 |
-+ ASSERT_RETURN(memcmp(&item->creds, &cached_creds, |
28091 |
-+ sizeof(struct kdbus_creds)) == 0); |
28092 |
-+ } else { |
28093 |
-+ ASSERT_RETURN(cnt == 0); |
28094 |
-+ } |
28095 |
-+ |
28096 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28097 |
-+ if (valid_flags & KDBUS_ATTACH_PIDS) { |
28098 |
-+ ASSERT_RETURN(item); |
28099 |
-+ |
28100 |
-+ /* Compare item->pids with cached PIDs */ |
28101 |
-+ ASSERT_RETURN(item->pids.pid == cached_pids.pid && |
28102 |
-+ item->pids.tid == cached_pids.tid && |
28103 |
-+ item->pids.ppid == cached_pids.ppid); |
28104 |
-+ } else { |
28105 |
-+ ASSERT_RETURN(item == NULL); |
28106 |
-+ } |
28107 |
-+ |
28108 |
-+ /* We did not request KDBUS_ITEM_CAPS */ |
28109 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CAPS); |
28110 |
-+ ASSERT_RETURN(item == NULL); |
28111 |
-+ |
28112 |
-+ kdbus_free(conn, offset); |
28113 |
-+ |
28114 |
-+ ret = kdbus_name_acquire(conn, "com.example.a", NULL); |
28115 |
-+ ASSERT_RETURN(ret >= 0); |
28116 |
-+ |
28117 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28118 |
-+ ASSERT_RETURN(ret == 0); |
28119 |
-+ |
28120 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28121 |
-+ ASSERT_RETURN(info->id == conn->id); |
28122 |
-+ |
28123 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); |
28124 |
-+ if (valid_flags & KDBUS_ATTACH_NAMES) { |
28125 |
-+ ASSERT_RETURN(item && !strcmp(item->name.name, "com.example.a")); |
28126 |
-+ } else { |
28127 |
-+ ASSERT_RETURN(item == NULL); |
28128 |
-+ } |
28129 |
-+ |
28130 |
-+ kdbus_free(conn, offset); |
28131 |
-+ |
28132 |
-+ ret = kdbus_conn_info(conn, 0, "com.example.a", valid_flags, &offset); |
28133 |
-+ ASSERT_RETURN(ret == 0); |
28134 |
-+ |
28135 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28136 |
-+ ASSERT_RETURN(info->id == conn->id); |
28137 |
-+ |
28138 |
-+ kdbus_free(conn, offset); |
28139 |
-+ |
28140 |
-+ /* does not have the necessary caps to drop to unprivileged */ |
28141 |
-+ if (!capable) |
28142 |
-+ goto continue_test; |
28143 |
-+ |
28144 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
28145 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, |
28146 |
-+ valid_flags, &offset); |
28147 |
-+ ASSERT_EXIT(ret == 0); |
28148 |
-+ |
28149 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28150 |
-+ ASSERT_EXIT(info->id == conn->id); |
28151 |
-+ |
28152 |
-+ if (valid_flags & KDBUS_ATTACH_NAMES) { |
28153 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); |
28154 |
-+ ASSERT_EXIT(item && |
28155 |
-+ strcmp(item->name.name, |
28156 |
-+ "com.example.a") == 0); |
28157 |
-+ } |
28158 |
-+ |
28159 |
-+ if (valid_flags & KDBUS_ATTACH_CREDS) { |
28160 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28161 |
-+ ASSERT_EXIT(item); |
28162 |
-+ |
28163 |
-+ /* Compare received items with cached creds */ |
28164 |
-+ ASSERT_EXIT(memcmp(&item->creds, &cached_creds, |
28165 |
-+ sizeof(struct kdbus_creds)) == 0); |
28166 |
-+ } |
28167 |
-+ |
28168 |
-+ if (valid_flags & KDBUS_ATTACH_PIDS) { |
28169 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28170 |
-+ ASSERT_EXIT(item); |
28171 |
-+ |
28172 |
-+ /* |
28173 |
-+ * Compare item->pids with cached pids of |
28174 |
-+ * privileged one. |
28175 |
-+ * |
28176 |
-+ * cmd_info will always return cached pids. |
28177 |
-+ */ |
28178 |
-+ ASSERT_EXIT(item->pids.pid == cached_pids.pid && |
28179 |
-+ item->pids.tid == cached_pids.tid); |
28180 |
-+ } |
28181 |
-+ |
28182 |
-+ kdbus_free(conn, offset); |
28183 |
-+ |
28184 |
-+ /* |
28185 |
-+ * Use invalid_flags and make sure that userspace |
28186 |
-+ * do not play with us. |
28187 |
-+ */ |
28188 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, |
28189 |
-+ invalid_flags, &offset); |
28190 |
-+ ASSERT_EXIT(ret == 0); |
28191 |
-+ |
28192 |
-+ /* |
28193 |
-+ * Make sure that we return only one creds item and |
28194 |
-+ * it points to the cached creds. |
28195 |
-+ */ |
28196 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); |
28197 |
-+ if (invalid_flags & KDBUS_ATTACH_CREDS) { |
28198 |
-+ ASSERT_EXIT(cnt == 1); |
28199 |
-+ |
28200 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28201 |
-+ ASSERT_EXIT(item); |
28202 |
-+ |
28203 |
-+ /* Compare received items with cached creds */ |
28204 |
-+ ASSERT_EXIT(memcmp(&item->creds, &cached_creds, |
28205 |
-+ sizeof(struct kdbus_creds)) == 0); |
28206 |
-+ } else { |
28207 |
-+ ASSERT_EXIT(cnt == 0); |
28208 |
-+ } |
28209 |
-+ |
28210 |
-+ if (invalid_flags & KDBUS_ATTACH_PIDS) { |
28211 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_PIDS); |
28212 |
-+ ASSERT_EXIT(cnt == 1); |
28213 |
-+ |
28214 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28215 |
-+ ASSERT_EXIT(item); |
28216 |
-+ |
28217 |
-+ /* Compare item->pids with cached pids */ |
28218 |
-+ ASSERT_EXIT(item->pids.pid == cached_pids.pid && |
28219 |
-+ item->pids.tid == cached_pids.tid); |
28220 |
-+ } |
28221 |
-+ |
28222 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CGROUP); |
28223 |
-+ if (invalid_flags & KDBUS_ATTACH_CGROUP) { |
28224 |
-+ ASSERT_EXIT(cnt == 1); |
28225 |
-+ } else { |
28226 |
-+ ASSERT_EXIT(cnt == 0); |
28227 |
-+ } |
28228 |
-+ |
28229 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CAPS); |
28230 |
-+ if (invalid_flags & KDBUS_ATTACH_CAPS) { |
28231 |
-+ ASSERT_EXIT(cnt == 1); |
28232 |
-+ } else { |
28233 |
-+ ASSERT_EXIT(cnt == 0); |
28234 |
-+ } |
28235 |
-+ |
28236 |
-+ kdbus_free(conn, offset); |
28237 |
-+ }), |
28238 |
-+ ({ 0; })); |
28239 |
-+ ASSERT_RETURN(ret == 0); |
28240 |
-+ |
28241 |
-+continue_test: |
28242 |
-+ |
28243 |
-+ /* A second name */ |
28244 |
-+ ret = kdbus_name_acquire(conn, "com.example.b", NULL); |
28245 |
-+ ASSERT_RETURN(ret >= 0); |
28246 |
-+ |
28247 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28248 |
-+ ASSERT_RETURN(ret == 0); |
28249 |
-+ |
28250 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28251 |
-+ ASSERT_RETURN(info->id == conn->id); |
28252 |
-+ |
28253 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_OWNED_NAME); |
28254 |
-+ if (valid_flags & KDBUS_ATTACH_NAMES) { |
28255 |
-+ ASSERT_RETURN(cnt == 2); |
28256 |
-+ } else { |
28257 |
-+ ASSERT_RETURN(cnt == 0); |
28258 |
-+ } |
28259 |
-+ |
28260 |
-+ kdbus_free(conn, offset); |
28261 |
-+ |
28262 |
-+ ASSERT_RETURN(ret == 0); |
28263 |
-+ |
28264 |
-+ return 0; |
28265 |
-+} |
28266 |
-+ |
28267 |
-+int kdbus_test_conn_info(struct kdbus_test_env *env) |
28268 |
-+{ |
28269 |
-+ int ret; |
28270 |
-+ int have_caps; |
28271 |
-+ struct { |
28272 |
-+ struct kdbus_cmd_info cmd_info; |
28273 |
-+ |
28274 |
-+ struct { |
28275 |
-+ uint64_t size; |
28276 |
-+ uint64_t type; |
28277 |
-+ char str[64]; |
28278 |
-+ } name; |
28279 |
-+ } buf; |
28280 |
-+ |
28281 |
-+ buf.cmd_info.size = sizeof(struct kdbus_cmd_info); |
28282 |
-+ buf.cmd_info.flags = 0; |
28283 |
-+ buf.cmd_info.attach_flags = 0; |
28284 |
-+ buf.cmd_info.id = env->conn->id; |
28285 |
-+ |
28286 |
-+ ret = kdbus_conn_info(env->conn, env->conn->id, NULL, 0, NULL); |
28287 |
-+ ASSERT_RETURN(ret == 0); |
28288 |
-+ |
28289 |
-+ /* try to pass a name that is longer than the buffer's size */ |
28290 |
-+ buf.name.size = KDBUS_ITEM_HEADER_SIZE + 1; |
28291 |
-+ buf.name.type = KDBUS_ITEM_NAME; |
28292 |
-+ strcpy(buf.name.str, "foo.bar.bla"); |
28293 |
-+ |
28294 |
-+ buf.cmd_info.id = 0; |
28295 |
-+ buf.cmd_info.size = sizeof(buf.cmd_info) + buf.name.size; |
28296 |
-+ ret = kdbus_cmd_conn_info(env->conn->fd, (struct kdbus_cmd_info *) &buf); |
28297 |
-+ ASSERT_RETURN(ret == -EINVAL); |
28298 |
-+ |
28299 |
-+ /* Pass a non existent name */ |
28300 |
-+ ret = kdbus_conn_info(env->conn, 0, "non.existent.name", 0, NULL); |
28301 |
-+ ASSERT_RETURN(ret == -ESRCH); |
28302 |
-+ |
28303 |
-+ if (!all_uids_gids_are_mapped()) |
28304 |
-+ return TEST_SKIP; |
28305 |
-+ |
28306 |
-+ /* Test for caps here, so we run the previous test */ |
28307 |
-+ have_caps = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
28308 |
-+ ASSERT_RETURN(have_caps >= 0); |
28309 |
-+ |
28310 |
-+ ret = kdbus_fuzz_conn_info(env, have_caps); |
28311 |
-+ ASSERT_RETURN(ret == 0); |
28312 |
-+ |
28313 |
-+ /* Now if we have skipped some tests then let the user know */ |
28314 |
-+ if (!have_caps) |
28315 |
-+ return TEST_SKIP; |
28316 |
-+ |
28317 |
-+ return TEST_OK; |
28318 |
-+} |
28319 |
-+ |
28320 |
-+int kdbus_test_conn_update(struct kdbus_test_env *env) |
28321 |
-+{ |
28322 |
-+ struct kdbus_conn *conn; |
28323 |
-+ struct kdbus_msg *msg; |
28324 |
-+ int found = 0; |
28325 |
-+ int ret; |
28326 |
-+ |
28327 |
-+ /* |
28328 |
-+ * kdbus_hello() sets all attach flags. Receive a message by this |
28329 |
-+ * connection, and make sure a timestamp item (just to pick one) is |
28330 |
-+ * present. |
28331 |
-+ */ |
28332 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28333 |
-+ ASSERT_RETURN(conn); |
28334 |
-+ |
28335 |
-+ ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); |
28336 |
-+ ASSERT_RETURN(ret == 0); |
28337 |
-+ |
28338 |
-+ ret = kdbus_msg_recv(conn, &msg, NULL); |
28339 |
-+ ASSERT_RETURN(ret == 0); |
28340 |
-+ |
28341 |
-+ found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
28342 |
-+ ASSERT_RETURN(found == 1); |
28343 |
-+ |
28344 |
-+ kdbus_msg_free(msg); |
28345 |
-+ |
28346 |
-+ /* |
28347 |
-+ * Now, modify the attach flags and repeat the action. The item must |
28348 |
-+ * now be missing. |
28349 |
-+ */ |
28350 |
-+ found = 0; |
28351 |
-+ |
28352 |
-+ ret = kdbus_conn_update_attach_flags(conn, |
28353 |
-+ _KDBUS_ATTACH_ALL, |
28354 |
-+ _KDBUS_ATTACH_ALL & |
28355 |
-+ ~KDBUS_ATTACH_TIMESTAMP); |
28356 |
-+ ASSERT_RETURN(ret == 0); |
28357 |
-+ |
28358 |
-+ ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); |
28359 |
-+ ASSERT_RETURN(ret == 0); |
28360 |
-+ |
28361 |
-+ ret = kdbus_msg_recv(conn, &msg, NULL); |
28362 |
-+ ASSERT_RETURN(ret == 0); |
28363 |
-+ |
28364 |
-+ found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
28365 |
-+ ASSERT_RETURN(found == 0); |
28366 |
-+ |
28367 |
-+ /* Provide a bogus attach_flags value */ |
28368 |
-+ ret = kdbus_conn_update_attach_flags(conn, |
28369 |
-+ _KDBUS_ATTACH_ALL + 1, |
28370 |
-+ _KDBUS_ATTACH_ALL); |
28371 |
-+ ASSERT_RETURN(ret == -EINVAL); |
28372 |
-+ |
28373 |
-+ kdbus_msg_free(msg); |
28374 |
-+ |
28375 |
-+ kdbus_conn_free(conn); |
28376 |
-+ |
28377 |
-+ return TEST_OK; |
28378 |
-+} |
28379 |
-+ |
28380 |
-+int kdbus_test_writable_pool(struct kdbus_test_env *env) |
28381 |
-+{ |
28382 |
-+ struct kdbus_cmd_free cmd_free = {}; |
28383 |
-+ struct kdbus_cmd_hello hello; |
28384 |
-+ int fd, ret; |
28385 |
-+ void *map; |
28386 |
-+ |
28387 |
-+ fd = open(env->buspath, O_RDWR | O_CLOEXEC); |
28388 |
-+ ASSERT_RETURN(fd >= 0); |
28389 |
-+ |
28390 |
-+ memset(&hello, 0, sizeof(hello)); |
28391 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
28392 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28393 |
-+ hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
28394 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
28395 |
-+ hello.pool_size = POOL_SIZE; |
28396 |
-+ hello.offset = (__u64)-1; |
28397 |
-+ |
28398 |
-+ /* success test */ |
28399 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
28400 |
-+ ASSERT_RETURN(ret == 0); |
28401 |
-+ |
28402 |
-+ /* The kernel should have returned some items */ |
28403 |
-+ ASSERT_RETURN(hello.offset != (__u64)-1); |
28404 |
-+ cmd_free.size = sizeof(cmd_free); |
28405 |
-+ cmd_free.offset = hello.offset; |
28406 |
-+ ret = kdbus_cmd_free(fd, &cmd_free); |
28407 |
-+ ASSERT_RETURN(ret >= 0); |
28408 |
-+ |
28409 |
-+ /* pools cannot be mapped writable */ |
28410 |
-+ map = mmap(NULL, POOL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
28411 |
-+ ASSERT_RETURN(map == MAP_FAILED); |
28412 |
-+ |
28413 |
-+ /* pools can always be mapped readable */ |
28414 |
-+ map = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
28415 |
-+ ASSERT_RETURN(map != MAP_FAILED); |
28416 |
-+ |
28417 |
-+ /* make sure we cannot change protection masks to writable */ |
28418 |
-+ ret = mprotect(map, POOL_SIZE, PROT_READ | PROT_WRITE); |
28419 |
-+ ASSERT_RETURN(ret < 0); |
28420 |
-+ |
28421 |
-+ munmap(map, POOL_SIZE); |
28422 |
-+ close(fd); |
28423 |
-+ |
28424 |
-+ return TEST_OK; |
28425 |
-+} |
28426 |
-diff --git a/tools/testing/selftests/kdbus/test-daemon.c b/tools/testing/selftests/kdbus/test-daemon.c |
28427 |
-new file mode 100644 |
28428 |
-index 0000000..8bc2386 |
28429 |
---- /dev/null |
28430 |
-+++ b/tools/testing/selftests/kdbus/test-daemon.c |
28431 |
-@@ -0,0 +1,65 @@ |
28432 |
-+#include <stdio.h> |
28433 |
-+#include <string.h> |
28434 |
-+#include <time.h> |
28435 |
-+#include <fcntl.h> |
28436 |
-+#include <stdlib.h> |
28437 |
-+#include <stddef.h> |
28438 |
-+#include <unistd.h> |
28439 |
-+#include <stdint.h> |
28440 |
-+#include <errno.h> |
28441 |
-+#include <assert.h> |
28442 |
-+#include <poll.h> |
28443 |
-+#include <stdbool.h> |
28444 |
-+ |
28445 |
-+#include "kdbus-test.h" |
28446 |
-+#include "kdbus-util.h" |
28447 |
-+#include "kdbus-enum.h" |
28448 |
-+ |
28449 |
-+int kdbus_test_daemon(struct kdbus_test_env *env) |
28450 |
-+{ |
28451 |
-+ struct pollfd fds[2]; |
28452 |
-+ int count; |
28453 |
-+ int ret; |
28454 |
-+ |
28455 |
-+ /* This test doesn't make any sense in non-interactive mode */ |
28456 |
-+ if (!kdbus_util_verbose) |
28457 |
-+ return TEST_OK; |
28458 |
-+ |
28459 |
-+ printf("Created connection %llu on bus '%s'\n", |
28460 |
-+ (unsigned long long) env->conn->id, env->buspath); |
28461 |
-+ |
28462 |
-+ ret = kdbus_name_acquire(env->conn, "com.example.kdbus-test", NULL); |
28463 |
-+ ASSERT_RETURN(ret == 0); |
28464 |
-+ printf(" Aquired name: com.example.kdbus-test\n"); |
28465 |
-+ |
28466 |
-+ fds[0].fd = env->conn->fd; |
28467 |
-+ fds[1].fd = STDIN_FILENO; |
28468 |
-+ |
28469 |
-+ printf("Monitoring connections:\n"); |
28470 |
-+ |
28471 |
-+ for (count = 0;; count++) { |
28472 |
-+ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
28473 |
-+ |
28474 |
-+ for (i = 0; i < nfds; i++) { |
28475 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
28476 |
-+ fds[i].revents = 0; |
28477 |
-+ } |
28478 |
-+ |
28479 |
-+ ret = poll(fds, nfds, -1); |
28480 |
-+ if (ret <= 0) |
28481 |
-+ break; |
28482 |
-+ |
28483 |
-+ if (fds[0].revents & POLLIN) { |
28484 |
-+ ret = kdbus_msg_recv(env->conn, NULL, NULL); |
28485 |
-+ ASSERT_RETURN(ret == 0); |
28486 |
-+ } |
28487 |
-+ |
28488 |
-+ /* stdin */ |
28489 |
-+ if (fds[1].revents & POLLIN) |
28490 |
-+ break; |
28491 |
-+ } |
28492 |
-+ |
28493 |
-+ printf("Closing bus connection\n"); |
28494 |
-+ |
28495 |
-+ return TEST_OK; |
28496 |
-+} |
28497 |
-diff --git a/tools/testing/selftests/kdbus/test-endpoint.c b/tools/testing/selftests/kdbus/test-endpoint.c |
28498 |
-new file mode 100644 |
28499 |
-index 0000000..34a7be4 |
28500 |
---- /dev/null |
28501 |
-+++ b/tools/testing/selftests/kdbus/test-endpoint.c |
28502 |
-@@ -0,0 +1,352 @@ |
28503 |
-+#include <stdio.h> |
28504 |
-+#include <string.h> |
28505 |
-+#include <fcntl.h> |
28506 |
-+#include <stdlib.h> |
28507 |
-+#include <stddef.h> |
28508 |
-+#include <unistd.h> |
28509 |
-+#include <stdint.h> |
28510 |
-+#include <errno.h> |
28511 |
-+#include <assert.h> |
28512 |
-+#include <libgen.h> |
28513 |
-+#include <sys/capability.h> |
28514 |
-+#include <sys/wait.h> |
28515 |
-+#include <stdbool.h> |
28516 |
-+ |
28517 |
-+#include "kdbus-api.h" |
28518 |
-+#include "kdbus-util.h" |
28519 |
-+#include "kdbus-enum.h" |
28520 |
-+#include "kdbus-test.h" |
28521 |
-+ |
28522 |
-+#define KDBUS_SYSNAME_MAX_LEN 63 |
28523 |
-+ |
28524 |
-+static int install_name_add_match(struct kdbus_conn *conn, const char *name) |
28525 |
-+{ |
28526 |
-+ struct { |
28527 |
-+ struct kdbus_cmd_match cmd; |
28528 |
-+ struct { |
28529 |
-+ uint64_t size; |
28530 |
-+ uint64_t type; |
28531 |
-+ struct kdbus_notify_name_change chg; |
28532 |
-+ } item; |
28533 |
-+ char name[64]; |
28534 |
-+ } buf; |
28535 |
-+ int ret; |
28536 |
-+ |
28537 |
-+ /* install the match rule */ |
28538 |
-+ memset(&buf, 0, sizeof(buf)); |
28539 |
-+ buf.item.type = KDBUS_ITEM_NAME_ADD; |
28540 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
28541 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
28542 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
28543 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
28544 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
28545 |
-+ |
28546 |
-+ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
28547 |
-+ if (ret < 0) |
28548 |
-+ return ret; |
28549 |
-+ |
28550 |
-+ return 0; |
28551 |
-+} |
28552 |
-+ |
28553 |
-+static int create_endpoint(const char *buspath, uid_t uid, const char *name, |
28554 |
-+ uint64_t flags) |
28555 |
-+{ |
28556 |
-+ struct { |
28557 |
-+ struct kdbus_cmd cmd; |
28558 |
-+ |
28559 |
-+ /* name item */ |
28560 |
-+ struct { |
28561 |
-+ uint64_t size; |
28562 |
-+ uint64_t type; |
28563 |
-+ /* max should be KDBUS_SYSNAME_MAX_LEN */ |
28564 |
-+ char str[128]; |
28565 |
-+ } name; |
28566 |
-+ } ep_make; |
28567 |
-+ int fd, ret; |
28568 |
-+ |
28569 |
-+ fd = open(buspath, O_RDWR); |
28570 |
-+ if (fd < 0) |
28571 |
-+ return fd; |
28572 |
-+ |
28573 |
-+ memset(&ep_make, 0, sizeof(ep_make)); |
28574 |
-+ |
28575 |
-+ snprintf(ep_make.name.str, |
28576 |
-+ /* Use the KDBUS_SYSNAME_MAX_LEN or sizeof(str) */ |
28577 |
-+ KDBUS_SYSNAME_MAX_LEN > strlen(name) ? |
28578 |
-+ KDBUS_SYSNAME_MAX_LEN : sizeof(ep_make.name.str), |
28579 |
-+ "%u-%s", uid, name); |
28580 |
-+ |
28581 |
-+ ep_make.name.type = KDBUS_ITEM_MAKE_NAME; |
28582 |
-+ ep_make.name.size = KDBUS_ITEM_HEADER_SIZE + |
28583 |
-+ strlen(ep_make.name.str) + 1; |
28584 |
-+ |
28585 |
-+ ep_make.cmd.flags = flags; |
28586 |
-+ ep_make.cmd.size = sizeof(ep_make.cmd) + ep_make.name.size; |
28587 |
-+ |
28588 |
-+ ret = kdbus_cmd_endpoint_make(fd, &ep_make.cmd); |
28589 |
-+ if (ret < 0) { |
28590 |
-+ kdbus_printf("error creating endpoint: %d (%m)\n", ret); |
28591 |
-+ return ret; |
28592 |
-+ } |
28593 |
-+ |
28594 |
-+ return fd; |
28595 |
-+} |
28596 |
-+ |
28597 |
-+static int unpriv_test_custom_ep(const char *buspath) |
28598 |
-+{ |
28599 |
-+ int ret, ep_fd1, ep_fd2; |
28600 |
-+ char *ep1, *ep2, *tmp1, *tmp2; |
28601 |
-+ |
28602 |
-+ tmp1 = strdup(buspath); |
28603 |
-+ tmp2 = strdup(buspath); |
28604 |
-+ ASSERT_RETURN(tmp1 && tmp2); |
28605 |
-+ |
28606 |
-+ ret = asprintf(&ep1, "%s/%u-%s", dirname(tmp1), getuid(), "apps1"); |
28607 |
-+ ASSERT_RETURN(ret >= 0); |
28608 |
-+ |
28609 |
-+ ret = asprintf(&ep2, "%s/%u-%s", dirname(tmp2), getuid(), "apps2"); |
28610 |
-+ ASSERT_RETURN(ret >= 0); |
28611 |
-+ |
28612 |
-+ free(tmp1); |
28613 |
-+ free(tmp2); |
28614 |
-+ |
28615 |
-+ /* endpoint only accessible to current uid */ |
28616 |
-+ ep_fd1 = create_endpoint(buspath, getuid(), "apps1", 0); |
28617 |
-+ ASSERT_RETURN(ep_fd1 >= 0); |
28618 |
-+ |
28619 |
-+ /* endpoint world accessible */ |
28620 |
-+ ep_fd2 = create_endpoint(buspath, getuid(), "apps2", |
28621 |
-+ KDBUS_MAKE_ACCESS_WORLD); |
28622 |
-+ ASSERT_RETURN(ep_fd2 >= 0); |
28623 |
-+ |
28624 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
28625 |
-+ int ep_fd; |
28626 |
-+ struct kdbus_conn *ep_conn; |
28627 |
-+ |
28628 |
-+ /* |
28629 |
-+ * Make sure that we are not able to create custom |
28630 |
-+ * endpoints |
28631 |
-+ */ |
28632 |
-+ ep_fd = create_endpoint(buspath, getuid(), |
28633 |
-+ "unpriv_costum_ep", 0); |
28634 |
-+ ASSERT_EXIT(ep_fd == -EPERM); |
28635 |
-+ |
28636 |
-+ /* |
28637 |
-+ * Endpoint "apps1" only accessible to same users, |
28638 |
-+ * that own the endpoint. Access denied by VFS |
28639 |
-+ */ |
28640 |
-+ ep_conn = kdbus_hello(ep1, 0, NULL, 0); |
28641 |
-+ ASSERT_EXIT(!ep_conn && errno == EACCES); |
28642 |
-+ |
28643 |
-+ /* Endpoint "apps2" world accessible */ |
28644 |
-+ ep_conn = kdbus_hello(ep2, 0, NULL, 0); |
28645 |
-+ ASSERT_EXIT(ep_conn); |
28646 |
-+ |
28647 |
-+ kdbus_conn_free(ep_conn); |
28648 |
-+ |
28649 |
-+ _exit(EXIT_SUCCESS); |
28650 |
-+ }), |
28651 |
-+ ({ 0; })); |
28652 |
-+ ASSERT_RETURN(ret == 0); |
28653 |
-+ |
28654 |
-+ close(ep_fd1); |
28655 |
-+ close(ep_fd2); |
28656 |
-+ free(ep1); |
28657 |
-+ free(ep2); |
28658 |
-+ |
28659 |
-+ return 0; |
28660 |
-+} |
28661 |
-+ |
28662 |
-+static int update_endpoint(int fd, const char *name) |
28663 |
-+{ |
28664 |
-+ int len = strlen(name) + 1; |
28665 |
-+ struct { |
28666 |
-+ struct kdbus_cmd cmd; |
28667 |
-+ |
28668 |
-+ /* name item */ |
28669 |
-+ struct { |
28670 |
-+ uint64_t size; |
28671 |
-+ uint64_t type; |
28672 |
-+ char str[KDBUS_ALIGN8(len)]; |
28673 |
-+ } name; |
28674 |
-+ |
28675 |
-+ struct { |
28676 |
-+ uint64_t size; |
28677 |
-+ uint64_t type; |
28678 |
-+ struct kdbus_policy_access access; |
28679 |
-+ } access; |
28680 |
-+ } ep_update; |
28681 |
-+ int ret; |
28682 |
-+ |
28683 |
-+ memset(&ep_update, 0, sizeof(ep_update)); |
28684 |
-+ |
28685 |
-+ ep_update.name.size = KDBUS_ITEM_HEADER_SIZE + len; |
28686 |
-+ ep_update.name.type = KDBUS_ITEM_NAME; |
28687 |
-+ strncpy(ep_update.name.str, name, sizeof(ep_update.name.str) - 1); |
28688 |
-+ |
28689 |
-+ ep_update.access.size = sizeof(ep_update.access); |
28690 |
-+ ep_update.access.type = KDBUS_ITEM_POLICY_ACCESS; |
28691 |
-+ ep_update.access.access.type = KDBUS_POLICY_ACCESS_WORLD; |
28692 |
-+ ep_update.access.access.access = KDBUS_POLICY_SEE; |
28693 |
-+ |
28694 |
-+ ep_update.cmd.size = sizeof(ep_update); |
28695 |
-+ |
28696 |
-+ ret = kdbus_cmd_endpoint_update(fd, &ep_update.cmd); |
28697 |
-+ if (ret < 0) { |
28698 |
-+ kdbus_printf("error updating endpoint: %d (%m)\n", ret); |
28699 |
-+ return ret; |
28700 |
-+ } |
28701 |
-+ |
28702 |
-+ return 0; |
28703 |
-+} |
28704 |
-+ |
28705 |
-+int kdbus_test_custom_endpoint(struct kdbus_test_env *env) |
28706 |
-+{ |
28707 |
-+ char *ep, *tmp; |
28708 |
-+ int ret, ep_fd; |
28709 |
-+ struct kdbus_msg *msg; |
28710 |
-+ struct kdbus_conn *ep_conn; |
28711 |
-+ struct kdbus_conn *reader; |
28712 |
-+ const char *name = "foo.bar.baz"; |
28713 |
-+ const char *epname = "foo"; |
28714 |
-+ char fake_ep[KDBUS_SYSNAME_MAX_LEN + 1] = {'\0'}; |
28715 |
-+ |
28716 |
-+ memset(fake_ep, 'X', sizeof(fake_ep) - 1); |
28717 |
-+ |
28718 |
-+ /* Try to create a custom endpoint with a long name */ |
28719 |
-+ ret = create_endpoint(env->buspath, getuid(), fake_ep, 0); |
28720 |
-+ ASSERT_RETURN(ret == -ENAMETOOLONG); |
28721 |
-+ |
28722 |
-+ /* Try to create a custom endpoint with a different uid */ |
28723 |
-+ ret = create_endpoint(env->buspath, getuid() + 1, "foobar", 0); |
28724 |
-+ ASSERT_RETURN(ret == -EINVAL); |
28725 |
-+ |
28726 |
-+ /* create a custom endpoint, and open a connection on it */ |
28727 |
-+ ep_fd = create_endpoint(env->buspath, getuid(), "foo", 0); |
28728 |
-+ ASSERT_RETURN(ep_fd >= 0); |
28729 |
-+ |
28730 |
-+ tmp = strdup(env->buspath); |
28731 |
-+ ASSERT_RETURN(tmp); |
28732 |
-+ |
28733 |
-+ ret = asprintf(&ep, "%s/%u-%s", dirname(tmp), getuid(), epname); |
28734 |
-+ free(tmp); |
28735 |
-+ ASSERT_RETURN(ret >= 0); |
28736 |
-+ |
28737 |
-+ /* Register a connection that listen to broadcasts */ |
28738 |
-+ reader = kdbus_hello(ep, 0, NULL, 0); |
28739 |
-+ ASSERT_RETURN(reader); |
28740 |
-+ |
28741 |
-+ /* Register to kernel signals */ |
28742 |
-+ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, |
28743 |
-+ KDBUS_MATCH_ID_ANY); |
28744 |
-+ ASSERT_RETURN(ret == 0); |
28745 |
-+ |
28746 |
-+ ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, |
28747 |
-+ KDBUS_MATCH_ID_ANY); |
28748 |
-+ ASSERT_RETURN(ret == 0); |
28749 |
-+ |
28750 |
-+ ret = install_name_add_match(reader, name); |
28751 |
-+ ASSERT_RETURN(ret == 0); |
28752 |
-+ |
28753 |
-+ /* Monitor connections are not supported on custom endpoints */ |
28754 |
-+ ep_conn = kdbus_hello(ep, KDBUS_HELLO_MONITOR, NULL, 0); |
28755 |
-+ ASSERT_RETURN(!ep_conn && errno == EOPNOTSUPP); |
28756 |
-+ |
28757 |
-+ ep_conn = kdbus_hello(ep, 0, NULL, 0); |
28758 |
-+ ASSERT_RETURN(ep_conn); |
28759 |
-+ |
28760 |
-+ /* Check that the reader got the IdAdd notification */ |
28761 |
-+ ret = kdbus_msg_recv(reader, &msg, NULL); |
28762 |
-+ ASSERT_RETURN(ret == 0); |
28763 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD); |
28764 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == ep_conn->id); |
28765 |
-+ kdbus_msg_free(msg); |
28766 |
-+ |
28767 |
-+ /* |
28768 |
-+ * Add a name add match on the endpoint connection, acquire name from |
28769 |
-+ * the unfiltered connection, and make sure the filtered connection |
28770 |
-+ * did not get the notification on the name owner change. Also, the |
28771 |
-+ * endpoint connection may not be able to call conn_info, neither on |
28772 |
-+ * the name nor on the ID. |
28773 |
-+ */ |
28774 |
-+ ret = install_name_add_match(ep_conn, name); |
28775 |
-+ ASSERT_RETURN(ret == 0); |
28776 |
-+ |
28777 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
28778 |
-+ ASSERT_RETURN(ret == 0); |
28779 |
-+ |
28780 |
-+ ret = kdbus_msg_recv(ep_conn, NULL, NULL); |
28781 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
28782 |
-+ |
28783 |
-+ ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); |
28784 |
-+ ASSERT_RETURN(ret == -ESRCH); |
28785 |
-+ |
28786 |
-+ ret = kdbus_conn_info(ep_conn, 0, "random.crappy.name", 0, NULL); |
28787 |
-+ ASSERT_RETURN(ret == -ESRCH); |
28788 |
-+ |
28789 |
-+ ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); |
28790 |
-+ ASSERT_RETURN(ret == -ENXIO); |
28791 |
-+ |
28792 |
-+ ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL); |
28793 |
-+ ASSERT_RETURN(ret == -ENXIO); |
28794 |
-+ |
28795 |
-+ /* Check that the reader did not receive the name notification */ |
28796 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
28797 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
28798 |
-+ |
28799 |
-+ /* |
28800 |
-+ * Release the name again, update the custom endpoint policy, |
28801 |
-+ * and try again. This time, the connection on the custom endpoint |
28802 |
-+ * should have gotten it. |
28803 |
-+ */ |
28804 |
-+ ret = kdbus_name_release(env->conn, name); |
28805 |
-+ ASSERT_RETURN(ret == 0); |
28806 |
-+ |
28807 |
-+ /* Check that the reader did not receive the name notification */ |
28808 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
28809 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
28810 |
-+ |
28811 |
-+ ret = update_endpoint(ep_fd, name); |
28812 |
-+ ASSERT_RETURN(ret == 0); |
28813 |
-+ |
28814 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
28815 |
-+ ASSERT_RETURN(ret == 0); |
28816 |
-+ |
28817 |
-+ ret = kdbus_msg_recv(ep_conn, &msg, NULL); |
28818 |
-+ ASSERT_RETURN(ret == 0); |
28819 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); |
28820 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); |
28821 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); |
28822 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
28823 |
-+ kdbus_msg_free(msg); |
28824 |
-+ |
28825 |
-+ ret = kdbus_msg_recv(reader, &msg, NULL); |
28826 |
-+ ASSERT_RETURN(ret == 0); |
28827 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
28828 |
-+ |
28829 |
-+ kdbus_msg_free(msg); |
28830 |
-+ |
28831 |
-+ ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); |
28832 |
-+ ASSERT_RETURN(ret == 0); |
28833 |
-+ |
28834 |
-+ ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); |
28835 |
-+ ASSERT_RETURN(ret == 0); |
28836 |
-+ |
28837 |
-+ /* If we have privileges test custom endpoints */ |
28838 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
28839 |
-+ ASSERT_RETURN(ret >= 0); |
28840 |
-+ |
28841 |
-+ /* |
28842 |
-+ * All uids/gids are mapped and we have the necessary caps |
28843 |
-+ */ |
28844 |
-+ if (ret && all_uids_gids_are_mapped()) { |
28845 |
-+ ret = unpriv_test_custom_ep(env->buspath); |
28846 |
-+ ASSERT_RETURN(ret == 0); |
28847 |
-+ } |
28848 |
-+ |
28849 |
-+ kdbus_conn_free(reader); |
28850 |
-+ kdbus_conn_free(ep_conn); |
28851 |
-+ close(ep_fd); |
28852 |
-+ |
28853 |
-+ return TEST_OK; |
28854 |
-+} |
28855 |
-diff --git a/tools/testing/selftests/kdbus/test-fd.c b/tools/testing/selftests/kdbus/test-fd.c |
28856 |
-new file mode 100644 |
28857 |
-index 0000000..2ae0f5a |
28858 |
---- /dev/null |
28859 |
-+++ b/tools/testing/selftests/kdbus/test-fd.c |
28860 |
-@@ -0,0 +1,789 @@ |
28861 |
-+#include <stdio.h> |
28862 |
-+#include <string.h> |
28863 |
-+#include <time.h> |
28864 |
-+#include <fcntl.h> |
28865 |
-+#include <stdlib.h> |
28866 |
-+#include <stdbool.h> |
28867 |
-+#include <stddef.h> |
28868 |
-+#include <unistd.h> |
28869 |
-+#include <stdint.h> |
28870 |
-+#include <errno.h> |
28871 |
-+#include <assert.h> |
28872 |
-+#include <sys/types.h> |
28873 |
-+#include <sys/mman.h> |
28874 |
-+#include <sys/socket.h> |
28875 |
-+#include <sys/wait.h> |
28876 |
-+ |
28877 |
-+#include "kdbus-api.h" |
28878 |
-+#include "kdbus-test.h" |
28879 |
-+#include "kdbus-util.h" |
28880 |
-+#include "kdbus-enum.h" |
28881 |
-+ |
28882 |
-+#define KDBUS_MSG_MAX_ITEMS 128 |
28883 |
-+#define KDBUS_USER_MAX_CONN 256 |
28884 |
-+ |
28885 |
-+/* maximum number of inflight fds in a target queue per user */ |
28886 |
-+#define KDBUS_CONN_MAX_FDS_PER_USER 16 |
28887 |
-+ |
28888 |
-+/* maximum number of memfd items per message */ |
28889 |
-+#define KDBUS_MSG_MAX_MEMFD_ITEMS 16 |
28890 |
-+ |
28891 |
-+static int make_msg_payload_dbus(uint64_t src_id, uint64_t dst_id, |
28892 |
-+ uint64_t msg_size, |
28893 |
-+ struct kdbus_msg **msg_dbus) |
28894 |
-+{ |
28895 |
-+ struct kdbus_msg *msg; |
28896 |
-+ |
28897 |
-+ msg = malloc(msg_size); |
28898 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
28899 |
-+ |
28900 |
-+ memset(msg, 0, msg_size); |
28901 |
-+ msg->size = msg_size; |
28902 |
-+ msg->src_id = src_id; |
28903 |
-+ msg->dst_id = dst_id; |
28904 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
28905 |
-+ |
28906 |
-+ *msg_dbus = msg; |
28907 |
-+ |
28908 |
-+ return 0; |
28909 |
-+} |
28910 |
-+ |
28911 |
-+static void make_item_memfds(struct kdbus_item *item, |
28912 |
-+ int *memfds, size_t memfd_size) |
28913 |
-+{ |
28914 |
-+ size_t i; |
28915 |
-+ |
28916 |
-+ for (i = 0; i < memfd_size; i++) { |
28917 |
-+ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
28918 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
28919 |
-+ sizeof(struct kdbus_memfd); |
28920 |
-+ item->memfd.fd = memfds[i]; |
28921 |
-+ item->memfd.size = sizeof(uint64_t); /* const size */ |
28922 |
-+ item = KDBUS_ITEM_NEXT(item); |
28923 |
-+ } |
28924 |
-+} |
28925 |
-+ |
28926 |
-+static void make_item_fds(struct kdbus_item *item, |
28927 |
-+ int *fd_array, size_t fd_size) |
28928 |
-+{ |
28929 |
-+ size_t i; |
28930 |
-+ item->type = KDBUS_ITEM_FDS; |
28931 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + (sizeof(int) * fd_size); |
28932 |
-+ |
28933 |
-+ for (i = 0; i < fd_size; i++) |
28934 |
-+ item->fds[i] = fd_array[i]; |
28935 |
-+} |
28936 |
-+ |
28937 |
-+static int memfd_write(const char *name, void *buf, size_t bufsize) |
28938 |
-+{ |
28939 |
-+ ssize_t ret; |
28940 |
-+ int memfd; |
28941 |
-+ |
28942 |
-+ memfd = sys_memfd_create(name, 0); |
28943 |
-+ ASSERT_RETURN_VAL(memfd >= 0, memfd); |
28944 |
-+ |
28945 |
-+ ret = write(memfd, buf, bufsize); |
28946 |
-+ ASSERT_RETURN_VAL(ret == (ssize_t)bufsize, -EAGAIN); |
28947 |
-+ |
28948 |
-+ ret = sys_memfd_seal_set(memfd); |
28949 |
-+ ASSERT_RETURN_VAL(ret == 0, -errno); |
28950 |
-+ |
28951 |
-+ return memfd; |
28952 |
-+} |
28953 |
-+ |
28954 |
-+static int send_memfds(struct kdbus_conn *conn, uint64_t dst_id, |
28955 |
-+ int *memfds_array, size_t memfd_count) |
28956 |
-+{ |
28957 |
-+ struct kdbus_cmd_send cmd = {}; |
28958 |
-+ struct kdbus_item *item; |
28959 |
-+ struct kdbus_msg *msg; |
28960 |
-+ uint64_t size; |
28961 |
-+ int ret; |
28962 |
-+ |
28963 |
-+ size = sizeof(struct kdbus_msg); |
28964 |
-+ size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
28965 |
-+ |
28966 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
28967 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
28968 |
-+ |
28969 |
-+ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
28970 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
28971 |
-+ |
28972 |
-+ item = msg->items; |
28973 |
-+ |
28974 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
28975 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
28976 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
28977 |
-+ item = KDBUS_ITEM_NEXT(item); |
28978 |
-+ |
28979 |
-+ msg->flags |= KDBUS_MSG_SIGNAL; |
28980 |
-+ } |
28981 |
-+ |
28982 |
-+ make_item_memfds(item, memfds_array, memfd_count); |
28983 |
-+ |
28984 |
-+ cmd.size = sizeof(cmd); |
28985 |
-+ cmd.msg_address = (uintptr_t)msg; |
28986 |
-+ |
28987 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
28988 |
-+ if (ret < 0) { |
28989 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
28990 |
-+ return ret; |
28991 |
-+ } |
28992 |
-+ |
28993 |
-+ free(msg); |
28994 |
-+ return 0; |
28995 |
-+} |
28996 |
-+ |
28997 |
-+static int send_fds(struct kdbus_conn *conn, uint64_t dst_id, |
28998 |
-+ int *fd_array, size_t fd_count) |
28999 |
-+{ |
29000 |
-+ struct kdbus_cmd_send cmd = {}; |
29001 |
-+ struct kdbus_item *item; |
29002 |
-+ struct kdbus_msg *msg; |
29003 |
-+ uint64_t size; |
29004 |
-+ int ret; |
29005 |
-+ |
29006 |
-+ size = sizeof(struct kdbus_msg); |
29007 |
-+ size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count); |
29008 |
-+ |
29009 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
29010 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29011 |
-+ |
29012 |
-+ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29013 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
29014 |
-+ |
29015 |
-+ item = msg->items; |
29016 |
-+ |
29017 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
29018 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
29019 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29020 |
-+ item = KDBUS_ITEM_NEXT(item); |
29021 |
-+ |
29022 |
-+ msg->flags |= KDBUS_MSG_SIGNAL; |
29023 |
-+ } |
29024 |
-+ |
29025 |
-+ make_item_fds(item, fd_array, fd_count); |
29026 |
-+ |
29027 |
-+ cmd.size = sizeof(cmd); |
29028 |
-+ cmd.msg_address = (uintptr_t)msg; |
29029 |
-+ |
29030 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
29031 |
-+ if (ret < 0) { |
29032 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
29033 |
-+ return ret; |
29034 |
-+ } |
29035 |
-+ |
29036 |
-+ free(msg); |
29037 |
-+ return ret; |
29038 |
-+} |
29039 |
-+ |
29040 |
-+static int send_fds_memfds(struct kdbus_conn *conn, uint64_t dst_id, |
29041 |
-+ int *fds_array, size_t fd_count, |
29042 |
-+ int *memfds_array, size_t memfd_count) |
29043 |
-+{ |
29044 |
-+ struct kdbus_cmd_send cmd = {}; |
29045 |
-+ struct kdbus_item *item; |
29046 |
-+ struct kdbus_msg *msg; |
29047 |
-+ uint64_t size; |
29048 |
-+ int ret; |
29049 |
-+ |
29050 |
-+ size = sizeof(struct kdbus_msg); |
29051 |
-+ size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
29052 |
-+ size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count); |
29053 |
-+ |
29054 |
-+ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29055 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
29056 |
-+ |
29057 |
-+ item = msg->items; |
29058 |
-+ |
29059 |
-+ make_item_fds(item, fds_array, fd_count); |
29060 |
-+ item = KDBUS_ITEM_NEXT(item); |
29061 |
-+ make_item_memfds(item, memfds_array, memfd_count); |
29062 |
-+ |
29063 |
-+ cmd.size = sizeof(cmd); |
29064 |
-+ cmd.msg_address = (uintptr_t)msg; |
29065 |
-+ |
29066 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
29067 |
-+ if (ret < 0) { |
29068 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
29069 |
-+ return ret; |
29070 |
-+ } |
29071 |
-+ |
29072 |
-+ free(msg); |
29073 |
-+ return ret; |
29074 |
-+} |
29075 |
-+ |
29076 |
-+/* Return the number of received fds */ |
29077 |
-+static unsigned int kdbus_item_get_nfds(struct kdbus_msg *msg) |
29078 |
-+{ |
29079 |
-+ unsigned int fds = 0; |
29080 |
-+ const struct kdbus_item *item; |
29081 |
-+ |
29082 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
29083 |
-+ switch (item->type) { |
29084 |
-+ case KDBUS_ITEM_FDS: { |
29085 |
-+ fds += (item->size - KDBUS_ITEM_HEADER_SIZE) / |
29086 |
-+ sizeof(int); |
29087 |
-+ break; |
29088 |
-+ } |
29089 |
-+ |
29090 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: |
29091 |
-+ fds++; |
29092 |
-+ break; |
29093 |
-+ |
29094 |
-+ default: |
29095 |
-+ break; |
29096 |
-+ } |
29097 |
-+ } |
29098 |
-+ |
29099 |
-+ return fds; |
29100 |
-+} |
29101 |
-+ |
29102 |
-+static struct kdbus_msg * |
29103 |
-+get_kdbus_msg_with_fd(struct kdbus_conn *conn_src, |
29104 |
-+ uint64_t dst_id, uint64_t cookie, int fd) |
29105 |
-+{ |
29106 |
-+ int ret; |
29107 |
-+ uint64_t size; |
29108 |
-+ struct kdbus_item *item; |
29109 |
-+ struct kdbus_msg *msg; |
29110 |
-+ |
29111 |
-+ size = sizeof(struct kdbus_msg); |
29112 |
-+ if (fd >= 0) |
29113 |
-+ size += KDBUS_ITEM_SIZE(sizeof(int)); |
29114 |
-+ |
29115 |
-+ ret = make_msg_payload_dbus(conn_src->id, dst_id, size, &msg); |
29116 |
-+ ASSERT_RETURN_VAL(ret == 0, NULL); |
29117 |
-+ |
29118 |
-+ msg->cookie = cookie; |
29119 |
-+ |
29120 |
-+ if (fd >= 0) { |
29121 |
-+ item = msg->items; |
29122 |
-+ |
29123 |
-+ make_item_fds(item, (int *)&fd, 1); |
29124 |
-+ } |
29125 |
-+ |
29126 |
-+ return msg; |
29127 |
-+} |
29128 |
-+ |
29129 |
-+static int kdbus_test_no_fds(struct kdbus_test_env *env, |
29130 |
-+ int *fds, int *memfd) |
29131 |
-+{ |
29132 |
-+ pid_t pid; |
29133 |
-+ int ret, status; |
29134 |
-+ uint64_t cookie; |
29135 |
-+ int connfd1, connfd2; |
29136 |
-+ struct kdbus_msg *msg, *msg_sync_reply; |
29137 |
-+ struct kdbus_cmd_hello hello; |
29138 |
-+ struct kdbus_conn *conn_src, *conn_dst, *conn_dummy; |
29139 |
-+ struct kdbus_cmd_send cmd = {}; |
29140 |
-+ struct kdbus_cmd_free cmd_free = {}; |
29141 |
-+ |
29142 |
-+ conn_src = kdbus_hello(env->buspath, 0, NULL, 0); |
29143 |
-+ ASSERT_RETURN(conn_src); |
29144 |
-+ |
29145 |
-+ connfd1 = open(env->buspath, O_RDWR|O_CLOEXEC); |
29146 |
-+ ASSERT_RETURN(connfd1 >= 0); |
29147 |
-+ |
29148 |
-+ connfd2 = open(env->buspath, O_RDWR|O_CLOEXEC); |
29149 |
-+ ASSERT_RETURN(connfd2 >= 0); |
29150 |
-+ |
29151 |
-+ /* |
29152 |
-+ * Create connections without KDBUS_HELLO_ACCEPT_FD |
29153 |
-+ * to test if send fd operations are blocked |
29154 |
-+ */ |
29155 |
-+ conn_dst = malloc(sizeof(*conn_dst)); |
29156 |
-+ ASSERT_RETURN(conn_dst); |
29157 |
-+ |
29158 |
-+ conn_dummy = malloc(sizeof(*conn_dummy)); |
29159 |
-+ ASSERT_RETURN(conn_dummy); |
29160 |
-+ |
29161 |
-+ memset(&hello, 0, sizeof(hello)); |
29162 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
29163 |
-+ hello.pool_size = POOL_SIZE; |
29164 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
29165 |
-+ |
29166 |
-+ ret = kdbus_cmd_hello(connfd1, &hello); |
29167 |
-+ ASSERT_RETURN(ret == 0); |
29168 |
-+ |
29169 |
-+ cmd_free.size = sizeof(cmd_free); |
29170 |
-+ cmd_free.offset = hello.offset; |
29171 |
-+ ret = kdbus_cmd_free(connfd1, &cmd_free); |
29172 |
-+ ASSERT_RETURN(ret >= 0); |
29173 |
-+ |
29174 |
-+ conn_dst->fd = connfd1; |
29175 |
-+ conn_dst->id = hello.id; |
29176 |
-+ |
29177 |
-+ memset(&hello, 0, sizeof(hello)); |
29178 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
29179 |
-+ hello.pool_size = POOL_SIZE; |
29180 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
29181 |
-+ |
29182 |
-+ ret = kdbus_cmd_hello(connfd2, &hello); |
29183 |
-+ ASSERT_RETURN(ret == 0); |
29184 |
-+ |
29185 |
-+ cmd_free.size = sizeof(cmd_free); |
29186 |
-+ cmd_free.offset = hello.offset; |
29187 |
-+ ret = kdbus_cmd_free(connfd2, &cmd_free); |
29188 |
-+ ASSERT_RETURN(ret >= 0); |
29189 |
-+ |
29190 |
-+ conn_dummy->fd = connfd2; |
29191 |
-+ conn_dummy->id = hello.id; |
29192 |
-+ |
29193 |
-+ conn_dst->buf = mmap(NULL, POOL_SIZE, PROT_READ, |
29194 |
-+ MAP_SHARED, connfd1, 0); |
29195 |
-+ ASSERT_RETURN(conn_dst->buf != MAP_FAILED); |
29196 |
-+ |
29197 |
-+ conn_dummy->buf = mmap(NULL, POOL_SIZE, PROT_READ, |
29198 |
-+ MAP_SHARED, connfd2, 0); |
29199 |
-+ ASSERT_RETURN(conn_dummy->buf != MAP_FAILED); |
29200 |
-+ |
29201 |
-+ /* |
29202 |
-+ * Send fds to connection that do not accept fd passing |
29203 |
-+ */ |
29204 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29205 |
-+ ASSERT_RETURN(ret == -ECOMM); |
29206 |
-+ |
29207 |
-+ /* |
29208 |
-+ * memfd are kdbus payload |
29209 |
-+ */ |
29210 |
-+ ret = send_memfds(conn_src, conn_dst->id, memfd, 1); |
29211 |
-+ ASSERT_RETURN(ret == 0); |
29212 |
-+ |
29213 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 100, NULL, NULL); |
29214 |
-+ ASSERT_RETURN(ret == 0); |
29215 |
-+ |
29216 |
-+ cookie = time(NULL); |
29217 |
-+ |
29218 |
-+ pid = fork(); |
29219 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
29220 |
-+ |
29221 |
-+ if (pid == 0) { |
29222 |
-+ struct timespec now; |
29223 |
-+ |
29224 |
-+ /* |
29225 |
-+ * A sync send/reply to a connection that do not |
29226 |
-+ * accept fds should fail if it contains an fd |
29227 |
-+ */ |
29228 |
-+ msg_sync_reply = get_kdbus_msg_with_fd(conn_dst, |
29229 |
-+ conn_dummy->id, |
29230 |
-+ cookie, fds[0]); |
29231 |
-+ ASSERT_EXIT(msg_sync_reply); |
29232 |
-+ |
29233 |
-+ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); |
29234 |
-+ ASSERT_EXIT(ret == 0); |
29235 |
-+ |
29236 |
-+ msg_sync_reply->timeout_ns = now.tv_sec * 1000000000ULL + |
29237 |
-+ now.tv_nsec + 100000000ULL; |
29238 |
-+ msg_sync_reply->flags = KDBUS_MSG_EXPECT_REPLY; |
29239 |
-+ |
29240 |
-+ memset(&cmd, 0, sizeof(cmd)); |
29241 |
-+ cmd.size = sizeof(cmd); |
29242 |
-+ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29243 |
-+ cmd.flags = KDBUS_SEND_SYNC_REPLY; |
29244 |
-+ |
29245 |
-+ ret = kdbus_cmd_send(conn_dst->fd, &cmd); |
29246 |
-+ ASSERT_EXIT(ret == -ECOMM); |
29247 |
-+ |
29248 |
-+ /* |
29249 |
-+ * Now send a normal message, but the sync reply |
29250 |
-+ * will fail since it contains an fd that the |
29251 |
-+ * original sender do not want. |
29252 |
-+ * |
29253 |
-+ * The original sender will fail with -ETIMEDOUT |
29254 |
-+ */ |
29255 |
-+ cookie++; |
29256 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
29257 |
-+ KDBUS_MSG_EXPECT_REPLY, |
29258 |
-+ 5000000000ULL, 0, conn_src->id, -1); |
29259 |
-+ ASSERT_EXIT(ret == -EREMOTEIO); |
29260 |
-+ |
29261 |
-+ cookie++; |
29262 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); |
29263 |
-+ ASSERT_EXIT(ret == 0); |
29264 |
-+ ASSERT_EXIT(msg->cookie == cookie); |
29265 |
-+ |
29266 |
-+ free(msg_sync_reply); |
29267 |
-+ kdbus_msg_free(msg); |
29268 |
-+ |
29269 |
-+ _exit(EXIT_SUCCESS); |
29270 |
-+ } |
29271 |
-+ |
29272 |
-+ ret = kdbus_msg_recv_poll(conn_dummy, 100, NULL, NULL); |
29273 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
29274 |
-+ |
29275 |
-+ cookie++; |
29276 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
29277 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
29278 |
-+ |
29279 |
-+ kdbus_msg_free(msg); |
29280 |
-+ |
29281 |
-+ /* |
29282 |
-+ * Try to reply with a kdbus connection handle, this should |
29283 |
-+ * fail with -EOPNOTSUPP |
29284 |
-+ */ |
29285 |
-+ msg_sync_reply = get_kdbus_msg_with_fd(conn_src, |
29286 |
-+ conn_dst->id, |
29287 |
-+ cookie, conn_dst->fd); |
29288 |
-+ ASSERT_RETURN(msg_sync_reply); |
29289 |
-+ |
29290 |
-+ msg_sync_reply->cookie_reply = cookie; |
29291 |
-+ |
29292 |
-+ memset(&cmd, 0, sizeof(cmd)); |
29293 |
-+ cmd.size = sizeof(cmd); |
29294 |
-+ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29295 |
-+ |
29296 |
-+ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
29297 |
-+ ASSERT_RETURN(ret == -EOPNOTSUPP); |
29298 |
-+ |
29299 |
-+ free(msg_sync_reply); |
29300 |
-+ |
29301 |
-+ /* |
29302 |
-+ * Try to reply with a normal fd, this should fail even |
29303 |
-+ * if the response is a sync reply |
29304 |
-+ * |
29305 |
-+ * From the sender view we fail with -ECOMM |
29306 |
-+ */ |
29307 |
-+ msg_sync_reply = get_kdbus_msg_with_fd(conn_src, |
29308 |
-+ conn_dst->id, |
29309 |
-+ cookie, fds[0]); |
29310 |
-+ ASSERT_RETURN(msg_sync_reply); |
29311 |
-+ |
29312 |
-+ msg_sync_reply->cookie_reply = cookie; |
29313 |
-+ |
29314 |
-+ memset(&cmd, 0, sizeof(cmd)); |
29315 |
-+ cmd.size = sizeof(cmd); |
29316 |
-+ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29317 |
-+ |
29318 |
-+ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
29319 |
-+ ASSERT_RETURN(ret == -ECOMM); |
29320 |
-+ |
29321 |
-+ free(msg_sync_reply); |
29322 |
-+ |
29323 |
-+ /* |
29324 |
-+ * Resend another normal message and check if the queue |
29325 |
-+ * is clear |
29326 |
-+ */ |
29327 |
-+ cookie++; |
29328 |
-+ ret = kdbus_msg_send(conn_src, NULL, cookie, 0, 0, 0, |
29329 |
-+ conn_dst->id); |
29330 |
-+ ASSERT_RETURN(ret == 0); |
29331 |
-+ |
29332 |
-+ ret = waitpid(pid, &status, 0); |
29333 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
29334 |
-+ |
29335 |
-+ kdbus_conn_free(conn_dummy); |
29336 |
-+ kdbus_conn_free(conn_dst); |
29337 |
-+ kdbus_conn_free(conn_src); |
29338 |
-+ |
29339 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
29340 |
-+} |
29341 |
-+ |
29342 |
-+static int kdbus_send_multiple_fds(struct kdbus_conn *conn_src, |
29343 |
-+ struct kdbus_conn *conn_dst) |
29344 |
-+{ |
29345 |
-+ int ret, i; |
29346 |
-+ unsigned int nfds; |
29347 |
-+ int fds[KDBUS_CONN_MAX_FDS_PER_USER + 1]; |
29348 |
-+ int memfds[KDBUS_MSG_MAX_ITEMS + 1]; |
29349 |
-+ struct kdbus_msg *msg; |
29350 |
-+ uint64_t dummy_value; |
29351 |
-+ |
29352 |
-+ dummy_value = time(NULL); |
29353 |
-+ |
29354 |
-+ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) { |
29355 |
-+ fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC); |
29356 |
-+ ASSERT_RETURN_VAL(fds[i] >= 0, -errno); |
29357 |
-+ } |
29358 |
-+ |
29359 |
-+ /* Send KDBUS_CONN_MAX_FDS_PER_USER with one more fd */ |
29360 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, |
29361 |
-+ KDBUS_CONN_MAX_FDS_PER_USER + 1); |
29362 |
-+ ASSERT_RETURN(ret == -EMFILE); |
29363 |
-+ |
29364 |
-+ /* Retry with the correct KDBUS_CONN_MAX_FDS_PER_USER */ |
29365 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, |
29366 |
-+ KDBUS_CONN_MAX_FDS_PER_USER); |
29367 |
-+ ASSERT_RETURN(ret == 0); |
29368 |
-+ |
29369 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29370 |
-+ ASSERT_RETURN(ret == 0); |
29371 |
-+ |
29372 |
-+ /* Check we got the right number of fds */ |
29373 |
-+ nfds = kdbus_item_get_nfds(msg); |
29374 |
-+ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER); |
29375 |
-+ |
29376 |
-+ kdbus_msg_free(msg); |
29377 |
-+ |
29378 |
-+ for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++, dummy_value++) { |
29379 |
-+ memfds[i] = memfd_write("memfd-name", |
29380 |
-+ &dummy_value, |
29381 |
-+ sizeof(dummy_value)); |
29382 |
-+ ASSERT_RETURN_VAL(memfds[i] >= 0, memfds[i]); |
29383 |
-+ } |
29384 |
-+ |
29385 |
-+ /* Send KDBUS_MSG_MAX_ITEMS with one more memfd */ |
29386 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29387 |
-+ memfds, KDBUS_MSG_MAX_ITEMS + 1); |
29388 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29389 |
-+ |
29390 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29391 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1); |
29392 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29393 |
-+ |
29394 |
-+ /* Retry with the correct KDBUS_MSG_MAX_ITEMS */ |
29395 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29396 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29397 |
-+ ASSERT_RETURN(ret == 0); |
29398 |
-+ |
29399 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29400 |
-+ ASSERT_RETURN(ret == 0); |
29401 |
-+ |
29402 |
-+ /* Check we got the right number of fds */ |
29403 |
-+ nfds = kdbus_item_get_nfds(msg); |
29404 |
-+ ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS); |
29405 |
-+ |
29406 |
-+ kdbus_msg_free(msg); |
29407 |
-+ |
29408 |
-+ |
29409 |
-+ /* |
29410 |
-+ * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER+1 fds and |
29411 |
-+ * 10 memfds |
29412 |
-+ */ |
29413 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29414 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER + 1, |
29415 |
-+ memfds, 10); |
29416 |
-+ ASSERT_RETURN(ret == -EMFILE); |
29417 |
-+ |
29418 |
-+ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29419 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
29420 |
-+ |
29421 |
-+ /* |
29422 |
-+ * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER fds and |
29423 |
-+ * (128 - 1) + 1 memfds, all fds take one item, while each |
29424 |
-+ * memfd takes one item |
29425 |
-+ */ |
29426 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29427 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29428 |
-+ memfds, (KDBUS_MSG_MAX_ITEMS - 1) + 1); |
29429 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29430 |
-+ |
29431 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29432 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29433 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1); |
29434 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29435 |
-+ |
29436 |
-+ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29437 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
29438 |
-+ |
29439 |
-+ /* |
29440 |
-+ * Send KDBUS_CONN_MAX_FDS_PER_USER fds + |
29441 |
-+ * KDBUS_MSG_MAX_MEMFD_ITEMS memfds |
29442 |
-+ */ |
29443 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29444 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29445 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29446 |
-+ ASSERT_RETURN(ret == 0); |
29447 |
-+ |
29448 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29449 |
-+ ASSERT_RETURN(ret == 0); |
29450 |
-+ |
29451 |
-+ /* Check we got the right number of fds */ |
29452 |
-+ nfds = kdbus_item_get_nfds(msg); |
29453 |
-+ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER + |
29454 |
-+ KDBUS_MSG_MAX_MEMFD_ITEMS); |
29455 |
-+ |
29456 |
-+ kdbus_msg_free(msg); |
29457 |
-+ |
29458 |
-+ |
29459 |
-+ /* |
29460 |
-+ * Re-send fds + memfds, close them, but do not receive them |
29461 |
-+ * and try to queue more |
29462 |
-+ */ |
29463 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29464 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29465 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29466 |
-+ ASSERT_RETURN(ret == 0); |
29467 |
-+ |
29468 |
-+ /* close old references and get a new ones */ |
29469 |
-+ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) { |
29470 |
-+ close(fds[i]); |
29471 |
-+ fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC); |
29472 |
-+ ASSERT_RETURN_VAL(fds[i] >= 0, -errno); |
29473 |
-+ } |
29474 |
-+ |
29475 |
-+ /* should fail since we have already fds in the queue */ |
29476 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, |
29477 |
-+ KDBUS_CONN_MAX_FDS_PER_USER); |
29478 |
-+ ASSERT_RETURN(ret == -EMFILE); |
29479 |
-+ |
29480 |
-+ /* This should succeed */ |
29481 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29482 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29483 |
-+ ASSERT_RETURN(ret == 0); |
29484 |
-+ |
29485 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29486 |
-+ ASSERT_RETURN(ret == 0); |
29487 |
-+ |
29488 |
-+ nfds = kdbus_item_get_nfds(msg); |
29489 |
-+ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER + |
29490 |
-+ KDBUS_MSG_MAX_MEMFD_ITEMS); |
29491 |
-+ |
29492 |
-+ kdbus_msg_free(msg); |
29493 |
-+ |
29494 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29495 |
-+ ASSERT_RETURN(ret == 0); |
29496 |
-+ |
29497 |
-+ nfds = kdbus_item_get_nfds(msg); |
29498 |
-+ ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS); |
29499 |
-+ |
29500 |
-+ kdbus_msg_free(msg); |
29501 |
-+ |
29502 |
-+ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29503 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
29504 |
-+ |
29505 |
-+ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) |
29506 |
-+ close(fds[i]); |
29507 |
-+ |
29508 |
-+ for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++) |
29509 |
-+ close(memfds[i]); |
29510 |
-+ |
29511 |
-+ return 0; |
29512 |
-+} |
29513 |
-+ |
29514 |
-+int kdbus_test_fd_passing(struct kdbus_test_env *env) |
29515 |
-+{ |
29516 |
-+ struct kdbus_conn *conn_src, *conn_dst; |
29517 |
-+ const char *str = "stackenblocken"; |
29518 |
-+ const struct kdbus_item *item; |
29519 |
-+ struct kdbus_msg *msg; |
29520 |
-+ unsigned int i; |
29521 |
-+ uint64_t now; |
29522 |
-+ int fds_conn[2]; |
29523 |
-+ int sock_pair[2]; |
29524 |
-+ int fds[2]; |
29525 |
-+ int memfd; |
29526 |
-+ int ret; |
29527 |
-+ |
29528 |
-+ now = (uint64_t) time(NULL); |
29529 |
-+ |
29530 |
-+ /* create two connections */ |
29531 |
-+ conn_src = kdbus_hello(env->buspath, 0, NULL, 0); |
29532 |
-+ conn_dst = kdbus_hello(env->buspath, 0, NULL, 0); |
29533 |
-+ ASSERT_RETURN(conn_src && conn_dst); |
29534 |
-+ |
29535 |
-+ fds_conn[0] = conn_src->fd; |
29536 |
-+ fds_conn[1] = conn_dst->fd; |
29537 |
-+ |
29538 |
-+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair); |
29539 |
-+ ASSERT_RETURN(ret == 0); |
29540 |
-+ |
29541 |
-+ /* Setup memfd */ |
29542 |
-+ memfd = memfd_write("memfd-name", &now, sizeof(now)); |
29543 |
-+ ASSERT_RETURN(memfd >= 0); |
29544 |
-+ |
29545 |
-+ /* Setup pipes */ |
29546 |
-+ ret = pipe(fds); |
29547 |
-+ ASSERT_RETURN(ret == 0); |
29548 |
-+ |
29549 |
-+ i = write(fds[1], str, strlen(str)); |
29550 |
-+ ASSERT_RETURN(i == strlen(str)); |
29551 |
-+ |
29552 |
-+ /* |
29553 |
-+ * Try to ass the handle of a connection as message payload. |
29554 |
-+ * This must fail. |
29555 |
-+ */ |
29556 |
-+ ret = send_fds(conn_src, conn_dst->id, fds_conn, 2); |
29557 |
-+ ASSERT_RETURN(ret == -ENOTSUP); |
29558 |
-+ |
29559 |
-+ ret = send_fds(conn_dst, conn_src->id, fds_conn, 2); |
29560 |
-+ ASSERT_RETURN(ret == -ENOTSUP); |
29561 |
-+ |
29562 |
-+ ret = send_fds(conn_src, conn_dst->id, sock_pair, 2); |
29563 |
-+ ASSERT_RETURN(ret == -ENOTSUP); |
29564 |
-+ |
29565 |
-+ /* |
29566 |
-+ * Send fds and memfds to connection that do not accept fds |
29567 |
-+ */ |
29568 |
-+ ret = kdbus_test_no_fds(env, fds, (int *)&memfd); |
29569 |
-+ ASSERT_RETURN(ret == 0); |
29570 |
-+ |
29571 |
-+ /* Try to broadcast file descriptors. This must fail. */ |
29572 |
-+ ret = send_fds(conn_src, KDBUS_DST_ID_BROADCAST, fds, 1); |
29573 |
-+ ASSERT_RETURN(ret == -ENOTUNIQ); |
29574 |
-+ |
29575 |
-+ /* Try to broadcast memfd. This must succeed. */ |
29576 |
-+ ret = send_memfds(conn_src, KDBUS_DST_ID_BROADCAST, (int *)&memfd, 1); |
29577 |
-+ ASSERT_RETURN(ret == 0); |
29578 |
-+ |
29579 |
-+ /* Open code this loop */ |
29580 |
-+loop_send_fds: |
29581 |
-+ |
29582 |
-+ /* |
29583 |
-+ * Send the read end of the pipe and close it. |
29584 |
-+ */ |
29585 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29586 |
-+ ASSERT_RETURN(ret == 0); |
29587 |
-+ close(fds[0]); |
29588 |
-+ |
29589 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29590 |
-+ ASSERT_RETURN(ret == 0); |
29591 |
-+ |
29592 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
29593 |
-+ if (item->type == KDBUS_ITEM_FDS) { |
29594 |
-+ char tmp[14]; |
29595 |
-+ int nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
29596 |
-+ sizeof(int); |
29597 |
-+ ASSERT_RETURN(nfds == 1); |
29598 |
-+ |
29599 |
-+ i = read(item->fds[0], tmp, sizeof(tmp)); |
29600 |
-+ if (i != 0) { |
29601 |
-+ ASSERT_RETURN(i == sizeof(tmp)); |
29602 |
-+ ASSERT_RETURN(memcmp(tmp, str, sizeof(tmp)) == 0); |
29603 |
-+ |
29604 |
-+ /* Write EOF */ |
29605 |
-+ close(fds[1]); |
29606 |
-+ |
29607 |
-+ /* |
29608 |
-+ * Resend the read end of the pipe, |
29609 |
-+ * the receiver still holds a reference |
29610 |
-+ * to it... |
29611 |
-+ */ |
29612 |
-+ goto loop_send_fds; |
29613 |
-+ } |
29614 |
-+ |
29615 |
-+ /* Got EOF */ |
29616 |
-+ |
29617 |
-+ /* |
29618 |
-+ * Close the last reference to the read end |
29619 |
-+ * of the pipe, other references are |
29620 |
-+ * automatically closed just after send. |
29621 |
-+ */ |
29622 |
-+ close(item->fds[0]); |
29623 |
-+ } |
29624 |
-+ } |
29625 |
-+ |
29626 |
-+ /* |
29627 |
-+ * Try to resend the read end of the pipe. Must fail with |
29628 |
-+ * -EBADF since both the sender and receiver closed their |
29629 |
-+ * references to it. We assume the above since sender and |
29630 |
-+ * receiver are on the same process. |
29631 |
-+ */ |
29632 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29633 |
-+ ASSERT_RETURN(ret == -EBADF); |
29634 |
-+ |
29635 |
-+ /* Then we clear out received any data... */ |
29636 |
-+ kdbus_msg_free(msg); |
29637 |
-+ |
29638 |
-+ ret = kdbus_send_multiple_fds(conn_src, conn_dst); |
29639 |
-+ ASSERT_RETURN(ret == 0); |
29640 |
-+ |
29641 |
-+ close(sock_pair[0]); |
29642 |
-+ close(sock_pair[1]); |
29643 |
-+ close(memfd); |
29644 |
-+ |
29645 |
-+ kdbus_conn_free(conn_src); |
29646 |
-+ kdbus_conn_free(conn_dst); |
29647 |
-+ |
29648 |
-+ return TEST_OK; |
29649 |
-+} |
29650 |
-diff --git a/tools/testing/selftests/kdbus/test-free.c b/tools/testing/selftests/kdbus/test-free.c |
29651 |
-new file mode 100644 |
29652 |
-index 0000000..f666da3 |
29653 |
---- /dev/null |
29654 |
-+++ b/tools/testing/selftests/kdbus/test-free.c |
29655 |
-@@ -0,0 +1,64 @@ |
29656 |
-+#include <stdio.h> |
29657 |
-+#include <string.h> |
29658 |
-+#include <fcntl.h> |
29659 |
-+#include <stdlib.h> |
29660 |
-+#include <stddef.h> |
29661 |
-+#include <unistd.h> |
29662 |
-+#include <stdint.h> |
29663 |
-+#include <errno.h> |
29664 |
-+#include <assert.h> |
29665 |
-+#include <stdbool.h> |
29666 |
-+ |
29667 |
-+#include "kdbus-api.h" |
29668 |
-+#include "kdbus-util.h" |
29669 |
-+#include "kdbus-enum.h" |
29670 |
-+#include "kdbus-test.h" |
29671 |
-+ |
29672 |
-+static int sample_ioctl_call(struct kdbus_test_env *env) |
29673 |
-+{ |
29674 |
-+ int ret; |
29675 |
-+ struct kdbus_cmd_list cmd_list = { |
29676 |
-+ .flags = KDBUS_LIST_QUEUED, |
29677 |
-+ .size = sizeof(cmd_list), |
29678 |
-+ }; |
29679 |
-+ |
29680 |
-+ ret = kdbus_cmd_list(env->conn->fd, &cmd_list); |
29681 |
-+ ASSERT_RETURN(ret == 0); |
29682 |
-+ |
29683 |
-+ /* DON'T FREE THIS SLICE OF MEMORY! */ |
29684 |
-+ |
29685 |
-+ return TEST_OK; |
29686 |
-+} |
29687 |
-+ |
29688 |
-+int kdbus_test_free(struct kdbus_test_env *env) |
29689 |
-+{ |
29690 |
-+ int ret; |
29691 |
-+ struct kdbus_cmd_free cmd_free = {}; |
29692 |
-+ |
29693 |
-+ /* free an unallocated buffer */ |
29694 |
-+ cmd_free.size = sizeof(cmd_free); |
29695 |
-+ cmd_free.flags = 0; |
29696 |
-+ cmd_free.offset = 0; |
29697 |
-+ ret = kdbus_cmd_free(env->conn->fd, &cmd_free); |
29698 |
-+ ASSERT_RETURN(ret == -ENXIO); |
29699 |
-+ |
29700 |
-+ /* free a buffer out of the pool's bounds */ |
29701 |
-+ cmd_free.size = sizeof(cmd_free); |
29702 |
-+ cmd_free.offset = POOL_SIZE + 1; |
29703 |
-+ ret = kdbus_cmd_free(env->conn->fd, &cmd_free); |
29704 |
-+ ASSERT_RETURN(ret == -ENXIO); |
29705 |
-+ |
29706 |
-+ /* |
29707 |
-+ * The user application is responsible for freeing the allocated |
29708 |
-+ * memory with the KDBUS_CMD_FREE ioctl, so let's test what happens |
29709 |
-+ * if we forget about it. |
29710 |
-+ */ |
29711 |
-+ |
29712 |
-+ ret = sample_ioctl_call(env); |
29713 |
-+ ASSERT_RETURN(ret == 0); |
29714 |
-+ |
29715 |
-+ ret = sample_ioctl_call(env); |
29716 |
-+ ASSERT_RETURN(ret == 0); |
29717 |
-+ |
29718 |
-+ return TEST_OK; |
29719 |
-+} |
29720 |
-diff --git a/tools/testing/selftests/kdbus/test-match.c b/tools/testing/selftests/kdbus/test-match.c |
29721 |
-new file mode 100644 |
29722 |
-index 0000000..2360dc1 |
29723 |
---- /dev/null |
29724 |
-+++ b/tools/testing/selftests/kdbus/test-match.c |
29725 |
-@@ -0,0 +1,441 @@ |
29726 |
-+#include <stdio.h> |
29727 |
-+#include <string.h> |
29728 |
-+#include <fcntl.h> |
29729 |
-+#include <stdlib.h> |
29730 |
-+#include <stddef.h> |
29731 |
-+#include <unistd.h> |
29732 |
-+#include <stdint.h> |
29733 |
-+#include <errno.h> |
29734 |
-+#include <assert.h> |
29735 |
-+#include <stdbool.h> |
29736 |
-+ |
29737 |
-+#include "kdbus-api.h" |
29738 |
-+#include "kdbus-util.h" |
29739 |
-+#include "kdbus-enum.h" |
29740 |
-+#include "kdbus-test.h" |
29741 |
-+ |
29742 |
-+int kdbus_test_match_id_add(struct kdbus_test_env *env) |
29743 |
-+{ |
29744 |
-+ struct { |
29745 |
-+ struct kdbus_cmd_match cmd; |
29746 |
-+ struct { |
29747 |
-+ uint64_t size; |
29748 |
-+ uint64_t type; |
29749 |
-+ struct kdbus_notify_id_change chg; |
29750 |
-+ } item; |
29751 |
-+ } buf; |
29752 |
-+ struct kdbus_conn *conn; |
29753 |
-+ struct kdbus_msg *msg; |
29754 |
-+ int ret; |
29755 |
-+ |
29756 |
-+ memset(&buf, 0, sizeof(buf)); |
29757 |
-+ |
29758 |
-+ buf.cmd.size = sizeof(buf); |
29759 |
-+ buf.cmd.cookie = 0xdeafbeefdeaddead; |
29760 |
-+ buf.item.size = sizeof(buf.item); |
29761 |
-+ buf.item.type = KDBUS_ITEM_ID_ADD; |
29762 |
-+ buf.item.chg.id = KDBUS_MATCH_ID_ANY; |
29763 |
-+ |
29764 |
-+ /* match on id add */ |
29765 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29766 |
-+ ASSERT_RETURN(ret == 0); |
29767 |
-+ |
29768 |
-+ /* create 2nd connection */ |
29769 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
29770 |
-+ ASSERT_RETURN(conn != NULL); |
29771 |
-+ |
29772 |
-+ /* 1st connection should have received a notification */ |
29773 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29774 |
-+ ASSERT_RETURN(ret == 0); |
29775 |
-+ |
29776 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD); |
29777 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == conn->id); |
29778 |
-+ |
29779 |
-+ kdbus_conn_free(conn); |
29780 |
-+ |
29781 |
-+ return TEST_OK; |
29782 |
-+} |
29783 |
-+ |
29784 |
-+int kdbus_test_match_id_remove(struct kdbus_test_env *env) |
29785 |
-+{ |
29786 |
-+ struct { |
29787 |
-+ struct kdbus_cmd_match cmd; |
29788 |
-+ struct { |
29789 |
-+ uint64_t size; |
29790 |
-+ uint64_t type; |
29791 |
-+ struct kdbus_notify_id_change chg; |
29792 |
-+ } item; |
29793 |
-+ } buf; |
29794 |
-+ struct kdbus_conn *conn; |
29795 |
-+ struct kdbus_msg *msg; |
29796 |
-+ size_t id; |
29797 |
-+ int ret; |
29798 |
-+ |
29799 |
-+ /* create 2nd connection */ |
29800 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
29801 |
-+ ASSERT_RETURN(conn != NULL); |
29802 |
-+ id = conn->id; |
29803 |
-+ |
29804 |
-+ memset(&buf, 0, sizeof(buf)); |
29805 |
-+ buf.cmd.size = sizeof(buf); |
29806 |
-+ buf.cmd.cookie = 0xdeafbeefdeaddead; |
29807 |
-+ buf.item.size = sizeof(buf.item); |
29808 |
-+ buf.item.type = KDBUS_ITEM_ID_REMOVE; |
29809 |
-+ buf.item.chg.id = id; |
29810 |
-+ |
29811 |
-+ /* register match on 2nd connection */ |
29812 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29813 |
-+ ASSERT_RETURN(ret == 0); |
29814 |
-+ |
29815 |
-+ /* remove 2nd connection again */ |
29816 |
-+ kdbus_conn_free(conn); |
29817 |
-+ |
29818 |
-+ /* 1st connection should have received a notification */ |
29819 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29820 |
-+ ASSERT_RETURN(ret == 0); |
29821 |
-+ |
29822 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE); |
29823 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == id); |
29824 |
-+ |
29825 |
-+ return TEST_OK; |
29826 |
-+} |
29827 |
-+ |
29828 |
-+int kdbus_test_match_replace(struct kdbus_test_env *env) |
29829 |
-+{ |
29830 |
-+ struct { |
29831 |
-+ struct kdbus_cmd_match cmd; |
29832 |
-+ struct { |
29833 |
-+ uint64_t size; |
29834 |
-+ uint64_t type; |
29835 |
-+ struct kdbus_notify_id_change chg; |
29836 |
-+ } item; |
29837 |
-+ } buf; |
29838 |
-+ struct kdbus_conn *conn; |
29839 |
-+ struct kdbus_msg *msg; |
29840 |
-+ size_t id; |
29841 |
-+ int ret; |
29842 |
-+ |
29843 |
-+ /* add a match to id_add */ |
29844 |
-+ ASSERT_RETURN(kdbus_test_match_id_add(env) == TEST_OK); |
29845 |
-+ |
29846 |
-+ /* do a replace of the match from id_add to id_remove */ |
29847 |
-+ memset(&buf, 0, sizeof(buf)); |
29848 |
-+ |
29849 |
-+ buf.cmd.size = sizeof(buf); |
29850 |
-+ buf.cmd.cookie = 0xdeafbeefdeaddead; |
29851 |
-+ buf.cmd.flags = KDBUS_MATCH_REPLACE; |
29852 |
-+ buf.item.size = sizeof(buf.item); |
29853 |
-+ buf.item.type = KDBUS_ITEM_ID_REMOVE; |
29854 |
-+ buf.item.chg.id = KDBUS_MATCH_ID_ANY; |
29855 |
-+ |
29856 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29857 |
-+ |
29858 |
-+ /* create 2nd connection */ |
29859 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
29860 |
-+ ASSERT_RETURN(conn != NULL); |
29861 |
-+ id = conn->id; |
29862 |
-+ |
29863 |
-+ /* 1st connection should _not_ have received a notification */ |
29864 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29865 |
-+ ASSERT_RETURN(ret != 0); |
29866 |
-+ |
29867 |
-+ /* remove 2nd connection */ |
29868 |
-+ kdbus_conn_free(conn); |
29869 |
-+ |
29870 |
-+ /* 1st connection should _now_ have received a notification */ |
29871 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29872 |
-+ ASSERT_RETURN(ret == 0); |
29873 |
-+ |
29874 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE); |
29875 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == id); |
29876 |
-+ |
29877 |
-+ return TEST_OK; |
29878 |
-+} |
29879 |
-+ |
29880 |
-+int kdbus_test_match_name_add(struct kdbus_test_env *env) |
29881 |
-+{ |
29882 |
-+ struct { |
29883 |
-+ struct kdbus_cmd_match cmd; |
29884 |
-+ struct { |
29885 |
-+ uint64_t size; |
29886 |
-+ uint64_t type; |
29887 |
-+ struct kdbus_notify_name_change chg; |
29888 |
-+ } item; |
29889 |
-+ char name[64]; |
29890 |
-+ } buf; |
29891 |
-+ struct kdbus_msg *msg; |
29892 |
-+ char *name; |
29893 |
-+ int ret; |
29894 |
-+ |
29895 |
-+ name = "foo.bla.blaz"; |
29896 |
-+ |
29897 |
-+ /* install the match rule */ |
29898 |
-+ memset(&buf, 0, sizeof(buf)); |
29899 |
-+ buf.item.type = KDBUS_ITEM_NAME_ADD; |
29900 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
29901 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
29902 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
29903 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
29904 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
29905 |
-+ |
29906 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29907 |
-+ ASSERT_RETURN(ret == 0); |
29908 |
-+ |
29909 |
-+ /* acquire the name */ |
29910 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
29911 |
-+ ASSERT_RETURN(ret == 0); |
29912 |
-+ |
29913 |
-+ /* we should have received a notification */ |
29914 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29915 |
-+ ASSERT_RETURN(ret == 0); |
29916 |
-+ |
29917 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); |
29918 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); |
29919 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); |
29920 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
29921 |
-+ |
29922 |
-+ return TEST_OK; |
29923 |
-+} |
29924 |
-+ |
29925 |
-+int kdbus_test_match_name_remove(struct kdbus_test_env *env) |
29926 |
-+{ |
29927 |
-+ struct { |
29928 |
-+ struct kdbus_cmd_match cmd; |
29929 |
-+ struct { |
29930 |
-+ uint64_t size; |
29931 |
-+ uint64_t type; |
29932 |
-+ struct kdbus_notify_name_change chg; |
29933 |
-+ } item; |
29934 |
-+ char name[64]; |
29935 |
-+ } buf; |
29936 |
-+ struct kdbus_msg *msg; |
29937 |
-+ char *name; |
29938 |
-+ int ret; |
29939 |
-+ |
29940 |
-+ name = "foo.bla.blaz"; |
29941 |
-+ |
29942 |
-+ /* acquire the name */ |
29943 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
29944 |
-+ ASSERT_RETURN(ret == 0); |
29945 |
-+ |
29946 |
-+ /* install the match rule */ |
29947 |
-+ memset(&buf, 0, sizeof(buf)); |
29948 |
-+ buf.item.type = KDBUS_ITEM_NAME_REMOVE; |
29949 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
29950 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
29951 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
29952 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
29953 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
29954 |
-+ |
29955 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29956 |
-+ ASSERT_RETURN(ret == 0); |
29957 |
-+ |
29958 |
-+ /* release the name again */ |
29959 |
-+ kdbus_name_release(env->conn, name); |
29960 |
-+ ASSERT_RETURN(ret == 0); |
29961 |
-+ |
29962 |
-+ /* we should have received a notification */ |
29963 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29964 |
-+ ASSERT_RETURN(ret == 0); |
29965 |
-+ |
29966 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_REMOVE); |
29967 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id); |
29968 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == 0); |
29969 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
29970 |
-+ |
29971 |
-+ return TEST_OK; |
29972 |
-+} |
29973 |
-+ |
29974 |
-+int kdbus_test_match_name_change(struct kdbus_test_env *env) |
29975 |
-+{ |
29976 |
-+ struct { |
29977 |
-+ struct kdbus_cmd_match cmd; |
29978 |
-+ struct { |
29979 |
-+ uint64_t size; |
29980 |
-+ uint64_t type; |
29981 |
-+ struct kdbus_notify_name_change chg; |
29982 |
-+ } item; |
29983 |
-+ char name[64]; |
29984 |
-+ } buf; |
29985 |
-+ struct kdbus_conn *conn; |
29986 |
-+ struct kdbus_msg *msg; |
29987 |
-+ uint64_t flags; |
29988 |
-+ char *name = "foo.bla.baz"; |
29989 |
-+ int ret; |
29990 |
-+ |
29991 |
-+ /* acquire the name */ |
29992 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
29993 |
-+ ASSERT_RETURN(ret == 0); |
29994 |
-+ |
29995 |
-+ /* install the match rule */ |
29996 |
-+ memset(&buf, 0, sizeof(buf)); |
29997 |
-+ buf.item.type = KDBUS_ITEM_NAME_CHANGE; |
29998 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
29999 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
30000 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
30001 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
30002 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
30003 |
-+ |
30004 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30005 |
-+ ASSERT_RETURN(ret == 0); |
30006 |
-+ |
30007 |
-+ /* create a 2nd connection */ |
30008 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30009 |
-+ ASSERT_RETURN(conn != NULL); |
30010 |
-+ |
30011 |
-+ /* allow the new connection to own the same name */ |
30012 |
-+ /* queue the 2nd connection as waiting owner */ |
30013 |
-+ flags = KDBUS_NAME_QUEUE; |
30014 |
-+ ret = kdbus_name_acquire(conn, name, &flags); |
30015 |
-+ ASSERT_RETURN(ret == 0); |
30016 |
-+ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); |
30017 |
-+ |
30018 |
-+ /* release name from 1st connection */ |
30019 |
-+ ret = kdbus_name_release(env->conn, name); |
30020 |
-+ ASSERT_RETURN(ret == 0); |
30021 |
-+ |
30022 |
-+ /* we should have received a notification */ |
30023 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30024 |
-+ ASSERT_RETURN(ret == 0); |
30025 |
-+ |
30026 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_CHANGE); |
30027 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id); |
30028 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == conn->id); |
30029 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
30030 |
-+ |
30031 |
-+ kdbus_conn_free(conn); |
30032 |
-+ |
30033 |
-+ return TEST_OK; |
30034 |
-+} |
30035 |
-+ |
30036 |
-+static int send_bloom_filter(const struct kdbus_conn *conn, |
30037 |
-+ uint64_t cookie, |
30038 |
-+ const uint8_t *filter, |
30039 |
-+ size_t filter_size, |
30040 |
-+ uint64_t filter_generation) |
30041 |
-+{ |
30042 |
-+ struct kdbus_cmd_send cmd = {}; |
30043 |
-+ struct kdbus_msg *msg; |
30044 |
-+ struct kdbus_item *item; |
30045 |
-+ uint64_t size; |
30046 |
-+ int ret; |
30047 |
-+ |
30048 |
-+ size = sizeof(struct kdbus_msg); |
30049 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + filter_size; |
30050 |
-+ |
30051 |
-+ msg = alloca(size); |
30052 |
-+ |
30053 |
-+ memset(msg, 0, size); |
30054 |
-+ msg->size = size; |
30055 |
-+ msg->src_id = conn->id; |
30056 |
-+ msg->dst_id = KDBUS_DST_ID_BROADCAST; |
30057 |
-+ msg->flags = KDBUS_MSG_SIGNAL; |
30058 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30059 |
-+ msg->cookie = cookie; |
30060 |
-+ |
30061 |
-+ item = msg->items; |
30062 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
30063 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + |
30064 |
-+ filter_size; |
30065 |
-+ |
30066 |
-+ item->bloom_filter.generation = filter_generation; |
30067 |
-+ memcpy(item->bloom_filter.data, filter, filter_size); |
30068 |
-+ |
30069 |
-+ cmd.size = sizeof(cmd); |
30070 |
-+ cmd.msg_address = (uintptr_t)msg; |
30071 |
-+ |
30072 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
30073 |
-+ if (ret < 0) { |
30074 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
30075 |
-+ return ret; |
30076 |
-+ } |
30077 |
-+ |
30078 |
-+ return 0; |
30079 |
-+} |
30080 |
-+ |
30081 |
-+int kdbus_test_match_bloom(struct kdbus_test_env *env) |
30082 |
-+{ |
30083 |
-+ struct { |
30084 |
-+ struct kdbus_cmd_match cmd; |
30085 |
-+ struct { |
30086 |
-+ uint64_t size; |
30087 |
-+ uint64_t type; |
30088 |
-+ uint8_t data_gen0[64]; |
30089 |
-+ uint8_t data_gen1[64]; |
30090 |
-+ } item; |
30091 |
-+ } buf; |
30092 |
-+ struct kdbus_conn *conn; |
30093 |
-+ struct kdbus_msg *msg; |
30094 |
-+ uint64_t cookie = 0xf000f00f; |
30095 |
-+ uint8_t filter[64]; |
30096 |
-+ int ret; |
30097 |
-+ |
30098 |
-+ /* install the match rule */ |
30099 |
-+ memset(&buf, 0, sizeof(buf)); |
30100 |
-+ buf.cmd.size = sizeof(buf); |
30101 |
-+ |
30102 |
-+ buf.item.size = sizeof(buf.item); |
30103 |
-+ buf.item.type = KDBUS_ITEM_BLOOM_MASK; |
30104 |
-+ buf.item.data_gen0[0] = 0x55; |
30105 |
-+ buf.item.data_gen0[63] = 0x80; |
30106 |
-+ |
30107 |
-+ buf.item.data_gen1[1] = 0xaa; |
30108 |
-+ buf.item.data_gen1[9] = 0x02; |
30109 |
-+ |
30110 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30111 |
-+ ASSERT_RETURN(ret == 0); |
30112 |
-+ |
30113 |
-+ /* create a 2nd connection */ |
30114 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30115 |
-+ ASSERT_RETURN(conn != NULL); |
30116 |
-+ |
30117 |
-+ /* a message with a 0'ed out filter must not reach the other peer */ |
30118 |
-+ memset(filter, 0, sizeof(filter)); |
30119 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30120 |
-+ ASSERT_RETURN(ret == 0); |
30121 |
-+ |
30122 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30123 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30124 |
-+ |
30125 |
-+ /* now set the filter to the connection's mask and expect success */ |
30126 |
-+ filter[0] = 0x55; |
30127 |
-+ filter[63] = 0x80; |
30128 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30129 |
-+ ASSERT_RETURN(ret == 0); |
30130 |
-+ |
30131 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30132 |
-+ ASSERT_RETURN(ret == 0); |
30133 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30134 |
-+ |
30135 |
-+ /* broaden the filter and try again. this should also succeed. */ |
30136 |
-+ filter[0] = 0xff; |
30137 |
-+ filter[8] = 0xff; |
30138 |
-+ filter[63] = 0xff; |
30139 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30140 |
-+ ASSERT_RETURN(ret == 0); |
30141 |
-+ |
30142 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30143 |
-+ ASSERT_RETURN(ret == 0); |
30144 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30145 |
-+ |
30146 |
-+ /* the same filter must not match against bloom generation 1 */ |
30147 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1); |
30148 |
-+ ASSERT_RETURN(ret == 0); |
30149 |
-+ |
30150 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30151 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30152 |
-+ |
30153 |
-+ /* set a different filter and try again */ |
30154 |
-+ filter[1] = 0xaa; |
30155 |
-+ filter[9] = 0x02; |
30156 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1); |
30157 |
-+ ASSERT_RETURN(ret == 0); |
30158 |
-+ |
30159 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30160 |
-+ ASSERT_RETURN(ret == 0); |
30161 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30162 |
-+ |
30163 |
-+ kdbus_conn_free(conn); |
30164 |
-+ |
30165 |
-+ return TEST_OK; |
30166 |
-+} |
30167 |
-diff --git a/tools/testing/selftests/kdbus/test-message.c b/tools/testing/selftests/kdbus/test-message.c |
30168 |
-new file mode 100644 |
30169 |
-index 0000000..563dc85 |
30170 |
---- /dev/null |
30171 |
-+++ b/tools/testing/selftests/kdbus/test-message.c |
30172 |
-@@ -0,0 +1,734 @@ |
30173 |
-+#include <stdio.h> |
30174 |
-+#include <string.h> |
30175 |
-+#include <fcntl.h> |
30176 |
-+#include <stdlib.h> |
30177 |
-+#include <stddef.h> |
30178 |
-+#include <unistd.h> |
30179 |
-+#include <stdint.h> |
30180 |
-+#include <errno.h> |
30181 |
-+#include <assert.h> |
30182 |
-+#include <time.h> |
30183 |
-+#include <stdbool.h> |
30184 |
-+#include <sys/eventfd.h> |
30185 |
-+#include <sys/types.h> |
30186 |
-+#include <sys/wait.h> |
30187 |
-+ |
30188 |
-+#include "kdbus-api.h" |
30189 |
-+#include "kdbus-util.h" |
30190 |
-+#include "kdbus-enum.h" |
30191 |
-+#include "kdbus-test.h" |
30192 |
-+ |
30193 |
-+/* maximum number of queued messages from the same individual user */ |
30194 |
-+#define KDBUS_CONN_MAX_MSGS 256 |
30195 |
-+ |
30196 |
-+/* maximum number of queued requests waiting for a reply */ |
30197 |
-+#define KDBUS_CONN_MAX_REQUESTS_PENDING 128 |
30198 |
-+ |
30199 |
-+/* maximum message payload size */ |
30200 |
-+#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE (2 * 1024UL * 1024UL) |
30201 |
-+ |
30202 |
-+int kdbus_test_message_basic(struct kdbus_test_env *env) |
30203 |
-+{ |
30204 |
-+ struct kdbus_conn *conn; |
30205 |
-+ struct kdbus_conn *sender; |
30206 |
-+ struct kdbus_msg *msg; |
30207 |
-+ uint64_t cookie = 0x1234abcd5678eeff; |
30208 |
-+ uint64_t offset; |
30209 |
-+ int ret; |
30210 |
-+ |
30211 |
-+ sender = kdbus_hello(env->buspath, 0, NULL, 0); |
30212 |
-+ ASSERT_RETURN(sender != NULL); |
30213 |
-+ |
30214 |
-+ /* create a 2nd connection */ |
30215 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30216 |
-+ ASSERT_RETURN(conn != NULL); |
30217 |
-+ |
30218 |
-+ ret = kdbus_add_match_empty(conn); |
30219 |
-+ ASSERT_RETURN(ret == 0); |
30220 |
-+ |
30221 |
-+ ret = kdbus_add_match_empty(sender); |
30222 |
-+ ASSERT_RETURN(ret == 0); |
30223 |
-+ |
30224 |
-+ /* send over 1st connection */ |
30225 |
-+ ret = kdbus_msg_send(sender, NULL, cookie, 0, 0, 0, |
30226 |
-+ KDBUS_DST_ID_BROADCAST); |
30227 |
-+ ASSERT_RETURN(ret == 0); |
30228 |
-+ |
30229 |
-+ /* Make sure that we do get our own broadcasts */ |
30230 |
-+ ret = kdbus_msg_recv(sender, &msg, &offset); |
30231 |
-+ ASSERT_RETURN(ret == 0); |
30232 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30233 |
-+ |
30234 |
-+ kdbus_msg_free(msg); |
30235 |
-+ |
30236 |
-+ /* ... and receive on the 2nd */ |
30237 |
-+ ret = kdbus_msg_recv_poll(conn, 100, &msg, &offset); |
30238 |
-+ ASSERT_RETURN(ret == 0); |
30239 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30240 |
-+ |
30241 |
-+ kdbus_msg_free(msg); |
30242 |
-+ |
30243 |
-+ /* Msgs that expect a reply must have timeout and cookie */ |
30244 |
-+ ret = kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY, |
30245 |
-+ 0, 0, conn->id); |
30246 |
-+ ASSERT_RETURN(ret == -EINVAL); |
30247 |
-+ |
30248 |
-+ /* Faked replies with a valid reply cookie are rejected */ |
30249 |
-+ ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id); |
30250 |
-+ ASSERT_RETURN(ret == -EBADSLT); |
30251 |
-+ |
30252 |
-+ ret = kdbus_free(conn, offset); |
30253 |
-+ ASSERT_RETURN(ret == 0); |
30254 |
-+ |
30255 |
-+ kdbus_conn_free(sender); |
30256 |
-+ kdbus_conn_free(conn); |
30257 |
-+ |
30258 |
-+ return TEST_OK; |
30259 |
-+} |
30260 |
-+ |
30261 |
-+static int msg_recv_prio(struct kdbus_conn *conn, |
30262 |
-+ int64_t requested_prio, |
30263 |
-+ int64_t expected_prio) |
30264 |
-+{ |
30265 |
-+ struct kdbus_cmd_recv recv = { |
30266 |
-+ .size = sizeof(recv), |
30267 |
-+ .flags = KDBUS_RECV_USE_PRIORITY, |
30268 |
-+ .priority = requested_prio, |
30269 |
-+ }; |
30270 |
-+ struct kdbus_msg *msg; |
30271 |
-+ int ret; |
30272 |
-+ |
30273 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30274 |
-+ if (ret < 0) { |
30275 |
-+ kdbus_printf("error receiving message: %d (%m)\n", -errno); |
30276 |
-+ return ret; |
30277 |
-+ } |
30278 |
-+ |
30279 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
30280 |
-+ kdbus_msg_dump(conn, msg); |
30281 |
-+ |
30282 |
-+ if (msg->priority != expected_prio) { |
30283 |
-+ kdbus_printf("expected message prio %lld, got %lld\n", |
30284 |
-+ (unsigned long long) expected_prio, |
30285 |
-+ (unsigned long long) msg->priority); |
30286 |
-+ return -EINVAL; |
30287 |
-+ } |
30288 |
-+ |
30289 |
-+ kdbus_msg_free(msg); |
30290 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
30291 |
-+ if (ret < 0) |
30292 |
-+ return ret; |
30293 |
-+ |
30294 |
-+ return 0; |
30295 |
-+} |
30296 |
-+ |
30297 |
-+int kdbus_test_message_prio(struct kdbus_test_env *env) |
30298 |
-+{ |
30299 |
-+ struct kdbus_conn *a, *b; |
30300 |
-+ uint64_t cookie = 0; |
30301 |
-+ |
30302 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30303 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30304 |
-+ ASSERT_RETURN(a && b); |
30305 |
-+ |
30306 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 25, a->id) == 0); |
30307 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id) == 0); |
30308 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); |
30309 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -35, a->id) == 0); |
30310 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id) == 0); |
30311 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 20, a->id) == 0); |
30312 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -15, a->id) == 0); |
30313 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); |
30314 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id) == 0); |
30315 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); |
30316 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); |
30317 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -10, a->id) == 0); |
30318 |
-+ |
30319 |
-+ ASSERT_RETURN(msg_recv_prio(a, -200, -800) == 0); |
30320 |
-+ ASSERT_RETURN(msg_recv_prio(a, -100, -800) == 0); |
30321 |
-+ ASSERT_RETURN(msg_recv_prio(a, -400, -600) == 0); |
30322 |
-+ ASSERT_RETURN(msg_recv_prio(a, -400, -600) == -EAGAIN); |
30323 |
-+ ASSERT_RETURN(msg_recv_prio(a, 10, -150) == 0); |
30324 |
-+ ASSERT_RETURN(msg_recv_prio(a, 10, -100) == 0); |
30325 |
-+ |
30326 |
-+ kdbus_printf("--- get priority (all)\n"); |
30327 |
-+ ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0); |
30328 |
-+ |
30329 |
-+ kdbus_conn_free(a); |
30330 |
-+ kdbus_conn_free(b); |
30331 |
-+ |
30332 |
-+ return TEST_OK; |
30333 |
-+} |
30334 |
-+ |
30335 |
-+static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env) |
30336 |
-+{ |
30337 |
-+ int ret; |
30338 |
-+ unsigned int i; |
30339 |
-+ struct kdbus_conn *conn; |
30340 |
-+ struct kdbus_conn *reader; |
30341 |
-+ struct kdbus_msg *msg = NULL; |
30342 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
30343 |
-+ |
30344 |
-+ reader = kdbus_hello(env->buspath, 0, NULL, 0); |
30345 |
-+ ASSERT_RETURN(reader); |
30346 |
-+ |
30347 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30348 |
-+ ASSERT_RETURN(conn); |
30349 |
-+ |
30350 |
-+ /* Register for ID signals */ |
30351 |
-+ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, |
30352 |
-+ KDBUS_MATCH_ID_ANY); |
30353 |
-+ ASSERT_RETURN(ret == 0); |
30354 |
-+ |
30355 |
-+ ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, |
30356 |
-+ KDBUS_MATCH_ID_ANY); |
30357 |
-+ ASSERT_RETURN(ret == 0); |
30358 |
-+ |
30359 |
-+ /* Each iteration two notifications: add and remove ID */ |
30360 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) { |
30361 |
-+ struct kdbus_conn *notifier; |
30362 |
-+ |
30363 |
-+ notifier = kdbus_hello(env->buspath, 0, NULL, 0); |
30364 |
-+ ASSERT_RETURN(notifier); |
30365 |
-+ |
30366 |
-+ kdbus_conn_free(notifier); |
30367 |
-+ } |
30368 |
-+ |
30369 |
-+ /* |
30370 |
-+ * Now the reader queue is full with kernel notfications, |
30371 |
-+ * but as a user we still have room to push our messages. |
30372 |
-+ */ |
30373 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id); |
30374 |
-+ ASSERT_RETURN(ret == 0); |
30375 |
-+ |
30376 |
-+ /* More ID kernel notifications that will be lost */ |
30377 |
-+ kdbus_conn_free(conn); |
30378 |
-+ |
30379 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30380 |
-+ ASSERT_RETURN(conn); |
30381 |
-+ |
30382 |
-+ kdbus_conn_free(conn); |
30383 |
-+ |
30384 |
-+ /* |
30385 |
-+ * We lost only 3 packets since only signal msgs are |
30386 |
-+ * accounted. The connection ID add/remove notification |
30387 |
-+ */ |
30388 |
-+ ret = kdbus_cmd_recv(reader->fd, &recv); |
30389 |
-+ ASSERT_RETURN(ret == 0); |
30390 |
-+ ASSERT_RETURN(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS); |
30391 |
-+ ASSERT_RETURN(recv.dropped_msgs == 3); |
30392 |
-+ |
30393 |
-+ msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset); |
30394 |
-+ kdbus_msg_free(msg); |
30395 |
-+ |
30396 |
-+ /* Read our queue */ |
30397 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) { |
30398 |
-+ memset(&recv, 0, sizeof(recv)); |
30399 |
-+ recv.size = sizeof(recv); |
30400 |
-+ |
30401 |
-+ ret = kdbus_cmd_recv(reader->fd, &recv); |
30402 |
-+ ASSERT_RETURN(ret == 0); |
30403 |
-+ ASSERT_RETURN(!(recv.return_flags & |
30404 |
-+ KDBUS_RECV_RETURN_DROPPED_MSGS)); |
30405 |
-+ |
30406 |
-+ msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset); |
30407 |
-+ kdbus_msg_free(msg); |
30408 |
-+ } |
30409 |
-+ |
30410 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
30411 |
-+ ASSERT_RETURN(ret == 0); |
30412 |
-+ |
30413 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
30414 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30415 |
-+ |
30416 |
-+ kdbus_conn_free(reader); |
30417 |
-+ |
30418 |
-+ return 0; |
30419 |
-+} |
30420 |
-+ |
30421 |
-+/* Return the number of message successfully sent */ |
30422 |
-+static int kdbus_fill_conn_queue(struct kdbus_conn *conn_src, |
30423 |
-+ uint64_t dst_id, |
30424 |
-+ unsigned int max_msgs) |
30425 |
-+{ |
30426 |
-+ unsigned int i; |
30427 |
-+ uint64_t cookie = 0; |
30428 |
-+ size_t size; |
30429 |
-+ struct kdbus_cmd_send cmd = {}; |
30430 |
-+ struct kdbus_msg *msg; |
30431 |
-+ int ret; |
30432 |
-+ |
30433 |
-+ size = sizeof(struct kdbus_msg); |
30434 |
-+ msg = malloc(size); |
30435 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30436 |
-+ |
30437 |
-+ memset(msg, 0, size); |
30438 |
-+ msg->size = size; |
30439 |
-+ msg->src_id = conn_src->id; |
30440 |
-+ msg->dst_id = dst_id; |
30441 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30442 |
-+ |
30443 |
-+ cmd.size = sizeof(cmd); |
30444 |
-+ cmd.msg_address = (uintptr_t)msg; |
30445 |
-+ |
30446 |
-+ for (i = 0; i < max_msgs; i++) { |
30447 |
-+ msg->cookie = cookie++; |
30448 |
-+ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
30449 |
-+ if (ret < 0) |
30450 |
-+ break; |
30451 |
-+ } |
30452 |
-+ |
30453 |
-+ free(msg); |
30454 |
-+ |
30455 |
-+ return i; |
30456 |
-+} |
30457 |
-+ |
30458 |
-+static int kdbus_test_activator_quota(struct kdbus_test_env *env) |
30459 |
-+{ |
30460 |
-+ int ret; |
30461 |
-+ unsigned int i; |
30462 |
-+ unsigned int activator_msgs_count = 0; |
30463 |
-+ uint64_t cookie = time(NULL); |
30464 |
-+ struct kdbus_conn *conn; |
30465 |
-+ struct kdbus_conn *sender; |
30466 |
-+ struct kdbus_conn *activator; |
30467 |
-+ struct kdbus_msg *msg; |
30468 |
-+ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
30469 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
30470 |
-+ struct kdbus_policy_access access = { |
30471 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
30472 |
-+ .id = geteuid(), |
30473 |
-+ .access = KDBUS_POLICY_OWN, |
30474 |
-+ }; |
30475 |
-+ |
30476 |
-+ activator = kdbus_hello_activator(env->buspath, "foo.test.activator", |
30477 |
-+ &access, 1); |
30478 |
-+ ASSERT_RETURN(activator); |
30479 |
-+ |
30480 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30481 |
-+ sender = kdbus_hello(env->buspath, 0, NULL, 0); |
30482 |
-+ ASSERT_RETURN(conn || sender); |
30483 |
-+ |
30484 |
-+ ret = kdbus_list(sender, KDBUS_LIST_NAMES | |
30485 |
-+ KDBUS_LIST_UNIQUE | |
30486 |
-+ KDBUS_LIST_ACTIVATORS | |
30487 |
-+ KDBUS_LIST_QUEUED); |
30488 |
-+ ASSERT_RETURN(ret == 0); |
30489 |
-+ |
30490 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30491 |
-+ ret = kdbus_msg_send(sender, "foo.test.activator", |
30492 |
-+ cookie++, 0, 0, 0, |
30493 |
-+ KDBUS_DST_ID_NAME); |
30494 |
-+ if (ret < 0) |
30495 |
-+ break; |
30496 |
-+ activator_msgs_count++; |
30497 |
-+ } |
30498 |
-+ |
30499 |
-+ /* we must have at least sent one message */ |
30500 |
-+ ASSERT_RETURN_VAL(i > 0, -errno); |
30501 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30502 |
-+ |
30503 |
-+ /* Good, activator queue is full now */ |
30504 |
-+ |
30505 |
-+ /* ENXIO on direct send (activators can never be addressed by ID) */ |
30506 |
-+ ret = kdbus_msg_send(conn, NULL, cookie++, 0, 0, 0, activator->id); |
30507 |
-+ ASSERT_RETURN(ret == -ENXIO); |
30508 |
-+ |
30509 |
-+ /* can't queue more */ |
30510 |
-+ ret = kdbus_msg_send(conn, "foo.test.activator", cookie++, |
30511 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
30512 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30513 |
-+ |
30514 |
-+ /* no match installed, so the broadcast will not inc dropped_msgs */ |
30515 |
-+ ret = kdbus_msg_send(sender, NULL, cookie++, 0, 0, 0, |
30516 |
-+ KDBUS_DST_ID_BROADCAST); |
30517 |
-+ ASSERT_RETURN(ret == 0); |
30518 |
-+ |
30519 |
-+ /* Check activator queue */ |
30520 |
-+ ret = kdbus_cmd_recv(activator->fd, &recv); |
30521 |
-+ ASSERT_RETURN(ret == 0); |
30522 |
-+ ASSERT_RETURN(recv.dropped_msgs == 0); |
30523 |
-+ |
30524 |
-+ activator_msgs_count--; |
30525 |
-+ |
30526 |
-+ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30527 |
-+ kdbus_msg_free(msg); |
30528 |
-+ |
30529 |
-+ |
30530 |
-+ /* Stage 1) of test check the pool memory quota */ |
30531 |
-+ |
30532 |
-+ /* Consume the connection pool memory */ |
30533 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30534 |
-+ ret = kdbus_msg_send(sender, NULL, |
30535 |
-+ cookie++, 0, 0, 0, conn->id); |
30536 |
-+ if (ret < 0) |
30537 |
-+ break; |
30538 |
-+ } |
30539 |
-+ |
30540 |
-+ /* consume one message, so later at least one can be moved */ |
30541 |
-+ memset(&recv, 0, sizeof(recv)); |
30542 |
-+ recv.size = sizeof(recv); |
30543 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30544 |
-+ ASSERT_RETURN(ret == 0); |
30545 |
-+ ASSERT_RETURN(recv.dropped_msgs == 0); |
30546 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
30547 |
-+ kdbus_msg_free(msg); |
30548 |
-+ |
30549 |
-+ /* Try to acquire the name now */ |
30550 |
-+ ret = kdbus_name_acquire(conn, "foo.test.activator", &flags); |
30551 |
-+ ASSERT_RETURN(ret == 0); |
30552 |
-+ |
30553 |
-+ /* try to read messages and see if we have lost some */ |
30554 |
-+ memset(&recv, 0, sizeof(recv)); |
30555 |
-+ recv.size = sizeof(recv); |
30556 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30557 |
-+ ASSERT_RETURN(ret == 0); |
30558 |
-+ ASSERT_RETURN(recv.dropped_msgs != 0); |
30559 |
-+ |
30560 |
-+ /* number of dropped msgs < received ones (at least one was moved) */ |
30561 |
-+ ASSERT_RETURN(recv.dropped_msgs < activator_msgs_count); |
30562 |
-+ |
30563 |
-+ /* Deduct the number of dropped msgs from the activator msgs */ |
30564 |
-+ activator_msgs_count -= recv.dropped_msgs; |
30565 |
-+ |
30566 |
-+ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30567 |
-+ kdbus_msg_free(msg); |
30568 |
-+ |
30569 |
-+ /* |
30570 |
-+ * Release the name and hand it back to activator, now |
30571 |
-+ * we should have 'activator_msgs_count' msgs again in |
30572 |
-+ * the activator queue |
30573 |
-+ */ |
30574 |
-+ ret = kdbus_name_release(conn, "foo.test.activator"); |
30575 |
-+ ASSERT_RETURN(ret == 0); |
30576 |
-+ |
30577 |
-+ /* make sure that we got our previous activator msgs */ |
30578 |
-+ ret = kdbus_msg_recv(activator, &msg, NULL); |
30579 |
-+ ASSERT_RETURN(ret == 0); |
30580 |
-+ ASSERT_RETURN(msg->src_id == sender->id); |
30581 |
-+ |
30582 |
-+ activator_msgs_count--; |
30583 |
-+ |
30584 |
-+ kdbus_msg_free(msg); |
30585 |
-+ |
30586 |
-+ |
30587 |
-+ /* Stage 2) of test check max message quota */ |
30588 |
-+ |
30589 |
-+ /* Empty conn queue */ |
30590 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30591 |
-+ ret = kdbus_msg_recv(conn, NULL, NULL); |
30592 |
-+ if (ret == -EAGAIN) |
30593 |
-+ break; |
30594 |
-+ } |
30595 |
-+ |
30596 |
-+ /* fill queue with max msgs quota */ |
30597 |
-+ ret = kdbus_fill_conn_queue(sender, conn->id, KDBUS_CONN_MAX_MSGS); |
30598 |
-+ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
30599 |
-+ |
30600 |
-+ /* This one is lost but it is not accounted */ |
30601 |
-+ ret = kdbus_msg_send(sender, NULL, |
30602 |
-+ cookie++, 0, 0, 0, conn->id); |
30603 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30604 |
-+ |
30605 |
-+ /* Acquire the name again */ |
30606 |
-+ ret = kdbus_name_acquire(conn, "foo.test.activator", &flags); |
30607 |
-+ ASSERT_RETURN(ret == 0); |
30608 |
-+ |
30609 |
-+ memset(&recv, 0, sizeof(recv)); |
30610 |
-+ recv.size = sizeof(recv); |
30611 |
-+ |
30612 |
-+ /* |
30613 |
-+ * Try to read messages and make sure that we have lost all |
30614 |
-+ * the activator messages due to quota checks. Our queue is |
30615 |
-+ * already full. |
30616 |
-+ */ |
30617 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30618 |
-+ ASSERT_RETURN(ret == 0); |
30619 |
-+ ASSERT_RETURN(recv.dropped_msgs == activator_msgs_count); |
30620 |
-+ |
30621 |
-+ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30622 |
-+ kdbus_msg_free(msg); |
30623 |
-+ |
30624 |
-+ kdbus_conn_free(sender); |
30625 |
-+ kdbus_conn_free(conn); |
30626 |
-+ kdbus_conn_free(activator); |
30627 |
-+ |
30628 |
-+ return 0; |
30629 |
-+} |
30630 |
-+ |
30631 |
-+static int kdbus_test_expected_reply_quota(struct kdbus_test_env *env) |
30632 |
-+{ |
30633 |
-+ int ret; |
30634 |
-+ unsigned int i, n; |
30635 |
-+ unsigned int count; |
30636 |
-+ uint64_t cookie = 0x1234abcd5678eeff; |
30637 |
-+ struct kdbus_conn *conn; |
30638 |
-+ struct kdbus_conn *connections[9]; |
30639 |
-+ |
30640 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30641 |
-+ ASSERT_RETURN(conn); |
30642 |
-+ |
30643 |
-+ for (i = 0; i < 9; i++) { |
30644 |
-+ connections[i] = kdbus_hello(env->buspath, 0, NULL, 0); |
30645 |
-+ ASSERT_RETURN(connections[i]); |
30646 |
-+ } |
30647 |
-+ |
30648 |
-+ count = 0; |
30649 |
-+ /* Send 16 messages to 8 different connections */ |
30650 |
-+ for (i = 0; i < 8; i++) { |
30651 |
-+ for (n = 0; n < 16; n++) { |
30652 |
-+ ret = kdbus_msg_send(conn, NULL, cookie++, |
30653 |
-+ KDBUS_MSG_EXPECT_REPLY, |
30654 |
-+ 100000000ULL, 0, |
30655 |
-+ connections[i]->id); |
30656 |
-+ if (ret < 0) |
30657 |
-+ break; |
30658 |
-+ |
30659 |
-+ count++; |
30660 |
-+ } |
30661 |
-+ } |
30662 |
-+ |
30663 |
-+ /* |
30664 |
-+ * We should have queued at least |
30665 |
-+ * KDBUS_CONN_MAX_REQUESTS_PENDING method call |
30666 |
-+ */ |
30667 |
-+ ASSERT_RETURN(count == KDBUS_CONN_MAX_REQUESTS_PENDING); |
30668 |
-+ |
30669 |
-+ /* |
30670 |
-+ * Now try to send a message to the last connection, |
30671 |
-+ * if we have reached KDBUS_CONN_MAX_REQUESTS_PENDING |
30672 |
-+ * no further requests are allowed |
30673 |
-+ */ |
30674 |
-+ ret = kdbus_msg_send(conn, NULL, cookie++, KDBUS_MSG_EXPECT_REPLY, |
30675 |
-+ 1000000000ULL, 0, connections[8]->id); |
30676 |
-+ ASSERT_RETURN(ret == -EMLINK); |
30677 |
-+ |
30678 |
-+ for (i = 0; i < 9; i++) |
30679 |
-+ kdbus_conn_free(connections[i]); |
30680 |
-+ |
30681 |
-+ kdbus_conn_free(conn); |
30682 |
-+ |
30683 |
-+ return 0; |
30684 |
-+} |
30685 |
-+ |
30686 |
-+int kdbus_test_pool_quota(struct kdbus_test_env *env) |
30687 |
-+{ |
30688 |
-+ struct kdbus_conn *a, *b, *c; |
30689 |
-+ struct kdbus_cmd_send cmd = {}; |
30690 |
-+ struct kdbus_item *item; |
30691 |
-+ struct kdbus_msg *recv_msg; |
30692 |
-+ struct kdbus_msg *msg; |
30693 |
-+ uint64_t cookie = time(NULL); |
30694 |
-+ uint64_t size; |
30695 |
-+ unsigned int i; |
30696 |
-+ char *payload; |
30697 |
-+ int ret; |
30698 |
-+ |
30699 |
-+ /* just a guard */ |
30700 |
-+ if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE || |
30701 |
-+ POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0) |
30702 |
-+ return 0; |
30703 |
-+ |
30704 |
-+ payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char)); |
30705 |
-+ ASSERT_RETURN_VAL(payload, -ENOMEM); |
30706 |
-+ |
30707 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30708 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30709 |
-+ c = kdbus_hello(env->buspath, 0, NULL, 0); |
30710 |
-+ ASSERT_RETURN(a && b && c); |
30711 |
-+ |
30712 |
-+ size = sizeof(struct kdbus_msg); |
30713 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
30714 |
-+ |
30715 |
-+ msg = malloc(size); |
30716 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30717 |
-+ |
30718 |
-+ memset(msg, 0, size); |
30719 |
-+ msg->size = size; |
30720 |
-+ msg->src_id = a->id; |
30721 |
-+ msg->dst_id = c->id; |
30722 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30723 |
-+ |
30724 |
-+ item = msg->items; |
30725 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
30726 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
30727 |
-+ item->vec.address = (uintptr_t)payload; |
30728 |
-+ item->vec.size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE; |
30729 |
-+ item = KDBUS_ITEM_NEXT(item); |
30730 |
-+ |
30731 |
-+ cmd.size = sizeof(cmd); |
30732 |
-+ cmd.msg_address = (uintptr_t)msg; |
30733 |
-+ |
30734 |
-+ /* |
30735 |
-+ * Send 2097248 bytes, a user is only allowed to get 33% of half of |
30736 |
-+ * the free space of the pool, the already used space is |
30737 |
-+ * accounted as free space |
30738 |
-+ */ |
30739 |
-+ size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE; |
30740 |
-+ for (i = size; i < (POOL_SIZE / 2 / 3); i += size) { |
30741 |
-+ msg->cookie = cookie++; |
30742 |
-+ |
30743 |
-+ ret = kdbus_cmd_send(a->fd, &cmd); |
30744 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
30745 |
-+ } |
30746 |
-+ |
30747 |
-+ /* Try to get more than 33% */ |
30748 |
-+ msg->cookie = cookie++; |
30749 |
-+ ret = kdbus_cmd_send(a->fd, &cmd); |
30750 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30751 |
-+ |
30752 |
-+ /* We still can pass small messages */ |
30753 |
-+ ret = kdbus_msg_send(b, NULL, cookie++, 0, 0, 0, c->id); |
30754 |
-+ ASSERT_RETURN(ret == 0); |
30755 |
-+ |
30756 |
-+ for (i = size; i < (POOL_SIZE / 2 / 3); i += size) { |
30757 |
-+ ret = kdbus_msg_recv(c, &recv_msg, NULL); |
30758 |
-+ ASSERT_RETURN(ret == 0); |
30759 |
-+ ASSERT_RETURN(recv_msg->src_id == a->id); |
30760 |
-+ |
30761 |
-+ kdbus_msg_free(recv_msg); |
30762 |
-+ } |
30763 |
-+ |
30764 |
-+ ret = kdbus_msg_recv(c, &recv_msg, NULL); |
30765 |
-+ ASSERT_RETURN(ret == 0); |
30766 |
-+ ASSERT_RETURN(recv_msg->src_id == b->id); |
30767 |
-+ |
30768 |
-+ kdbus_msg_free(recv_msg); |
30769 |
-+ |
30770 |
-+ ret = kdbus_msg_recv(c, NULL, NULL); |
30771 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30772 |
-+ |
30773 |
-+ free(msg); |
30774 |
-+ free(payload); |
30775 |
-+ |
30776 |
-+ kdbus_conn_free(c); |
30777 |
-+ kdbus_conn_free(b); |
30778 |
-+ kdbus_conn_free(a); |
30779 |
-+ |
30780 |
-+ return 0; |
30781 |
-+} |
30782 |
-+ |
30783 |
-+int kdbus_test_message_quota(struct kdbus_test_env *env) |
30784 |
-+{ |
30785 |
-+ struct kdbus_conn *a, *b; |
30786 |
-+ uint64_t cookie = 0; |
30787 |
-+ int ret; |
30788 |
-+ int i; |
30789 |
-+ |
30790 |
-+ ret = kdbus_test_activator_quota(env); |
30791 |
-+ ASSERT_RETURN(ret == 0); |
30792 |
-+ |
30793 |
-+ ret = kdbus_test_notify_kernel_quota(env); |
30794 |
-+ ASSERT_RETURN(ret == 0); |
30795 |
-+ |
30796 |
-+ ret = kdbus_test_pool_quota(env); |
30797 |
-+ ASSERT_RETURN(ret == 0); |
30798 |
-+ |
30799 |
-+ ret = kdbus_test_expected_reply_quota(env); |
30800 |
-+ ASSERT_RETURN(ret == 0); |
30801 |
-+ |
30802 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30803 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30804 |
-+ |
30805 |
-+ ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS); |
30806 |
-+ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
30807 |
-+ |
30808 |
-+ ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id); |
30809 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30810 |
-+ |
30811 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i) { |
30812 |
-+ ret = kdbus_msg_recv(a, NULL, NULL); |
30813 |
-+ ASSERT_RETURN(ret == 0); |
30814 |
-+ } |
30815 |
-+ |
30816 |
-+ ret = kdbus_msg_recv(a, NULL, NULL); |
30817 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30818 |
-+ |
30819 |
-+ ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1); |
30820 |
-+ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
30821 |
-+ |
30822 |
-+ ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id); |
30823 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30824 |
-+ |
30825 |
-+ kdbus_conn_free(a); |
30826 |
-+ kdbus_conn_free(b); |
30827 |
-+ |
30828 |
-+ return TEST_OK; |
30829 |
-+} |
30830 |
-+ |
30831 |
-+int kdbus_test_memory_access(struct kdbus_test_env *env) |
30832 |
-+{ |
30833 |
-+ struct kdbus_conn *a, *b; |
30834 |
-+ struct kdbus_cmd_send cmd = {}; |
30835 |
-+ struct kdbus_item *item; |
30836 |
-+ struct kdbus_msg *msg; |
30837 |
-+ uint64_t test_addr = 0; |
30838 |
-+ char line[256]; |
30839 |
-+ uint64_t size; |
30840 |
-+ FILE *f; |
30841 |
-+ int ret; |
30842 |
-+ |
30843 |
-+ /* |
30844 |
-+ * Search in /proc/kallsyms for the address of a kernel symbol that |
30845 |
-+ * should always be there, regardless of the config. Use that address |
30846 |
-+ * in a PAYLOAD_VEC item and make sure it's inaccessible. |
30847 |
-+ */ |
30848 |
-+ |
30849 |
-+ f = fopen("/proc/kallsyms", "r"); |
30850 |
-+ if (!f) |
30851 |
-+ return TEST_SKIP; |
30852 |
-+ |
30853 |
-+ while (fgets(line, sizeof(line), f)) { |
30854 |
-+ char *s = line; |
30855 |
-+ |
30856 |
-+ if (!strsep(&s, " ")) |
30857 |
-+ continue; |
30858 |
-+ |
30859 |
-+ if (!strsep(&s, " ")) |
30860 |
-+ continue; |
30861 |
-+ |
30862 |
-+ if (!strncmp(s, "mutex_lock", 10)) { |
30863 |
-+ test_addr = strtoull(line, NULL, 16); |
30864 |
-+ break; |
30865 |
-+ } |
30866 |
-+ } |
30867 |
-+ |
30868 |
-+ fclose(f); |
30869 |
-+ |
30870 |
-+ if (!test_addr) |
30871 |
-+ return TEST_SKIP; |
30872 |
-+ |
30873 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30874 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30875 |
-+ ASSERT_RETURN(a && b); |
30876 |
-+ |
30877 |
-+ size = sizeof(struct kdbus_msg); |
30878 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
30879 |
-+ |
30880 |
-+ msg = alloca(size); |
30881 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30882 |
-+ |
30883 |
-+ memset(msg, 0, size); |
30884 |
-+ msg->size = size; |
30885 |
-+ msg->src_id = a->id; |
30886 |
-+ msg->dst_id = b->id; |
30887 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30888 |
-+ |
30889 |
-+ item = msg->items; |
30890 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
30891 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
30892 |
-+ item->vec.address = test_addr; |
30893 |
-+ item->vec.size = sizeof(void*); |
30894 |
-+ item = KDBUS_ITEM_NEXT(item); |
30895 |
-+ |
30896 |
-+ cmd.size = sizeof(cmd); |
30897 |
-+ cmd.msg_address = (uintptr_t)msg; |
30898 |
-+ |
30899 |
-+ ret = kdbus_cmd_send(a->fd, &cmd); |
30900 |
-+ ASSERT_RETURN(ret == -EFAULT); |
30901 |
-+ |
30902 |
-+ kdbus_conn_free(b); |
30903 |
-+ kdbus_conn_free(a); |
30904 |
-+ |
30905 |
-+ return 0; |
30906 |
-+} |
30907 |
-diff --git a/tools/testing/selftests/kdbus/test-metadata-ns.c b/tools/testing/selftests/kdbus/test-metadata-ns.c |
30908 |
-new file mode 100644 |
30909 |
-index 0000000..1f6edc0 |
30910 |
---- /dev/null |
30911 |
-+++ b/tools/testing/selftests/kdbus/test-metadata-ns.c |
30912 |
-@@ -0,0 +1,500 @@ |
30913 |
-+/* |
30914 |
-+ * Test metadata in new namespaces. Even if our tests can run |
30915 |
-+ * in a namespaced setup, this test is necessary so we can inspect |
30916 |
-+ * metadata on the same kdbusfs but between multiple namespaces |
30917 |
-+ */ |
30918 |
-+ |
30919 |
-+#include <stdio.h> |
30920 |
-+#include <string.h> |
30921 |
-+#include <sched.h> |
30922 |
-+#include <time.h> |
30923 |
-+#include <fcntl.h> |
30924 |
-+#include <stdlib.h> |
30925 |
-+#include <stddef.h> |
30926 |
-+#include <unistd.h> |
30927 |
-+#include <stdint.h> |
30928 |
-+#include <errno.h> |
30929 |
-+#include <assert.h> |
30930 |
-+#include <signal.h> |
30931 |
-+#include <sys/wait.h> |
30932 |
-+#include <sys/prctl.h> |
30933 |
-+#include <sys/eventfd.h> |
30934 |
-+#include <sys/syscall.h> |
30935 |
-+#include <sys/capability.h> |
30936 |
-+#include <linux/sched.h> |
30937 |
-+ |
30938 |
-+#include "kdbus-test.h" |
30939 |
-+#include "kdbus-util.h" |
30940 |
-+#include "kdbus-enum.h" |
30941 |
-+ |
30942 |
-+static const struct kdbus_creds privileged_creds = {}; |
30943 |
-+ |
30944 |
-+static const struct kdbus_creds unmapped_creds = { |
30945 |
-+ .uid = UNPRIV_UID, |
30946 |
-+ .euid = UNPRIV_UID, |
30947 |
-+ .suid = UNPRIV_UID, |
30948 |
-+ .fsuid = UNPRIV_UID, |
30949 |
-+ .gid = UNPRIV_GID, |
30950 |
-+ .egid = UNPRIV_GID, |
30951 |
-+ .sgid = UNPRIV_GID, |
30952 |
-+ .fsgid = UNPRIV_GID, |
30953 |
-+}; |
30954 |
-+ |
30955 |
-+static const struct kdbus_pids unmapped_pids = {}; |
30956 |
-+ |
30957 |
-+/* Get only the first item */ |
30958 |
-+static struct kdbus_item *kdbus_get_item(struct kdbus_msg *msg, |
30959 |
-+ uint64_t type) |
30960 |
-+{ |
30961 |
-+ struct kdbus_item *item; |
30962 |
-+ |
30963 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) |
30964 |
-+ if (item->type == type) |
30965 |
-+ return item; |
30966 |
-+ |
30967 |
-+ return NULL; |
30968 |
-+} |
30969 |
-+ |
30970 |
-+static int kdbus_match_kdbus_creds(struct kdbus_msg *msg, |
30971 |
-+ const struct kdbus_creds *expected_creds) |
30972 |
-+{ |
30973 |
-+ struct kdbus_item *item; |
30974 |
-+ |
30975 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CREDS); |
30976 |
-+ ASSERT_RETURN(item); |
30977 |
-+ |
30978 |
-+ ASSERT_RETURN(memcmp(&item->creds, expected_creds, |
30979 |
-+ sizeof(struct kdbus_creds)) == 0); |
30980 |
-+ |
30981 |
-+ return 0; |
30982 |
-+} |
30983 |
-+ |
30984 |
-+static int kdbus_match_kdbus_pids(struct kdbus_msg *msg, |
30985 |
-+ const struct kdbus_pids *expected_pids) |
30986 |
-+{ |
30987 |
-+ struct kdbus_item *item; |
30988 |
-+ |
30989 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
30990 |
-+ ASSERT_RETURN(item); |
30991 |
-+ |
30992 |
-+ ASSERT_RETURN(memcmp(&item->pids, expected_pids, |
30993 |
-+ sizeof(struct kdbus_pids)) == 0); |
30994 |
-+ |
30995 |
-+ return 0; |
30996 |
-+} |
30997 |
-+ |
30998 |
-+static int __kdbus_clone_userns_test(const char *bus, |
30999 |
-+ struct kdbus_conn *conn, |
31000 |
-+ uint64_t grandpa_pid, |
31001 |
-+ int signal_fd) |
31002 |
-+{ |
31003 |
-+ int clone_ret; |
31004 |
-+ int ret; |
31005 |
-+ struct kdbus_msg *msg = NULL; |
31006 |
-+ const struct kdbus_item *item; |
31007 |
-+ uint64_t cookie = time(NULL) ^ 0xdeadbeef; |
31008 |
-+ struct kdbus_conn *unpriv_conn = NULL; |
31009 |
-+ struct kdbus_pids parent_pids = { |
31010 |
-+ .pid = getppid(), |
31011 |
-+ .tid = getppid(), |
31012 |
-+ .ppid = grandpa_pid, |
31013 |
-+ }; |
31014 |
-+ |
31015 |
-+ ret = drop_privileges(UNPRIV_UID, UNPRIV_GID); |
31016 |
-+ ASSERT_EXIT(ret == 0); |
31017 |
-+ |
31018 |
-+ unpriv_conn = kdbus_hello(bus, 0, NULL, 0); |
31019 |
-+ ASSERT_EXIT(unpriv_conn); |
31020 |
-+ |
31021 |
-+ ret = kdbus_add_match_empty(unpriv_conn); |
31022 |
-+ ASSERT_EXIT(ret == 0); |
31023 |
-+ |
31024 |
-+ /* |
31025 |
-+ * ping privileged connection from this new unprivileged |
31026 |
-+ * one |
31027 |
-+ */ |
31028 |
-+ |
31029 |
-+ ret = kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0, |
31030 |
-+ 0, conn->id); |
31031 |
-+ ASSERT_EXIT(ret == 0); |
31032 |
-+ |
31033 |
-+ /* |
31034 |
-+ * Since we just dropped privileges, the dumpable flag |
31035 |
-+ * was just cleared which makes the /proc/$clone_child/uid_map |
31036 |
-+ * to be owned by root, hence any userns uid mapping will fail |
31037 |
-+ * with -EPERM since the mapping will be done by uid 65534. |
31038 |
-+ * |
31039 |
-+ * To avoid this set the dumpable flag again which makes |
31040 |
-+ * procfs update the /proc/$clone_child/ inodes owner to 65534. |
31041 |
-+ * |
31042 |
-+ * Using this we will be able write to /proc/$clone_child/uid_map |
31043 |
-+ * as uid 65534 and map the uid 65534 to 0 inside the user namespace. |
31044 |
-+ */ |
31045 |
-+ ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER); |
31046 |
-+ ASSERT_EXIT(ret == 0); |
31047 |
-+ |
31048 |
-+ /* Make child privileged in its new userns and run tests */ |
31049 |
-+ |
31050 |
-+ ret = RUN_CLONE_CHILD(&clone_ret, |
31051 |
-+ SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID, |
31052 |
-+ ({ 0; /* Clone setup, nothing */ }), |
31053 |
-+ ({ |
31054 |
-+ eventfd_t event_status = 0; |
31055 |
-+ struct kdbus_conn *userns_conn; |
31056 |
-+ |
31057 |
-+ /* ping connection from the new user namespace */ |
31058 |
-+ userns_conn = kdbus_hello(bus, 0, NULL, 0); |
31059 |
-+ ASSERT_EXIT(userns_conn); |
31060 |
-+ |
31061 |
-+ ret = kdbus_add_match_empty(userns_conn); |
31062 |
-+ ASSERT_EXIT(ret == 0); |
31063 |
-+ |
31064 |
-+ cookie++; |
31065 |
-+ ret = kdbus_msg_send(userns_conn, NULL, cookie, |
31066 |
-+ 0, 0, 0, conn->id); |
31067 |
-+ ASSERT_EXIT(ret == 0); |
31068 |
-+ |
31069 |
-+ /* Parent did send */ |
31070 |
-+ ret = eventfd_read(signal_fd, &event_status); |
31071 |
-+ ASSERT_RETURN(ret >= 0 && event_status == 1); |
31072 |
-+ |
31073 |
-+ /* |
31074 |
-+ * Receive from privileged connection |
31075 |
-+ */ |
31076 |
-+ kdbus_printf("Privileged → unprivileged/privileged " |
31077 |
-+ "in its userns " |
31078 |
-+ "(different userns and pidns):\n"); |
31079 |
-+ ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL); |
31080 |
-+ ASSERT_EXIT(ret == 0); |
31081 |
-+ ASSERT_EXIT(msg->dst_id == userns_conn->id); |
31082 |
-+ |
31083 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31084 |
-+ ASSERT_EXIT(item); |
31085 |
-+ |
31086 |
-+ /* uid/gid not mapped, so we have unpriv cached creds */ |
31087 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31088 |
-+ ASSERT_EXIT(ret == 0); |
31089 |
-+ |
31090 |
-+ /* |
31091 |
-+ * Diffent pid namepsaces. This is the child pidns |
31092 |
-+ * so it should not see its parent kdbus_pids |
31093 |
-+ */ |
31094 |
-+ ret = kdbus_match_kdbus_pids(msg, &unmapped_pids); |
31095 |
-+ ASSERT_EXIT(ret == 0); |
31096 |
-+ |
31097 |
-+ kdbus_msg_free(msg); |
31098 |
-+ |
31099 |
-+ |
31100 |
-+ /* |
31101 |
-+ * Receive broadcast from privileged connection |
31102 |
-+ */ |
31103 |
-+ kdbus_printf("Privileged → unprivileged/privileged " |
31104 |
-+ "in its userns " |
31105 |
-+ "(different userns and pidns):\n"); |
31106 |
-+ ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL); |
31107 |
-+ ASSERT_EXIT(ret == 0); |
31108 |
-+ ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST); |
31109 |
-+ |
31110 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31111 |
-+ ASSERT_EXIT(item); |
31112 |
-+ |
31113 |
-+ /* uid/gid not mapped, so we have unpriv cached creds */ |
31114 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31115 |
-+ ASSERT_EXIT(ret == 0); |
31116 |
-+ |
31117 |
-+ /* |
31118 |
-+ * Diffent pid namepsaces. This is the child pidns |
31119 |
-+ * so it should not see its parent kdbus_pids |
31120 |
-+ */ |
31121 |
-+ ret = kdbus_match_kdbus_pids(msg, &unmapped_pids); |
31122 |
-+ ASSERT_EXIT(ret == 0); |
31123 |
-+ |
31124 |
-+ kdbus_msg_free(msg); |
31125 |
-+ |
31126 |
-+ kdbus_conn_free(userns_conn); |
31127 |
-+ }), |
31128 |
-+ ({ |
31129 |
-+ /* Parent setup map child uid/gid */ |
31130 |
-+ ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"); |
31131 |
-+ ASSERT_EXIT(ret == 0); |
31132 |
-+ }), |
31133 |
-+ ({ 0; })); |
31134 |
-+ /* Unprivileged was not able to create user namespace */ |
31135 |
-+ if (clone_ret == -EPERM) { |
31136 |
-+ kdbus_printf("-- CLONE_NEWUSER TEST Failed for " |
31137 |
-+ "uid: %u\n -- Make sure that your kernel " |
31138 |
-+ "do not allow CLONE_NEWUSER for " |
31139 |
-+ "unprivileged users\n", UNPRIV_UID); |
31140 |
-+ ret = 0; |
31141 |
-+ goto out; |
31142 |
-+ } |
31143 |
-+ |
31144 |
-+ ASSERT_EXIT(ret == 0); |
31145 |
-+ |
31146 |
-+ |
31147 |
-+ /* |
31148 |
-+ * Receive from privileged connection |
31149 |
-+ */ |
31150 |
-+ kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n"); |
31151 |
-+ ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL); |
31152 |
-+ |
31153 |
-+ ASSERT_EXIT(ret == 0); |
31154 |
-+ ASSERT_EXIT(msg->dst_id == unpriv_conn->id); |
31155 |
-+ |
31156 |
-+ /* will get the privileged creds */ |
31157 |
-+ ret = kdbus_match_kdbus_creds(msg, &privileged_creds); |
31158 |
-+ ASSERT_EXIT(ret == 0); |
31159 |
-+ |
31160 |
-+ /* Same pidns so will get the kdbus_pids */ |
31161 |
-+ ret = kdbus_match_kdbus_pids(msg, &parent_pids); |
31162 |
-+ ASSERT_RETURN(ret == 0); |
31163 |
-+ |
31164 |
-+ kdbus_msg_free(msg); |
31165 |
-+ |
31166 |
-+ |
31167 |
-+ /* |
31168 |
-+ * Receive broadcast from privileged connection |
31169 |
-+ */ |
31170 |
-+ kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n"); |
31171 |
-+ ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL); |
31172 |
-+ |
31173 |
-+ ASSERT_EXIT(ret == 0); |
31174 |
-+ ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST); |
31175 |
-+ |
31176 |
-+ /* will get the privileged creds */ |
31177 |
-+ ret = kdbus_match_kdbus_creds(msg, &privileged_creds); |
31178 |
-+ ASSERT_EXIT(ret == 0); |
31179 |
-+ |
31180 |
-+ ret = kdbus_match_kdbus_pids(msg, &parent_pids); |
31181 |
-+ ASSERT_RETURN(ret == 0); |
31182 |
-+ |
31183 |
-+ kdbus_msg_free(msg); |
31184 |
-+ |
31185 |
-+out: |
31186 |
-+ kdbus_conn_free(unpriv_conn); |
31187 |
-+ |
31188 |
-+ return ret; |
31189 |
-+} |
31190 |
-+ |
31191 |
-+static int kdbus_clone_userns_test(const char *bus, |
31192 |
-+ struct kdbus_conn *conn) |
31193 |
-+{ |
31194 |
-+ int ret, status, efd; |
31195 |
-+ pid_t pid, ppid; |
31196 |
-+ uint64_t unpriv_conn_id, userns_conn_id; |
31197 |
-+ struct kdbus_msg *msg; |
31198 |
-+ const struct kdbus_item *item; |
31199 |
-+ struct kdbus_pids expected_pids; |
31200 |
-+ struct kdbus_conn *monitor; |
31201 |
-+ |
31202 |
-+ kdbus_printf("STARTING TEST 'metadata-ns'.\n"); |
31203 |
-+ |
31204 |
-+ monitor = kdbus_hello(bus, KDBUS_HELLO_MONITOR, NULL, 0); |
31205 |
-+ ASSERT_EXIT(monitor); |
31206 |
-+ |
31207 |
-+ /* |
31208 |
-+ * parent will signal to child that is in its |
31209 |
-+ * userns to read its queue |
31210 |
-+ */ |
31211 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
31212 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
31213 |
-+ |
31214 |
-+ ppid = getppid(); |
31215 |
-+ |
31216 |
-+ pid = fork(); |
31217 |
-+ ASSERT_RETURN_VAL(pid >= 0, -errno); |
31218 |
-+ |
31219 |
-+ if (pid == 0) { |
31220 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
31221 |
-+ ASSERT_EXIT_VAL(ret == 0, -errno); |
31222 |
-+ |
31223 |
-+ ret = __kdbus_clone_userns_test(bus, conn, ppid, efd); |
31224 |
-+ _exit(ret); |
31225 |
-+ } |
31226 |
-+ |
31227 |
-+ |
31228 |
-+ /* Phase 1) privileged receives from unprivileged */ |
31229 |
-+ |
31230 |
-+ /* |
31231 |
-+ * Receive from the unprivileged child |
31232 |
-+ */ |
31233 |
-+ kdbus_printf("\nUnprivileged → privileged (same namespaces):\n"); |
31234 |
-+ ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL); |
31235 |
-+ ASSERT_RETURN(ret == 0); |
31236 |
-+ |
31237 |
-+ unpriv_conn_id = msg->src_id; |
31238 |
-+ |
31239 |
-+ /* Unprivileged user */ |
31240 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31241 |
-+ ASSERT_RETURN(ret == 0); |
31242 |
-+ |
31243 |
-+ /* Set the expected creds_pids */ |
31244 |
-+ expected_pids = (struct kdbus_pids) { |
31245 |
-+ .pid = pid, |
31246 |
-+ .tid = pid, |
31247 |
-+ .ppid = getpid(), |
31248 |
-+ }; |
31249 |
-+ ret = kdbus_match_kdbus_pids(msg, &expected_pids); |
31250 |
-+ ASSERT_RETURN(ret == 0); |
31251 |
-+ |
31252 |
-+ kdbus_msg_free(msg); |
31253 |
-+ |
31254 |
-+ |
31255 |
-+ /* |
31256 |
-+ * Receive from the unprivileged that is in his own |
31257 |
-+ * userns and pidns |
31258 |
-+ */ |
31259 |
-+ |
31260 |
-+ kdbus_printf("\nUnprivileged/privileged in its userns → privileged " |
31261 |
-+ "(different userns and pidns)\n"); |
31262 |
-+ ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL); |
31263 |
-+ if (ret == -ETIMEDOUT) |
31264 |
-+ /* perhaps unprivileged userns is not allowed */ |
31265 |
-+ goto wait; |
31266 |
-+ |
31267 |
-+ ASSERT_RETURN(ret == 0); |
31268 |
-+ |
31269 |
-+ userns_conn_id = msg->src_id; |
31270 |
-+ |
31271 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31272 |
-+ ASSERT_RETURN(item); |
31273 |
-+ |
31274 |
-+ /* |
31275 |
-+ * Compare received items, creds must be translated into |
31276 |
-+ * the receiver user namespace, so the user is unprivileged |
31277 |
-+ */ |
31278 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31279 |
-+ ASSERT_RETURN(ret == 0); |
31280 |
-+ |
31281 |
-+ /* |
31282 |
-+ * We should have the kdbus_pids since we are the parent |
31283 |
-+ * pidns |
31284 |
-+ */ |
31285 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31286 |
-+ ASSERT_RETURN(item); |
31287 |
-+ |
31288 |
-+ ASSERT_RETURN(memcmp(&item->pids, &unmapped_pids, |
31289 |
-+ sizeof(struct kdbus_pids)) != 0); |
31290 |
-+ |
31291 |
-+ /* |
31292 |
-+ * Parent pid of the unprivileged/privileged in its userns |
31293 |
-+ * is the unprivileged child pid that was forked here. |
31294 |
-+ */ |
31295 |
-+ ASSERT_RETURN((uint64_t)pid == item->pids.ppid); |
31296 |
-+ |
31297 |
-+ kdbus_msg_free(msg); |
31298 |
-+ |
31299 |
-+ |
31300 |
-+ /* Phase 2) Privileged connection sends now 3 packets */ |
31301 |
-+ |
31302 |
-+ /* |
31303 |
-+ * Sending to unprivileged connections a unicast |
31304 |
-+ */ |
31305 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31306 |
-+ 0, unpriv_conn_id); |
31307 |
-+ ASSERT_RETURN(ret == 0); |
31308 |
-+ |
31309 |
-+ /* signal to child that is in its userns */ |
31310 |
-+ ret = eventfd_write(efd, 1); |
31311 |
-+ ASSERT_EXIT(ret == 0); |
31312 |
-+ |
31313 |
-+ /* |
31314 |
-+ * Sending to unprivileged/privilged in its userns |
31315 |
-+ * connections a unicast |
31316 |
-+ */ |
31317 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31318 |
-+ 0, userns_conn_id); |
31319 |
-+ ASSERT_RETURN(ret == 0); |
31320 |
-+ |
31321 |
-+ /* |
31322 |
-+ * Sending to unprivileged connections a broadcast |
31323 |
-+ */ |
31324 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31325 |
-+ 0, KDBUS_DST_ID_BROADCAST); |
31326 |
-+ ASSERT_RETURN(ret == 0); |
31327 |
-+ |
31328 |
-+ |
31329 |
-+wait: |
31330 |
-+ ret = waitpid(pid, &status, 0); |
31331 |
-+ ASSERT_RETURN(ret >= 0); |
31332 |
-+ |
31333 |
-+ ASSERT_RETURN(WIFEXITED(status)) |
31334 |
-+ ASSERT_RETURN(!WEXITSTATUS(status)); |
31335 |
-+ |
31336 |
-+ /* Dump monitor queue */ |
31337 |
-+ kdbus_printf("\n\nMonitor queue:\n"); |
31338 |
-+ for (;;) { |
31339 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, NULL); |
31340 |
-+ if (ret < 0) |
31341 |
-+ break; |
31342 |
-+ |
31343 |
-+ if (msg->payload_type == KDBUS_PAYLOAD_DBUS) { |
31344 |
-+ /* |
31345 |
-+ * Parent pidns should see all the |
31346 |
-+ * pids |
31347 |
-+ */ |
31348 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31349 |
-+ ASSERT_RETURN(item); |
31350 |
-+ |
31351 |
-+ ASSERT_RETURN(item->pids.pid != 0 && |
31352 |
-+ item->pids.tid != 0 && |
31353 |
-+ item->pids.ppid != 0); |
31354 |
-+ } |
31355 |
-+ |
31356 |
-+ kdbus_msg_free(msg); |
31357 |
-+ } |
31358 |
-+ |
31359 |
-+ kdbus_conn_free(monitor); |
31360 |
-+ close(efd); |
31361 |
-+ |
31362 |
-+ return 0; |
31363 |
-+} |
31364 |
-+ |
31365 |
-+int kdbus_test_metadata_ns(struct kdbus_test_env *env) |
31366 |
-+{ |
31367 |
-+ int ret; |
31368 |
-+ struct kdbus_conn *holder, *conn; |
31369 |
-+ struct kdbus_policy_access policy_access = { |
31370 |
-+ /* Allow world so we can inspect metadata in namespace */ |
31371 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
31372 |
-+ .id = geteuid(), |
31373 |
-+ .access = KDBUS_POLICY_TALK, |
31374 |
-+ }; |
31375 |
-+ |
31376 |
-+ /* |
31377 |
-+ * We require user-namespaces and all uids/gids |
31378 |
-+ * should be mapped (we can just require the necessary ones) |
31379 |
-+ */ |
31380 |
-+ if (!config_user_ns_is_enabled() || |
31381 |
-+ !all_uids_gids_are_mapped()) |
31382 |
-+ return TEST_SKIP; |
31383 |
-+ |
31384 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, CAP_SYS_ADMIN, -1); |
31385 |
-+ ASSERT_RETURN(ret >= 0); |
31386 |
-+ |
31387 |
-+ /* no enough privileges, SKIP test */ |
31388 |
-+ if (!ret) |
31389 |
-+ return TEST_SKIP; |
31390 |
-+ |
31391 |
-+ holder = kdbus_hello_registrar(env->buspath, "com.example.metadata", |
31392 |
-+ &policy_access, 1, |
31393 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
31394 |
-+ ASSERT_RETURN(holder); |
31395 |
-+ |
31396 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31397 |
-+ ASSERT_RETURN(conn); |
31398 |
-+ |
31399 |
-+ ret = kdbus_add_match_empty(conn); |
31400 |
-+ ASSERT_RETURN(ret == 0); |
31401 |
-+ |
31402 |
-+ ret = kdbus_name_acquire(conn, "com.example.metadata", NULL); |
31403 |
-+ ASSERT_EXIT(ret >= 0); |
31404 |
-+ |
31405 |
-+ ret = kdbus_clone_userns_test(env->buspath, conn); |
31406 |
-+ ASSERT_RETURN(ret == 0); |
31407 |
-+ |
31408 |
-+ kdbus_conn_free(holder); |
31409 |
-+ kdbus_conn_free(conn); |
31410 |
-+ |
31411 |
-+ return TEST_OK; |
31412 |
-+} |
31413 |
-diff --git a/tools/testing/selftests/kdbus/test-monitor.c b/tools/testing/selftests/kdbus/test-monitor.c |
31414 |
-new file mode 100644 |
31415 |
-index 0000000..e00d738 |
31416 |
---- /dev/null |
31417 |
-+++ b/tools/testing/selftests/kdbus/test-monitor.c |
31418 |
-@@ -0,0 +1,176 @@ |
31419 |
-+#include <stdio.h> |
31420 |
-+#include <string.h> |
31421 |
-+#include <time.h> |
31422 |
-+#include <fcntl.h> |
31423 |
-+#include <stdlib.h> |
31424 |
-+#include <stddef.h> |
31425 |
-+#include <unistd.h> |
31426 |
-+#include <stdint.h> |
31427 |
-+#include <stdbool.h> |
31428 |
-+#include <errno.h> |
31429 |
-+#include <assert.h> |
31430 |
-+#include <signal.h> |
31431 |
-+#include <sys/time.h> |
31432 |
-+#include <sys/mman.h> |
31433 |
-+#include <sys/capability.h> |
31434 |
-+#include <sys/wait.h> |
31435 |
-+ |
31436 |
-+#include "kdbus-util.h" |
31437 |
-+#include "kdbus-enum.h" |
31438 |
-+ |
31439 |
-+#include "kdbus-util.h" |
31440 |
-+#include "kdbus-enum.h" |
31441 |
-+#include "kdbus-test.h" |
31442 |
-+ |
31443 |
-+int kdbus_test_monitor(struct kdbus_test_env *env) |
31444 |
-+{ |
31445 |
-+ struct kdbus_conn *monitor, *conn; |
31446 |
-+ unsigned int cookie = 0xdeadbeef; |
31447 |
-+ struct kdbus_msg *msg; |
31448 |
-+ uint64_t offset = 0; |
31449 |
-+ int ret; |
31450 |
-+ |
31451 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31452 |
-+ ASSERT_RETURN(conn); |
31453 |
-+ |
31454 |
-+ /* add matches to make sure the monitor do not trigger an item add or |
31455 |
-+ * remove on connect and disconnect, respectively. |
31456 |
-+ */ |
31457 |
-+ ret = kdbus_add_match_id(conn, 0x1, KDBUS_ITEM_ID_ADD, |
31458 |
-+ KDBUS_MATCH_ID_ANY); |
31459 |
-+ ASSERT_RETURN(ret == 0); |
31460 |
-+ |
31461 |
-+ ret = kdbus_add_match_id(conn, 0x2, KDBUS_ITEM_ID_REMOVE, |
31462 |
-+ KDBUS_MATCH_ID_ANY); |
31463 |
-+ ASSERT_RETURN(ret == 0); |
31464 |
-+ |
31465 |
-+ /* register a monitor */ |
31466 |
-+ monitor = kdbus_hello(env->buspath, KDBUS_HELLO_MONITOR, NULL, 0); |
31467 |
-+ ASSERT_RETURN(monitor); |
31468 |
-+ |
31469 |
-+ /* make sure we did not receive a monitor connect notification */ |
31470 |
-+ ret = kdbus_msg_recv(conn, &msg, &offset); |
31471 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
31472 |
-+ |
31473 |
-+ /* check that a monitor cannot acquire a name */ |
31474 |
-+ ret = kdbus_name_acquire(monitor, "foo.bar.baz", NULL); |
31475 |
-+ ASSERT_RETURN(ret == -EOPNOTSUPP); |
31476 |
-+ |
31477 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, conn->id); |
31478 |
-+ ASSERT_RETURN(ret == 0); |
31479 |
-+ |
31480 |
-+ /* the recipient should have gotten the message */ |
31481 |
-+ ret = kdbus_msg_recv(conn, &msg, &offset); |
31482 |
-+ ASSERT_RETURN(ret == 0); |
31483 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31484 |
-+ kdbus_msg_free(msg); |
31485 |
-+ kdbus_free(conn, offset); |
31486 |
-+ |
31487 |
-+ /* and so should the monitor */ |
31488 |
-+ ret = kdbus_msg_recv(monitor, &msg, &offset); |
31489 |
-+ ASSERT_RETURN(ret == 0); |
31490 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31491 |
-+ |
31492 |
-+ kdbus_msg_free(msg); |
31493 |
-+ kdbus_free(monitor, offset); |
31494 |
-+ |
31495 |
-+ /* Installing matches for monitors must fais must fail */ |
31496 |
-+ ret = kdbus_add_match_empty(monitor); |
31497 |
-+ ASSERT_RETURN(ret == -EOPNOTSUPP); |
31498 |
-+ |
31499 |
-+ cookie++; |
31500 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31501 |
-+ KDBUS_DST_ID_BROADCAST); |
31502 |
-+ ASSERT_RETURN(ret == 0); |
31503 |
-+ |
31504 |
-+ /* The monitor should get the message. */ |
31505 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31506 |
-+ ASSERT_RETURN(ret == 0); |
31507 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31508 |
-+ |
31509 |
-+ kdbus_msg_free(msg); |
31510 |
-+ kdbus_free(monitor, offset); |
31511 |
-+ |
31512 |
-+ /* |
31513 |
-+ * Since we are the only monitor, update the attach flags |
31514 |
-+ * and tell we are not interessted in attach flags recv |
31515 |
-+ */ |
31516 |
-+ |
31517 |
-+ ret = kdbus_conn_update_attach_flags(monitor, |
31518 |
-+ _KDBUS_ATTACH_ALL, |
31519 |
-+ 0); |
31520 |
-+ ASSERT_RETURN(ret == 0); |
31521 |
-+ |
31522 |
-+ cookie++; |
31523 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31524 |
-+ KDBUS_DST_ID_BROADCAST); |
31525 |
-+ ASSERT_RETURN(ret == 0); |
31526 |
-+ |
31527 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31528 |
-+ ASSERT_RETURN(ret == 0); |
31529 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31530 |
-+ |
31531 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
31532 |
-+ ASSERT_RETURN(ret == 0); |
31533 |
-+ |
31534 |
-+ kdbus_msg_free(msg); |
31535 |
-+ kdbus_free(monitor, offset); |
31536 |
-+ |
31537 |
-+ /* |
31538 |
-+ * Now we are interested in KDBUS_ITEM_TIMESTAMP and |
31539 |
-+ * KDBUS_ITEM_CREDS |
31540 |
-+ */ |
31541 |
-+ ret = kdbus_conn_update_attach_flags(monitor, |
31542 |
-+ _KDBUS_ATTACH_ALL, |
31543 |
-+ KDBUS_ATTACH_TIMESTAMP | |
31544 |
-+ KDBUS_ATTACH_CREDS); |
31545 |
-+ ASSERT_RETURN(ret == 0); |
31546 |
-+ |
31547 |
-+ cookie++; |
31548 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31549 |
-+ KDBUS_DST_ID_BROADCAST); |
31550 |
-+ ASSERT_RETURN(ret == 0); |
31551 |
-+ |
31552 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31553 |
-+ ASSERT_RETURN(ret == 0); |
31554 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31555 |
-+ |
31556 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
31557 |
-+ ASSERT_RETURN(ret == 1); |
31558 |
-+ |
31559 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_CREDS); |
31560 |
-+ ASSERT_RETURN(ret == 1); |
31561 |
-+ |
31562 |
-+ /* the KDBUS_ITEM_PID_COMM was not requested */ |
31563 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_PID_COMM); |
31564 |
-+ ASSERT_RETURN(ret == 0); |
31565 |
-+ |
31566 |
-+ kdbus_msg_free(msg); |
31567 |
-+ kdbus_free(monitor, offset); |
31568 |
-+ |
31569 |
-+ kdbus_conn_free(monitor); |
31570 |
-+ /* make sure we did not receive a monitor disconnect notification */ |
31571 |
-+ ret = kdbus_msg_recv(conn, &msg, &offset); |
31572 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
31573 |
-+ |
31574 |
-+ kdbus_conn_free(conn); |
31575 |
-+ |
31576 |
-+ /* Make sure that monitor as unprivileged is not allowed */ |
31577 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
31578 |
-+ ASSERT_RETURN(ret >= 0); |
31579 |
-+ |
31580 |
-+ if (ret && all_uids_gids_are_mapped()) { |
31581 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
31582 |
-+ monitor = kdbus_hello(env->buspath, |
31583 |
-+ KDBUS_HELLO_MONITOR, |
31584 |
-+ NULL, 0); |
31585 |
-+ ASSERT_EXIT(!monitor && errno == EPERM); |
31586 |
-+ |
31587 |
-+ _exit(EXIT_SUCCESS); |
31588 |
-+ }), |
31589 |
-+ ({ 0; })); |
31590 |
-+ ASSERT_RETURN(ret == 0); |
31591 |
-+ } |
31592 |
-+ |
31593 |
-+ return TEST_OK; |
31594 |
-+} |
31595 |
-diff --git a/tools/testing/selftests/kdbus/test-names.c b/tools/testing/selftests/kdbus/test-names.c |
31596 |
-new file mode 100644 |
31597 |
-index 0000000..e400dc8 |
31598 |
---- /dev/null |
31599 |
-+++ b/tools/testing/selftests/kdbus/test-names.c |
31600 |
-@@ -0,0 +1,272 @@ |
31601 |
-+#include <stdio.h> |
31602 |
-+#include <string.h> |
31603 |
-+#include <time.h> |
31604 |
-+#include <fcntl.h> |
31605 |
-+#include <stdlib.h> |
31606 |
-+#include <stddef.h> |
31607 |
-+#include <unistd.h> |
31608 |
-+#include <stdint.h> |
31609 |
-+#include <errno.h> |
31610 |
-+#include <assert.h> |
31611 |
-+#include <limits.h> |
31612 |
-+#include <getopt.h> |
31613 |
-+#include <stdbool.h> |
31614 |
-+ |
31615 |
-+#include "kdbus-api.h" |
31616 |
-+#include "kdbus-util.h" |
31617 |
-+#include "kdbus-enum.h" |
31618 |
-+#include "kdbus-test.h" |
31619 |
-+ |
31620 |
-+struct test_name { |
31621 |
-+ const char *name; |
31622 |
-+ __u64 owner_id; |
31623 |
-+ __u64 flags; |
31624 |
-+}; |
31625 |
-+ |
31626 |
-+static bool conn_test_names(const struct kdbus_conn *conn, |
31627 |
-+ const struct test_name *tests, |
31628 |
-+ unsigned int n_tests) |
31629 |
-+{ |
31630 |
-+ struct kdbus_cmd_list cmd_list = {}; |
31631 |
-+ struct kdbus_info *name, *list; |
31632 |
-+ unsigned int i; |
31633 |
-+ int ret; |
31634 |
-+ |
31635 |
-+ cmd_list.size = sizeof(cmd_list); |
31636 |
-+ cmd_list.flags = KDBUS_LIST_NAMES | |
31637 |
-+ KDBUS_LIST_ACTIVATORS | |
31638 |
-+ KDBUS_LIST_QUEUED; |
31639 |
-+ |
31640 |
-+ ret = kdbus_cmd_list(conn->fd, &cmd_list); |
31641 |
-+ ASSERT_RETURN(ret == 0); |
31642 |
-+ |
31643 |
-+ list = (struct kdbus_info *)(conn->buf + cmd_list.offset); |
31644 |
-+ |
31645 |
-+ for (i = 0; i < n_tests; i++) { |
31646 |
-+ const struct test_name *t = tests + i; |
31647 |
-+ bool found = false; |
31648 |
-+ |
31649 |
-+ KDBUS_FOREACH(name, list, cmd_list.list_size) { |
31650 |
-+ struct kdbus_item *item; |
31651 |
-+ |
31652 |
-+ KDBUS_ITEM_FOREACH(item, name, items) { |
31653 |
-+ if (item->type != KDBUS_ITEM_OWNED_NAME || |
31654 |
-+ strcmp(item->name.name, t->name) != 0) |
31655 |
-+ continue; |
31656 |
-+ |
31657 |
-+ if (t->owner_id == name->id && |
31658 |
-+ t->flags == item->name.flags) { |
31659 |
-+ found = true; |
31660 |
-+ break; |
31661 |
-+ } |
31662 |
-+ } |
31663 |
-+ } |
31664 |
-+ |
31665 |
-+ if (!found) |
31666 |
-+ return false; |
31667 |
-+ } |
31668 |
-+ |
31669 |
-+ return true; |
31670 |
-+} |
31671 |
-+ |
31672 |
-+static bool conn_is_name_primary_owner(const struct kdbus_conn *conn, |
31673 |
-+ const char *needle) |
31674 |
-+{ |
31675 |
-+ struct test_name t = { |
31676 |
-+ .name = needle, |
31677 |
-+ .owner_id = conn->id, |
31678 |
-+ .flags = KDBUS_NAME_PRIMARY, |
31679 |
-+ }; |
31680 |
-+ |
31681 |
-+ return conn_test_names(conn, &t, 1); |
31682 |
-+} |
31683 |
-+ |
31684 |
-+int kdbus_test_name_basic(struct kdbus_test_env *env) |
31685 |
-+{ |
31686 |
-+ struct kdbus_conn *conn; |
31687 |
-+ char *name, *dot_name, *invalid_name, *wildcard_name; |
31688 |
-+ int ret; |
31689 |
-+ |
31690 |
-+ name = "foo.bla.blaz"; |
31691 |
-+ dot_name = ".bla.blaz"; |
31692 |
-+ invalid_name = "foo"; |
31693 |
-+ wildcard_name = "foo.bla.bl.*"; |
31694 |
-+ |
31695 |
-+ /* create a 2nd connection */ |
31696 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31697 |
-+ ASSERT_RETURN(conn != NULL); |
31698 |
-+ |
31699 |
-+ /* acquire name "foo.bar.xxx" name */ |
31700 |
-+ ret = kdbus_name_acquire(conn, "foo.bar.xxx", NULL); |
31701 |
-+ ASSERT_RETURN(ret == 0); |
31702 |
-+ |
31703 |
-+ /* Name is not valid, must fail */ |
31704 |
-+ ret = kdbus_name_acquire(env->conn, dot_name, NULL); |
31705 |
-+ ASSERT_RETURN(ret == -EINVAL); |
31706 |
-+ |
31707 |
-+ ret = kdbus_name_acquire(env->conn, invalid_name, NULL); |
31708 |
-+ ASSERT_RETURN(ret == -EINVAL); |
31709 |
-+ |
31710 |
-+ ret = kdbus_name_acquire(env->conn, wildcard_name, NULL); |
31711 |
-+ ASSERT_RETURN(ret == -EINVAL); |
31712 |
-+ |
31713 |
-+ /* check that we can acquire a name */ |
31714 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
31715 |
-+ ASSERT_RETURN(ret == 0); |
31716 |
-+ |
31717 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31718 |
-+ ASSERT_RETURN(ret == true); |
31719 |
-+ |
31720 |
-+ /* ... and release it again */ |
31721 |
-+ ret = kdbus_name_release(env->conn, name); |
31722 |
-+ ASSERT_RETURN(ret == 0); |
31723 |
-+ |
31724 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31725 |
-+ ASSERT_RETURN(ret == false); |
31726 |
-+ |
31727 |
-+ /* check that we can't release it again */ |
31728 |
-+ ret = kdbus_name_release(env->conn, name); |
31729 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31730 |
-+ |
31731 |
-+ /* check that we can't release a name that we don't own */ |
31732 |
-+ ret = kdbus_name_release(env->conn, "foo.bar.xxx"); |
31733 |
-+ ASSERT_RETURN(ret == -EADDRINUSE); |
31734 |
-+ |
31735 |
-+ /* Name is not valid, must fail */ |
31736 |
-+ ret = kdbus_name_release(env->conn, dot_name); |
31737 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31738 |
-+ |
31739 |
-+ ret = kdbus_name_release(env->conn, invalid_name); |
31740 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31741 |
-+ |
31742 |
-+ ret = kdbus_name_release(env->conn, wildcard_name); |
31743 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31744 |
-+ |
31745 |
-+ kdbus_conn_free(conn); |
31746 |
-+ |
31747 |
-+ return TEST_OK; |
31748 |
-+} |
31749 |
-+ |
31750 |
-+int kdbus_test_name_conflict(struct kdbus_test_env *env) |
31751 |
-+{ |
31752 |
-+ struct kdbus_conn *conn; |
31753 |
-+ char *name; |
31754 |
-+ int ret; |
31755 |
-+ |
31756 |
-+ name = "foo.bla.blaz"; |
31757 |
-+ |
31758 |
-+ /* create a 2nd connection */ |
31759 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31760 |
-+ ASSERT_RETURN(conn != NULL); |
31761 |
-+ |
31762 |
-+ /* allow the new connection to own the same name */ |
31763 |
-+ /* acquire name from the 1st connection */ |
31764 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
31765 |
-+ ASSERT_RETURN(ret == 0); |
31766 |
-+ |
31767 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31768 |
-+ ASSERT_RETURN(ret == true); |
31769 |
-+ |
31770 |
-+ /* check that we also can't acquire it again from the 2nd connection */ |
31771 |
-+ ret = kdbus_name_acquire(conn, name, NULL); |
31772 |
-+ ASSERT_RETURN(ret == -EEXIST); |
31773 |
-+ |
31774 |
-+ kdbus_conn_free(conn); |
31775 |
-+ |
31776 |
-+ return TEST_OK; |
31777 |
-+} |
31778 |
-+ |
31779 |
-+int kdbus_test_name_queue(struct kdbus_test_env *env) |
31780 |
-+{ |
31781 |
-+ struct kdbus_conn *conn; |
31782 |
-+ struct test_name t[2]; |
31783 |
-+ const char *name; |
31784 |
-+ uint64_t flags; |
31785 |
-+ int ret; |
31786 |
-+ |
31787 |
-+ name = "foo.bla.blaz"; |
31788 |
-+ |
31789 |
-+ flags = 0; |
31790 |
-+ |
31791 |
-+ /* create a 2nd connection */ |
31792 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31793 |
-+ ASSERT_RETURN(conn != NULL); |
31794 |
-+ |
31795 |
-+ /* allow the new connection to own the same name */ |
31796 |
-+ /* acquire name from the 1st connection */ |
31797 |
-+ ret = kdbus_name_acquire(env->conn, name, &flags); |
31798 |
-+ ASSERT_RETURN(ret == 0); |
31799 |
-+ |
31800 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31801 |
-+ ASSERT_RETURN(ret == true); |
31802 |
-+ |
31803 |
-+ /* queue the 2nd connection as waiting owner */ |
31804 |
-+ flags = KDBUS_NAME_QUEUE; |
31805 |
-+ ret = kdbus_name_acquire(conn, name, &flags); |
31806 |
-+ ASSERT_RETURN(ret == 0); |
31807 |
-+ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); |
31808 |
-+ |
31809 |
-+ t[0].name = name; |
31810 |
-+ t[0].owner_id = env->conn->id; |
31811 |
-+ t[0].flags = KDBUS_NAME_PRIMARY; |
31812 |
-+ t[1].name = name; |
31813 |
-+ t[1].owner_id = conn->id; |
31814 |
-+ t[1].flags = KDBUS_NAME_QUEUE | KDBUS_NAME_IN_QUEUE; |
31815 |
-+ ret = conn_test_names(conn, t, 2); |
31816 |
-+ ASSERT_RETURN(ret == true); |
31817 |
-+ |
31818 |
-+ /* release name from 1st connection */ |
31819 |
-+ ret = kdbus_name_release(env->conn, name); |
31820 |
-+ ASSERT_RETURN(ret == 0); |
31821 |
-+ |
31822 |
-+ /* now the name should be owned by the 2nd connection */ |
31823 |
-+ t[0].name = name; |
31824 |
-+ t[0].owner_id = conn->id; |
31825 |
-+ t[0].flags = KDBUS_NAME_PRIMARY | KDBUS_NAME_QUEUE; |
31826 |
-+ ret = conn_test_names(conn, t, 1); |
31827 |
-+ ASSERT_RETURN(ret == true); |
31828 |
-+ |
31829 |
-+ kdbus_conn_free(conn); |
31830 |
-+ |
31831 |
-+ return TEST_OK; |
31832 |
-+} |
31833 |
-+ |
31834 |
-+int kdbus_test_name_takeover(struct kdbus_test_env *env) |
31835 |
-+{ |
31836 |
-+ struct kdbus_conn *conn; |
31837 |
-+ struct test_name t; |
31838 |
-+ const char *name; |
31839 |
-+ uint64_t flags; |
31840 |
-+ int ret; |
31841 |
-+ |
31842 |
-+ name = "foo.bla.blaz"; |
31843 |
-+ |
31844 |
-+ flags = KDBUS_NAME_ALLOW_REPLACEMENT; |
31845 |
-+ |
31846 |
-+ /* create a 2nd connection */ |
31847 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31848 |
-+ ASSERT_RETURN(conn != NULL); |
31849 |
-+ |
31850 |
-+ /* acquire name for 1st connection */ |
31851 |
-+ ret = kdbus_name_acquire(env->conn, name, &flags); |
31852 |
-+ ASSERT_RETURN(ret == 0); |
31853 |
-+ |
31854 |
-+ t.name = name; |
31855 |
-+ t.owner_id = env->conn->id; |
31856 |
-+ t.flags = KDBUS_NAME_ALLOW_REPLACEMENT | KDBUS_NAME_PRIMARY; |
31857 |
-+ ret = conn_test_names(conn, &t, 1); |
31858 |
-+ ASSERT_RETURN(ret == true); |
31859 |
-+ |
31860 |
-+ /* now steal name with 2nd connection */ |
31861 |
-+ flags = KDBUS_NAME_REPLACE_EXISTING; |
31862 |
-+ ret = kdbus_name_acquire(conn, name, &flags); |
31863 |
-+ ASSERT_RETURN(ret == 0); |
31864 |
-+ ASSERT_RETURN(flags & KDBUS_NAME_ACQUIRED); |
31865 |
-+ |
31866 |
-+ ret = conn_is_name_primary_owner(conn, name); |
31867 |
-+ ASSERT_RETURN(ret == true); |
31868 |
-+ |
31869 |
-+ kdbus_conn_free(conn); |
31870 |
-+ |
31871 |
-+ return TEST_OK; |
31872 |
-+} |
31873 |
-diff --git a/tools/testing/selftests/kdbus/test-policy-ns.c b/tools/testing/selftests/kdbus/test-policy-ns.c |
31874 |
-new file mode 100644 |
31875 |
-index 0000000..3437012 |
31876 |
---- /dev/null |
31877 |
-+++ b/tools/testing/selftests/kdbus/test-policy-ns.c |
31878 |
-@@ -0,0 +1,632 @@ |
31879 |
-+/* |
31880 |
-+ * Test metadata and policies in new namespaces. Even if our tests |
31881 |
-+ * can run in a namespaced setup, this test is necessary so we can |
31882 |
-+ * inspect policies on the same kdbusfs but between multiple |
31883 |
-+ * namespaces. |
31884 |
-+ * |
31885 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
31886 |
-+ * |
31887 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
31888 |
-+ * the terms of the GNU Lesser General Public License as published by the |
31889 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
31890 |
-+ * your option) any later version. |
31891 |
-+ */ |
31892 |
-+ |
31893 |
-+#include <stdio.h> |
31894 |
-+#include <string.h> |
31895 |
-+#include <fcntl.h> |
31896 |
-+#include <pthread.h> |
31897 |
-+#include <sched.h> |
31898 |
-+#include <stdlib.h> |
31899 |
-+#include <stddef.h> |
31900 |
-+#include <stdint.h> |
31901 |
-+#include <stdbool.h> |
31902 |
-+#include <unistd.h> |
31903 |
-+#include <errno.h> |
31904 |
-+#include <signal.h> |
31905 |
-+#include <sys/wait.h> |
31906 |
-+#include <sys/prctl.h> |
31907 |
-+#include <sys/eventfd.h> |
31908 |
-+#include <sys/syscall.h> |
31909 |
-+#include <sys/capability.h> |
31910 |
-+#include <linux/sched.h> |
31911 |
-+ |
31912 |
-+#include "kdbus-test.h" |
31913 |
-+#include "kdbus-util.h" |
31914 |
-+#include "kdbus-enum.h" |
31915 |
-+ |
31916 |
-+#define MAX_CONN 64 |
31917 |
-+#define POLICY_NAME "foo.test.policy-test" |
31918 |
-+ |
31919 |
-+#define KDBUS_CONN_MAX_MSGS_PER_USER 16 |
31920 |
-+ |
31921 |
-+/** |
31922 |
-+ * Note: this test can be used to inspect policy_db->talk_access_hash |
31923 |
-+ * |
31924 |
-+ * The purpose of these tests: |
31925 |
-+ * 1) Check KDBUS_POLICY_TALK |
31926 |
-+ * 2) Check the cache state: kdbus_policy_db->talk_access_hash |
31927 |
-+ * Should be extended |
31928 |
-+ */ |
31929 |
-+ |
31930 |
-+/** |
31931 |
-+ * Check a list of connections against conn_db[0] |
31932 |
-+ * conn_db[0] will own the name "foo.test.policy-test" and the |
31933 |
-+ * policy holder connection for this name will update the policy |
31934 |
-+ * entries, so different use cases can be tested. |
31935 |
-+ */ |
31936 |
-+static struct kdbus_conn **conn_db; |
31937 |
-+ |
31938 |
-+static void *kdbus_recv_echo(void *ptr) |
31939 |
-+{ |
31940 |
-+ int ret; |
31941 |
-+ struct kdbus_conn *conn = ptr; |
31942 |
-+ |
31943 |
-+ ret = kdbus_msg_recv_poll(conn, 200, NULL, NULL); |
31944 |
-+ |
31945 |
-+ return (void *)(long)ret; |
31946 |
-+} |
31947 |
-+ |
31948 |
-+/* Trigger kdbus_policy_set() */ |
31949 |
-+static int kdbus_set_policy_talk(struct kdbus_conn *conn, |
31950 |
-+ const char *name, |
31951 |
-+ uid_t id, unsigned int type) |
31952 |
-+{ |
31953 |
-+ int ret; |
31954 |
-+ struct kdbus_policy_access access = { |
31955 |
-+ .type = type, |
31956 |
-+ .id = id, |
31957 |
-+ .access = KDBUS_POLICY_TALK, |
31958 |
-+ }; |
31959 |
-+ |
31960 |
-+ ret = kdbus_conn_update_policy(conn, name, &access, 1); |
31961 |
-+ ASSERT_RETURN(ret == 0); |
31962 |
-+ |
31963 |
-+ return TEST_OK; |
31964 |
-+} |
31965 |
-+ |
31966 |
-+/* return TEST_OK or TEST_ERR on failure */ |
31967 |
-+static int kdbus_register_same_activator(char *bus, const char *name, |
31968 |
-+ struct kdbus_conn **c) |
31969 |
-+{ |
31970 |
-+ int ret; |
31971 |
-+ struct kdbus_conn *activator; |
31972 |
-+ |
31973 |
-+ activator = kdbus_hello_activator(bus, name, NULL, 0); |
31974 |
-+ if (activator) { |
31975 |
-+ *c = activator; |
31976 |
-+ fprintf(stderr, "--- error was able to register name twice '%s'.\n", |
31977 |
-+ name); |
31978 |
-+ return TEST_ERR; |
31979 |
-+ } |
31980 |
-+ |
31981 |
-+ ret = -errno; |
31982 |
-+ /* -EEXIST means test succeeded */ |
31983 |
-+ if (ret == -EEXIST) |
31984 |
-+ return TEST_OK; |
31985 |
-+ |
31986 |
-+ return TEST_ERR; |
31987 |
-+} |
31988 |
-+ |
31989 |
-+/* return TEST_OK or TEST_ERR on failure */ |
31990 |
-+static int kdbus_register_policy_holder(char *bus, const char *name, |
31991 |
-+ struct kdbus_conn **conn) |
31992 |
-+{ |
31993 |
-+ struct kdbus_conn *c; |
31994 |
-+ struct kdbus_policy_access access[2]; |
31995 |
-+ |
31996 |
-+ access[0].type = KDBUS_POLICY_ACCESS_USER; |
31997 |
-+ access[0].access = KDBUS_POLICY_OWN; |
31998 |
-+ access[0].id = geteuid(); |
31999 |
-+ |
32000 |
-+ access[1].type = KDBUS_POLICY_ACCESS_WORLD; |
32001 |
-+ access[1].access = KDBUS_POLICY_TALK; |
32002 |
-+ access[1].id = geteuid(); |
32003 |
-+ |
32004 |
-+ c = kdbus_hello_registrar(bus, name, access, 2, |
32005 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
32006 |
-+ ASSERT_RETURN(c); |
32007 |
-+ |
32008 |
-+ *conn = c; |
32009 |
-+ |
32010 |
-+ return TEST_OK; |
32011 |
-+} |
32012 |
-+ |
32013 |
-+/** |
32014 |
-+ * Create new threads for receiving from multiple senders, |
32015 |
-+ * The 'conn_db' will be populated by newly created connections. |
32016 |
-+ * Caller should free all allocated connections. |
32017 |
-+ * |
32018 |
-+ * return 0 on success, negative errno on failure. |
32019 |
-+ */ |
32020 |
-+static int kdbus_recv_in_threads(const char *bus, const char *name, |
32021 |
-+ struct kdbus_conn **conn_db) |
32022 |
-+{ |
32023 |
-+ int ret; |
32024 |
-+ bool pool_full = false; |
32025 |
-+ unsigned int sent_packets = 0; |
32026 |
-+ unsigned int lost_packets = 0; |
32027 |
-+ unsigned int i, tid; |
32028 |
-+ unsigned long dst_id; |
32029 |
-+ unsigned long cookie = 1; |
32030 |
-+ unsigned int thread_nr = MAX_CONN - 1; |
32031 |
-+ pthread_t thread_id[MAX_CONN - 1] = {'\0'}; |
32032 |
-+ |
32033 |
-+ dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id; |
32034 |
-+ |
32035 |
-+ for (tid = 0, i = 1; tid < thread_nr; tid++, i++) { |
32036 |
-+ ret = pthread_create(&thread_id[tid], NULL, |
32037 |
-+ kdbus_recv_echo, (void *)conn_db[0]); |
32038 |
-+ if (ret < 0) { |
32039 |
-+ ret = -errno; |
32040 |
-+ kdbus_printf("error pthread_create: %d (%m)\n", |
32041 |
-+ ret); |
32042 |
-+ break; |
32043 |
-+ } |
32044 |
-+ |
32045 |
-+ /* just free before re-using */ |
32046 |
-+ kdbus_conn_free(conn_db[i]); |
32047 |
-+ conn_db[i] = NULL; |
32048 |
-+ |
32049 |
-+ /* We need to create connections here */ |
32050 |
-+ conn_db[i] = kdbus_hello(bus, 0, NULL, 0); |
32051 |
-+ if (!conn_db[i]) { |
32052 |
-+ ret = -errno; |
32053 |
-+ break; |
32054 |
-+ } |
32055 |
-+ |
32056 |
-+ ret = kdbus_add_match_empty(conn_db[i]); |
32057 |
-+ if (ret < 0) |
32058 |
-+ break; |
32059 |
-+ |
32060 |
-+ ret = kdbus_msg_send(conn_db[i], name, cookie++, |
32061 |
-+ 0, 0, 0, dst_id); |
32062 |
-+ if (ret < 0) { |
32063 |
-+ /* |
32064 |
-+ * Receivers are not reading their messages, |
32065 |
-+ * not scheduled ?! |
32066 |
-+ * |
32067 |
-+ * So set the pool full here, perhaps the |
32068 |
-+ * connection pool or queue was full, later |
32069 |
-+ * recheck receivers errors |
32070 |
-+ */ |
32071 |
-+ if (ret == -ENOBUFS || ret == -EXFULL) |
32072 |
-+ pool_full = true; |
32073 |
-+ break; |
32074 |
-+ } |
32075 |
-+ |
32076 |
-+ sent_packets++; |
32077 |
-+ } |
32078 |
-+ |
32079 |
-+ for (tid = 0; tid < thread_nr; tid++) { |
32080 |
-+ int thread_ret = 0; |
32081 |
-+ |
32082 |
-+ if (thread_id[tid]) { |
32083 |
-+ pthread_join(thread_id[tid], (void *)&thread_ret); |
32084 |
-+ if (thread_ret < 0) { |
32085 |
-+ /* Update only if send did not fail */ |
32086 |
-+ if (ret == 0) |
32087 |
-+ ret = thread_ret; |
32088 |
-+ |
32089 |
-+ lost_packets++; |
32090 |
-+ } |
32091 |
-+ } |
32092 |
-+ } |
32093 |
-+ |
32094 |
-+ /* |
32095 |
-+ * When sending if we did fail with -ENOBUFS or -EXFULL |
32096 |
-+ * then we should have set lost_packet and we should at |
32097 |
-+ * least have sent_packets set to KDBUS_CONN_MAX_MSGS_PER_USER |
32098 |
-+ */ |
32099 |
-+ if (pool_full) { |
32100 |
-+ ASSERT_RETURN(lost_packets > 0); |
32101 |
-+ |
32102 |
-+ /* |
32103 |
-+ * We should at least send KDBUS_CONN_MAX_MSGS_PER_USER |
32104 |
-+ * |
32105 |
-+ * For every send operation we create a thread to |
32106 |
-+ * recv the packet, so we keep the queue clean |
32107 |
-+ */ |
32108 |
-+ ASSERT_RETURN(sent_packets >= KDBUS_CONN_MAX_MSGS_PER_USER); |
32109 |
-+ |
32110 |
-+ /* |
32111 |
-+ * Set ret to zero since we only failed due to |
32112 |
-+ * the receiving threads that have not been |
32113 |
-+ * scheduled |
32114 |
-+ */ |
32115 |
-+ ret = 0; |
32116 |
-+ } |
32117 |
-+ |
32118 |
-+ return ret; |
32119 |
-+} |
32120 |
-+ |
32121 |
-+/* Return: TEST_OK or TEST_ERR on failure */ |
32122 |
-+static int kdbus_normal_test(const char *bus, const char *name, |
32123 |
-+ struct kdbus_conn **conn_db) |
32124 |
-+{ |
32125 |
-+ int ret; |
32126 |
-+ |
32127 |
-+ ret = kdbus_recv_in_threads(bus, name, conn_db); |
32128 |
-+ ASSERT_RETURN(ret >= 0); |
32129 |
-+ |
32130 |
-+ return TEST_OK; |
32131 |
-+} |
32132 |
-+ |
32133 |
-+static int kdbus_fork_test_by_id(const char *bus, |
32134 |
-+ struct kdbus_conn **conn_db, |
32135 |
-+ int parent_status, int child_status) |
32136 |
-+{ |
32137 |
-+ int ret; |
32138 |
-+ pid_t pid; |
32139 |
-+ uint64_t cookie = 0x9876ecba; |
32140 |
-+ struct kdbus_msg *msg = NULL; |
32141 |
-+ uint64_t offset = 0; |
32142 |
-+ int status = 0; |
32143 |
-+ |
32144 |
-+ /* |
32145 |
-+ * If the child_status is not EXIT_SUCCESS, then we expect |
32146 |
-+ * that sending from the child will fail, thus receiving |
32147 |
-+ * from parent must error with -ETIMEDOUT, and vice versa. |
32148 |
-+ */ |
32149 |
-+ bool parent_timedout = !!child_status; |
32150 |
-+ bool child_timedout = !!parent_status; |
32151 |
-+ |
32152 |
-+ pid = fork(); |
32153 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
32154 |
-+ |
32155 |
-+ if (pid == 0) { |
32156 |
-+ struct kdbus_conn *conn_src; |
32157 |
-+ |
32158 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32159 |
-+ ASSERT_EXIT(ret == 0); |
32160 |
-+ |
32161 |
-+ ret = drop_privileges(65534, 65534); |
32162 |
-+ ASSERT_EXIT(ret == 0); |
32163 |
-+ |
32164 |
-+ conn_src = kdbus_hello(bus, 0, NULL, 0); |
32165 |
-+ ASSERT_EXIT(conn_src); |
32166 |
-+ |
32167 |
-+ ret = kdbus_add_match_empty(conn_src); |
32168 |
-+ ASSERT_EXIT(ret == 0); |
32169 |
-+ |
32170 |
-+ /* |
32171 |
-+ * child_status is always checked against send |
32172 |
-+ * operations, in case it fails always return |
32173 |
-+ * EXIT_FAILURE. |
32174 |
-+ */ |
32175 |
-+ ret = kdbus_msg_send(conn_src, NULL, cookie, |
32176 |
-+ 0, 0, 0, conn_db[0]->id); |
32177 |
-+ ASSERT_EXIT(ret == child_status); |
32178 |
-+ |
32179 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); |
32180 |
-+ |
32181 |
-+ kdbus_conn_free(conn_src); |
32182 |
-+ |
32183 |
-+ /* |
32184 |
-+ * Child kdbus_msg_recv_poll() should timeout since |
32185 |
-+ * the parent_status was set to a non EXIT_SUCCESS |
32186 |
-+ * value. |
32187 |
-+ */ |
32188 |
-+ if (child_timedout) |
32189 |
-+ _exit(ret == -ETIMEDOUT ? EXIT_SUCCESS : EXIT_FAILURE); |
32190 |
-+ |
32191 |
-+ _exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); |
32192 |
-+ } |
32193 |
-+ |
32194 |
-+ ret = kdbus_msg_recv_poll(conn_db[0], 100, &msg, &offset); |
32195 |
-+ /* |
32196 |
-+ * If parent_timedout is set then this should fail with |
32197 |
-+ * -ETIMEDOUT since the child_status was set to a non |
32198 |
-+ * EXIT_SUCCESS value. Otherwise, assume |
32199 |
-+ * that kdbus_msg_recv_poll() has succeeded. |
32200 |
-+ */ |
32201 |
-+ if (parent_timedout) { |
32202 |
-+ ASSERT_RETURN_VAL(ret == -ETIMEDOUT, TEST_ERR); |
32203 |
-+ |
32204 |
-+ /* timedout no need to continue, we don't have the |
32205 |
-+ * child connection ID, so just terminate. */ |
32206 |
-+ goto out; |
32207 |
-+ } else { |
32208 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32209 |
-+ } |
32210 |
-+ |
32211 |
-+ ret = kdbus_msg_send(conn_db[0], NULL, ++cookie, |
32212 |
-+ 0, 0, 0, msg->src_id); |
32213 |
-+ /* |
32214 |
-+ * parent_status is checked against send operations, |
32215 |
-+ * on failures always return TEST_ERR. |
32216 |
-+ */ |
32217 |
-+ ASSERT_RETURN_VAL(ret == parent_status, TEST_ERR); |
32218 |
-+ |
32219 |
-+ kdbus_msg_free(msg); |
32220 |
-+ kdbus_free(conn_db[0], offset); |
32221 |
-+ |
32222 |
-+out: |
32223 |
-+ ret = waitpid(pid, &status, 0); |
32224 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
32225 |
-+ |
32226 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32227 |
-+} |
32228 |
-+ |
32229 |
-+/* |
32230 |
-+ * Return: TEST_OK, TEST_ERR or TEST_SKIP |
32231 |
-+ * we return TEST_OK only if the children return with the expected |
32232 |
-+ * 'expected_status' that is specified as an argument. |
32233 |
-+ */ |
32234 |
-+static int kdbus_fork_test(const char *bus, const char *name, |
32235 |
-+ struct kdbus_conn **conn_db, int expected_status) |
32236 |
-+{ |
32237 |
-+ pid_t pid; |
32238 |
-+ int ret = 0; |
32239 |
-+ int status = 0; |
32240 |
-+ |
32241 |
-+ pid = fork(); |
32242 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
32243 |
-+ |
32244 |
-+ if (pid == 0) { |
32245 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32246 |
-+ ASSERT_EXIT(ret == 0); |
32247 |
-+ |
32248 |
-+ ret = drop_privileges(65534, 65534); |
32249 |
-+ ASSERT_EXIT(ret == 0); |
32250 |
-+ |
32251 |
-+ ret = kdbus_recv_in_threads(bus, name, conn_db); |
32252 |
-+ _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE); |
32253 |
-+ } |
32254 |
-+ |
32255 |
-+ ret = waitpid(pid, &status, 0); |
32256 |
-+ ASSERT_RETURN(ret >= 0); |
32257 |
-+ |
32258 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32259 |
-+} |
32260 |
-+ |
32261 |
-+/* Return EXIT_SUCCESS, EXIT_FAILURE or negative errno */ |
32262 |
-+static int __kdbus_clone_userns_test(const char *bus, |
32263 |
-+ const char *name, |
32264 |
-+ struct kdbus_conn **conn_db, |
32265 |
-+ int expected_status) |
32266 |
-+{ |
32267 |
-+ int efd; |
32268 |
-+ pid_t pid; |
32269 |
-+ int ret = 0; |
32270 |
-+ unsigned int uid = 65534; |
32271 |
-+ int status; |
32272 |
-+ |
32273 |
-+ ret = drop_privileges(uid, uid); |
32274 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32275 |
-+ |
32276 |
-+ /* |
32277 |
-+ * Since we just dropped privileges, the dumpable flag was just |
32278 |
-+ * cleared which makes the /proc/$clone_child/uid_map to be |
32279 |
-+ * owned by root, hence any userns uid mapping will fail with |
32280 |
-+ * -EPERM since the mapping will be done by uid 65534. |
32281 |
-+ * |
32282 |
-+ * To avoid this set the dumpable flag again which makes procfs |
32283 |
-+ * update the /proc/$clone_child/ inodes owner to 65534. |
32284 |
-+ * |
32285 |
-+ * Using this we will be able write to /proc/$clone_child/uid_map |
32286 |
-+ * as uid 65534 and map the uid 65534 to 0 inside the user |
32287 |
-+ * namespace. |
32288 |
-+ */ |
32289 |
-+ ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER); |
32290 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32291 |
-+ |
32292 |
-+ /* sync parent/child */ |
32293 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
32294 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
32295 |
-+ |
32296 |
-+ pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWUSER, NULL); |
32297 |
-+ if (pid < 0) { |
32298 |
-+ ret = -errno; |
32299 |
-+ kdbus_printf("error clone: %d (%m)\n", ret); |
32300 |
-+ /* |
32301 |
-+ * Normal user not allowed to create userns, |
32302 |
-+ * so nothing to worry about ? |
32303 |
-+ */ |
32304 |
-+ if (ret == -EPERM) { |
32305 |
-+ kdbus_printf("-- CLONE_NEWUSER TEST Failed for uid: %u\n" |
32306 |
-+ "-- Make sure that your kernel do not allow " |
32307 |
-+ "CLONE_NEWUSER for unprivileged users\n" |
32308 |
-+ "-- Upstream Commit: " |
32309 |
-+ "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5eaf563e\n", |
32310 |
-+ uid); |
32311 |
-+ ret = 0; |
32312 |
-+ } |
32313 |
-+ |
32314 |
-+ return ret; |
32315 |
-+ } |
32316 |
-+ |
32317 |
-+ if (pid == 0) { |
32318 |
-+ struct kdbus_conn *conn_src; |
32319 |
-+ eventfd_t event_status = 0; |
32320 |
-+ |
32321 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32322 |
-+ ASSERT_EXIT(ret == 0); |
32323 |
-+ |
32324 |
-+ ret = eventfd_read(efd, &event_status); |
32325 |
-+ ASSERT_EXIT(ret >= 0 && event_status == 1); |
32326 |
-+ |
32327 |
-+ /* ping connection from the new user namespace */ |
32328 |
-+ conn_src = kdbus_hello(bus, 0, NULL, 0); |
32329 |
-+ ASSERT_EXIT(conn_src); |
32330 |
-+ |
32331 |
-+ ret = kdbus_add_match_empty(conn_src); |
32332 |
-+ ASSERT_EXIT(ret == 0); |
32333 |
-+ |
32334 |
-+ ret = kdbus_msg_send(conn_src, name, 0xabcd1234, |
32335 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
32336 |
-+ kdbus_conn_free(conn_src); |
32337 |
-+ |
32338 |
-+ _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE); |
32339 |
-+ } |
32340 |
-+ |
32341 |
-+ ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"); |
32342 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32343 |
-+ |
32344 |
-+ /* Tell child we are ready */ |
32345 |
-+ ret = eventfd_write(efd, 1); |
32346 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32347 |
-+ |
32348 |
-+ ret = waitpid(pid, &status, 0); |
32349 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
32350 |
-+ |
32351 |
-+ close(efd); |
32352 |
-+ |
32353 |
-+ return status == EXIT_SUCCESS ? TEST_OK : TEST_ERR; |
32354 |
-+} |
32355 |
-+ |
32356 |
-+static int kdbus_clone_userns_test(const char *bus, |
32357 |
-+ const char *name, |
32358 |
-+ struct kdbus_conn **conn_db, |
32359 |
-+ int expected_status) |
32360 |
-+{ |
32361 |
-+ pid_t pid; |
32362 |
-+ int ret = 0; |
32363 |
-+ int status; |
32364 |
-+ |
32365 |
-+ pid = fork(); |
32366 |
-+ ASSERT_RETURN_VAL(pid >= 0, -errno); |
32367 |
-+ |
32368 |
-+ if (pid == 0) { |
32369 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32370 |
-+ if (ret < 0) |
32371 |
-+ _exit(EXIT_FAILURE); |
32372 |
-+ |
32373 |
-+ ret = __kdbus_clone_userns_test(bus, name, conn_db, |
32374 |
-+ expected_status); |
32375 |
-+ _exit(ret); |
32376 |
-+ } |
32377 |
-+ |
32378 |
-+ /* |
32379 |
-+ * Receive in the original (root privileged) user namespace, |
32380 |
-+ * must fail with -ETIMEDOUT. |
32381 |
-+ */ |
32382 |
-+ ret = kdbus_msg_recv_poll(conn_db[0], 100, NULL, NULL); |
32383 |
-+ ASSERT_RETURN_VAL(ret == -ETIMEDOUT, ret); |
32384 |
-+ |
32385 |
-+ ret = waitpid(pid, &status, 0); |
32386 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
32387 |
-+ |
32388 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32389 |
-+} |
32390 |
-+ |
32391 |
-+int kdbus_test_policy_ns(struct kdbus_test_env *env) |
32392 |
-+{ |
32393 |
-+ int i; |
32394 |
-+ int ret; |
32395 |
-+ struct kdbus_conn *activator = NULL; |
32396 |
-+ struct kdbus_conn *policy_holder = NULL; |
32397 |
-+ char *bus = env->buspath; |
32398 |
-+ |
32399 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
32400 |
-+ ASSERT_RETURN(ret >= 0); |
32401 |
-+ |
32402 |
-+ /* no enough privileges, SKIP test */ |
32403 |
-+ if (!ret) |
32404 |
-+ return TEST_SKIP; |
32405 |
-+ |
32406 |
-+ /* we require user-namespaces */ |
32407 |
-+ if (access("/proc/self/uid_map", F_OK) != 0) |
32408 |
-+ return TEST_SKIP; |
32409 |
-+ |
32410 |
-+ /* uids/gids must be mapped */ |
32411 |
-+ if (!all_uids_gids_are_mapped()) |
32412 |
-+ return TEST_SKIP; |
32413 |
-+ |
32414 |
-+ conn_db = calloc(MAX_CONN, sizeof(struct kdbus_conn *)); |
32415 |
-+ ASSERT_RETURN(conn_db); |
32416 |
-+ |
32417 |
-+ memset(conn_db, 0, MAX_CONN * sizeof(struct kdbus_conn *)); |
32418 |
-+ |
32419 |
-+ conn_db[0] = kdbus_hello(bus, 0, NULL, 0); |
32420 |
-+ ASSERT_RETURN(conn_db[0]); |
32421 |
-+ |
32422 |
-+ ret = kdbus_add_match_empty(conn_db[0]); |
32423 |
-+ ASSERT_RETURN(ret == 0); |
32424 |
-+ |
32425 |
-+ ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM); |
32426 |
-+ ASSERT_EXIT(ret == 0); |
32427 |
-+ |
32428 |
-+ ret = kdbus_register_policy_holder(bus, POLICY_NAME, |
32429 |
-+ &policy_holder); |
32430 |
-+ ASSERT_RETURN(ret == 0); |
32431 |
-+ |
32432 |
-+ /* Try to register the same name with an activator */ |
32433 |
-+ ret = kdbus_register_same_activator(bus, POLICY_NAME, |
32434 |
-+ &activator); |
32435 |
-+ ASSERT_RETURN(ret == 0); |
32436 |
-+ |
32437 |
-+ /* Acquire POLICY_NAME */ |
32438 |
-+ ret = kdbus_name_acquire(conn_db[0], POLICY_NAME, NULL); |
32439 |
-+ ASSERT_RETURN(ret == 0); |
32440 |
-+ |
32441 |
-+ ret = kdbus_normal_test(bus, POLICY_NAME, conn_db); |
32442 |
-+ ASSERT_RETURN(ret == 0); |
32443 |
-+ |
32444 |
-+ ret = kdbus_list(conn_db[0], KDBUS_LIST_NAMES | |
32445 |
-+ KDBUS_LIST_UNIQUE | |
32446 |
-+ KDBUS_LIST_ACTIVATORS | |
32447 |
-+ KDBUS_LIST_QUEUED); |
32448 |
-+ ASSERT_RETURN(ret == 0); |
32449 |
-+ |
32450 |
-+ ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, EXIT_SUCCESS); |
32451 |
-+ ASSERT_RETURN(ret == 0); |
32452 |
-+ |
32453 |
-+ /* |
32454 |
-+ * children connections are able to talk to conn_db[0] since |
32455 |
-+ * current POLICY_NAME TALK type is KDBUS_POLICY_ACCESS_WORLD, |
32456 |
-+ * so expect EXIT_SUCCESS when sending from child. However, |
32457 |
-+ * since the child's connection does not own any well-known |
32458 |
-+ * name, The parent connection conn_db[0] should fail with |
32459 |
-+ * -EPERM but since it is a privileged bus user the TALK is |
32460 |
-+ * allowed. |
32461 |
-+ */ |
32462 |
-+ ret = kdbus_fork_test_by_id(bus, conn_db, |
32463 |
-+ EXIT_SUCCESS, EXIT_SUCCESS); |
32464 |
-+ ASSERT_EXIT(ret == 0); |
32465 |
-+ |
32466 |
-+ /* |
32467 |
-+ * Connections that can talk are perhaps being destroyed now. |
32468 |
-+ * Restrict the policy and purge cache entries where the |
32469 |
-+ * conn_db[0] is the destination. |
32470 |
-+ * |
32471 |
-+ * Now only connections with uid == 0 are allowed to talk. |
32472 |
-+ */ |
32473 |
-+ ret = kdbus_set_policy_talk(policy_holder, POLICY_NAME, |
32474 |
-+ geteuid(), KDBUS_POLICY_ACCESS_USER); |
32475 |
-+ ASSERT_RETURN(ret == 0); |
32476 |
-+ |
32477 |
-+ /* |
32478 |
-+ * Testing connections (FORK+DROP) again: |
32479 |
-+ * After setting the policy re-check connections |
32480 |
-+ * we expect the children to fail with -EPERM |
32481 |
-+ */ |
32482 |
-+ ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, -EPERM); |
32483 |
-+ ASSERT_RETURN(ret == 0); |
32484 |
-+ |
32485 |
-+ /* |
32486 |
-+ * Now expect that both parent and child to fail. |
32487 |
-+ * |
32488 |
-+ * Child should fail with -EPERM since we just restricted |
32489 |
-+ * the POLICY_NAME TALK to uid 0 and its uid is 65534. |
32490 |
-+ * |
32491 |
-+ * Since the parent's connection will timeout when receiving |
32492 |
-+ * from the child, we never continue. FWIW just put -EPERM. |
32493 |
-+ */ |
32494 |
-+ ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM); |
32495 |
-+ ASSERT_EXIT(ret == 0); |
32496 |
-+ |
32497 |
-+ /* Check if the name can be reached in a new userns */ |
32498 |
-+ ret = kdbus_clone_userns_test(bus, POLICY_NAME, conn_db, -EPERM); |
32499 |
-+ ASSERT_RETURN(ret == 0); |
32500 |
-+ |
32501 |
-+ for (i = 0; i < MAX_CONN; i++) |
32502 |
-+ kdbus_conn_free(conn_db[i]); |
32503 |
-+ |
32504 |
-+ kdbus_conn_free(activator); |
32505 |
-+ kdbus_conn_free(policy_holder); |
32506 |
-+ |
32507 |
-+ free(conn_db); |
32508 |
-+ |
32509 |
-+ return ret; |
32510 |
-+} |
32511 |
-diff --git a/tools/testing/selftests/kdbus/test-policy-priv.c b/tools/testing/selftests/kdbus/test-policy-priv.c |
32512 |
-new file mode 100644 |
32513 |
-index 0000000..0208638 |
32514 |
---- /dev/null |
32515 |
-+++ b/tools/testing/selftests/kdbus/test-policy-priv.c |
32516 |
-@@ -0,0 +1,1285 @@ |
32517 |
-+#include <errno.h> |
32518 |
-+#include <stdio.h> |
32519 |
-+#include <string.h> |
32520 |
-+#include <fcntl.h> |
32521 |
-+#include <stdlib.h> |
32522 |
-+#include <stdint.h> |
32523 |
-+#include <stdbool.h> |
32524 |
-+#include <unistd.h> |
32525 |
-+#include <time.h> |
32526 |
-+#include <sys/capability.h> |
32527 |
-+#include <sys/eventfd.h> |
32528 |
-+#include <sys/wait.h> |
32529 |
-+ |
32530 |
-+#include "kdbus-test.h" |
32531 |
-+#include "kdbus-util.h" |
32532 |
-+#include "kdbus-enum.h" |
32533 |
-+ |
32534 |
-+static int test_policy_priv_by_id(const char *bus, |
32535 |
-+ struct kdbus_conn *conn_dst, |
32536 |
-+ bool drop_second_user, |
32537 |
-+ int parent_status, |
32538 |
-+ int child_status) |
32539 |
-+{ |
32540 |
-+ int ret = 0; |
32541 |
-+ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32542 |
-+ |
32543 |
-+ ASSERT_RETURN(conn_dst); |
32544 |
-+ |
32545 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, bus, ({ |
32546 |
-+ ret = kdbus_msg_send(unpriv, NULL, |
32547 |
-+ expected_cookie, 0, 0, 0, |
32548 |
-+ conn_dst->id); |
32549 |
-+ ASSERT_EXIT(ret == child_status); |
32550 |
-+ })); |
32551 |
-+ ASSERT_RETURN(ret >= 0); |
32552 |
-+ |
32553 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 300, NULL, NULL); |
32554 |
-+ ASSERT_RETURN(ret == parent_status); |
32555 |
-+ |
32556 |
-+ return 0; |
32557 |
-+} |
32558 |
-+ |
32559 |
-+static int test_policy_priv_by_broadcast(const char *bus, |
32560 |
-+ struct kdbus_conn *conn_dst, |
32561 |
-+ int drop_second_user, |
32562 |
-+ int parent_status, |
32563 |
-+ int child_status) |
32564 |
-+{ |
32565 |
-+ int efd; |
32566 |
-+ int ret = 0; |
32567 |
-+ eventfd_t event_status = 0; |
32568 |
-+ struct kdbus_msg *msg = NULL; |
32569 |
-+ uid_t second_uid = UNPRIV_UID; |
32570 |
-+ gid_t second_gid = UNPRIV_GID; |
32571 |
-+ struct kdbus_conn *child_2 = conn_dst; |
32572 |
-+ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32573 |
-+ |
32574 |
-+ /* Drop to another unprivileged user other than UNPRIV_UID */ |
32575 |
-+ if (drop_second_user == DROP_OTHER_UNPRIV) { |
32576 |
-+ second_uid = UNPRIV_UID - 1; |
32577 |
-+ second_gid = UNPRIV_GID - 1; |
32578 |
-+ } |
32579 |
-+ |
32580 |
-+ /* child will signal parent to send broadcast */ |
32581 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
32582 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
32583 |
-+ |
32584 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
32585 |
-+ struct kdbus_conn *child; |
32586 |
-+ |
32587 |
-+ child = kdbus_hello(bus, 0, NULL, 0); |
32588 |
-+ ASSERT_EXIT(child); |
32589 |
-+ |
32590 |
-+ ret = kdbus_add_match_empty(child); |
32591 |
-+ ASSERT_EXIT(ret == 0); |
32592 |
-+ |
32593 |
-+ /* signal parent */ |
32594 |
-+ ret = eventfd_write(efd, 1); |
32595 |
-+ ASSERT_EXIT(ret == 0); |
32596 |
-+ |
32597 |
-+ /* Use a little bit high time */ |
32598 |
-+ ret = kdbus_msg_recv_poll(child, 500, &msg, NULL); |
32599 |
-+ ASSERT_EXIT(ret == child_status); |
32600 |
-+ |
32601 |
-+ /* |
32602 |
-+ * If we expect the child to get the broadcast |
32603 |
-+ * message, then check the received cookie. |
32604 |
-+ */ |
32605 |
-+ if (ret == 0) { |
32606 |
-+ ASSERT_EXIT(expected_cookie == msg->cookie); |
32607 |
-+ } |
32608 |
-+ |
32609 |
-+ /* Use expected_cookie since 'msg' might be NULL */ |
32610 |
-+ ret = kdbus_msg_send(child, NULL, expected_cookie + 1, |
32611 |
-+ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
32612 |
-+ ASSERT_EXIT(ret == 0); |
32613 |
-+ |
32614 |
-+ kdbus_msg_free(msg); |
32615 |
-+ kdbus_conn_free(child); |
32616 |
-+ }), |
32617 |
-+ ({ |
32618 |
-+ if (drop_second_user == DO_NOT_DROP) { |
32619 |
-+ ASSERT_RETURN(child_2); |
32620 |
-+ |
32621 |
-+ ret = eventfd_read(efd, &event_status); |
32622 |
-+ ASSERT_RETURN(ret >= 0 && event_status == 1); |
32623 |
-+ |
32624 |
-+ ret = kdbus_msg_send(child_2, NULL, |
32625 |
-+ expected_cookie, 0, 0, 0, |
32626 |
-+ KDBUS_DST_ID_BROADCAST); |
32627 |
-+ ASSERT_RETURN(ret == 0); |
32628 |
-+ |
32629 |
-+ /* drop own broadcast */ |
32630 |
-+ ret = kdbus_msg_recv(child_2, &msg, NULL); |
32631 |
-+ ASSERT_RETURN(ret == 0); |
32632 |
-+ ASSERT_RETURN(msg->src_id == child_2->id); |
32633 |
-+ kdbus_msg_free(msg); |
32634 |
-+ |
32635 |
-+ /* Use a little bit high time */ |
32636 |
-+ ret = kdbus_msg_recv_poll(child_2, 1000, |
32637 |
-+ &msg, NULL); |
32638 |
-+ ASSERT_RETURN(ret == parent_status); |
32639 |
-+ |
32640 |
-+ /* |
32641 |
-+ * Check returned cookie in case we expect |
32642 |
-+ * success. |
32643 |
-+ */ |
32644 |
-+ if (ret == 0) { |
32645 |
-+ ASSERT_RETURN(msg->cookie == |
32646 |
-+ expected_cookie + 1); |
32647 |
-+ } |
32648 |
-+ |
32649 |
-+ kdbus_msg_free(msg); |
32650 |
-+ } else { |
32651 |
-+ /* |
32652 |
-+ * Two unprivileged users will try to |
32653 |
-+ * communicate using broadcast. |
32654 |
-+ */ |
32655 |
-+ ret = RUN_UNPRIVILEGED(second_uid, second_gid, ({ |
32656 |
-+ child_2 = kdbus_hello(bus, 0, NULL, 0); |
32657 |
-+ ASSERT_EXIT(child_2); |
32658 |
-+ |
32659 |
-+ ret = kdbus_add_match_empty(child_2); |
32660 |
-+ ASSERT_EXIT(ret == 0); |
32661 |
-+ |
32662 |
-+ ret = eventfd_read(efd, &event_status); |
32663 |
-+ ASSERT_EXIT(ret >= 0 && event_status == 1); |
32664 |
-+ |
32665 |
-+ ret = kdbus_msg_send(child_2, NULL, |
32666 |
-+ expected_cookie, 0, 0, 0, |
32667 |
-+ KDBUS_DST_ID_BROADCAST); |
32668 |
-+ ASSERT_EXIT(ret == 0); |
32669 |
-+ |
32670 |
-+ /* drop own broadcast */ |
32671 |
-+ ret = kdbus_msg_recv(child_2, &msg, NULL); |
32672 |
-+ ASSERT_RETURN(ret == 0); |
32673 |
-+ ASSERT_RETURN(msg->src_id == child_2->id); |
32674 |
-+ kdbus_msg_free(msg); |
32675 |
-+ |
32676 |
-+ /* Use a little bit high time */ |
32677 |
-+ ret = kdbus_msg_recv_poll(child_2, 1000, |
32678 |
-+ &msg, NULL); |
32679 |
-+ ASSERT_EXIT(ret == parent_status); |
32680 |
-+ |
32681 |
-+ /* |
32682 |
-+ * Check returned cookie in case we expect |
32683 |
-+ * success. |
32684 |
-+ */ |
32685 |
-+ if (ret == 0) { |
32686 |
-+ ASSERT_EXIT(msg->cookie == |
32687 |
-+ expected_cookie + 1); |
32688 |
-+ } |
32689 |
-+ |
32690 |
-+ kdbus_msg_free(msg); |
32691 |
-+ kdbus_conn_free(child_2); |
32692 |
-+ }), |
32693 |
-+ ({ 0; })); |
32694 |
-+ ASSERT_RETURN(ret == 0); |
32695 |
-+ } |
32696 |
-+ })); |
32697 |
-+ ASSERT_RETURN(ret == 0); |
32698 |
-+ |
32699 |
-+ close(efd); |
32700 |
-+ |
32701 |
-+ return ret; |
32702 |
-+} |
32703 |
-+ |
32704 |
-+static void nosig(int sig) |
32705 |
-+{ |
32706 |
-+} |
32707 |
-+ |
32708 |
-+static int test_priv_before_policy_upload(struct kdbus_test_env *env) |
32709 |
-+{ |
32710 |
-+ int ret = 0; |
32711 |
-+ struct kdbus_conn *conn; |
32712 |
-+ |
32713 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
32714 |
-+ ASSERT_RETURN(conn); |
32715 |
-+ |
32716 |
-+ /* |
32717 |
-+ * Make sure unprivileged bus user cannot acquire names |
32718 |
-+ * before registring any policy holder. |
32719 |
-+ */ |
32720 |
-+ |
32721 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
32722 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
32723 |
-+ ASSERT_EXIT(ret < 0); |
32724 |
-+ })); |
32725 |
-+ ASSERT_RETURN(ret == 0); |
32726 |
-+ |
32727 |
-+ /* |
32728 |
-+ * Make sure unprivileged bus users cannot talk by default |
32729 |
-+ * to privileged ones, unless a policy holder that allows |
32730 |
-+ * this was uploaded. |
32731 |
-+ */ |
32732 |
-+ |
32733 |
-+ ret = test_policy_priv_by_id(env->buspath, conn, false, |
32734 |
-+ -ETIMEDOUT, -EPERM); |
32735 |
-+ ASSERT_RETURN(ret == 0); |
32736 |
-+ |
32737 |
-+ /* Activate matching for a privileged connection */ |
32738 |
-+ ret = kdbus_add_match_empty(conn); |
32739 |
-+ ASSERT_RETURN(ret == 0); |
32740 |
-+ |
32741 |
-+ /* |
32742 |
-+ * First make sure that BROADCAST with msg flag |
32743 |
-+ * KDBUS_MSG_EXPECT_REPLY will fail with -ENOTUNIQ |
32744 |
-+ */ |
32745 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
32746 |
-+ ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, |
32747 |
-+ KDBUS_MSG_EXPECT_REPLY, |
32748 |
-+ 5000000000ULL, 0, |
32749 |
-+ KDBUS_DST_ID_BROADCAST); |
32750 |
-+ ASSERT_EXIT(ret == -ENOTUNIQ); |
32751 |
-+ })); |
32752 |
-+ ASSERT_RETURN(ret == 0); |
32753 |
-+ |
32754 |
-+ /* |
32755 |
-+ * Test broadcast with a privileged connection. |
32756 |
-+ * |
32757 |
-+ * The first unprivileged receiver should not get the |
32758 |
-+ * broadcast message sent by the privileged connection, |
32759 |
-+ * since there is no a TALK policy that allows the |
32760 |
-+ * unprivileged to TALK to the privileged connection. It |
32761 |
-+ * will fail with -ETIMEDOUT |
32762 |
-+ * |
32763 |
-+ * Then second case: |
32764 |
-+ * The privileged connection should get the broadcast |
32765 |
-+ * message from the unprivileged one. Since the receiver is |
32766 |
-+ * a privileged bus user and it has default TALK access to |
32767 |
-+ * all connections it will receive those. |
32768 |
-+ */ |
32769 |
-+ |
32770 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, conn, |
32771 |
-+ DO_NOT_DROP, |
32772 |
-+ 0, -ETIMEDOUT); |
32773 |
-+ ASSERT_RETURN(ret == 0); |
32774 |
-+ |
32775 |
-+ |
32776 |
-+ /* |
32777 |
-+ * Test broadcast with two unprivileged connections running |
32778 |
-+ * under the same user. |
32779 |
-+ * |
32780 |
-+ * Both connections should succeed. |
32781 |
-+ */ |
32782 |
-+ |
32783 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32784 |
-+ DROP_SAME_UNPRIV, 0, 0); |
32785 |
-+ ASSERT_RETURN(ret == 0); |
32786 |
-+ |
32787 |
-+ /* |
32788 |
-+ * Test broadcast with two unprivileged connections running |
32789 |
-+ * under different users. |
32790 |
-+ * |
32791 |
-+ * Both connections will fail with -ETIMEDOUT. |
32792 |
-+ */ |
32793 |
-+ |
32794 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32795 |
-+ DROP_OTHER_UNPRIV, |
32796 |
-+ -ETIMEDOUT, -ETIMEDOUT); |
32797 |
-+ ASSERT_RETURN(ret == 0); |
32798 |
-+ |
32799 |
-+ kdbus_conn_free(conn); |
32800 |
-+ |
32801 |
-+ return ret; |
32802 |
-+} |
32803 |
-+ |
32804 |
-+static int test_broadcast_after_policy_upload(struct kdbus_test_env *env) |
32805 |
-+{ |
32806 |
-+ int ret; |
32807 |
-+ int efd; |
32808 |
-+ eventfd_t event_status = 0; |
32809 |
-+ struct kdbus_msg *msg = NULL; |
32810 |
-+ struct kdbus_conn *owner_a, *owner_b; |
32811 |
-+ struct kdbus_conn *holder_a, *holder_b; |
32812 |
-+ struct kdbus_policy_access access = {}; |
32813 |
-+ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32814 |
-+ |
32815 |
-+ owner_a = kdbus_hello(env->buspath, 0, NULL, 0); |
32816 |
-+ ASSERT_RETURN(owner_a); |
32817 |
-+ |
32818 |
-+ ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL); |
32819 |
-+ ASSERT_EXIT(ret >= 0); |
32820 |
-+ |
32821 |
-+ /* |
32822 |
-+ * Make sure unprivileged bus users cannot talk by default |
32823 |
-+ * to privileged ones, unless a policy holder that allows |
32824 |
-+ * this was uploaded. |
32825 |
-+ */ |
32826 |
-+ |
32827 |
-+ ++expected_cookie; |
32828 |
-+ ret = test_policy_priv_by_id(env->buspath, owner_a, false, |
32829 |
-+ -ETIMEDOUT, -EPERM); |
32830 |
-+ ASSERT_RETURN(ret == 0); |
32831 |
-+ |
32832 |
-+ /* |
32833 |
-+ * Make sure that privileged won't receive broadcasts unless |
32834 |
-+ * it installs a match. It will fail with -ETIMEDOUT |
32835 |
-+ * |
32836 |
-+ * At same time check that the unprivileged connection will |
32837 |
-+ * not receive the broadcast message from the privileged one |
32838 |
-+ * since the privileged one owns a name with a restricted |
32839 |
-+ * policy TALK (actually the TALK policy is still not |
32840 |
-+ * registered so we fail by default), thus the unprivileged |
32841 |
-+ * receiver is not able to TALK to that name. |
32842 |
-+ */ |
32843 |
-+ |
32844 |
-+ /* Activate matching for a privileged connection */ |
32845 |
-+ ret = kdbus_add_match_empty(owner_a); |
32846 |
-+ ASSERT_RETURN(ret == 0); |
32847 |
-+ |
32848 |
-+ /* |
32849 |
-+ * Redo the previous test. The privileged conn owner_a is |
32850 |
-+ * able to TALK to any connection so it will receive the |
32851 |
-+ * broadcast message now. |
32852 |
-+ */ |
32853 |
-+ |
32854 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
32855 |
-+ DO_NOT_DROP, |
32856 |
-+ 0, -ETIMEDOUT); |
32857 |
-+ ASSERT_RETURN(ret == 0); |
32858 |
-+ |
32859 |
-+ /* |
32860 |
-+ * Test that broadcast between two unprivileged users running |
32861 |
-+ * under the same user still succeed. |
32862 |
-+ */ |
32863 |
-+ |
32864 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32865 |
-+ DROP_SAME_UNPRIV, 0, 0); |
32866 |
-+ ASSERT_RETURN(ret == 0); |
32867 |
-+ |
32868 |
-+ /* |
32869 |
-+ * Test broadcast with two unprivileged connections running |
32870 |
-+ * under different users. |
32871 |
-+ * |
32872 |
-+ * Both connections will fail with -ETIMEDOUT. |
32873 |
-+ */ |
32874 |
-+ |
32875 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32876 |
-+ DROP_OTHER_UNPRIV, |
32877 |
-+ -ETIMEDOUT, -ETIMEDOUT); |
32878 |
-+ ASSERT_RETURN(ret == 0); |
32879 |
-+ |
32880 |
-+ access = (struct kdbus_policy_access){ |
32881 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
32882 |
-+ .id = geteuid(), |
32883 |
-+ .access = KDBUS_POLICY_OWN, |
32884 |
-+ }; |
32885 |
-+ |
32886 |
-+ holder_a = kdbus_hello_registrar(env->buspath, |
32887 |
-+ "com.example.broadcastA", |
32888 |
-+ &access, 1, |
32889 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
32890 |
-+ ASSERT_RETURN(holder_a); |
32891 |
-+ |
32892 |
-+ holder_b = kdbus_hello_registrar(env->buspath, |
32893 |
-+ "com.example.broadcastB", |
32894 |
-+ &access, 1, |
32895 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
32896 |
-+ ASSERT_RETURN(holder_b); |
32897 |
-+ |
32898 |
-+ /* Free connections and their received messages and restart */ |
32899 |
-+ kdbus_conn_free(owner_a); |
32900 |
-+ |
32901 |
-+ owner_a = kdbus_hello(env->buspath, 0, NULL, 0); |
32902 |
-+ ASSERT_RETURN(owner_a); |
32903 |
-+ |
32904 |
-+ /* Activate matching for a privileged connection */ |
32905 |
-+ ret = kdbus_add_match_empty(owner_a); |
32906 |
-+ ASSERT_RETURN(ret == 0); |
32907 |
-+ |
32908 |
-+ ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL); |
32909 |
-+ ASSERT_EXIT(ret >= 0); |
32910 |
-+ |
32911 |
-+ owner_b = kdbus_hello(env->buspath, 0, NULL, 0); |
32912 |
-+ ASSERT_RETURN(owner_b); |
32913 |
-+ |
32914 |
-+ ret = kdbus_name_acquire(owner_b, "com.example.broadcastB", NULL); |
32915 |
-+ ASSERT_EXIT(ret >= 0); |
32916 |
-+ |
32917 |
-+ /* Activate matching for a privileged connection */ |
32918 |
-+ ret = kdbus_add_match_empty(owner_b); |
32919 |
-+ ASSERT_RETURN(ret == 0); |
32920 |
-+ |
32921 |
-+ /* |
32922 |
-+ * Test that even if "com.example.broadcastA" and |
32923 |
-+ * "com.example.broadcastB" do have a TALK access by default |
32924 |
-+ * they are able to signal each other using broadcast due to |
32925 |
-+ * the fact they are privileged connections, they receive |
32926 |
-+ * all broadcasts if the match allows it. |
32927 |
-+ */ |
32928 |
-+ |
32929 |
-+ ++expected_cookie; |
32930 |
-+ ret = kdbus_msg_send(owner_a, NULL, expected_cookie, 0, |
32931 |
-+ 0, 0, KDBUS_DST_ID_BROADCAST); |
32932 |
-+ ASSERT_RETURN(ret == 0); |
32933 |
-+ |
32934 |
-+ ret = kdbus_msg_recv_poll(owner_a, 100, &msg, NULL); |
32935 |
-+ ASSERT_RETURN(ret == 0); |
32936 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
32937 |
-+ |
32938 |
-+ /* Check src ID */ |
32939 |
-+ ASSERT_RETURN(msg->src_id == owner_a->id); |
32940 |
-+ |
32941 |
-+ kdbus_msg_free(msg); |
32942 |
-+ |
32943 |
-+ ret = kdbus_msg_recv_poll(owner_b, 100, &msg, NULL); |
32944 |
-+ ASSERT_RETURN(ret == 0); |
32945 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
32946 |
-+ |
32947 |
-+ /* Check src ID */ |
32948 |
-+ ASSERT_RETURN(msg->src_id == owner_a->id); |
32949 |
-+ |
32950 |
-+ kdbus_msg_free(msg); |
32951 |
-+ |
32952 |
-+ /* Release name "com.example.broadcastB" */ |
32953 |
-+ |
32954 |
-+ ret = kdbus_name_release(owner_b, "com.example.broadcastB"); |
32955 |
-+ ASSERT_EXIT(ret >= 0); |
32956 |
-+ |
32957 |
-+ /* KDBUS_POLICY_OWN for unprivileged connections */ |
32958 |
-+ access = (struct kdbus_policy_access){ |
32959 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
32960 |
-+ .id = geteuid(), |
32961 |
-+ .access = KDBUS_POLICY_OWN, |
32962 |
-+ }; |
32963 |
-+ |
32964 |
-+ /* Update the policy so unprivileged will own the name */ |
32965 |
-+ |
32966 |
-+ ret = kdbus_conn_update_policy(holder_b, |
32967 |
-+ "com.example.broadcastB", |
32968 |
-+ &access, 1); |
32969 |
-+ ASSERT_RETURN(ret == 0); |
32970 |
-+ |
32971 |
-+ /* |
32972 |
-+ * Send broadcasts from an unprivileged connection that |
32973 |
-+ * owns a name "com.example.broadcastB". |
32974 |
-+ * |
32975 |
-+ * We'll have four destinations here: |
32976 |
-+ * |
32977 |
-+ * 1) destination owner_a: privileged connection that owns |
32978 |
-+ * "com.example.broadcastA". It will receive the broadcast |
32979 |
-+ * since it is a privileged has default TALK access to all |
32980 |
-+ * connections, and it is subscribed to the match. |
32981 |
-+ * Will succeed. |
32982 |
-+ * |
32983 |
-+ * owner_b: privileged connection (running under a different |
32984 |
-+ * uid) that do not own names, but with an empty broadcast |
32985 |
-+ * match, so it will receive broadcasts since it has default |
32986 |
-+ * TALK access to all connection. |
32987 |
-+ * |
32988 |
-+ * unpriv_a: unpriv connection that do not own any name. |
32989 |
-+ * It will receive the broadcast since it is running under |
32990 |
-+ * the same user of the one broadcasting and did install |
32991 |
-+ * matches. It should get the message. |
32992 |
-+ * |
32993 |
-+ * unpriv_b: unpriv connection is not interested in broadcast |
32994 |
-+ * messages, so it did not install broadcast matches. Should |
32995 |
-+ * fail with -ETIMEDOUT |
32996 |
-+ */ |
32997 |
-+ |
32998 |
-+ ++expected_cookie; |
32999 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
33000 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
33001 |
-+ |
33002 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
33003 |
-+ struct kdbus_conn *unpriv_owner; |
33004 |
-+ struct kdbus_conn *unpriv_a, *unpriv_b; |
33005 |
-+ |
33006 |
-+ unpriv_owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33007 |
-+ ASSERT_EXIT(unpriv_owner); |
33008 |
-+ |
33009 |
-+ unpriv_a = kdbus_hello(env->buspath, 0, NULL, 0); |
33010 |
-+ ASSERT_EXIT(unpriv_a); |
33011 |
-+ |
33012 |
-+ unpriv_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33013 |
-+ ASSERT_EXIT(unpriv_b); |
33014 |
-+ |
33015 |
-+ ret = kdbus_name_acquire(unpriv_owner, |
33016 |
-+ "com.example.broadcastB", |
33017 |
-+ NULL); |
33018 |
-+ ASSERT_EXIT(ret >= 0); |
33019 |
-+ |
33020 |
-+ ret = kdbus_add_match_empty(unpriv_a); |
33021 |
-+ ASSERT_EXIT(ret == 0); |
33022 |
-+ |
33023 |
-+ /* Signal that we are doing broadcasts */ |
33024 |
-+ ret = eventfd_write(efd, 1); |
33025 |
-+ ASSERT_EXIT(ret == 0); |
33026 |
-+ |
33027 |
-+ /* |
33028 |
-+ * Do broadcast from a connection that owns the |
33029 |
-+ * names "com.example.broadcastB". |
33030 |
-+ */ |
33031 |
-+ ret = kdbus_msg_send(unpriv_owner, NULL, |
33032 |
-+ expected_cookie, |
33033 |
-+ 0, 0, 0, |
33034 |
-+ KDBUS_DST_ID_BROADCAST); |
33035 |
-+ ASSERT_EXIT(ret == 0); |
33036 |
-+ |
33037 |
-+ /* |
33038 |
-+ * Unprivileged connection running under the same |
33039 |
-+ * user. It should succeed. |
33040 |
-+ */ |
33041 |
-+ ret = kdbus_msg_recv_poll(unpriv_a, 300, &msg, NULL); |
33042 |
-+ ASSERT_EXIT(ret == 0 && msg->cookie == expected_cookie); |
33043 |
-+ |
33044 |
-+ /* |
33045 |
-+ * Did not install matches, not interested in |
33046 |
-+ * broadcasts |
33047 |
-+ */ |
33048 |
-+ ret = kdbus_msg_recv_poll(unpriv_b, 300, NULL, NULL); |
33049 |
-+ ASSERT_EXIT(ret == -ETIMEDOUT); |
33050 |
-+ }), |
33051 |
-+ ({ |
33052 |
-+ ret = eventfd_read(efd, &event_status); |
33053 |
-+ ASSERT_RETURN(ret >= 0 && event_status == 1); |
33054 |
-+ |
33055 |
-+ /* |
33056 |
-+ * owner_a must fail with -ETIMEDOUT, since it owns |
33057 |
-+ * name "com.example.broadcastA" and its TALK |
33058 |
-+ * access is restriced. |
33059 |
-+ */ |
33060 |
-+ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33061 |
-+ ASSERT_RETURN(ret == 0); |
33062 |
-+ |
33063 |
-+ /* confirm the received cookie */ |
33064 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33065 |
-+ |
33066 |
-+ kdbus_msg_free(msg); |
33067 |
-+ |
33068 |
-+ /* |
33069 |
-+ * owner_b got the broadcast from an unprivileged |
33070 |
-+ * connection. |
33071 |
-+ */ |
33072 |
-+ ret = kdbus_msg_recv_poll(owner_b, 300, &msg, NULL); |
33073 |
-+ ASSERT_RETURN(ret == 0); |
33074 |
-+ |
33075 |
-+ /* confirm the received cookie */ |
33076 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33077 |
-+ |
33078 |
-+ kdbus_msg_free(msg); |
33079 |
-+ |
33080 |
-+ })); |
33081 |
-+ ASSERT_RETURN(ret == 0); |
33082 |
-+ |
33083 |
-+ close(efd); |
33084 |
-+ |
33085 |
-+ /* |
33086 |
-+ * Test broadcast with two unprivileged connections running |
33087 |
-+ * under different users. |
33088 |
-+ * |
33089 |
-+ * Both connections will fail with -ETIMEDOUT. |
33090 |
-+ */ |
33091 |
-+ |
33092 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33093 |
-+ DROP_OTHER_UNPRIV, |
33094 |
-+ -ETIMEDOUT, -ETIMEDOUT); |
33095 |
-+ ASSERT_RETURN(ret == 0); |
33096 |
-+ |
33097 |
-+ /* Drop received broadcasts by privileged */ |
33098 |
-+ ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL); |
33099 |
-+ ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL); |
33100 |
-+ ASSERT_RETURN(ret == 0); |
33101 |
-+ |
33102 |
-+ ret = kdbus_msg_recv(owner_a, NULL, NULL); |
33103 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
33104 |
-+ |
33105 |
-+ ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL); |
33106 |
-+ ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL); |
33107 |
-+ ASSERT_RETURN(ret == 0); |
33108 |
-+ |
33109 |
-+ ret = kdbus_msg_recv(owner_b, NULL, NULL); |
33110 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
33111 |
-+ |
33112 |
-+ /* |
33113 |
-+ * Perform last tests, allow others to talk to name |
33114 |
-+ * "com.example.broadcastA". So now receiving broadcasts |
33115 |
-+ * from it should succeed since the TALK policy allow it. |
33116 |
-+ */ |
33117 |
-+ |
33118 |
-+ /* KDBUS_POLICY_OWN for unprivileged connections */ |
33119 |
-+ access = (struct kdbus_policy_access){ |
33120 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33121 |
-+ .id = geteuid(), |
33122 |
-+ .access = KDBUS_POLICY_TALK, |
33123 |
-+ }; |
33124 |
-+ |
33125 |
-+ ret = kdbus_conn_update_policy(holder_a, |
33126 |
-+ "com.example.broadcastA", |
33127 |
-+ &access, 1); |
33128 |
-+ ASSERT_RETURN(ret == 0); |
33129 |
-+ |
33130 |
-+ /* |
33131 |
-+ * Unprivileged is able to TALK to "com.example.broadcastA" |
33132 |
-+ * now so it will receive its broadcasts |
33133 |
-+ */ |
33134 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
33135 |
-+ DO_NOT_DROP, 0, 0); |
33136 |
-+ ASSERT_RETURN(ret == 0); |
33137 |
-+ |
33138 |
-+ ++expected_cookie; |
33139 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33140 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.broadcastB", |
33141 |
-+ NULL); |
33142 |
-+ ASSERT_EXIT(ret >= 0); |
33143 |
-+ ret = kdbus_msg_send(unpriv, NULL, expected_cookie, |
33144 |
-+ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
33145 |
-+ ASSERT_EXIT(ret == 0); |
33146 |
-+ })); |
33147 |
-+ ASSERT_RETURN(ret == 0); |
33148 |
-+ |
33149 |
-+ /* owner_a is privileged it will get the broadcast now. */ |
33150 |
-+ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33151 |
-+ ASSERT_RETURN(ret == 0); |
33152 |
-+ |
33153 |
-+ /* confirm the received cookie */ |
33154 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33155 |
-+ |
33156 |
-+ kdbus_msg_free(msg); |
33157 |
-+ |
33158 |
-+ /* |
33159 |
-+ * owner_a released name "com.example.broadcastA". It should |
33160 |
-+ * receive broadcasts since it is still privileged and has |
33161 |
-+ * the right match. |
33162 |
-+ * |
33163 |
-+ * Unprivileged connection will own a name and will try to |
33164 |
-+ * signal to the privileged connection. |
33165 |
-+ */ |
33166 |
-+ |
33167 |
-+ ret = kdbus_name_release(owner_a, "com.example.broadcastA"); |
33168 |
-+ ASSERT_EXIT(ret >= 0); |
33169 |
-+ |
33170 |
-+ ++expected_cookie; |
33171 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33172 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.broadcastB", |
33173 |
-+ NULL); |
33174 |
-+ ASSERT_EXIT(ret >= 0); |
33175 |
-+ ret = kdbus_msg_send(unpriv, NULL, expected_cookie, |
33176 |
-+ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
33177 |
-+ ASSERT_EXIT(ret == 0); |
33178 |
-+ })); |
33179 |
-+ ASSERT_RETURN(ret == 0); |
33180 |
-+ |
33181 |
-+ /* owner_a will get the broadcast now. */ |
33182 |
-+ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33183 |
-+ ASSERT_RETURN(ret == 0); |
33184 |
-+ |
33185 |
-+ /* confirm the received cookie */ |
33186 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33187 |
-+ |
33188 |
-+ kdbus_msg_free(msg); |
33189 |
-+ |
33190 |
-+ kdbus_conn_free(owner_a); |
33191 |
-+ kdbus_conn_free(owner_b); |
33192 |
-+ kdbus_conn_free(holder_a); |
33193 |
-+ kdbus_conn_free(holder_b); |
33194 |
-+ |
33195 |
-+ return 0; |
33196 |
-+} |
33197 |
-+ |
33198 |
-+static int test_policy_priv(struct kdbus_test_env *env) |
33199 |
-+{ |
33200 |
-+ struct kdbus_conn *conn_a, *conn_b, *conn, *owner; |
33201 |
-+ struct kdbus_policy_access access, *acc; |
33202 |
-+ sigset_t sset; |
33203 |
-+ size_t num; |
33204 |
-+ int ret; |
33205 |
-+ |
33206 |
-+ /* |
33207 |
-+ * Make sure we have CAP_SETUID/SETGID so we can drop privileges |
33208 |
-+ */ |
33209 |
-+ |
33210 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
33211 |
-+ ASSERT_RETURN(ret >= 0); |
33212 |
-+ |
33213 |
-+ if (!ret) |
33214 |
-+ return TEST_SKIP; |
33215 |
-+ |
33216 |
-+ /* make sure that uids and gids are mapped */ |
33217 |
-+ if (!all_uids_gids_are_mapped()) |
33218 |
-+ return TEST_SKIP; |
33219 |
-+ |
33220 |
-+ /* |
33221 |
-+ * Setup: |
33222 |
-+ * conn_a: policy holder for com.example.a |
33223 |
-+ * conn_b: name holder of com.example.b |
33224 |
-+ */ |
33225 |
-+ |
33226 |
-+ signal(SIGUSR1, nosig); |
33227 |
-+ sigemptyset(&sset); |
33228 |
-+ sigaddset(&sset, SIGUSR1); |
33229 |
-+ sigprocmask(SIG_BLOCK, &sset, NULL); |
33230 |
-+ |
33231 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33232 |
-+ ASSERT_RETURN(conn); |
33233 |
-+ |
33234 |
-+ /* |
33235 |
-+ * Before registering any policy holder, make sure that the |
33236 |
-+ * bus is secure by default. This test is necessary, it catches |
33237 |
-+ * several cases where old D-Bus was vulnerable. |
33238 |
-+ */ |
33239 |
-+ |
33240 |
-+ ret = test_priv_before_policy_upload(env); |
33241 |
-+ ASSERT_RETURN(ret == 0); |
33242 |
-+ |
33243 |
-+ /* |
33244 |
-+ * Make sure unprivileged are not able to register policy |
33245 |
-+ * holders |
33246 |
-+ */ |
33247 |
-+ |
33248 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
33249 |
-+ struct kdbus_conn *holder; |
33250 |
-+ |
33251 |
-+ holder = kdbus_hello_registrar(env->buspath, |
33252 |
-+ "com.example.a", NULL, 0, |
33253 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
33254 |
-+ ASSERT_EXIT(holder == NULL && errno == EPERM); |
33255 |
-+ }), |
33256 |
-+ ({ 0; })); |
33257 |
-+ ASSERT_RETURN(ret == 0); |
33258 |
-+ |
33259 |
-+ |
33260 |
-+ /* Register policy holder */ |
33261 |
-+ |
33262 |
-+ conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", |
33263 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33264 |
-+ ASSERT_RETURN(conn_a); |
33265 |
-+ |
33266 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33267 |
-+ ASSERT_RETURN(conn_b); |
33268 |
-+ |
33269 |
-+ ret = kdbus_name_acquire(conn_b, "com.example.b", NULL); |
33270 |
-+ ASSERT_EXIT(ret >= 0); |
33271 |
-+ |
33272 |
-+ /* |
33273 |
-+ * Make sure bus-owners can always acquire names. |
33274 |
-+ */ |
33275 |
-+ ret = kdbus_name_acquire(conn, "com.example.a", NULL); |
33276 |
-+ ASSERT_EXIT(ret >= 0); |
33277 |
-+ |
33278 |
-+ kdbus_conn_free(conn); |
33279 |
-+ |
33280 |
-+ /* |
33281 |
-+ * Make sure unprivileged users cannot acquire names with default |
33282 |
-+ * policy assigned. |
33283 |
-+ */ |
33284 |
-+ |
33285 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33286 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33287 |
-+ ASSERT_EXIT(ret < 0); |
33288 |
-+ })); |
33289 |
-+ ASSERT_RETURN(ret >= 0); |
33290 |
-+ |
33291 |
-+ /* |
33292 |
-+ * Make sure unprivileged users can acquire names if we make them |
33293 |
-+ * world-accessible. |
33294 |
-+ */ |
33295 |
-+ |
33296 |
-+ access = (struct kdbus_policy_access){ |
33297 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33298 |
-+ .id = 0, |
33299 |
-+ .access = KDBUS_POLICY_OWN, |
33300 |
-+ }; |
33301 |
-+ |
33302 |
-+ /* |
33303 |
-+ * Make sure unprivileged/normal connections are not able |
33304 |
-+ * to update policies |
33305 |
-+ */ |
33306 |
-+ |
33307 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33308 |
-+ ret = kdbus_conn_update_policy(unpriv, "com.example.a", |
33309 |
-+ &access, 1); |
33310 |
-+ ASSERT_EXIT(ret == -EOPNOTSUPP); |
33311 |
-+ })); |
33312 |
-+ ASSERT_RETURN(ret == 0); |
33313 |
-+ |
33314 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33315 |
-+ ASSERT_RETURN(ret == 0); |
33316 |
-+ |
33317 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33318 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33319 |
-+ ASSERT_EXIT(ret >= 0); |
33320 |
-+ })); |
33321 |
-+ ASSERT_RETURN(ret >= 0); |
33322 |
-+ |
33323 |
-+ /* |
33324 |
-+ * Make sure unprivileged users can acquire names if we make them |
33325 |
-+ * gid-accessible. But only if the gid matches. |
33326 |
-+ */ |
33327 |
-+ |
33328 |
-+ access = (struct kdbus_policy_access){ |
33329 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33330 |
-+ .id = UNPRIV_GID, |
33331 |
-+ .access = KDBUS_POLICY_OWN, |
33332 |
-+ }; |
33333 |
-+ |
33334 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33335 |
-+ ASSERT_RETURN(ret == 0); |
33336 |
-+ |
33337 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33338 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33339 |
-+ ASSERT_EXIT(ret >= 0); |
33340 |
-+ })); |
33341 |
-+ ASSERT_RETURN(ret >= 0); |
33342 |
-+ |
33343 |
-+ access = (struct kdbus_policy_access){ |
33344 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33345 |
-+ .id = 1, |
33346 |
-+ .access = KDBUS_POLICY_OWN, |
33347 |
-+ }; |
33348 |
-+ |
33349 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33350 |
-+ ASSERT_RETURN(ret == 0); |
33351 |
-+ |
33352 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33353 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33354 |
-+ ASSERT_EXIT(ret < 0); |
33355 |
-+ })); |
33356 |
-+ ASSERT_RETURN(ret >= 0); |
33357 |
-+ |
33358 |
-+ /* |
33359 |
-+ * Make sure unprivileged users can acquire names if we make them |
33360 |
-+ * uid-accessible. But only if the uid matches. |
33361 |
-+ */ |
33362 |
-+ |
33363 |
-+ access = (struct kdbus_policy_access){ |
33364 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33365 |
-+ .id = UNPRIV_UID, |
33366 |
-+ .access = KDBUS_POLICY_OWN, |
33367 |
-+ }; |
33368 |
-+ |
33369 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33370 |
-+ ASSERT_RETURN(ret == 0); |
33371 |
-+ |
33372 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33373 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33374 |
-+ ASSERT_EXIT(ret >= 0); |
33375 |
-+ })); |
33376 |
-+ ASSERT_RETURN(ret >= 0); |
33377 |
-+ |
33378 |
-+ access = (struct kdbus_policy_access){ |
33379 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33380 |
-+ .id = 1, |
33381 |
-+ .access = KDBUS_POLICY_OWN, |
33382 |
-+ }; |
33383 |
-+ |
33384 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33385 |
-+ ASSERT_RETURN(ret == 0); |
33386 |
-+ |
33387 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33388 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33389 |
-+ ASSERT_EXIT(ret < 0); |
33390 |
-+ })); |
33391 |
-+ ASSERT_RETURN(ret >= 0); |
33392 |
-+ |
33393 |
-+ /* |
33394 |
-+ * Make sure unprivileged users cannot acquire names if no owner-policy |
33395 |
-+ * matches, even if SEE/TALK policies match. |
33396 |
-+ */ |
33397 |
-+ |
33398 |
-+ num = 4; |
33399 |
-+ acc = (struct kdbus_policy_access[]){ |
33400 |
-+ { |
33401 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33402 |
-+ .id = UNPRIV_GID, |
33403 |
-+ .access = KDBUS_POLICY_SEE, |
33404 |
-+ }, |
33405 |
-+ { |
33406 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33407 |
-+ .id = UNPRIV_UID, |
33408 |
-+ .access = KDBUS_POLICY_TALK, |
33409 |
-+ }, |
33410 |
-+ { |
33411 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33412 |
-+ .id = 0, |
33413 |
-+ .access = KDBUS_POLICY_TALK, |
33414 |
-+ }, |
33415 |
-+ { |
33416 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33417 |
-+ .id = 0, |
33418 |
-+ .access = KDBUS_POLICY_SEE, |
33419 |
-+ }, |
33420 |
-+ }; |
33421 |
-+ |
33422 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num); |
33423 |
-+ ASSERT_RETURN(ret == 0); |
33424 |
-+ |
33425 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33426 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33427 |
-+ ASSERT_EXIT(ret < 0); |
33428 |
-+ })); |
33429 |
-+ ASSERT_RETURN(ret >= 0); |
33430 |
-+ |
33431 |
-+ /* |
33432 |
-+ * Make sure unprivileged users can acquire names if the only matching |
33433 |
-+ * policy is somewhere in the middle. |
33434 |
-+ */ |
33435 |
-+ |
33436 |
-+ num = 5; |
33437 |
-+ acc = (struct kdbus_policy_access[]){ |
33438 |
-+ { |
33439 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33440 |
-+ .id = 1, |
33441 |
-+ .access = KDBUS_POLICY_OWN, |
33442 |
-+ }, |
33443 |
-+ { |
33444 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33445 |
-+ .id = 2, |
33446 |
-+ .access = KDBUS_POLICY_OWN, |
33447 |
-+ }, |
33448 |
-+ { |
33449 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33450 |
-+ .id = UNPRIV_UID, |
33451 |
-+ .access = KDBUS_POLICY_OWN, |
33452 |
-+ }, |
33453 |
-+ { |
33454 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33455 |
-+ .id = 3, |
33456 |
-+ .access = KDBUS_POLICY_OWN, |
33457 |
-+ }, |
33458 |
-+ { |
33459 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33460 |
-+ .id = 4, |
33461 |
-+ .access = KDBUS_POLICY_OWN, |
33462 |
-+ }, |
33463 |
-+ }; |
33464 |
-+ |
33465 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num); |
33466 |
-+ ASSERT_RETURN(ret == 0); |
33467 |
-+ |
33468 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33469 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33470 |
-+ ASSERT_EXIT(ret >= 0); |
33471 |
-+ })); |
33472 |
-+ ASSERT_RETURN(ret >= 0); |
33473 |
-+ |
33474 |
-+ /* |
33475 |
-+ * Clear policies |
33476 |
-+ */ |
33477 |
-+ |
33478 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", NULL, 0); |
33479 |
-+ ASSERT_RETURN(ret == 0); |
33480 |
-+ |
33481 |
-+ /* |
33482 |
-+ * Make sure privileged bus users can _always_ talk to others. |
33483 |
-+ */ |
33484 |
-+ |
33485 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33486 |
-+ ASSERT_RETURN(conn); |
33487 |
-+ |
33488 |
-+ ret = kdbus_msg_send(conn, "com.example.b", 0xdeadbeef, 0, 0, 0, 0); |
33489 |
-+ ASSERT_EXIT(ret >= 0); |
33490 |
-+ |
33491 |
-+ ret = kdbus_msg_recv_poll(conn_b, 300, NULL, NULL); |
33492 |
-+ ASSERT_EXIT(ret >= 0); |
33493 |
-+ |
33494 |
-+ kdbus_conn_free(conn); |
33495 |
-+ |
33496 |
-+ /* |
33497 |
-+ * Make sure unprivileged bus users cannot talk by default. |
33498 |
-+ */ |
33499 |
-+ |
33500 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33501 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33502 |
-+ 0, 0); |
33503 |
-+ ASSERT_EXIT(ret == -EPERM); |
33504 |
-+ })); |
33505 |
-+ ASSERT_RETURN(ret >= 0); |
33506 |
-+ |
33507 |
-+ /* |
33508 |
-+ * Make sure unprivileged bus users can talk to equals, even without |
33509 |
-+ * policy. |
33510 |
-+ */ |
33511 |
-+ |
33512 |
-+ access = (struct kdbus_policy_access){ |
33513 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33514 |
-+ .id = UNPRIV_UID, |
33515 |
-+ .access = KDBUS_POLICY_OWN, |
33516 |
-+ }; |
33517 |
-+ |
33518 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.c", &access, 1); |
33519 |
-+ ASSERT_RETURN(ret == 0); |
33520 |
-+ |
33521 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33522 |
-+ struct kdbus_conn *owner; |
33523 |
-+ |
33524 |
-+ owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33525 |
-+ ASSERT_RETURN(owner); |
33526 |
-+ |
33527 |
-+ ret = kdbus_name_acquire(owner, "com.example.c", NULL); |
33528 |
-+ ASSERT_EXIT(ret >= 0); |
33529 |
-+ |
33530 |
-+ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33531 |
-+ 0, 0); |
33532 |
-+ ASSERT_EXIT(ret >= 0); |
33533 |
-+ ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL); |
33534 |
-+ ASSERT_EXIT(ret >= 0); |
33535 |
-+ |
33536 |
-+ kdbus_conn_free(owner); |
33537 |
-+ })); |
33538 |
-+ ASSERT_RETURN(ret >= 0); |
33539 |
-+ |
33540 |
-+ /* |
33541 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33542 |
-+ * suitable UID policy is set. |
33543 |
-+ */ |
33544 |
-+ |
33545 |
-+ access = (struct kdbus_policy_access){ |
33546 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33547 |
-+ .id = UNPRIV_UID, |
33548 |
-+ .access = KDBUS_POLICY_TALK, |
33549 |
-+ }; |
33550 |
-+ |
33551 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33552 |
-+ ASSERT_RETURN(ret == 0); |
33553 |
-+ |
33554 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33555 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33556 |
-+ 0, 0); |
33557 |
-+ ASSERT_EXIT(ret >= 0); |
33558 |
-+ })); |
33559 |
-+ ASSERT_RETURN(ret >= 0); |
33560 |
-+ |
33561 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33562 |
-+ ASSERT_EXIT(ret >= 0); |
33563 |
-+ |
33564 |
-+ /* |
33565 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33566 |
-+ * suitable GID policy is set. |
33567 |
-+ */ |
33568 |
-+ |
33569 |
-+ access = (struct kdbus_policy_access){ |
33570 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33571 |
-+ .id = UNPRIV_GID, |
33572 |
-+ .access = KDBUS_POLICY_TALK, |
33573 |
-+ }; |
33574 |
-+ |
33575 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33576 |
-+ ASSERT_RETURN(ret == 0); |
33577 |
-+ |
33578 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33579 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33580 |
-+ 0, 0); |
33581 |
-+ ASSERT_EXIT(ret >= 0); |
33582 |
-+ })); |
33583 |
-+ ASSERT_RETURN(ret >= 0); |
33584 |
-+ |
33585 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33586 |
-+ ASSERT_EXIT(ret >= 0); |
33587 |
-+ |
33588 |
-+ /* |
33589 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33590 |
-+ * suitable WORLD policy is set. |
33591 |
-+ */ |
33592 |
-+ |
33593 |
-+ access = (struct kdbus_policy_access){ |
33594 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33595 |
-+ .id = 0, |
33596 |
-+ .access = KDBUS_POLICY_TALK, |
33597 |
-+ }; |
33598 |
-+ |
33599 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33600 |
-+ ASSERT_RETURN(ret == 0); |
33601 |
-+ |
33602 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33603 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33604 |
-+ 0, 0); |
33605 |
-+ ASSERT_EXIT(ret >= 0); |
33606 |
-+ })); |
33607 |
-+ ASSERT_RETURN(ret >= 0); |
33608 |
-+ |
33609 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33610 |
-+ ASSERT_EXIT(ret >= 0); |
33611 |
-+ |
33612 |
-+ /* |
33613 |
-+ * Make sure unprivileged bus users cannot talk to privileged users if |
33614 |
-+ * no suitable policy is set. |
33615 |
-+ */ |
33616 |
-+ |
33617 |
-+ num = 5; |
33618 |
-+ acc = (struct kdbus_policy_access[]){ |
33619 |
-+ { |
33620 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33621 |
-+ .id = 0, |
33622 |
-+ .access = KDBUS_POLICY_OWN, |
33623 |
-+ }, |
33624 |
-+ { |
33625 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33626 |
-+ .id = 1, |
33627 |
-+ .access = KDBUS_POLICY_TALK, |
33628 |
-+ }, |
33629 |
-+ { |
33630 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33631 |
-+ .id = UNPRIV_UID, |
33632 |
-+ .access = KDBUS_POLICY_SEE, |
33633 |
-+ }, |
33634 |
-+ { |
33635 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33636 |
-+ .id = 3, |
33637 |
-+ .access = KDBUS_POLICY_TALK, |
33638 |
-+ }, |
33639 |
-+ { |
33640 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33641 |
-+ .id = 4, |
33642 |
-+ .access = KDBUS_POLICY_TALK, |
33643 |
-+ }, |
33644 |
-+ }; |
33645 |
-+ |
33646 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", acc, num); |
33647 |
-+ ASSERT_RETURN(ret == 0); |
33648 |
-+ |
33649 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33650 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33651 |
-+ 0, 0); |
33652 |
-+ ASSERT_EXIT(ret == -EPERM); |
33653 |
-+ })); |
33654 |
-+ ASSERT_RETURN(ret >= 0); |
33655 |
-+ |
33656 |
-+ /* |
33657 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33658 |
-+ * suitable OWN privilege overwrites TALK. |
33659 |
-+ */ |
33660 |
-+ |
33661 |
-+ access = (struct kdbus_policy_access){ |
33662 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33663 |
-+ .id = 0, |
33664 |
-+ .access = KDBUS_POLICY_OWN, |
33665 |
-+ }; |
33666 |
-+ |
33667 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33668 |
-+ ASSERT_RETURN(ret == 0); |
33669 |
-+ |
33670 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33671 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33672 |
-+ 0, 0); |
33673 |
-+ ASSERT_EXIT(ret >= 0); |
33674 |
-+ })); |
33675 |
-+ ASSERT_RETURN(ret >= 0); |
33676 |
-+ |
33677 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33678 |
-+ ASSERT_EXIT(ret >= 0); |
33679 |
-+ |
33680 |
-+ /* |
33681 |
-+ * Make sure the TALK cache is reset correctly when policies are |
33682 |
-+ * updated. |
33683 |
-+ */ |
33684 |
-+ |
33685 |
-+ access = (struct kdbus_policy_access){ |
33686 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33687 |
-+ .id = 0, |
33688 |
-+ .access = KDBUS_POLICY_TALK, |
33689 |
-+ }; |
33690 |
-+ |
33691 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33692 |
-+ ASSERT_RETURN(ret == 0); |
33693 |
-+ |
33694 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33695 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33696 |
-+ 0, 0); |
33697 |
-+ ASSERT_EXIT(ret >= 0); |
33698 |
-+ |
33699 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33700 |
-+ ASSERT_EXIT(ret >= 0); |
33701 |
-+ |
33702 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", |
33703 |
-+ NULL, 0); |
33704 |
-+ ASSERT_RETURN(ret == 0); |
33705 |
-+ |
33706 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33707 |
-+ 0, 0); |
33708 |
-+ ASSERT_EXIT(ret == -EPERM); |
33709 |
-+ })); |
33710 |
-+ ASSERT_RETURN(ret >= 0); |
33711 |
-+ |
33712 |
-+ /* |
33713 |
-+ * Make sure the TALK cache is reset correctly when policy holders |
33714 |
-+ * disconnect. |
33715 |
-+ */ |
33716 |
-+ |
33717 |
-+ access = (struct kdbus_policy_access){ |
33718 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33719 |
-+ .id = 0, |
33720 |
-+ .access = KDBUS_POLICY_OWN, |
33721 |
-+ }; |
33722 |
-+ |
33723 |
-+ conn = kdbus_hello_registrar(env->buspath, "com.example.c", |
33724 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33725 |
-+ ASSERT_RETURN(conn); |
33726 |
-+ |
33727 |
-+ ret = kdbus_conn_update_policy(conn, "com.example.c", &access, 1); |
33728 |
-+ ASSERT_RETURN(ret == 0); |
33729 |
-+ |
33730 |
-+ owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33731 |
-+ ASSERT_RETURN(owner); |
33732 |
-+ |
33733 |
-+ ret = kdbus_name_acquire(owner, "com.example.c", NULL); |
33734 |
-+ ASSERT_RETURN(ret >= 0); |
33735 |
-+ |
33736 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
33737 |
-+ struct kdbus_conn *unpriv; |
33738 |
-+ |
33739 |
-+ /* wait for parent to be finished */ |
33740 |
-+ sigemptyset(&sset); |
33741 |
-+ ret = sigsuspend(&sset); |
33742 |
-+ ASSERT_RETURN(ret == -1 && errno == EINTR); |
33743 |
-+ |
33744 |
-+ unpriv = kdbus_hello(env->buspath, 0, NULL, 0); |
33745 |
-+ ASSERT_RETURN(unpriv); |
33746 |
-+ |
33747 |
-+ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33748 |
-+ 0, 0); |
33749 |
-+ ASSERT_EXIT(ret >= 0); |
33750 |
-+ |
33751 |
-+ ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL); |
33752 |
-+ ASSERT_EXIT(ret >= 0); |
33753 |
-+ |
33754 |
-+ /* free policy holder */ |
33755 |
-+ kdbus_conn_free(conn); |
33756 |
-+ |
33757 |
-+ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33758 |
-+ 0, 0); |
33759 |
-+ ASSERT_EXIT(ret == -EPERM); |
33760 |
-+ |
33761 |
-+ kdbus_conn_free(unpriv); |
33762 |
-+ }), ({ |
33763 |
-+ /* make sure policy holder is only valid in child */ |
33764 |
-+ kdbus_conn_free(conn); |
33765 |
-+ kill(pid, SIGUSR1); |
33766 |
-+ })); |
33767 |
-+ ASSERT_RETURN(ret >= 0); |
33768 |
-+ |
33769 |
-+ |
33770 |
-+ /* |
33771 |
-+ * The following tests are necessary. |
33772 |
-+ */ |
33773 |
-+ |
33774 |
-+ ret = test_broadcast_after_policy_upload(env); |
33775 |
-+ ASSERT_RETURN(ret == 0); |
33776 |
-+ |
33777 |
-+ kdbus_conn_free(owner); |
33778 |
-+ |
33779 |
-+ /* |
33780 |
-+ * cleanup resources |
33781 |
-+ */ |
33782 |
-+ |
33783 |
-+ kdbus_conn_free(conn_b); |
33784 |
-+ kdbus_conn_free(conn_a); |
33785 |
-+ |
33786 |
-+ return TEST_OK; |
33787 |
-+} |
33788 |
-+ |
33789 |
-+int kdbus_test_policy_priv(struct kdbus_test_env *env) |
33790 |
-+{ |
33791 |
-+ pid_t pid; |
33792 |
-+ int ret; |
33793 |
-+ |
33794 |
-+ /* make sure to exit() if a child returns from fork() */ |
33795 |
-+ pid = getpid(); |
33796 |
-+ ret = test_policy_priv(env); |
33797 |
-+ if (pid != getpid()) |
33798 |
-+ exit(1); |
33799 |
-+ |
33800 |
-+ return ret; |
33801 |
-+} |
33802 |
-diff --git a/tools/testing/selftests/kdbus/test-policy.c b/tools/testing/selftests/kdbus/test-policy.c |
33803 |
-new file mode 100644 |
33804 |
-index 0000000..96d20d5 |
33805 |
---- /dev/null |
33806 |
-+++ b/tools/testing/selftests/kdbus/test-policy.c |
33807 |
-@@ -0,0 +1,80 @@ |
33808 |
-+#include <errno.h> |
33809 |
-+#include <stdio.h> |
33810 |
-+#include <string.h> |
33811 |
-+#include <fcntl.h> |
33812 |
-+#include <stdlib.h> |
33813 |
-+#include <stdint.h> |
33814 |
-+#include <stdbool.h> |
33815 |
-+#include <unistd.h> |
33816 |
-+ |
33817 |
-+#include "kdbus-test.h" |
33818 |
-+#include "kdbus-util.h" |
33819 |
-+#include "kdbus-enum.h" |
33820 |
-+ |
33821 |
-+int kdbus_test_policy(struct kdbus_test_env *env) |
33822 |
-+{ |
33823 |
-+ struct kdbus_conn *conn_a, *conn_b; |
33824 |
-+ struct kdbus_policy_access access; |
33825 |
-+ int ret; |
33826 |
-+ |
33827 |
-+ /* Invalid name */ |
33828 |
-+ conn_a = kdbus_hello_registrar(env->buspath, ".example.a", |
33829 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33830 |
-+ ASSERT_RETURN(conn_a == NULL); |
33831 |
-+ |
33832 |
-+ conn_a = kdbus_hello_registrar(env->buspath, "example", |
33833 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33834 |
-+ ASSERT_RETURN(conn_a == NULL); |
33835 |
-+ |
33836 |
-+ conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", |
33837 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33838 |
-+ ASSERT_RETURN(conn_a); |
33839 |
-+ |
33840 |
-+ conn_b = kdbus_hello_registrar(env->buspath, "com.example.b", |
33841 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33842 |
-+ ASSERT_RETURN(conn_b); |
33843 |
-+ |
33844 |
-+ /* |
33845 |
-+ * Verify there cannot be any duplicate entries, except for specific vs. |
33846 |
-+ * wildcard entries. |
33847 |
-+ */ |
33848 |
-+ |
33849 |
-+ access = (struct kdbus_policy_access){ |
33850 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33851 |
-+ .id = geteuid(), |
33852 |
-+ .access = KDBUS_POLICY_SEE, |
33853 |
-+ }; |
33854 |
-+ |
33855 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33856 |
-+ ASSERT_RETURN(ret == 0); |
33857 |
-+ |
33858 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); |
33859 |
-+ ASSERT_RETURN(ret == -EEXIST); |
33860 |
-+ |
33861 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.a.*", &access, 1); |
33862 |
-+ ASSERT_RETURN(ret == 0); |
33863 |
-+ |
33864 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a.*", &access, 1); |
33865 |
-+ ASSERT_RETURN(ret == -EEXIST); |
33866 |
-+ |
33867 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.*", &access, 1); |
33868 |
-+ ASSERT_RETURN(ret == 0); |
33869 |
-+ |
33870 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); |
33871 |
-+ ASSERT_RETURN(ret == 0); |
33872 |
-+ |
33873 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.*", &access, 1); |
33874 |
-+ ASSERT_RETURN(ret == -EEXIST); |
33875 |
-+ |
33876 |
-+ /* Invalid name */ |
33877 |
-+ ret = kdbus_conn_update_policy(conn_b, ".example.*", &access, 1); |
33878 |
-+ ASSERT_RETURN(ret == -EINVAL); |
33879 |
-+ |
33880 |
-+ ret = kdbus_conn_update_policy(conn_b, "example", &access, 1); |
33881 |
-+ ASSERT_RETURN(ret == -EINVAL); |
33882 |
-+ |
33883 |
-+ kdbus_conn_free(conn_b); |
33884 |
-+ kdbus_conn_free(conn_a); |
33885 |
-+ |
33886 |
-+ return TEST_OK; |
33887 |
-+} |
33888 |
-diff --git a/tools/testing/selftests/kdbus/test-sync.c b/tools/testing/selftests/kdbus/test-sync.c |
33889 |
-new file mode 100644 |
33890 |
-index 0000000..0655a54 |
33891 |
---- /dev/null |
33892 |
-+++ b/tools/testing/selftests/kdbus/test-sync.c |
33893 |
-@@ -0,0 +1,369 @@ |
33894 |
-+#include <stdio.h> |
33895 |
-+#include <string.h> |
33896 |
-+#include <time.h> |
33897 |
-+#include <fcntl.h> |
33898 |
-+#include <stdlib.h> |
33899 |
-+#include <stddef.h> |
33900 |
-+#include <unistd.h> |
33901 |
-+#include <stdint.h> |
33902 |
-+#include <errno.h> |
33903 |
-+#include <assert.h> |
33904 |
-+#include <pthread.h> |
33905 |
-+#include <stdbool.h> |
33906 |
-+#include <signal.h> |
33907 |
-+#include <sys/wait.h> |
33908 |
-+#include <sys/eventfd.h> |
33909 |
-+ |
33910 |
-+#include "kdbus-api.h" |
33911 |
-+#include "kdbus-test.h" |
33912 |
-+#include "kdbus-util.h" |
33913 |
-+#include "kdbus-enum.h" |
33914 |
-+ |
33915 |
-+static struct kdbus_conn *conn_a, *conn_b; |
33916 |
-+static unsigned int cookie = 0xdeadbeef; |
33917 |
-+ |
33918 |
-+static void nop_handler(int sig) {} |
33919 |
-+ |
33920 |
-+static int interrupt_sync(struct kdbus_conn *conn_src, |
33921 |
-+ struct kdbus_conn *conn_dst) |
33922 |
-+{ |
33923 |
-+ pid_t pid; |
33924 |
-+ int ret, status; |
33925 |
-+ struct kdbus_msg *msg = NULL; |
33926 |
-+ struct sigaction sa = { |
33927 |
-+ .sa_handler = nop_handler, |
33928 |
-+ .sa_flags = SA_NOCLDSTOP|SA_RESTART, |
33929 |
-+ }; |
33930 |
-+ |
33931 |
-+ cookie++; |
33932 |
-+ pid = fork(); |
33933 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
33934 |
-+ |
33935 |
-+ if (pid == 0) { |
33936 |
-+ ret = sigaction(SIGINT, &sa, NULL); |
33937 |
-+ ASSERT_EXIT(ret == 0); |
33938 |
-+ |
33939 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
33940 |
-+ KDBUS_MSG_EXPECT_REPLY, |
33941 |
-+ 100000000ULL, 0, conn_src->id, -1); |
33942 |
-+ ASSERT_EXIT(ret == -ETIMEDOUT); |
33943 |
-+ |
33944 |
-+ _exit(EXIT_SUCCESS); |
33945 |
-+ } |
33946 |
-+ |
33947 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
33948 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
33949 |
-+ |
33950 |
-+ kdbus_msg_free(msg); |
33951 |
-+ |
33952 |
-+ ret = kill(pid, SIGINT); |
33953 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
33954 |
-+ |
33955 |
-+ ret = waitpid(pid, &status, 0); |
33956 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
33957 |
-+ |
33958 |
-+ if (WIFSIGNALED(status)) |
33959 |
-+ return TEST_ERR; |
33960 |
-+ |
33961 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); |
33962 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
33963 |
-+ |
33964 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
33965 |
-+} |
33966 |
-+ |
33967 |
-+static int close_epipe_sync(const char *bus) |
33968 |
-+{ |
33969 |
-+ pid_t pid; |
33970 |
-+ int ret, status; |
33971 |
-+ struct kdbus_conn *conn_src; |
33972 |
-+ struct kdbus_conn *conn_dst; |
33973 |
-+ struct kdbus_msg *msg = NULL; |
33974 |
-+ |
33975 |
-+ conn_src = kdbus_hello(bus, 0, NULL, 0); |
33976 |
-+ ASSERT_RETURN(conn_src); |
33977 |
-+ |
33978 |
-+ ret = kdbus_add_match_empty(conn_src); |
33979 |
-+ ASSERT_RETURN(ret == 0); |
33980 |
-+ |
33981 |
-+ conn_dst = kdbus_hello(bus, 0, NULL, 0); |
33982 |
-+ ASSERT_RETURN(conn_dst); |
33983 |
-+ |
33984 |
-+ cookie++; |
33985 |
-+ pid = fork(); |
33986 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
33987 |
-+ |
33988 |
-+ if (pid == 0) { |
33989 |
-+ uint64_t dst_id; |
33990 |
-+ |
33991 |
-+ /* close our reference */ |
33992 |
-+ dst_id = conn_dst->id; |
33993 |
-+ kdbus_conn_free(conn_dst); |
33994 |
-+ |
33995 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
33996 |
-+ ASSERT_EXIT(ret == 0 && msg->cookie == cookie); |
33997 |
-+ ASSERT_EXIT(msg->src_id == dst_id); |
33998 |
-+ |
33999 |
-+ cookie++; |
34000 |
-+ ret = kdbus_msg_send_sync(conn_src, NULL, cookie, |
34001 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34002 |
-+ 100000000ULL, 0, dst_id, -1); |
34003 |
-+ ASSERT_EXIT(ret == -EPIPE); |
34004 |
-+ |
34005 |
-+ _exit(EXIT_SUCCESS); |
34006 |
-+ } |
34007 |
-+ |
34008 |
-+ ret = kdbus_msg_send(conn_dst, NULL, cookie, 0, 0, 0, |
34009 |
-+ KDBUS_DST_ID_BROADCAST); |
34010 |
-+ ASSERT_RETURN(ret == 0); |
34011 |
-+ |
34012 |
-+ cookie++; |
34013 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); |
34014 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34015 |
-+ |
34016 |
-+ kdbus_msg_free(msg); |
34017 |
-+ |
34018 |
-+ /* destroy connection */ |
34019 |
-+ kdbus_conn_free(conn_dst); |
34020 |
-+ kdbus_conn_free(conn_src); |
34021 |
-+ |
34022 |
-+ ret = waitpid(pid, &status, 0); |
34023 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34024 |
-+ |
34025 |
-+ if (!WIFEXITED(status)) |
34026 |
-+ return TEST_ERR; |
34027 |
-+ |
34028 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34029 |
-+} |
34030 |
-+ |
34031 |
-+static int cancel_fd_sync(struct kdbus_conn *conn_src, |
34032 |
-+ struct kdbus_conn *conn_dst) |
34033 |
-+{ |
34034 |
-+ pid_t pid; |
34035 |
-+ int cancel_fd; |
34036 |
-+ int ret, status; |
34037 |
-+ uint64_t counter = 1; |
34038 |
-+ struct kdbus_msg *msg = NULL; |
34039 |
-+ |
34040 |
-+ cancel_fd = eventfd(0, 0); |
34041 |
-+ ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); |
34042 |
-+ |
34043 |
-+ cookie++; |
34044 |
-+ pid = fork(); |
34045 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
34046 |
-+ |
34047 |
-+ if (pid == 0) { |
34048 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34049 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34050 |
-+ 100000000ULL, 0, conn_src->id, |
34051 |
-+ cancel_fd); |
34052 |
-+ ASSERT_EXIT(ret == -ECANCELED); |
34053 |
-+ |
34054 |
-+ _exit(EXIT_SUCCESS); |
34055 |
-+ } |
34056 |
-+ |
34057 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34058 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34059 |
-+ |
34060 |
-+ kdbus_msg_free(msg); |
34061 |
-+ |
34062 |
-+ ret = write(cancel_fd, &counter, sizeof(counter)); |
34063 |
-+ ASSERT_RETURN(ret == sizeof(counter)); |
34064 |
-+ |
34065 |
-+ ret = waitpid(pid, &status, 0); |
34066 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34067 |
-+ |
34068 |
-+ if (WIFSIGNALED(status)) |
34069 |
-+ return TEST_ERR; |
34070 |
-+ |
34071 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34072 |
-+} |
34073 |
-+ |
34074 |
-+static int no_cancel_sync(struct kdbus_conn *conn_src, |
34075 |
-+ struct kdbus_conn *conn_dst) |
34076 |
-+{ |
34077 |
-+ pid_t pid; |
34078 |
-+ int cancel_fd; |
34079 |
-+ int ret, status; |
34080 |
-+ struct kdbus_msg *msg = NULL; |
34081 |
-+ |
34082 |
-+ /* pass eventfd, but never signal it so it shouldn't have any effect */ |
34083 |
-+ |
34084 |
-+ cancel_fd = eventfd(0, 0); |
34085 |
-+ ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); |
34086 |
-+ |
34087 |
-+ cookie++; |
34088 |
-+ pid = fork(); |
34089 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
34090 |
-+ |
34091 |
-+ if (pid == 0) { |
34092 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34093 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34094 |
-+ 100000000ULL, 0, conn_src->id, |
34095 |
-+ cancel_fd); |
34096 |
-+ ASSERT_EXIT(ret == 0); |
34097 |
-+ |
34098 |
-+ _exit(EXIT_SUCCESS); |
34099 |
-+ } |
34100 |
-+ |
34101 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34102 |
-+ ASSERT_RETURN_VAL(ret == 0 && msg->cookie == cookie, -1); |
34103 |
-+ |
34104 |
-+ kdbus_msg_free(msg); |
34105 |
-+ |
34106 |
-+ ret = kdbus_msg_send_reply(conn_src, cookie, conn_dst->id); |
34107 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34108 |
-+ |
34109 |
-+ ret = waitpid(pid, &status, 0); |
34110 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34111 |
-+ |
34112 |
-+ if (WIFSIGNALED(status)) |
34113 |
-+ return -1; |
34114 |
-+ |
34115 |
-+ return (status == EXIT_SUCCESS) ? 0 : -1; |
34116 |
-+} |
34117 |
-+ |
34118 |
-+static void *run_thread_reply(void *data) |
34119 |
-+{ |
34120 |
-+ int ret; |
34121 |
-+ unsigned long status = TEST_OK; |
34122 |
-+ |
34123 |
-+ ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); |
34124 |
-+ if (ret < 0) |
34125 |
-+ goto exit_thread; |
34126 |
-+ |
34127 |
-+ kdbus_printf("Thread received message, sending reply ...\n"); |
34128 |
-+ |
34129 |
-+ /* using an unknown cookie must fail */ |
34130 |
-+ ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id); |
34131 |
-+ if (ret != -EBADSLT) { |
34132 |
-+ status = TEST_ERR; |
34133 |
-+ goto exit_thread; |
34134 |
-+ } |
34135 |
-+ |
34136 |
-+ ret = kdbus_msg_send_reply(conn_a, cookie, conn_b->id); |
34137 |
-+ if (ret != 0) { |
34138 |
-+ status = TEST_ERR; |
34139 |
-+ goto exit_thread; |
34140 |
-+ } |
34141 |
-+ |
34142 |
-+exit_thread: |
34143 |
-+ pthread_exit(NULL); |
34144 |
-+ return (void *) status; |
34145 |
-+} |
34146 |
-+ |
34147 |
-+int kdbus_test_sync_reply(struct kdbus_test_env *env) |
34148 |
-+{ |
34149 |
-+ unsigned long status; |
34150 |
-+ pthread_t thread; |
34151 |
-+ int ret; |
34152 |
-+ |
34153 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34154 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34155 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34156 |
-+ |
34157 |
-+ pthread_create(&thread, NULL, run_thread_reply, NULL); |
34158 |
-+ |
34159 |
-+ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34160 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34161 |
-+ 5000000000ULL, 0, conn_a->id, -1); |
34162 |
-+ |
34163 |
-+ pthread_join(thread, (void *) &status); |
34164 |
-+ ASSERT_RETURN(status == 0); |
34165 |
-+ ASSERT_RETURN(ret == 0); |
34166 |
-+ |
34167 |
-+ ret = interrupt_sync(conn_a, conn_b); |
34168 |
-+ ASSERT_RETURN(ret == 0); |
34169 |
-+ |
34170 |
-+ ret = close_epipe_sync(env->buspath); |
34171 |
-+ ASSERT_RETURN(ret == 0); |
34172 |
-+ |
34173 |
-+ ret = cancel_fd_sync(conn_a, conn_b); |
34174 |
-+ ASSERT_RETURN(ret == 0); |
34175 |
-+ |
34176 |
-+ ret = no_cancel_sync(conn_a, conn_b); |
34177 |
-+ ASSERT_RETURN(ret == 0); |
34178 |
-+ |
34179 |
-+ kdbus_printf("-- closing bus connections\n"); |
34180 |
-+ |
34181 |
-+ kdbus_conn_free(conn_a); |
34182 |
-+ kdbus_conn_free(conn_b); |
34183 |
-+ |
34184 |
-+ return TEST_OK; |
34185 |
-+} |
34186 |
-+ |
34187 |
-+#define BYEBYE_ME ((void*)0L) |
34188 |
-+#define BYEBYE_THEM ((void*)1L) |
34189 |
-+ |
34190 |
-+static void *run_thread_byebye(void *data) |
34191 |
-+{ |
34192 |
-+ struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; |
34193 |
-+ int ret; |
34194 |
-+ |
34195 |
-+ ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); |
34196 |
-+ if (ret == 0) { |
34197 |
-+ kdbus_printf("Thread received message, invoking BYEBYE ...\n"); |
34198 |
-+ kdbus_msg_recv(conn_a, NULL, NULL); |
34199 |
-+ if (data == BYEBYE_ME) |
34200 |
-+ kdbus_cmd_byebye(conn_b->fd, &cmd_byebye); |
34201 |
-+ else if (data == BYEBYE_THEM) |
34202 |
-+ kdbus_cmd_byebye(conn_a->fd, &cmd_byebye); |
34203 |
-+ } |
34204 |
-+ |
34205 |
-+ pthread_exit(NULL); |
34206 |
-+ return NULL; |
34207 |
-+} |
34208 |
-+ |
34209 |
-+int kdbus_test_sync_byebye(struct kdbus_test_env *env) |
34210 |
-+{ |
34211 |
-+ pthread_t thread; |
34212 |
-+ int ret; |
34213 |
-+ |
34214 |
-+ /* |
34215 |
-+ * This sends a synchronous message to a thread, which waits until it |
34216 |
-+ * received the message and then invokes BYEBYE on the *ORIGINAL* |
34217 |
-+ * connection. That is, on the same connection that synchronously waits |
34218 |
-+ * for an reply. |
34219 |
-+ * This should properly wake the connection up and cause ECONNRESET as |
34220 |
-+ * the connection is disconnected now. |
34221 |
-+ * |
34222 |
-+ * The second time, we do the same but invoke BYEBYE on the *TARGET* |
34223 |
-+ * connection. This should also wake up the synchronous sender as the |
34224 |
-+ * reply cannot be sent by a disconnected target. |
34225 |
-+ */ |
34226 |
-+ |
34227 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34228 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34229 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34230 |
-+ |
34231 |
-+ pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_ME); |
34232 |
-+ |
34233 |
-+ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34234 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34235 |
-+ 5000000000ULL, 0, conn_a->id, -1); |
34236 |
-+ |
34237 |
-+ ASSERT_RETURN(ret == -ECONNRESET); |
34238 |
-+ |
34239 |
-+ pthread_join(thread, NULL); |
34240 |
-+ |
34241 |
-+ kdbus_conn_free(conn_a); |
34242 |
-+ kdbus_conn_free(conn_b); |
34243 |
-+ |
34244 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34245 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34246 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34247 |
-+ |
34248 |
-+ pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_THEM); |
34249 |
-+ |
34250 |
-+ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34251 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34252 |
-+ 5000000000ULL, 0, conn_a->id, -1); |
34253 |
-+ |
34254 |
-+ ASSERT_RETURN(ret == -EPIPE); |
34255 |
-+ |
34256 |
-+ pthread_join(thread, NULL); |
34257 |
-+ |
34258 |
-+ kdbus_conn_free(conn_a); |
34259 |
-+ kdbus_conn_free(conn_b); |
34260 |
-+ |
34261 |
-+ return TEST_OK; |
34262 |
-+} |
34263 |
-diff --git a/tools/testing/selftests/kdbus/test-timeout.c b/tools/testing/selftests/kdbus/test-timeout.c |
34264 |
-new file mode 100644 |
34265 |
-index 0000000..cfd1930 |
34266 |
---- /dev/null |
34267 |
-+++ b/tools/testing/selftests/kdbus/test-timeout.c |
34268 |
-@@ -0,0 +1,99 @@ |
34269 |
-+#include <stdio.h> |
34270 |
-+#include <string.h> |
34271 |
-+#include <time.h> |
34272 |
-+#include <fcntl.h> |
34273 |
-+#include <stdlib.h> |
34274 |
-+#include <stddef.h> |
34275 |
-+#include <unistd.h> |
34276 |
-+#include <stdint.h> |
34277 |
-+#include <errno.h> |
34278 |
-+#include <assert.h> |
34279 |
-+#include <poll.h> |
34280 |
-+#include <stdbool.h> |
34281 |
-+ |
34282 |
-+#include "kdbus-api.h" |
34283 |
-+#include "kdbus-test.h" |
34284 |
-+#include "kdbus-util.h" |
34285 |
-+#include "kdbus-enum.h" |
34286 |
-+ |
34287 |
-+int timeout_msg_recv(struct kdbus_conn *conn, uint64_t *expected) |
34288 |
-+{ |
34289 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
34290 |
-+ struct kdbus_msg *msg; |
34291 |
-+ int ret; |
34292 |
-+ |
34293 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
34294 |
-+ if (ret < 0) { |
34295 |
-+ kdbus_printf("error receiving message: %d (%m)\n", ret); |
34296 |
-+ return ret; |
34297 |
-+ } |
34298 |
-+ |
34299 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
34300 |
-+ |
34301 |
-+ ASSERT_RETURN_VAL(msg->payload_type == KDBUS_PAYLOAD_KERNEL, -EINVAL); |
34302 |
-+ ASSERT_RETURN_VAL(msg->src_id == KDBUS_SRC_ID_KERNEL, -EINVAL); |
34303 |
-+ ASSERT_RETURN_VAL(msg->dst_id == conn->id, -EINVAL); |
34304 |
-+ |
34305 |
-+ *expected &= ~(1ULL << msg->cookie_reply); |
34306 |
-+ kdbus_printf("Got message timeout for cookie %llu\n", |
34307 |
-+ msg->cookie_reply); |
34308 |
-+ |
34309 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
34310 |
-+ if (ret < 0) |
34311 |
-+ return ret; |
34312 |
-+ |
34313 |
-+ return 0; |
34314 |
-+} |
34315 |
-+ |
34316 |
-+int kdbus_test_timeout(struct kdbus_test_env *env) |
34317 |
-+{ |
34318 |
-+ struct kdbus_conn *conn_a, *conn_b; |
34319 |
-+ struct pollfd fd; |
34320 |
-+ int ret, i, n_msgs = 4; |
34321 |
-+ uint64_t expected = 0; |
34322 |
-+ uint64_t cookie = 0xdeadbeef; |
34323 |
-+ |
34324 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34325 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34326 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34327 |
-+ |
34328 |
-+ fd.fd = conn_b->fd; |
34329 |
-+ |
34330 |
-+ /* |
34331 |
-+ * send messages that expect a reply (within 100 msec), |
34332 |
-+ * but never answer it. |
34333 |
-+ */ |
34334 |
-+ for (i = 0; i < n_msgs; i++, cookie++) { |
34335 |
-+ kdbus_printf("Sending message with cookie %llu ...\n", |
34336 |
-+ (unsigned long long)cookie); |
34337 |
-+ ASSERT_RETURN(kdbus_msg_send(conn_b, NULL, cookie, |
34338 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34339 |
-+ (i + 1) * 100ULL * 1000000ULL, 0, |
34340 |
-+ conn_a->id) == 0); |
34341 |
-+ expected |= 1ULL << cookie; |
34342 |
-+ } |
34343 |
-+ |
34344 |
-+ for (;;) { |
34345 |
-+ fd.events = POLLIN | POLLPRI | POLLHUP; |
34346 |
-+ fd.revents = 0; |
34347 |
-+ |
34348 |
-+ ret = poll(&fd, 1, (n_msgs + 1) * 100); |
34349 |
-+ if (ret == 0) |
34350 |
-+ kdbus_printf("--- timeout\n"); |
34351 |
-+ if (ret <= 0) |
34352 |
-+ break; |
34353 |
-+ |
34354 |
-+ if (fd.revents & POLLIN) |
34355 |
-+ ASSERT_RETURN(!timeout_msg_recv(conn_b, &expected)); |
34356 |
-+ |
34357 |
-+ if (expected == 0) |
34358 |
-+ break; |
34359 |
-+ } |
34360 |
-+ |
34361 |
-+ ASSERT_RETURN(expected == 0); |
34362 |
-+ |
34363 |
-+ kdbus_conn_free(conn_a); |
34364 |
-+ kdbus_conn_free(conn_b); |
34365 |
-+ |
34366 |
-+ return TEST_OK; |
34367 |
-+} |