1 |
commit: 20ba937d586c2e0e21e4f9bf37a1a2935c996147 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Jun 26 22:36:56 2015 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri Jun 26 22:36:56 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=20ba937d |
7 |
|
8 |
Add the kernel-level IPC implementation kdbus as an optional patch. |
9 |
|
10 |
0000_README | 4 + |
11 |
5015_kdbus-4.1-rc1.patch | 34698 +++++++++++++++++++++++++++++++++++++++++++++ |
12 |
2 files changed, 34702 insertions(+) |
13 |
|
14 |
diff --git a/0000_README b/0000_README |
15 |
index 69f60dc..d33ec2f 100644 |
16 |
--- a/0000_README |
17 |
+++ b/0000_README |
18 |
@@ -82,3 +82,7 @@ Desc: Kernel patch enables gcc < v4.9 optimizations for additional CPUs. |
19 |
Patch: 5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch |
20 |
From: https://github.com/graysky2/kernel_gcc_patch/ |
21 |
Desc: Kernel patch enables gcc >= v4.9 optimizations for additional CPUs. |
22 |
+ |
23 |
+Patch: 5015_kdbus-4.1-rc1.patch |
24 |
+From: https://lkml.org |
25 |
+Desc: Kernel-level IPC implementation |
26 |
|
27 |
diff --git a/5015_kdbus-4.1-rc1.patch b/5015_kdbus-4.1-rc1.patch |
28 |
new file mode 100644 |
29 |
index 0000000..a5169bd |
30 |
--- /dev/null |
31 |
+++ b/5015_kdbus-4.1-rc1.patch |
32 |
@@ -0,0 +1,34698 @@ |
33 |
+diff --git a/Documentation/Makefile b/Documentation/Makefile |
34 |
+index 6883a1b..5e3fde6 100644 |
35 |
+--- a/Documentation/Makefile |
36 |
++++ b/Documentation/Makefile |
37 |
+@@ -1,4 +1,4 @@ |
38 |
+ subdir-y := accounting arm auxdisplay blackfin connector \ |
39 |
+- filesystems filesystems ia64 laptops mic misc-devices \ |
40 |
++ filesystems filesystems ia64 kdbus laptops mic misc-devices \ |
41 |
+ networking pcmcia prctl ptp spi timers vDSO video4linux \ |
42 |
+ watchdog |
43 |
+diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt |
44 |
+index 8136e1f..54e091e 100644 |
45 |
+--- a/Documentation/ioctl/ioctl-number.txt |
46 |
++++ b/Documentation/ioctl/ioctl-number.txt |
47 |
+@@ -292,6 +292,7 @@ Code Seq#(hex) Include File Comments |
48 |
+ 0x92 00-0F drivers/usb/mon/mon_bin.c |
49 |
+ 0x93 60-7F linux/auto_fs.h |
50 |
+ 0x94 all fs/btrfs/ioctl.h |
51 |
++0x95 all uapi/linux/kdbus.h kdbus IPC driver |
52 |
+ 0x97 00-7F fs/ceph/ioctl.h Ceph file system |
53 |
+ 0x99 00-0F 537-Addinboard driver |
54 |
+ <mailto:buk@××××××××.de> |
55 |
+diff --git a/Documentation/kdbus/.gitignore b/Documentation/kdbus/.gitignore |
56 |
+new file mode 100644 |
57 |
+index 0000000..b4a77cc |
58 |
+--- /dev/null |
59 |
++++ b/Documentation/kdbus/.gitignore |
60 |
+@@ -0,0 +1,2 @@ |
61 |
++*.7 |
62 |
++*.html |
63 |
+diff --git a/Documentation/kdbus/Makefile b/Documentation/kdbus/Makefile |
64 |
+new file mode 100644 |
65 |
+index 0000000..af87641 |
66 |
+--- /dev/null |
67 |
++++ b/Documentation/kdbus/Makefile |
68 |
+@@ -0,0 +1,40 @@ |
69 |
++DOCS := \ |
70 |
++ kdbus.xml \ |
71 |
++ kdbus.bus.xml \ |
72 |
++ kdbus.connection.xml \ |
73 |
++ kdbus.endpoint.xml \ |
74 |
++ kdbus.fs.xml \ |
75 |
++ kdbus.item.xml \ |
76 |
++ kdbus.match.xml \ |
77 |
++ kdbus.message.xml \ |
78 |
++ kdbus.name.xml \ |
79 |
++ kdbus.policy.xml \ |
80 |
++ kdbus.pool.xml |
81 |
++ |
82 |
++XMLFILES := $(addprefix $(obj)/,$(DOCS)) |
83 |
++MANFILES := $(patsubst %.xml, %.7, $(XMLFILES)) |
84 |
++HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES)) |
85 |
++ |
86 |
++XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl --skip-validation |
87 |
++ |
88 |
++quiet_cmd_db2man = MAN $@ |
89 |
++ cmd_db2man = xmlto man $(XMLTO_ARGS) -o $(obj) $< |
90 |
++%.7: %.xml |
91 |
++ @(which xmlto > /dev/null 2>&1) || \ |
92 |
++ (echo "*** You need to install xmlto ***"; \ |
93 |
++ exit 1) |
94 |
++ $(call cmd,db2man) |
95 |
++ |
96 |
++quiet_cmd_db2html = HTML $@ |
97 |
++ cmd_db2html = xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $< |
98 |
++%.html: %.xml |
99 |
++ @(which xmlto > /dev/null 2>&1) || \ |
100 |
++ (echo "*** You need to install xmlto ***"; \ |
101 |
++ exit 1) |
102 |
++ $(call cmd,db2html) |
103 |
++ |
104 |
++mandocs: $(MANFILES) |
105 |
++ |
106 |
++htmldocs: $(HTMLFILES) |
107 |
++ |
108 |
++clean-files := $(MANFILES) $(HTMLFILES) |
109 |
+diff --git a/Documentation/kdbus/kdbus.bus.xml b/Documentation/kdbus/kdbus.bus.xml |
110 |
+new file mode 100644 |
111 |
+index 0000000..4b9a0ac |
112 |
+--- /dev/null |
113 |
++++ b/Documentation/kdbus/kdbus.bus.xml |
114 |
+@@ -0,0 +1,359 @@ |
115 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
116 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
117 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
118 |
++ |
119 |
++<refentry id="kdbus.bus"> |
120 |
++ |
121 |
++ <refentryinfo> |
122 |
++ <title>kdbus.bus</title> |
123 |
++ <productname>kdbus.bus</productname> |
124 |
++ </refentryinfo> |
125 |
++ |
126 |
++ <refmeta> |
127 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
128 |
++ <manvolnum>7</manvolnum> |
129 |
++ </refmeta> |
130 |
++ |
131 |
++ <refnamediv> |
132 |
++ <refname>kdbus.bus</refname> |
133 |
++ <refpurpose>kdbus bus</refpurpose> |
134 |
++ </refnamediv> |
135 |
++ |
136 |
++ <refsect1> |
137 |
++ <title>Description</title> |
138 |
++ |
139 |
++ <para> |
140 |
++ A bus is a resource that is shared between connections in order to |
141 |
++ transmit messages (see |
142 |
++ <citerefentry> |
143 |
++ <refentrytitle>kdbus.message</refentrytitle> |
144 |
++ <manvolnum>7</manvolnum> |
145 |
++ </citerefentry>). |
146 |
++ Each bus is independent, and operations on the bus will not have any |
147 |
++ effect on other buses. A bus is a management entity that controls the |
148 |
++ addresses of its connections, their policies and message transactions |
149 |
++ performed via this bus. |
150 |
++ </para> |
151 |
++ <para> |
152 |
++ Each bus is bound to the mount instance it was created on. It has a |
153 |
++ custom name that is unique across all buses of a domain. In |
154 |
++ <citerefentry> |
155 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
156 |
++ <manvolnum>7</manvolnum> |
157 |
++ </citerefentry> |
158 |
++ a bus is presented as a directory. No operations can be performed on |
159 |
++ the bus itself; instead you need to perform the operations on an endpoint |
160 |
++ associated with the bus. Endpoints are accessible as files underneath the |
161 |
++ bus directory. A default endpoint called <constant>bus</constant> is |
162 |
++ provided on each bus. |
163 |
++ </para> |
164 |
++ <para> |
165 |
++ Bus names may be chosen freely except for one restriction: the name must |
166 |
++ be prefixed with the numeric effective UID of the creator and a dash. This |
167 |
++ is required to avoid namespace clashes between different users. When |
168 |
++ creating a bus, the name that is passed in must be properly formatted, or |
169 |
++ the kernel will refuse creation of the bus. Example: |
170 |
++ <literal>1047-foobar</literal> is an acceptable name for a bus |
171 |
++ registered by a user with UID 1047. However, |
172 |
++ <literal>1024-foobar</literal> is not, and neither is |
173 |
++ <literal>foobar</literal>. The UID must be provided in the |
174 |
++ user-namespace of the bus owner. |
175 |
++ </para> |
176 |
++ <para> |
177 |
++ To create a new bus, you need to open the control file of a domain and |
178 |
++ employ the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. The control |
179 |
++ file descriptor that was used to issue |
180 |
++ <constant>KDBUS_CMD_BUS_MAKE</constant> must not previously have been |
181 |
++ used for any other control-ioctl and must be kept open for the entire |
182 |
++ life-time of the created bus. Closing it will immediately cleanup the |
183 |
++ entire bus and all its associated resources and endpoints. Every control |
184 |
++ file descriptor can only be used to create a single new bus; from that |
185 |
++ point on, it is not used for any further communication until the final |
186 |
++ <citerefentry> |
187 |
++ <refentrytitle>close</refentrytitle> |
188 |
++ <manvolnum>2</manvolnum> |
189 |
++ </citerefentry> |
190 |
++ . |
191 |
++ </para> |
192 |
++ <para> |
193 |
++ Each bus will generate a random, 128-bit UUID upon creation. This UUID |
194 |
++ will be returned to creators of connections through |
195 |
++ <varname>kdbus_cmd_hello.id128</varname> and can be used to uniquely |
196 |
++ identify buses, even across different machines or containers. The UUID |
197 |
++ will have its variant bits set to <literal>DCE</literal>, and denote |
198 |
++ version 4 (random). For more details on UUIDs, see <ulink |
199 |
++ url="https://en.wikipedia.org/wiki/Universally_unique_identifier"> |
200 |
++ the Wikipedia article on UUIDs</ulink>. |
201 |
++ </para> |
202 |
++ |
203 |
++ </refsect1> |
204 |
++ |
205 |
++ <refsect1> |
206 |
++ <title>Creating buses</title> |
207 |
++ <para> |
208 |
++ To create a new bus, the <constant>KDBUS_CMD_BUS_MAKE</constant> |
209 |
++ command is used. It takes a <type>struct kdbus_cmd</type> argument. |
210 |
++ </para> |
211 |
++ <programlisting> |
212 |
++struct kdbus_cmd { |
213 |
++ __u64 size; |
214 |
++ __u64 flags; |
215 |
++ __u64 return_flags; |
216 |
++ struct kdbus_item items[0]; |
217 |
++}; |
218 |
++ </programlisting> |
219 |
++ |
220 |
++ <para>The fields in this struct are described below.</para> |
221 |
++ |
222 |
++ <variablelist> |
223 |
++ <varlistentry> |
224 |
++ <term><varname>size</varname></term> |
225 |
++ <listitem><para> |
226 |
++ The overall size of the struct, including its items. |
227 |
++ </para></listitem> |
228 |
++ </varlistentry> |
229 |
++ |
230 |
++ <varlistentry> |
231 |
++ <term><varname>flags</varname></term> |
232 |
++ <listitem><para>The flags for creation.</para> |
233 |
++ <variablelist> |
234 |
++ <varlistentry> |
235 |
++ <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term> |
236 |
++ <listitem> |
237 |
++ <para>Make the bus file group-accessible.</para> |
238 |
++ </listitem> |
239 |
++ </varlistentry> |
240 |
++ |
241 |
++ <varlistentry> |
242 |
++ <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term> |
243 |
++ <listitem> |
244 |
++ <para>Make the bus file world-accessible.</para> |
245 |
++ </listitem> |
246 |
++ </varlistentry> |
247 |
++ |
248 |
++ <varlistentry> |
249 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
250 |
++ <listitem> |
251 |
++ <para> |
252 |
++ Requests a set of valid flags for this ioctl. When this bit is |
253 |
++ set, no action is taken; the ioctl will return |
254 |
++ <errorcode>0</errorcode>, and the <varname>flags</varname> |
255 |
++ field will have all bits set that are valid for this command. |
256 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
257 |
++ cleared by the operation. |
258 |
++ </para> |
259 |
++ </listitem> |
260 |
++ </varlistentry> |
261 |
++ </variablelist> |
262 |
++ </listitem> |
263 |
++ </varlistentry> |
264 |
++ |
265 |
++ <varlistentry> |
266 |
++ <term><varname>return_flags</varname></term> |
267 |
++ <listitem><para> |
268 |
++ Flags returned by the kernel. Currently unused and always set to |
269 |
++ <constant>0</constant> by the kernel. |
270 |
++ </para></listitem> |
271 |
++ </varlistentry> |
272 |
++ |
273 |
++ <varlistentry> |
274 |
++ <term><varname>items</varname></term> |
275 |
++ <listitem> |
276 |
++ <para> |
277 |
++ The following items (see |
278 |
++ <citerefentry> |
279 |
++ <refentrytitle>kdbus.item</refentrytitle> |
280 |
++ <manvolnum>7</manvolnum> |
281 |
++ </citerefentry>) |
282 |
++ are expected for <constant>KDBUS_CMD_BUS_MAKE</constant>. |
283 |
++ </para> |
284 |
++ <variablelist> |
285 |
++ <varlistentry> |
286 |
++ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
287 |
++ <listitem> |
288 |
++ <para> |
289 |
++ Contains a null-terminated string that identifies the |
290 |
++ bus. The name must be unique across the kdbus domain and |
291 |
++ must start with the effective UID of the caller, followed by |
292 |
++ a '<literal>-</literal>' (dash). This item is mandatory. |
293 |
++ </para> |
294 |
++ </listitem> |
295 |
++ </varlistentry> |
296 |
++ |
297 |
++ <varlistentry> |
298 |
++ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
299 |
++ <listitem> |
300 |
++ <para> |
301 |
++ Bus-wide bloom parameters passed in a |
302 |
++ <type>struct kdbus_bloom_parameter</type>. These settings are |
303 |
++ copied back to new connections verbatim. This item is |
304 |
++ mandatory. See |
305 |
++ <citerefentry> |
306 |
++ <refentrytitle>kdbus.item</refentrytitle> |
307 |
++ <manvolnum>7</manvolnum> |
308 |
++ </citerefentry> |
309 |
++ for a more detailed description of this item. |
310 |
++ </para> |
311 |
++ </listitem> |
312 |
++ </varlistentry> |
313 |
++ |
314 |
++ <varlistentry> |
315 |
++ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
316 |
++ <listitem> |
317 |
++ <para> |
318 |
++ An optional item that contains a set of required attach flags |
319 |
++ that connections must allow. This item is used as a |
320 |
++ negotiation measure during connection creation. If connections |
321 |
++ do not satisfy the bus requirements, they are not allowed on |
322 |
++ the bus. If not set, the bus does not require any metadata to |
323 |
++ be attached; in this case connections are free to set their |
324 |
++ own attach flags. |
325 |
++ </para> |
326 |
++ </listitem> |
327 |
++ </varlistentry> |
328 |
++ |
329 |
++ <varlistentry> |
330 |
++ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
331 |
++ <listitem> |
332 |
++ <para> |
333 |
++ An optional item that contains a set of attach flags that are |
334 |
++ returned to connections when they query the bus creator |
335 |
++ metadata. If not set, no metadata is returned. |
336 |
++ </para> |
337 |
++ </listitem> |
338 |
++ </varlistentry> |
339 |
++ |
340 |
++ <varlistentry> |
341 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
342 |
++ <listitem><para> |
343 |
++ With this item, programs can <emphasis>probe</emphasis> the |
344 |
++ kernel for known item types. See |
345 |
++ <citerefentry> |
346 |
++ <refentrytitle>kdbus.item</refentrytitle> |
347 |
++ <manvolnum>7</manvolnum> |
348 |
++ </citerefentry> |
349 |
++ for more details. |
350 |
++ </para></listitem> |
351 |
++ </varlistentry> |
352 |
++ </variablelist> |
353 |
++ </listitem> |
354 |
++ </varlistentry> |
355 |
++ </variablelist> |
356 |
++ |
357 |
++ <para> |
358 |
++ Unrecognized items are rejected, and the ioctl will fail with |
359 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
360 |
++ </para> |
361 |
++ </refsect1> |
362 |
++ |
363 |
++ <refsect1> |
364 |
++ <title>Return value</title> |
365 |
++ <para> |
366 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
367 |
++ on error, <errorcode>-1</errorcode> is returned, and |
368 |
++ <varname>errno</varname> is set to indicate the error. |
369 |
++ If the issued ioctl is illegal for the file descriptor used, |
370 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
371 |
++ </para> |
372 |
++ |
373 |
++ <refsect2> |
374 |
++ <title> |
375 |
++ <constant>KDBUS_CMD_BUS_MAKE</constant> may fail with the following |
376 |
++ errors |
377 |
++ </title> |
378 |
++ |
379 |
++ <variablelist> |
380 |
++ <varlistentry> |
381 |
++ <term><constant>EBADMSG</constant></term> |
382 |
++ <listitem><para> |
383 |
++ A mandatory item is missing. |
384 |
++ </para></listitem> |
385 |
++ </varlistentry> |
386 |
++ |
387 |
++ <varlistentry> |
388 |
++ <term><constant>EINVAL</constant></term> |
389 |
++ <listitem><para> |
390 |
++ The flags supplied in the <constant>struct kdbus_cmd</constant> |
391 |
++ are invalid or the supplied name does not start with the current |
392 |
++ UID and a '<literal>-</literal>' (dash). |
393 |
++ </para></listitem> |
394 |
++ </varlistentry> |
395 |
++ |
396 |
++ <varlistentry> |
397 |
++ <term><constant>EEXIST</constant></term> |
398 |
++ <listitem><para> |
399 |
++ A bus of that name already exists. |
400 |
++ </para></listitem> |
401 |
++ </varlistentry> |
402 |
++ |
403 |
++ <varlistentry> |
404 |
++ <term><constant>ESHUTDOWN</constant></term> |
405 |
++ <listitem><para> |
406 |
++ The kdbus mount instance for the bus was already shut down. |
407 |
++ </para></listitem> |
408 |
++ </varlistentry> |
409 |
++ |
410 |
++ <varlistentry> |
411 |
++ <term><constant>EMFILE</constant></term> |
412 |
++ <listitem><para> |
413 |
++ The maximum number of buses for the current user is exhausted. |
414 |
++ </para></listitem> |
415 |
++ </varlistentry> |
416 |
++ </variablelist> |
417 |
++ </refsect2> |
418 |
++ </refsect1> |
419 |
++ |
420 |
++ <refsect1> |
421 |
++ <title>See Also</title> |
422 |
++ <simplelist type="inline"> |
423 |
++ <member> |
424 |
++ <citerefentry> |
425 |
++ <refentrytitle>kdbus</refentrytitle> |
426 |
++ <manvolnum>7</manvolnum> |
427 |
++ </citerefentry> |
428 |
++ </member> |
429 |
++ <member> |
430 |
++ <citerefentry> |
431 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
432 |
++ <manvolnum>7</manvolnum> |
433 |
++ </citerefentry> |
434 |
++ </member> |
435 |
++ <member> |
436 |
++ <citerefentry> |
437 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
438 |
++ <manvolnum>7</manvolnum> |
439 |
++ </citerefentry> |
440 |
++ </member> |
441 |
++ <member> |
442 |
++ <citerefentry> |
443 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
444 |
++ <manvolnum>7</manvolnum> |
445 |
++ </citerefentry> |
446 |
++ </member> |
447 |
++ <member> |
448 |
++ <citerefentry> |
449 |
++ <refentrytitle>kdbus.item</refentrytitle> |
450 |
++ <manvolnum>7</manvolnum> |
451 |
++ </citerefentry> |
452 |
++ </member> |
453 |
++ <member> |
454 |
++ <citerefentry> |
455 |
++ <refentrytitle>kdbus.message</refentrytitle> |
456 |
++ <manvolnum>7</manvolnum> |
457 |
++ </citerefentry> |
458 |
++ </member> |
459 |
++ <member> |
460 |
++ <citerefentry> |
461 |
++ <refentrytitle>kdbus.name</refentrytitle> |
462 |
++ <manvolnum>7</manvolnum> |
463 |
++ </citerefentry> |
464 |
++ </member> |
465 |
++ <member> |
466 |
++ <citerefentry> |
467 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
468 |
++ <manvolnum>7</manvolnum> |
469 |
++ </citerefentry> |
470 |
++ </member> |
471 |
++ </simplelist> |
472 |
++ </refsect1> |
473 |
++</refentry> |
474 |
+diff --git a/Documentation/kdbus/kdbus.connection.xml b/Documentation/kdbus/kdbus.connection.xml |
475 |
+new file mode 100644 |
476 |
+index 0000000..cefb419 |
477 |
+--- /dev/null |
478 |
++++ b/Documentation/kdbus/kdbus.connection.xml |
479 |
+@@ -0,0 +1,1250 @@ |
480 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
481 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
482 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
483 |
++ |
484 |
++<refentry id="kdbus.connection"> |
485 |
++ |
486 |
++ <refentryinfo> |
487 |
++ <title>kdbus.connection</title> |
488 |
++ <productname>kdbus.connection</productname> |
489 |
++ </refentryinfo> |
490 |
++ |
491 |
++ <refmeta> |
492 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
493 |
++ <manvolnum>7</manvolnum> |
494 |
++ </refmeta> |
495 |
++ |
496 |
++ <refnamediv> |
497 |
++ <refname>kdbus.connection</refname> |
498 |
++ <refpurpose>kdbus connection</refpurpose> |
499 |
++ </refnamediv> |
500 |
++ |
501 |
++ <refsect1> |
502 |
++ <title>Description</title> |
503 |
++ |
504 |
++ <para> |
505 |
++ Connections are identified by their <emphasis>connection ID</emphasis>, |
506 |
++ internally implemented as a <type>uint64_t</type> counter. |
507 |
++ The IDs of every newly created bus start at <constant>1</constant>, and |
508 |
++ every new connection will increment the counter by <constant>1</constant>. |
509 |
++ The IDs are not reused. |
510 |
++ </para> |
511 |
++ <para> |
512 |
++ In higher level tools, the user visible representation of a connection is |
513 |
++ defined by the D-Bus protocol specification as |
514 |
++ <constant>":1.<ID>"</constant>. |
515 |
++ </para> |
516 |
++ <para> |
517 |
++ Messages with a specific <type>uint64_t</type> destination ID are |
518 |
++ directly delivered to the connection with the corresponding ID. Signal |
519 |
++ messages (see |
520 |
++ <citerefentry> |
521 |
++ <refentrytitle>kdbus.message</refentrytitle> |
522 |
++ <manvolnum>7</manvolnum> |
523 |
++ </citerefentry>) |
524 |
++ may be addressed to the special destination ID |
525 |
++ <constant>KDBUS_DST_ID_BROADCAST</constant> (~0ULL) and will then |
526 |
++ potentially be delivered to all currently active connections on the bus. |
527 |
++ However, in order to receive any signal messages, clients must subscribe |
528 |
++ to them by installing a match (see |
529 |
++ <citerefentry> |
530 |
++ <refentrytitle>kdbus.match</refentrytitle> |
531 |
++ <manvolnum>7</manvolnum> |
532 |
++ </citerefentry>). |
533 |
++ </para> |
534 |
++ <para> |
535 |
++ Messages synthesized and sent directly by the kernel will carry the |
536 |
++ special source ID <constant>KDBUS_SRC_ID_KERNEL</constant> (0). |
537 |
++ </para> |
538 |
++ <para> |
539 |
++ In addition to the unique <type>uint64_t</type> connection ID, |
540 |
++ established connections can request the ownership of |
541 |
++ <emphasis>well-known names</emphasis>, under which they can be found and |
542 |
++ addressed by other bus clients. A well-known name is associated with one |
543 |
++ and only one connection at a time. See |
544 |
++ <citerefentry> |
545 |
++ <refentrytitle>kdbus.name</refentrytitle> |
546 |
++ <manvolnum>7</manvolnum> |
547 |
++ </citerefentry> |
548 |
++ on name acquisition, the name registry, and the validity of names. |
549 |
++ </para> |
550 |
++ <para> |
551 |
++ Messages can specify the special destination ID |
552 |
++ <constant>KDBUS_DST_ID_NAME</constant> (0) and carry a well-known name |
553 |
++ in the message data. Such a message is delivered to the destination |
554 |
++ connection which owns that well-known name. |
555 |
++ </para> |
556 |
++ |
557 |
++ <programlisting><![CDATA[ |
558 |
++ +-------------------------------------------------------------------------+ |
559 |
++ | +---------------+ +---------------------------+ | |
560 |
++ | | Connection | | Message | -----------------+ | |
561 |
++ | | :1.22 | --> | src: 22 | | | |
562 |
++ | | | | dst: 25 | | | |
563 |
++ | | | | | | | |
564 |
++ | | | | | | | |
565 |
++ | | | +---------------------------+ | | |
566 |
++ | | | | | |
567 |
++ | | | <--------------------------------------+ | | |
568 |
++ | +---------------+ | | | |
569 |
++ | | | | |
570 |
++ | +---------------+ +---------------------------+ | | | |
571 |
++ | | Connection | | Message | -----+ | | |
572 |
++ | | :1.25 | --> | src: 25 | | | |
573 |
++ | | | | dst: 0xffffffffffffffff | -------------+ | | |
574 |
++ | | | | (KDBUS_DST_ID_BROADCAST) | | | | |
575 |
++ | | | | | ---------+ | | | |
576 |
++ | | | +---------------------------+ | | | | |
577 |
++ | | | | | | | |
578 |
++ | | | <--------------------------------------------------+ | |
579 |
++ | +---------------+ | | | |
580 |
++ | | | | |
581 |
++ | +---------------+ +---------------------------+ | | | |
582 |
++ | | Connection | | Message | --+ | | | |
583 |
++ | | :1.55 | --> | src: 55 | | | | | |
584 |
++ | | | | dst: 0 / org.foo.bar | | | | | |
585 |
++ | | | | | | | | | |
586 |
++ | | | | | | | | | |
587 |
++ | | | +---------------------------+ | | | | |
588 |
++ | | | | | | | |
589 |
++ | | | <------------------------------------------+ | | |
590 |
++ | +---------------+ | | | |
591 |
++ | | | | |
592 |
++ | +---------------+ | | | |
593 |
++ | | Connection | | | | |
594 |
++ | | :1.81 | | | | |
595 |
++ | | org.foo.bar | | | | |
596 |
++ | | | | | | |
597 |
++ | | | | | | |
598 |
++ | | | <-----------------------------------+ | | |
599 |
++ | | | | | |
600 |
++ | | | <----------------------------------------------+ | |
601 |
++ | +---------------+ | |
602 |
++ +-------------------------------------------------------------------------+ |
603 |
++ ]]></programlisting> |
604 |
++ </refsect1> |
605 |
++ |
606 |
++ <refsect1> |
607 |
++ <title>Privileged connections</title> |
608 |
++ <para> |
609 |
++ A connection is considered <emphasis>privileged</emphasis> if the user |
610 |
++ it was created by is the same that created the bus, or if the creating |
611 |
++ task had <constant>CAP_IPC_OWNER</constant> set when it called |
612 |
++ <constant>KDBUS_CMD_HELLO</constant> (see below). |
613 |
++ </para> |
614 |
++ <para> |
615 |
++ Privileged connections have permission to employ certain restricted |
616 |
++ functions and commands, which are explained below and in other kdbus |
617 |
++ man-pages. |
618 |
++ </para> |
619 |
++ </refsect1> |
620 |
++ |
621 |
++ <refsect1> |
622 |
++ <title>Activator and policy holder connection</title> |
623 |
++ <para> |
624 |
++ An <emphasis>activator</emphasis> connection is a placeholder for a |
625 |
++ <emphasis>well-known name</emphasis>. Messages sent to such a connection |
626 |
++ can be used to start an implementer connection, which will then get all |
627 |
++ the messages from the activator copied over. An activator connection |
628 |
++ cannot be used to send any message. |
629 |
++ </para> |
630 |
++ <para> |
631 |
++ A <emphasis>policy holder</emphasis> connection only installs a policy |
632 |
++ for one or more names. These policy entries are kept active as long as |
633 |
++ the connection is alive, and are removed once it terminates. Such a |
634 |
++ policy connection type can be used to deploy restrictions for names that |
635 |
++ are not yet active on the bus. A policy holder connection cannot be used |
636 |
++ to send any message. |
637 |
++ </para> |
638 |
++ <para> |
639 |
++ The creation of activator or policy holder connections is restricted to |
640 |
++ privileged users on the bus (see above). |
641 |
++ </para> |
642 |
++ </refsect1> |
643 |
++ |
644 |
++ <refsect1> |
645 |
++ <title>Monitor connections</title> |
646 |
++ <para> |
647 |
++ Monitors are eavesdropping connections that receive all the traffic on the |
648 |
++ bus, but is invisible to other connections. Such connections have all |
649 |
++ properties of any other, regular connection, except for the following |
650 |
++ details: |
651 |
++ </para> |
652 |
++ |
653 |
++ <itemizedlist> |
654 |
++ <listitem><para> |
655 |
++ They will get every message sent over the bus, both unicasts and |
656 |
++ broadcasts. |
657 |
++ </para></listitem> |
658 |
++ |
659 |
++ <listitem><para> |
660 |
++ Installing matches for signal messages is neither necessary |
661 |
++ nor allowed. |
662 |
++ </para></listitem> |
663 |
++ |
664 |
++ <listitem><para> |
665 |
++ They cannot send messages or be directly addressed as receiver. |
666 |
++ </para></listitem> |
667 |
++ |
668 |
++ <listitem><para> |
669 |
++ They cannot own well-known names. Therefore, they also can't operate as |
670 |
++ activators. |
671 |
++ </para></listitem> |
672 |
++ |
673 |
++ <listitem><para> |
674 |
++ Their creation and destruction will not cause |
675 |
++ <constant>KDBUS_ITEM_ID_{ADD,REMOVE}</constant> (see |
676 |
++ <citerefentry> |
677 |
++ <refentrytitle>kdbus.item</refentrytitle> |
678 |
++ <manvolnum>7</manvolnum> |
679 |
++ </citerefentry>). |
680 |
++ </para></listitem> |
681 |
++ |
682 |
++ <listitem><para> |
683 |
++ They are not listed with their unique name in name registry dumps |
684 |
++ (see <constant>KDBUS_CMD_NAME_LIST</constant> in |
685 |
++ <citerefentry> |
686 |
++ <refentrytitle>kdbus.name</refentrytitle> |
687 |
++ <manvolnum>7</manvolnum> |
688 |
++ </citerefentry>), so other connections cannot detect the presence of |
689 |
++ a monitor. |
690 |
++ </para></listitem> |
691 |
++ </itemizedlist> |
692 |
++ <para> |
693 |
++ The creation of monitor connections is restricted to privileged users on |
694 |
++ the bus (see above). |
695 |
++ </para> |
696 |
++ </refsect1> |
697 |
++ |
698 |
++ <refsect1> |
699 |
++ <title>Creating connections</title> |
700 |
++ <para> |
701 |
++ A connection to a bus is created by opening an endpoint file (see |
702 |
++ <citerefentry> |
703 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
704 |
++ <manvolnum>7</manvolnum> |
705 |
++ </citerefentry>) |
706 |
++ of a bus and becoming an active client with the |
707 |
++ <constant>KDBUS_CMD_HELLO</constant> ioctl. Every connection has a unique |
708 |
++ identifier on the bus and can address messages to every other connection |
709 |
++ on the same bus by using the peer's connection ID as the destination. |
710 |
++ </para> |
711 |
++ <para> |
712 |
++ The <constant>KDBUS_CMD_HELLO</constant> ioctl takes a <type>struct |
713 |
++ kdbus_cmd_hello</type> as argument. |
714 |
++ </para> |
715 |
++ |
716 |
++ <programlisting> |
717 |
++struct kdbus_cmd_hello { |
718 |
++ __u64 size; |
719 |
++ __u64 flags; |
720 |
++ __u64 return_flags; |
721 |
++ __u64 attach_flags_send; |
722 |
++ __u64 attach_flags_recv; |
723 |
++ __u64 bus_flags; |
724 |
++ __u64 id; |
725 |
++ __u64 pool_size; |
726 |
++ __u64 offset; |
727 |
++ __u8 id128[16]; |
728 |
++ struct kdbus_item items[0]; |
729 |
++}; |
730 |
++ </programlisting> |
731 |
++ |
732 |
++ <para>The fields in this struct are described below.</para> |
733 |
++ |
734 |
++ <variablelist> |
735 |
++ <varlistentry> |
736 |
++ <term><varname>size</varname></term> |
737 |
++ <listitem><para> |
738 |
++ The overall size of the struct, including its items. |
739 |
++ </para></listitem> |
740 |
++ </varlistentry> |
741 |
++ |
742 |
++ <varlistentry> |
743 |
++ <term><varname>flags</varname></term> |
744 |
++ <listitem> |
745 |
++ <para>Flags to apply to this connection</para> |
746 |
++ <variablelist> |
747 |
++ <varlistentry> |
748 |
++ <term><constant>KDBUS_HELLO_ACCEPT_FD</constant></term> |
749 |
++ <listitem> |
750 |
++ <para> |
751 |
++ When this flag is set, the connection can be sent file |
752 |
++ descriptors as message payload of unicast messages. If it's |
753 |
++ not set, an attempt to send file descriptors will result in |
754 |
++ <constant>-ECOMM</constant> on the sender's side. |
755 |
++ </para> |
756 |
++ </listitem> |
757 |
++ </varlistentry> |
758 |
++ |
759 |
++ <varlistentry> |
760 |
++ <term><constant>KDBUS_HELLO_ACTIVATOR</constant></term> |
761 |
++ <listitem> |
762 |
++ <para> |
763 |
++ Make this connection an activator (see above). With this bit |
764 |
++ set, an item of type <constant>KDBUS_ITEM_NAME</constant> has |
765 |
++ to be attached. This item describes the well-known name this |
766 |
++ connection should be an activator for. |
767 |
++ A connection can not be an activator and a policy holder at |
768 |
++ the same time time, so this bit is not allowed together with |
769 |
++ <constant>KDBUS_HELLO_POLICY_HOLDER</constant>. |
770 |
++ </para> |
771 |
++ </listitem> |
772 |
++ </varlistentry> |
773 |
++ |
774 |
++ <varlistentry> |
775 |
++ <term><constant>KDBUS_HELLO_POLICY_HOLDER</constant></term> |
776 |
++ <listitem> |
777 |
++ <para> |
778 |
++ Make this connection a policy holder (see above). With this |
779 |
++ bit set, an item of type <constant>KDBUS_ITEM_NAME</constant> |
780 |
++ has to be attached. This item describes the well-known name |
781 |
++ this connection should hold a policy for. |
782 |
++ A connection can not be an activator and a policy holder at |
783 |
++ the same time time, so this bit is not allowed together with |
784 |
++ <constant>KDBUS_HELLO_ACTIVATOR</constant>. |
785 |
++ </para> |
786 |
++ </listitem> |
787 |
++ </varlistentry> |
788 |
++ |
789 |
++ <varlistentry> |
790 |
++ <term><constant>KDBUS_HELLO_MONITOR</constant></term> |
791 |
++ <listitem> |
792 |
++ <para> |
793 |
++ Make this connection a monitor connection (see above). |
794 |
++ </para> |
795 |
++ <para> |
796 |
++ This flag can only be set by privileged bus connections. See |
797 |
++ below for more information. |
798 |
++ A connection can not be monitor and an activator or a policy |
799 |
++ holder at the same time time, so this bit is not allowed |
800 |
++ together with <constant>KDBUS_HELLO_ACTIVATOR</constant> or |
801 |
++ <constant>KDBUS_HELLO_POLICY_HOLDER</constant>. |
802 |
++ </para> |
803 |
++ </listitem> |
804 |
++ </varlistentry> |
805 |
++ |
806 |
++ <varlistentry> |
807 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
808 |
++ <listitem> |
809 |
++ <para> |
810 |
++ Requests a set of valid flags for this ioctl. When this bit is |
811 |
++ set, no action is taken; the ioctl will return |
812 |
++ <errorcode>0</errorcode>, and the <varname>flags</varname> |
813 |
++ field will have all bits set that are valid for this command. |
814 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
815 |
++ cleared by the operation. |
816 |
++ </para> |
817 |
++ </listitem> |
818 |
++ </varlistentry> |
819 |
++ </variablelist> |
820 |
++ </listitem> |
821 |
++ </varlistentry> |
822 |
++ |
823 |
++ <varlistentry> |
824 |
++ <term><varname>return_flags</varname></term> |
825 |
++ <listitem><para> |
826 |
++ Flags returned by the kernel. Currently unused and always set to |
827 |
++ <constant>0</constant> by the kernel. |
828 |
++ </para></listitem> |
829 |
++ </varlistentry> |
830 |
++ |
831 |
++ <varlistentry> |
832 |
++ <term><varname>attach_flags_send</varname></term> |
833 |
++ <listitem><para> |
834 |
++ Set the bits for metadata this connection permits to be sent to the |
835 |
++ receiving peer. Only metadata items that are both allowed to be sent |
836 |
++ by the sender and that are requested by the receiver will be attached |
837 |
++ to the message. Note, however, that the bus may optionally require |
838 |
++ some of those bits to be set. If the match fails, the ioctl will fail |
839 |
++ with <varname>errno</varname> set to |
840 |
++ <constant>ECONNREFUSED</constant>. In either case, when returning the |
841 |
++ field will be set to the mask of metadata items that are enforced by |
842 |
++ the bus with the <constant>KDBUS_FLAGS_KERNEL</constant> bit set as |
843 |
++ well. |
844 |
++ </para></listitem> |
845 |
++ </varlistentry> |
846 |
++ |
847 |
++ <varlistentry> |
848 |
++ <term><varname>attach_flags_recv</varname></term> |
849 |
++ <listitem><para> |
850 |
++ Request the attachment of metadata for each message received by this |
851 |
++ connection. See |
852 |
++ <citerefentry> |
853 |
++ <refentrytitle>kdbus</refentrytitle> |
854 |
++ <manvolnum>7</manvolnum> |
855 |
++ </citerefentry> |
856 |
++ for information about metadata, and |
857 |
++ <citerefentry> |
858 |
++ <refentrytitle>kdbus.item</refentrytitle> |
859 |
++ <manvolnum>7</manvolnum> |
860 |
++ </citerefentry> |
861 |
++ regarding items in general. |
862 |
++ </para></listitem> |
863 |
++ </varlistentry> |
864 |
++ |
865 |
++ <varlistentry> |
866 |
++ <term><varname>bus_flags</varname></term> |
867 |
++ <listitem><para> |
868 |
++ Upon successful completion of the ioctl, this member will contain the |
869 |
++ flags of the bus it connected to. |
870 |
++ </para></listitem> |
871 |
++ </varlistentry> |
872 |
++ |
873 |
++ <varlistentry> |
874 |
++ <term><varname>id</varname></term> |
875 |
++ <listitem><para> |
876 |
++ Upon successful completion of the command, this member will contain |
877 |
++ the numerical ID of the new connection. |
878 |
++ </para></listitem> |
879 |
++ </varlistentry> |
880 |
++ |
881 |
++ <varlistentry> |
882 |
++ <term><varname>pool_size</varname></term> |
883 |
++ <listitem><para> |
884 |
++ The size of the communication pool, in bytes. The pool can be |
885 |
++ accessed by calling |
886 |
++ <citerefentry> |
887 |
++ <refentrytitle>mmap</refentrytitle> |
888 |
++ <manvolnum>2</manvolnum> |
889 |
++ </citerefentry> |
890 |
++ on the file descriptor that was used to issue the |
891 |
++ <constant>KDBUS_CMD_HELLO</constant> ioctl. |
892 |
++ The pool size of a connection must be greater than |
893 |
++ <constant>0</constant> and a multiple of |
894 |
++ <constant>PAGE_SIZE</constant>. See |
895 |
++ <citerefentry> |
896 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
897 |
++ <manvolnum>7</manvolnum> |
898 |
++ </citerefentry> |
899 |
++ for more information. |
900 |
++ </para></listitem> |
901 |
++ </varlistentry> |
902 |
++ |
903 |
++ <varlistentry> |
904 |
++ <term><varname>offset</varname></term> |
905 |
++ <listitem><para> |
906 |
++ The kernel will return the offset in the pool where returned details |
907 |
++ will be stored. See below. |
908 |
++ </para></listitem> |
909 |
++ </varlistentry> |
910 |
++ |
911 |
++ <varlistentry> |
912 |
++ <term><varname>id128</varname></term> |
913 |
++ <listitem><para> |
914 |
++ Upon successful completion of the ioctl, this member will contain the |
915 |
++ <emphasis>128-bit UUID</emphasis> of the connected bus. |
916 |
++ </para></listitem> |
917 |
++ </varlistentry> |
918 |
++ |
919 |
++ <varlistentry> |
920 |
++ <term><varname>items</varname></term> |
921 |
++ <listitem> |
922 |
++ <para> |
923 |
++ Variable list of items containing optional additional information. |
924 |
++ The following items are currently expected/valid: |
925 |
++ </para> |
926 |
++ <variablelist> |
927 |
++ <varlistentry> |
928 |
++ <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term> |
929 |
++ <listitem> |
930 |
++ <para> |
931 |
++ Contains a string that describes this connection, so it can |
932 |
++ be identified later. |
933 |
++ </para> |
934 |
++ </listitem> |
935 |
++ </varlistentry> |
936 |
++ |
937 |
++ <varlistentry> |
938 |
++ <term><constant>KDBUS_ITEM_NAME</constant></term> |
939 |
++ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
940 |
++ <listitem> |
941 |
++ <para> |
942 |
++ For activators and policy holders only, combinations of |
943 |
++ these two items describe policy access entries. See |
944 |
++ <citerefentry> |
945 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
946 |
++ <manvolnum>7</manvolnum> |
947 |
++ </citerefentry> |
948 |
++ for further details. |
949 |
++ </para> |
950 |
++ </listitem> |
951 |
++ </varlistentry> |
952 |
++ |
953 |
++ <varlistentry> |
954 |
++ <term><constant>KDBUS_ITEM_CREDS</constant></term> |
955 |
++ <term><constant>KDBUS_ITEM_PIDS</constant></term> |
956 |
++ <term><constant>KDBUS_ITEM_SECLABEL</constant></term> |
957 |
++ <listitem> |
958 |
++ <para> |
959 |
++ Privileged bus users may submit these types in order to |
960 |
++ create connections with faked credentials. This information |
961 |
++ will be returned when peer information is queried by |
962 |
++ <constant>KDBUS_CMD_CONN_INFO</constant>. See below for more |
963 |
++ information on retrieving information on connections. |
964 |
++ </para> |
965 |
++ </listitem> |
966 |
++ </varlistentry> |
967 |
++ |
968 |
++ <varlistentry> |
969 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
970 |
++ <listitem><para> |
971 |
++ With this item, programs can <emphasis>probe</emphasis> the |
972 |
++ kernel for known item types. See |
973 |
++ <citerefentry> |
974 |
++ <refentrytitle>kdbus.item</refentrytitle> |
975 |
++ <manvolnum>7</manvolnum> |
976 |
++ </citerefentry> |
977 |
++ for more details. |
978 |
++ </para></listitem> |
979 |
++ </varlistentry> |
980 |
++ </variablelist> |
981 |
++ |
982 |
++ <para> |
983 |
++ Unrecognized items are rejected, and the ioctl will fail with |
984 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
985 |
++ </para> |
986 |
++ </listitem> |
987 |
++ </varlistentry> |
988 |
++ </variablelist> |
989 |
++ |
990 |
++ <para> |
991 |
++ At the offset returned in the <varname>offset</varname> field of |
992 |
++ <type>struct kdbus_cmd_hello</type>, the kernel will store items |
993 |
++ of the following types: |
994 |
++ </para> |
995 |
++ |
996 |
++ <variablelist> |
997 |
++ <varlistentry> |
998 |
++ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
999 |
++ <listitem> |
1000 |
++ <para> |
1001 |
++ Bloom filter parameter as defined by the bus creator. |
1002 |
++ </para> |
1003 |
++ </listitem> |
1004 |
++ </varlistentry> |
1005 |
++ </variablelist> |
1006 |
++ |
1007 |
++ <para> |
1008 |
++ The offset in the pool has to be freed with the |
1009 |
++ <constant>KDBUS_CMD_FREE</constant> ioctl. See |
1010 |
++ <citerefentry> |
1011 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
1012 |
++ <manvolnum>7</manvolnum> |
1013 |
++ </citerefentry> |
1014 |
++ for further information. |
1015 |
++ </para> |
1016 |
++ </refsect1> |
1017 |
++ |
1018 |
++ <refsect1> |
1019 |
++ <title>Retrieving information on a connection</title> |
1020 |
++ <para> |
1021 |
++ The <constant>KDBUS_CMD_CONN_INFO</constant> ioctl can be used to |
1022 |
++ retrieve credentials and properties of the initial creator of a |
1023 |
++ connection. This ioctl uses the following struct. |
1024 |
++ </para> |
1025 |
++ |
1026 |
++ <programlisting> |
1027 |
++struct kdbus_cmd_info { |
1028 |
++ __u64 size; |
1029 |
++ __u64 flags; |
1030 |
++ __u64 return_flags; |
1031 |
++ __u64 id; |
1032 |
++ __u64 attach_flags; |
1033 |
++ __u64 offset; |
1034 |
++ __u64 info_size; |
1035 |
++ struct kdbus_item items[0]; |
1036 |
++}; |
1037 |
++ </programlisting> |
1038 |
++ |
1039 |
++ <variablelist> |
1040 |
++ <varlistentry> |
1041 |
++ <term><varname>size</varname></term> |
1042 |
++ <listitem><para> |
1043 |
++ The overall size of the struct, including its items. |
1044 |
++ </para></listitem> |
1045 |
++ </varlistentry> |
1046 |
++ |
1047 |
++ <varlistentry> |
1048 |
++ <term><varname>flags</varname></term> |
1049 |
++ <listitem><para> |
1050 |
++ Currently, no flags are supported. |
1051 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1052 |
++ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1053 |
++ and the <varname>flags</varname> field is set to |
1054 |
++ <constant>0</constant>. |
1055 |
++ </para></listitem> |
1056 |
++ </varlistentry> |
1057 |
++ |
1058 |
++ <varlistentry> |
1059 |
++ <term><varname>return_flags</varname></term> |
1060 |
++ <listitem><para> |
1061 |
++ Flags returned by the kernel. Currently unused and always set to |
1062 |
++ <constant>0</constant> by the kernel. |
1063 |
++ </para></listitem> |
1064 |
++ </varlistentry> |
1065 |
++ |
1066 |
++ <varlistentry> |
1067 |
++ <term><varname>id</varname></term> |
1068 |
++ <listitem><para> |
1069 |
++ The numerical ID of the connection for which information is to be |
1070 |
++ retrieved. If set to a non-zero value, the |
1071 |
++ <constant>KDBUS_ITEM_OWNED_NAME</constant> item is ignored. |
1072 |
++ </para></listitem> |
1073 |
++ </varlistentry> |
1074 |
++ |
1075 |
++ <varlistentry> |
1076 |
++ <term><varname>attach_flags</varname></term> |
1077 |
++ <listitem><para> |
1078 |
++ Specifies which metadata items should be attached to the answer. See |
1079 |
++ <citerefentry> |
1080 |
++ <refentrytitle>kdbus.message</refentrytitle> |
1081 |
++ <manvolnum>7</manvolnum> |
1082 |
++ </citerefentry>. |
1083 |
++ </para></listitem> |
1084 |
++ </varlistentry> |
1085 |
++ |
1086 |
++ <varlistentry> |
1087 |
++ <term><varname>offset</varname></term> |
1088 |
++ <listitem><para> |
1089 |
++ When the ioctl returns, this field will contain the offset of the |
1090 |
++ connection information inside the caller's pool. See |
1091 |
++ <citerefentry> |
1092 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
1093 |
++ <manvolnum>7</manvolnum> |
1094 |
++ </citerefentry> |
1095 |
++ for further information. |
1096 |
++ </para></listitem> |
1097 |
++ </varlistentry> |
1098 |
++ |
1099 |
++ <varlistentry> |
1100 |
++ <term><varname>info_size</varname></term> |
1101 |
++ <listitem><para> |
1102 |
++ The kernel will return the size of the returned information, so |
1103 |
++ applications can optionally |
1104 |
++ <citerefentry> |
1105 |
++ <refentrytitle>mmap</refentrytitle> |
1106 |
++ <manvolnum>2</manvolnum> |
1107 |
++ </citerefentry> |
1108 |
++ specific parts of the pool. See |
1109 |
++ <citerefentry> |
1110 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
1111 |
++ <manvolnum>7</manvolnum> |
1112 |
++ </citerefentry> |
1113 |
++ for further information. |
1114 |
++ </para></listitem> |
1115 |
++ </varlistentry> |
1116 |
++ |
1117 |
++ <varlistentry> |
1118 |
++ <term><varname>items</varname></term> |
1119 |
++ <listitem> |
1120 |
++ <para> |
1121 |
++ The following items are expected for |
1122 |
++ <constant>KDBUS_CMD_CONN_INFO</constant>. |
1123 |
++ </para> |
1124 |
++ <variablelist> |
1125 |
++ <varlistentry> |
1126 |
++ <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term> |
1127 |
++ <listitem> |
1128 |
++ <para> |
1129 |
++ Contains the well-known name of the connection to look up as. |
1130 |
++ This item is mandatory if the <varname>id</varname> field is |
1131 |
++ set to 0. |
1132 |
++ </para> |
1133 |
++ </listitem> |
1134 |
++ </varlistentry> |
1135 |
++ |
1136 |
++ <varlistentry> |
1137 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1138 |
++ <listitem><para> |
1139 |
++ With this item, programs can <emphasis>probe</emphasis> the |
1140 |
++ kernel for known item types. See |
1141 |
++ <citerefentry> |
1142 |
++ <refentrytitle>kdbus.item</refentrytitle> |
1143 |
++ <manvolnum>7</manvolnum> |
1144 |
++ </citerefentry> |
1145 |
++ for more details. |
1146 |
++ </para></listitem> |
1147 |
++ </varlistentry> |
1148 |
++ </variablelist> |
1149 |
++ <para> |
1150 |
++ Unrecognized items are rejected, and the ioctl will fail with |
1151 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1152 |
++ </para> |
1153 |
++ </listitem> |
1154 |
++ </varlistentry> |
1155 |
++ </variablelist> |
1156 |
++ |
1157 |
++ <para> |
1158 |
++ When the ioctl returns, the following struct will be stored in the |
1159 |
++ caller's pool at <varname>offset</varname>. The fields in this struct |
1160 |
++ are described below. |
1161 |
++ </para> |
1162 |
++ |
1163 |
++ <programlisting> |
1164 |
++struct kdbus_info { |
1165 |
++ __u64 size; |
1166 |
++ __u64 id; |
1167 |
++ __u64 flags; |
1168 |
++ struct kdbus_item items[0]; |
1169 |
++}; |
1170 |
++ </programlisting> |
1171 |
++ |
1172 |
++ <variablelist> |
1173 |
++ <varlistentry> |
1174 |
++ <term><varname>size</varname></term> |
1175 |
++ <listitem><para> |
1176 |
++ The overall size of the struct, including its items. |
1177 |
++ </para></listitem> |
1178 |
++ </varlistentry> |
1179 |
++ |
1180 |
++ <varlistentry> |
1181 |
++ <term><varname>id</varname></term> |
1182 |
++ <listitem><para> |
1183 |
++ The connection's unique ID. |
1184 |
++ </para></listitem> |
1185 |
++ </varlistentry> |
1186 |
++ |
1187 |
++ <varlistentry> |
1188 |
++ <term><varname>flags</varname></term> |
1189 |
++ <listitem><para> |
1190 |
++ The connection's flags as specified when it was created. |
1191 |
++ </para></listitem> |
1192 |
++ </varlistentry> |
1193 |
++ |
1194 |
++ <varlistentry> |
1195 |
++ <term><varname>items</varname></term> |
1196 |
++ <listitem> |
1197 |
++ <para> |
1198 |
++ Depending on the <varname>flags</varname> field in |
1199 |
++ <type>struct kdbus_cmd_info</type>, items of types |
1200 |
++ <constant>KDBUS_ITEM_OWNED_NAME</constant> and |
1201 |
++ <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant> may follow here. |
1202 |
++ <constant>KDBUS_ITEM_NEGOTIATE</constant> is also allowed. |
1203 |
++ </para> |
1204 |
++ </listitem> |
1205 |
++ </varlistentry> |
1206 |
++ </variablelist> |
1207 |
++ |
1208 |
++ <para> |
1209 |
++ Once the caller is finished with parsing the return buffer, it needs to |
1210 |
++ employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in |
1211 |
++ order to free the buffer part. See |
1212 |
++ <citerefentry> |
1213 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
1214 |
++ <manvolnum>7</manvolnum> |
1215 |
++ </citerefentry> |
1216 |
++ for further information. |
1217 |
++ </para> |
1218 |
++ </refsect1> |
1219 |
++ |
1220 |
++ <refsect1> |
1221 |
++ <title>Getting information about a connection's bus creator</title> |
1222 |
++ <para> |
1223 |
++ The <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> ioctl takes the same |
1224 |
++ struct as <constant>KDBUS_CMD_CONN_INFO</constant>, but is used to |
1225 |
++ retrieve information about the creator of the bus the connection is |
1226 |
++ attached to. The metadata returned by this call is collected during the |
1227 |
++ creation of the bus and is never altered afterwards, so it provides |
1228 |
++ pristine information on the task that created the bus, at the moment when |
1229 |
++ it did so. |
1230 |
++ </para> |
1231 |
++ <para> |
1232 |
++ In response to this call, a slice in the connection's pool is allocated |
1233 |
++ and filled with an object of type <type>struct kdbus_info</type>, |
1234 |
++ pointed to by the ioctl's <varname>offset</varname> field. |
1235 |
++ </para> |
1236 |
++ |
1237 |
++ <programlisting> |
1238 |
++struct kdbus_info { |
1239 |
++ __u64 size; |
1240 |
++ __u64 id; |
1241 |
++ __u64 flags; |
1242 |
++ struct kdbus_item items[0]; |
1243 |
++}; |
1244 |
++ </programlisting> |
1245 |
++ |
1246 |
++ <variablelist> |
1247 |
++ <varlistentry> |
1248 |
++ <term><varname>size</varname></term> |
1249 |
++ <listitem><para> |
1250 |
++ The overall size of the struct, including its items. |
1251 |
++ </para></listitem> |
1252 |
++ </varlistentry> |
1253 |
++ |
1254 |
++ <varlistentry> |
1255 |
++ <term><varname>id</varname></term> |
1256 |
++ <listitem><para> |
1257 |
++ The bus ID. |
1258 |
++ </para></listitem> |
1259 |
++ </varlistentry> |
1260 |
++ |
1261 |
++ <varlistentry> |
1262 |
++ <term><varname>flags</varname></term> |
1263 |
++ <listitem><para> |
1264 |
++ The bus flags as specified when it was created. |
1265 |
++ </para></listitem> |
1266 |
++ </varlistentry> |
1267 |
++ |
1268 |
++ <varlistentry> |
1269 |
++ <term><varname>items</varname></term> |
1270 |
++ <listitem> |
1271 |
++ <para> |
1272 |
++ Metadata information is stored in items here. The item list |
1273 |
++ contains a <constant>KDBUS_ITEM_MAKE_NAME</constant> item that |
1274 |
++ indicates the bus name of the calling connection. |
1275 |
++ <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed to probe |
1276 |
++ for known item types. |
1277 |
++ </para> |
1278 |
++ </listitem> |
1279 |
++ </varlistentry> |
1280 |
++ </variablelist> |
1281 |
++ |
1282 |
++ <para> |
1283 |
++ Once the caller is finished with parsing the return buffer, it needs to |
1284 |
++ employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in |
1285 |
++ order to free the buffer part. See |
1286 |
++ <citerefentry> |
1287 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
1288 |
++ <manvolnum>7</manvolnum> |
1289 |
++ </citerefentry> |
1290 |
++ for further information. |
1291 |
++ </para> |
1292 |
++ </refsect1> |
1293 |
++ |
1294 |
++ <refsect1> |
1295 |
++ <title>Updating connection details</title> |
1296 |
++ <para> |
1297 |
++ Some of a connection's details can be updated with the |
1298 |
++ <constant>KDBUS_CMD_CONN_UPDATE</constant> ioctl, using the file |
1299 |
++ descriptor that was used to create the connection. The update command |
1300 |
++ uses the following struct. |
1301 |
++ </para> |
1302 |
++ |
1303 |
++ <programlisting> |
1304 |
++struct kdbus_cmd { |
1305 |
++ __u64 size; |
1306 |
++ __u64 flags; |
1307 |
++ __u64 return_flags; |
1308 |
++ struct kdbus_item items[0]; |
1309 |
++}; |
1310 |
++ </programlisting> |
1311 |
++ |
1312 |
++ <variablelist> |
1313 |
++ <varlistentry> |
1314 |
++ <term><varname>size</varname></term> |
1315 |
++ <listitem><para> |
1316 |
++ The overall size of the struct, including its items. |
1317 |
++ </para></listitem> |
1318 |
++ </varlistentry> |
1319 |
++ |
1320 |
++ <varlistentry> |
1321 |
++ <term><varname>flags</varname></term> |
1322 |
++ <listitem><para> |
1323 |
++ Currently, no flags are supported. |
1324 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1325 |
++ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1326 |
++ and the <varname>flags</varname> field is set to |
1327 |
++ <constant>0</constant>. |
1328 |
++ </para></listitem> |
1329 |
++ </varlistentry> |
1330 |
++ |
1331 |
++ <varlistentry> |
1332 |
++ <term><varname>return_flags</varname></term> |
1333 |
++ <listitem><para> |
1334 |
++ Flags returned by the kernel. Currently unused and always set to |
1335 |
++ <constant>0</constant> by the kernel. |
1336 |
++ </para></listitem> |
1337 |
++ </varlistentry> |
1338 |
++ |
1339 |
++ <varlistentry> |
1340 |
++ <term><varname>items</varname></term> |
1341 |
++ <listitem> |
1342 |
++ <para> |
1343 |
++ Items to describe the connection details to be updated. The |
1344 |
++ following item types are supported. |
1345 |
++ </para> |
1346 |
++ <variablelist> |
1347 |
++ <varlistentry> |
1348 |
++ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
1349 |
++ <listitem> |
1350 |
++ <para> |
1351 |
++ Supply a new set of metadata items that this connection |
1352 |
++ permits to be sent along with messages. |
1353 |
++ </para> |
1354 |
++ </listitem> |
1355 |
++ </varlistentry> |
1356 |
++ |
1357 |
++ <varlistentry> |
1358 |
++ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
1359 |
++ <listitem> |
1360 |
++ <para> |
1361 |
++ Supply a new set of metadata items that this connection |
1362 |
++ requests to be attached to each message. |
1363 |
++ </para> |
1364 |
++ </listitem> |
1365 |
++ </varlistentry> |
1366 |
++ |
1367 |
++ <varlistentry> |
1368 |
++ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1369 |
++ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1370 |
++ <listitem> |
1371 |
++ <para> |
1372 |
++ Policy holder connections may supply a new set of policy |
1373 |
++ information with these items. For other connection types, |
1374 |
++ <constant>EOPNOTSUPP</constant> is returned in |
1375 |
++ <varname>errno</varname>. |
1376 |
++ </para> |
1377 |
++ </listitem> |
1378 |
++ </varlistentry> |
1379 |
++ |
1380 |
++ <varlistentry> |
1381 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1382 |
++ <listitem><para> |
1383 |
++ With this item, programs can <emphasis>probe</emphasis> the |
1384 |
++ kernel for known item types. See |
1385 |
++ <citerefentry> |
1386 |
++ <refentrytitle>kdbus.item</refentrytitle> |
1387 |
++ <manvolnum>7</manvolnum> |
1388 |
++ </citerefentry> |
1389 |
++ for more details. |
1390 |
++ </para></listitem> |
1391 |
++ </varlistentry> |
1392 |
++ </variablelist> |
1393 |
++ |
1394 |
++ <para> |
1395 |
++ Unrecognized items are rejected, and the ioctl will fail with |
1396 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1397 |
++ </para> |
1398 |
++ </listitem> |
1399 |
++ </varlistentry> |
1400 |
++ </variablelist> |
1401 |
++ </refsect1> |
1402 |
++ |
1403 |
++ <refsect1> |
1404 |
++ <title>Termination of connections</title> |
1405 |
++ <para> |
1406 |
++ A connection can be terminated by simply calling |
1407 |
++ <citerefentry> |
1408 |
++ <refentrytitle>close</refentrytitle> |
1409 |
++ <manvolnum>2</manvolnum> |
1410 |
++ </citerefentry> |
1411 |
++ on its file descriptor. All pending incoming messages will be discarded, |
1412 |
++ and the memory allocated by the pool will be freed. |
1413 |
++ </para> |
1414 |
++ |
1415 |
++ <para> |
1416 |
++ An alternative way of closing down a connection is via the |
1417 |
++ <constant>KDBUS_CMD_BYEBYE</constant> ioctl. This ioctl will succeed only |
1418 |
++ if the message queue of the connection is empty at the time of closing; |
1419 |
++ otherwise, the ioctl will fail with <varname>errno</varname> set to |
1420 |
++ <constant>EBUSY</constant>. When this ioctl returns |
1421 |
++ successfully, the connection has been terminated and won't accept any new |
1422 |
++ messages from remote peers. This way, a connection can be terminated |
1423 |
++ race-free, without losing any messages. The ioctl takes an argument of |
1424 |
++ type <type>struct kdbus_cmd</type>. |
1425 |
++ </para> |
1426 |
++ |
1427 |
++ <programlisting> |
1428 |
++struct kdbus_cmd { |
1429 |
++ __u64 size; |
1430 |
++ __u64 flags; |
1431 |
++ __u64 return_flags; |
1432 |
++ struct kdbus_item items[0]; |
1433 |
++}; |
1434 |
++ </programlisting> |
1435 |
++ |
1436 |
++ <variablelist> |
1437 |
++ <varlistentry> |
1438 |
++ <term><varname>size</varname></term> |
1439 |
++ <listitem><para> |
1440 |
++ The overall size of the struct, including its items. |
1441 |
++ </para></listitem> |
1442 |
++ </varlistentry> |
1443 |
++ |
1444 |
++ <varlistentry> |
1445 |
++ <term><varname>flags</varname></term> |
1446 |
++ <listitem><para> |
1447 |
++ Currently, no flags are supported. |
1448 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1449 |
++ valid flags. If set, the ioctl will fail with |
1450 |
++ <varname>errno</varname> set to <constant>EPROTO</constant>, and |
1451 |
++ the <varname>flags</varname> field is set to <constant>0</constant>. |
1452 |
++ </para></listitem> |
1453 |
++ </varlistentry> |
1454 |
++ |
1455 |
++ <varlistentry> |
1456 |
++ <term><varname>return_flags</varname></term> |
1457 |
++ <listitem><para> |
1458 |
++ Flags returned by the kernel. Currently unused and always set to |
1459 |
++ <constant>0</constant> by the kernel. |
1460 |
++ </para></listitem> |
1461 |
++ </varlistentry> |
1462 |
++ |
1463 |
++ <varlistentry> |
1464 |
++ <term><varname>items</varname></term> |
1465 |
++ <listitem> |
1466 |
++ <para> |
1467 |
++ The following item types are supported. |
1468 |
++ </para> |
1469 |
++ <variablelist> |
1470 |
++ <varlistentry> |
1471 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1472 |
++ <listitem><para> |
1473 |
++ With this item, programs can <emphasis>probe</emphasis> the |
1474 |
++ kernel for known item types. See |
1475 |
++ <citerefentry> |
1476 |
++ <refentrytitle>kdbus.item</refentrytitle> |
1477 |
++ <manvolnum>7</manvolnum> |
1478 |
++ </citerefentry> |
1479 |
++ for more details. |
1480 |
++ </para></listitem> |
1481 |
++ </varlistentry> |
1482 |
++ </variablelist> |
1483 |
++ |
1484 |
++ <para> |
1485 |
++ Unrecognized items are rejected, and the ioctl will fail with |
1486 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1487 |
++ </para> |
1488 |
++ </listitem> |
1489 |
++ </varlistentry> |
1490 |
++ </variablelist> |
1491 |
++ </refsect1> |
1492 |
++ |
1493 |
++ <refsect1> |
1494 |
++ <title>Return value</title> |
1495 |
++ <para> |
1496 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
1497 |
++ on error, <errorcode>-1</errorcode> is returned, and |
1498 |
++ <varname>errno</varname> is set to indicate the error. |
1499 |
++ If the issued ioctl is illegal for the file descriptor used, |
1500 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
1501 |
++ </para> |
1502 |
++ |
1503 |
++ <refsect2> |
1504 |
++ <title> |
1505 |
++ <constant>KDBUS_CMD_HELLO</constant> may fail with the following |
1506 |
++ errors |
1507 |
++ </title> |
1508 |
++ |
1509 |
++ <variablelist> |
1510 |
++ <varlistentry> |
1511 |
++ <term><constant>EFAULT</constant></term> |
1512 |
++ <listitem><para> |
1513 |
++ The supplied pool size was 0 or not a multiple of the page size. |
1514 |
++ </para></listitem> |
1515 |
++ </varlistentry> |
1516 |
++ |
1517 |
++ <varlistentry> |
1518 |
++ <term><constant>EINVAL</constant></term> |
1519 |
++ <listitem><para> |
1520 |
++ The flags supplied in <type>struct kdbus_cmd_hello</type> |
1521 |
++ are invalid. |
1522 |
++ </para></listitem> |
1523 |
++ </varlistentry> |
1524 |
++ |
1525 |
++ <varlistentry> |
1526 |
++ <term><constant>EINVAL</constant></term> |
1527 |
++ <listitem><para> |
1528 |
++ An illegal combination of |
1529 |
++ <constant>KDBUS_HELLO_MONITOR</constant>, |
1530 |
++ <constant>KDBUS_HELLO_ACTIVATOR</constant> and |
1531 |
++ <constant>KDBUS_HELLO_POLICY_HOLDER</constant> was passed in |
1532 |
++ <varname>flags</varname>. |
1533 |
++ </para></listitem> |
1534 |
++ </varlistentry> |
1535 |
++ |
1536 |
++ <varlistentry> |
1537 |
++ <term><constant>EINVAL</constant></term> |
1538 |
++ <listitem><para> |
1539 |
++ An invalid set of items was supplied. |
1540 |
++ </para></listitem> |
1541 |
++ </varlistentry> |
1542 |
++ |
1543 |
++ <varlistentry> |
1544 |
++ <term><constant>ECONNREFUSED</constant></term> |
1545 |
++ <listitem><para> |
1546 |
++ The attach_flags_send field did not satisfy the requirements of |
1547 |
++ the bus. |
1548 |
++ </para></listitem> |
1549 |
++ </varlistentry> |
1550 |
++ |
1551 |
++ <varlistentry> |
1552 |
++ <term><constant>EPERM</constant></term> |
1553 |
++ <listitem><para> |
1554 |
++ A <constant>KDBUS_ITEM_CREDS</constant> items was supplied, but the |
1555 |
++ current user is not privileged. |
1556 |
++ </para></listitem> |
1557 |
++ </varlistentry> |
1558 |
++ |
1559 |
++ <varlistentry> |
1560 |
++ <term><constant>ESHUTDOWN</constant></term> |
1561 |
++ <listitem><para> |
1562 |
++ The bus you were trying to connect to has already been shut down. |
1563 |
++ </para></listitem> |
1564 |
++ </varlistentry> |
1565 |
++ |
1566 |
++ <varlistentry> |
1567 |
++ <term><constant>EMFILE</constant></term> |
1568 |
++ <listitem><para> |
1569 |
++ The maximum number of connections on the bus has been reached. |
1570 |
++ </para></listitem> |
1571 |
++ </varlistentry> |
1572 |
++ |
1573 |
++ <varlistentry> |
1574 |
++ <term><constant>EOPNOTSUPP</constant></term> |
1575 |
++ <listitem><para> |
1576 |
++ The endpoint does not support the connection flags supplied in |
1577 |
++ <type>struct kdbus_cmd_hello</type>. |
1578 |
++ </para></listitem> |
1579 |
++ </varlistentry> |
1580 |
++ </variablelist> |
1581 |
++ </refsect2> |
1582 |
++ |
1583 |
++ <refsect2> |
1584 |
++ <title> |
1585 |
++ <constant>KDBUS_CMD_BYEBYE</constant> may fail with the following |
1586 |
++ errors |
1587 |
++ </title> |
1588 |
++ |
1589 |
++ <variablelist> |
1590 |
++ <varlistentry> |
1591 |
++ <term><constant>EALREADY</constant></term> |
1592 |
++ <listitem><para> |
1593 |
++ The connection has already been shut down. |
1594 |
++ </para></listitem> |
1595 |
++ </varlistentry> |
1596 |
++ |
1597 |
++ <varlistentry> |
1598 |
++ <term><constant>EBUSY</constant></term> |
1599 |
++ <listitem><para> |
1600 |
++ There are still messages queued up in the connection's pool. |
1601 |
++ </para></listitem> |
1602 |
++ </varlistentry> |
1603 |
++ </variablelist> |
1604 |
++ </refsect2> |
1605 |
++ |
1606 |
++ <refsect2> |
1607 |
++ <title> |
1608 |
++ <constant>KDBUS_CMD_CONN_INFO</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 |
++ Invalid flags, or neither an ID nor a name was provided, or the |
1617 |
++ name is invalid. |
1618 |
++ </para></listitem> |
1619 |
++ </varlistentry> |
1620 |
++ |
1621 |
++ <varlistentry> |
1622 |
++ <term><constant>ESRCH</constant></term> |
1623 |
++ <listitem><para> |
1624 |
++ Connection lookup by name failed. |
1625 |
++ </para></listitem> |
1626 |
++ </varlistentry> |
1627 |
++ |
1628 |
++ <varlistentry> |
1629 |
++ <term><constant>ENXIO</constant></term> |
1630 |
++ <listitem><para> |
1631 |
++ No connection with the provided connection ID found. |
1632 |
++ </para></listitem> |
1633 |
++ </varlistentry> |
1634 |
++ </variablelist> |
1635 |
++ </refsect2> |
1636 |
++ |
1637 |
++ <refsect2> |
1638 |
++ <title> |
1639 |
++ <constant>KDBUS_CMD_CONN_UPDATE</constant> may fail with the following |
1640 |
++ errors |
1641 |
++ </title> |
1642 |
++ |
1643 |
++ <variablelist> |
1644 |
++ <varlistentry> |
1645 |
++ <term><constant>EINVAL</constant></term> |
1646 |
++ <listitem><para> |
1647 |
++ Illegal flags or items. |
1648 |
++ </para></listitem> |
1649 |
++ </varlistentry> |
1650 |
++ |
1651 |
++ <varlistentry> |
1652 |
++ <term><constant>EINVAL</constant></term> |
1653 |
++ <listitem><para> |
1654 |
++ Wildcards submitted in policy entries, or illegal sequence |
1655 |
++ of policy items. |
1656 |
++ </para></listitem> |
1657 |
++ </varlistentry> |
1658 |
++ |
1659 |
++ <varlistentry> |
1660 |
++ <term><constant>EOPNOTSUPP</constant></term> |
1661 |
++ <listitem><para> |
1662 |
++ Operation not supported by connection. |
1663 |
++ </para></listitem> |
1664 |
++ </varlistentry> |
1665 |
++ |
1666 |
++ <varlistentry> |
1667 |
++ <term><constant>E2BIG</constant></term> |
1668 |
++ <listitem><para> |
1669 |
++ Too many policy items attached. |
1670 |
++ </para></listitem> |
1671 |
++ </varlistentry> |
1672 |
++ </variablelist> |
1673 |
++ </refsect2> |
1674 |
++ </refsect1> |
1675 |
++ |
1676 |
++ <refsect1> |
1677 |
++ <title>See Also</title> |
1678 |
++ <simplelist type="inline"> |
1679 |
++ <member> |
1680 |
++ <citerefentry> |
1681 |
++ <refentrytitle>kdbus</refentrytitle> |
1682 |
++ <manvolnum>7</manvolnum> |
1683 |
++ </citerefentry> |
1684 |
++ </member> |
1685 |
++ <member> |
1686 |
++ <citerefentry> |
1687 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
1688 |
++ <manvolnum>7</manvolnum> |
1689 |
++ </citerefentry> |
1690 |
++ </member> |
1691 |
++ <member> |
1692 |
++ <citerefentry> |
1693 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
1694 |
++ <manvolnum>7</manvolnum> |
1695 |
++ </citerefentry> |
1696 |
++ </member> |
1697 |
++ <member> |
1698 |
++ <citerefentry> |
1699 |
++ <refentrytitle>kdbus.message</refentrytitle> |
1700 |
++ <manvolnum>7</manvolnum> |
1701 |
++ </citerefentry> |
1702 |
++ </member> |
1703 |
++ <member> |
1704 |
++ <citerefentry> |
1705 |
++ <refentrytitle>kdbus.name</refentrytitle> |
1706 |
++ <manvolnum>7</manvolnum> |
1707 |
++ </citerefentry> |
1708 |
++ </member> |
1709 |
++ <member> |
1710 |
++ <citerefentry> |
1711 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
1712 |
++ <manvolnum>7</manvolnum> |
1713 |
++ </citerefentry> |
1714 |
++ </member> |
1715 |
++ <member> |
1716 |
++ <citerefentry> |
1717 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
1718 |
++ <manvolnum>7</manvolnum> |
1719 |
++ </citerefentry> |
1720 |
++ </member> |
1721 |
++ <member> |
1722 |
++ <citerefentry> |
1723 |
++ <refentrytitle>kdbus.item</refentrytitle> |
1724 |
++ <manvolnum>7</manvolnum> |
1725 |
++ </citerefentry> |
1726 |
++ </member> |
1727 |
++ </simplelist> |
1728 |
++ </refsect1> |
1729 |
++</refentry> |
1730 |
+diff --git a/Documentation/kdbus/kdbus.endpoint.xml b/Documentation/kdbus/kdbus.endpoint.xml |
1731 |
+new file mode 100644 |
1732 |
+index 0000000..6632485 |
1733 |
+--- /dev/null |
1734 |
++++ b/Documentation/kdbus/kdbus.endpoint.xml |
1735 |
+@@ -0,0 +1,429 @@ |
1736 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
1737 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
1738 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
1739 |
++ |
1740 |
++<refentry id="kdbus.endpoint"> |
1741 |
++ |
1742 |
++ <refentryinfo> |
1743 |
++ <title>kdbus.endpoint</title> |
1744 |
++ <productname>kdbus.endpoint</productname> |
1745 |
++ </refentryinfo> |
1746 |
++ |
1747 |
++ <refmeta> |
1748 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
1749 |
++ <manvolnum>7</manvolnum> |
1750 |
++ </refmeta> |
1751 |
++ |
1752 |
++ <refnamediv> |
1753 |
++ <refname>kdbus.endpoint</refname> |
1754 |
++ <refpurpose>kdbus endpoint</refpurpose> |
1755 |
++ </refnamediv> |
1756 |
++ |
1757 |
++ <refsect1> |
1758 |
++ <title>Description</title> |
1759 |
++ |
1760 |
++ <para> |
1761 |
++ Endpoints are entry points to a bus (see |
1762 |
++ <citerefentry> |
1763 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
1764 |
++ <manvolnum>7</manvolnum> |
1765 |
++ </citerefentry>). |
1766 |
++ By default, each bus has a default |
1767 |
++ endpoint called 'bus'. The bus owner has the ability to create custom |
1768 |
++ endpoints with specific names, permissions, and policy databases |
1769 |
++ (see below). An endpoint is presented as file underneath the directory |
1770 |
++ of the parent bus. |
1771 |
++ </para> |
1772 |
++ <para> |
1773 |
++ To create a custom endpoint, open the default endpoint |
1774 |
++ (<literal>bus</literal>) and use the |
1775 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> ioctl with |
1776 |
++ <type>struct kdbus_cmd</type>. Custom endpoints always have a policy |
1777 |
++ database that, by default, forbids any operation. You have to explicitly |
1778 |
++ install policy entries to allow any operation on this endpoint. |
1779 |
++ </para> |
1780 |
++ <para> |
1781 |
++ Once <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> succeeded, the new |
1782 |
++ endpoint will appear in the filesystem |
1783 |
++ (<citerefentry> |
1784 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
1785 |
++ <manvolnum>7</manvolnum> |
1786 |
++ </citerefentry>), and the used file descriptor will manage the |
1787 |
++ newly created endpoint resource. It cannot be used to manage further |
1788 |
++ resources and must be kept open as long as the endpoint is needed. The |
1789 |
++ endpoint will be terminated as soon as the file descriptor is closed. |
1790 |
++ </para> |
1791 |
++ <para> |
1792 |
++ Endpoint names may be chosen freely except for one restriction: the name |
1793 |
++ must be prefixed with the numeric effective UID of the creator and a dash. |
1794 |
++ This is required to avoid namespace clashes between different users. When |
1795 |
++ creating an endpoint, the name that is passed in must be properly |
1796 |
++ formatted or the kernel will refuse creation of the endpoint. Example: |
1797 |
++ <literal>1047-my-endpoint</literal> is an acceptable name for an |
1798 |
++ endpoint registered by a user with UID 1047. However, |
1799 |
++ <literal>1024-my-endpoint</literal> is not, and neither is |
1800 |
++ <literal>my-endpoint</literal>. The UID must be provided in the |
1801 |
++ user-namespace of the bus. |
1802 |
++ </para> |
1803 |
++ <para> |
1804 |
++ To create connections to a bus, use <constant>KDBUS_CMD_HELLO</constant> |
1805 |
++ on a file descriptor returned by <function>open()</function> on an |
1806 |
++ endpoint node. See |
1807 |
++ <citerefentry> |
1808 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
1809 |
++ <manvolnum>7</manvolnum> |
1810 |
++ </citerefentry> |
1811 |
++ for further details. |
1812 |
++ </para> |
1813 |
++ </refsect1> |
1814 |
++ |
1815 |
++ <refsect1> |
1816 |
++ <title>Creating custom endpoints</title> |
1817 |
++ <para> |
1818 |
++ To create a new endpoint, the |
1819 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> command is used. Along with |
1820 |
++ the endpoint's name, which will be used to expose the endpoint in the |
1821 |
++ <citerefentry> |
1822 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
1823 |
++ <manvolnum>7</manvolnum> |
1824 |
++ </citerefentry>, |
1825 |
++ the command also optionally takes items to set up the endpoint's |
1826 |
++ <citerefentry> |
1827 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
1828 |
++ <manvolnum>7</manvolnum> |
1829 |
++ </citerefentry>. |
1830 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> takes a |
1831 |
++ <type>struct kdbus_cmd</type> argument. |
1832 |
++ </para> |
1833 |
++ <programlisting> |
1834 |
++struct kdbus_cmd { |
1835 |
++ __u64 size; |
1836 |
++ __u64 flags; |
1837 |
++ __u64 return_flags; |
1838 |
++ struct kdbus_item items[0]; |
1839 |
++}; |
1840 |
++ </programlisting> |
1841 |
++ |
1842 |
++ <para>The fields in this struct are described below.</para> |
1843 |
++ |
1844 |
++ <variablelist> |
1845 |
++ <varlistentry> |
1846 |
++ <term><varname>size</varname></term> |
1847 |
++ <listitem><para> |
1848 |
++ The overall size of the struct, including its items. |
1849 |
++ </para></listitem> |
1850 |
++ </varlistentry> |
1851 |
++ |
1852 |
++ <varlistentry> |
1853 |
++ <term><varname>flags</varname></term> |
1854 |
++ <listitem><para>The flags for creation.</para> |
1855 |
++ <variablelist> |
1856 |
++ <varlistentry> |
1857 |
++ <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term> |
1858 |
++ <listitem> |
1859 |
++ <para>Make the endpoint file group-accessible.</para> |
1860 |
++ </listitem> |
1861 |
++ </varlistentry> |
1862 |
++ |
1863 |
++ <varlistentry> |
1864 |
++ <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term> |
1865 |
++ <listitem> |
1866 |
++ <para>Make the endpoint file world-accessible.</para> |
1867 |
++ </listitem> |
1868 |
++ </varlistentry> |
1869 |
++ |
1870 |
++ <varlistentry> |
1871 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
1872 |
++ <listitem> |
1873 |
++ <para> |
1874 |
++ Requests a set of valid flags for this ioctl. When this bit is |
1875 |
++ set, no action is taken; the ioctl will return |
1876 |
++ <errorcode>0</errorcode>, and the <varname>flags</varname> |
1877 |
++ field will have all bits set that are valid for this command. |
1878 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
1879 |
++ cleared by the operation. |
1880 |
++ </para> |
1881 |
++ </listitem> |
1882 |
++ </varlistentry> |
1883 |
++ </variablelist> |
1884 |
++ </listitem> |
1885 |
++ </varlistentry> |
1886 |
++ |
1887 |
++ <varlistentry> |
1888 |
++ <term><varname>return_flags</varname></term> |
1889 |
++ <listitem><para> |
1890 |
++ Flags returned by the kernel. Currently unused and always set to |
1891 |
++ <constant>0</constant> by the kernel. |
1892 |
++ </para></listitem> |
1893 |
++ </varlistentry> |
1894 |
++ |
1895 |
++ <varlistentry> |
1896 |
++ <term><varname>items</varname></term> |
1897 |
++ <listitem> |
1898 |
++ <para> |
1899 |
++ The following items are expected for |
1900 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. |
1901 |
++ </para> |
1902 |
++ <variablelist> |
1903 |
++ <varlistentry> |
1904 |
++ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
1905 |
++ <listitem> |
1906 |
++ <para>Contains a string to identify the endpoint name.</para> |
1907 |
++ </listitem> |
1908 |
++ </varlistentry> |
1909 |
++ |
1910 |
++ <varlistentry> |
1911 |
++ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1912 |
++ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1913 |
++ <listitem> |
1914 |
++ <para> |
1915 |
++ These items are used to set the policy attached to the |
1916 |
++ endpoint. For more details on bus and endpoint policies, see |
1917 |
++ <citerefentry> |
1918 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
1919 |
++ <manvolnum>7</manvolnum> |
1920 |
++ </citerefentry>. |
1921 |
++ </para> |
1922 |
++ </listitem> |
1923 |
++ </varlistentry> |
1924 |
++ </variablelist> |
1925 |
++ <para> |
1926 |
++ Unrecognized items are rejected, and the ioctl will fail with |
1927 |
++ <varname>errno</varname> set to <varname>EINVAL</varname>. |
1928 |
++ </para> |
1929 |
++ </listitem> |
1930 |
++ </varlistentry> |
1931 |
++ </variablelist> |
1932 |
++ </refsect1> |
1933 |
++ |
1934 |
++ <refsect1> |
1935 |
++ <title>Updating endpoints</title> |
1936 |
++ <para> |
1937 |
++ To update an existing endpoint, the |
1938 |
++ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> command is used on the file |
1939 |
++ descriptor that was used to create the endpoint, using |
1940 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. The only relevant detail of |
1941 |
++ the endpoint that can be updated is the policy. When the command is |
1942 |
++ employed, the policy of the endpoint is <emphasis>replaced</emphasis> |
1943 |
++ atomically with the new set of rules. |
1944 |
++ The command takes a <type>struct kdbus_cmd</type> argument. |
1945 |
++ </para> |
1946 |
++ <programlisting> |
1947 |
++struct kdbus_cmd { |
1948 |
++ __u64 size; |
1949 |
++ __u64 flags; |
1950 |
++ __u64 return_flags; |
1951 |
++ struct kdbus_item items[0]; |
1952 |
++}; |
1953 |
++ </programlisting> |
1954 |
++ |
1955 |
++ <para>The fields in this struct are described below.</para> |
1956 |
++ |
1957 |
++ <variablelist> |
1958 |
++ <varlistentry> |
1959 |
++ <term><varname>size</varname></term> |
1960 |
++ <listitem><para> |
1961 |
++ The overall size of the struct, including its items. |
1962 |
++ </para></listitem> |
1963 |
++ </varlistentry> |
1964 |
++ |
1965 |
++ <varlistentry> |
1966 |
++ <term><varname>flags</varname></term> |
1967 |
++ <listitem><para> |
1968 |
++ Unused for this command. |
1969 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1970 |
++ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1971 |
++ and the <varname>flags</varname> field is set to |
1972 |
++ <constant>0</constant>. |
1973 |
++ </para></listitem> |
1974 |
++ </varlistentry> |
1975 |
++ |
1976 |
++ <varlistentry> |
1977 |
++ <term><varname>return_flags</varname></term> |
1978 |
++ <listitem><para> |
1979 |
++ Flags returned by the kernel. Currently unused and always set to |
1980 |
++ <constant>0</constant> by the kernel. |
1981 |
++ </para></listitem> |
1982 |
++ </varlistentry> |
1983 |
++ |
1984 |
++ <varlistentry> |
1985 |
++ <term><varname>items</varname></term> |
1986 |
++ <listitem> |
1987 |
++ <para> |
1988 |
++ The following items are expected for |
1989 |
++ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant>. |
1990 |
++ </para> |
1991 |
++ <variablelist> |
1992 |
++ <varlistentry> |
1993 |
++ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1994 |
++ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1995 |
++ <listitem> |
1996 |
++ <para> |
1997 |
++ These items are used to set the policy attached to the |
1998 |
++ endpoint. For more details on bus and endpoint policies, see |
1999 |
++ <citerefentry> |
2000 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
2001 |
++ <manvolnum>7</manvolnum> |
2002 |
++ </citerefentry>. |
2003 |
++ Existing policy is atomically replaced with the new rules |
2004 |
++ provided. |
2005 |
++ </para> |
2006 |
++ </listitem> |
2007 |
++ </varlistentry> |
2008 |
++ |
2009 |
++ <varlistentry> |
2010 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
2011 |
++ <listitem><para> |
2012 |
++ With this item, programs can <emphasis>probe</emphasis> the |
2013 |
++ kernel for known item types. See |
2014 |
++ <citerefentry> |
2015 |
++ <refentrytitle>kdbus.item</refentrytitle> |
2016 |
++ <manvolnum>7</manvolnum> |
2017 |
++ </citerefentry> |
2018 |
++ for more details. |
2019 |
++ </para></listitem> |
2020 |
++ </varlistentry> |
2021 |
++ </variablelist> |
2022 |
++ <para> |
2023 |
++ Unrecognized items are rejected, and the ioctl will fail with |
2024 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
2025 |
++ </para> |
2026 |
++ </listitem> |
2027 |
++ </varlistentry> |
2028 |
++ </variablelist> |
2029 |
++ </refsect1> |
2030 |
++ |
2031 |
++ <refsect1> |
2032 |
++ <title>Return value</title> |
2033 |
++ <para> |
2034 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
2035 |
++ on error, <errorcode>-1</errorcode> is returned, and |
2036 |
++ <varname>errno</varname> is set to indicate the error. |
2037 |
++ If the issued ioctl is illegal for the file descriptor used, |
2038 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
2039 |
++ </para> |
2040 |
++ |
2041 |
++ <refsect2> |
2042 |
++ <title> |
2043 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> may fail with the |
2044 |
++ following errors |
2045 |
++ </title> |
2046 |
++ |
2047 |
++ <variablelist> |
2048 |
++ <varlistentry> |
2049 |
++ <term><constant>EINVAL</constant></term> |
2050 |
++ <listitem><para> |
2051 |
++ The flags supplied in the <type>struct kdbus_cmd</type> |
2052 |
++ are invalid. |
2053 |
++ </para></listitem> |
2054 |
++ </varlistentry> |
2055 |
++ |
2056 |
++ <varlistentry> |
2057 |
++ <term><constant>EINVAL</constant></term> |
2058 |
++ <listitem><para> |
2059 |
++ Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and |
2060 |
++ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided. |
2061 |
++ </para></listitem> |
2062 |
++ </varlistentry> |
2063 |
++ |
2064 |
++ <varlistentry> |
2065 |
++ <term><constant>EEXIST</constant></term> |
2066 |
++ <listitem><para> |
2067 |
++ An endpoint of that name already exists. |
2068 |
++ </para></listitem> |
2069 |
++ </varlistentry> |
2070 |
++ |
2071 |
++ <varlistentry> |
2072 |
++ <term><constant>EPERM</constant></term> |
2073 |
++ <listitem><para> |
2074 |
++ The calling user is not privileged. See |
2075 |
++ <citerefentry> |
2076 |
++ <refentrytitle>kdbus</refentrytitle> |
2077 |
++ <manvolnum>7</manvolnum> |
2078 |
++ </citerefentry> |
2079 |
++ for information about privileged users. |
2080 |
++ </para></listitem> |
2081 |
++ </varlistentry> |
2082 |
++ </variablelist> |
2083 |
++ </refsect2> |
2084 |
++ |
2085 |
++ <refsect2> |
2086 |
++ <title> |
2087 |
++ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> may fail with the |
2088 |
++ following errors |
2089 |
++ </title> |
2090 |
++ |
2091 |
++ <variablelist> |
2092 |
++ <varlistentry> |
2093 |
++ <term><constant>EINVAL</constant></term> |
2094 |
++ <listitem><para> |
2095 |
++ The flags supplied in <type>struct kdbus_cmd</type> |
2096 |
++ are invalid. |
2097 |
++ </para></listitem> |
2098 |
++ </varlistentry> |
2099 |
++ |
2100 |
++ <varlistentry> |
2101 |
++ <term><constant>EINVAL</constant></term> |
2102 |
++ <listitem><para> |
2103 |
++ Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and |
2104 |
++ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided. |
2105 |
++ </para></listitem> |
2106 |
++ </varlistentry> |
2107 |
++ </variablelist> |
2108 |
++ </refsect2> |
2109 |
++ </refsect1> |
2110 |
++ |
2111 |
++ <refsect1> |
2112 |
++ <title>See Also</title> |
2113 |
++ <simplelist type="inline"> |
2114 |
++ <member> |
2115 |
++ <citerefentry> |
2116 |
++ <refentrytitle>kdbus</refentrytitle> |
2117 |
++ <manvolnum>7</manvolnum> |
2118 |
++ </citerefentry> |
2119 |
++ </member> |
2120 |
++ <member> |
2121 |
++ <citerefentry> |
2122 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
2123 |
++ <manvolnum>7</manvolnum> |
2124 |
++ </citerefentry> |
2125 |
++ </member> |
2126 |
++ <member> |
2127 |
++ <citerefentry> |
2128 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
2129 |
++ <manvolnum>7</manvolnum> |
2130 |
++ </citerefentry> |
2131 |
++ </member> |
2132 |
++ <member> |
2133 |
++ <citerefentry> |
2134 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
2135 |
++ <manvolnum>7</manvolnum> |
2136 |
++ </citerefentry> |
2137 |
++ </member> |
2138 |
++ <member> |
2139 |
++ <citerefentry> |
2140 |
++ <refentrytitle>kdbus.item</refentrytitle> |
2141 |
++ <manvolnum>7</manvolnum> |
2142 |
++ </citerefentry> |
2143 |
++ </member> |
2144 |
++ <member> |
2145 |
++ <citerefentry> |
2146 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2147 |
++ <manvolnum>7</manvolnum> |
2148 |
++ </citerefentry> |
2149 |
++ </member> |
2150 |
++ <member> |
2151 |
++ <citerefentry> |
2152 |
++ <refentrytitle>kdbus.name</refentrytitle> |
2153 |
++ <manvolnum>7</manvolnum> |
2154 |
++ </citerefentry> |
2155 |
++ </member> |
2156 |
++ <member> |
2157 |
++ <citerefentry> |
2158 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
2159 |
++ <manvolnum>7</manvolnum> |
2160 |
++ </citerefentry> |
2161 |
++ </member> |
2162 |
++ </simplelist> |
2163 |
++ </refsect1> |
2164 |
++</refentry> |
2165 |
+diff --git a/Documentation/kdbus/kdbus.fs.xml b/Documentation/kdbus/kdbus.fs.xml |
2166 |
+new file mode 100644 |
2167 |
+index 0000000..8c2a90e |
2168 |
+--- /dev/null |
2169 |
++++ b/Documentation/kdbus/kdbus.fs.xml |
2170 |
+@@ -0,0 +1,124 @@ |
2171 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
2172 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
2173 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
2174 |
++ |
2175 |
++<refentry id="kdbus_fs"> |
2176 |
++ |
2177 |
++ <refentryinfo> |
2178 |
++ <title>kdbus.fs</title> |
2179 |
++ <productname>kdbus.fs</productname> |
2180 |
++ </refentryinfo> |
2181 |
++ |
2182 |
++ <refmeta> |
2183 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
2184 |
++ <manvolnum>7</manvolnum> |
2185 |
++ </refmeta> |
2186 |
++ |
2187 |
++ <refnamediv> |
2188 |
++ <refname>kdbus.fs</refname> |
2189 |
++ <refpurpose>kdbus file system</refpurpose> |
2190 |
++ </refnamediv> |
2191 |
++ |
2192 |
++ <refsect1> |
2193 |
++ <title>File-system Layout</title> |
2194 |
++ |
2195 |
++ <para> |
2196 |
++ The <emphasis>kdbusfs</emphasis> pseudo filesystem provides access to |
2197 |
++ kdbus entities, such as <emphasis>buses</emphasis> and |
2198 |
++ <emphasis>endpoints</emphasis>. Each time the filesystem is mounted, |
2199 |
++ a new, isolated kdbus instance is created, which is independent from the |
2200 |
++ other instances. |
2201 |
++ </para> |
2202 |
++ <para> |
2203 |
++ The system-wide standard mount point for <emphasis>kdbusfs</emphasis> is |
2204 |
++ <constant>/sys/fs/kdbus</constant>. |
2205 |
++ </para> |
2206 |
++ |
2207 |
++ <para> |
2208 |
++ Buses are represented as directories in the file system layout, whereas |
2209 |
++ endpoints are exposed as files inside these directories. At the top-level, |
2210 |
++ a <emphasis>control</emphasis> node is present, which can be opened to |
2211 |
++ create new buses via the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. |
2212 |
++ Each <emphasis>bus</emphasis> shows a default endpoint called |
2213 |
++ <varname>bus</varname>, which can be opened to either create a connection |
2214 |
++ with the <constant>KDBUS_CMD_HELLO</constant> ioctl, or to create new |
2215 |
++ custom endpoints for the bus with |
2216 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. See |
2217 |
++ <citerefentry> |
2218 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
2219 |
++ <manvolnum>7</manvolnum> |
2220 |
++ </citerefentry>, |
2221 |
++ <citerefentry> |
2222 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
2223 |
++ <manvolnum>7</manvolnum> |
2224 |
++ </citerefentry> and |
2225 |
++ <citerefentry> |
2226 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
2227 |
++ <manvolnum>7</manvolnum> |
2228 |
++ </citerefentry> |
2229 |
++ for more details. |
2230 |
++ </para> |
2231 |
++ |
2232 |
++ <para>Following, you can see an example layout of the |
2233 |
++ <emphasis>kdbusfs</emphasis> filesystem:</para> |
2234 |
++ |
2235 |
++<programlisting> |
2236 |
++ /sys/fs/kdbus/ ; mount-point |
2237 |
++ |-- 0-system ; bus directory |
2238 |
++ | |-- bus ; default endpoint |
2239 |
++ | `-- 1017-custom ; custom endpoint |
2240 |
++ |-- 1000-user ; bus directory |
2241 |
++ | |-- bus ; default endpoint |
2242 |
++ | |-- 1000-service-A ; custom endpoint |
2243 |
++ | `-- 1000-service-B ; custom endpoint |
2244 |
++ `-- control ; control file |
2245 |
++</programlisting> |
2246 |
++ </refsect1> |
2247 |
++ |
2248 |
++ <refsect1> |
2249 |
++ <title>Mounting instances</title> |
2250 |
++ <para> |
2251 |
++ In order to get a new and separate kdbus environment, a new instance |
2252 |
++ of <emphasis>kdbusfs</emphasis> can be mounted like this: |
2253 |
++ </para> |
2254 |
++<programlisting> |
2255 |
++ # mount -t kdbusfs kdbusfs /tmp/new_kdbus/ |
2256 |
++</programlisting> |
2257 |
++ </refsect1> |
2258 |
++ |
2259 |
++ <refsect1> |
2260 |
++ <title>See Also</title> |
2261 |
++ <simplelist type="inline"> |
2262 |
++ <member> |
2263 |
++ <citerefentry> |
2264 |
++ <refentrytitle>kdbus</refentrytitle> |
2265 |
++ <manvolnum>7</manvolnum> |
2266 |
++ </citerefentry> |
2267 |
++ </member> |
2268 |
++ <member> |
2269 |
++ <citerefentry> |
2270 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
2271 |
++ <manvolnum>7</manvolnum> |
2272 |
++ </citerefentry> |
2273 |
++ </member> |
2274 |
++ <member> |
2275 |
++ <citerefentry> |
2276 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
2277 |
++ <manvolnum>7</manvolnum> |
2278 |
++ </citerefentry> |
2279 |
++ </member> |
2280 |
++ <member> |
2281 |
++ <citerefentry> |
2282 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
2283 |
++ <manvolnum>7</manvolnum> |
2284 |
++ </citerefentry> |
2285 |
++ </member> |
2286 |
++ <member> |
2287 |
++ <citerefentry> |
2288 |
++ <refentrytitle>mount</refentrytitle> |
2289 |
++ <manvolnum>8</manvolnum> |
2290 |
++ </citerefentry> |
2291 |
++ </member> |
2292 |
++ </simplelist> |
2293 |
++ </refsect1> |
2294 |
++</refentry> |
2295 |
+diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml |
2296 |
+new file mode 100644 |
2297 |
+index 0000000..09f8b90 |
2298 |
+--- /dev/null |
2299 |
++++ b/Documentation/kdbus/kdbus.item.xml |
2300 |
+@@ -0,0 +1,839 @@ |
2301 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
2302 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
2303 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
2304 |
++ |
2305 |
++<refentry id="kdbus"> |
2306 |
++ |
2307 |
++ <refentryinfo> |
2308 |
++ <title>kdbus.item</title> |
2309 |
++ <productname>kdbus item</productname> |
2310 |
++ </refentryinfo> |
2311 |
++ |
2312 |
++ <refmeta> |
2313 |
++ <refentrytitle>kdbus.item</refentrytitle> |
2314 |
++ <manvolnum>7</manvolnum> |
2315 |
++ </refmeta> |
2316 |
++ |
2317 |
++ <refnamediv> |
2318 |
++ <refname>kdbus.item</refname> |
2319 |
++ <refpurpose>kdbus item structure, layout and usage</refpurpose> |
2320 |
++ </refnamediv> |
2321 |
++ |
2322 |
++ <refsect1> |
2323 |
++ <title>Description</title> |
2324 |
++ |
2325 |
++ <para> |
2326 |
++ To flexibly augment transport structures, data blobs of type |
2327 |
++ <type>struct kdbus_item</type> can be attached to the structs passed |
2328 |
++ into the ioctls. Some ioctls make items of certain types mandatory, |
2329 |
++ others are optional. Items that are unsupported by ioctls they are |
2330 |
++ attached to will cause the ioctl to fail with <varname>errno</varname> |
2331 |
++ set to <constant>EINVAL</constant>. |
2332 |
++ Items are also used for information stored in a connection's |
2333 |
++ <emphasis>pool</emphasis>, such as received messages, name lists or |
2334 |
++ requested connection or bus owner information. Depending on the type of |
2335 |
++ an item, its total size is either fixed or variable. |
2336 |
++ </para> |
2337 |
++ |
2338 |
++ <refsect2> |
2339 |
++ <title>Chaining items</title> |
2340 |
++ <para> |
2341 |
++ Whenever items are used as part of the kdbus kernel API, they are |
2342 |
++ embedded in structs that are embedded inside structs that themselves |
2343 |
++ include a size field containing the overall size of the structure. |
2344 |
++ This allows multiple items to be chained up, and an item iterator |
2345 |
++ (see below) is capable of detecting the end of an item chain. |
2346 |
++ </para> |
2347 |
++ </refsect2> |
2348 |
++ |
2349 |
++ <refsect2> |
2350 |
++ <title>Alignment</title> |
2351 |
++ <para> |
2352 |
++ The kernel expects all items to be aligned to 8-byte boundaries. |
2353 |
++ Unaligned items will cause the ioctl they are used with to fail |
2354 |
++ with <varname>errno</varname> set to <constant>EINVAL</constant>. |
2355 |
++ An item that has an unaligned size itself hence needs to be padded |
2356 |
++ if it is followed by another item. |
2357 |
++ </para> |
2358 |
++ </refsect2> |
2359 |
++ |
2360 |
++ <refsect2> |
2361 |
++ <title>Iterating items</title> |
2362 |
++ <para> |
2363 |
++ A simple iterator would iterate over the items until the items have |
2364 |
++ reached the embedding structure's overall size. An example |
2365 |
++ implementation is shown below. |
2366 |
++ </para> |
2367 |
++ |
2368 |
++ <programlisting><![CDATA[ |
2369 |
++#define KDBUS_ALIGN8(val) (((val) + 7) & ~7) |
2370 |
++ |
2371 |
++#define KDBUS_ITEM_NEXT(item) \ |
2372 |
++ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size)) |
2373 |
++ |
2374 |
++#define KDBUS_ITEM_FOREACH(item, head, first) \ |
2375 |
++ for (item = (head)->first; \ |
2376 |
++ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ |
2377 |
++ ((uint8_t *)(item) >= (uint8_t *)(head)); \ |
2378 |
++ item = KDBUS_ITEM_NEXT(item)) |
2379 |
++ ]]></programlisting> |
2380 |
++ </refsect2> |
2381 |
++ </refsect1> |
2382 |
++ |
2383 |
++ <refsect1> |
2384 |
++ <title>Item layout</title> |
2385 |
++ <para> |
2386 |
++ A <type>struct kdbus_item</type> consists of a |
2387 |
++ <varname>size</varname> field, describing its overall size, and a |
2388 |
++ <varname>type</varname> field, both 64 bit wide. They are followed by |
2389 |
++ a union to store information that is specific to the item's type. |
2390 |
++ The struct layout is shown below. |
2391 |
++ </para> |
2392 |
++ |
2393 |
++ <programlisting> |
2394 |
++struct kdbus_item { |
2395 |
++ __u64 size; |
2396 |
++ __u64 type; |
2397 |
++ /* item payload - see below */ |
2398 |
++ union { |
2399 |
++ __u8 data[0]; |
2400 |
++ __u32 data32[0]; |
2401 |
++ __u64 data64[0]; |
2402 |
++ char str[0]; |
2403 |
++ |
2404 |
++ __u64 id; |
2405 |
++ struct kdbus_vec vec; |
2406 |
++ struct kdbus_creds creds; |
2407 |
++ struct kdbus_pids pids; |
2408 |
++ struct kdbus_audit audit; |
2409 |
++ struct kdbus_caps caps; |
2410 |
++ struct kdbus_timestamp timestamp; |
2411 |
++ struct kdbus_name name; |
2412 |
++ struct kdbus_bloom_parameter bloom_parameter; |
2413 |
++ struct kdbus_bloom_filter bloom_filter; |
2414 |
++ struct kdbus_memfd memfd; |
2415 |
++ int fds[0]; |
2416 |
++ struct kdbus_notify_name_change name_change; |
2417 |
++ struct kdbus_notify_id_change id_change; |
2418 |
++ struct kdbus_policy_access policy_access; |
2419 |
++ }; |
2420 |
++}; |
2421 |
++ </programlisting> |
2422 |
++ |
2423 |
++ <para> |
2424 |
++ <type>struct kdbus_item</type> should never be used to allocate |
2425 |
++ an item instance, as its size may grow in future releases of the API. |
2426 |
++ Instead, it should be manually assembled by storing the |
2427 |
++ <varname>size</varname>, <varname>type</varname> and payload to a |
2428 |
++ struct of its own. |
2429 |
++ </para> |
2430 |
++ </refsect1> |
2431 |
++ |
2432 |
++ <refsect1> |
2433 |
++ <title>Item types</title> |
2434 |
++ |
2435 |
++ <refsect2> |
2436 |
++ <title>Negotiation item</title> |
2437 |
++ <variablelist> |
2438 |
++ <varlistentry> |
2439 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
2440 |
++ <listitem><para> |
2441 |
++ With this item is attached to any ioctl, programs can |
2442 |
++ <emphasis>probe</emphasis> the kernel for known item types. |
2443 |
++ The item carries an array of <type>uint64_t</type> values in |
2444 |
++ <varname>item.data64</varname>, each set to an item type to |
2445 |
++ probe. The kernel will reset each member of this array that is |
2446 |
++ not recognized as valid item type to <constant>0</constant>. |
2447 |
++ This way, users can negotiate kernel features at start-up to |
2448 |
++ keep newer userspace compatible with older kernels. This item |
2449 |
++ is never attached by the kernel in response to any command. |
2450 |
++ </para></listitem> |
2451 |
++ </varlistentry> |
2452 |
++ </variablelist> |
2453 |
++ </refsect2> |
2454 |
++ |
2455 |
++ <refsect2> |
2456 |
++ <title>Command specific items</title> |
2457 |
++ <variablelist> |
2458 |
++ <varlistentry> |
2459 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
2460 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term> |
2461 |
++ <listitem><para> |
2462 |
++ Messages are directly copied by the sending process into the |
2463 |
++ receiver's |
2464 |
++ <citerefentry> |
2465 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
2466 |
++ <manvolnum>7</manvolnum> |
2467 |
++ </citerefentry>. |
2468 |
++ This way, two peers can exchange data by effectively doing a |
2469 |
++ single-copy from one process to another; the kernel will not buffer |
2470 |
++ the data anywhere else. <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> |
2471 |
++ is used when <emphasis>sending</emphasis> message. The item |
2472 |
++ references a memory address when the payload data can be found. |
2473 |
++ <constant>KDBUS_ITEM_PAYLOAD_OFF</constant> is used when messages |
2474 |
++ are <emphasis>received</emphasis>, and the |
2475 |
++ <constant>offset</constant> value describes the offset inside the |
2476 |
++ receiving connection's |
2477 |
++ <citerefentry> |
2478 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
2479 |
++ <manvolnum>7</manvolnum> |
2480 |
++ </citerefentry> |
2481 |
++ where the message payload can be found. See |
2482 |
++ <citerefentry> |
2483 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2484 |
++ <manvolnum>7</manvolnum> |
2485 |
++ </citerefentry> |
2486 |
++ for more information on passing of payload data along with a |
2487 |
++ message. |
2488 |
++ <programlisting> |
2489 |
++struct kdbus_vec { |
2490 |
++ __u64 size; |
2491 |
++ union { |
2492 |
++ __u64 address; |
2493 |
++ __u64 offset; |
2494 |
++ }; |
2495 |
++}; |
2496 |
++ </programlisting> |
2497 |
++ </para></listitem> |
2498 |
++ </varlistentry> |
2499 |
++ |
2500 |
++ <varlistentry> |
2501 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
2502 |
++ <listitem><para> |
2503 |
++ Transports a file descriptor of a <emphasis>memfd</emphasis> in |
2504 |
++ <type>struct kdbus_memfd</type> in <varname>item.memfd</varname>. |
2505 |
++ The <varname>size</varname> field has to match the actual size of |
2506 |
++ the memfd that was specified when it was created. The |
2507 |
++ <varname>start</varname> parameter denotes the offset inside the |
2508 |
++ memfd at which the referenced payload starts. See |
2509 |
++ <citerefentry> |
2510 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2511 |
++ <manvolnum>7</manvolnum> |
2512 |
++ </citerefentry> |
2513 |
++ for more information on passing of payload data along with a |
2514 |
++ message. |
2515 |
++ <programlisting> |
2516 |
++struct kdbus_memfd { |
2517 |
++ __u64 start; |
2518 |
++ __u64 size; |
2519 |
++ int fd; |
2520 |
++ __u32 __pad; |
2521 |
++}; |
2522 |
++ </programlisting> |
2523 |
++ </para></listitem> |
2524 |
++ </varlistentry> |
2525 |
++ |
2526 |
++ <varlistentry> |
2527 |
++ <term><constant>KDBUS_ITEM_FDS</constant></term> |
2528 |
++ <listitem><para> |
2529 |
++ Contains an array of <emphasis>file descriptors</emphasis>. |
2530 |
++ When used with <constant>KDBUS_CMD_SEND</constant>, the values of |
2531 |
++ this array must be filled with valid file descriptor numbers. |
2532 |
++ When received as item attached to a message, the array will |
2533 |
++ contain the numbers of the installed file descriptors, or |
2534 |
++ <constant>-1</constant> in case an error occurred. |
2535 |
++ In either case, the number of entries in the array is derived from |
2536 |
++ the item's total size. See |
2537 |
++ <citerefentry> |
2538 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2539 |
++ <manvolnum>7</manvolnum> |
2540 |
++ </citerefentry> |
2541 |
++ for more information. |
2542 |
++ </para></listitem> |
2543 |
++ </varlistentry> |
2544 |
++ </variablelist> |
2545 |
++ </refsect2> |
2546 |
++ |
2547 |
++ <refsect2> |
2548 |
++ <title>Items specific to some commands</title> |
2549 |
++ <variablelist> |
2550 |
++ <varlistentry> |
2551 |
++ <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term> |
2552 |
++ <listitem><para> |
2553 |
++ Transports a file descriptor that can be used to cancel a |
2554 |
++ synchronous <constant>KDBUS_CMD_SEND</constant> operation by |
2555 |
++ writing to it. The file descriptor is stored in |
2556 |
++ <varname>item.fd[0]</varname>. The item may only contain one |
2557 |
++ file descriptor. See |
2558 |
++ <citerefentry> |
2559 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2560 |
++ <manvolnum>7</manvolnum> |
2561 |
++ </citerefentry> |
2562 |
++ for more information on this item and how to use it. |
2563 |
++ </para></listitem> |
2564 |
++ </varlistentry> |
2565 |
++ |
2566 |
++ <varlistentry> |
2567 |
++ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
2568 |
++ <listitem><para> |
2569 |
++ Contains a set of <emphasis>bloom parameters</emphasis> as |
2570 |
++ <type>struct kdbus_bloom_parameter</type> in |
2571 |
++ <varname>item.bloom_parameter</varname>. |
2572 |
++ The item is passed from userspace to kernel during the |
2573 |
++ <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl, and returned |
2574 |
++ verbatim when <constant>KDBUS_CMD_HELLO</constant> is called. |
2575 |
++ The kernel does not use the bloom parameters, but they need to |
2576 |
++ be known by each connection on the bus in order to define the |
2577 |
++ bloom filter hash details. See |
2578 |
++ <citerefentry> |
2579 |
++ <refentrytitle>kdbus.match</refentrytitle> |
2580 |
++ <manvolnum>7</manvolnum> |
2581 |
++ </citerefentry> |
2582 |
++ for more information on matching and bloom filters. |
2583 |
++ <programlisting> |
2584 |
++struct kdbus_bloom_parameter { |
2585 |
++ __u64 size; |
2586 |
++ __u64 n_hash; |
2587 |
++}; |
2588 |
++ </programlisting> |
2589 |
++ </para></listitem> |
2590 |
++ </varlistentry> |
2591 |
++ |
2592 |
++ <varlistentry> |
2593 |
++ <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term> |
2594 |
++ <listitem><para> |
2595 |
++ Carries a <emphasis>bloom filter</emphasis> as |
2596 |
++ <type>struct kdbus_bloom_filter</type> in |
2597 |
++ <varname>item.bloom_filter</varname>. It is mandatory to send this |
2598 |
++ item attached to a <type>struct kdbus_msg</type>, in case the |
2599 |
++ message is a signal. This item is never transported from kernel to |
2600 |
++ userspace. See |
2601 |
++ <citerefentry> |
2602 |
++ <refentrytitle>kdbus.match</refentrytitle> |
2603 |
++ <manvolnum>7</manvolnum> |
2604 |
++ </citerefentry> |
2605 |
++ for more information on matching and bloom filters. |
2606 |
++ <programlisting> |
2607 |
++struct kdbus_bloom_filter { |
2608 |
++ __u64 generation; |
2609 |
++ __u64 data[0]; |
2610 |
++}; |
2611 |
++ </programlisting> |
2612 |
++ </para></listitem> |
2613 |
++ </varlistentry> |
2614 |
++ |
2615 |
++ <varlistentry> |
2616 |
++ <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term> |
2617 |
++ <listitem><para> |
2618 |
++ Transports a <emphasis>bloom mask</emphasis> as binary data blob |
2619 |
++ stored in <varname>item.data</varname>. This item is used to |
2620 |
++ describe a match into a connection's match database. See |
2621 |
++ <citerefentry> |
2622 |
++ <refentrytitle>kdbus.match</refentrytitle> |
2623 |
++ <manvolnum>7</manvolnum> |
2624 |
++ </citerefentry> |
2625 |
++ for more information on matching and bloom filters. |
2626 |
++ </para></listitem> |
2627 |
++ </varlistentry> |
2628 |
++ |
2629 |
++ <varlistentry> |
2630 |
++ <term><constant>KDBUS_ITEM_DST_NAME</constant></term> |
2631 |
++ <listitem><para> |
2632 |
++ Contains a <emphasis>well-known name</emphasis> to send a |
2633 |
++ message to, as null-terminated string in |
2634 |
++ <varname>item.str</varname>. This item is used with |
2635 |
++ <constant>KDBUS_CMD_SEND</constant>. See |
2636 |
++ <citerefentry> |
2637 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2638 |
++ <manvolnum>7</manvolnum> |
2639 |
++ </citerefentry> |
2640 |
++ for more information on how to send a message. |
2641 |
++ </para></listitem> |
2642 |
++ </varlistentry> |
2643 |
++ |
2644 |
++ <varlistentry> |
2645 |
++ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
2646 |
++ <listitem><para> |
2647 |
++ Contains a <emphasis>bus name</emphasis> or |
2648 |
++ <emphasis>endpoint name</emphasis>, stored as null-terminated |
2649 |
++ string in <varname>item.str</varname>. This item is sent from |
2650 |
++ userspace to kernel when buses or endpoints are created, and |
2651 |
++ returned back to userspace when the bus creator information is |
2652 |
++ queried. See |
2653 |
++ <citerefentry> |
2654 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
2655 |
++ <manvolnum>7</manvolnum> |
2656 |
++ </citerefentry> |
2657 |
++ and |
2658 |
++ <citerefentry> |
2659 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
2660 |
++ <manvolnum>7</manvolnum> |
2661 |
++ </citerefentry>. |
2662 |
++ </para></listitem> |
2663 |
++ </varlistentry> |
2664 |
++ |
2665 |
++ <varlistentry> |
2666 |
++ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
2667 |
++ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
2668 |
++ <listitem><para> |
2669 |
++ Contains a set of <emphasis>attach flags</emphasis> at |
2670 |
++ <emphasis>send</emphasis> or <emphasis>receive</emphasis> time. See |
2671 |
++ <citerefentry> |
2672 |
++ <refentrytitle>kdbus</refentrytitle> |
2673 |
++ <manvolnum>7</manvolnum> |
2674 |
++ </citerefentry>, |
2675 |
++ <citerefentry> |
2676 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
2677 |
++ <manvolnum>7</manvolnum> |
2678 |
++ </citerefentry> and |
2679 |
++ <citerefentry> |
2680 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
2681 |
++ <manvolnum>7</manvolnum> |
2682 |
++ </citerefentry> |
2683 |
++ for more information on attach flags. |
2684 |
++ </para></listitem> |
2685 |
++ </varlistentry> |
2686 |
++ |
2687 |
++ <varlistentry> |
2688 |
++ <term><constant>KDBUS_ITEM_ID</constant></term> |
2689 |
++ <listitem><para> |
2690 |
++ Transports a connection's <emphasis>numerical ID</emphasis> of |
2691 |
++ a connection as <type>uint64_t</type> value in |
2692 |
++ <varname>item.id</varname>. |
2693 |
++ </para></listitem> |
2694 |
++ </varlistentry> |
2695 |
++ |
2696 |
++ <varlistentry> |
2697 |
++ <term><constant>KDBUS_ITEM_NAME</constant></term> |
2698 |
++ <listitem><para> |
2699 |
++ Transports a name associated with the |
2700 |
++ <emphasis>name registry</emphasis> as null-terminated string as |
2701 |
++ <type>struct kdbus_name</type> in |
2702 |
++ <varname>item.name</varname>. The <varname>flags</varname> |
2703 |
++ contains the flags of the name. See |
2704 |
++ <citerefentry> |
2705 |
++ <refentrytitle>kdbus.name</refentrytitle> |
2706 |
++ <manvolnum>7</manvolnum> |
2707 |
++ </citerefentry> |
2708 |
++ for more information on how to access the name registry of a bus. |
2709 |
++ <programlisting> |
2710 |
++struct kdbus_name { |
2711 |
++ __u64 flags; |
2712 |
++ char name[0]; |
2713 |
++}; |
2714 |
++ </programlisting> |
2715 |
++ </para></listitem> |
2716 |
++ </varlistentry> |
2717 |
++ </variablelist> |
2718 |
++ </refsect2> |
2719 |
++ |
2720 |
++ <refsect2> |
2721 |
++ <title>Items attached by the kernel as metadata</title> |
2722 |
++ |
2723 |
++ <variablelist> |
2724 |
++ <varlistentry> |
2725 |
++ <term><constant>KDBUS_ITEM_TIMESTAMP</constant></term> |
2726 |
++ <listitem><para> |
2727 |
++ Contains both the <emphasis>monotonic</emphasis> and the |
2728 |
++ <emphasis>realtime</emphasis> timestamp, taken when the message |
2729 |
++ was processed on the kernel side. |
2730 |
++ Stored as <type>struct kdbus_timestamp</type> in |
2731 |
++ <varname>item.timestamp</varname>. |
2732 |
++ <programlisting> |
2733 |
++struct kdbus_timestamp { |
2734 |
++ __u64 seqnum; |
2735 |
++ __u64 monotonic_ns; |
2736 |
++ __u64 realtime_ns; |
2737 |
++}; |
2738 |
++ </programlisting> |
2739 |
++ </para></listitem> |
2740 |
++ </varlistentry> |
2741 |
++ |
2742 |
++ <varlistentry> |
2743 |
++ <term><constant>KDBUS_ITEM_CREDS</constant></term> |
2744 |
++ <listitem><para> |
2745 |
++ Contains a set of <emphasis>user</emphasis> and |
2746 |
++ <emphasis>group</emphasis> information as 32-bit values, in the |
2747 |
++ usual four flavors: real, effective, saved and filesystem related. |
2748 |
++ Stored as <type>struct kdbus_creds</type> in |
2749 |
++ <varname>item.creds</varname>. |
2750 |
++ <programlisting> |
2751 |
++struct kdbus_creds { |
2752 |
++ __u32 uid; |
2753 |
++ __u32 euid; |
2754 |
++ __u32 suid; |
2755 |
++ __u32 fsuid; |
2756 |
++ __u32 gid; |
2757 |
++ __u32 egid; |
2758 |
++ __u32 sgid; |
2759 |
++ __u32 fsgid; |
2760 |
++}; |
2761 |
++ </programlisting> |
2762 |
++ </para></listitem> |
2763 |
++ </varlistentry> |
2764 |
++ |
2765 |
++ <varlistentry> |
2766 |
++ <term><constant>KDBUS_ITEM_PIDS</constant></term> |
2767 |
++ <listitem><para> |
2768 |
++ Contains the <emphasis>PID</emphasis>, <emphasis>TID</emphasis> |
2769 |
++ and <emphasis>parent PID (PPID)</emphasis> of a remote peer. |
2770 |
++ Stored as <type>struct kdbus_pids</type> in |
2771 |
++ <varname>item.pids</varname>. |
2772 |
++ <programlisting> |
2773 |
++struct kdbus_pids { |
2774 |
++ __u64 pid; |
2775 |
++ __u64 tid; |
2776 |
++ __u64 ppid; |
2777 |
++}; |
2778 |
++ </programlisting> |
2779 |
++ </para></listitem> |
2780 |
++ </varlistentry> |
2781 |
++ |
2782 |
++ <varlistentry> |
2783 |
++ <term><constant>KDBUS_ITEM_AUXGROUPS</constant></term> |
2784 |
++ <listitem><para> |
2785 |
++ Contains the <emphasis>auxiliary (supplementary) groups</emphasis> |
2786 |
++ a remote peer is a member of, stored as array of |
2787 |
++ <type>uint32_t</type> values in <varname>item.data32</varname>. |
2788 |
++ The array length can be determined by looking at the item's total |
2789 |
++ size, subtracting the size of the header and dividing the |
2790 |
++ remainder by <constant>sizeof(uint32_t)</constant>. |
2791 |
++ </para></listitem> |
2792 |
++ </varlistentry> |
2793 |
++ |
2794 |
++ <varlistentry> |
2795 |
++ <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term> |
2796 |
++ <listitem><para> |
2797 |
++ Contains a <emphasis>well-known name</emphasis> currently owned |
2798 |
++ by a connection. The name is stored as null-terminated string in |
2799 |
++ <varname>item.str</varname>. Its length can also be derived from |
2800 |
++ the item's total size. |
2801 |
++ </para></listitem> |
2802 |
++ </varlistentry> |
2803 |
++ |
2804 |
++ <varlistentry> |
2805 |
++ <term><constant>KDBUS_ITEM_TID_COMM</constant> [*]</term> |
2806 |
++ <listitem><para> |
2807 |
++ Contains the <emphasis>comm</emphasis> string of a task's |
2808 |
++ <emphasis>TID</emphasis> (thread ID), stored as null-terminated |
2809 |
++ string in <varname>item.str</varname>. Its length can also be |
2810 |
++ derived from the item's total size. Receivers of this item should |
2811 |
++ not use its contents for any kind of security measures. See below. |
2812 |
++ </para></listitem> |
2813 |
++ </varlistentry> |
2814 |
++ |
2815 |
++ <varlistentry> |
2816 |
++ <term><constant>KDBUS_ITEM_PID_COMM</constant> [*]</term> |
2817 |
++ <listitem><para> |
2818 |
++ Contains the <emphasis>comm</emphasis> string of a task's |
2819 |
++ <emphasis>PID</emphasis> (process ID), stored as null-terminated |
2820 |
++ string in <varname>item.str</varname>. Its length can also be |
2821 |
++ derived from the item's total size. Receivers of this item should |
2822 |
++ not use its contents for any kind of security measures. See below. |
2823 |
++ </para></listitem> |
2824 |
++ </varlistentry> |
2825 |
++ |
2826 |
++ <varlistentry> |
2827 |
++ <term><constant>KDBUS_ITEM_EXE</constant> [*]</term> |
2828 |
++ <listitem><para> |
2829 |
++ Contains the <emphasis>path to the executable</emphasis> of a task, |
2830 |
++ stored as null-terminated string in <varname>item.str</varname>. Its |
2831 |
++ length can also be derived from the item's total size. Receivers of |
2832 |
++ this item should not use its contents for any kind of security |
2833 |
++ measures. See below. |
2834 |
++ </para></listitem> |
2835 |
++ </varlistentry> |
2836 |
++ |
2837 |
++ <varlistentry> |
2838 |
++ <term><constant>KDBUS_ITEM_CMDLINE</constant> [*]</term> |
2839 |
++ <listitem><para> |
2840 |
++ Contains the <emphasis>command line arguments</emphasis> of a |
2841 |
++ task, stored as an <emphasis>array</emphasis> of null-terminated |
2842 |
++ strings in <varname>item.str</varname>. The total length of all |
2843 |
++ strings in the array can be derived from the item's total size. |
2844 |
++ Receivers of this item should not use its contents for any kind |
2845 |
++ of security measures. See below. |
2846 |
++ </para></listitem> |
2847 |
++ </varlistentry> |
2848 |
++ |
2849 |
++ <varlistentry> |
2850 |
++ <term><constant>KDBUS_ITEM_CGROUP</constant></term> |
2851 |
++ <listitem><para> |
2852 |
++ Contains the <emphasis>cgroup path</emphasis> of a task, stored |
2853 |
++ as null-terminated string in <varname>item.str</varname>. Its |
2854 |
++ length can also be derived from the item's total size. |
2855 |
++ </para></listitem> |
2856 |
++ </varlistentry> |
2857 |
++ |
2858 |
++ <varlistentry> |
2859 |
++ <term><constant>KDBUS_ITEM_CAPS</constant></term> |
2860 |
++ <listitem><para> |
2861 |
++ Contains sets of <emphasis>capabilities</emphasis>, stored as |
2862 |
++ <type>struct kdbus_caps</type> in <varname>item.caps</varname>. |
2863 |
++ As the item size may increase in the future, programs should be |
2864 |
++ written in a way that it takes |
2865 |
++ <varname>item.caps.last_cap</varname> into account, and derive |
2866 |
++ the number of sets and rows from the item size and the reported |
2867 |
++ number of valid capability bits. |
2868 |
++ <programlisting> |
2869 |
++struct kdbus_caps { |
2870 |
++ __u32 last_cap; |
2871 |
++ __u32 caps[0]; |
2872 |
++}; |
2873 |
++ </programlisting> |
2874 |
++ </para></listitem> |
2875 |
++ </varlistentry> |
2876 |
++ |
2877 |
++ <varlistentry> |
2878 |
++ <term><constant>KDBUS_ITEM_SECLABEL</constant></term> |
2879 |
++ <listitem><para> |
2880 |
++ Contains the <emphasis>LSM label</emphasis> of a task, stored as |
2881 |
++ null-terminated string in <varname>item.str</varname>. Its length |
2882 |
++ can also be derived from the item's total size. |
2883 |
++ </para></listitem> |
2884 |
++ </varlistentry> |
2885 |
++ |
2886 |
++ <varlistentry> |
2887 |
++ <term><constant>KDBUS_ITEM_AUDIT</constant></term> |
2888 |
++ <listitem><para> |
2889 |
++ Contains the audit <emphasis>sessionid</emphasis> and |
2890 |
++ <emphasis>loginuid</emphasis> of a task, stored as |
2891 |
++ <type>struct kdbus_audit</type> in |
2892 |
++ <varname>item.audit</varname>. |
2893 |
++ <programlisting> |
2894 |
++struct kdbus_audit { |
2895 |
++ __u32 sessionid; |
2896 |
++ __u32 loginuid; |
2897 |
++}; |
2898 |
++ </programlisting> |
2899 |
++ </para></listitem> |
2900 |
++ </varlistentry> |
2901 |
++ |
2902 |
++ <varlistentry> |
2903 |
++ <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term> |
2904 |
++ <listitem><para> |
2905 |
++ Contains the <emphasis>connection description</emphasis>, as set |
2906 |
++ by <constant>KDBUS_CMD_HELLO</constant> or |
2907 |
++ <constant>KDBUS_CMD_CONN_UPDATE</constant>, stored as |
2908 |
++ null-terminated string in <varname>item.str</varname>. Its length |
2909 |
++ can also be derived from the item's total size. |
2910 |
++ </para></listitem> |
2911 |
++ </varlistentry> |
2912 |
++ </variablelist> |
2913 |
++ |
2914 |
++ <para> |
2915 |
++ All metadata is automatically translated into the |
2916 |
++ <emphasis>namespaces</emphasis> of the task that receives them. See |
2917 |
++ <citerefentry> |
2918 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2919 |
++ <manvolnum>7</manvolnum> |
2920 |
++ </citerefentry> |
2921 |
++ for more information. |
2922 |
++ </para> |
2923 |
++ |
2924 |
++ <para> |
2925 |
++ [*] Note that the content stored in metadata items of type |
2926 |
++ <constant>KDBUS_ITEM_TID_COMM</constant>, |
2927 |
++ <constant>KDBUS_ITEM_PID_COMM</constant>, |
2928 |
++ <constant>KDBUS_ITEM_EXE</constant> and |
2929 |
++ <constant>KDBUS_ITEM_CMDLINE</constant> |
2930 |
++ can easily be tampered by the sending tasks. Therefore, they should |
2931 |
++ <emphasis>not</emphasis> be used for any sort of security relevant |
2932 |
++ assumptions. The only reason they are transmitted is to let |
2933 |
++ receivers know about details that were set when metadata was |
2934 |
++ collected, even though the task they were collected from is not |
2935 |
++ active any longer when the items are received. |
2936 |
++ </para> |
2937 |
++ </refsect2> |
2938 |
++ |
2939 |
++ <refsect2> |
2940 |
++ <title>Items used for policy entries, matches and notifications</title> |
2941 |
++ |
2942 |
++ <variablelist> |
2943 |
++ <varlistentry> |
2944 |
++ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
2945 |
++ <listitem><para> |
2946 |
++ This item describes a <emphasis>policy access</emphasis> entry to |
2947 |
++ access the policy database of a |
2948 |
++ <citerefentry> |
2949 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
2950 |
++ <manvolnum>7</manvolnum> |
2951 |
++ </citerefentry> or |
2952 |
++ <citerefentry> |
2953 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
2954 |
++ <manvolnum>7</manvolnum> |
2955 |
++ </citerefentry>. |
2956 |
++ Please refer to |
2957 |
++ <citerefentry> |
2958 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
2959 |
++ <manvolnum>7</manvolnum> |
2960 |
++ </citerefentry> |
2961 |
++ for more information on the policy database and how to access it. |
2962 |
++ <programlisting> |
2963 |
++struct kdbus_policy_access { |
2964 |
++ __u64 type; |
2965 |
++ __u64 access; |
2966 |
++ __u64 id; |
2967 |
++}; |
2968 |
++ </programlisting> |
2969 |
++ </para></listitem> |
2970 |
++ </varlistentry> |
2971 |
++ |
2972 |
++ <varlistentry> |
2973 |
++ <term><constant>KDBUS_ITEM_ID_ADD</constant></term> |
2974 |
++ <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term> |
2975 |
++ <listitem><para> |
2976 |
++ This item is sent as attachment to a |
2977 |
++ <emphasis>kernel notification</emphasis> and indicates that a |
2978 |
++ new connection was created on the bus, or that a connection was |
2979 |
++ disconnected, respectively. It stores a |
2980 |
++ <type>struct kdbus_notify_id_change</type> in |
2981 |
++ <varname>item.id_change</varname>. |
2982 |
++ The <varname>id</varname> field contains the numeric ID of the |
2983 |
++ connection that was added or removed, and <varname>flags</varname> |
2984 |
++ is set to the connection flags, as passed by |
2985 |
++ <constant>KDBUS_CMD_HELLO</constant>. See |
2986 |
++ <citerefentry> |
2987 |
++ <refentrytitle>kdbus.match</refentrytitle> |
2988 |
++ <manvolnum>7</manvolnum> |
2989 |
++ </citerefentry> |
2990 |
++ and |
2991 |
++ <citerefentry> |
2992 |
++ <refentrytitle>kdbus.message</refentrytitle> |
2993 |
++ <manvolnum>7</manvolnum> |
2994 |
++ </citerefentry> |
2995 |
++ for more information on matches and notification messages. |
2996 |
++ <programlisting> |
2997 |
++struct kdbus_notify_id_change { |
2998 |
++ __u64 id; |
2999 |
++ __u64 flags; |
3000 |
++}; |
3001 |
++ </programlisting> |
3002 |
++ </para></listitem> |
3003 |
++ </varlistentry> |
3004 |
++ |
3005 |
++ <varlistentry> |
3006 |
++ <term><constant>KDBUS_ITEM_NAME_ADD</constant></term> |
3007 |
++ <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term> |
3008 |
++ <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term> |
3009 |
++ <listitem><para> |
3010 |
++ This item is sent as attachment to a |
3011 |
++ <emphasis>kernel notification</emphasis> and indicates that a |
3012 |
++ <emphasis>well-known name</emphasis> appeared, disappeared or |
3013 |
++ transferred to another owner on the bus. It stores a |
3014 |
++ <type>struct kdbus_notify_name_change</type> in |
3015 |
++ <varname>item.name_change</varname>. |
3016 |
++ <varname>old_id</varname> describes the former owner of the name |
3017 |
++ and is set to <constant>0</constant> values in case of |
3018 |
++ <constant>KDBUS_ITEM_NAME_ADD</constant>. |
3019 |
++ <varname>new_id</varname> describes the new owner of the name and |
3020 |
++ is set to <constant>0</constant> values in case of |
3021 |
++ <constant>KDBUS_ITEM_NAME_REMOVE</constant>. |
3022 |
++ The <varname>name</varname> field contains the well-known name the |
3023 |
++ notification is about, as null-terminated string. See |
3024 |
++ <citerefentry> |
3025 |
++ <refentrytitle>kdbus.match</refentrytitle> |
3026 |
++ <manvolnum>7</manvolnum> |
3027 |
++ </citerefentry> |
3028 |
++ and |
3029 |
++ <citerefentry> |
3030 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3031 |
++ <manvolnum>7</manvolnum> |
3032 |
++ </citerefentry> |
3033 |
++ for more information on matches and notification messages. |
3034 |
++ <programlisting> |
3035 |
++struct kdbus_notify_name_change { |
3036 |
++ struct kdbus_notify_id_change old_id; |
3037 |
++ struct kdbus_notify_id_change new_id; |
3038 |
++ char name[0]; |
3039 |
++}; |
3040 |
++ </programlisting> |
3041 |
++ </para></listitem> |
3042 |
++ </varlistentry> |
3043 |
++ |
3044 |
++ <varlistentry> |
3045 |
++ <term><constant>KDBUS_ITEM_REPLY_TIMEOUT</constant></term> |
3046 |
++ <listitem><para> |
3047 |
++ This item is sent as attachment to a |
3048 |
++ <emphasis>kernel notification</emphasis>. It informs the receiver |
3049 |
++ that an expected reply to a message was not received in time. |
3050 |
++ The remote peer ID and the message cookie are stored in the message |
3051 |
++ header. See |
3052 |
++ <citerefentry> |
3053 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3054 |
++ <manvolnum>7</manvolnum> |
3055 |
++ </citerefentry> |
3056 |
++ for more information about messages, timeouts and notifications. |
3057 |
++ </para></listitem> |
3058 |
++ </varlistentry> |
3059 |
++ |
3060 |
++ <varlistentry> |
3061 |
++ <term><constant>KDBUS_ITEM_REPLY_DEAD</constant></term> |
3062 |
++ <listitem><para> |
3063 |
++ This item is sent as attachment to a |
3064 |
++ <emphasis>kernel notification</emphasis>. It informs the receiver |
3065 |
++ that a remote connection a reply is expected from was disconnected |
3066 |
++ before that reply was sent. The remote peer ID and the message |
3067 |
++ cookie are stored in the message header. See |
3068 |
++ <citerefentry> |
3069 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3070 |
++ <manvolnum>7</manvolnum> |
3071 |
++ </citerefentry> |
3072 |
++ for more information about messages, timeouts and notifications. |
3073 |
++ </para></listitem> |
3074 |
++ </varlistentry> |
3075 |
++ </variablelist> |
3076 |
++ </refsect2> |
3077 |
++ </refsect1> |
3078 |
++ |
3079 |
++ <refsect1> |
3080 |
++ <title>See Also</title> |
3081 |
++ <simplelist type="inline"> |
3082 |
++ <member> |
3083 |
++ <citerefentry> |
3084 |
++ <refentrytitle>kdbus</refentrytitle> |
3085 |
++ <manvolnum>7</manvolnum> |
3086 |
++ </citerefentry> |
3087 |
++ </member> |
3088 |
++ <member> |
3089 |
++ <citerefentry> |
3090 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
3091 |
++ <manvolnum>7</manvolnum> |
3092 |
++ </citerefentry> |
3093 |
++ </member> |
3094 |
++ <member> |
3095 |
++ <citerefentry> |
3096 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
3097 |
++ <manvolnum>7</manvolnum> |
3098 |
++ </citerefentry> |
3099 |
++ </member> |
3100 |
++ <member> |
3101 |
++ <citerefentry> |
3102 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
3103 |
++ <manvolnum>7</manvolnum> |
3104 |
++ </citerefentry> |
3105 |
++ </member> |
3106 |
++ <member> |
3107 |
++ <citerefentry> |
3108 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
3109 |
++ <manvolnum>7</manvolnum> |
3110 |
++ </citerefentry> |
3111 |
++ </member> |
3112 |
++ <member> |
3113 |
++ <citerefentry> |
3114 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3115 |
++ <manvolnum>7</manvolnum> |
3116 |
++ </citerefentry> |
3117 |
++ </member> |
3118 |
++ <member> |
3119 |
++ <citerefentry> |
3120 |
++ <refentrytitle>kdbus.name</refentrytitle> |
3121 |
++ <manvolnum>7</manvolnum> |
3122 |
++ </citerefentry> |
3123 |
++ </member> |
3124 |
++ <member> |
3125 |
++ <citerefentry> |
3126 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
3127 |
++ <manvolnum>7</manvolnum> |
3128 |
++ </citerefentry> |
3129 |
++ </member> |
3130 |
++ <member> |
3131 |
++ <citerefentry> |
3132 |
++ <refentrytitle>memfd_create</refentrytitle> |
3133 |
++ <manvolnum>2</manvolnum> |
3134 |
++ </citerefentry> |
3135 |
++ </member> |
3136 |
++ </simplelist> |
3137 |
++ </refsect1> |
3138 |
++ |
3139 |
++</refentry> |
3140 |
+diff --git a/Documentation/kdbus/kdbus.match.xml b/Documentation/kdbus/kdbus.match.xml |
3141 |
+new file mode 100644 |
3142 |
+index 0000000..ae38e04 |
3143 |
+--- /dev/null |
3144 |
++++ b/Documentation/kdbus/kdbus.match.xml |
3145 |
+@@ -0,0 +1,555 @@ |
3146 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
3147 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
3148 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
3149 |
++ |
3150 |
++<refentry id="kdbus.match"> |
3151 |
++ |
3152 |
++ <refentryinfo> |
3153 |
++ <title>kdbus.match</title> |
3154 |
++ <productname>kdbus.match</productname> |
3155 |
++ </refentryinfo> |
3156 |
++ |
3157 |
++ <refmeta> |
3158 |
++ <refentrytitle>kdbus.match</refentrytitle> |
3159 |
++ <manvolnum>7</manvolnum> |
3160 |
++ </refmeta> |
3161 |
++ |
3162 |
++ <refnamediv> |
3163 |
++ <refname>kdbus.match</refname> |
3164 |
++ <refpurpose>kdbus match</refpurpose> |
3165 |
++ </refnamediv> |
3166 |
++ |
3167 |
++ <refsect1> |
3168 |
++ <title>Description</title> |
3169 |
++ |
3170 |
++ <para> |
3171 |
++ kdbus connections can install matches in order to subscribe to signal |
3172 |
++ messages sent on the bus. Such signal messages can be either directed |
3173 |
++ to a single connection (by setting a specific connection ID in |
3174 |
++ <varname>struct kdbus_msg.dst_id</varname> or by sending it to a |
3175 |
++ well-known name), or to potentially <emphasis>all</emphasis> currently |
3176 |
++ active connections on the bus (by setting |
3177 |
++ <varname>struct kdbus_msg.dst_id</varname> to |
3178 |
++ <constant>KDBUS_DST_ID_BROADCAST</constant>). |
3179 |
++ A signal message always has the <constant>KDBUS_MSG_SIGNAL</constant> |
3180 |
++ bit set in the <varname>flags</varname> bitfield. |
3181 |
++ Also, signal messages can originate from either the kernel (called |
3182 |
++ <emphasis>notifications</emphasis>), or from other bus connections. |
3183 |
++ In either case, a bus connection needs to have a suitable |
3184 |
++ <emphasis>match</emphasis> installed in order to receive any signal |
3185 |
++ message. Without any rules installed in the connection, no signal message |
3186 |
++ will be received. |
3187 |
++ </para> |
3188 |
++ </refsect1> |
3189 |
++ |
3190 |
++ <refsect1> |
3191 |
++ <title>Matches for signal messages from other connections</title> |
3192 |
++ <para> |
3193 |
++ Matches for messages from other connections (not kernel notifications) |
3194 |
++ are implemented as bloom filters (see below). The sender adds certain |
3195 |
++ properties of the message as elements to a bloom filter bit field, and |
3196 |
++ sends that along with the signal message. |
3197 |
++ |
3198 |
++ The receiving connection adds the message properties it is interested in |
3199 |
++ as elements to a bloom mask bit field, and uploads the mask as match rule, |
3200 |
++ possibly along with some other rules to further limit the match. |
3201 |
++ |
3202 |
++ The kernel will match the signal message's bloom filter against the |
3203 |
++ connection's bloom mask (simply by &-ing it), and will decide whether |
3204 |
++ the message should be delivered to a connection. |
3205 |
++ </para> |
3206 |
++ <para> |
3207 |
++ The kernel has no notion of any specific properties of the signal message, |
3208 |
++ all it sees are the bit fields of the bloom filter and the mask to match |
3209 |
++ against. The use of bloom filters allows simple and efficient matching, |
3210 |
++ without exposing any message properties or internals to the kernel side. |
3211 |
++ Clients need to deal with the fact that they might receive signal messages |
3212 |
++ which they did not subscribe to, as the bloom filter might allow |
3213 |
++ false-positives to pass the filter. |
3214 |
++ |
3215 |
++ To allow the future extension of the set of elements in the bloom filter, |
3216 |
++ the filter specifies a <emphasis>generation</emphasis> number. A later |
3217 |
++ generation must always contain all elements of the set of the previous |
3218 |
++ generation, but can add new elements to the set. The match rules mask can |
3219 |
++ carry an array with all previous generations of masks individually stored. |
3220 |
++ When the filter and mask are matched by the kernel, the mask with the |
3221 |
++ closest matching generation is selected as the index into the mask array. |
3222 |
++ </para> |
3223 |
++ </refsect1> |
3224 |
++ |
3225 |
++ <refsect1> |
3226 |
++ <title>Bloom filters</title> |
3227 |
++ <para> |
3228 |
++ Bloom filters allow checking whether a given word is present in a |
3229 |
++ dictionary. This allows connections to set up a mask for information it |
3230 |
++ is interested in, and will be delivered signal messages that have a |
3231 |
++ matching filter. |
3232 |
++ |
3233 |
++ For general information, see |
3234 |
++ <ulink url="https://en.wikipedia.org/wiki/Bloom_filter">the Wikipedia |
3235 |
++ article on bloom filters</ulink>. |
3236 |
++ </para> |
3237 |
++ <para> |
3238 |
++ The size of the bloom filter is defined per bus when it is created, in |
3239 |
++ <varname>kdbus_bloom_parameter.size</varname>. All bloom filters attached |
3240 |
++ to signal messages on the bus must match this size, and all bloom filter |
3241 |
++ matches uploaded by connections must also match the size, or a multiple |
3242 |
++ thereof (see below). |
3243 |
++ |
3244 |
++ The calculation of the mask has to be done in userspace applications. The |
3245 |
++ kernel just checks the bitmasks to decide whether or not to let the |
3246 |
++ message pass. All bits in the mask must match the filter in and bit-wise |
3247 |
++ <emphasis>AND</emphasis> logic, but the mask may have more bits set than |
3248 |
++ the filter. Consequently, false positive matches are expected to happen, |
3249 |
++ and programs must deal with that fact by checking the contents of the |
3250 |
++ payload again at receive time. |
3251 |
++ </para> |
3252 |
++ <para> |
3253 |
++ Masks are entities that are always passed to the kernel as part of a |
3254 |
++ match (with an item of type <constant>KDBUS_ITEM_BLOOM_MASK</constant>), |
3255 |
++ and filters can be attached to signals, with an item of type |
3256 |
++ <constant>KDBUS_ITEM_BLOOM_FILTER</constant>. For a filter to match, all |
3257 |
++ its bits have to be set in the match mask as well. |
3258 |
++ </para> |
3259 |
++ <para> |
3260 |
++ For example, consider a bus that has a bloom size of 8 bytes, and the |
3261 |
++ following mask/filter combinations: |
3262 |
++ </para> |
3263 |
++ <programlisting><![CDATA[ |
3264 |
++ filter 0x0101010101010101 |
3265 |
++ mask 0x0101010101010101 |
3266 |
++ -> matches |
3267 |
++ |
3268 |
++ filter 0x0303030303030303 |
3269 |
++ mask 0x0101010101010101 |
3270 |
++ -> doesn't match |
3271 |
++ |
3272 |
++ filter 0x0101010101010101 |
3273 |
++ mask 0x0303030303030303 |
3274 |
++ -> matches |
3275 |
++ ]]></programlisting> |
3276 |
++ |
3277 |
++ <para> |
3278 |
++ Hence, in order to catch all messages, a mask filled with |
3279 |
++ <constant>0xff</constant> bytes can be installed as a wildcard match rule. |
3280 |
++ </para> |
3281 |
++ |
3282 |
++ <refsect2> |
3283 |
++ <title>Generations</title> |
3284 |
++ |
3285 |
++ <para> |
3286 |
++ Uploaded matches may contain multiple masks, which have to be as large |
3287 |
++ as the bloom filter size defined by the bus. Each block of a mask is |
3288 |
++ called a <emphasis>generation</emphasis>, starting at index 0. |
3289 |
++ |
3290 |
++ At match time, when a signal is about to be delivered, a bloom mask |
3291 |
++ generation is passed, which denotes which of the bloom masks the filter |
3292 |
++ should be matched against. This allows programs to provide backward |
3293 |
++ compatible masks at upload time, while older clients can still match |
3294 |
++ against older versions of filters. |
3295 |
++ </para> |
3296 |
++ </refsect2> |
3297 |
++ </refsect1> |
3298 |
++ |
3299 |
++ <refsect1> |
3300 |
++ <title>Matches for kernel notifications</title> |
3301 |
++ <para> |
3302 |
++ To receive kernel generated notifications (see |
3303 |
++ <citerefentry> |
3304 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3305 |
++ <manvolnum>7</manvolnum> |
3306 |
++ </citerefentry>), |
3307 |
++ a connection must install match rules that are different from |
3308 |
++ the bloom filter matches described in the section above. They can be |
3309 |
++ filtered by the connection ID that caused the notification to be sent, by |
3310 |
++ one of the names it currently owns, or by the type of the notification |
3311 |
++ (ID/name add/remove/change). |
3312 |
++ </para> |
3313 |
++ </refsect1> |
3314 |
++ |
3315 |
++ <refsect1> |
3316 |
++ <title>Adding a match</title> |
3317 |
++ <para> |
3318 |
++ To add a match, the <constant>KDBUS_CMD_MATCH_ADD</constant> ioctl is |
3319 |
++ used, which takes a <type>struct kdbus_cmd_match</type> as an argument |
3320 |
++ described below. |
3321 |
++ |
3322 |
++ Note that each of the items attached to this command will internally |
3323 |
++ create one match <emphasis>rule</emphasis>, and the collection of them, |
3324 |
++ which is submitted as one block via the ioctl, is called a |
3325 |
++ <emphasis>match</emphasis>. To allow a message to pass, all rules of a |
3326 |
++ match have to be satisfied. Hence, adding more items to the command will |
3327 |
++ only narrow the possibility of a match to effectively let the message |
3328 |
++ pass, and will decrease the chance that the connection's process will be |
3329 |
++ woken up needlessly. |
3330 |
++ |
3331 |
++ Multiple matches can be installed per connection. As long as one of it has |
3332 |
++ a set of rules which allows the message to pass, this one will be |
3333 |
++ decisive. |
3334 |
++ </para> |
3335 |
++ |
3336 |
++ <programlisting> |
3337 |
++struct kdbus_cmd_match { |
3338 |
++ __u64 size; |
3339 |
++ __u64 flags; |
3340 |
++ __u64 return_flags; |
3341 |
++ __u64 cookie; |
3342 |
++ struct kdbus_item items[0]; |
3343 |
++}; |
3344 |
++ </programlisting> |
3345 |
++ |
3346 |
++ <para>The fields in this struct are described below.</para> |
3347 |
++ |
3348 |
++ <variablelist> |
3349 |
++ <varlistentry> |
3350 |
++ <term><varname>size</varname></term> |
3351 |
++ <listitem><para> |
3352 |
++ The overall size of the struct, including its items. |
3353 |
++ </para></listitem> |
3354 |
++ </varlistentry> |
3355 |
++ |
3356 |
++ <varlistentry> |
3357 |
++ <term><varname>flags</varname></term> |
3358 |
++ <listitem><para>Flags to control the behavior of the ioctl.</para> |
3359 |
++ <variablelist> |
3360 |
++ <varlistentry> |
3361 |
++ <term><constant>KDBUS_MATCH_REPLACE</constant></term> |
3362 |
++ <listitem> |
3363 |
++ <para>Make the endpoint file group-accessible</para> |
3364 |
++ </listitem> |
3365 |
++ </varlistentry> |
3366 |
++ |
3367 |
++ <varlistentry> |
3368 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
3369 |
++ <listitem> |
3370 |
++ <para> |
3371 |
++ Requests a set of valid flags for this ioctl. When this bit is |
3372 |
++ set, no action is taken; the ioctl will return |
3373 |
++ <errorcode>0</errorcode>, and the <varname>flags</varname> |
3374 |
++ field will have all bits set that are valid for this command. |
3375 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
3376 |
++ cleared by the operation. |
3377 |
++ </para> |
3378 |
++ </listitem> |
3379 |
++ </varlistentry> |
3380 |
++ </variablelist> |
3381 |
++ </listitem> |
3382 |
++ </varlistentry> |
3383 |
++ |
3384 |
++ <varlistentry> |
3385 |
++ <term><varname>return_flags</varname></term> |
3386 |
++ <listitem><para> |
3387 |
++ Flags returned by the kernel. Currently unused and always set to |
3388 |
++ <constant>0</constant> by the kernel. |
3389 |
++ </para></listitem> |
3390 |
++ </varlistentry> |
3391 |
++ |
3392 |
++ <varlistentry> |
3393 |
++ <term><varname>cookie</varname></term> |
3394 |
++ <listitem><para> |
3395 |
++ A cookie which identifies the match, so it can be referred to when |
3396 |
++ removing it. |
3397 |
++ </para></listitem> |
3398 |
++ </varlistentry> |
3399 |
++ |
3400 |
++ <varlistentry> |
3401 |
++ <term><varname>items</varname></term> |
3402 |
++ <listitem> |
3403 |
++ <para> |
3404 |
++ Items to define the actual rules of the matches. The following item |
3405 |
++ types are expected. Each item will create one new match rule. |
3406 |
++ </para> |
3407 |
++ <variablelist> |
3408 |
++ <varlistentry> |
3409 |
++ <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term> |
3410 |
++ <listitem> |
3411 |
++ <para> |
3412 |
++ An item that carries the bloom filter mask to match against |
3413 |
++ in its data field. The payload size must match the bloom |
3414 |
++ filter size that was specified when the bus was created. |
3415 |
++ See the "Bloom filters" section above for more information on |
3416 |
++ bloom filters. |
3417 |
++ </para> |
3418 |
++ </listitem> |
3419 |
++ </varlistentry> |
3420 |
++ |
3421 |
++ <varlistentry> |
3422 |
++ <term><constant>KDBUS_ITEM_NAME</constant></term> |
3423 |
++ <listitem> |
3424 |
++ <para> |
3425 |
++ When used as part of kernel notifications, this item specifies |
3426 |
++ a name that is acquired, lost or that changed its owner (see |
3427 |
++ below). When used as part of a match for user-generated signal |
3428 |
++ messages, it specifies a name that the sending connection must |
3429 |
++ own at the time of sending the signal. |
3430 |
++ </para> |
3431 |
++ </listitem> |
3432 |
++ </varlistentry> |
3433 |
++ |
3434 |
++ <varlistentry> |
3435 |
++ <term><constant>KDBUS_ITEM_ID</constant></term> |
3436 |
++ <listitem> |
3437 |
++ <para> |
3438 |
++ Specify a sender connection's ID that will match this rule. |
3439 |
++ For kernel notifications, this specifies the ID of a |
3440 |
++ connection that was added to or removed from the bus. |
3441 |
++ For used-generated signals, it specifies the ID of the |
3442 |
++ connection that sent the signal message. |
3443 |
++ </para> |
3444 |
++ </listitem> |
3445 |
++ </varlistentry> |
3446 |
++ |
3447 |
++ <varlistentry> |
3448 |
++ <term><constant>KDBUS_ITEM_NAME_ADD</constant></term> |
3449 |
++ <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term> |
3450 |
++ <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term> |
3451 |
++ <listitem> |
3452 |
++ <para> |
3453 |
++ These items request delivery of kernel notifications that |
3454 |
++ describe a name acquisition, loss, or change. The details |
3455 |
++ are stored in the item's |
3456 |
++ <varname>kdbus_notify_name_change</varname> member. |
3457 |
++ All information specified must be matched in order to make |
3458 |
++ the message pass. Use |
3459 |
++ <constant>KDBUS_MATCH_ID_ANY</constant> to |
3460 |
++ match against any unique connection ID. |
3461 |
++ </para> |
3462 |
++ </listitem> |
3463 |
++ </varlistentry> |
3464 |
++ |
3465 |
++ <varlistentry> |
3466 |
++ <term><constant>KDBUS_ITEM_ID_ADD</constant></term> |
3467 |
++ <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term> |
3468 |
++ <listitem> |
3469 |
++ <para> |
3470 |
++ These items request delivery of kernel notifications that are |
3471 |
++ generated when a connection is created or terminated. |
3472 |
++ <type>struct kdbus_notify_id_change</type> is used to |
3473 |
++ store the actual match information. This item can be used to |
3474 |
++ monitor one particular connection ID, or, when the ID field |
3475 |
++ is set to <constant>KDBUS_MATCH_ID_ANY</constant>, |
3476 |
++ all of them. |
3477 |
++ </para> |
3478 |
++ </listitem> |
3479 |
++ </varlistentry> |
3480 |
++ |
3481 |
++ <varlistentry> |
3482 |
++ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
3483 |
++ <listitem><para> |
3484 |
++ With this item, programs can <emphasis>probe</emphasis> the |
3485 |
++ kernel for known item types. See |
3486 |
++ <citerefentry> |
3487 |
++ <refentrytitle>kdbus.item</refentrytitle> |
3488 |
++ <manvolnum>7</manvolnum> |
3489 |
++ </citerefentry> |
3490 |
++ for more details. |
3491 |
++ </para></listitem> |
3492 |
++ </varlistentry> |
3493 |
++ </variablelist> |
3494 |
++ |
3495 |
++ <para> |
3496 |
++ Unrecognized items are rejected, and the ioctl will fail with |
3497 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
3498 |
++ </para> |
3499 |
++ </listitem> |
3500 |
++ </varlistentry> |
3501 |
++ </variablelist> |
3502 |
++ |
3503 |
++ <para> |
3504 |
++ Refer to |
3505 |
++ <citerefentry> |
3506 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3507 |
++ <manvolnum>7</manvolnum> |
3508 |
++ </citerefentry> |
3509 |
++ for more information on message types. |
3510 |
++ </para> |
3511 |
++ </refsect1> |
3512 |
++ |
3513 |
++ <refsect1> |
3514 |
++ <title>Removing a match</title> |
3515 |
++ <para> |
3516 |
++ Matches can be removed with the |
3517 |
++ <constant>KDBUS_CMD_MATCH_REMOVE</constant> ioctl, which takes |
3518 |
++ <type>struct kdbus_cmd_match</type> as argument, but its fields |
3519 |
++ usage slightly differs compared to that of |
3520 |
++ <constant>KDBUS_CMD_MATCH_ADD</constant>. |
3521 |
++ </para> |
3522 |
++ |
3523 |
++ <programlisting> |
3524 |
++struct kdbus_cmd_match { |
3525 |
++ __u64 size; |
3526 |
++ __u64 cookie; |
3527 |
++ __u64 flags; |
3528 |
++ __u64 return_flags; |
3529 |
++ struct kdbus_item items[0]; |
3530 |
++}; |
3531 |
++ </programlisting> |
3532 |
++ |
3533 |
++ <para>The fields in this struct are described below.</para> |
3534 |
++ |
3535 |
++ <variablelist> |
3536 |
++ <varlistentry> |
3537 |
++ <term><varname>size</varname></term> |
3538 |
++ <listitem><para> |
3539 |
++ The overall size of the struct, including its items. |
3540 |
++ </para></listitem> |
3541 |
++ </varlistentry> |
3542 |
++ |
3543 |
++ <varlistentry> |
3544 |
++ <term><varname>cookie</varname></term> |
3545 |
++ <listitem><para> |
3546 |
++ The cookie of the match, as it was passed when the match was added. |
3547 |
++ All matches that have this cookie will be removed. |
3548 |
++ </para></listitem> |
3549 |
++ </varlistentry> |
3550 |
++ |
3551 |
++ <varlistentry> |
3552 |
++ <term><varname>flags</varname></term> |
3553 |
++ <listitem><para> |
3554 |
++ No flags are supported for this use case. |
3555 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
3556 |
++ valid flags. If set, the ioctl will fail with |
3557 |
++ <errorcode>-1</errorcode>, <varname>errno</varname> is set to |
3558 |
++ <constant>EPROTO</constant>, and the <varname>flags</varname> field |
3559 |
++ is set to <constant>0</constant>. |
3560 |
++ </para></listitem> |
3561 |
++ </varlistentry> |
3562 |
++ |
3563 |
++ <varlistentry> |
3564 |
++ <term><varname>return_flags</varname></term> |
3565 |
++ <listitem><para> |
3566 |
++ Flags returned by the kernel. Currently unused and always set to |
3567 |
++ <constant>0</constant> by the kernel. |
3568 |
++ </para></listitem> |
3569 |
++ </varlistentry> |
3570 |
++ |
3571 |
++ <varlistentry> |
3572 |
++ <term><varname>items</varname></term> |
3573 |
++ <listitem> |
3574 |
++ <para> |
3575 |
++ No items are supported for this use case, but |
3576 |
++ <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed nevertheless. |
3577 |
++ </para> |
3578 |
++ </listitem> |
3579 |
++ </varlistentry> |
3580 |
++ </variablelist> |
3581 |
++ </refsect1> |
3582 |
++ |
3583 |
++ <refsect1> |
3584 |
++ <title>Return value</title> |
3585 |
++ <para> |
3586 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
3587 |
++ on error, <errorcode>-1</errorcode> is returned, and |
3588 |
++ <varname>errno</varname> is set to indicate the error. |
3589 |
++ If the issued ioctl is illegal for the file descriptor used, |
3590 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
3591 |
++ </para> |
3592 |
++ |
3593 |
++ <refsect2> |
3594 |
++ <title> |
3595 |
++ <constant>KDBUS_CMD_MATCH_ADD</constant> may fail with the following |
3596 |
++ errors |
3597 |
++ </title> |
3598 |
++ |
3599 |
++ <variablelist> |
3600 |
++ <varlistentry> |
3601 |
++ <term><constant>EINVAL</constant></term> |
3602 |
++ <listitem><para> |
3603 |
++ Illegal flags or items. |
3604 |
++ </para></listitem> |
3605 |
++ </varlistentry> |
3606 |
++ |
3607 |
++ <varlistentry> |
3608 |
++ <term><constant>EDOM</constant></term> |
3609 |
++ <listitem><para> |
3610 |
++ Illegal bloom filter size. |
3611 |
++ </para></listitem> |
3612 |
++ </varlistentry> |
3613 |
++ |
3614 |
++ <varlistentry> |
3615 |
++ <term><constant>EMFILE</constant></term> |
3616 |
++ <listitem><para> |
3617 |
++ Too many matches for this connection. |
3618 |
++ </para></listitem> |
3619 |
++ </varlistentry> |
3620 |
++ </variablelist> |
3621 |
++ </refsect2> |
3622 |
++ |
3623 |
++ <refsect2> |
3624 |
++ <title> |
3625 |
++ <constant>KDBUS_CMD_MATCH_REMOVE</constant> may fail with the following |
3626 |
++ errors |
3627 |
++ </title> |
3628 |
++ |
3629 |
++ <variablelist> |
3630 |
++ <varlistentry> |
3631 |
++ <term><constant>EINVAL</constant></term> |
3632 |
++ <listitem><para> |
3633 |
++ Illegal flags. |
3634 |
++ </para></listitem> |
3635 |
++ </varlistentry> |
3636 |
++ |
3637 |
++ <varlistentry> |
3638 |
++ <term><constant>EBADSLT</constant></term> |
3639 |
++ <listitem><para> |
3640 |
++ A match entry with the given cookie could not be found. |
3641 |
++ </para></listitem> |
3642 |
++ </varlistentry> |
3643 |
++ </variablelist> |
3644 |
++ </refsect2> |
3645 |
++ </refsect1> |
3646 |
++ |
3647 |
++ <refsect1> |
3648 |
++ <title>See Also</title> |
3649 |
++ <simplelist type="inline"> |
3650 |
++ <member> |
3651 |
++ <citerefentry> |
3652 |
++ <refentrytitle>kdbus</refentrytitle> |
3653 |
++ <manvolnum>7</manvolnum> |
3654 |
++ </citerefentry> |
3655 |
++ </member> |
3656 |
++ <member> |
3657 |
++ <citerefentry> |
3658 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
3659 |
++ <manvolnum>7</manvolnum> |
3660 |
++ </citerefentry> |
3661 |
++ </member> |
3662 |
++ <member> |
3663 |
++ <citerefentry> |
3664 |
++ <refentrytitle>kdbus.match</refentrytitle> |
3665 |
++ <manvolnum>7</manvolnum> |
3666 |
++ </citerefentry> |
3667 |
++ </member> |
3668 |
++ <member> |
3669 |
++ <citerefentry> |
3670 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
3671 |
++ <manvolnum>7</manvolnum> |
3672 |
++ </citerefentry> |
3673 |
++ </member> |
3674 |
++ <member> |
3675 |
++ <citerefentry> |
3676 |
++ <refentrytitle>kdbus.item</refentrytitle> |
3677 |
++ <manvolnum>7</manvolnum> |
3678 |
++ </citerefentry> |
3679 |
++ </member> |
3680 |
++ <member> |
3681 |
++ <citerefentry> |
3682 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3683 |
++ <manvolnum>7</manvolnum> |
3684 |
++ </citerefentry> |
3685 |
++ </member> |
3686 |
++ <member> |
3687 |
++ <citerefentry> |
3688 |
++ <refentrytitle>kdbus.name</refentrytitle> |
3689 |
++ <manvolnum>7</manvolnum> |
3690 |
++ </citerefentry> |
3691 |
++ </member> |
3692 |
++ <member> |
3693 |
++ <citerefentry> |
3694 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
3695 |
++ <manvolnum>7</manvolnum> |
3696 |
++ </citerefentry> |
3697 |
++ </member> |
3698 |
++ </simplelist> |
3699 |
++ </refsect1> |
3700 |
++</refentry> |
3701 |
+diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml |
3702 |
+new file mode 100644 |
3703 |
+index 0000000..0115d9d |
3704 |
+--- /dev/null |
3705 |
++++ b/Documentation/kdbus/kdbus.message.xml |
3706 |
+@@ -0,0 +1,1276 @@ |
3707 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
3708 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
3709 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
3710 |
++ |
3711 |
++<refentry id="kdbus.message"> |
3712 |
++ |
3713 |
++ <refentryinfo> |
3714 |
++ <title>kdbus.message</title> |
3715 |
++ <productname>kdbus.message</productname> |
3716 |
++ </refentryinfo> |
3717 |
++ |
3718 |
++ <refmeta> |
3719 |
++ <refentrytitle>kdbus.message</refentrytitle> |
3720 |
++ <manvolnum>7</manvolnum> |
3721 |
++ </refmeta> |
3722 |
++ |
3723 |
++ <refnamediv> |
3724 |
++ <refname>kdbus.message</refname> |
3725 |
++ <refpurpose>kdbus message</refpurpose> |
3726 |
++ </refnamediv> |
3727 |
++ |
3728 |
++ <refsect1> |
3729 |
++ <title>Description</title> |
3730 |
++ |
3731 |
++ <para> |
3732 |
++ A kdbus message is used to exchange information between two connections |
3733 |
++ on a bus, or to transport notifications from the kernel to one or many |
3734 |
++ connections. This document describes the layout of messages, how payload |
3735 |
++ is added to them and how they are sent and received. |
3736 |
++ </para> |
3737 |
++ </refsect1> |
3738 |
++ |
3739 |
++ <refsect1> |
3740 |
++ <title>Message layout</title> |
3741 |
++ |
3742 |
++ <para>The layout of a message is shown below.</para> |
3743 |
++ |
3744 |
++ <programlisting> |
3745 |
++ +-------------------------------------------------------------------------+ |
3746 |
++ | Message | |
3747 |
++ | +---------------------------------------------------------------------+ | |
3748 |
++ | | Header | | |
3749 |
++ | | size: overall message size, including the data records | | |
3750 |
++ | | destination: connection ID of the receiver | | |
3751 |
++ | | source: connection ID of the sender (set by kernel) | | |
3752 |
++ | | payload_type: "DBusDBus" textual identifier stored as uint64_t | | |
3753 |
++ | +---------------------------------------------------------------------+ | |
3754 |
++ | +---------------------------------------------------------------------+ | |
3755 |
++ | | Data Record | | |
3756 |
++ | | size: overall record size (without padding) | | |
3757 |
++ | | type: type of data | | |
3758 |
++ | | data: reference to data (address or file descriptor) | | |
3759 |
++ | +---------------------------------------------------------------------+ | |
3760 |
++ | +---------------------------------------------------------------------+ | |
3761 |
++ | | padding bytes to the next 8 byte alignment | | |
3762 |
++ | +---------------------------------------------------------------------+ | |
3763 |
++ | +---------------------------------------------------------------------+ | |
3764 |
++ | | Data Record | | |
3765 |
++ | | size: overall record size (without padding) | | |
3766 |
++ | | ... | | |
3767 |
++ | +---------------------------------------------------------------------+ | |
3768 |
++ | +---------------------------------------------------------------------+ | |
3769 |
++ | | padding bytes to the next 8 byte alignment | | |
3770 |
++ | +---------------------------------------------------------------------+ | |
3771 |
++ | +---------------------------------------------------------------------+ | |
3772 |
++ | | Data Record | | |
3773 |
++ | | size: overall record size | | |
3774 |
++ | | ... | | |
3775 |
++ | +---------------------------------------------------------------------+ | |
3776 |
++ | ... further data records ... | |
3777 |
++ +-------------------------------------------------------------------------+ |
3778 |
++ </programlisting> |
3779 |
++ </refsect1> |
3780 |
++ |
3781 |
++ <refsect1> |
3782 |
++ <title>Message payload</title> |
3783 |
++ |
3784 |
++ <para> |
3785 |
++ When connecting to the bus, receivers request a memory pool of a given |
3786 |
++ size, large enough to carry all backlog of data enqueued for the |
3787 |
++ connection. The pool is internally backed by a shared memory file which |
3788 |
++ can be <function>mmap()</function>ed by the receiver. See |
3789 |
++ <citerefentry> |
3790 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
3791 |
++ <manvolnum>7</manvolnum> |
3792 |
++ </citerefentry> |
3793 |
++ for more information. |
3794 |
++ </para> |
3795 |
++ |
3796 |
++ <para> |
3797 |
++ Message payload must be described in items attached to a message when |
3798 |
++ it is sent. A receiver can access the payload by looking at the items |
3799 |
++ that are attached to a message in its pool. The following items are used. |
3800 |
++ </para> |
3801 |
++ |
3802 |
++ <variablelist> |
3803 |
++ <varlistentry> |
3804 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
3805 |
++ <listitem> |
3806 |
++ <para> |
3807 |
++ This item references a piece of memory on the sender side which is |
3808 |
++ directly copied into the receiver's pool. This way, two peers can |
3809 |
++ exchange data by effectively doing a single-copy from one process |
3810 |
++ to another; the kernel will not buffer the data anywhere else. |
3811 |
++ This item is never found in a message received by a connection. |
3812 |
++ </para> |
3813 |
++ </listitem> |
3814 |
++ </varlistentry> |
3815 |
++ |
3816 |
++ <varlistentry> |
3817 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term> |
3818 |
++ <listitem> |
3819 |
++ <para> |
3820 |
++ This item is attached to messages on the receiving side and points |
3821 |
++ to a memory area inside the receiver's pool. The |
3822 |
++ <varname>offset</varname> variable in the item denotes the memory |
3823 |
++ location relative to the message itself. |
3824 |
++ </para> |
3825 |
++ </listitem> |
3826 |
++ </varlistentry> |
3827 |
++ |
3828 |
++ <varlistentry> |
3829 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
3830 |
++ <listitem> |
3831 |
++ <para> |
3832 |
++ Messages can reference <emphasis>memfd</emphasis> files which |
3833 |
++ contain the data. memfd files are tmpfs-backed files that allow |
3834 |
++ sealing of the content of the file, which prevents all writable |
3835 |
++ access to the file content. |
3836 |
++ </para> |
3837 |
++ <para> |
3838 |
++ Only memfds that have |
3839 |
++ <constant>(F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_SEAL) |
3840 |
++ </constant> |
3841 |
++ set are accepted as payload data, which enforces reliable passing of |
3842 |
++ data. The receiver can assume that neither the sender nor anyone |
3843 |
++ else can alter the content after the message is sent. If those |
3844 |
++ seals are not set on the memfd, the ioctl will fail with |
3845 |
++ <errorcode>-1</errorcode>, and <varname>errno</varname> will be |
3846 |
++ set to <constant>ETXTBUSY</constant>. |
3847 |
++ </para> |
3848 |
++ </listitem> |
3849 |
++ </varlistentry> |
3850 |
++ |
3851 |
++ <varlistentry> |
3852 |
++ <term><constant>KDBUS_ITEM_FDS</constant></term> |
3853 |
++ <listitem> |
3854 |
++ <para> |
3855 |
++ Messages can transport regular file descriptors via |
3856 |
++ <constant>KDBUS_ITEM_FDS</constant>. This item carries an array |
3857 |
++ of <type>int</type> values in <varname>item.fd</varname>. The |
3858 |
++ maximum number of file descriptors in the item is |
3859 |
++ <constant>253</constant>, and only one item of this type is |
3860 |
++ accepted per message. All passed values must be valid file |
3861 |
++ descriptors; the open count of each file descriptors is increased |
3862 |
++ by installing it to the receiver's task. This item can only be |
3863 |
++ used for directed messages, not for broadcasts, and only to |
3864 |
++ remote peers that have opted-in for receiving file descriptors |
3865 |
++ at connection time (<constant>KDBUS_HELLO_ACCEPT_FD</constant>). |
3866 |
++ </para> |
3867 |
++ </listitem> |
3868 |
++ </varlistentry> |
3869 |
++ </variablelist> |
3870 |
++ |
3871 |
++ <para> |
3872 |
++ The sender must not make any assumptions on the type in which data is |
3873 |
++ received by the remote peer. The kernel is free to re-pack multiple |
3874 |
++ <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> and |
3875 |
++ <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> payloads. For instance, the |
3876 |
++ kernel may decide to merge multiple <constant>VECs</constant> into a |
3877 |
++ single <constant>VEC</constant>, inline <constant>MEMFD</constant> |
3878 |
++ payloads into memory, or merge all passed <constant>VECs</constant> into a |
3879 |
++ single <constant>MEMFD</constant>. However, the kernel preserves the order |
3880 |
++ of passed data. This means that the order of all <constant>VEC</constant> |
3881 |
++ and <constant>MEMFD</constant> items is not changed in respect to each |
3882 |
++ other. In other words: All passed <constant>VEC</constant> and |
3883 |
++ <constant>MEMFD</constant> data payloads are treated as a single stream |
3884 |
++ of data that may be received by the remote peer in a different set of |
3885 |
++ chunks than it was sent as. |
3886 |
++ </para> |
3887 |
++ </refsect1> |
3888 |
++ |
3889 |
++ <refsect1> |
3890 |
++ <title>Sending messages</title> |
3891 |
++ |
3892 |
++ <para> |
3893 |
++ Messages are passed to the kernel with the |
3894 |
++ <constant>KDBUS_CMD_SEND</constant> ioctl. Depending on the destination |
3895 |
++ address of the message, the kernel delivers the message to the specific |
3896 |
++ destination connection, or to some subset of all connections on the same |
3897 |
++ bus. Sending messages across buses is not possible. Messages are always |
3898 |
++ queued in the memory pool of the destination connection (see above). |
3899 |
++ </para> |
3900 |
++ |
3901 |
++ <para> |
3902 |
++ The <constant>KDBUS_CMD_SEND</constant> ioctl uses a |
3903 |
++ <type>struct kdbus_cmd_send</type> to describe the message |
3904 |
++ transfer. |
3905 |
++ </para> |
3906 |
++ <programlisting> |
3907 |
++struct kdbus_cmd_send { |
3908 |
++ __u64 size; |
3909 |
++ __u64 flags; |
3910 |
++ __u64 return_flags; |
3911 |
++ __u64 msg_address; |
3912 |
++ struct kdbus_msg_info reply; |
3913 |
++ struct kdbus_item items[0]; |
3914 |
++}; |
3915 |
++ </programlisting> |
3916 |
++ |
3917 |
++ <para>The fields in this struct are described below.</para> |
3918 |
++ |
3919 |
++ <variablelist> |
3920 |
++ <varlistentry> |
3921 |
++ <term><varname>size</varname></term> |
3922 |
++ <listitem><para> |
3923 |
++ The overall size of the struct, including its items. |
3924 |
++ </para></listitem> |
3925 |
++ </varlistentry> |
3926 |
++ |
3927 |
++ <varlistentry> |
3928 |
++ <term><varname>flags</varname></term> |
3929 |
++ <listitem><para>Flags for message delivery</para> |
3930 |
++ <variablelist> |
3931 |
++ <varlistentry> |
3932 |
++ <term><constant>KDBUS_SEND_SYNC_REPLY</constant></term> |
3933 |
++ <listitem> |
3934 |
++ <para> |
3935 |
++ By default, all calls to kdbus are considered asynchronous, |
3936 |
++ non-blocking. However, as there are many use cases that need |
3937 |
++ to wait for a remote peer to answer a method call, there's a |
3938 |
++ way to send a message and wait for a reply in a synchronous |
3939 |
++ fashion. This is what the |
3940 |
++ <constant>KDBUS_SEND_SYNC_REPLY</constant> controls. The |
3941 |
++ <constant>KDBUS_CMD_SEND</constant> ioctl will block until the |
3942 |
++ reply has arrived, the timeout limit is reached, in case the |
3943 |
++ remote connection was shut down, or if interrupted by a signal |
3944 |
++ before any reply; see |
3945 |
++ <citerefentry> |
3946 |
++ <refentrytitle>signal</refentrytitle> |
3947 |
++ <manvolnum>7</manvolnum> |
3948 |
++ </citerefentry>. |
3949 |
++ |
3950 |
++ The offset of the reply message in the sender's pool is stored |
3951 |
++ in <varname>reply</varname> when the ioctl has returned without |
3952 |
++ error. Hence, there is no need for another |
3953 |
++ <constant>KDBUS_CMD_RECV</constant> ioctl or anything else to |
3954 |
++ receive the reply. |
3955 |
++ </para> |
3956 |
++ </listitem> |
3957 |
++ </varlistentry> |
3958 |
++ |
3959 |
++ <varlistentry> |
3960 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
3961 |
++ <listitem> |
3962 |
++ <para> |
3963 |
++ Request a set of valid flags for this ioctl. When this bit is |
3964 |
++ set, no action is taken; the ioctl will fail with |
3965 |
++ <errorcode>-1</errorcode>, <varname>errno</varname> |
3966 |
++ is set to <constant>EPROTO</constant>. |
3967 |
++ Once the ioctl returned, the <varname>flags</varname> |
3968 |
++ field will have all bits set that the kernel recognizes as |
3969 |
++ valid for this command. |
3970 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
3971 |
++ cleared by the operation. |
3972 |
++ </para> |
3973 |
++ </listitem> |
3974 |
++ </varlistentry> |
3975 |
++ </variablelist> |
3976 |
++ </listitem> |
3977 |
++ </varlistentry> |
3978 |
++ |
3979 |
++ <varlistentry> |
3980 |
++ <term><varname>return_flags</varname></term> |
3981 |
++ <listitem><para> |
3982 |
++ Flags returned by the kernel. Currently unused and always set to |
3983 |
++ <constant>0</constant> by the kernel. |
3984 |
++ </para></listitem> |
3985 |
++ </varlistentry> |
3986 |
++ |
3987 |
++ <varlistentry> |
3988 |
++ <term><varname>msg_address</varname></term> |
3989 |
++ <listitem><para> |
3990 |
++ In this field, users have to provide a pointer to a message |
3991 |
++ (<type>struct kdbus_msg</type>) to send. See below for a |
3992 |
++ detailed description. |
3993 |
++ </para></listitem> |
3994 |
++ </varlistentry> |
3995 |
++ |
3996 |
++ <varlistentry> |
3997 |
++ <term><varname>reply</varname></term> |
3998 |
++ <listitem><para> |
3999 |
++ Only used for synchronous replies. See description of |
4000 |
++ <type>struct kdbus_cmd_recv</type> for more details. |
4001 |
++ </para></listitem> |
4002 |
++ </varlistentry> |
4003 |
++ |
4004 |
++ <varlistentry> |
4005 |
++ <term><varname>items</varname></term> |
4006 |
++ <listitem> |
4007 |
++ <para> |
4008 |
++ The following items are currently recognized. |
4009 |
++ </para> |
4010 |
++ <variablelist> |
4011 |
++ <varlistentry> |
4012 |
++ <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term> |
4013 |
++ <listitem> |
4014 |
++ <para> |
4015 |
++ When this optional item is passed in, and the call is |
4016 |
++ executed as SYNC call, the passed in file descriptor can be |
4017 |
++ used as alternative cancellation point. The kernel will call |
4018 |
++ <citerefentry> |
4019 |
++ <refentrytitle>poll</refentrytitle> |
4020 |
++ <manvolnum>2</manvolnum> |
4021 |
++ </citerefentry> |
4022 |
++ on this file descriptor, and once it reports any incoming |
4023 |
++ bytes, the blocking send operation will be canceled; the |
4024 |
++ blocking, synchronous ioctl call will return |
4025 |
++ <errorcode>-1</errorcode>, and <varname>errno</varname> will |
4026 |
++ be set to <errorname>ECANCELED</errorname>. |
4027 |
++ Any type of file descriptor on which |
4028 |
++ <citerefentry> |
4029 |
++ <refentrytitle>poll</refentrytitle> |
4030 |
++ <manvolnum>2</manvolnum> |
4031 |
++ </citerefentry> |
4032 |
++ can be called on can be used as payload to this item; for |
4033 |
++ example, an eventfd can be used for this purpose, see |
4034 |
++ <citerefentry> |
4035 |
++ <refentrytitle>eventfd</refentrytitle> |
4036 |
++ <manvolnum>2</manvolnum> |
4037 |
++ </citerefentry>. |
4038 |
++ For asynchronous message sending, this item is allowed but |
4039 |
++ ignored. |
4040 |
++ </para> |
4041 |
++ </listitem> |
4042 |
++ </varlistentry> |
4043 |
++ </variablelist> |
4044 |
++ <para> |
4045 |
++ Unrecognized items are rejected, and the ioctl will fail with |
4046 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
4047 |
++ </para> |
4048 |
++ </listitem> |
4049 |
++ </varlistentry> |
4050 |
++ </variablelist> |
4051 |
++ |
4052 |
++ <para> |
4053 |
++ The message referenced by the <varname>msg_address</varname> above has |
4054 |
++ the following layout. |
4055 |
++ </para> |
4056 |
++ |
4057 |
++ <programlisting> |
4058 |
++struct kdbus_msg { |
4059 |
++ __u64 size; |
4060 |
++ __u64 flags; |
4061 |
++ __s64 priority; |
4062 |
++ __u64 dst_id; |
4063 |
++ __u64 src_id; |
4064 |
++ __u64 payload_type; |
4065 |
++ __u64 cookie; |
4066 |
++ __u64 timeout_ns; |
4067 |
++ __u64 cookie_reply; |
4068 |
++ struct kdbus_item items[0]; |
4069 |
++}; |
4070 |
++ </programlisting> |
4071 |
++ |
4072 |
++ <para>The fields in this struct are described below.</para> |
4073 |
++ |
4074 |
++ <variablelist> |
4075 |
++ <varlistentry> |
4076 |
++ <term><varname>size</varname></term> |
4077 |
++ <listitem><para> |
4078 |
++ The overall size of the struct, including its items. |
4079 |
++ </para></listitem> |
4080 |
++ </varlistentry> |
4081 |
++ |
4082 |
++ <varlistentry> |
4083 |
++ <term><varname>flags</varname></term> |
4084 |
++ <listitem><para>Flags to describe message details.</para> |
4085 |
++ <variablelist> |
4086 |
++ <varlistentry> |
4087 |
++ <term><constant>KDBUS_MSG_EXPECT_REPLY</constant></term> |
4088 |
++ <listitem> |
4089 |
++ <para> |
4090 |
++ Expect a reply to this message from the remote peer. With |
4091 |
++ this bit set, the timeout_ns field must be set to a non-zero |
4092 |
++ number of nanoseconds in which the receiving peer is expected |
4093 |
++ to reply. If such a reply is not received in time, the sender |
4094 |
++ will be notified with a timeout message (see below). The |
4095 |
++ value must be an absolute value, in nanoseconds and based on |
4096 |
++ <constant>CLOCK_MONOTONIC</constant>. |
4097 |
++ </para><para> |
4098 |
++ For a message to be accepted as reply, it must be a direct |
4099 |
++ message to the original sender (not a broadcast and not a |
4100 |
++ signal message), and its |
4101 |
++ <varname>kdbus_msg.cookie_reply</varname> must match the |
4102 |
++ previous message's <varname>kdbus_msg.cookie</varname>. |
4103 |
++ </para><para> |
4104 |
++ Expected replies also temporarily open the policy of the |
4105 |
++ sending connection, so the other peer is allowed to respond |
4106 |
++ within the given time window. |
4107 |
++ </para> |
4108 |
++ </listitem> |
4109 |
++ </varlistentry> |
4110 |
++ |
4111 |
++ <varlistentry> |
4112 |
++ <term><constant>KDBUS_MSG_NO_AUTO_START</constant></term> |
4113 |
++ <listitem> |
4114 |
++ <para> |
4115 |
++ By default, when a message is sent to an activator |
4116 |
++ connection, the activator is notified and will start an |
4117 |
++ implementer. This flag inhibits that behavior. With this bit |
4118 |
++ set, and the remote being an activator, the ioctl will fail |
4119 |
++ with <varname>errno</varname> set to |
4120 |
++ <constant>EADDRNOTAVAIL</constant>. |
4121 |
++ </para> |
4122 |
++ </listitem> |
4123 |
++ </varlistentry> |
4124 |
++ |
4125 |
++ <varlistentry> |
4126 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
4127 |
++ <listitem> |
4128 |
++ <para> |
4129 |
++ Requests a set of valid flags for this ioctl. When this bit is |
4130 |
++ set, no action is taken; the ioctl will return |
4131 |
++ <errorcode>0</errorcode>, and the <varname>flags</varname> |
4132 |
++ field will have all bits set that are valid for this command. |
4133 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
4134 |
++ cleared by the operation. |
4135 |
++ </para> |
4136 |
++ </listitem> |
4137 |
++ </varlistentry> |
4138 |
++ </variablelist> |
4139 |
++ </listitem> |
4140 |
++ </varlistentry> |
4141 |
++ |
4142 |
++ <varlistentry> |
4143 |
++ <term><varname>priority</varname></term> |
4144 |
++ <listitem><para> |
4145 |
++ The priority of this message. Receiving messages (see below) may |
4146 |
++ optionally be constrained to messages of a minimal priority. This |
4147 |
++ allows for use cases where timing critical data is interleaved with |
4148 |
++ control data on the same connection. If unused, the priority field |
4149 |
++ should be set to <constant>0</constant>. |
4150 |
++ </para></listitem> |
4151 |
++ </varlistentry> |
4152 |
++ |
4153 |
++ <varlistentry> |
4154 |
++ <term><varname>dst_id</varname></term> |
4155 |
++ <listitem><para> |
4156 |
++ The numeric ID of the destination connection, or |
4157 |
++ <constant>KDBUS_DST_ID_BROADCAST</constant> |
4158 |
++ (~0ULL) to address every peer on the bus, or |
4159 |
++ <constant>KDBUS_DST_ID_NAME</constant> (0) to look |
4160 |
++ it up dynamically from the bus' name registry. |
4161 |
++ In the latter case, an item of type |
4162 |
++ <constant>KDBUS_ITEM_DST_NAME</constant> is mandatory. |
4163 |
++ Also see |
4164 |
++ <citerefentry> |
4165 |
++ <refentrytitle>kdbus.name</refentrytitle> |
4166 |
++ <manvolnum>7</manvolnum> |
4167 |
++ </citerefentry> |
4168 |
++ . |
4169 |
++ </para></listitem> |
4170 |
++ </varlistentry> |
4171 |
++ |
4172 |
++ <varlistentry> |
4173 |
++ <term><varname>src_id</varname></term> |
4174 |
++ <listitem><para> |
4175 |
++ Upon return of the ioctl, this member will contain the sending |
4176 |
++ connection's numerical ID. Should be 0 at send time. |
4177 |
++ </para></listitem> |
4178 |
++ </varlistentry> |
4179 |
++ |
4180 |
++ <varlistentry> |
4181 |
++ <term><varname>payload_type</varname></term> |
4182 |
++ <listitem><para> |
4183 |
++ Type of the payload in the actual data records. Currently, only |
4184 |
++ <constant>KDBUS_PAYLOAD_DBUS</constant> is accepted as input value |
4185 |
++ of this field. When receiving messages that are generated by the |
4186 |
++ kernel (notifications), this field will contain |
4187 |
++ <constant>KDBUS_PAYLOAD_KERNEL</constant>. |
4188 |
++ </para></listitem> |
4189 |
++ </varlistentry> |
4190 |
++ |
4191 |
++ <varlistentry> |
4192 |
++ <term><varname>cookie</varname></term> |
4193 |
++ <listitem><para> |
4194 |
++ Cookie of this message, for later recognition. Also, when replying |
4195 |
++ to a message (see above), the <varname>cookie_reply</varname> |
4196 |
++ field must match this value. |
4197 |
++ </para></listitem> |
4198 |
++ </varlistentry> |
4199 |
++ |
4200 |
++ <varlistentry> |
4201 |
++ <term><varname>timeout_ns</varname></term> |
4202 |
++ <listitem><para> |
4203 |
++ If the message sent requires a reply from the remote peer (see above), |
4204 |
++ this field contains the timeout in absolute nanoseconds based on |
4205 |
++ <constant>CLOCK_MONOTONIC</constant>. Also see |
4206 |
++ <citerefentry> |
4207 |
++ <refentrytitle>clock_gettime</refentrytitle> |
4208 |
++ <manvolnum>2</manvolnum> |
4209 |
++ </citerefentry>. |
4210 |
++ </para></listitem> |
4211 |
++ </varlistentry> |
4212 |
++ |
4213 |
++ <varlistentry> |
4214 |
++ <term><varname>cookie_reply</varname></term> |
4215 |
++ <listitem><para> |
4216 |
++ If the message sent is a reply to another message, this field must |
4217 |
++ match the cookie of the formerly received message. |
4218 |
++ </para></listitem> |
4219 |
++ </varlistentry> |
4220 |
++ |
4221 |
++ <varlistentry> |
4222 |
++ <term><varname>items</varname></term> |
4223 |
++ <listitem> |
4224 |
++ <para> |
4225 |
++ A dynamically sized list of items to contain additional information. |
4226 |
++ The following items are expected/valid: |
4227 |
++ </para> |
4228 |
++ <variablelist> |
4229 |
++ <varlistentry> |
4230 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
4231 |
++ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
4232 |
++ <term><constant>KDBUS_ITEM_FDS</constant></term> |
4233 |
++ <listitem> |
4234 |
++ <para> |
4235 |
++ Actual data records containing the payload. See section |
4236 |
++ "Message payload". |
4237 |
++ </para> |
4238 |
++ </listitem> |
4239 |
++ </varlistentry> |
4240 |
++ |
4241 |
++ <varlistentry> |
4242 |
++ <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term> |
4243 |
++ <listitem> |
4244 |
++ <para> |
4245 |
++ Bloom filter for matches (see below). |
4246 |
++ </para> |
4247 |
++ </listitem> |
4248 |
++ </varlistentry> |
4249 |
++ |
4250 |
++ <varlistentry> |
4251 |
++ <term><constant>KDBUS_ITEM_DST_NAME</constant></term> |
4252 |
++ <listitem> |
4253 |
++ <para> |
4254 |
++ Well-known name to send this message to. Required if |
4255 |
++ <varname>dst_id</varname> is set to |
4256 |
++ <constant>KDBUS_DST_ID_NAME</constant>. |
4257 |
++ If a connection holding the given name can't be found, |
4258 |
++ the ioctl will fail with <varname>errno</varname> set to |
4259 |
++ <constant>ESRCH</constant> is returned. |
4260 |
++ </para> |
4261 |
++ <para> |
4262 |
++ For messages to a unique name (ID), this item is optional. If |
4263 |
++ present, the kernel will make sure the name owner matches the |
4264 |
++ given unique name. This allows programs to tie the message |
4265 |
++ sending to the condition that a name is currently owned by a |
4266 |
++ certain unique name. |
4267 |
++ </para> |
4268 |
++ </listitem> |
4269 |
++ </varlistentry> |
4270 |
++ </variablelist> |
4271 |
++ </listitem> |
4272 |
++ </varlistentry> |
4273 |
++ </variablelist> |
4274 |
++ |
4275 |
++ <para> |
4276 |
++ The message will be augmented by the requested metadata items when |
4277 |
++ queued into the receiver's pool. See |
4278 |
++ <citerefentry> |
4279 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
4280 |
++ <manvolnum>7</manvolnum> |
4281 |
++ </citerefentry> |
4282 |
++ and |
4283 |
++ <citerefentry> |
4284 |
++ <refentrytitle>kdbus.item</refentrytitle> |
4285 |
++ <manvolnum>7</manvolnum> |
4286 |
++ </citerefentry> |
4287 |
++ for more information on metadata. |
4288 |
++ </para> |
4289 |
++ </refsect1> |
4290 |
++ |
4291 |
++ <refsect1> |
4292 |
++ <title>Receiving messages</title> |
4293 |
++ |
4294 |
++ <para> |
4295 |
++ Messages are received by the client with the |
4296 |
++ <constant>KDBUS_CMD_RECV</constant> ioctl. The endpoint file of the bus |
4297 |
++ supports <function>poll()/epoll()/select()</function>; when new messages |
4298 |
++ are available on the connection's file descriptor, |
4299 |
++ <constant>POLLIN</constant> is reported. For compatibility reasons, |
4300 |
++ <constant>POLLOUT</constant> is always reported as well. Note, however, |
4301 |
++ that the latter does not guarantee that a message can in fact be sent, as |
4302 |
++ this depends on how many pending messages the receiver has in its pool. |
4303 |
++ </para> |
4304 |
++ |
4305 |
++ <para> |
4306 |
++ With the <constant>KDBUS_CMD_RECV</constant> ioctl, a |
4307 |
++ <type>struct kdbus_cmd_recv</type> is used. |
4308 |
++ </para> |
4309 |
++ |
4310 |
++ <programlisting> |
4311 |
++struct kdbus_cmd_recv { |
4312 |
++ __u64 size; |
4313 |
++ __u64 flags; |
4314 |
++ __u64 return_flags; |
4315 |
++ __s64 priority; |
4316 |
++ __u64 dropped_msgs; |
4317 |
++ struct kdbus_msg_info msg; |
4318 |
++ struct kdbus_item items[0]; |
4319 |
++}; |
4320 |
++ </programlisting> |
4321 |
++ |
4322 |
++ <para>The fields in this struct are described below.</para> |
4323 |
++ |
4324 |
++ <variablelist> |
4325 |
++ <varlistentry> |
4326 |
++ <term><varname>size</varname></term> |
4327 |
++ <listitem><para> |
4328 |
++ The overall size of the struct, including its items. |
4329 |
++ </para></listitem> |
4330 |
++ </varlistentry> |
4331 |
++ |
4332 |
++ <varlistentry> |
4333 |
++ <term><varname>flags</varname></term> |
4334 |
++ <listitem><para>Flags to control the receive command.</para> |
4335 |
++ <variablelist> |
4336 |
++ <varlistentry> |
4337 |
++ <term><constant>KDBUS_RECV_PEEK</constant></term> |
4338 |
++ <listitem> |
4339 |
++ <para> |
4340 |
++ Just return the location of the next message. Do not install |
4341 |
++ file descriptors or anything else. This is usually used to |
4342 |
++ determine the sender of the next queued message. |
4343 |
++ </para> |
4344 |
++ </listitem> |
4345 |
++ </varlistentry> |
4346 |
++ |
4347 |
++ <varlistentry> |
4348 |
++ <term><constant>KDBUS_RECV_DROP</constant></term> |
4349 |
++ <listitem> |
4350 |
++ <para> |
4351 |
++ Drop the next message without doing anything else with it, |
4352 |
++ and free the pool slice. This a short-cut for |
4353 |
++ <constant>KDBUS_RECV_PEEK</constant> and |
4354 |
++ <constant>KDBUS_CMD_FREE</constant>. |
4355 |
++ </para> |
4356 |
++ </listitem> |
4357 |
++ </varlistentry> |
4358 |
++ |
4359 |
++ <varlistentry> |
4360 |
++ <term><constant>KDBUS_RECV_USE_PRIORITY</constant></term> |
4361 |
++ <listitem> |
4362 |
++ <para> |
4363 |
++ Dequeue the messages ordered by their priority, and filtering |
4364 |
++ them with the priority field (see below). |
4365 |
++ </para> |
4366 |
++ </listitem> |
4367 |
++ </varlistentry> |
4368 |
++ |
4369 |
++ <varlistentry> |
4370 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
4371 |
++ <listitem> |
4372 |
++ <para> |
4373 |
++ Request a set of valid flags for this ioctl. When this bit is |
4374 |
++ set, no action is taken; the ioctl will fail with |
4375 |
++ <errorcode>-1</errorcode>, <varname>errno</varname> |
4376 |
++ is set to <constant>EPROTO</constant>. |
4377 |
++ Once the ioctl returned, the <varname>flags</varname> |
4378 |
++ field will have all bits set that the kernel recognizes as |
4379 |
++ valid for this command. |
4380 |
++ </para> |
4381 |
++ </listitem> |
4382 |
++ </varlistentry> |
4383 |
++ </variablelist> |
4384 |
++ </listitem> |
4385 |
++ </varlistentry> |
4386 |
++ |
4387 |
++ <varlistentry> |
4388 |
++ <term><varname>return_flags</varname></term> |
4389 |
++ <listitem><para> |
4390 |
++ Flags returned by the kernel. If the <varname>dropped_msgs</varname> |
4391 |
++ field is non-zero, <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> |
4392 |
++ is set. If a file descriptor could not be installed, the |
4393 |
++ <constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant> flag is set. |
4394 |
++ </para></listitem> |
4395 |
++ </varlistentry> |
4396 |
++ |
4397 |
++ <varlistentry> |
4398 |
++ <term><varname>priority</varname></term> |
4399 |
++ <listitem><para> |
4400 |
++ With <constant>KDBUS_RECV_USE_PRIORITY</constant> set in |
4401 |
++ <varname>flags</varname>, messages will be dequeued ordered by their |
4402 |
++ priority, starting with the highest value. Also, messages will be |
4403 |
++ filtered by the value given in this field, so the returned message |
4404 |
++ will at least have the requested priority. If no such message is |
4405 |
++ waiting in the queue, the ioctl will fail, and |
4406 |
++ <varname>errno</varname> will be set to <constant>EAGAIN</constant>. |
4407 |
++ </para></listitem> |
4408 |
++ </varlistentry> |
4409 |
++ |
4410 |
++ <varlistentry> |
4411 |
++ <term><varname>dropped_msgs</varname></term> |
4412 |
++ <listitem><para> |
4413 |
++ Whenever a message with <constant>KDBUS_MSG_SIGNAL</constant> is sent |
4414 |
++ but cannot be queued on a peer (e.g., as it contains FDs but the peer |
4415 |
++ does not support FDs, or there is no space left in the peer's pool) |
4416 |
++ the 'dropped_msgs' counter of the peer is incremented. On the next |
4417 |
++ RECV ioctl, the 'dropped_msgs' field is copied into the ioctl struct |
4418 |
++ and cleared on the peer. If it was non-zero, the |
4419 |
++ <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> flag will be set |
4420 |
++ in <varname>return_flags</varname>. Note that this will only happen |
4421 |
++ if the ioctl succeeded or failed with <constant>EAGAIN</constant>. In |
4422 |
++ other error cases, the 'dropped_msgs' field of the peer is left |
4423 |
++ untouched. |
4424 |
++ </para></listitem> |
4425 |
++ </varlistentry> |
4426 |
++ |
4427 |
++ <varlistentry> |
4428 |
++ <term><varname>msg</varname></term> |
4429 |
++ <listitem><para> |
4430 |
++ Embedded struct containing information on the received message when |
4431 |
++ this command succeeded (see below). |
4432 |
++ </para></listitem> |
4433 |
++ </varlistentry> |
4434 |
++ |
4435 |
++ <varlistentry> |
4436 |
++ <term><varname>items</varname></term> |
4437 |
++ <listitem><para> |
4438 |
++ Items to specify further details for the receive command. |
4439 |
++ Currently unused, and all items will be rejected with |
4440 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
4441 |
++ </para></listitem> |
4442 |
++ </varlistentry> |
4443 |
++ </variablelist> |
4444 |
++ |
4445 |
++ <para> |
4446 |
++ Both <type>struct kdbus_cmd_recv</type> and |
4447 |
++ <type>struct kdbus_cmd_send</type> embed |
4448 |
++ <type>struct kdbus_msg_info</type>. |
4449 |
++ For the <constant>KDBUS_CMD_SEND</constant> ioctl, it is used to catch |
4450 |
++ synchronous replies, if one was requested, and is unused otherwise. |
4451 |
++ </para> |
4452 |
++ |
4453 |
++ <programlisting> |
4454 |
++struct kdbus_msg_info { |
4455 |
++ __u64 offset; |
4456 |
++ __u64 msg_size; |
4457 |
++ __u64 return_flags; |
4458 |
++}; |
4459 |
++ </programlisting> |
4460 |
++ |
4461 |
++ <para>The fields in this struct are described below.</para> |
4462 |
++ |
4463 |
++ <variablelist> |
4464 |
++ <varlistentry> |
4465 |
++ <term><varname>offset</varname></term> |
4466 |
++ <listitem><para> |
4467 |
++ Upon return of the ioctl, this field contains the offset in the |
4468 |
++ receiver's memory pool. The memory must be freed with |
4469 |
++ <constant>KDBUS_CMD_FREE</constant>. See |
4470 |
++ <citerefentry> |
4471 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
4472 |
++ <manvolnum>7</manvolnum> |
4473 |
++ </citerefentry> |
4474 |
++ for further details. |
4475 |
++ </para></listitem> |
4476 |
++ </varlistentry> |
4477 |
++ |
4478 |
++ <varlistentry> |
4479 |
++ <term><varname>msg_size</varname></term> |
4480 |
++ <listitem><para> |
4481 |
++ Upon successful return of the ioctl, this field contains the size of |
4482 |
++ the allocated slice at offset <varname>offset</varname>. |
4483 |
++ It is the combination of the size of the stored |
4484 |
++ <type>struct kdbus_msg</type> object plus all appended VECs. |
4485 |
++ You can use it in combination with <varname>offset</varname> to map |
4486 |
++ a single message, instead of mapping the entire pool. See |
4487 |
++ <citerefentry> |
4488 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
4489 |
++ <manvolnum>7</manvolnum> |
4490 |
++ </citerefentry> |
4491 |
++ for further details. |
4492 |
++ </para></listitem> |
4493 |
++ </varlistentry> |
4494 |
++ |
4495 |
++ <varlistentry> |
4496 |
++ <term><varname>return_flags</varname></term> |
4497 |
++ <listitem> |
4498 |
++ <para> |
4499 |
++ Kernel-provided return flags. Currently, the following flags are |
4500 |
++ defined. |
4501 |
++ </para> |
4502 |
++ <variablelist> |
4503 |
++ <varlistentry> |
4504 |
++ <term><constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant></term> |
4505 |
++ <listitem> |
4506 |
++ <para> |
4507 |
++ The message contained memfds or file descriptors, and the |
4508 |
++ kernel failed to install one or more of them at receive time. |
4509 |
++ Most probably that happened because the maximum number of |
4510 |
++ file descriptors for the receiver's task were exceeded. |
4511 |
++ In such cases, the message is still delivered, so this is not |
4512 |
++ a fatal condition. File descriptors numbers inside the |
4513 |
++ <constant>KDBUS_ITEM_FDS</constant> item or memfd files |
4514 |
++ referenced by <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> |
4515 |
++ items which could not be installed will be set to |
4516 |
++ <constant>-1</constant>. |
4517 |
++ </para> |
4518 |
++ </listitem> |
4519 |
++ </varlistentry> |
4520 |
++ </variablelist> |
4521 |
++ </listitem> |
4522 |
++ </varlistentry> |
4523 |
++ </variablelist> |
4524 |
++ |
4525 |
++ <para> |
4526 |
++ Unless <constant>KDBUS_RECV_DROP</constant> was passed, the |
4527 |
++ <varname>offset</varname> field contains the location of the new message |
4528 |
++ inside the receiver's pool after the <constant>KDBUS_CMD_RECV</constant> |
4529 |
++ ioctl was employed. The message is stored as <type>struct kdbus_msg</type> |
4530 |
++ at this offset, and can be interpreted with the semantics described above. |
4531 |
++ </para> |
4532 |
++ <para> |
4533 |
++ Also, if the connection allowed for file descriptor to be passed |
4534 |
++ (<constant>KDBUS_HELLO_ACCEPT_FD</constant>), and if the message contained |
4535 |
++ any, they will be installed into the receiving process when the |
4536 |
++ <constant>KDBUS_CMD_RECV</constant> ioctl is called. |
4537 |
++ <emphasis>memfds</emphasis> may always be part of the message payload. |
4538 |
++ The receiving task is obliged to close all file descriptors appropriately |
4539 |
++ once no longer needed. If <constant>KDBUS_RECV_PEEK</constant> is set, no |
4540 |
++ file descriptors are installed. This allows for peeking at a message, |
4541 |
++ looking at its metadata only and dropping it via |
4542 |
++ <constant>KDBUS_RECV_DROP</constant>, without installing any of the file |
4543 |
++ descriptors into the receiving process. |
4544 |
++ </para> |
4545 |
++ <para> |
4546 |
++ The caller is obliged to call the <constant>KDBUS_CMD_FREE</constant> |
4547 |
++ ioctl with the returned offset when the memory is no longer needed. |
4548 |
++ </para> |
4549 |
++ </refsect1> |
4550 |
++ |
4551 |
++ <refsect1> |
4552 |
++ <title>Notifications</title> |
4553 |
++ <para> |
4554 |
++ A kernel notification is a regular kdbus message with the following |
4555 |
++ details. |
4556 |
++ </para> |
4557 |
++ |
4558 |
++ <itemizedlist> |
4559 |
++ <listitem><para> |
4560 |
++ kdbus_msg.src_id == <constant>KDBUS_SRC_ID_KERNEL</constant> |
4561 |
++ </para></listitem> |
4562 |
++ <listitem><para> |
4563 |
++ kdbus_msg.dst_id == <constant>KDBUS_DST_ID_BROADCAST</constant> |
4564 |
++ </para></listitem> |
4565 |
++ <listitem><para> |
4566 |
++ kdbus_msg.payload_type == <constant>KDBUS_PAYLOAD_KERNEL</constant> |
4567 |
++ </para></listitem> |
4568 |
++ <listitem><para> |
4569 |
++ Has exactly one of the items attached that are described below. |
4570 |
++ </para></listitem> |
4571 |
++ <listitem><para> |
4572 |
++ Always has a timestamp item (<constant>KDBUS_ITEM_TIMESTAMP</constant>) |
4573 |
++ attached. |
4574 |
++ </para></listitem> |
4575 |
++ </itemizedlist> |
4576 |
++ |
4577 |
++ <para> |
4578 |
++ The kernel will notify its users of the following events. |
4579 |
++ </para> |
4580 |
++ |
4581 |
++ <itemizedlist> |
4582 |
++ <listitem><para> |
4583 |
++ When connection <emphasis>A</emphasis> is terminated while connection |
4584 |
++ <emphasis>B</emphasis> is waiting for a reply from it, connection |
4585 |
++ <emphasis>B</emphasis> is notified with a message with an item of |
4586 |
++ type <constant>KDBUS_ITEM_REPLY_DEAD</constant>. |
4587 |
++ </para></listitem> |
4588 |
++ |
4589 |
++ <listitem><para> |
4590 |
++ When connection <emphasis>A</emphasis> does not receive a reply from |
4591 |
++ connection <emphasis>B</emphasis> within the specified timeout window, |
4592 |
++ connection <emphasis>A</emphasis> will receive a message with an |
4593 |
++ item of type <constant>KDBUS_ITEM_REPLY_TIMEOUT</constant>. |
4594 |
++ </para></listitem> |
4595 |
++ |
4596 |
++ <listitem><para> |
4597 |
++ When an ordinary connection (not a monitor) is created on or removed |
4598 |
++ from a bus, messages with an item of type |
4599 |
++ <constant>KDBUS_ITEM_ID_ADD</constant> or |
4600 |
++ <constant>KDBUS_ITEM_ID_REMOVE</constant>, respectively, are delivered |
4601 |
++ to all bus members that match these messages through their match |
4602 |
++ database. Eavesdroppers (monitor connections) do not cause such |
4603 |
++ notifications to be sent. They are invisible on the bus. |
4604 |
++ </para></listitem> |
4605 |
++ |
4606 |
++ <listitem><para> |
4607 |
++ When a connection gains or loses ownership of a name, messages with an |
4608 |
++ item of type <constant>KDBUS_ITEM_NAME_ADD</constant>, |
4609 |
++ <constant>KDBUS_ITEM_NAME_REMOVE</constant> or |
4610 |
++ <constant>KDBUS_ITEM_NAME_CHANGE</constant> are delivered to all bus |
4611 |
++ members that match these messages through their match database. |
4612 |
++ </para></listitem> |
4613 |
++ </itemizedlist> |
4614 |
++ </refsect1> |
4615 |
++ |
4616 |
++ <refsect1> |
4617 |
++ <title>Return value</title> |
4618 |
++ <para> |
4619 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
4620 |
++ on error, <errorcode>-1</errorcode> is returned, and |
4621 |
++ <varname>errno</varname> is set to indicate the error. |
4622 |
++ If the issued ioctl is illegal for the file descriptor used, |
4623 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
4624 |
++ </para> |
4625 |
++ |
4626 |
++ <refsect2> |
4627 |
++ <title> |
4628 |
++ <constant>KDBUS_CMD_SEND</constant> may fail with the following |
4629 |
++ errors |
4630 |
++ </title> |
4631 |
++ |
4632 |
++ <variablelist> |
4633 |
++ <varlistentry> |
4634 |
++ <term><constant>EOPNOTSUPP</constant></term> |
4635 |
++ <listitem><para> |
4636 |
++ The connection is not an ordinary connection, or the passed |
4637 |
++ file descriptors in <constant>KDBUS_ITEM_FDS</constant> item are |
4638 |
++ either kdbus handles or unix domain sockets. Both are currently |
4639 |
++ unsupported. |
4640 |
++ </para></listitem> |
4641 |
++ </varlistentry> |
4642 |
++ |
4643 |
++ <varlistentry> |
4644 |
++ <term><constant>EINVAL</constant></term> |
4645 |
++ <listitem><para> |
4646 |
++ The submitted payload type is |
4647 |
++ <constant>KDBUS_PAYLOAD_KERNEL</constant>, |
4648 |
++ <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set without timeout |
4649 |
++ or cookie values, <constant>KDBUS_SEND_SYNC_REPLY</constant> was |
4650 |
++ set without <constant>KDBUS_MSG_EXPECT_REPLY</constant>, an invalid |
4651 |
++ item was supplied, <constant>src_id</constant> was non-zero and was |
4652 |
++ different from the current connection's ID, a supplied memfd had a |
4653 |
++ size of 0, or a string was not properly null-terminated. |
4654 |
++ </para></listitem> |
4655 |
++ </varlistentry> |
4656 |
++ |
4657 |
++ <varlistentry> |
4658 |
++ <term><constant>ENOTUNIQ</constant></term> |
4659 |
++ <listitem><para> |
4660 |
++ The supplied destination is |
4661 |
++ <constant>KDBUS_DST_ID_BROADCAST</constant> and either |
4662 |
++ file descriptors were passed, or |
4663 |
++ <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set, |
4664 |
++ or a timeout was given. |
4665 |
++ </para></listitem> |
4666 |
++ </varlistentry> |
4667 |
++ |
4668 |
++ <varlistentry> |
4669 |
++ <term><constant>E2BIG</constant></term> |
4670 |
++ <listitem><para> |
4671 |
++ Too many items. |
4672 |
++ </para></listitem> |
4673 |
++ </varlistentry> |
4674 |
++ |
4675 |
++ <varlistentry> |
4676 |
++ <term><constant>EMSGSIZE</constant></term> |
4677 |
++ <listitem><para> |
4678 |
++ The size of the message header and items or the payload vector |
4679 |
++ is excessive. |
4680 |
++ </para></listitem> |
4681 |
++ </varlistentry> |
4682 |
++ |
4683 |
++ <varlistentry> |
4684 |
++ <term><constant>EEXIST</constant></term> |
4685 |
++ <listitem><para> |
4686 |
++ Multiple <constant>KDBUS_ITEM_FDS</constant>, |
4687 |
++ <constant>KDBUS_ITEM_BLOOM_FILTER</constant> or |
4688 |
++ <constant>KDBUS_ITEM_DST_NAME</constant> items were supplied. |
4689 |
++ </para></listitem> |
4690 |
++ </varlistentry> |
4691 |
++ |
4692 |
++ <varlistentry> |
4693 |
++ <term><constant>EBADF</constant></term> |
4694 |
++ <listitem><para> |
4695 |
++ The supplied <constant>KDBUS_ITEM_FDS</constant> or |
4696 |
++ <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> items |
4697 |
++ contained an illegal file descriptor. |
4698 |
++ </para></listitem> |
4699 |
++ </varlistentry> |
4700 |
++ |
4701 |
++ <varlistentry> |
4702 |
++ <term><constant>EMEDIUMTYPE</constant></term> |
4703 |
++ <listitem><para> |
4704 |
++ The supplied memfd is not a sealed kdbus memfd. |
4705 |
++ </para></listitem> |
4706 |
++ </varlistentry> |
4707 |
++ |
4708 |
++ <varlistentry> |
4709 |
++ <term><constant>EMFILE</constant></term> |
4710 |
++ <listitem><para> |
4711 |
++ Too many file descriptors inside a |
4712 |
++ <constant>KDBUS_ITEM_FDS</constant>. |
4713 |
++ </para></listitem> |
4714 |
++ </varlistentry> |
4715 |
++ |
4716 |
++ <varlistentry> |
4717 |
++ <term><constant>EBADMSG</constant></term> |
4718 |
++ <listitem><para> |
4719 |
++ An item had illegal size, both a <constant>dst_id</constant> and a |
4720 |
++ <constant>KDBUS_ITEM_DST_NAME</constant> was given, or both a name |
4721 |
++ and a bloom filter was given. |
4722 |
++ </para></listitem> |
4723 |
++ </varlistentry> |
4724 |
++ |
4725 |
++ <varlistentry> |
4726 |
++ <term><constant>ETXTBSY</constant></term> |
4727 |
++ <listitem><para> |
4728 |
++ The supplied kdbus memfd file cannot be sealed or the seal |
4729 |
++ was removed, because it is shared with other processes or |
4730 |
++ still mapped with |
4731 |
++ <citerefentry> |
4732 |
++ <refentrytitle>mmap</refentrytitle> |
4733 |
++ <manvolnum>2</manvolnum> |
4734 |
++ </citerefentry>. |
4735 |
++ </para></listitem> |
4736 |
++ </varlistentry> |
4737 |
++ |
4738 |
++ <varlistentry> |
4739 |
++ <term><constant>ECOMM</constant></term> |
4740 |
++ <listitem><para> |
4741 |
++ A peer does not accept the file descriptors addressed to it. |
4742 |
++ </para></listitem> |
4743 |
++ </varlistentry> |
4744 |
++ |
4745 |
++ <varlistentry> |
4746 |
++ <term><constant>EFAULT</constant></term> |
4747 |
++ <listitem><para> |
4748 |
++ The supplied bloom filter size was not 64-bit aligned, or supplied |
4749 |
++ memory could not be accessed by the kernel. |
4750 |
++ </para></listitem> |
4751 |
++ </varlistentry> |
4752 |
++ |
4753 |
++ <varlistentry> |
4754 |
++ <term><constant>EDOM</constant></term> |
4755 |
++ <listitem><para> |
4756 |
++ The supplied bloom filter size did not match the bloom filter |
4757 |
++ size of the bus. |
4758 |
++ </para></listitem> |
4759 |
++ </varlistentry> |
4760 |
++ |
4761 |
++ <varlistentry> |
4762 |
++ <term><constant>EDESTADDRREQ</constant></term> |
4763 |
++ <listitem><para> |
4764 |
++ <constant>dst_id</constant> was set to |
4765 |
++ <constant>KDBUS_DST_ID_NAME</constant>, but no |
4766 |
++ <constant>KDBUS_ITEM_DST_NAME</constant> was attached. |
4767 |
++ </para></listitem> |
4768 |
++ </varlistentry> |
4769 |
++ |
4770 |
++ <varlistentry> |
4771 |
++ <term><constant>ESRCH</constant></term> |
4772 |
++ <listitem><para> |
4773 |
++ The name to look up was not found in the name registry. |
4774 |
++ </para></listitem> |
4775 |
++ </varlistentry> |
4776 |
++ |
4777 |
++ <varlistentry> |
4778 |
++ <term><constant>EADDRNOTAVAIL</constant></term> |
4779 |
++ <listitem><para> |
4780 |
++ <constant>KDBUS_MSG_NO_AUTO_START</constant> was given but the |
4781 |
++ destination connection is an activator. |
4782 |
++ </para></listitem> |
4783 |
++ </varlistentry> |
4784 |
++ |
4785 |
++ <varlistentry> |
4786 |
++ <term><constant>ENXIO</constant></term> |
4787 |
++ <listitem><para> |
4788 |
++ The passed numeric destination connection ID couldn't be found, |
4789 |
++ or is not connected. |
4790 |
++ </para></listitem> |
4791 |
++ </varlistentry> |
4792 |
++ |
4793 |
++ <varlistentry> |
4794 |
++ <term><constant>ECONNRESET</constant></term> |
4795 |
++ <listitem><para> |
4796 |
++ The destination connection is no longer active. |
4797 |
++ </para></listitem> |
4798 |
++ </varlistentry> |
4799 |
++ |
4800 |
++ <varlistentry> |
4801 |
++ <term><constant>ETIMEDOUT</constant></term> |
4802 |
++ <listitem><para> |
4803 |
++ Timeout while synchronously waiting for a reply. |
4804 |
++ </para></listitem> |
4805 |
++ </varlistentry> |
4806 |
++ |
4807 |
++ <varlistentry> |
4808 |
++ <term><constant>EINTR</constant></term> |
4809 |
++ <listitem><para> |
4810 |
++ Interrupted system call while synchronously waiting for a reply. |
4811 |
++ </para></listitem> |
4812 |
++ </varlistentry> |
4813 |
++ |
4814 |
++ <varlistentry> |
4815 |
++ <term><constant>EPIPE</constant></term> |
4816 |
++ <listitem><para> |
4817 |
++ When sending a message, a synchronous reply from the receiving |
4818 |
++ connection was expected but the connection died before answering. |
4819 |
++ </para></listitem> |
4820 |
++ </varlistentry> |
4821 |
++ |
4822 |
++ <varlistentry> |
4823 |
++ <term><constant>ENOBUFS</constant></term> |
4824 |
++ <listitem><para> |
4825 |
++ Too many pending messages on the receiver side. |
4826 |
++ </para></listitem> |
4827 |
++ </varlistentry> |
4828 |
++ |
4829 |
++ <varlistentry> |
4830 |
++ <term><constant>EREMCHG</constant></term> |
4831 |
++ <listitem><para> |
4832 |
++ Both a well-known name and a unique name (ID) was given, but |
4833 |
++ the name is not currently owned by that connection. |
4834 |
++ </para></listitem> |
4835 |
++ </varlistentry> |
4836 |
++ |
4837 |
++ <varlistentry> |
4838 |
++ <term><constant>EXFULL</constant></term> |
4839 |
++ <listitem><para> |
4840 |
++ The memory pool of the receiver is full. |
4841 |
++ </para></listitem> |
4842 |
++ </varlistentry> |
4843 |
++ |
4844 |
++ <varlistentry> |
4845 |
++ <term><constant>EREMOTEIO</constant></term> |
4846 |
++ <listitem><para> |
4847 |
++ While synchronously waiting for a reply, the remote peer |
4848 |
++ failed with an I/O error. |
4849 |
++ </para></listitem> |
4850 |
++ </varlistentry> |
4851 |
++ </variablelist> |
4852 |
++ </refsect2> |
4853 |
++ |
4854 |
++ <refsect2> |
4855 |
++ <title> |
4856 |
++ <constant>KDBUS_CMD_RECV</constant> may fail with the following |
4857 |
++ errors |
4858 |
++ </title> |
4859 |
++ |
4860 |
++ <variablelist> |
4861 |
++ <varlistentry> |
4862 |
++ <term><constant>EOPNOTSUPP</constant></term> |
4863 |
++ <listitem><para> |
4864 |
++ The connection is not an ordinary connection, or the passed |
4865 |
++ file descriptors are either kdbus handles or unix domain |
4866 |
++ sockets. Both are currently unsupported. |
4867 |
++ </para></listitem> |
4868 |
++ </varlistentry> |
4869 |
++ |
4870 |
++ <varlistentry> |
4871 |
++ <term><constant>EINVAL</constant></term> |
4872 |
++ <listitem><para> |
4873 |
++ Invalid flags or offset. |
4874 |
++ </para></listitem> |
4875 |
++ </varlistentry> |
4876 |
++ |
4877 |
++ <varlistentry> |
4878 |
++ <term><constant>EAGAIN</constant></term> |
4879 |
++ <listitem><para> |
4880 |
++ No message found in the queue. |
4881 |
++ </para></listitem> |
4882 |
++ </varlistentry> |
4883 |
++ </variablelist> |
4884 |
++ </refsect2> |
4885 |
++ </refsect1> |
4886 |
++ |
4887 |
++ <refsect1> |
4888 |
++ <title>See Also</title> |
4889 |
++ <simplelist type="inline"> |
4890 |
++ <member> |
4891 |
++ <citerefentry> |
4892 |
++ <refentrytitle>kdbus</refentrytitle> |
4893 |
++ <manvolnum>7</manvolnum> |
4894 |
++ </citerefentry> |
4895 |
++ </member> |
4896 |
++ <member> |
4897 |
++ <citerefentry> |
4898 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
4899 |
++ <manvolnum>7</manvolnum> |
4900 |
++ </citerefentry> |
4901 |
++ </member> |
4902 |
++ <member> |
4903 |
++ <citerefentry> |
4904 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
4905 |
++ <manvolnum>7</manvolnum> |
4906 |
++ </citerefentry> |
4907 |
++ </member> |
4908 |
++ <member> |
4909 |
++ <citerefentry> |
4910 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
4911 |
++ <manvolnum>7</manvolnum> |
4912 |
++ </citerefentry> |
4913 |
++ </member> |
4914 |
++ <member> |
4915 |
++ <citerefentry> |
4916 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
4917 |
++ <manvolnum>7</manvolnum> |
4918 |
++ </citerefentry> |
4919 |
++ </member> |
4920 |
++ <member> |
4921 |
++ <citerefentry> |
4922 |
++ <refentrytitle>kdbus.item</refentrytitle> |
4923 |
++ <manvolnum>7</manvolnum> |
4924 |
++ </citerefentry> |
4925 |
++ </member> |
4926 |
++ <member> |
4927 |
++ <citerefentry> |
4928 |
++ <refentrytitle>kdbus.name</refentrytitle> |
4929 |
++ <manvolnum>7</manvolnum> |
4930 |
++ </citerefentry> |
4931 |
++ </member> |
4932 |
++ <member> |
4933 |
++ <citerefentry> |
4934 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
4935 |
++ <manvolnum>7</manvolnum> |
4936 |
++ </citerefentry> |
4937 |
++ </member> |
4938 |
++ <member> |
4939 |
++ <citerefentry> |
4940 |
++ <refentrytitle>clock_gettime</refentrytitle> |
4941 |
++ <manvolnum>2</manvolnum> |
4942 |
++ </citerefentry> |
4943 |
++ </member> |
4944 |
++ <member> |
4945 |
++ <citerefentry> |
4946 |
++ <refentrytitle>ioctl</refentrytitle> |
4947 |
++ <manvolnum>2</manvolnum> |
4948 |
++ </citerefentry> |
4949 |
++ </member> |
4950 |
++ <member> |
4951 |
++ <citerefentry> |
4952 |
++ <refentrytitle>poll</refentrytitle> |
4953 |
++ <manvolnum>2</manvolnum> |
4954 |
++ </citerefentry> |
4955 |
++ </member> |
4956 |
++ <member> |
4957 |
++ <citerefentry> |
4958 |
++ <refentrytitle>select</refentrytitle> |
4959 |
++ <manvolnum>2</manvolnum> |
4960 |
++ </citerefentry> |
4961 |
++ </member> |
4962 |
++ <member> |
4963 |
++ <citerefentry> |
4964 |
++ <refentrytitle>epoll</refentrytitle> |
4965 |
++ <manvolnum>7</manvolnum> |
4966 |
++ </citerefentry> |
4967 |
++ </member> |
4968 |
++ <member> |
4969 |
++ <citerefentry> |
4970 |
++ <refentrytitle>eventfd</refentrytitle> |
4971 |
++ <manvolnum>2</manvolnum> |
4972 |
++ </citerefentry> |
4973 |
++ </member> |
4974 |
++ <member> |
4975 |
++ <citerefentry> |
4976 |
++ <refentrytitle>memfd_create</refentrytitle> |
4977 |
++ <manvolnum>2</manvolnum> |
4978 |
++ </citerefentry> |
4979 |
++ </member> |
4980 |
++ </simplelist> |
4981 |
++ </refsect1> |
4982 |
++</refentry> |
4983 |
+diff --git a/Documentation/kdbus/kdbus.name.xml b/Documentation/kdbus/kdbus.name.xml |
4984 |
+new file mode 100644 |
4985 |
+index 0000000..3f5f6a6 |
4986 |
+--- /dev/null |
4987 |
++++ b/Documentation/kdbus/kdbus.name.xml |
4988 |
+@@ -0,0 +1,711 @@ |
4989 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
4990 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
4991 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
4992 |
++ |
4993 |
++<refentry id="kdbus.name"> |
4994 |
++ |
4995 |
++ <refentryinfo> |
4996 |
++ <title>kdbus.name</title> |
4997 |
++ <productname>kdbus.name</productname> |
4998 |
++ </refentryinfo> |
4999 |
++ |
5000 |
++ <refmeta> |
5001 |
++ <refentrytitle>kdbus.name</refentrytitle> |
5002 |
++ <manvolnum>7</manvolnum> |
5003 |
++ </refmeta> |
5004 |
++ |
5005 |
++ <refnamediv> |
5006 |
++ <refname>kdbus.name</refname> |
5007 |
++ <refpurpose>kdbus.name</refpurpose> |
5008 |
++ </refnamediv> |
5009 |
++ |
5010 |
++ <refsect1> |
5011 |
++ <title>Description</title> |
5012 |
++ <para> |
5013 |
++ Each |
5014 |
++ <citerefentry> |
5015 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
5016 |
++ <manvolnum>7</manvolnum> |
5017 |
++ </citerefentry> |
5018 |
++ instantiates a name registry to resolve well-known names into unique |
5019 |
++ connection IDs for message delivery. The registry will be queried when a |
5020 |
++ message is sent with <varname>kdbus_msg.dst_id</varname> set to |
5021 |
++ <constant>KDBUS_DST_ID_NAME</constant>, or when a registry dump is |
5022 |
++ requested with <constant>KDBUS_CMD_NAME_LIST</constant>. |
5023 |
++ </para> |
5024 |
++ |
5025 |
++ <para> |
5026 |
++ All of the below is subject to policy rules for <emphasis>SEE</emphasis> |
5027 |
++ and <emphasis>OWN</emphasis> permissions. See |
5028 |
++ <citerefentry> |
5029 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
5030 |
++ <manvolnum>7</manvolnum> |
5031 |
++ </citerefentry> |
5032 |
++ for more information. |
5033 |
++ </para> |
5034 |
++ </refsect1> |
5035 |
++ |
5036 |
++ <refsect1> |
5037 |
++ <title>Name validity</title> |
5038 |
++ <para> |
5039 |
++ A name has to comply with the following rules in order to be considered |
5040 |
++ valid. |
5041 |
++ </para> |
5042 |
++ |
5043 |
++ <itemizedlist> |
5044 |
++ <listitem> |
5045 |
++ <para> |
5046 |
++ The name has two or more elements separated by a |
5047 |
++ '<literal>.</literal>' (period) character. |
5048 |
++ </para> |
5049 |
++ </listitem> |
5050 |
++ <listitem> |
5051 |
++ <para> |
5052 |
++ All elements must contain at least one character. |
5053 |
++ </para> |
5054 |
++ </listitem> |
5055 |
++ <listitem> |
5056 |
++ <para> |
5057 |
++ Each element must only contain the ASCII characters |
5058 |
++ <literal>[A-Z][a-z][0-9]_</literal> and must not begin with a |
5059 |
++ digit. |
5060 |
++ </para> |
5061 |
++ </listitem> |
5062 |
++ <listitem> |
5063 |
++ <para> |
5064 |
++ The name must contain at least one '<literal>.</literal>' (period) |
5065 |
++ character (and thus at least two elements). |
5066 |
++ </para> |
5067 |
++ </listitem> |
5068 |
++ <listitem> |
5069 |
++ <para> |
5070 |
++ The name must not begin with a '<literal>.</literal>' (period) |
5071 |
++ character. |
5072 |
++ </para> |
5073 |
++ </listitem> |
5074 |
++ <listitem> |
5075 |
++ <para> |
5076 |
++ The name must not exceed <constant>255</constant> characters in |
5077 |
++ length. |
5078 |
++ </para> |
5079 |
++ </listitem> |
5080 |
++ </itemizedlist> |
5081 |
++ </refsect1> |
5082 |
++ |
5083 |
++ <refsect1> |
5084 |
++ <title>Acquiring a name</title> |
5085 |
++ <para> |
5086 |
++ To acquire a name, a client uses the |
5087 |
++ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> ioctl with |
5088 |
++ <type>struct kdbus_cmd</type> as argument. |
5089 |
++ </para> |
5090 |
++ |
5091 |
++ <programlisting> |
5092 |
++struct kdbus_cmd { |
5093 |
++ __u64 size; |
5094 |
++ __u64 flags; |
5095 |
++ __u64 return_flags; |
5096 |
++ struct kdbus_item items[0]; |
5097 |
++}; |
5098 |
++ </programlisting> |
5099 |
++ |
5100 |
++ <para>The fields in this struct are described below.</para> |
5101 |
++ |
5102 |
++ <variablelist> |
5103 |
++ <varlistentry> |
5104 |
++ <term><varname>size</varname></term> |
5105 |
++ <listitem><para> |
5106 |
++ The overall size of the struct, including its items. |
5107 |
++ </para></listitem> |
5108 |
++ </varlistentry> |
5109 |
++ |
5110 |
++ <varlistentry> |
5111 |
++ <term><varname>flags</varname></term> |
5112 |
++ <listitem><para>Flags to control details in the name acquisition.</para> |
5113 |
++ <variablelist> |
5114 |
++ <varlistentry> |
5115 |
++ <term><constant>KDBUS_NAME_REPLACE_EXISTING</constant></term> |
5116 |
++ <listitem> |
5117 |
++ <para> |
5118 |
++ Acquiring a name that is already present usually fails, |
5119 |
++ unless this flag is set in the call, and |
5120 |
++ <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> (see below) |
5121 |
++ was set when the current owner of the name acquired it, or |
5122 |
++ if the current owner is an activator connection (see |
5123 |
++ <citerefentry> |
5124 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
5125 |
++ <manvolnum>7</manvolnum> |
5126 |
++ </citerefentry>). |
5127 |
++ </para> |
5128 |
++ </listitem> |
5129 |
++ </varlistentry> |
5130 |
++ |
5131 |
++ <varlistentry> |
5132 |
++ <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term> |
5133 |
++ <listitem> |
5134 |
++ <para> |
5135 |
++ Allow other connections to take over this name. When this |
5136 |
++ happens, the former owner of the connection will be notified |
5137 |
++ of the name loss. |
5138 |
++ </para> |
5139 |
++ </listitem> |
5140 |
++ </varlistentry> |
5141 |
++ |
5142 |
++ <varlistentry> |
5143 |
++ <term><constant>KDBUS_NAME_QUEUE</constant></term> |
5144 |
++ <listitem> |
5145 |
++ <para> |
5146 |
++ A name that is already acquired by a connection can not be |
5147 |
++ acquired again (unless the |
5148 |
++ <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> flag was |
5149 |
++ set during acquisition; see above). |
5150 |
++ However, a connection can put itself in a queue of |
5151 |
++ connections waiting for the name to be released. Once that |
5152 |
++ happens, the first connection in that queue becomes the new |
5153 |
++ owner and is notified accordingly. |
5154 |
++ </para> |
5155 |
++ </listitem> |
5156 |
++ </varlistentry> |
5157 |
++ |
5158 |
++ <varlistentry> |
5159 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5160 |
++ <listitem> |
5161 |
++ <para> |
5162 |
++ Request a set of valid flags for this ioctl. When this bit is |
5163 |
++ set, no action is taken; the ioctl will fail with |
5164 |
++ <errorcode>-1</errorcode>, and <varname>errno</varname> |
5165 |
++ is set to <constant>EPROTO</constant>. |
5166 |
++ Once the ioctl returned, the <varname>flags</varname> |
5167 |
++ field will have all bits set that the kernel recognizes as |
5168 |
++ valid for this command. |
5169 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5170 |
++ cleared by the operation. |
5171 |
++ </para> |
5172 |
++ </listitem> |
5173 |
++ </varlistentry> |
5174 |
++ </variablelist> |
5175 |
++ </listitem> |
5176 |
++ </varlistentry> |
5177 |
++ |
5178 |
++ <varlistentry> |
5179 |
++ <term><varname>return_flags</varname></term> |
5180 |
++ <listitem> |
5181 |
++ <para> |
5182 |
++ Flags returned by the kernel. Currently, the following may be |
5183 |
++ returned by the kernel. |
5184 |
++ </para> |
5185 |
++ <variablelist> |
5186 |
++ <varlistentry> |
5187 |
++ <term><constant>KDBUS_NAME_IN_QUEUE</constant></term> |
5188 |
++ <listitem> |
5189 |
++ <para> |
5190 |
++ The name was not acquired yet, but the connection was |
5191 |
++ placed in the queue of peers waiting for the name. |
5192 |
++ This can only happen if <constant>KDBUS_NAME_QUEUE</constant> |
5193 |
++ was set in the <varname>flags</varname> member (see above). |
5194 |
++ The connection will receive a name owner change notification |
5195 |
++ once the current owner has given up the name and its |
5196 |
++ ownership was transferred. |
5197 |
++ </para> |
5198 |
++ </listitem> |
5199 |
++ </varlistentry> |
5200 |
++ </variablelist> |
5201 |
++ </listitem> |
5202 |
++ </varlistentry> |
5203 |
++ |
5204 |
++ <varlistentry> |
5205 |
++ <term><varname>items</varname></term> |
5206 |
++ <listitem> |
5207 |
++ <para> |
5208 |
++ Items to submit the name. Currently, one item of type |
5209 |
++ <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and |
5210 |
++ the contained string must be a valid bus name. |
5211 |
++ <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for |
5212 |
++ valid item types. See |
5213 |
++ <citerefentry> |
5214 |
++ <refentrytitle>kdbus.item</refentrytitle> |
5215 |
++ <manvolnum>7</manvolnum> |
5216 |
++ </citerefentry> |
5217 |
++ for a detailed description of how this item is used. |
5218 |
++ </para> |
5219 |
++ <para> |
5220 |
++ Unrecognized items are rejected, and the ioctl will fail with |
5221 |
++ <varname>errno</varname> set to <errorname>>EINVAL</errorname>. |
5222 |
++ </para> |
5223 |
++ </listitem> |
5224 |
++ </varlistentry> |
5225 |
++ </variablelist> |
5226 |
++ </refsect1> |
5227 |
++ |
5228 |
++ <refsect1> |
5229 |
++ <title>Releasing a name</title> |
5230 |
++ <para> |
5231 |
++ A connection may release a name explicitly with the |
5232 |
++ <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl. If the connection was |
5233 |
++ an implementer of an activatable name, its pending messages are moved |
5234 |
++ back to the activator. If there are any connections queued up as waiters |
5235 |
++ for the name, the first one in the queue (the oldest entry) will become |
5236 |
++ the new owner. The same happens implicitly for all names once a |
5237 |
++ connection terminates. See |
5238 |
++ <citerefentry> |
5239 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
5240 |
++ <manvolnum>7</manvolnum> |
5241 |
++ </citerefentry> |
5242 |
++ for more information on connections. |
5243 |
++ </para> |
5244 |
++ <para> |
5245 |
++ The <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl uses the same data |
5246 |
++ structure as the acquisition call |
5247 |
++ (<constant>KDBUS_CMD_NAME_ACQUIRE</constant>), |
5248 |
++ but with slightly different field usage. |
5249 |
++ </para> |
5250 |
++ |
5251 |
++ <programlisting> |
5252 |
++struct kdbus_cmd { |
5253 |
++ __u64 size; |
5254 |
++ __u64 flags; |
5255 |
++ __u64 return_flags; |
5256 |
++ struct kdbus_item items[0]; |
5257 |
++}; |
5258 |
++ </programlisting> |
5259 |
++ |
5260 |
++ <para>The fields in this struct are described below.</para> |
5261 |
++ |
5262 |
++ <variablelist> |
5263 |
++ <varlistentry> |
5264 |
++ <term><varname>size</varname></term> |
5265 |
++ <listitem><para> |
5266 |
++ The overall size of the struct, including its items. |
5267 |
++ </para></listitem> |
5268 |
++ </varlistentry> |
5269 |
++ |
5270 |
++ <varlistentry> |
5271 |
++ <term><varname>flags</varname></term> |
5272 |
++ <listitem><para> |
5273 |
++ Flags to the command. Currently unused. |
5274 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
5275 |
++ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
5276 |
++ and the <varname>flags</varname> field is set to |
5277 |
++ <constant>0</constant>. |
5278 |
++ </para></listitem> |
5279 |
++ </varlistentry> |
5280 |
++ |
5281 |
++ <varlistentry> |
5282 |
++ <term><varname>return_flags</varname></term> |
5283 |
++ <listitem><para> |
5284 |
++ Flags returned by the kernel. Currently unused and always set to |
5285 |
++ <constant>0</constant> by the kernel. |
5286 |
++ </para></listitem> |
5287 |
++ </varlistentry> |
5288 |
++ |
5289 |
++ <varlistentry> |
5290 |
++ <term><varname>items</varname></term> |
5291 |
++ <listitem> |
5292 |
++ <para> |
5293 |
++ Items to submit the name. Currently, one item of type |
5294 |
++ <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and |
5295 |
++ the contained string must be a valid bus name. |
5296 |
++ <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for |
5297 |
++ valid item types. See |
5298 |
++ <citerefentry> |
5299 |
++ <refentrytitle>kdbus.item</refentrytitle> |
5300 |
++ <manvolnum>7</manvolnum> |
5301 |
++ </citerefentry> |
5302 |
++ for a detailed description of how this item is used. |
5303 |
++ </para> |
5304 |
++ <para> |
5305 |
++ Unrecognized items are rejected, and the ioctl will fail with |
5306 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
5307 |
++ </para> |
5308 |
++ </listitem> |
5309 |
++ </varlistentry> |
5310 |
++ </variablelist> |
5311 |
++ </refsect1> |
5312 |
++ |
5313 |
++ <refsect1> |
5314 |
++ <title>Dumping the name registry</title> |
5315 |
++ <para> |
5316 |
++ A connection may request a complete or filtered dump of currently active |
5317 |
++ bus names with the <constant>KDBUS_CMD_LIST</constant> ioctl, which |
5318 |
++ takes a <type>struct kdbus_cmd_list</type> as argument. |
5319 |
++ </para> |
5320 |
++ |
5321 |
++ <programlisting> |
5322 |
++struct kdbus_cmd_list { |
5323 |
++ __u64 flags; |
5324 |
++ __u64 return_flags; |
5325 |
++ __u64 offset; |
5326 |
++}; |
5327 |
++ </programlisting> |
5328 |
++ |
5329 |
++ <para>The fields in this struct are described below.</para> |
5330 |
++ |
5331 |
++ <variablelist> |
5332 |
++ <varlistentry> |
5333 |
++ <term><varname>flags</varname></term> |
5334 |
++ <listitem> |
5335 |
++ <para> |
5336 |
++ Any combination of flags to specify which names should be dumped. |
5337 |
++ </para> |
5338 |
++ <variablelist> |
5339 |
++ <varlistentry> |
5340 |
++ <term><constant>KDBUS_LIST_UNIQUE</constant></term> |
5341 |
++ <listitem> |
5342 |
++ <para> |
5343 |
++ List the unique (numeric) IDs of the connection, whether it |
5344 |
++ owns a name or not. |
5345 |
++ </para> |
5346 |
++ </listitem> |
5347 |
++ </varlistentry> |
5348 |
++ |
5349 |
++ <varlistentry> |
5350 |
++ <term><constant>KDBUS_LIST_NAMES</constant></term> |
5351 |
++ <listitem> |
5352 |
++ <para> |
5353 |
++ List well-known names stored in the database which are |
5354 |
++ actively owned by a real connection (not an activator). |
5355 |
++ </para> |
5356 |
++ </listitem> |
5357 |
++ </varlistentry> |
5358 |
++ |
5359 |
++ <varlistentry> |
5360 |
++ <term><constant>KDBUS_LIST_ACTIVATORS</constant></term> |
5361 |
++ <listitem> |
5362 |
++ <para> |
5363 |
++ List names that are owned by an activator. |
5364 |
++ </para> |
5365 |
++ </listitem> |
5366 |
++ </varlistentry> |
5367 |
++ |
5368 |
++ <varlistentry> |
5369 |
++ <term><constant>KDBUS_LIST_QUEUED</constant></term> |
5370 |
++ <listitem> |
5371 |
++ <para> |
5372 |
++ List connections that are not yet owning a name but are |
5373 |
++ waiting for it to become available. |
5374 |
++ </para> |
5375 |
++ </listitem> |
5376 |
++ </varlistentry> |
5377 |
++ |
5378 |
++ <varlistentry> |
5379 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5380 |
++ <listitem> |
5381 |
++ <para> |
5382 |
++ Request a set of valid flags for this ioctl. When this bit is |
5383 |
++ set, no action is taken; the ioctl will fail with |
5384 |
++ <errorcode>-1</errorcode>, and <varname>errno</varname> |
5385 |
++ is set to <constant>EPROTO</constant>. |
5386 |
++ Once the ioctl returned, the <varname>flags</varname> |
5387 |
++ field will have all bits set that the kernel recognizes as |
5388 |
++ valid for this command. |
5389 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5390 |
++ cleared by the operation. |
5391 |
++ </para> |
5392 |
++ </listitem> |
5393 |
++ </varlistentry> |
5394 |
++ </variablelist> |
5395 |
++ </listitem> |
5396 |
++ </varlistentry> |
5397 |
++ |
5398 |
++ <varlistentry> |
5399 |
++ <term><varname>return_flags</varname></term> |
5400 |
++ <listitem><para> |
5401 |
++ Flags returned by the kernel. Currently unused and always set to |
5402 |
++ <constant>0</constant> by the kernel. |
5403 |
++ </para></listitem> |
5404 |
++ </varlistentry> |
5405 |
++ |
5406 |
++ <varlistentry> |
5407 |
++ <term><varname>offset</varname></term> |
5408 |
++ <listitem><para> |
5409 |
++ When the ioctl returns successfully, the offset to the name registry |
5410 |
++ dump inside the connection's pool will be stored in this field. |
5411 |
++ </para></listitem> |
5412 |
++ </varlistentry> |
5413 |
++ </variablelist> |
5414 |
++ |
5415 |
++ <para> |
5416 |
++ The returned list of names is stored in a <type>struct kdbus_list</type> |
5417 |
++ that in turn contains an array of type <type>struct kdbus_info</type>, |
5418 |
++ The array-size in bytes is given as <varname>list_size</varname>. |
5419 |
++ The fields inside <type>struct kdbus_info</type> is described next. |
5420 |
++ </para> |
5421 |
++ |
5422 |
++ <programlisting> |
5423 |
++struct kdbus_info { |
5424 |
++ __u64 size; |
5425 |
++ __u64 id; |
5426 |
++ __u64 flags; |
5427 |
++ struct kdbus_item items[0]; |
5428 |
++}; |
5429 |
++ </programlisting> |
5430 |
++ |
5431 |
++ <para>The fields in this struct are described below.</para> |
5432 |
++ |
5433 |
++ <variablelist> |
5434 |
++ <varlistentry> |
5435 |
++ <term><varname>size</varname></term> |
5436 |
++ <listitem><para> |
5437 |
++ The overall size of the struct, including its items. |
5438 |
++ </para></listitem> |
5439 |
++ </varlistentry> |
5440 |
++ |
5441 |
++ <varlistentry> |
5442 |
++ <term><varname>id</varname></term> |
5443 |
++ <listitem><para> |
5444 |
++ The owning connection's unique ID. |
5445 |
++ </para></listitem> |
5446 |
++ </varlistentry> |
5447 |
++ |
5448 |
++ <varlistentry> |
5449 |
++ <term><varname>flags</varname></term> |
5450 |
++ <listitem><para> |
5451 |
++ The flags of the owning connection. |
5452 |
++ </para></listitem> |
5453 |
++ </varlistentry> |
5454 |
++ |
5455 |
++ <varlistentry> |
5456 |
++ <term><varname>items</varname></term> |
5457 |
++ <listitem> |
5458 |
++ <para> |
5459 |
++ Items containing the actual name. Currently, one item of type |
5460 |
++ <constant>KDBUS_ITEM_OWNED_NAME</constant> will be attached, |
5461 |
++ including the name's flags. In that item, the flags field of the |
5462 |
++ name may carry the following bits: |
5463 |
++ </para> |
5464 |
++ <variablelist> |
5465 |
++ <varlistentry> |
5466 |
++ <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term> |
5467 |
++ <listitem> |
5468 |
++ <para> |
5469 |
++ Other connections are allowed to take over this name from the |
5470 |
++ connection that owns it. |
5471 |
++ </para> |
5472 |
++ </listitem> |
5473 |
++ </varlistentry> |
5474 |
++ |
5475 |
++ <varlistentry> |
5476 |
++ <term><constant>KDBUS_NAME_IN_QUEUE</constant></term> |
5477 |
++ <listitem> |
5478 |
++ <para> |
5479 |
++ When retrieving a list of currently acquired names in the |
5480 |
++ registry, this flag indicates whether the connection |
5481 |
++ actually owns the name or is currently waiting for it to |
5482 |
++ become available. |
5483 |
++ </para> |
5484 |
++ </listitem> |
5485 |
++ </varlistentry> |
5486 |
++ |
5487 |
++ <varlistentry> |
5488 |
++ <term><constant>KDBUS_NAME_ACTIVATOR</constant></term> |
5489 |
++ <listitem> |
5490 |
++ <para> |
5491 |
++ An activator connection owns a name as a placeholder for an |
5492 |
++ implementer, which is started on demand by programs as soon |
5493 |
++ as the first message arrives. There's some more information |
5494 |
++ on this topic in |
5495 |
++ <citerefentry> |
5496 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
5497 |
++ <manvolnum>7</manvolnum> |
5498 |
++ </citerefentry> |
5499 |
++ . |
5500 |
++ </para> |
5501 |
++ <para> |
5502 |
++ In contrast to |
5503 |
++ <constant>KDBUS_NAME_REPLACE_EXISTING</constant>, |
5504 |
++ when a name is taken over from an activator connection, all |
5505 |
++ the messages that have been queued in the activator |
5506 |
++ connection will be moved over to the new owner. The activator |
5507 |
++ connection will still be tracked for the name and will take |
5508 |
++ control again if the implementer connection terminates. |
5509 |
++ </para> |
5510 |
++ <para> |
5511 |
++ This flag can not be used when acquiring a name, but is |
5512 |
++ implicitly set through <constant>KDBUS_CMD_HELLO</constant> |
5513 |
++ with <constant>KDBUS_HELLO_ACTIVATOR</constant> set in |
5514 |
++ <varname>kdbus_cmd_hello.conn_flags</varname>. |
5515 |
++ </para> |
5516 |
++ </listitem> |
5517 |
++ </varlistentry> |
5518 |
++ |
5519 |
++ <varlistentry> |
5520 |
++ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5521 |
++ <listitem> |
5522 |
++ <para> |
5523 |
++ Requests a set of valid flags for this ioctl. When this bit is |
5524 |
++ set, no action is taken; the ioctl will return |
5525 |
++ <errorcode>0</errorcode>, and the <varname>flags</varname> |
5526 |
++ field will have all bits set that are valid for this command. |
5527 |
++ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5528 |
++ cleared by the operation. |
5529 |
++ </para> |
5530 |
++ </listitem> |
5531 |
++ </varlistentry> |
5532 |
++ </variablelist> |
5533 |
++ </listitem> |
5534 |
++ </varlistentry> |
5535 |
++ </variablelist> |
5536 |
++ |
5537 |
++ <para> |
5538 |
++ The returned buffer must be freed with the |
5539 |
++ <constant>KDBUS_CMD_FREE</constant> ioctl when the user is finished with |
5540 |
++ it. See |
5541 |
++ <citerefentry> |
5542 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
5543 |
++ <manvolnum>7</manvolnum> |
5544 |
++ </citerefentry> |
5545 |
++ for more information. |
5546 |
++ </para> |
5547 |
++ </refsect1> |
5548 |
++ |
5549 |
++ <refsect1> |
5550 |
++ <title>Return value</title> |
5551 |
++ <para> |
5552 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
5553 |
++ on error, <errorcode>-1</errorcode> is returned, and |
5554 |
++ <varname>errno</varname> is set to indicate the error. |
5555 |
++ If the issued ioctl is illegal for the file descriptor used, |
5556 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
5557 |
++ </para> |
5558 |
++ |
5559 |
++ <refsect2> |
5560 |
++ <title> |
5561 |
++ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> may fail with the following |
5562 |
++ errors |
5563 |
++ </title> |
5564 |
++ |
5565 |
++ <variablelist> |
5566 |
++ <varlistentry> |
5567 |
++ <term><constant>EINVAL</constant></term> |
5568 |
++ <listitem><para> |
5569 |
++ Illegal command flags, illegal name provided, or an activator |
5570 |
++ tried to acquire a second name. |
5571 |
++ </para></listitem> |
5572 |
++ </varlistentry> |
5573 |
++ |
5574 |
++ <varlistentry> |
5575 |
++ <term><constant>EPERM</constant></term> |
5576 |
++ <listitem><para> |
5577 |
++ Policy prohibited name ownership. |
5578 |
++ </para></listitem> |
5579 |
++ </varlistentry> |
5580 |
++ |
5581 |
++ <varlistentry> |
5582 |
++ <term><constant>EALREADY</constant></term> |
5583 |
++ <listitem><para> |
5584 |
++ Connection already owns that name. |
5585 |
++ </para></listitem> |
5586 |
++ </varlistentry> |
5587 |
++ |
5588 |
++ <varlistentry> |
5589 |
++ <term><constant>EEXIST</constant></term> |
5590 |
++ <listitem><para> |
5591 |
++ The name already exists and can not be taken over. |
5592 |
++ </para></listitem> |
5593 |
++ </varlistentry> |
5594 |
++ |
5595 |
++ <varlistentry> |
5596 |
++ <term><constant>E2BIG</constant></term> |
5597 |
++ <listitem><para> |
5598 |
++ The maximum number of well-known names per connection is exhausted. |
5599 |
++ </para></listitem> |
5600 |
++ </varlistentry> |
5601 |
++ </variablelist> |
5602 |
++ </refsect2> |
5603 |
++ |
5604 |
++ <refsect2> |
5605 |
++ <title> |
5606 |
++ <constant>KDBUS_CMD_NAME_RELEASE</constant> |
5607 |
++ may fail with the following errors |
5608 |
++ </title> |
5609 |
++ |
5610 |
++ <variablelist> |
5611 |
++ <varlistentry> |
5612 |
++ <term><constant>EINVAL</constant></term> |
5613 |
++ <listitem><para> |
5614 |
++ Invalid command flags, or invalid name provided. |
5615 |
++ </para></listitem> |
5616 |
++ </varlistentry> |
5617 |
++ |
5618 |
++ <varlistentry> |
5619 |
++ <term><constant>ESRCH</constant></term> |
5620 |
++ <listitem><para> |
5621 |
++ Name is not found in the registry. |
5622 |
++ </para></listitem> |
5623 |
++ </varlistentry> |
5624 |
++ |
5625 |
++ <varlistentry> |
5626 |
++ <term><constant>EADDRINUSE</constant></term> |
5627 |
++ <listitem><para> |
5628 |
++ Name is owned by a different connection and can't be released. |
5629 |
++ </para></listitem> |
5630 |
++ </varlistentry> |
5631 |
++ </variablelist> |
5632 |
++ </refsect2> |
5633 |
++ |
5634 |
++ <refsect2> |
5635 |
++ <title> |
5636 |
++ <constant>KDBUS_CMD_LIST</constant> may fail with the following |
5637 |
++ errors |
5638 |
++ </title> |
5639 |
++ |
5640 |
++ <variablelist> |
5641 |
++ <varlistentry> |
5642 |
++ <term><constant>EINVAL</constant></term> |
5643 |
++ <listitem><para> |
5644 |
++ Invalid command flags |
5645 |
++ </para></listitem> |
5646 |
++ </varlistentry> |
5647 |
++ |
5648 |
++ <varlistentry> |
5649 |
++ <term><constant>ENOBUFS</constant></term> |
5650 |
++ <listitem><para> |
5651 |
++ No available memory in the connection's pool. |
5652 |
++ </para></listitem> |
5653 |
++ </varlistentry> |
5654 |
++ </variablelist> |
5655 |
++ </refsect2> |
5656 |
++ </refsect1> |
5657 |
++ |
5658 |
++ <refsect1> |
5659 |
++ <title>See Also</title> |
5660 |
++ <simplelist type="inline"> |
5661 |
++ <member> |
5662 |
++ <citerefentry> |
5663 |
++ <refentrytitle>kdbus</refentrytitle> |
5664 |
++ <manvolnum>7</manvolnum> |
5665 |
++ </citerefentry> |
5666 |
++ </member> |
5667 |
++ <member> |
5668 |
++ <citerefentry> |
5669 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
5670 |
++ <manvolnum>7</manvolnum> |
5671 |
++ </citerefentry> |
5672 |
++ </member> |
5673 |
++ <member> |
5674 |
++ <citerefentry> |
5675 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
5676 |
++ <manvolnum>7</manvolnum> |
5677 |
++ </citerefentry> |
5678 |
++ </member> |
5679 |
++ <member> |
5680 |
++ <citerefentry> |
5681 |
++ <refentrytitle>kdbus.item</refentrytitle> |
5682 |
++ <manvolnum>7</manvolnum> |
5683 |
++ </citerefentry> |
5684 |
++ </member> |
5685 |
++ <member> |
5686 |
++ <citerefentry> |
5687 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
5688 |
++ <manvolnum>7</manvolnum> |
5689 |
++ </citerefentry> |
5690 |
++ </member> |
5691 |
++ <member> |
5692 |
++ <citerefentry> |
5693 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
5694 |
++ <manvolnum>7</manvolnum> |
5695 |
++ </citerefentry> |
5696 |
++ </member> |
5697 |
++ </simplelist> |
5698 |
++ </refsect1> |
5699 |
++</refentry> |
5700 |
+diff --git a/Documentation/kdbus/kdbus.policy.xml b/Documentation/kdbus/kdbus.policy.xml |
5701 |
+new file mode 100644 |
5702 |
+index 0000000..6732416 |
5703 |
+--- /dev/null |
5704 |
++++ b/Documentation/kdbus/kdbus.policy.xml |
5705 |
+@@ -0,0 +1,406 @@ |
5706 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
5707 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
5708 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
5709 |
++ |
5710 |
++<refentry id="kdbus.policy"> |
5711 |
++ |
5712 |
++ <refentryinfo> |
5713 |
++ <title>kdbus.policy</title> |
5714 |
++ <productname>kdbus.policy</productname> |
5715 |
++ </refentryinfo> |
5716 |
++ |
5717 |
++ <refmeta> |
5718 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
5719 |
++ <manvolnum>7</manvolnum> |
5720 |
++ </refmeta> |
5721 |
++ |
5722 |
++ <refnamediv> |
5723 |
++ <refname>kdbus.policy</refname> |
5724 |
++ <refpurpose>kdbus policy</refpurpose> |
5725 |
++ </refnamediv> |
5726 |
++ |
5727 |
++ <refsect1> |
5728 |
++ <title>Description</title> |
5729 |
++ |
5730 |
++ <para> |
5731 |
++ A kdbus policy restricts the possibilities of connections to own, see and |
5732 |
++ talk to well-known names. A policy can be associated with a bus (through a |
5733 |
++ policy holder connection) or a custom endpoint. kdbus stores its policy |
5734 |
++ information in a database that can be accessed through the following |
5735 |
++ ioctl commands: |
5736 |
++ </para> |
5737 |
++ |
5738 |
++ <variablelist> |
5739 |
++ <varlistentry> |
5740 |
++ <term><constant>KDBUS_CMD_HELLO</constant></term> |
5741 |
++ <listitem><para> |
5742 |
++ When creating, or updating, a policy holder connection. See |
5743 |
++ <citerefentry> |
5744 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
5745 |
++ <manvolnum>7</manvolnum> |
5746 |
++ </citerefentry>. |
5747 |
++ </para></listitem> |
5748 |
++ </varlistentry> |
5749 |
++ |
5750 |
++ <varlistentry> |
5751 |
++ <term><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></term> |
5752 |
++ <term><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></term> |
5753 |
++ <listitem><para> |
5754 |
++ When creating, or updating, a bus custom endpoint. See |
5755 |
++ <citerefentry> |
5756 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
5757 |
++ <manvolnum>7</manvolnum> |
5758 |
++ </citerefentry>. |
5759 |
++ </para></listitem> |
5760 |
++ </varlistentry> |
5761 |
++ </variablelist> |
5762 |
++ |
5763 |
++ <para> |
5764 |
++ In all cases, the name and policy access information is stored in items |
5765 |
++ of type <constant>KDBUS_ITEM_NAME</constant> and |
5766 |
++ <constant>KDBUS_ITEM_POLICY_ACCESS</constant>. For this transport, the |
5767 |
++ following rules apply. |
5768 |
++ </para> |
5769 |
++ |
5770 |
++ <itemizedlist> |
5771 |
++ <listitem> |
5772 |
++ <para> |
5773 |
++ An item of type <constant>KDBUS_ITEM_NAME</constant> must be followed |
5774 |
++ by at least one <constant>KDBUS_ITEM_POLICY_ACCESS</constant> item. |
5775 |
++ </para> |
5776 |
++ </listitem> |
5777 |
++ |
5778 |
++ <listitem> |
5779 |
++ <para> |
5780 |
++ An item of type <constant>KDBUS_ITEM_NAME</constant> can be followed |
5781 |
++ by an arbitrary number of |
5782 |
++ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> items. |
5783 |
++ </para> |
5784 |
++ </listitem> |
5785 |
++ |
5786 |
++ <listitem> |
5787 |
++ <para> |
5788 |
++ An arbitrary number of groups of names and access levels can be given. |
5789 |
++ </para> |
5790 |
++ </listitem> |
5791 |
++ </itemizedlist> |
5792 |
++ |
5793 |
++ <para> |
5794 |
++ Names passed in items of type <constant>KDBUS_ITEM_NAME</constant> must |
5795 |
++ comply to the rules of valid kdbus.name. See |
5796 |
++ <citerefentry> |
5797 |
++ <refentrytitle>kdbus.name</refentrytitle> |
5798 |
++ <manvolnum>7</manvolnum> |
5799 |
++ </citerefentry> |
5800 |
++ for more information. |
5801 |
++ |
5802 |
++ The payload of an item of type |
5803 |
++ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> is defined by the following |
5804 |
++ struct. For more information on the layout of items, please refer to |
5805 |
++ <citerefentry> |
5806 |
++ <refentrytitle>kdbus.item</refentrytitle> |
5807 |
++ <manvolnum>7</manvolnum> |
5808 |
++ </citerefentry>. |
5809 |
++ </para> |
5810 |
++ |
5811 |
++ <programlisting> |
5812 |
++struct kdbus_policy_access { |
5813 |
++ __u64 type; |
5814 |
++ __u64 access; |
5815 |
++ __u64 id; |
5816 |
++}; |
5817 |
++ </programlisting> |
5818 |
++ |
5819 |
++ <para>The fields in this struct are described below.</para> |
5820 |
++ |
5821 |
++ <variablelist> |
5822 |
++ <varlistentry> |
5823 |
++ <term><varname>type</varname></term> |
5824 |
++ <listitem> |
5825 |
++ <para> |
5826 |
++ One of the following. |
5827 |
++ </para> |
5828 |
++ |
5829 |
++ <variablelist> |
5830 |
++ <varlistentry> |
5831 |
++ <term><constant>KDBUS_POLICY_ACCESS_USER</constant></term> |
5832 |
++ <listitem><para> |
5833 |
++ Grant access to a user with the UID stored in the |
5834 |
++ <varname>id</varname> field. |
5835 |
++ </para></listitem> |
5836 |
++ </varlistentry> |
5837 |
++ |
5838 |
++ <varlistentry> |
5839 |
++ <term><constant>KDBUS_POLICY_ACCESS_GROUP</constant></term> |
5840 |
++ <listitem><para> |
5841 |
++ Grant access to a user with the GID stored in the |
5842 |
++ <varname>id</varname> field. |
5843 |
++ </para></listitem> |
5844 |
++ </varlistentry> |
5845 |
++ |
5846 |
++ <varlistentry> |
5847 |
++ <term><constant>KDBUS_POLICY_ACCESS_WORLD</constant></term> |
5848 |
++ <listitem><para> |
5849 |
++ Grant access to everyone. The <varname>id</varname> field |
5850 |
++ is ignored. |
5851 |
++ </para></listitem> |
5852 |
++ </varlistentry> |
5853 |
++ </variablelist> |
5854 |
++ </listitem> |
5855 |
++ </varlistentry> |
5856 |
++ |
5857 |
++ <varlistentry> |
5858 |
++ <term><varname>access</varname></term> |
5859 |
++ <listitem> |
5860 |
++ <para> |
5861 |
++ The access to grant. One of the following. |
5862 |
++ </para> |
5863 |
++ |
5864 |
++ <variablelist> |
5865 |
++ <varlistentry> |
5866 |
++ <term><constant>KDBUS_POLICY_SEE</constant></term> |
5867 |
++ <listitem><para> |
5868 |
++ Allow the name to be seen. |
5869 |
++ </para></listitem> |
5870 |
++ </varlistentry> |
5871 |
++ |
5872 |
++ <varlistentry> |
5873 |
++ <term><constant>KDBUS_POLICY_TALK</constant></term> |
5874 |
++ <listitem><para> |
5875 |
++ Allow the name to be talked to. |
5876 |
++ </para></listitem> |
5877 |
++ </varlistentry> |
5878 |
++ |
5879 |
++ <varlistentry> |
5880 |
++ <term><constant>KDBUS_POLICY_OWN</constant></term> |
5881 |
++ <listitem><para> |
5882 |
++ Allow the name to be owned. |
5883 |
++ </para></listitem> |
5884 |
++ </varlistentry> |
5885 |
++ </variablelist> |
5886 |
++ </listitem> |
5887 |
++ </varlistentry> |
5888 |
++ |
5889 |
++ <varlistentry> |
5890 |
++ <term><varname>id</varname></term> |
5891 |
++ <listitem><para> |
5892 |
++ For <constant>KDBUS_POLICY_ACCESS_USER</constant>, stores the UID. |
5893 |
++ For <constant>KDBUS_POLICY_ACCESS_GROUP</constant>, stores the GID. |
5894 |
++ </para></listitem> |
5895 |
++ </varlistentry> |
5896 |
++ |
5897 |
++ </variablelist> |
5898 |
++ |
5899 |
++ <para> |
5900 |
++ All endpoints of buses have an empty policy database by default. |
5901 |
++ Therefore, unless policy rules are added, all operations will also be |
5902 |
++ denied by default. Also see |
5903 |
++ <citerefentry> |
5904 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
5905 |
++ <manvolnum>7</manvolnum> |
5906 |
++ </citerefentry>. |
5907 |
++ </para> |
5908 |
++ </refsect1> |
5909 |
++ |
5910 |
++ <refsect1> |
5911 |
++ <title>Wildcard names</title> |
5912 |
++ <para> |
5913 |
++ Policy holder connections may upload names that contain the wildcard |
5914 |
++ suffix (<literal>".*"</literal>). Such a policy entry is effective for |
5915 |
++ every well-known name that extends the provided name by exactly one more |
5916 |
++ level. |
5917 |
++ |
5918 |
++ For example, the name <literal>foo.bar.*</literal> matches both |
5919 |
++ <literal>"foo.bar.baz"</literal> and |
5920 |
++ <literal>"foo.bar.bazbaz"</literal> are, but not |
5921 |
++ <literal>"foo.bar.baz.baz"</literal>. |
5922 |
++ |
5923 |
++ This allows connections to take control over multiple names that the |
5924 |
++ policy holder doesn't need to know about when uploading the policy. |
5925 |
++ |
5926 |
++ Such wildcard entries are not allowed for custom endpoints. |
5927 |
++ </para> |
5928 |
++ </refsect1> |
5929 |
++ |
5930 |
++ <refsect1> |
5931 |
++ <title>Privileged connections</title> |
5932 |
++ <para> |
5933 |
++ The policy database is overruled when action is taken by a privileged |
5934 |
++ connection. Please refer to |
5935 |
++ <citerefentry> |
5936 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
5937 |
++ <manvolnum>7</manvolnum> |
5938 |
++ </citerefentry> |
5939 |
++ for more information on what makes a connection privileged. |
5940 |
++ </para> |
5941 |
++ </refsect1> |
5942 |
++ |
5943 |
++ <refsect1> |
5944 |
++ <title>Examples</title> |
5945 |
++ <para> |
5946 |
++ For instance, a set of policy rules may look like this: |
5947 |
++ </para> |
5948 |
++ |
5949 |
++ <programlisting> |
5950 |
++KDBUS_ITEM_NAME: str='org.foo.bar' |
5951 |
++KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=1000 |
5952 |
++KDBUS_ITEM_POLICY_ACCESS: type=USER, access=TALK, ID=1001 |
5953 |
++KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=SEE |
5954 |
++ |
5955 |
++KDBUS_ITEM_NAME: str='org.blah.baz' |
5956 |
++KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=0 |
5957 |
++KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=TALK |
5958 |
++ </programlisting> |
5959 |
++ |
5960 |
++ <para> |
5961 |
++ That means that 'org.foo.bar' may only be owned by UID 1000, but every |
5962 |
++ user on the bus is allowed to see the name. However, only UID 1001 may |
5963 |
++ actually send a message to the connection and receive a reply from it. |
5964 |
++ |
5965 |
++ The second rule allows 'org.blah.baz' to be owned by UID 0 only, but |
5966 |
++ every user may talk to it. |
5967 |
++ </para> |
5968 |
++ </refsect1> |
5969 |
++ |
5970 |
++ <refsect1> |
5971 |
++ <title>TALK access and multiple well-known names per connection</title> |
5972 |
++ <para> |
5973 |
++ Note that TALK access is checked against all names of a connection. For |
5974 |
++ example, if a connection owns both <constant>'org.foo.bar'</constant> and |
5975 |
++ <constant>'org.blah.baz'</constant>, and the policy database allows |
5976 |
++ <constant>'org.blah.baz'</constant> to be talked to by WORLD, then this |
5977 |
++ permission is also granted to <constant>'org.foo.bar'</constant>. That |
5978 |
++ might sound illogical, but after all, we allow messages to be directed to |
5979 |
++ either the ID or a well-known name, and policy is applied to the |
5980 |
++ connection, not the name. In other words, the effective TALK policy for a |
5981 |
++ connection is the most permissive of all names the connection owns. |
5982 |
++ |
5983 |
++ For broadcast messages, the receiver needs TALK permissions to the sender |
5984 |
++ to receive the broadcast. |
5985 |
++ </para> |
5986 |
++ <para> |
5987 |
++ Both the endpoint and the bus policy databases are consulted to allow |
5988 |
++ name registry listing, owning a well-known name and message delivery. |
5989 |
++ If either one fails, the operation is failed with |
5990 |
++ <varname>errno</varname> set to <constant>EPERM</constant>. |
5991 |
++ |
5992 |
++ For best practices, connections that own names with a restricted TALK |
5993 |
++ access should not install matches. This avoids cases where the sent |
5994 |
++ message may pass the bloom filter due to false-positives and may also |
5995 |
++ satisfy the policy rules. |
5996 |
++ |
5997 |
++ Also see |
5998 |
++ <citerefentry> |
5999 |
++ <refentrytitle>kdbus.match</refentrytitle> |
6000 |
++ <manvolnum>7</manvolnum> |
6001 |
++ </citerefentry>. |
6002 |
++ </para> |
6003 |
++ </refsect1> |
6004 |
++ |
6005 |
++ <refsect1> |
6006 |
++ <title>Implicit policies</title> |
6007 |
++ <para> |
6008 |
++ Depending on the type of the endpoint, a set of implicit rules that |
6009 |
++ override installed policies might be enforced. |
6010 |
++ |
6011 |
++ On default endpoints, the following set is enforced and checked before |
6012 |
++ any user-supplied policy is checked. |
6013 |
++ </para> |
6014 |
++ |
6015 |
++ <itemizedlist> |
6016 |
++ <listitem> |
6017 |
++ <para> |
6018 |
++ Privileged connections always override any installed policy. Those |
6019 |
++ connections could easily install their own policies, so there is no |
6020 |
++ reason to enforce installed policies. |
6021 |
++ </para> |
6022 |
++ </listitem> |
6023 |
++ <listitem> |
6024 |
++ <para> |
6025 |
++ Connections can always talk to connections of the same user. This |
6026 |
++ includes broadcast messages. |
6027 |
++ </para> |
6028 |
++ </listitem> |
6029 |
++ </itemizedlist> |
6030 |
++ |
6031 |
++ <para> |
6032 |
++ Custom endpoints have stricter policies. The following rules apply: |
6033 |
++ </para> |
6034 |
++ |
6035 |
++ <itemizedlist> |
6036 |
++ <listitem> |
6037 |
++ <para> |
6038 |
++ Policy rules are always enforced, even if the connection is a |
6039 |
++ privileged connection. |
6040 |
++ </para> |
6041 |
++ </listitem> |
6042 |
++ <listitem> |
6043 |
++ <para> |
6044 |
++ Policy rules are always enforced for <constant>TALK</constant> access, |
6045 |
++ even if both ends are running under the same user. This includes |
6046 |
++ broadcast messages. |
6047 |
++ </para> |
6048 |
++ </listitem> |
6049 |
++ <listitem> |
6050 |
++ <para> |
6051 |
++ To restrict the set of names that can be seen, endpoint policies can |
6052 |
++ install <constant>SEE</constant> policies. |
6053 |
++ </para> |
6054 |
++ </listitem> |
6055 |
++ </itemizedlist> |
6056 |
++ </refsect1> |
6057 |
++ |
6058 |
++ <refsect1> |
6059 |
++ <title>See Also</title> |
6060 |
++ <simplelist type="inline"> |
6061 |
++ <member> |
6062 |
++ <citerefentry> |
6063 |
++ <refentrytitle>kdbus</refentrytitle> |
6064 |
++ <manvolnum>7</manvolnum> |
6065 |
++ </citerefentry> |
6066 |
++ </member> |
6067 |
++ <member> |
6068 |
++ <citerefentry> |
6069 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
6070 |
++ <manvolnum>7</manvolnum> |
6071 |
++ </citerefentry> |
6072 |
++ </member> |
6073 |
++ <member> |
6074 |
++ <citerefentry> |
6075 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
6076 |
++ <manvolnum>7</manvolnum> |
6077 |
++ </citerefentry> |
6078 |
++ </member> |
6079 |
++ <member> |
6080 |
++ <citerefentry> |
6081 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
6082 |
++ <manvolnum>7</manvolnum> |
6083 |
++ </citerefentry> |
6084 |
++ </member> |
6085 |
++ <member> |
6086 |
++ <citerefentry> |
6087 |
++ <refentrytitle>kdbus.item</refentrytitle> |
6088 |
++ <manvolnum>7</manvolnum> |
6089 |
++ </citerefentry> |
6090 |
++ </member> |
6091 |
++ <member> |
6092 |
++ <citerefentry> |
6093 |
++ <refentrytitle>kdbus.message</refentrytitle> |
6094 |
++ <manvolnum>7</manvolnum> |
6095 |
++ </citerefentry> |
6096 |
++ </member> |
6097 |
++ <member> |
6098 |
++ <citerefentry> |
6099 |
++ <refentrytitle>kdbus.name</refentrytitle> |
6100 |
++ <manvolnum>7</manvolnum> |
6101 |
++ </citerefentry> |
6102 |
++ </member> |
6103 |
++ <member> |
6104 |
++ <citerefentry> |
6105 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
6106 |
++ <manvolnum>7</manvolnum> |
6107 |
++ </citerefentry> |
6108 |
++ </member> |
6109 |
++ </simplelist> |
6110 |
++ </refsect1> |
6111 |
++</refentry> |
6112 |
+diff --git a/Documentation/kdbus/kdbus.pool.xml b/Documentation/kdbus/kdbus.pool.xml |
6113 |
+new file mode 100644 |
6114 |
+index 0000000..a9e16f1 |
6115 |
+--- /dev/null |
6116 |
++++ b/Documentation/kdbus/kdbus.pool.xml |
6117 |
+@@ -0,0 +1,326 @@ |
6118 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
6119 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
6120 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
6121 |
++ |
6122 |
++<refentry id="kdbus.pool"> |
6123 |
++ |
6124 |
++ <refentryinfo> |
6125 |
++ <title>kdbus.pool</title> |
6126 |
++ <productname>kdbus.pool</productname> |
6127 |
++ </refentryinfo> |
6128 |
++ |
6129 |
++ <refmeta> |
6130 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
6131 |
++ <manvolnum>7</manvolnum> |
6132 |
++ </refmeta> |
6133 |
++ |
6134 |
++ <refnamediv> |
6135 |
++ <refname>kdbus.pool</refname> |
6136 |
++ <refpurpose>kdbus pool</refpurpose> |
6137 |
++ </refnamediv> |
6138 |
++ |
6139 |
++ <refsect1> |
6140 |
++ <title>Description</title> |
6141 |
++ <para> |
6142 |
++ A pool for data received from the kernel is installed for every |
6143 |
++ <emphasis>connection</emphasis> of the <emphasis>bus</emphasis>, and |
6144 |
++ is sized according to the information stored in the |
6145 |
++ <varname>pool_size</varname> member of <type>struct kdbus_cmd_hello</type> |
6146 |
++ when <constant>KDBUS_CMD_HELLO</constant> is employed. Internally, the |
6147 |
++ pool is segmented into <emphasis>slices</emphasis>, each referenced by its |
6148 |
++ <emphasis>offset</emphasis> in the pool, expressed in <type>bytes</type>. |
6149 |
++ See |
6150 |
++ <citerefentry> |
6151 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6152 |
++ <manvolnum>7</manvolnum> |
6153 |
++ </citerefentry> |
6154 |
++ for more information about <constant>KDBUS_CMD_HELLO</constant>. |
6155 |
++ </para> |
6156 |
++ |
6157 |
++ <para> |
6158 |
++ The pool is written to by the kernel when one of the following |
6159 |
++ <emphasis>ioctls</emphasis> is issued: |
6160 |
++ |
6161 |
++ <variablelist> |
6162 |
++ <varlistentry> |
6163 |
++ <term><constant>KDBUS_CMD_HELLO</constant></term> |
6164 |
++ <listitem><para> |
6165 |
++ ... to receive details about the bus the connection was made to |
6166 |
++ </para></listitem> |
6167 |
++ </varlistentry> |
6168 |
++ <varlistentry> |
6169 |
++ <term><constant>KDBUS_CMD_RECV</constant></term> |
6170 |
++ <listitem><para> |
6171 |
++ ... to receive a message |
6172 |
++ </para></listitem> |
6173 |
++ </varlistentry> |
6174 |
++ <varlistentry> |
6175 |
++ <term><constant>KDBUS_CMD_LIST</constant></term> |
6176 |
++ <listitem><para> |
6177 |
++ ... to dump the name registry |
6178 |
++ </para></listitem> |
6179 |
++ </varlistentry> |
6180 |
++ <varlistentry> |
6181 |
++ <term><constant>KDBUS_CMD_CONN_INFO</constant></term> |
6182 |
++ <listitem><para> |
6183 |
++ ... to retrieve information on a connection |
6184 |
++ </para></listitem> |
6185 |
++ </varlistentry> |
6186 |
++ <varlistentry> |
6187 |
++ <term><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></term> |
6188 |
++ <listitem><para> |
6189 |
++ ... to retrieve information about a connection's bus creator |
6190 |
++ </para></listitem> |
6191 |
++ </varlistentry> |
6192 |
++ </variablelist> |
6193 |
++ |
6194 |
++ </para> |
6195 |
++ <para> |
6196 |
++ The <varname>offset</varname> fields returned by either one of the |
6197 |
++ aforementioned ioctls describe offsets inside the pool. In order to make |
6198 |
++ the slice available for subsequent calls, |
6199 |
++ <constant>KDBUS_CMD_FREE</constant> has to be called on that offset |
6200 |
++ (see below). Otherwise, the pool will fill up, and the connection won't |
6201 |
++ be able to receive any more information through its pool. |
6202 |
++ </para> |
6203 |
++ </refsect1> |
6204 |
++ |
6205 |
++ <refsect1> |
6206 |
++ <title>Pool slice allocation</title> |
6207 |
++ <para> |
6208 |
++ Pool slices are allocated by the kernel in order to report information |
6209 |
++ back to a task, such as messages, returned name list etc. |
6210 |
++ Allocation of pool slices cannot be initiated by userspace. See |
6211 |
++ <citerefentry> |
6212 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6213 |
++ <manvolnum>7</manvolnum> |
6214 |
++ </citerefentry> |
6215 |
++ and |
6216 |
++ <citerefentry> |
6217 |
++ <refentrytitle>kdbus.name</refentrytitle> |
6218 |
++ <manvolnum>7</manvolnum> |
6219 |
++ </citerefentry> |
6220 |
++ for examples of commands that use the <emphasis>pool</emphasis> to |
6221 |
++ return data. |
6222 |
++ </para> |
6223 |
++ </refsect1> |
6224 |
++ |
6225 |
++ <refsect1> |
6226 |
++ <title>Accessing the pool memory</title> |
6227 |
++ <para> |
6228 |
++ Memory in the pool is read-only for userspace and may only be written |
6229 |
++ to by the kernel. To read from the pool memory, the caller is expected to |
6230 |
++ <citerefentry> |
6231 |
++ <refentrytitle>mmap</refentrytitle> |
6232 |
++ <manvolnum>2</manvolnum> |
6233 |
++ </citerefentry> |
6234 |
++ the buffer into its task, like this: |
6235 |
++ </para> |
6236 |
++ <programlisting> |
6237 |
++uint8_t *buf = mmap(NULL, size, PROT_READ, MAP_SHARED, conn_fd, 0); |
6238 |
++ </programlisting> |
6239 |
++ |
6240 |
++ <para> |
6241 |
++ In order to map the entire pool, the <varname>size</varname> parameter in |
6242 |
++ the example above should be set to the value of the |
6243 |
++ <varname>pool_size</varname> member of |
6244 |
++ <type>struct kdbus_cmd_hello</type> when |
6245 |
++ <constant>KDBUS_CMD_HELLO</constant> was employed to create the |
6246 |
++ connection (see above). |
6247 |
++ </para> |
6248 |
++ |
6249 |
++ <para> |
6250 |
++ The <emphasis>file descriptor</emphasis> used to map the memory must be |
6251 |
++ the one that was used to create the <emphasis>connection</emphasis>. |
6252 |
++ In other words, the one that was used to call |
6253 |
++ <constant>KDBUS_CMD_HELLO</constant>. See |
6254 |
++ <citerefentry> |
6255 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6256 |
++ <manvolnum>7</manvolnum> |
6257 |
++ </citerefentry> |
6258 |
++ for more details. |
6259 |
++ </para> |
6260 |
++ |
6261 |
++ <para> |
6262 |
++ Alternatively, instead of mapping the entire pool buffer, only parts |
6263 |
++ of it can be mapped. Every kdbus command that returns an |
6264 |
++ <emphasis>offset</emphasis> (see above) also reports a |
6265 |
++ <emphasis>size</emphasis> along with it, so programs can be written |
6266 |
++ in a way that it only maps portions of the pool to access a specific |
6267 |
++ <emphasis>slice</emphasis>. |
6268 |
++ </para> |
6269 |
++ |
6270 |
++ <para> |
6271 |
++ When access to the pool memory is no longer needed, programs should |
6272 |
++ call <function>munmap()</function> on the pointer returned by |
6273 |
++ <function>mmap()</function>. |
6274 |
++ </para> |
6275 |
++ </refsect1> |
6276 |
++ |
6277 |
++ <refsect1> |
6278 |
++ <title>Freeing pool slices</title> |
6279 |
++ <para> |
6280 |
++ The <constant>KDBUS_CMD_FREE</constant> ioctl is used to free a slice |
6281 |
++ inside the pool, describing an offset that was returned in an |
6282 |
++ <varname>offset</varname> field of another ioctl struct. |
6283 |
++ The <constant>KDBUS_CMD_FREE</constant> command takes a |
6284 |
++ <type>struct kdbus_cmd_free</type> as argument. |
6285 |
++ </para> |
6286 |
++ |
6287 |
++<programlisting> |
6288 |
++struct kdbus_cmd_free { |
6289 |
++ __u64 size; |
6290 |
++ __u64 flags; |
6291 |
++ __u64 return_flags; |
6292 |
++ __u64 offset; |
6293 |
++ struct kdbus_item items[0]; |
6294 |
++}; |
6295 |
++</programlisting> |
6296 |
++ |
6297 |
++ <para>The fields in this struct are described below.</para> |
6298 |
++ |
6299 |
++ <variablelist> |
6300 |
++ <varlistentry> |
6301 |
++ <term><varname>size</varname></term> |
6302 |
++ <listitem><para> |
6303 |
++ The overall size of the struct, including its items. |
6304 |
++ </para></listitem> |
6305 |
++ </varlistentry> |
6306 |
++ |
6307 |
++ <varlistentry> |
6308 |
++ <term><varname>flags</varname></term> |
6309 |
++ <listitem><para> |
6310 |
++ Currently unused. |
6311 |
++ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
6312 |
++ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
6313 |
++ and the <varname>flags</varname> field is set to |
6314 |
++ <constant>0</constant>. |
6315 |
++ </para></listitem> |
6316 |
++ </varlistentry> |
6317 |
++ |
6318 |
++ <varlistentry> |
6319 |
++ <term><varname>return_flags</varname></term> |
6320 |
++ <listitem><para> |
6321 |
++ Flags returned by the kernel. Currently unused and always set to |
6322 |
++ <constant>0</constant> by the kernel. |
6323 |
++ </para></listitem> |
6324 |
++ </varlistentry> |
6325 |
++ |
6326 |
++ <varlistentry> |
6327 |
++ <term><varname>offset</varname></term> |
6328 |
++ <listitem><para> |
6329 |
++ The offset to free, as returned by other ioctls that allocated |
6330 |
++ memory for returned information. |
6331 |
++ </para></listitem> |
6332 |
++ </varlistentry> |
6333 |
++ |
6334 |
++ <varlistentry> |
6335 |
++ <term><varname>items</varname></term> |
6336 |
++ <listitem><para> |
6337 |
++ Items to specify further details for the receive command. |
6338 |
++ Currently unused. |
6339 |
++ Unrecognized items are rejected, and the ioctl will fail with |
6340 |
++ <varname>errno</varname> set to <constant>EINVAL</constant>. |
6341 |
++ All items except for |
6342 |
++ <constant>KDBUS_ITEM_NEGOTIATE</constant> (see |
6343 |
++ <citerefentry> |
6344 |
++ <refentrytitle>kdbus.item</refentrytitle> |
6345 |
++ <manvolnum>7</manvolnum> |
6346 |
++ </citerefentry> |
6347 |
++ ) will be rejected. |
6348 |
++ </para></listitem> |
6349 |
++ </varlistentry> |
6350 |
++ </variablelist> |
6351 |
++ </refsect1> |
6352 |
++ |
6353 |
++ <refsect1> |
6354 |
++ <title>Return value</title> |
6355 |
++ <para> |
6356 |
++ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
6357 |
++ on error, <errorcode>-1</errorcode> is returned, and |
6358 |
++ <varname>errno</varname> is set to indicate the error. |
6359 |
++ If the issued ioctl is illegal for the file descriptor used, |
6360 |
++ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
6361 |
++ </para> |
6362 |
++ |
6363 |
++ <refsect2> |
6364 |
++ <title> |
6365 |
++ <constant>KDBUS_CMD_FREE</constant> may fail with the following |
6366 |
++ errors |
6367 |
++ </title> |
6368 |
++ |
6369 |
++ <variablelist> |
6370 |
++ <varlistentry> |
6371 |
++ <term><constant>ENXIO</constant></term> |
6372 |
++ <listitem><para> |
6373 |
++ No pool slice found at given offset. |
6374 |
++ </para></listitem> |
6375 |
++ </varlistentry> |
6376 |
++ |
6377 |
++ <varlistentry> |
6378 |
++ <term><constant>EINVAL</constant></term> |
6379 |
++ <listitem><para> |
6380 |
++ Invalid flags provided. |
6381 |
++ </para></listitem> |
6382 |
++ </varlistentry> |
6383 |
++ |
6384 |
++ <varlistentry> |
6385 |
++ <term><constant>EINVAL</constant></term> |
6386 |
++ <listitem><para> |
6387 |
++ The offset is valid, but the user is not allowed to free the slice. |
6388 |
++ This happens, for example, if the offset was retrieved with |
6389 |
++ <constant>KDBUS_RECV_PEEK</constant>. |
6390 |
++ </para></listitem> |
6391 |
++ </varlistentry> |
6392 |
++ </variablelist> |
6393 |
++ </refsect2> |
6394 |
++ </refsect1> |
6395 |
++ |
6396 |
++ <refsect1> |
6397 |
++ <title>See Also</title> |
6398 |
++ <simplelist type="inline"> |
6399 |
++ <member> |
6400 |
++ <citerefentry> |
6401 |
++ <refentrytitle>kdbus</refentrytitle> |
6402 |
++ <manvolnum>7</manvolnum> |
6403 |
++ </citerefentry> |
6404 |
++ </member> |
6405 |
++ <member> |
6406 |
++ <citerefentry> |
6407 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
6408 |
++ <manvolnum>7</manvolnum> |
6409 |
++ </citerefentry> |
6410 |
++ </member> |
6411 |
++ <member> |
6412 |
++ <citerefentry> |
6413 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6414 |
++ <manvolnum>7</manvolnum> |
6415 |
++ </citerefentry> |
6416 |
++ </member> |
6417 |
++ <member> |
6418 |
++ <citerefentry> |
6419 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
6420 |
++ <manvolnum>7</manvolnum> |
6421 |
++ </citerefentry> |
6422 |
++ </member> |
6423 |
++ <member> |
6424 |
++ <citerefentry> |
6425 |
++ <refentrytitle>kdbus.name</refentrytitle> |
6426 |
++ <manvolnum>7</manvolnum> |
6427 |
++ </citerefentry> |
6428 |
++ </member> |
6429 |
++ <member> |
6430 |
++ <citerefentry> |
6431 |
++ <refentrytitle>mmap</refentrytitle> |
6432 |
++ <manvolnum>2</manvolnum> |
6433 |
++ </citerefentry> |
6434 |
++ </member> |
6435 |
++ <member> |
6436 |
++ <citerefentry> |
6437 |
++ <refentrytitle>munmap</refentrytitle> |
6438 |
++ <manvolnum>2</manvolnum> |
6439 |
++ </citerefentry> |
6440 |
++ </member> |
6441 |
++ </simplelist> |
6442 |
++ </refsect1> |
6443 |
++</refentry> |
6444 |
+diff --git a/Documentation/kdbus/kdbus.xml b/Documentation/kdbus/kdbus.xml |
6445 |
+new file mode 100644 |
6446 |
+index 0000000..d8e7400 |
6447 |
+--- /dev/null |
6448 |
++++ b/Documentation/kdbus/kdbus.xml |
6449 |
+@@ -0,0 +1,1012 @@ |
6450 |
++<?xml version='1.0'?> <!--*-nxml-*--> |
6451 |
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
6452 |
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
6453 |
++ |
6454 |
++<refentry id="kdbus"> |
6455 |
++ |
6456 |
++ <refentryinfo> |
6457 |
++ <title>kdbus</title> |
6458 |
++ <productname>kdbus</productname> |
6459 |
++ </refentryinfo> |
6460 |
++ |
6461 |
++ <refmeta> |
6462 |
++ <refentrytitle>kdbus</refentrytitle> |
6463 |
++ <manvolnum>7</manvolnum> |
6464 |
++ </refmeta> |
6465 |
++ |
6466 |
++ <refnamediv> |
6467 |
++ <refname>kdbus</refname> |
6468 |
++ <refpurpose>Kernel Message Bus</refpurpose> |
6469 |
++ </refnamediv> |
6470 |
++ |
6471 |
++ <refsect1> |
6472 |
++ <title>Synopsis</title> |
6473 |
++ <para> |
6474 |
++ kdbus is an inter-process communication bus system controlled by the |
6475 |
++ kernel. It provides user-space with an API to create buses and send |
6476 |
++ unicast and multicast messages to one, or many, peers connected to the |
6477 |
++ same bus. It does not enforce any layout on the transmitted data, but |
6478 |
++ only provides the transport layer used for message interchange between |
6479 |
++ peers. |
6480 |
++ </para> |
6481 |
++ <para> |
6482 |
++ This set of man-pages gives a comprehensive overview of the kernel-level |
6483 |
++ API, with all ioctl commands, associated structs and bit masks. However, |
6484 |
++ most people will not use this API level directly, but rather let one of |
6485 |
++ the high-level abstraction libraries help them integrate D-Bus |
6486 |
++ functionality into their applications. |
6487 |
++ </para> |
6488 |
++ </refsect1> |
6489 |
++ |
6490 |
++ <refsect1> |
6491 |
++ <title>Description</title> |
6492 |
++ <para> |
6493 |
++ kdbus provides a pseudo filesystem called <emphasis>kdbusfs</emphasis>, |
6494 |
++ which is usually mounted on <filename>/sys/fs/kdbus</filename>. Bus |
6495 |
++ primitives can be accessed as files and sub-directories underneath this |
6496 |
++ mount-point. Any advanced operations are done via |
6497 |
++ <function>ioctl()</function> on files created by |
6498 |
++ <emphasis>kdbusfs</emphasis>. Multiple mount-points of |
6499 |
++ <emphasis>kdbusfs</emphasis> are independent of each other. This allows |
6500 |
++ namespacing of kdbus by mounting a new instance of |
6501 |
++ <emphasis>kdbusfs</emphasis> in a new mount-namespace. kdbus calls these |
6502 |
++ mount instances domains and each bus belongs to exactly one domain. |
6503 |
++ </para> |
6504 |
++ |
6505 |
++ <para> |
6506 |
++ kdbus was designed as a transport layer for D-Bus, but is in no way |
6507 |
++ limited, nor controlled by the D-Bus protocol specification. The D-Bus |
6508 |
++ protocol is one possible application layer on top of kdbus. |
6509 |
++ </para> |
6510 |
++ |
6511 |
++ <para> |
6512 |
++ For the general D-Bus protocol specification, its payload format, its |
6513 |
++ marshaling, and its communication semantics, please refer to the |
6514 |
++ <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html"> |
6515 |
++ D-Bus specification</ulink>. |
6516 |
++ </para> |
6517 |
++ |
6518 |
++ </refsect1> |
6519 |
++ |
6520 |
++ <refsect1> |
6521 |
++ <title>Terminology</title> |
6522 |
++ |
6523 |
++ <refsect2> |
6524 |
++ <title>Domain</title> |
6525 |
++ <para> |
6526 |
++ A domain is a <emphasis>kdbusfs</emphasis> mount-point containing all |
6527 |
++ the bus primitives. Each domain is independent, and separate domains |
6528 |
++ do not affect each other. |
6529 |
++ </para> |
6530 |
++ </refsect2> |
6531 |
++ |
6532 |
++ <refsect2> |
6533 |
++ <title>Bus</title> |
6534 |
++ <para> |
6535 |
++ A bus is a named object inside a domain. Clients exchange messages |
6536 |
++ over a bus. Multiple buses themselves have no connection to each other; |
6537 |
++ messages can only be exchanged on the same bus. The default endpoint of |
6538 |
++ a bus, to which clients establish connections, is the "bus" file |
6539 |
++ /sys/fs/kdbus/<bus name>/bus. |
6540 |
++ Common operating system setups create one "system bus" per system, |
6541 |
++ and one "user bus" for every logged-in user. Applications or services |
6542 |
++ may create their own private buses. The kernel driver does not |
6543 |
++ distinguish between different bus types, they are all handled the same |
6544 |
++ way. See |
6545 |
++ <citerefentry> |
6546 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
6547 |
++ <manvolnum>7</manvolnum> |
6548 |
++ </citerefentry> |
6549 |
++ for more details. |
6550 |
++ </para> |
6551 |
++ </refsect2> |
6552 |
++ |
6553 |
++ <refsect2> |
6554 |
++ <title>Endpoint</title> |
6555 |
++ <para> |
6556 |
++ An endpoint provides a file to talk to a bus. Opening an endpoint |
6557 |
++ creates a new connection to the bus to which the endpoint belongs. All |
6558 |
++ endpoints have unique names and are accessible as files underneath the |
6559 |
++ directory of a bus, e.g., /sys/fs/kdbus/<bus>/<endpoint> |
6560 |
++ Every bus has a default endpoint called "bus". |
6561 |
++ A bus can optionally offer additional endpoints with custom names |
6562 |
++ to provide restricted access to the bus. Custom endpoints carry |
6563 |
++ additional policy which can be used to create sandboxes with |
6564 |
++ locked-down, limited, filtered access to a bus. See |
6565 |
++ <citerefentry> |
6566 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
6567 |
++ <manvolnum>7</manvolnum> |
6568 |
++ </citerefentry> |
6569 |
++ for more details. |
6570 |
++ </para> |
6571 |
++ </refsect2> |
6572 |
++ |
6573 |
++ <refsect2> |
6574 |
++ <title>Connection</title> |
6575 |
++ <para> |
6576 |
++ A connection to a bus is created by opening an endpoint file of a |
6577 |
++ bus. Every ordinary client connection has a unique identifier on the |
6578 |
++ bus and can address messages to every other connection on the same |
6579 |
++ bus by using the peer's connection ID as the destination. See |
6580 |
++ <citerefentry> |
6581 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6582 |
++ <manvolnum>7</manvolnum> |
6583 |
++ </citerefentry> |
6584 |
++ for more details. |
6585 |
++ </para> |
6586 |
++ </refsect2> |
6587 |
++ |
6588 |
++ <refsect2> |
6589 |
++ <title>Pool</title> |
6590 |
++ <para> |
6591 |
++ Each connection allocates a piece of shmem-backed memory that is |
6592 |
++ used to receive messages and answers to ioctl commands from the kernel. |
6593 |
++ It is never used to send anything to the kernel. In order to access that |
6594 |
++ memory, an application must mmap() it into its address space. See |
6595 |
++ <citerefentry> |
6596 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
6597 |
++ <manvolnum>7</manvolnum> |
6598 |
++ </citerefentry> |
6599 |
++ for more details. |
6600 |
++ </para> |
6601 |
++ </refsect2> |
6602 |
++ |
6603 |
++ <refsect2> |
6604 |
++ <title>Well-known Name</title> |
6605 |
++ <para> |
6606 |
++ A connection can, in addition to its implicit unique connection ID, |
6607 |
++ request the ownership of a textual well-known name. Well-known names are |
6608 |
++ noted in reverse-domain notation, such as com.example.service1. A |
6609 |
++ connection that offers a service on a bus is usually reached by its |
6610 |
++ well-known name. An analogy of connection ID and well-known name is an |
6611 |
++ IP address and a DNS name associated with that address. See |
6612 |
++ <citerefentry> |
6613 |
++ <refentrytitle>kdbus.name</refentrytitle> |
6614 |
++ <manvolnum>7</manvolnum> |
6615 |
++ </citerefentry> |
6616 |
++ for more details. |
6617 |
++ </para> |
6618 |
++ </refsect2> |
6619 |
++ |
6620 |
++ <refsect2> |
6621 |
++ <title>Message</title> |
6622 |
++ <para> |
6623 |
++ Connections can exchange messages with other connections by addressing |
6624 |
++ the peers with their connection ID or well-known name. A message |
6625 |
++ consists of a message header with information on how to route the |
6626 |
++ message, and the message payload, which is a logical byte stream of |
6627 |
++ arbitrary size. Messages can carry additional file descriptors to be |
6628 |
++ passed from one connection to another, just like passing file |
6629 |
++ descriptors over UNIX domain sockets. Every connection can specify which |
6630 |
++ set of metadata the kernel should attach to the message when it is |
6631 |
++ delivered to the receiving connection. Metadata contains information |
6632 |
++ like: system time stamps, UID, GID, TID, proc-starttime, well-known |
6633 |
++ names, process comm, process exe, process argv, cgroup, capabilities, |
6634 |
++ seclabel, audit session, loginuid and the connection's human-readable |
6635 |
++ name. See |
6636 |
++ <citerefentry> |
6637 |
++ <refentrytitle>kdbus.message</refentrytitle> |
6638 |
++ <manvolnum>7</manvolnum> |
6639 |
++ </citerefentry> |
6640 |
++ for more details. |
6641 |
++ </para> |
6642 |
++ </refsect2> |
6643 |
++ |
6644 |
++ <refsect2> |
6645 |
++ <title>Item</title> |
6646 |
++ <para> |
6647 |
++ The API of kdbus implements the notion of items, submitted through and |
6648 |
++ returned by most ioctls, and stored inside data structures in the |
6649 |
++ connection's pool. See |
6650 |
++ <citerefentry> |
6651 |
++ <refentrytitle>kdbus.item</refentrytitle> |
6652 |
++ <manvolnum>7</manvolnum> |
6653 |
++ </citerefentry> |
6654 |
++ for more details. |
6655 |
++ </para> |
6656 |
++ </refsect2> |
6657 |
++ |
6658 |
++ <refsect2> |
6659 |
++ <title>Broadcast, signal, filter, match</title> |
6660 |
++ <para> |
6661 |
++ Signals are messages that a receiver opts in for by installing a blob of |
6662 |
++ bytes, called a 'match'. Signal messages must always carry a |
6663 |
++ counter-part blob, called a 'filter', and signals are only delivered to |
6664 |
++ peers which have a match that white-lists the message's filter. Senders |
6665 |
++ of signal messages can use either a single connection ID as receiver, |
6666 |
++ or the special connection ID |
6667 |
++ <constant>KDBUS_DST_ID_BROADCAST</constant> to potentially send it to |
6668 |
++ all connections of a bus, following the logic described above. See |
6669 |
++ <citerefentry> |
6670 |
++ <refentrytitle>kdbus.match</refentrytitle> |
6671 |
++ <manvolnum>7</manvolnum> |
6672 |
++ </citerefentry> |
6673 |
++ and |
6674 |
++ <citerefentry> |
6675 |
++ <refentrytitle>kdbus.message</refentrytitle> |
6676 |
++ <manvolnum>7</manvolnum> |
6677 |
++ </citerefentry> |
6678 |
++ for more details. |
6679 |
++ </para> |
6680 |
++ </refsect2> |
6681 |
++ |
6682 |
++ <refsect2> |
6683 |
++ <title>Policy</title> |
6684 |
++ <para> |
6685 |
++ A policy is a set of rules that define which connections can see, talk |
6686 |
++ to, or register a well-known name on the bus. A policy is attached to |
6687 |
++ buses and custom endpoints, and modified by policy holder connections or |
6688 |
++ owners of custom endpoints. See |
6689 |
++ <citerefentry> |
6690 |
++ <refentrytitle>kdbus.policy</refentrytitle> |
6691 |
++ <manvolnum>7</manvolnum> |
6692 |
++ </citerefentry> |
6693 |
++ for more details. |
6694 |
++ </para> |
6695 |
++ </refsect2> |
6696 |
++ |
6697 |
++ <refsect2> |
6698 |
++ <title>Privileged bus users</title> |
6699 |
++ <para> |
6700 |
++ A user connecting to the bus is considered privileged if it is either |
6701 |
++ the creator of the bus, or if it has the CAP_IPC_OWNER capability flag |
6702 |
++ set. See |
6703 |
++ <citerefentry> |
6704 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6705 |
++ <manvolnum>7</manvolnum> |
6706 |
++ </citerefentry> |
6707 |
++ for more details. |
6708 |
++ </para> |
6709 |
++ </refsect2> |
6710 |
++ </refsect1> |
6711 |
++ |
6712 |
++ <refsect1> |
6713 |
++ <title>Bus Layout</title> |
6714 |
++ |
6715 |
++ <para> |
6716 |
++ A <emphasis>bus</emphasis> provides and defines an environment that peers |
6717 |
++ can connect to for message interchange. A bus is created via the kdbus |
6718 |
++ control interface and can be modified by the bus creator. It applies the |
6719 |
++ policy that control all bus operations. The bus creator itself does not |
6720 |
++ participate as a peer. To establish a peer |
6721 |
++ <emphasis>connection</emphasis>, you have to open one of the |
6722 |
++ <emphasis>endpoints</emphasis> of a bus. Each bus provides a default |
6723 |
++ endpoint, but further endpoints can be created on-demand. Endpoints are |
6724 |
++ used to apply additional policies for all connections on this endpoint. |
6725 |
++ Thus, they provide additional filters to further restrict access of |
6726 |
++ specific connections to the bus. |
6727 |
++ </para> |
6728 |
++ |
6729 |
++ <para> |
6730 |
++ Following, you can see an example bus layout: |
6731 |
++ </para> |
6732 |
++ |
6733 |
++ <programlisting><![CDATA[ |
6734 |
++ Bus Creator |
6735 |
++ | |
6736 |
++ | |
6737 |
++ +-----+ |
6738 |
++ | Bus | |
6739 |
++ +-----+ |
6740 |
++ | |
6741 |
++ __________________/ \__________________ |
6742 |
++ / \ |
6743 |
++ | | |
6744 |
++ +----------+ +----------+ |
6745 |
++ | Endpoint | | Endpoint | |
6746 |
++ +----------+ +----------+ |
6747 |
++ _________/|\_________ _________/|\_________ |
6748 |
++ / | \ / | \ |
6749 |
++ | | | | | | |
6750 |
++ | | | | | | |
6751 |
++ Connection Connection Connection Connection Connection Connection |
6752 |
++ ]]></programlisting> |
6753 |
++ |
6754 |
++ </refsect1> |
6755 |
++ |
6756 |
++ <refsect1> |
6757 |
++ <title>Data structures and interconnections</title> |
6758 |
++ <programlisting><![CDATA[ |
6759 |
++ +--------------------------------------------------------------------------+ |
6760 |
++ | Domain (Mount Point) | |
6761 |
++ | /sys/fs/kdbus/control | |
6762 |
++ | +----------------------------------------------------------------------+ | |
6763 |
++ | | Bus (System Bus) | | |
6764 |
++ | | /sys/fs/kdbus/0-system/ | | |
6765 |
++ | | +-------------------------------+ +--------------------------------+ | | |
6766 |
++ | | | Endpoint | | Endpoint | | | |
6767 |
++ | | | /sys/fs/kdbus/0-system/bus | | /sys/fs/kdbus/0-system/ep.app | | | |
6768 |
++ | | +-------------------------------+ +--------------------------------+ | | |
6769 |
++ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6770 |
++ | | | Connection | | Connection | | Connection | | Connection | | | |
6771 |
++ | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | | |
6772 |
++ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6773 |
++ | +----------------------------------------------------------------------+ | |
6774 |
++ | | |
6775 |
++ | +----------------------------------------------------------------------+ | |
6776 |
++ | | Bus (User Bus for UID 2702) | | |
6777 |
++ | | /sys/fs/kdbus/2702-user/ | | |
6778 |
++ | | +-------------------------------+ +--------------------------------+ | | |
6779 |
++ | | | Endpoint | | Endpoint | | | |
6780 |
++ | | | /sys/fs/kdbus/2702-user/bus | | /sys/fs/kdbus/2702-user/ep.app | | | |
6781 |
++ | | +-------------------------------+ +--------------------------------+ | | |
6782 |
++ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6783 |
++ | | | Connection | | Connection | | Connection | | Connection | | | |
6784 |
++ | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | | |
6785 |
++ | | +--------------+ +--------------+ +--------------------------------+ | | |
6786 |
++ | +----------------------------------------------------------------------+ | |
6787 |
++ +--------------------------------------------------------------------------+ |
6788 |
++ ]]></programlisting> |
6789 |
++ </refsect1> |
6790 |
++ |
6791 |
++ <refsect1> |
6792 |
++ <title>Metadata</title> |
6793 |
++ |
6794 |
++ <refsect2> |
6795 |
++ <title>When metadata is collected</title> |
6796 |
++ <para> |
6797 |
++ kdbus records data about the system in certain situations. Such metadata |
6798 |
++ can refer to the currently active process (creds, PIDs, current user |
6799 |
++ groups, process names and its executable path, cgroup membership, |
6800 |
++ capabilities, security label and audit information), connection |
6801 |
++ information (description string, currently owned names) and time stamps. |
6802 |
++ </para> |
6803 |
++ <para> |
6804 |
++ Metadata is collected at the following times. |
6805 |
++ </para> |
6806 |
++ |
6807 |
++ <itemizedlist> |
6808 |
++ <listitem><para> |
6809 |
++ When a bus is created (<constant>KDBUS_CMD_MAKE</constant>), |
6810 |
++ information about the calling task is collected. This data is returned |
6811 |
++ by the kernel via the <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> |
6812 |
++ call. |
6813 |
++ </para></listitem> |
6814 |
++ |
6815 |
++ <listitem> |
6816 |
++ <para> |
6817 |
++ When a connection is created (<constant>KDBUS_CMD_HELLO</constant>), |
6818 |
++ information about the calling task is collected. Alternatively, a |
6819 |
++ privileged connection may provide 'faked' information about |
6820 |
++ credentials, PIDs and security labels which will be stored instead. |
6821 |
++ This data is returned by the kernel as information on a connection |
6822 |
++ (<constant>KDBUS_CMD_CONN_INFO</constant>). Only metadata that a |
6823 |
++ connection allowed to be sent (by setting its bit in |
6824 |
++ <varname>attach_flags_send</varname>) will be exported in this way. |
6825 |
++ </para> |
6826 |
++ </listitem> |
6827 |
++ |
6828 |
++ <listitem> |
6829 |
++ <para> |
6830 |
++ When a message is sent (<constant>KDBUS_CMD_SEND</constant>), |
6831 |
++ information about the sending task and the sending connection is |
6832 |
++ collected. This metadata will be attached to the message when it |
6833 |
++ arrives in the receiver's pool. If the connection sending the |
6834 |
++ message installed faked credentials (see |
6835 |
++ <citerefentry> |
6836 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
6837 |
++ <manvolnum>7</manvolnum> |
6838 |
++ </citerefentry>), |
6839 |
++ the message will not be augmented by any information about the |
6840 |
++ currently sending task. Note that only metadata that was requested |
6841 |
++ by the receiving connection will be collected and attached to |
6842 |
++ messages. |
6843 |
++ </para> |
6844 |
++ </listitem> |
6845 |
++ </itemizedlist> |
6846 |
++ |
6847 |
++ <para> |
6848 |
++ Which metadata items are actually delivered depends on the following |
6849 |
++ sets and masks: |
6850 |
++ </para> |
6851 |
++ |
6852 |
++ <itemizedlist> |
6853 |
++ <listitem><para> |
6854 |
++ (a) the system-wide kmod creds mask |
6855 |
++ (module parameter <varname>attach_flags_mask</varname>) |
6856 |
++ </para></listitem> |
6857 |
++ |
6858 |
++ <listitem><para> |
6859 |
++ (b) the per-connection send creds mask, set by the connecting client |
6860 |
++ </para></listitem> |
6861 |
++ |
6862 |
++ <listitem><para> |
6863 |
++ (c) the per-connection receive creds mask, set by the connecting |
6864 |
++ client |
6865 |
++ </para></listitem> |
6866 |
++ |
6867 |
++ <listitem><para> |
6868 |
++ (d) the per-bus minimal creds mask, set by the bus creator |
6869 |
++ </para></listitem> |
6870 |
++ |
6871 |
++ <listitem><para> |
6872 |
++ (e) the per-bus owner creds mask, set by the bus creator |
6873 |
++ </para></listitem> |
6874 |
++ |
6875 |
++ <listitem><para> |
6876 |
++ (f) the mask specified when querying creds of a bus peer |
6877 |
++ </para></listitem> |
6878 |
++ |
6879 |
++ <listitem><para> |
6880 |
++ (g) the mask specified when querying creds of a bus owner |
6881 |
++ </para></listitem> |
6882 |
++ </itemizedlist> |
6883 |
++ |
6884 |
++ <para> |
6885 |
++ With the following rules: |
6886 |
++ </para> |
6887 |
++ |
6888 |
++ <itemizedlist> |
6889 |
++ <listitem> |
6890 |
++ <para> |
6891 |
++ [1] The creds attached to messages are determined as |
6892 |
++ <constant>a & b & c</constant>. |
6893 |
++ </para> |
6894 |
++ </listitem> |
6895 |
++ |
6896 |
++ <listitem> |
6897 |
++ <para> |
6898 |
++ [2] When connecting to a bus (<constant>KDBUS_CMD_HELLO</constant>), |
6899 |
++ and <constant>~b & d != 0</constant>, the call will fail with, |
6900 |
++ <errorcode>-1</errorcode>, and <varname>errno</varname> is set to |
6901 |
++ <constant>ECONNREFUSED</constant>. |
6902 |
++ </para> |
6903 |
++ </listitem> |
6904 |
++ |
6905 |
++ <listitem> |
6906 |
++ <para> |
6907 |
++ [3] When querying creds of a bus peer, the creds returned are |
6908 |
++ <constant>a & b & f</constant>. |
6909 |
++ </para> |
6910 |
++ </listitem> |
6911 |
++ |
6912 |
++ <listitem> |
6913 |
++ <para> |
6914 |
++ [4] When querying creds of a bus owner, the creds returned are |
6915 |
++ <constant>a & e & g</constant>. |
6916 |
++ </para> |
6917 |
++ </listitem> |
6918 |
++ </itemizedlist> |
6919 |
++ |
6920 |
++ <para> |
6921 |
++ Hence, programs might not always get all requested metadata items that |
6922 |
++ it requested. Code must be written so that it can cope with this fact. |
6923 |
++ </para> |
6924 |
++ </refsect2> |
6925 |
++ |
6926 |
++ <refsect2> |
6927 |
++ <title>Benefits and heads-up</title> |
6928 |
++ <para> |
6929 |
++ Attaching metadata to messages has two major benefits. |
6930 |
++ |
6931 |
++ <itemizedlist> |
6932 |
++ <listitem> |
6933 |
++ <para> |
6934 |
++ Metadata attached to messages is gathered at the moment when the |
6935 |
++ other side calls <constant>KDBUS_CMD_SEND</constant>, or, |
6936 |
++ respectively, then the kernel notification is generated. There is |
6937 |
++ no need for the receiving peer to retrieve information about the |
6938 |
++ task in a second step. This closes a race gap that would otherwise |
6939 |
++ be inherent. |
6940 |
++ </para> |
6941 |
++ </listitem> |
6942 |
++ <listitem> |
6943 |
++ <para> |
6944 |
++ As metadata is delivered along with messages in the same data |
6945 |
++ blob, no extra calls to kernel functions etc. are needed to gather |
6946 |
++ them. |
6947 |
++ </para> |
6948 |
++ </listitem> |
6949 |
++ </itemizedlist> |
6950 |
++ |
6951 |
++ Note, however, that collecting metadata does come at a price for |
6952 |
++ performance, so developers should carefully assess which metadata to |
6953 |
++ really opt-in for. For best practice, data that is not needed as part |
6954 |
++ of a message should not be requested by the connection in the first |
6955 |
++ place (see <varname>attach_flags_recv</varname> in |
6956 |
++ <constant>KDBUS_CMD_HELLO</constant>). |
6957 |
++ </para> |
6958 |
++ </refsect2> |
6959 |
++ |
6960 |
++ <refsect2> |
6961 |
++ <title>Attach flags for metadata items</title> |
6962 |
++ <para> |
6963 |
++ To let the kernel know which metadata information to attach as items |
6964 |
++ to the aforementioned commands, it uses a bitmask. In those, the |
6965 |
++ following <emphasis>attach flags</emphasis> are currently supported. |
6966 |
++ Both the <varname>attach_flags_recv</varname> and |
6967 |
++ <varname>attach_flags_send</varname> fields of |
6968 |
++ <type>struct kdbus_cmd_hello</type>, as well as the payload of the |
6969 |
++ <constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant> and |
6970 |
++ <constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant> items follow this |
6971 |
++ scheme. |
6972 |
++ </para> |
6973 |
++ |
6974 |
++ <variablelist> |
6975 |
++ <varlistentry> |
6976 |
++ <term><constant>KDBUS_ATTACH_TIMESTAMP</constant></term> |
6977 |
++ <listitem><para> |
6978 |
++ Requests the attachment of an item of type |
6979 |
++ <constant>KDBUS_ITEM_TIMESTAMP</constant>. |
6980 |
++ </para></listitem> |
6981 |
++ </varlistentry> |
6982 |
++ |
6983 |
++ <varlistentry> |
6984 |
++ <term><constant>KDBUS_ATTACH_CREDS</constant></term> |
6985 |
++ <listitem><para> |
6986 |
++ Requests the attachment of an item of type |
6987 |
++ <constant>KDBUS_ITEM_CREDS</constant>. |
6988 |
++ </para></listitem> |
6989 |
++ </varlistentry> |
6990 |
++ |
6991 |
++ <varlistentry> |
6992 |
++ <term><constant>KDBUS_ATTACH_PIDS</constant></term> |
6993 |
++ <listitem><para> |
6994 |
++ Requests the attachment of an item of type |
6995 |
++ <constant>KDBUS_ITEM_PIDS</constant>. |
6996 |
++ </para></listitem> |
6997 |
++ </varlistentry> |
6998 |
++ |
6999 |
++ <varlistentry> |
7000 |
++ <term><constant>KDBUS_ATTACH_AUXGROUPS</constant></term> |
7001 |
++ <listitem><para> |
7002 |
++ Requests the attachment of an item of type |
7003 |
++ <constant>KDBUS_ITEM_AUXGROUPS</constant>. |
7004 |
++ </para></listitem> |
7005 |
++ </varlistentry> |
7006 |
++ |
7007 |
++ <varlistentry> |
7008 |
++ <term><constant>KDBUS_ATTACH_NAMES</constant></term> |
7009 |
++ <listitem><para> |
7010 |
++ Requests the attachment of an item of type |
7011 |
++ <constant>KDBUS_ITEM_OWNED_NAME</constant>. |
7012 |
++ </para></listitem> |
7013 |
++ </varlistentry> |
7014 |
++ |
7015 |
++ <varlistentry> |
7016 |
++ <term><constant>KDBUS_ATTACH_TID_COMM</constant></term> |
7017 |
++ <listitem><para> |
7018 |
++ Requests the attachment of an item of type |
7019 |
++ <constant>KDBUS_ITEM_TID_COMM</constant>. |
7020 |
++ </para></listitem> |
7021 |
++ </varlistentry> |
7022 |
++ |
7023 |
++ <varlistentry> |
7024 |
++ <term><constant>KDBUS_ATTACH_PID_COMM</constant></term> |
7025 |
++ <listitem><para> |
7026 |
++ Requests the attachment of an item of type |
7027 |
++ <constant>KDBUS_ITEM_PID_COMM</constant>. |
7028 |
++ </para></listitem> |
7029 |
++ </varlistentry> |
7030 |
++ |
7031 |
++ <varlistentry> |
7032 |
++ <term><constant>KDBUS_ATTACH_EXE</constant></term> |
7033 |
++ <listitem><para> |
7034 |
++ Requests the attachment of an item of type |
7035 |
++ <constant>KDBUS_ITEM_EXE</constant>. |
7036 |
++ </para></listitem> |
7037 |
++ </varlistentry> |
7038 |
++ |
7039 |
++ <varlistentry> |
7040 |
++ <term><constant>KDBUS_ATTACH_CMDLINE</constant></term> |
7041 |
++ <listitem><para> |
7042 |
++ Requests the attachment of an item of type |
7043 |
++ <constant>KDBUS_ITEM_CMDLINE</constant>. |
7044 |
++ </para></listitem> |
7045 |
++ </varlistentry> |
7046 |
++ |
7047 |
++ <varlistentry> |
7048 |
++ <term><constant>KDBUS_ATTACH_CGROUP</constant></term> |
7049 |
++ <listitem><para> |
7050 |
++ Requests the attachment of an item of type |
7051 |
++ <constant>KDBUS_ITEM_CGROUP</constant>. |
7052 |
++ </para></listitem> |
7053 |
++ </varlistentry> |
7054 |
++ |
7055 |
++ <varlistentry> |
7056 |
++ <term><constant>KDBUS_ATTACH_CAPS</constant></term> |
7057 |
++ <listitem><para> |
7058 |
++ Requests the attachment of an item of type |
7059 |
++ <constant>KDBUS_ITEM_CAPS</constant>. |
7060 |
++ </para></listitem> |
7061 |
++ </varlistentry> |
7062 |
++ |
7063 |
++ <varlistentry> |
7064 |
++ <term><constant>KDBUS_ATTACH_SECLABEL</constant></term> |
7065 |
++ <listitem><para> |
7066 |
++ Requests the attachment of an item of type |
7067 |
++ <constant>KDBUS_ITEM_SECLABEL</constant>. |
7068 |
++ </para></listitem> |
7069 |
++ </varlistentry> |
7070 |
++ |
7071 |
++ <varlistentry> |
7072 |
++ <term><constant>KDBUS_ATTACH_AUDIT</constant></term> |
7073 |
++ <listitem><para> |
7074 |
++ Requests the attachment of an item of type |
7075 |
++ <constant>KDBUS_ITEM_AUDIT</constant>. |
7076 |
++ </para></listitem> |
7077 |
++ </varlistentry> |
7078 |
++ |
7079 |
++ <varlistentry> |
7080 |
++ <term><constant>KDBUS_ATTACH_CONN_DESCRIPTION</constant></term> |
7081 |
++ <listitem><para> |
7082 |
++ Requests the attachment of an item of type |
7083 |
++ <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant>. |
7084 |
++ </para></listitem> |
7085 |
++ </varlistentry> |
7086 |
++ </variablelist> |
7087 |
++ |
7088 |
++ <para> |
7089 |
++ Please refer to |
7090 |
++ <citerefentry> |
7091 |
++ <refentrytitle>kdbus.item</refentrytitle> |
7092 |
++ <manvolnum>7</manvolnum> |
7093 |
++ </citerefentry> |
7094 |
++ for detailed information about the layout and payload of items and |
7095 |
++ what metadata should be used to. |
7096 |
++ </para> |
7097 |
++ </refsect2> |
7098 |
++ </refsect1> |
7099 |
++ |
7100 |
++ <refsect1> |
7101 |
++ <title>The ioctl interface</title> |
7102 |
++ |
7103 |
++ <para> |
7104 |
++ As stated in the 'synopsis' section above, application developers are |
7105 |
++ strongly encouraged to use kdbus through one of the high-level D-Bus |
7106 |
++ abstraction libraries, rather than using the low-level API directly. |
7107 |
++ </para> |
7108 |
++ |
7109 |
++ <para> |
7110 |
++ kdbus on the kernel level exposes its functions exclusively through |
7111 |
++ <citerefentry> |
7112 |
++ <refentrytitle>ioctl</refentrytitle> |
7113 |
++ <manvolnum>2</manvolnum> |
7114 |
++ </citerefentry>, |
7115 |
++ employed on file descriptors returned by |
7116 |
++ <citerefentry> |
7117 |
++ <refentrytitle>open</refentrytitle> |
7118 |
++ <manvolnum>2</manvolnum> |
7119 |
++ </citerefentry> |
7120 |
++ on pseudo files exposed by |
7121 |
++ <citerefentry> |
7122 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
7123 |
++ <manvolnum>7</manvolnum> |
7124 |
++ </citerefentry>. |
7125 |
++ </para> |
7126 |
++ <para> |
7127 |
++ Following is a list of all the ioctls, along with the command structs |
7128 |
++ they must be used with. |
7129 |
++ </para> |
7130 |
++ |
7131 |
++ <informaltable frame="none"> |
7132 |
++ <tgroup cols="3" colsep="1"> |
7133 |
++ <thead> |
7134 |
++ <row> |
7135 |
++ <entry>ioctl signature</entry> |
7136 |
++ <entry>command</entry> |
7137 |
++ <entry>transported struct</entry> |
7138 |
++ </row> |
7139 |
++ </thead> |
7140 |
++ <tbody> |
7141 |
++ <row> |
7142 |
++ <entry><constant>0x40189500</constant></entry> |
7143 |
++ <entry><constant>KDBUS_CMD_BUS_MAKE</constant></entry> |
7144 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7145 |
++ </row><row> |
7146 |
++ <entry><constant>0x40189510</constant></entry> |
7147 |
++ <entry><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></entry> |
7148 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7149 |
++ </row><row> |
7150 |
++ <entry><constant>0xc0609580</constant></entry> |
7151 |
++ <entry><constant>KDBUS_CMD_HELLO</constant></entry> |
7152 |
++ <entry><type>struct kdbus_cmd_hello *</type></entry> |
7153 |
++ </row><row> |
7154 |
++ <entry><constant>0x40189582</constant></entry> |
7155 |
++ <entry><constant>KDBUS_CMD_BYEBYE</constant></entry> |
7156 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7157 |
++ </row><row> |
7158 |
++ <entry><constant>0x40389590</constant></entry> |
7159 |
++ <entry><constant>KDBUS_CMD_SEND</constant></entry> |
7160 |
++ <entry><type>struct kdbus_cmd_send *</type></entry> |
7161 |
++ </row><row> |
7162 |
++ <entry><constant>0x80409591</constant></entry> |
7163 |
++ <entry><constant>KDBUS_CMD_RECV</constant></entry> |
7164 |
++ <entry><type>struct kdbus_cmd_recv *</type></entry> |
7165 |
++ </row><row> |
7166 |
++ <entry><constant>0x40209583</constant></entry> |
7167 |
++ <entry><constant>KDBUS_CMD_FREE</constant></entry> |
7168 |
++ <entry><type>struct kdbus_cmd_free *</type></entry> |
7169 |
++ </row><row> |
7170 |
++ <entry><constant>0x401895a0</constant></entry> |
7171 |
++ <entry><constant>KDBUS_CMD_NAME_ACQUIRE</constant></entry> |
7172 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7173 |
++ </row><row> |
7174 |
++ <entry><constant>0x401895a1</constant></entry> |
7175 |
++ <entry><constant>KDBUS_CMD_NAME_RELEASE</constant></entry> |
7176 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7177 |
++ </row><row> |
7178 |
++ <entry><constant>0x80289586</constant></entry> |
7179 |
++ <entry><constant>KDBUS_CMD_LIST</constant></entry> |
7180 |
++ <entry><type>struct kdbus_cmd_list *</type></entry> |
7181 |
++ </row><row> |
7182 |
++ <entry><constant>0x80309584</constant></entry> |
7183 |
++ <entry><constant>KDBUS_CMD_CONN_INFO</constant></entry> |
7184 |
++ <entry><type>struct kdbus_cmd_info *</type></entry> |
7185 |
++ </row><row> |
7186 |
++ <entry><constant>0x40209551</constant></entry> |
7187 |
++ <entry><constant>KDBUS_CMD_UPDATE</constant></entry> |
7188 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7189 |
++ </row><row> |
7190 |
++ <entry><constant>0x80309585</constant></entry> |
7191 |
++ <entry><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></entry> |
7192 |
++ <entry><type>struct kdbus_cmd_info *</type></entry> |
7193 |
++ </row><row> |
7194 |
++ <entry><constant>0x40189511</constant></entry> |
7195 |
++ <entry><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></entry> |
7196 |
++ <entry><type>struct kdbus_cmd *</type></entry> |
7197 |
++ </row><row> |
7198 |
++ <entry><constant>0x402095b0</constant></entry> |
7199 |
++ <entry><constant>KDBUS_CMD_MATCH_ADD</constant></entry> |
7200 |
++ <entry><type>struct kdbus_cmd_match *</type></entry> |
7201 |
++ </row><row> |
7202 |
++ <entry><constant>0x402095b1</constant></entry> |
7203 |
++ <entry><constant>KDBUS_CMD_MATCH_REMOVE</constant></entry> |
7204 |
++ <entry><type>struct kdbus_cmd_match *</type></entry> |
7205 |
++ </row> |
7206 |
++ </tbody> |
7207 |
++ </tgroup> |
7208 |
++ </informaltable> |
7209 |
++ |
7210 |
++ <para> |
7211 |
++ Depending on the type of <emphasis>kdbusfs</emphasis> node that was |
7212 |
++ opened and what ioctls have been executed on a file descriptor before, |
7213 |
++ a different sub-set of ioctl commands is allowed. |
7214 |
++ </para> |
7215 |
++ |
7216 |
++ <itemizedlist> |
7217 |
++ <listitem> |
7218 |
++ <para> |
7219 |
++ On a file descriptor resulting from opening a |
7220 |
++ <emphasis>control node</emphasis>, only the |
7221 |
++ <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl may be executed. |
7222 |
++ </para> |
7223 |
++ </listitem> |
7224 |
++ <listitem> |
7225 |
++ <para> |
7226 |
++ On a file descriptor resulting from opening a |
7227 |
++ <emphasis>bus endpoint node</emphasis>, only the |
7228 |
++ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> and |
7229 |
++ <constant>KDBUS_CMD_HELLO</constant> ioctls may be executed. |
7230 |
++ </para> |
7231 |
++ </listitem> |
7232 |
++ <listitem> |
7233 |
++ <para> |
7234 |
++ A file descriptor that was used to create a bus |
7235 |
++ (via <constant>KDBUS_CMD_BUS_MAKE</constant>) is called a |
7236 |
++ <emphasis>bus owner</emphasis> file descriptor. The bus will be |
7237 |
++ active as long as the file descriptor is kept open. |
7238 |
++ A bus owner file descriptor can not be used to |
7239 |
++ employ any further ioctls. As soon as |
7240 |
++ <citerefentry> |
7241 |
++ <refentrytitle>close</refentrytitle> |
7242 |
++ <manvolnum>2</manvolnum> |
7243 |
++ </citerefentry> |
7244 |
++ is called on it, the bus will be shut down, along will all associated |
7245 |
++ endpoints and connections. See |
7246 |
++ <citerefentry> |
7247 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
7248 |
++ <manvolnum>7</manvolnum> |
7249 |
++ </citerefentry> |
7250 |
++ for more details. |
7251 |
++ </para> |
7252 |
++ </listitem> |
7253 |
++ <listitem> |
7254 |
++ <para> |
7255 |
++ A file descriptor that was used to create an endpoint |
7256 |
++ (via <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>) is called an |
7257 |
++ <emphasis>endpoint owner</emphasis> file descriptor. The endpoint |
7258 |
++ will be active as long as the file descriptor is kept open. |
7259 |
++ An endpoint owner file descriptor can only be used |
7260 |
++ to update details of an endpoint through the |
7261 |
++ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> ioctl. As soon as |
7262 |
++ <citerefentry> |
7263 |
++ <refentrytitle>close</refentrytitle> |
7264 |
++ <manvolnum>2</manvolnum> |
7265 |
++ </citerefentry> |
7266 |
++ is called on it, the endpoint will be removed from the bus, and all |
7267 |
++ connections that are connected to the bus through it are shut down. |
7268 |
++ See |
7269 |
++ <citerefentry> |
7270 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
7271 |
++ <manvolnum>7</manvolnum> |
7272 |
++ </citerefentry> |
7273 |
++ for more details. |
7274 |
++ </para> |
7275 |
++ </listitem> |
7276 |
++ <listitem> |
7277 |
++ <para> |
7278 |
++ A file descriptor that was used to create a connection |
7279 |
++ (via <constant>KDBUS_CMD_HELLO</constant>) is called a |
7280 |
++ <emphasis>connection owner</emphasis> file descriptor. The connection |
7281 |
++ will be active as long as the file descriptor is kept open. |
7282 |
++ A connection owner file descriptor may be used to |
7283 |
++ issue any of the following ioctls. |
7284 |
++ </para> |
7285 |
++ |
7286 |
++ <itemizedlist> |
7287 |
++ <listitem><para> |
7288 |
++ <constant>KDBUS_CMD_UPDATE</constant> to tweak details of the |
7289 |
++ connection. See |
7290 |
++ <citerefentry> |
7291 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
7292 |
++ <manvolnum>7</manvolnum> |
7293 |
++ </citerefentry>. |
7294 |
++ </para></listitem> |
7295 |
++ |
7296 |
++ <listitem><para> |
7297 |
++ <constant>KDBUS_CMD_BYEBYE</constant> to shut down a connection |
7298 |
++ without losing messages. See |
7299 |
++ <citerefentry> |
7300 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
7301 |
++ <manvolnum>7</manvolnum> |
7302 |
++ </citerefentry>. |
7303 |
++ </para></listitem> |
7304 |
++ |
7305 |
++ <listitem><para> |
7306 |
++ <constant>KDBUS_CMD_FREE</constant> to free a slice of memory in |
7307 |
++ the pool. See |
7308 |
++ <citerefentry> |
7309 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
7310 |
++ <manvolnum>7</manvolnum> |
7311 |
++ </citerefentry>. |
7312 |
++ </para></listitem> |
7313 |
++ |
7314 |
++ <listitem><para> |
7315 |
++ <constant>KDBUS_CMD_CONN_INFO</constant> to retrieve information |
7316 |
++ on other connections on the bus. See |
7317 |
++ <citerefentry> |
7318 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
7319 |
++ <manvolnum>7</manvolnum> |
7320 |
++ </citerefentry>. |
7321 |
++ </para></listitem> |
7322 |
++ |
7323 |
++ <listitem><para> |
7324 |
++ <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> to retrieve |
7325 |
++ information on the bus creator. See |
7326 |
++ <citerefentry> |
7327 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
7328 |
++ <manvolnum>7</manvolnum> |
7329 |
++ </citerefentry>. |
7330 |
++ </para></listitem> |
7331 |
++ |
7332 |
++ <listitem><para> |
7333 |
++ <constant>KDBUS_CMD_LIST</constant> to retrieve a list of |
7334 |
++ currently active well-known names and unique IDs on the bus. See |
7335 |
++ <citerefentry> |
7336 |
++ <refentrytitle>kdbus.name</refentrytitle> |
7337 |
++ <manvolnum>7</manvolnum> |
7338 |
++ </citerefentry>. |
7339 |
++ </para></listitem> |
7340 |
++ |
7341 |
++ <listitem><para> |
7342 |
++ <constant>KDBUS_CMD_SEND</constant> and |
7343 |
++ <constant>KDBUS_CMD_RECV</constant> to send or receive a message. |
7344 |
++ See |
7345 |
++ <citerefentry> |
7346 |
++ <refentrytitle>kdbus.message</refentrytitle> |
7347 |
++ <manvolnum>7</manvolnum> |
7348 |
++ </citerefentry>. |
7349 |
++ </para></listitem> |
7350 |
++ |
7351 |
++ <listitem><para> |
7352 |
++ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> and |
7353 |
++ <constant>KDBUS_CMD_NAME_RELEASE</constant> to acquire or release |
7354 |
++ a well-known name on the bus. See |
7355 |
++ <citerefentry> |
7356 |
++ <refentrytitle>kdbus.name</refentrytitle> |
7357 |
++ <manvolnum>7</manvolnum> |
7358 |
++ </citerefentry>. |
7359 |
++ </para></listitem> |
7360 |
++ |
7361 |
++ <listitem><para> |
7362 |
++ <constant>KDBUS_CMD_MATCH_ADD</constant> and |
7363 |
++ <constant>KDBUS_CMD_MATCH_REMOVE</constant> to add or remove |
7364 |
++ a match for signal messages. See |
7365 |
++ <citerefentry> |
7366 |
++ <refentrytitle>kdbus.match</refentrytitle> |
7367 |
++ <manvolnum>7</manvolnum> |
7368 |
++ </citerefentry>. |
7369 |
++ </para></listitem> |
7370 |
++ </itemizedlist> |
7371 |
++ </listitem> |
7372 |
++ </itemizedlist> |
7373 |
++ |
7374 |
++ <para> |
7375 |
++ These ioctls, along with the structs they transport, are explained in |
7376 |
++ detail in the other documents linked to in the "See Also" section below. |
7377 |
++ </para> |
7378 |
++ </refsect1> |
7379 |
++ |
7380 |
++ <refsect1> |
7381 |
++ <title>See Also</title> |
7382 |
++ <simplelist type="inline"> |
7383 |
++ <member> |
7384 |
++ <citerefentry> |
7385 |
++ <refentrytitle>kdbus.bus</refentrytitle> |
7386 |
++ <manvolnum>7</manvolnum> |
7387 |
++ </citerefentry> |
7388 |
++ </member> |
7389 |
++ <member> |
7390 |
++ <citerefentry> |
7391 |
++ <refentrytitle>kdbus.connection</refentrytitle> |
7392 |
++ <manvolnum>7</manvolnum> |
7393 |
++ </citerefentry> |
7394 |
++ </member> |
7395 |
++ <member> |
7396 |
++ <citerefentry> |
7397 |
++ <refentrytitle>kdbus.endpoint</refentrytitle> |
7398 |
++ <manvolnum>7</manvolnum> |
7399 |
++ </citerefentry> |
7400 |
++ </member> |
7401 |
++ <member> |
7402 |
++ <citerefentry> |
7403 |
++ <refentrytitle>kdbus.fs</refentrytitle> |
7404 |
++ <manvolnum>7</manvolnum> |
7405 |
++ </citerefentry> |
7406 |
++ </member> |
7407 |
++ <member> |
7408 |
++ <citerefentry> |
7409 |
++ <refentrytitle>kdbus.item</refentrytitle> |
7410 |
++ <manvolnum>7</manvolnum> |
7411 |
++ </citerefentry> |
7412 |
++ </member> |
7413 |
++ <member> |
7414 |
++ <citerefentry> |
7415 |
++ <refentrytitle>kdbus.message</refentrytitle> |
7416 |
++ <manvolnum>7</manvolnum> |
7417 |
++ </citerefentry> |
7418 |
++ </member> |
7419 |
++ <member> |
7420 |
++ <citerefentry> |
7421 |
++ <refentrytitle>kdbus.name</refentrytitle> |
7422 |
++ <manvolnum>7</manvolnum> |
7423 |
++ </citerefentry> |
7424 |
++ </member> |
7425 |
++ <member> |
7426 |
++ <citerefentry> |
7427 |
++ <refentrytitle>kdbus.pool</refentrytitle> |
7428 |
++ <manvolnum>7</manvolnum> |
7429 |
++ </citerefentry> |
7430 |
++ </member> |
7431 |
++ <member> |
7432 |
++ <citerefentry> |
7433 |
++ <refentrytitle>ioctl</refentrytitle> |
7434 |
++ <manvolnum>2</manvolnum> |
7435 |
++ </citerefentry> |
7436 |
++ </member> |
7437 |
++ <member> |
7438 |
++ <citerefentry> |
7439 |
++ <refentrytitle>mmap</refentrytitle> |
7440 |
++ <manvolnum>2</manvolnum> |
7441 |
++ </citerefentry> |
7442 |
++ </member> |
7443 |
++ <member> |
7444 |
++ <citerefentry> |
7445 |
++ <refentrytitle>open</refentrytitle> |
7446 |
++ <manvolnum>2</manvolnum> |
7447 |
++ </citerefentry> |
7448 |
++ </member> |
7449 |
++ <member> |
7450 |
++ <citerefentry> |
7451 |
++ <refentrytitle>close</refentrytitle> |
7452 |
++ <manvolnum>2</manvolnum> |
7453 |
++ </citerefentry> |
7454 |
++ </member> |
7455 |
++ <member> |
7456 |
++ <ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink> |
7457 |
++ </member> |
7458 |
++ </simplelist> |
7459 |
++ </refsect1> |
7460 |
++ |
7461 |
++</refentry> |
7462 |
+diff --git a/Documentation/kdbus/stylesheet.xsl b/Documentation/kdbus/stylesheet.xsl |
7463 |
+new file mode 100644 |
7464 |
+index 0000000..52565ea |
7465 |
+--- /dev/null |
7466 |
++++ b/Documentation/kdbus/stylesheet.xsl |
7467 |
+@@ -0,0 +1,16 @@ |
7468 |
++<?xml version="1.0" encoding="UTF-8"?> |
7469 |
++<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"> |
7470 |
++ <param name="chunk.quietly">1</param> |
7471 |
++ <param name="funcsynopsis.style">ansi</param> |
7472 |
++ <param name="funcsynopsis.tabular.threshold">80</param> |
7473 |
++ <param name="callout.graphics">0</param> |
7474 |
++ <param name="paper.type">A4</param> |
7475 |
++ <param name="generate.section.toc.level">2</param> |
7476 |
++ <param name="use.id.as.filename">1</param> |
7477 |
++ <param name="citerefentry.link">1</param> |
7478 |
++ <strip-space elements="*"/> |
7479 |
++ <template name="generate.citerefentry.link"> |
7480 |
++ <value-of select="refentrytitle"/> |
7481 |
++ <text>.html</text> |
7482 |
++ </template> |
7483 |
++</stylesheet> |
7484 |
+diff --git a/MAINTAINERS b/MAINTAINERS |
7485 |
+index 6239a30..e924246 100644 |
7486 |
+--- a/MAINTAINERS |
7487 |
++++ b/MAINTAINERS |
7488 |
+@@ -5503,6 +5503,19 @@ S: Maintained |
7489 |
+ F: Documentation/kbuild/kconfig-language.txt |
7490 |
+ F: scripts/kconfig/ |
7491 |
+ |
7492 |
++KDBUS |
7493 |
++M: Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
7494 |
++M: Daniel Mack <daniel@××××××.org> |
7495 |
++M: David Herrmann <dh.herrmann@××××××××××.com> |
7496 |
++M: Djalal Harouni <tixxdz@××××××.org> |
7497 |
++L: linux-kernel@×××××××××××.org |
7498 |
++S: Maintained |
7499 |
++F: ipc/kdbus/* |
7500 |
++F: samples/kdbus/* |
7501 |
++F: Documentation/kdbus/* |
7502 |
++F: include/uapi/linux/kdbus.h |
7503 |
++F: tools/testing/selftests/kdbus/ |
7504 |
++ |
7505 |
+ KDUMP |
7506 |
+ M: Vivek Goyal <vgoyal@××××××.com> |
7507 |
+ M: Haren Myneni <hbabu@××××××.com> |
7508 |
+diff --git a/Makefile b/Makefile |
7509 |
+index 1100ff3..08c9818 100644 |
7510 |
+--- a/Makefile |
7511 |
++++ b/Makefile |
7512 |
+@@ -1350,6 +1350,7 @@ $(help-board-dirs): help-%: |
7513 |
+ %docs: scripts_basic FORCE |
7514 |
+ $(Q)$(MAKE) $(build)=scripts build_docproc |
7515 |
+ $(Q)$(MAKE) $(build)=Documentation/DocBook $@ |
7516 |
++ $(Q)$(MAKE) $(build)=Documentation/kdbus $@ |
7517 |
+ |
7518 |
+ else # KBUILD_EXTMOD |
7519 |
+ |
7520 |
+diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild |
7521 |
+index 68ceb97..ddc413e 100644 |
7522 |
+--- a/include/uapi/linux/Kbuild |
7523 |
++++ b/include/uapi/linux/Kbuild |
7524 |
+@@ -214,6 +214,7 @@ header-y += ixjuser.h |
7525 |
+ header-y += jffs2.h |
7526 |
+ header-y += joystick.h |
7527 |
+ header-y += kcmp.h |
7528 |
++header-y += kdbus.h |
7529 |
+ header-y += kdev_t.h |
7530 |
+ header-y += kd.h |
7531 |
+ header-y += kernelcapi.h |
7532 |
+diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h |
7533 |
+new file mode 100644 |
7534 |
+index 0000000..00a6e14 |
7535 |
+--- /dev/null |
7536 |
++++ b/include/uapi/linux/kdbus.h |
7537 |
+@@ -0,0 +1,979 @@ |
7538 |
++/* |
7539 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
7540 |
++ * the terms of the GNU Lesser General Public License as published by the |
7541 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
7542 |
++ * your option) any later version. |
7543 |
++ */ |
7544 |
++ |
7545 |
++#ifndef _UAPI_KDBUS_H_ |
7546 |
++#define _UAPI_KDBUS_H_ |
7547 |
++ |
7548 |
++#include <linux/ioctl.h> |
7549 |
++#include <linux/types.h> |
7550 |
++ |
7551 |
++#define KDBUS_IOCTL_MAGIC 0x95 |
7552 |
++#define KDBUS_SRC_ID_KERNEL (0) |
7553 |
++#define KDBUS_DST_ID_NAME (0) |
7554 |
++#define KDBUS_MATCH_ID_ANY (~0ULL) |
7555 |
++#define KDBUS_DST_ID_BROADCAST (~0ULL) |
7556 |
++#define KDBUS_FLAG_NEGOTIATE (1ULL << 63) |
7557 |
++ |
7558 |
++/** |
7559 |
++ * struct kdbus_notify_id_change - name registry change message |
7560 |
++ * @id: New or former owner of the name |
7561 |
++ * @flags: flags field from KDBUS_HELLO_* |
7562 |
++ * |
7563 |
++ * Sent from kernel to userspace when the owner or activator of |
7564 |
++ * a well-known name changes. |
7565 |
++ * |
7566 |
++ * Attached to: |
7567 |
++ * KDBUS_ITEM_ID_ADD |
7568 |
++ * KDBUS_ITEM_ID_REMOVE |
7569 |
++ */ |
7570 |
++struct kdbus_notify_id_change { |
7571 |
++ __u64 id; |
7572 |
++ __u64 flags; |
7573 |
++} __attribute__((__aligned__(8))); |
7574 |
++ |
7575 |
++/** |
7576 |
++ * struct kdbus_notify_name_change - name registry change message |
7577 |
++ * @old_id: ID and flags of former owner of a name |
7578 |
++ * @new_id: ID and flags of new owner of a name |
7579 |
++ * @name: Well-known name |
7580 |
++ * |
7581 |
++ * Sent from kernel to userspace when the owner or activator of |
7582 |
++ * a well-known name changes. |
7583 |
++ * |
7584 |
++ * Attached to: |
7585 |
++ * KDBUS_ITEM_NAME_ADD |
7586 |
++ * KDBUS_ITEM_NAME_REMOVE |
7587 |
++ * KDBUS_ITEM_NAME_CHANGE |
7588 |
++ */ |
7589 |
++struct kdbus_notify_name_change { |
7590 |
++ struct kdbus_notify_id_change old_id; |
7591 |
++ struct kdbus_notify_id_change new_id; |
7592 |
++ char name[0]; |
7593 |
++} __attribute__((__aligned__(8))); |
7594 |
++ |
7595 |
++/** |
7596 |
++ * struct kdbus_creds - process credentials |
7597 |
++ * @uid: User ID |
7598 |
++ * @euid: Effective UID |
7599 |
++ * @suid: Saved UID |
7600 |
++ * @fsuid: Filesystem UID |
7601 |
++ * @gid: Group ID |
7602 |
++ * @egid: Effective GID |
7603 |
++ * @sgid: Saved GID |
7604 |
++ * @fsgid: Filesystem GID |
7605 |
++ * |
7606 |
++ * Attached to: |
7607 |
++ * KDBUS_ITEM_CREDS |
7608 |
++ */ |
7609 |
++struct kdbus_creds { |
7610 |
++ __u64 uid; |
7611 |
++ __u64 euid; |
7612 |
++ __u64 suid; |
7613 |
++ __u64 fsuid; |
7614 |
++ __u64 gid; |
7615 |
++ __u64 egid; |
7616 |
++ __u64 sgid; |
7617 |
++ __u64 fsgid; |
7618 |
++} __attribute__((__aligned__(8))); |
7619 |
++ |
7620 |
++/** |
7621 |
++ * struct kdbus_pids - process identifiers |
7622 |
++ * @pid: Process ID |
7623 |
++ * @tid: Thread ID |
7624 |
++ * @ppid: Parent process ID |
7625 |
++ * |
7626 |
++ * The PID and TID of a process. |
7627 |
++ * |
7628 |
++ * Attached to: |
7629 |
++ * KDBUS_ITEM_PIDS |
7630 |
++ */ |
7631 |
++struct kdbus_pids { |
7632 |
++ __u64 pid; |
7633 |
++ __u64 tid; |
7634 |
++ __u64 ppid; |
7635 |
++} __attribute__((__aligned__(8))); |
7636 |
++ |
7637 |
++/** |
7638 |
++ * struct kdbus_caps - process capabilities |
7639 |
++ * @last_cap: Highest currently known capability bit |
7640 |
++ * @caps: Variable number of 32-bit capabilities flags |
7641 |
++ * |
7642 |
++ * Contains a variable number of 32-bit capabilities flags. |
7643 |
++ * |
7644 |
++ * Attached to: |
7645 |
++ * KDBUS_ITEM_CAPS |
7646 |
++ */ |
7647 |
++struct kdbus_caps { |
7648 |
++ __u32 last_cap; |
7649 |
++ __u32 caps[0]; |
7650 |
++} __attribute__((__aligned__(8))); |
7651 |
++ |
7652 |
++/** |
7653 |
++ * struct kdbus_audit - audit information |
7654 |
++ * @sessionid: The audit session ID |
7655 |
++ * @loginuid: The audit login uid |
7656 |
++ * |
7657 |
++ * Attached to: |
7658 |
++ * KDBUS_ITEM_AUDIT |
7659 |
++ */ |
7660 |
++struct kdbus_audit { |
7661 |
++ __u32 sessionid; |
7662 |
++ __u32 loginuid; |
7663 |
++} __attribute__((__aligned__(8))); |
7664 |
++ |
7665 |
++/** |
7666 |
++ * struct kdbus_timestamp |
7667 |
++ * @seqnum: Global per-domain message sequence number |
7668 |
++ * @monotonic_ns: Monotonic timestamp, in nanoseconds |
7669 |
++ * @realtime_ns: Realtime timestamp, in nanoseconds |
7670 |
++ * |
7671 |
++ * Attached to: |
7672 |
++ * KDBUS_ITEM_TIMESTAMP |
7673 |
++ */ |
7674 |
++struct kdbus_timestamp { |
7675 |
++ __u64 seqnum; |
7676 |
++ __u64 monotonic_ns; |
7677 |
++ __u64 realtime_ns; |
7678 |
++} __attribute__((__aligned__(8))); |
7679 |
++ |
7680 |
++/** |
7681 |
++ * struct kdbus_vec - I/O vector for kdbus payload items |
7682 |
++ * @size: The size of the vector |
7683 |
++ * @address: Memory address of data buffer |
7684 |
++ * @offset: Offset in the in-message payload memory, |
7685 |
++ * relative to the message head |
7686 |
++ * |
7687 |
++ * Attached to: |
7688 |
++ * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF |
7689 |
++ */ |
7690 |
++struct kdbus_vec { |
7691 |
++ __u64 size; |
7692 |
++ union { |
7693 |
++ __u64 address; |
7694 |
++ __u64 offset; |
7695 |
++ }; |
7696 |
++} __attribute__((__aligned__(8))); |
7697 |
++ |
7698 |
++/** |
7699 |
++ * struct kdbus_bloom_parameter - bus-wide bloom parameters |
7700 |
++ * @size: Size of the bit field in bytes (m / 8) |
7701 |
++ * @n_hash: Number of hash functions used (k) |
7702 |
++ */ |
7703 |
++struct kdbus_bloom_parameter { |
7704 |
++ __u64 size; |
7705 |
++ __u64 n_hash; |
7706 |
++} __attribute__((__aligned__(8))); |
7707 |
++ |
7708 |
++/** |
7709 |
++ * struct kdbus_bloom_filter - bloom filter containing n elements |
7710 |
++ * @generation: Generation of the element set in the filter |
7711 |
++ * @data: Bit field, multiple of 8 bytes |
7712 |
++ */ |
7713 |
++struct kdbus_bloom_filter { |
7714 |
++ __u64 generation; |
7715 |
++ __u64 data[0]; |
7716 |
++} __attribute__((__aligned__(8))); |
7717 |
++ |
7718 |
++/** |
7719 |
++ * struct kdbus_memfd - a kdbus memfd |
7720 |
++ * @start: The offset into the memfd where the segment starts |
7721 |
++ * @size: The size of the memfd segment |
7722 |
++ * @fd: The file descriptor number |
7723 |
++ * @__pad: Padding to ensure proper alignment and size |
7724 |
++ * |
7725 |
++ * Attached to: |
7726 |
++ * KDBUS_ITEM_PAYLOAD_MEMFD |
7727 |
++ */ |
7728 |
++struct kdbus_memfd { |
7729 |
++ __u64 start; |
7730 |
++ __u64 size; |
7731 |
++ int fd; |
7732 |
++ __u32 __pad; |
7733 |
++} __attribute__((__aligned__(8))); |
7734 |
++ |
7735 |
++/** |
7736 |
++ * struct kdbus_name - a registered well-known name with its flags |
7737 |
++ * @flags: Flags from KDBUS_NAME_* |
7738 |
++ * @name: Well-known name |
7739 |
++ * |
7740 |
++ * Attached to: |
7741 |
++ * KDBUS_ITEM_OWNED_NAME |
7742 |
++ */ |
7743 |
++struct kdbus_name { |
7744 |
++ __u64 flags; |
7745 |
++ char name[0]; |
7746 |
++} __attribute__((__aligned__(8))); |
7747 |
++ |
7748 |
++/** |
7749 |
++ * enum kdbus_policy_access_type - permissions of a policy record |
7750 |
++ * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid |
7751 |
++ * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid |
7752 |
++ * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid |
7753 |
++ * @KDBUS_POLICY_ACCESS_WORLD: World-accessible |
7754 |
++ */ |
7755 |
++enum kdbus_policy_access_type { |
7756 |
++ _KDBUS_POLICY_ACCESS_NULL, |
7757 |
++ KDBUS_POLICY_ACCESS_USER, |
7758 |
++ KDBUS_POLICY_ACCESS_GROUP, |
7759 |
++ KDBUS_POLICY_ACCESS_WORLD, |
7760 |
++}; |
7761 |
++ |
7762 |
++/** |
7763 |
++ * enum kdbus_policy_access_flags - mode flags |
7764 |
++ * @KDBUS_POLICY_OWN: Allow to own a well-known name |
7765 |
++ * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE |
7766 |
++ * @KDBUS_POLICY_TALK: Allow communication to a well-known name |
7767 |
++ * Implies KDBUS_POLICY_SEE |
7768 |
++ * @KDBUS_POLICY_SEE: Allow to see a well-known name |
7769 |
++ */ |
7770 |
++enum kdbus_policy_type { |
7771 |
++ KDBUS_POLICY_SEE = 0, |
7772 |
++ KDBUS_POLICY_TALK, |
7773 |
++ KDBUS_POLICY_OWN, |
7774 |
++}; |
7775 |
++ |
7776 |
++/** |
7777 |
++ * struct kdbus_policy_access - policy access item |
7778 |
++ * @type: One of KDBUS_POLICY_ACCESS_* types |
7779 |
++ * @access: Access to grant |
7780 |
++ * @id: For KDBUS_POLICY_ACCESS_USER, the uid |
7781 |
++ * For KDBUS_POLICY_ACCESS_GROUP, the gid |
7782 |
++ */ |
7783 |
++struct kdbus_policy_access { |
7784 |
++ __u64 type; /* USER, GROUP, WORLD */ |
7785 |
++ __u64 access; /* OWN, TALK, SEE */ |
7786 |
++ __u64 id; /* uid, gid, 0 */ |
7787 |
++} __attribute__((__aligned__(8))); |
7788 |
++ |
7789 |
++/** |
7790 |
++ * enum kdbus_attach_flags - flags for metadata attachments |
7791 |
++ * @KDBUS_ATTACH_TIMESTAMP: Timestamp |
7792 |
++ * @KDBUS_ATTACH_CREDS: Credentials |
7793 |
++ * @KDBUS_ATTACH_PIDS: PIDs |
7794 |
++ * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups |
7795 |
++ * @KDBUS_ATTACH_NAMES: Well-known names |
7796 |
++ * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID |
7797 |
++ * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID |
7798 |
++ * @KDBUS_ATTACH_EXE: The path of the executable |
7799 |
++ * @KDBUS_ATTACH_CMDLINE: The process command line |
7800 |
++ * @KDBUS_ATTACH_CGROUP: The croup membership |
7801 |
++ * @KDBUS_ATTACH_CAPS: The process capabilities |
7802 |
++ * @KDBUS_ATTACH_SECLABEL: The security label |
7803 |
++ * @KDBUS_ATTACH_AUDIT: The audit IDs |
7804 |
++ * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name |
7805 |
++ * @_KDBUS_ATTACH_ALL: All of the above |
7806 |
++ * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of |
7807 |
++ * metatdata. |
7808 |
++ */ |
7809 |
++enum kdbus_attach_flags { |
7810 |
++ KDBUS_ATTACH_TIMESTAMP = 1ULL << 0, |
7811 |
++ KDBUS_ATTACH_CREDS = 1ULL << 1, |
7812 |
++ KDBUS_ATTACH_PIDS = 1ULL << 2, |
7813 |
++ KDBUS_ATTACH_AUXGROUPS = 1ULL << 3, |
7814 |
++ KDBUS_ATTACH_NAMES = 1ULL << 4, |
7815 |
++ KDBUS_ATTACH_TID_COMM = 1ULL << 5, |
7816 |
++ KDBUS_ATTACH_PID_COMM = 1ULL << 6, |
7817 |
++ KDBUS_ATTACH_EXE = 1ULL << 7, |
7818 |
++ KDBUS_ATTACH_CMDLINE = 1ULL << 8, |
7819 |
++ KDBUS_ATTACH_CGROUP = 1ULL << 9, |
7820 |
++ KDBUS_ATTACH_CAPS = 1ULL << 10, |
7821 |
++ KDBUS_ATTACH_SECLABEL = 1ULL << 11, |
7822 |
++ KDBUS_ATTACH_AUDIT = 1ULL << 12, |
7823 |
++ KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13, |
7824 |
++ _KDBUS_ATTACH_ALL = (1ULL << 14) - 1, |
7825 |
++ _KDBUS_ATTACH_ANY = ~0ULL |
7826 |
++}; |
7827 |
++ |
7828 |
++/** |
7829 |
++ * enum kdbus_item_type - item types to chain data in a list |
7830 |
++ * @_KDBUS_ITEM_NULL: Uninitialized/invalid |
7831 |
++ * @_KDBUS_ITEM_USER_BASE: Start of user items |
7832 |
++ * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items |
7833 |
++ * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data |
7834 |
++ * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head |
7835 |
++ * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd |
7836 |
++ * @KDBUS_ITEM_FDS: Attached file descriptors |
7837 |
++ * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous |
7838 |
++ * operation by writing to it from |
7839 |
++ * userspace |
7840 |
++ * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with |
7841 |
++ * KDBUS_CMD_BUS_MAKE, carries a |
7842 |
++ * struct kdbus_bloom_parameter |
7843 |
++ * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message, |
7844 |
++ * used to match against a bloom mask of a |
7845 |
++ * connection, carries a struct |
7846 |
++ * kdbus_bloom_filter |
7847 |
++ * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a |
7848 |
++ * message'sbloom filter |
7849 |
++ * @KDBUS_ITEM_DST_NAME: Destination's well-known name |
7850 |
++ * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint |
7851 |
++ * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which |
7852 |
++ * metadata a connection opts in to send |
7853 |
++ * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which |
7854 |
++ * metadata a connection requests to |
7855 |
++ * receive for each reeceived message |
7856 |
++ * @KDBUS_ITEM_ID: Connection ID |
7857 |
++ * @KDBUS_ITEM_NAME: Well-know name with flags |
7858 |
++ * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items |
7859 |
++ * @KDBUS_ITEM_TIMESTAMP: Timestamp |
7860 |
++ * @KDBUS_ITEM_CREDS: Process credentials |
7861 |
++ * @KDBUS_ITEM_PIDS: Process identifiers |
7862 |
++ * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups |
7863 |
++ * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated |
7864 |
++ * connection |
7865 |
++ * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier |
7866 |
++ * (Don't trust this, see below.) |
7867 |
++ * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier |
7868 |
++ * (Don't trust this, see below.) |
7869 |
++ * @KDBUS_ITEM_EXE: The path of the executable |
7870 |
++ * (Don't trust this, see below.) |
7871 |
++ * @KDBUS_ITEM_CMDLINE: The process command line |
7872 |
++ * (Don't trust this, see below.) |
7873 |
++ * @KDBUS_ITEM_CGROUP: The croup membership |
7874 |
++ * @KDBUS_ITEM_CAPS: The process capabilities |
7875 |
++ * @KDBUS_ITEM_SECLABEL: The security label |
7876 |
++ * @KDBUS_ITEM_AUDIT: The audit IDs |
7877 |
++ * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name |
7878 |
++ * (debugging) |
7879 |
++ * @_KDBUS_ITEM_POLICY_BASE: Start of policy items |
7880 |
++ * @KDBUS_ITEM_POLICY_ACCESS: Policy access block |
7881 |
++ * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items |
7882 |
++ * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change |
7883 |
++ * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change |
7884 |
++ * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change |
7885 |
++ * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change |
7886 |
++ * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change |
7887 |
++ * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached |
7888 |
++ * @KDBUS_ITEM_REPLY_DEAD: Destination died |
7889 |
++ * |
7890 |
++ * N.B: The process and thread COMM fields, as well as the CMDLINE and |
7891 |
++ * EXE fields may be altered by unprivileged processes und should |
7892 |
++ * hence *not* used for security decisions. Peers should make use of |
7893 |
++ * these items only for informational purposes, such as generating log |
7894 |
++ * records. |
7895 |
++ */ |
7896 |
++enum kdbus_item_type { |
7897 |
++ _KDBUS_ITEM_NULL, |
7898 |
++ _KDBUS_ITEM_USER_BASE, |
7899 |
++ KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE, |
7900 |
++ KDBUS_ITEM_PAYLOAD_VEC, |
7901 |
++ KDBUS_ITEM_PAYLOAD_OFF, |
7902 |
++ KDBUS_ITEM_PAYLOAD_MEMFD, |
7903 |
++ KDBUS_ITEM_FDS, |
7904 |
++ KDBUS_ITEM_CANCEL_FD, |
7905 |
++ KDBUS_ITEM_BLOOM_PARAMETER, |
7906 |
++ KDBUS_ITEM_BLOOM_FILTER, |
7907 |
++ KDBUS_ITEM_BLOOM_MASK, |
7908 |
++ KDBUS_ITEM_DST_NAME, |
7909 |
++ KDBUS_ITEM_MAKE_NAME, |
7910 |
++ KDBUS_ITEM_ATTACH_FLAGS_SEND, |
7911 |
++ KDBUS_ITEM_ATTACH_FLAGS_RECV, |
7912 |
++ KDBUS_ITEM_ID, |
7913 |
++ KDBUS_ITEM_NAME, |
7914 |
++ |
7915 |
++ /* keep these item types in sync with KDBUS_ATTACH_* flags */ |
7916 |
++ _KDBUS_ITEM_ATTACH_BASE = 0x1000, |
7917 |
++ KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE, |
7918 |
++ KDBUS_ITEM_CREDS, |
7919 |
++ KDBUS_ITEM_PIDS, |
7920 |
++ KDBUS_ITEM_AUXGROUPS, |
7921 |
++ KDBUS_ITEM_OWNED_NAME, |
7922 |
++ KDBUS_ITEM_TID_COMM, |
7923 |
++ KDBUS_ITEM_PID_COMM, |
7924 |
++ KDBUS_ITEM_EXE, |
7925 |
++ KDBUS_ITEM_CMDLINE, |
7926 |
++ KDBUS_ITEM_CGROUP, |
7927 |
++ KDBUS_ITEM_CAPS, |
7928 |
++ KDBUS_ITEM_SECLABEL, |
7929 |
++ KDBUS_ITEM_AUDIT, |
7930 |
++ KDBUS_ITEM_CONN_DESCRIPTION, |
7931 |
++ |
7932 |
++ _KDBUS_ITEM_POLICY_BASE = 0x2000, |
7933 |
++ KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE, |
7934 |
++ |
7935 |
++ _KDBUS_ITEM_KERNEL_BASE = 0x8000, |
7936 |
++ KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE, |
7937 |
++ KDBUS_ITEM_NAME_REMOVE, |
7938 |
++ KDBUS_ITEM_NAME_CHANGE, |
7939 |
++ KDBUS_ITEM_ID_ADD, |
7940 |
++ KDBUS_ITEM_ID_REMOVE, |
7941 |
++ KDBUS_ITEM_REPLY_TIMEOUT, |
7942 |
++ KDBUS_ITEM_REPLY_DEAD, |
7943 |
++}; |
7944 |
++ |
7945 |
++/** |
7946 |
++ * struct kdbus_item - chain of data blocks |
7947 |
++ * @size: Overall data record size |
7948 |
++ * @type: Kdbus_item type of data |
7949 |
++ * @data: Generic bytes |
7950 |
++ * @data32: Generic 32 bit array |
7951 |
++ * @data64: Generic 64 bit array |
7952 |
++ * @str: Generic string |
7953 |
++ * @id: Connection ID |
7954 |
++ * @vec: KDBUS_ITEM_PAYLOAD_VEC |
7955 |
++ * @creds: KDBUS_ITEM_CREDS |
7956 |
++ * @audit: KDBUS_ITEM_AUDIT |
7957 |
++ * @timestamp: KDBUS_ITEM_TIMESTAMP |
7958 |
++ * @name: KDBUS_ITEM_NAME |
7959 |
++ * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER |
7960 |
++ * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER |
7961 |
++ * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD |
7962 |
++ * @name_change: KDBUS_ITEM_NAME_ADD |
7963 |
++ * KDBUS_ITEM_NAME_REMOVE |
7964 |
++ * KDBUS_ITEM_NAME_CHANGE |
7965 |
++ * @id_change: KDBUS_ITEM_ID_ADD |
7966 |
++ * KDBUS_ITEM_ID_REMOVE |
7967 |
++ * @policy: KDBUS_ITEM_POLICY_ACCESS |
7968 |
++ */ |
7969 |
++struct kdbus_item { |
7970 |
++ __u64 size; |
7971 |
++ __u64 type; |
7972 |
++ union { |
7973 |
++ __u8 data[0]; |
7974 |
++ __u32 data32[0]; |
7975 |
++ __u64 data64[0]; |
7976 |
++ char str[0]; |
7977 |
++ |
7978 |
++ __u64 id; |
7979 |
++ struct kdbus_vec vec; |
7980 |
++ struct kdbus_creds creds; |
7981 |
++ struct kdbus_pids pids; |
7982 |
++ struct kdbus_audit audit; |
7983 |
++ struct kdbus_caps caps; |
7984 |
++ struct kdbus_timestamp timestamp; |
7985 |
++ struct kdbus_name name; |
7986 |
++ struct kdbus_bloom_parameter bloom_parameter; |
7987 |
++ struct kdbus_bloom_filter bloom_filter; |
7988 |
++ struct kdbus_memfd memfd; |
7989 |
++ int fds[0]; |
7990 |
++ struct kdbus_notify_name_change name_change; |
7991 |
++ struct kdbus_notify_id_change id_change; |
7992 |
++ struct kdbus_policy_access policy_access; |
7993 |
++ }; |
7994 |
++} __attribute__((__aligned__(8))); |
7995 |
++ |
7996 |
++/** |
7997 |
++ * enum kdbus_msg_flags - type of message |
7998 |
++ * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for |
7999 |
++ * method calls. The userspace-supplied |
8000 |
++ * cookie identifies the message and the |
8001 |
++ * respective reply carries the cookie |
8002 |
++ * in cookie_reply |
8003 |
++ * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed |
8004 |
++ * name is not currently active. This flag is |
8005 |
++ * not looked at by the kernel but only |
8006 |
++ * serves as hint for userspace implementations. |
8007 |
++ * @KDBUS_MSG_SIGNAL: Treat this message as signal |
8008 |
++ */ |
8009 |
++enum kdbus_msg_flags { |
8010 |
++ KDBUS_MSG_EXPECT_REPLY = 1ULL << 0, |
8011 |
++ KDBUS_MSG_NO_AUTO_START = 1ULL << 1, |
8012 |
++ KDBUS_MSG_SIGNAL = 1ULL << 2, |
8013 |
++}; |
8014 |
++ |
8015 |
++/** |
8016 |
++ * enum kdbus_payload_type - type of payload carried by message |
8017 |
++ * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message |
8018 |
++ * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus" |
8019 |
++ * |
8020 |
++ * Any payload-type is accepted. Common types will get added here once |
8021 |
++ * established. |
8022 |
++ */ |
8023 |
++enum kdbus_payload_type { |
8024 |
++ KDBUS_PAYLOAD_KERNEL, |
8025 |
++ KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL, |
8026 |
++}; |
8027 |
++ |
8028 |
++/** |
8029 |
++ * struct kdbus_msg - the representation of a kdbus message |
8030 |
++ * @size: Total size of the message |
8031 |
++ * @flags: Message flags (KDBUS_MSG_*), userspace → kernel |
8032 |
++ * @priority: Message queue priority value |
8033 |
++ * @dst_id: 64-bit ID of the destination connection |
8034 |
++ * @src_id: 64-bit ID of the source connection |
8035 |
++ * @payload_type: Payload type (KDBUS_PAYLOAD_*) |
8036 |
++ * @cookie: Userspace-supplied cookie, for the connection |
8037 |
++ * to identify its messages |
8038 |
++ * @timeout_ns: The time to wait for a message reply from the peer. |
8039 |
++ * If there is no reply, and the send command is |
8040 |
++ * executed asynchronously, a kernel-generated message |
8041 |
++ * with an attached KDBUS_ITEM_REPLY_TIMEOUT item |
8042 |
++ * is sent to @src_id. For synchronously executed send |
8043 |
++ * command, the value denotes the maximum time the call |
8044 |
++ * blocks to wait for a reply. The timeout is expected in |
8045 |
++ * nanoseconds and as absolute CLOCK_MONOTONIC value. |
8046 |
++ * @cookie_reply: A reply to the requesting message with the same |
8047 |
++ * cookie. The requesting connection can match its |
8048 |
++ * request and the reply with this value |
8049 |
++ * @items: A list of kdbus_items containing the message payload |
8050 |
++ */ |
8051 |
++struct kdbus_msg { |
8052 |
++ __u64 size; |
8053 |
++ __u64 flags; |
8054 |
++ __s64 priority; |
8055 |
++ __u64 dst_id; |
8056 |
++ __u64 src_id; |
8057 |
++ __u64 payload_type; |
8058 |
++ __u64 cookie; |
8059 |
++ union { |
8060 |
++ __u64 timeout_ns; |
8061 |
++ __u64 cookie_reply; |
8062 |
++ }; |
8063 |
++ struct kdbus_item items[0]; |
8064 |
++} __attribute__((__aligned__(8))); |
8065 |
++ |
8066 |
++/** |
8067 |
++ * struct kdbus_msg_info - returned message container |
8068 |
++ * @offset: Offset of kdbus_msg slice in pool |
8069 |
++ * @msg_size: Copy of the kdbus_msg.size field |
8070 |
++ * @return_flags: Command return flags, kernel → userspace |
8071 |
++ */ |
8072 |
++struct kdbus_msg_info { |
8073 |
++ __u64 offset; |
8074 |
++ __u64 msg_size; |
8075 |
++ __u64 return_flags; |
8076 |
++} __attribute__((__aligned__(8))); |
8077 |
++ |
8078 |
++/** |
8079 |
++ * enum kdbus_send_flags - flags for sending messages |
8080 |
++ * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to |
8081 |
++ * reply to this message. The |
8082 |
++ * KDBUS_CMD_SEND ioctl() will block |
8083 |
++ * until the reply is received, and |
8084 |
++ * reply in struct kdbus_cmd_send will |
8085 |
++ * yield the offset in the sender's pool |
8086 |
++ * where the reply can be found. |
8087 |
++ * This flag is only valid if |
8088 |
++ * @KDBUS_MSG_EXPECT_REPLY is set as well. |
8089 |
++ */ |
8090 |
++enum kdbus_send_flags { |
8091 |
++ KDBUS_SEND_SYNC_REPLY = 1ULL << 0, |
8092 |
++}; |
8093 |
++ |
8094 |
++/** |
8095 |
++ * struct kdbus_cmd_send - send message |
8096 |
++ * @size: Overall size of this structure |
8097 |
++ * @flags: Flags to change send behavior (KDBUS_SEND_*) |
8098 |
++ * @return_flags: Command return flags, kernel → userspace |
8099 |
++ * @msg_address: Storage address of the kdbus_msg to send |
8100 |
++ * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY |
8101 |
++ * was given |
8102 |
++ * @items: Additional items for this command |
8103 |
++ */ |
8104 |
++struct kdbus_cmd_send { |
8105 |
++ __u64 size; |
8106 |
++ __u64 flags; |
8107 |
++ __u64 return_flags; |
8108 |
++ __u64 msg_address; |
8109 |
++ struct kdbus_msg_info reply; |
8110 |
++ struct kdbus_item items[0]; |
8111 |
++} __attribute__((__aligned__(8))); |
8112 |
++ |
8113 |
++/** |
8114 |
++ * enum kdbus_recv_flags - flags for de-queuing messages |
8115 |
++ * @KDBUS_RECV_PEEK: Return the next queued message without |
8116 |
++ * actually de-queuing it, and without installing |
8117 |
++ * any file descriptors or other resources. It is |
8118 |
++ * usually used to determine the activating |
8119 |
++ * connection of a bus name. |
8120 |
++ * @KDBUS_RECV_DROP: Drop and free the next queued message and all |
8121 |
++ * its resources without actually receiving it. |
8122 |
++ * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or |
8123 |
++ * higher priority (lowest values); if not set, |
8124 |
++ * the priority value is ignored. |
8125 |
++ */ |
8126 |
++enum kdbus_recv_flags { |
8127 |
++ KDBUS_RECV_PEEK = 1ULL << 0, |
8128 |
++ KDBUS_RECV_DROP = 1ULL << 1, |
8129 |
++ KDBUS_RECV_USE_PRIORITY = 1ULL << 2, |
8130 |
++}; |
8131 |
++ |
8132 |
++/** |
8133 |
++ * enum kdbus_recv_return_flags - return flags for message receive commands |
8134 |
++ * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not |
8135 |
++ * be installed. These descriptors in |
8136 |
++ * KDBUS_ITEM_FDS will carry the value -1. |
8137 |
++ * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since |
8138 |
++ * the last time a message was received. |
8139 |
++ * The 'dropped_msgs' counter contains the |
8140 |
++ * number of messages dropped pool |
8141 |
++ * overflows or other missed broadcasts. |
8142 |
++ */ |
8143 |
++enum kdbus_recv_return_flags { |
8144 |
++ KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0, |
8145 |
++ KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1, |
8146 |
++}; |
8147 |
++ |
8148 |
++/** |
8149 |
++ * struct kdbus_cmd_recv - struct to de-queue a buffered message |
8150 |
++ * @size: Overall size of this object |
8151 |
++ * @flags: KDBUS_RECV_* flags, userspace → kernel |
8152 |
++ * @return_flags: Command return flags, kernel → userspace |
8153 |
++ * @priority: Minimum priority of the messages to de-queue. Lowest |
8154 |
++ * values have the highest priority. |
8155 |
++ * @dropped_msgs: In case there were any dropped messages since the last |
8156 |
++ * time a message was received, this will be set to the |
8157 |
++ * number of lost messages and |
8158 |
++ * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in |
8159 |
++ * 'return_flags'. This can only happen if the ioctl |
8160 |
++ * returns 0 or EAGAIN. |
8161 |
++ * @msg: Return storage for received message. |
8162 |
++ * @items: Additional items for this command. |
8163 |
++ * |
8164 |
++ * This struct is used with the KDBUS_CMD_RECV ioctl. |
8165 |
++ */ |
8166 |
++struct kdbus_cmd_recv { |
8167 |
++ __u64 size; |
8168 |
++ __u64 flags; |
8169 |
++ __u64 return_flags; |
8170 |
++ __s64 priority; |
8171 |
++ __u64 dropped_msgs; |
8172 |
++ struct kdbus_msg_info msg; |
8173 |
++ struct kdbus_item items[0]; |
8174 |
++} __attribute__((__aligned__(8))); |
8175 |
++ |
8176 |
++/** |
8177 |
++ * struct kdbus_cmd_free - struct to free a slice of memory in the pool |
8178 |
++ * @size: Overall size of this structure |
8179 |
++ * @flags: Flags for the free command, userspace → kernel |
8180 |
++ * @return_flags: Command return flags, kernel → userspace |
8181 |
++ * @offset: The offset of the memory slice, as returned by other |
8182 |
++ * ioctls |
8183 |
++ * @items: Additional items to modify the behavior |
8184 |
++ * |
8185 |
++ * This struct is used with the KDBUS_CMD_FREE ioctl. |
8186 |
++ */ |
8187 |
++struct kdbus_cmd_free { |
8188 |
++ __u64 size; |
8189 |
++ __u64 flags; |
8190 |
++ __u64 return_flags; |
8191 |
++ __u64 offset; |
8192 |
++ struct kdbus_item items[0]; |
8193 |
++} __attribute__((__aligned__(8))); |
8194 |
++ |
8195 |
++/** |
8196 |
++ * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello |
8197 |
++ * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of |
8198 |
++ * any passed file descriptors |
8199 |
++ * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers |
8200 |
++ * a well-know name for a process to be started |
8201 |
++ * when traffic arrives |
8202 |
++ * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers |
8203 |
++ * policy entries for a name. The provided name |
8204 |
++ * is not activated and not registered with the |
8205 |
++ * name database, it only allows unprivileged |
8206 |
++ * connections to acquire a name, talk or discover |
8207 |
++ * a service |
8208 |
++ * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor |
8209 |
++ * bus traffic |
8210 |
++ */ |
8211 |
++enum kdbus_hello_flags { |
8212 |
++ KDBUS_HELLO_ACCEPT_FD = 1ULL << 0, |
8213 |
++ KDBUS_HELLO_ACTIVATOR = 1ULL << 1, |
8214 |
++ KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2, |
8215 |
++ KDBUS_HELLO_MONITOR = 1ULL << 3, |
8216 |
++}; |
8217 |
++ |
8218 |
++/** |
8219 |
++ * struct kdbus_cmd_hello - struct to say hello to kdbus |
8220 |
++ * @size: The total size of the structure |
8221 |
++ * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel |
8222 |
++ * @return_flags: Command return flags, kernel → userspace |
8223 |
++ * @attach_flags_send: Mask of metadata to attach to each message sent |
8224 |
++ * off by this connection (KDBUS_ATTACH_*) |
8225 |
++ * @attach_flags_recv: Mask of metadata to attach to each message receieved |
8226 |
++ * by the new connection (KDBUS_ATTACH_*) |
8227 |
++ * @bus_flags: The flags field copied verbatim from the original |
8228 |
++ * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful |
8229 |
++ * to do negotiation of features of the payload that is |
8230 |
++ * transferred (kernel → userspace) |
8231 |
++ * @id: The ID of this connection (kernel → userspace) |
8232 |
++ * @pool_size: Size of the connection's buffer where the received |
8233 |
++ * messages are placed |
8234 |
++ * @offset: Pool offset where items are returned to report |
8235 |
++ * additional information about the bus and the newly |
8236 |
++ * created connection. |
8237 |
++ * @items_size: Size of buffer returned in the pool slice at @offset. |
8238 |
++ * @id128: Unique 128-bit ID of the bus (kernel → userspace) |
8239 |
++ * @items: A list of items |
8240 |
++ * |
8241 |
++ * This struct is used with the KDBUS_CMD_HELLO ioctl. |
8242 |
++ */ |
8243 |
++struct kdbus_cmd_hello { |
8244 |
++ __u64 size; |
8245 |
++ __u64 flags; |
8246 |
++ __u64 return_flags; |
8247 |
++ __u64 attach_flags_send; |
8248 |
++ __u64 attach_flags_recv; |
8249 |
++ __u64 bus_flags; |
8250 |
++ __u64 id; |
8251 |
++ __u64 pool_size; |
8252 |
++ __u64 offset; |
8253 |
++ __u64 items_size; |
8254 |
++ __u8 id128[16]; |
8255 |
++ struct kdbus_item items[0]; |
8256 |
++} __attribute__((__aligned__(8))); |
8257 |
++ |
8258 |
++/** |
8259 |
++ * struct kdbus_info - connection information |
8260 |
++ * @size: total size of the struct |
8261 |
++ * @id: 64bit object ID |
8262 |
++ * @flags: object creation flags |
8263 |
++ * @items: list of items |
8264 |
++ * |
8265 |
++ * Note that the user is responsible for freeing the allocated memory with |
8266 |
++ * the KDBUS_CMD_FREE ioctl. |
8267 |
++ */ |
8268 |
++struct kdbus_info { |
8269 |
++ __u64 size; |
8270 |
++ __u64 id; |
8271 |
++ __u64 flags; |
8272 |
++ struct kdbus_item items[0]; |
8273 |
++} __attribute__((__aligned__(8))); |
8274 |
++ |
8275 |
++/** |
8276 |
++ * enum kdbus_list_flags - what to include into the returned list |
8277 |
++ * @KDBUS_LIST_UNIQUE: active connections |
8278 |
++ * @KDBUS_LIST_ACTIVATORS: activator connections |
8279 |
++ * @KDBUS_LIST_NAMES: known well-known names |
8280 |
++ * @KDBUS_LIST_QUEUED: queued-up names |
8281 |
++ */ |
8282 |
++enum kdbus_list_flags { |
8283 |
++ KDBUS_LIST_UNIQUE = 1ULL << 0, |
8284 |
++ KDBUS_LIST_NAMES = 1ULL << 1, |
8285 |
++ KDBUS_LIST_ACTIVATORS = 1ULL << 2, |
8286 |
++ KDBUS_LIST_QUEUED = 1ULL << 3, |
8287 |
++}; |
8288 |
++ |
8289 |
++/** |
8290 |
++ * struct kdbus_cmd_list - list connections |
8291 |
++ * @size: overall size of this object |
8292 |
++ * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel |
8293 |
++ * @return_flags: command return flags, kernel → userspace |
8294 |
++ * @offset: Offset in the caller's pool buffer where an array of |
8295 |
++ * kdbus_info objects is stored. |
8296 |
++ * The user must use KDBUS_CMD_FREE to free the |
8297 |
++ * allocated memory. |
8298 |
++ * @list_size: size of returned list in bytes |
8299 |
++ * @items: Items for the command. Reserved for future use. |
8300 |
++ * |
8301 |
++ * This structure is used with the KDBUS_CMD_LIST ioctl. |
8302 |
++ */ |
8303 |
++struct kdbus_cmd_list { |
8304 |
++ __u64 size; |
8305 |
++ __u64 flags; |
8306 |
++ __u64 return_flags; |
8307 |
++ __u64 offset; |
8308 |
++ __u64 list_size; |
8309 |
++ struct kdbus_item items[0]; |
8310 |
++} __attribute__((__aligned__(8))); |
8311 |
++ |
8312 |
++/** |
8313 |
++ * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl |
8314 |
++ * @size: The total size of the struct |
8315 |
++ * @flags: Flags for this ioctl, userspace → kernel |
8316 |
++ * @return_flags: Command return flags, kernel → userspace |
8317 |
++ * @id: The 64-bit ID of the connection. If set to zero, passing |
8318 |
++ * @name is required. kdbus will look up the name to |
8319 |
++ * determine the ID in this case. |
8320 |
++ * @attach_flags: Set of attach flags to specify the set of information |
8321 |
++ * to receive, userspace → kernel |
8322 |
++ * @offset: Returned offset in the caller's pool buffer where the |
8323 |
++ * kdbus_info struct result is stored. The user must |
8324 |
++ * use KDBUS_CMD_FREE to free the allocated memory. |
8325 |
++ * @info_size: Output buffer to report size of data at @offset. |
8326 |
++ * @items: The optional item list, containing the |
8327 |
++ * well-known name to look up as a KDBUS_ITEM_NAME. |
8328 |
++ * Only needed in case @id is zero. |
8329 |
++ * |
8330 |
++ * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will |
8331 |
++ * tell the user the offset in the connection pool buffer at which to find the |
8332 |
++ * result in a struct kdbus_info. |
8333 |
++ */ |
8334 |
++struct kdbus_cmd_info { |
8335 |
++ __u64 size; |
8336 |
++ __u64 flags; |
8337 |
++ __u64 return_flags; |
8338 |
++ __u64 id; |
8339 |
++ __u64 attach_flags; |
8340 |
++ __u64 offset; |
8341 |
++ __u64 info_size; |
8342 |
++ struct kdbus_item items[0]; |
8343 |
++} __attribute__((__aligned__(8))); |
8344 |
++ |
8345 |
++/** |
8346 |
++ * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl |
8347 |
++ * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already |
8348 |
++ * exists, remove them before installing the new |
8349 |
++ * matches. |
8350 |
++ */ |
8351 |
++enum kdbus_cmd_match_flags { |
8352 |
++ KDBUS_MATCH_REPLACE = 1ULL << 0, |
8353 |
++}; |
8354 |
++ |
8355 |
++/** |
8356 |
++ * struct kdbus_cmd_match - struct to add or remove matches |
8357 |
++ * @size: The total size of the struct |
8358 |
++ * @flags: Flags for match command (KDBUS_MATCH_*), |
8359 |
++ * userspace → kernel |
8360 |
++ * @return_flags: Command return flags, kernel → userspace |
8361 |
++ * @cookie: Userspace supplied cookie. When removing, the cookie |
8362 |
++ * identifies the match to remove |
8363 |
++ * @items: A list of items for additional information |
8364 |
++ * |
8365 |
++ * This structure is used with the KDBUS_CMD_MATCH_ADD and |
8366 |
++ * KDBUS_CMD_MATCH_REMOVE ioctl. |
8367 |
++ */ |
8368 |
++struct kdbus_cmd_match { |
8369 |
++ __u64 size; |
8370 |
++ __u64 flags; |
8371 |
++ __u64 return_flags; |
8372 |
++ __u64 cookie; |
8373 |
++ struct kdbus_item items[0]; |
8374 |
++} __attribute__((__aligned__(8))); |
8375 |
++ |
8376 |
++/** |
8377 |
++ * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE |
8378 |
++ * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible |
8379 |
++ * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible |
8380 |
++ */ |
8381 |
++enum kdbus_make_flags { |
8382 |
++ KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0, |
8383 |
++ KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1, |
8384 |
++}; |
8385 |
++ |
8386 |
++/** |
8387 |
++ * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE |
8388 |
++ * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections |
8389 |
++ * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name |
8390 |
++ * @KDBUS_NAME_QUEUE: Name should be queued if busy |
8391 |
++ * @KDBUS_NAME_IN_QUEUE: Name is queued |
8392 |
++ * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection |
8393 |
++ */ |
8394 |
++enum kdbus_name_flags { |
8395 |
++ KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0, |
8396 |
++ KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1, |
8397 |
++ KDBUS_NAME_QUEUE = 1ULL << 2, |
8398 |
++ KDBUS_NAME_IN_QUEUE = 1ULL << 3, |
8399 |
++ KDBUS_NAME_ACTIVATOR = 1ULL << 4, |
8400 |
++}; |
8401 |
++ |
8402 |
++/** |
8403 |
++ * struct kdbus_cmd - generic ioctl payload |
8404 |
++ * @size: Overall size of this structure |
8405 |
++ * @flags: Flags for this ioctl, userspace → kernel |
8406 |
++ * @return_flags: Ioctl return flags, kernel → userspace |
8407 |
++ * @items: Additional items to modify the behavior |
8408 |
++ * |
8409 |
++ * This is a generic ioctl payload object. It's used by all ioctls that only |
8410 |
++ * take flags and items as input. |
8411 |
++ */ |
8412 |
++struct kdbus_cmd { |
8413 |
++ __u64 size; |
8414 |
++ __u64 flags; |
8415 |
++ __u64 return_flags; |
8416 |
++ struct kdbus_item items[0]; |
8417 |
++} __attribute__((__aligned__(8))); |
8418 |
++ |
8419 |
++/** |
8420 |
++ * Ioctl API |
8421 |
++ * |
8422 |
++ * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command |
8423 |
++ * creates a new bus with the specified |
8424 |
++ * name. The bus is immediately shut down and |
8425 |
++ * cleaned up when the opened file descriptor is |
8426 |
++ * closed. |
8427 |
++ * |
8428 |
++ * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to |
8429 |
++ * the bus. Such endpoints usually carry a more |
8430 |
++ * restrictive policy and grant restricted access |
8431 |
++ * to specific applications. |
8432 |
++ * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used |
8433 |
++ * to update the policy. |
8434 |
++ * |
8435 |
++ * KDBUS_CMD_HELLO: By opening the bus node, a connection is |
8436 |
++ * created. After a HELLO the opened connection |
8437 |
++ * becomes an active peer on the bus. |
8438 |
++ * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to |
8439 |
++ * update the metadata subscription mask and |
8440 |
++ * policy. |
8441 |
++ * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no |
8442 |
++ * messages queued up in the connection's pool, |
8443 |
++ * the call succeeds, and the handle is rendered |
8444 |
++ * unusable. Otherwise, -EBUSY is returned without |
8445 |
++ * any further side-effects. |
8446 |
++ * KDBUS_CMD_FREE: Release the allocated memory in the receiver's |
8447 |
++ * pool. |
8448 |
++ * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the |
8449 |
++ * initial creator of the connection. The data was |
8450 |
++ * stored at registration time and does not |
8451 |
++ * necessarily represent the connected process or |
8452 |
++ * the actual state of the process. |
8453 |
++ * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus |
8454 |
++ * a connection is attached to. |
8455 |
++ * |
8456 |
++ * KDBUS_CMD_SEND: Send a message and pass data from userspace to |
8457 |
++ * the kernel. |
8458 |
++ * KDBUS_CMD_RECV: Receive a message from the kernel which is |
8459 |
++ * placed in the receiver's pool. |
8460 |
++ * |
8461 |
++ * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with |
8462 |
++ * the connection. Well-known names are used to |
8463 |
++ * address a peer on the bus. |
8464 |
++ * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection |
8465 |
++ * currently owns. |
8466 |
++ * KDBUS_CMD_LIST: Retrieve the list of all currently registered |
8467 |
++ * well-known and unique names. |
8468 |
++ * |
8469 |
++ * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should |
8470 |
++ * be delivered to the connection. |
8471 |
++ * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages. |
8472 |
++ */ |
8473 |
++enum kdbus_ioctl_type { |
8474 |
++ /* bus owner (00-0f) */ |
8475 |
++ KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00, |
8476 |
++ struct kdbus_cmd), |
8477 |
++ |
8478 |
++ /* endpoint owner (10-1f) */ |
8479 |
++ KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10, |
8480 |
++ struct kdbus_cmd), |
8481 |
++ KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11, |
8482 |
++ struct kdbus_cmd), |
8483 |
++ |
8484 |
++ /* connection owner (80-ff) */ |
8485 |
++ KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80, |
8486 |
++ struct kdbus_cmd_hello), |
8487 |
++ KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81, |
8488 |
++ struct kdbus_cmd), |
8489 |
++ KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82, |
8490 |
++ struct kdbus_cmd), |
8491 |
++ KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83, |
8492 |
++ struct kdbus_cmd_free), |
8493 |
++ KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84, |
8494 |
++ struct kdbus_cmd_info), |
8495 |
++ KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85, |
8496 |
++ struct kdbus_cmd_info), |
8497 |
++ KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86, |
8498 |
++ struct kdbus_cmd_list), |
8499 |
++ |
8500 |
++ KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90, |
8501 |
++ struct kdbus_cmd_send), |
8502 |
++ KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91, |
8503 |
++ struct kdbus_cmd_recv), |
8504 |
++ |
8505 |
++ KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0, |
8506 |
++ struct kdbus_cmd), |
8507 |
++ KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1, |
8508 |
++ struct kdbus_cmd), |
8509 |
++ |
8510 |
++ KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0, |
8511 |
++ struct kdbus_cmd_match), |
8512 |
++ KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1, |
8513 |
++ struct kdbus_cmd_match), |
8514 |
++}; |
8515 |
++ |
8516 |
++#endif /* _UAPI_KDBUS_H_ */ |
8517 |
+diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h |
8518 |
+index 7d664ea..1cf05c0 100644 |
8519 |
+--- a/include/uapi/linux/magic.h |
8520 |
++++ b/include/uapi/linux/magic.h |
8521 |
+@@ -74,4 +74,6 @@ |
8522 |
+ #define BTRFS_TEST_MAGIC 0x73727279 |
8523 |
+ #define NSFS_MAGIC 0x6e736673 |
8524 |
+ |
8525 |
++#define KDBUS_SUPER_MAGIC 0x44427573 |
8526 |
++ |
8527 |
+ #endif /* __LINUX_MAGIC_H__ */ |
8528 |
+diff --git a/init/Kconfig b/init/Kconfig |
8529 |
+index f5dbc6d..6bda631 100644 |
8530 |
+--- a/init/Kconfig |
8531 |
++++ b/init/Kconfig |
8532 |
+@@ -261,6 +261,19 @@ config POSIX_MQUEUE_SYSCTL |
8533 |
+ depends on SYSCTL |
8534 |
+ default y |
8535 |
+ |
8536 |
++config KDBUS |
8537 |
++ tristate "kdbus interprocess communication" |
8538 |
++ depends on TMPFS |
8539 |
++ help |
8540 |
++ D-Bus is a system for low-latency, low-overhead, easy to use |
8541 |
++ interprocess communication (IPC). |
8542 |
++ |
8543 |
++ See the man-pages and HTML files in Documentation/kdbus/ |
8544 |
++ that are generated by 'make mandocs' and 'make htmldocs'. |
8545 |
++ |
8546 |
++ If you have an ordinary machine, select M here. The module |
8547 |
++ will be called kdbus. |
8548 |
++ |
8549 |
+ config CROSS_MEMORY_ATTACH |
8550 |
+ bool "Enable process_vm_readv/writev syscalls" |
8551 |
+ depends on MMU |
8552 |
+diff --git a/ipc/Makefile b/ipc/Makefile |
8553 |
+index 86c7300..68ec416 100644 |
8554 |
+--- a/ipc/Makefile |
8555 |
++++ b/ipc/Makefile |
8556 |
+@@ -9,4 +9,4 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
8557 |
+ obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
8558 |
+ obj-$(CONFIG_IPC_NS) += namespace.o |
8559 |
+ obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o |
8560 |
+- |
8561 |
++obj-$(CONFIG_KDBUS) += kdbus/ |
8562 |
+diff --git a/ipc/kdbus/Makefile b/ipc/kdbus/Makefile |
8563 |
+new file mode 100644 |
8564 |
+index 0000000..7ee9271 |
8565 |
+--- /dev/null |
8566 |
++++ b/ipc/kdbus/Makefile |
8567 |
+@@ -0,0 +1,22 @@ |
8568 |
++kdbus-y := \ |
8569 |
++ bus.o \ |
8570 |
++ connection.o \ |
8571 |
++ endpoint.o \ |
8572 |
++ fs.o \ |
8573 |
++ handle.o \ |
8574 |
++ item.o \ |
8575 |
++ main.o \ |
8576 |
++ match.o \ |
8577 |
++ message.o \ |
8578 |
++ metadata.o \ |
8579 |
++ names.o \ |
8580 |
++ node.o \ |
8581 |
++ notify.o \ |
8582 |
++ domain.o \ |
8583 |
++ policy.o \ |
8584 |
++ pool.o \ |
8585 |
++ reply.o \ |
8586 |
++ queue.o \ |
8587 |
++ util.o |
8588 |
++ |
8589 |
++obj-$(CONFIG_KDBUS) += kdbus.o |
8590 |
+diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c |
8591 |
+new file mode 100644 |
8592 |
+index 0000000..9d0679e |
8593 |
+--- /dev/null |
8594 |
++++ b/ipc/kdbus/bus.c |
8595 |
+@@ -0,0 +1,560 @@ |
8596 |
++/* |
8597 |
++ * Copyright (C) 2013-2015 Kay Sievers |
8598 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
8599 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
8600 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
8601 |
++ * Copyright (C) 2013-2015 Linux Foundation |
8602 |
++ * Copyright (C) 2014-2015 Djalal Harouni |
8603 |
++ * |
8604 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
8605 |
++ * the terms of the GNU Lesser General Public License as published by the |
8606 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
8607 |
++ * your option) any later version. |
8608 |
++ */ |
8609 |
++ |
8610 |
++#include <linux/fs.h> |
8611 |
++#include <linux/hashtable.h> |
8612 |
++#include <linux/init.h> |
8613 |
++#include <linux/module.h> |
8614 |
++#include <linux/random.h> |
8615 |
++#include <linux/sched.h> |
8616 |
++#include <linux/sizes.h> |
8617 |
++#include <linux/slab.h> |
8618 |
++#include <linux/uaccess.h> |
8619 |
++#include <linux/uio.h> |
8620 |
++ |
8621 |
++#include "bus.h" |
8622 |
++#include "notify.h" |
8623 |
++#include "connection.h" |
8624 |
++#include "domain.h" |
8625 |
++#include "endpoint.h" |
8626 |
++#include "handle.h" |
8627 |
++#include "item.h" |
8628 |
++#include "match.h" |
8629 |
++#include "message.h" |
8630 |
++#include "metadata.h" |
8631 |
++#include "names.h" |
8632 |
++#include "policy.h" |
8633 |
++#include "util.h" |
8634 |
++ |
8635 |
++static void kdbus_bus_free(struct kdbus_node *node) |
8636 |
++{ |
8637 |
++ struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node); |
8638 |
++ |
8639 |
++ WARN_ON(!list_empty(&bus->monitors_list)); |
8640 |
++ WARN_ON(!hash_empty(bus->conn_hash)); |
8641 |
++ |
8642 |
++ kdbus_notify_free(bus); |
8643 |
++ |
8644 |
++ kdbus_user_unref(bus->creator); |
8645 |
++ kdbus_name_registry_free(bus->name_registry); |
8646 |
++ kdbus_domain_unref(bus->domain); |
8647 |
++ kdbus_policy_db_clear(&bus->policy_db); |
8648 |
++ kdbus_meta_proc_unref(bus->creator_meta); |
8649 |
++ kfree(bus); |
8650 |
++} |
8651 |
++ |
8652 |
++static void kdbus_bus_release(struct kdbus_node *node, bool was_active) |
8653 |
++{ |
8654 |
++ struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node); |
8655 |
++ |
8656 |
++ if (was_active) |
8657 |
++ atomic_dec(&bus->creator->buses); |
8658 |
++} |
8659 |
++ |
8660 |
++static struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain, |
8661 |
++ const char *name, |
8662 |
++ struct kdbus_bloom_parameter *bloom, |
8663 |
++ const u64 *pattach_owner, |
8664 |
++ const u64 *pattach_recv, |
8665 |
++ u64 flags, kuid_t uid, kgid_t gid) |
8666 |
++{ |
8667 |
++ struct kdbus_bus *b; |
8668 |
++ u64 attach_owner; |
8669 |
++ u64 attach_recv; |
8670 |
++ int ret; |
8671 |
++ |
8672 |
++ if (bloom->size < 8 || bloom->size > KDBUS_BUS_BLOOM_MAX_SIZE || |
8673 |
++ !KDBUS_IS_ALIGNED8(bloom->size) || bloom->n_hash < 1) |
8674 |
++ return ERR_PTR(-EINVAL); |
8675 |
++ |
8676 |
++ ret = kdbus_sanitize_attach_flags(pattach_recv ? *pattach_recv : 0, |
8677 |
++ &attach_recv); |
8678 |
++ if (ret < 0) |
8679 |
++ return ERR_PTR(ret); |
8680 |
++ |
8681 |
++ ret = kdbus_sanitize_attach_flags(pattach_owner ? *pattach_owner : 0, |
8682 |
++ &attach_owner); |
8683 |
++ if (ret < 0) |
8684 |
++ return ERR_PTR(ret); |
8685 |
++ |
8686 |
++ ret = kdbus_verify_uid_prefix(name, domain->user_namespace, uid); |
8687 |
++ if (ret < 0) |
8688 |
++ return ERR_PTR(ret); |
8689 |
++ |
8690 |
++ b = kzalloc(sizeof(*b), GFP_KERNEL); |
8691 |
++ if (!b) |
8692 |
++ return ERR_PTR(-ENOMEM); |
8693 |
++ |
8694 |
++ kdbus_node_init(&b->node, KDBUS_NODE_BUS); |
8695 |
++ |
8696 |
++ b->node.free_cb = kdbus_bus_free; |
8697 |
++ b->node.release_cb = kdbus_bus_release; |
8698 |
++ b->node.uid = uid; |
8699 |
++ b->node.gid = gid; |
8700 |
++ b->node.mode = S_IRUSR | S_IXUSR; |
8701 |
++ |
8702 |
++ if (flags & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
8703 |
++ b->node.mode |= S_IRGRP | S_IXGRP; |
8704 |
++ if (flags & KDBUS_MAKE_ACCESS_WORLD) |
8705 |
++ b->node.mode |= S_IROTH | S_IXOTH; |
8706 |
++ |
8707 |
++ b->id = atomic64_inc_return(&domain->last_id); |
8708 |
++ b->bus_flags = flags; |
8709 |
++ b->attach_flags_req = attach_recv; |
8710 |
++ b->attach_flags_owner = attach_owner; |
8711 |
++ generate_random_uuid(b->id128); |
8712 |
++ b->bloom = *bloom; |
8713 |
++ b->domain = kdbus_domain_ref(domain); |
8714 |
++ |
8715 |
++ kdbus_policy_db_init(&b->policy_db); |
8716 |
++ |
8717 |
++ init_rwsem(&b->conn_rwlock); |
8718 |
++ hash_init(b->conn_hash); |
8719 |
++ INIT_LIST_HEAD(&b->monitors_list); |
8720 |
++ |
8721 |
++ INIT_LIST_HEAD(&b->notify_list); |
8722 |
++ spin_lock_init(&b->notify_lock); |
8723 |
++ mutex_init(&b->notify_flush_lock); |
8724 |
++ |
8725 |
++ ret = kdbus_node_link(&b->node, &domain->node, name); |
8726 |
++ if (ret < 0) |
8727 |
++ goto exit_unref; |
8728 |
++ |
8729 |
++ /* cache the metadata/credentials of the creator */ |
8730 |
++ b->creator_meta = kdbus_meta_proc_new(); |
8731 |
++ if (IS_ERR(b->creator_meta)) { |
8732 |
++ ret = PTR_ERR(b->creator_meta); |
8733 |
++ b->creator_meta = NULL; |
8734 |
++ goto exit_unref; |
8735 |
++ } |
8736 |
++ |
8737 |
++ ret = kdbus_meta_proc_collect(b->creator_meta, |
8738 |
++ KDBUS_ATTACH_CREDS | |
8739 |
++ KDBUS_ATTACH_PIDS | |
8740 |
++ KDBUS_ATTACH_AUXGROUPS | |
8741 |
++ KDBUS_ATTACH_TID_COMM | |
8742 |
++ KDBUS_ATTACH_PID_COMM | |
8743 |
++ KDBUS_ATTACH_EXE | |
8744 |
++ KDBUS_ATTACH_CMDLINE | |
8745 |
++ KDBUS_ATTACH_CGROUP | |
8746 |
++ KDBUS_ATTACH_CAPS | |
8747 |
++ KDBUS_ATTACH_SECLABEL | |
8748 |
++ KDBUS_ATTACH_AUDIT); |
8749 |
++ if (ret < 0) |
8750 |
++ goto exit_unref; |
8751 |
++ |
8752 |
++ b->name_registry = kdbus_name_registry_new(); |
8753 |
++ if (IS_ERR(b->name_registry)) { |
8754 |
++ ret = PTR_ERR(b->name_registry); |
8755 |
++ b->name_registry = NULL; |
8756 |
++ goto exit_unref; |
8757 |
++ } |
8758 |
++ |
8759 |
++ /* |
8760 |
++ * Bus-limits of the creator are accounted on its real UID, just like |
8761 |
++ * all other per-user limits. |
8762 |
++ */ |
8763 |
++ b->creator = kdbus_user_lookup(domain, current_uid()); |
8764 |
++ if (IS_ERR(b->creator)) { |
8765 |
++ ret = PTR_ERR(b->creator); |
8766 |
++ b->creator = NULL; |
8767 |
++ goto exit_unref; |
8768 |
++ } |
8769 |
++ |
8770 |
++ return b; |
8771 |
++ |
8772 |
++exit_unref: |
8773 |
++ kdbus_node_deactivate(&b->node); |
8774 |
++ kdbus_node_unref(&b->node); |
8775 |
++ return ERR_PTR(ret); |
8776 |
++} |
8777 |
++ |
8778 |
++/** |
8779 |
++ * kdbus_bus_ref() - increase the reference counter of a kdbus_bus |
8780 |
++ * @bus: The bus to reference |
8781 |
++ * |
8782 |
++ * Every user of a bus, except for its creator, must add a reference to the |
8783 |
++ * kdbus_bus using this function. |
8784 |
++ * |
8785 |
++ * Return: the bus itself |
8786 |
++ */ |
8787 |
++struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus) |
8788 |
++{ |
8789 |
++ if (bus) |
8790 |
++ kdbus_node_ref(&bus->node); |
8791 |
++ return bus; |
8792 |
++} |
8793 |
++ |
8794 |
++/** |
8795 |
++ * kdbus_bus_unref() - decrease the reference counter of a kdbus_bus |
8796 |
++ * @bus: The bus to unref |
8797 |
++ * |
8798 |
++ * Release a reference. If the reference count drops to 0, the bus will be |
8799 |
++ * freed. |
8800 |
++ * |
8801 |
++ * Return: NULL |
8802 |
++ */ |
8803 |
++struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus) |
8804 |
++{ |
8805 |
++ if (bus) |
8806 |
++ kdbus_node_unref(&bus->node); |
8807 |
++ return NULL; |
8808 |
++} |
8809 |
++ |
8810 |
++/** |
8811 |
++ * kdbus_bus_find_conn_by_id() - find a connection with a given id |
8812 |
++ * @bus: The bus to look for the connection |
8813 |
++ * @id: The 64-bit connection id |
8814 |
++ * |
8815 |
++ * Looks up a connection with a given id. The returned connection |
8816 |
++ * is ref'ed, and needs to be unref'ed by the user. Returns NULL if |
8817 |
++ * the connection can't be found. |
8818 |
++ */ |
8819 |
++struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id) |
8820 |
++{ |
8821 |
++ struct kdbus_conn *conn, *found = NULL; |
8822 |
++ |
8823 |
++ down_read(&bus->conn_rwlock); |
8824 |
++ hash_for_each_possible(bus->conn_hash, conn, hentry, id) |
8825 |
++ if (conn->id == id) { |
8826 |
++ found = kdbus_conn_ref(conn); |
8827 |
++ break; |
8828 |
++ } |
8829 |
++ up_read(&bus->conn_rwlock); |
8830 |
++ |
8831 |
++ return found; |
8832 |
++} |
8833 |
++ |
8834 |
++/** |
8835 |
++ * kdbus_bus_broadcast() - send a message to all subscribed connections |
8836 |
++ * @bus: The bus the connections are connected to |
8837 |
++ * @conn_src: The source connection, may be %NULL for kernel notifications |
8838 |
++ * @kmsg: The message to send. |
8839 |
++ * |
8840 |
++ * Send @kmsg to all connections that are currently active on the bus. |
8841 |
++ * Connections must still have matches installed in order to let the message |
8842 |
++ * pass. |
8843 |
++ * |
8844 |
++ * The caller must hold the name-registry lock of @bus. |
8845 |
++ */ |
8846 |
++void kdbus_bus_broadcast(struct kdbus_bus *bus, |
8847 |
++ struct kdbus_conn *conn_src, |
8848 |
++ struct kdbus_kmsg *kmsg) |
8849 |
++{ |
8850 |
++ struct kdbus_conn *conn_dst; |
8851 |
++ unsigned int i; |
8852 |
++ int ret; |
8853 |
++ |
8854 |
++ lockdep_assert_held(&bus->name_registry->rwlock); |
8855 |
++ |
8856 |
++ /* |
8857 |
++ * Make sure broadcast are queued on monitors before we send it out to |
8858 |
++ * anyone else. Otherwise, connections might react to broadcasts before |
8859 |
++ * the monitor gets the broadcast queued. In the worst case, the |
8860 |
++ * monitor sees a reaction to the broadcast before the broadcast itself. |
8861 |
++ * We don't give ordering guarantees across connections (and monitors |
8862 |
++ * can re-construct order via sequence numbers), but we should at least |
8863 |
++ * try to avoid re-ordering for monitors. |
8864 |
++ */ |
8865 |
++ kdbus_bus_eavesdrop(bus, conn_src, kmsg); |
8866 |
++ |
8867 |
++ down_read(&bus->conn_rwlock); |
8868 |
++ hash_for_each(bus->conn_hash, i, conn_dst, hentry) { |
8869 |
++ if (conn_dst->id == kmsg->msg.src_id) |
8870 |
++ continue; |
8871 |
++ if (!kdbus_conn_is_ordinary(conn_dst)) |
8872 |
++ continue; |
8873 |
++ |
8874 |
++ /* |
8875 |
++ * Check if there is a match for the kmsg object in |
8876 |
++ * the destination connection match db |
8877 |
++ */ |
8878 |
++ if (!kdbus_match_db_match_kmsg(conn_dst->match_db, conn_src, |
8879 |
++ kmsg)) |
8880 |
++ continue; |
8881 |
++ |
8882 |
++ if (conn_src) { |
8883 |
++ u64 attach_flags; |
8884 |
++ |
8885 |
++ /* |
8886 |
++ * Anyone can send broadcasts, as they have no |
8887 |
++ * destination. But a receiver needs TALK access to |
8888 |
++ * the sender in order to receive broadcasts. |
8889 |
++ */ |
8890 |
++ if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src)) |
8891 |
++ continue; |
8892 |
++ |
8893 |
++ attach_flags = kdbus_meta_calc_attach_flags(conn_src, |
8894 |
++ conn_dst); |
8895 |
++ |
8896 |
++ /* |
8897 |
++ * Keep sending messages even if we cannot acquire the |
8898 |
++ * requested metadata. It's up to the receiver to drop |
8899 |
++ * messages that lack expected metadata. |
8900 |
++ */ |
8901 |
++ if (!conn_src->faked_meta) |
8902 |
++ kdbus_meta_proc_collect(kmsg->proc_meta, |
8903 |
++ attach_flags); |
8904 |
++ kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src, |
8905 |
++ attach_flags); |
8906 |
++ } else { |
8907 |
++ /* |
8908 |
++ * Check if there is a policy db that prevents the |
8909 |
++ * destination connection from receiving this kernel |
8910 |
++ * notification |
8911 |
++ */ |
8912 |
++ if (!kdbus_conn_policy_see_notification(conn_dst, NULL, |
8913 |
++ kmsg)) |
8914 |
++ continue; |
8915 |
++ } |
8916 |
++ |
8917 |
++ ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL); |
8918 |
++ if (ret < 0) |
8919 |
++ kdbus_conn_lost_message(conn_dst); |
8920 |
++ } |
8921 |
++ up_read(&bus->conn_rwlock); |
8922 |
++} |
8923 |
++ |
8924 |
++/** |
8925 |
++ * kdbus_bus_eavesdrop() - send a message to all subscribed monitors |
8926 |
++ * @bus: The bus the monitors are connected to |
8927 |
++ * @conn_src: The source connection, may be %NULL for kernel notifications |
8928 |
++ * @kmsg: The message to send. |
8929 |
++ * |
8930 |
++ * Send @kmsg to all monitors that are currently active on the bus. Monitors |
8931 |
++ * must still have matches installed in order to let the message pass. |
8932 |
++ * |
8933 |
++ * The caller must hold the name-registry lock of @bus. |
8934 |
++ */ |
8935 |
++void kdbus_bus_eavesdrop(struct kdbus_bus *bus, |
8936 |
++ struct kdbus_conn *conn_src, |
8937 |
++ struct kdbus_kmsg *kmsg) |
8938 |
++{ |
8939 |
++ struct kdbus_conn *conn_dst; |
8940 |
++ int ret; |
8941 |
++ |
8942 |
++ /* |
8943 |
++ * Monitor connections get all messages; ignore possible errors |
8944 |
++ * when sending messages to monitor connections. |
8945 |
++ */ |
8946 |
++ |
8947 |
++ lockdep_assert_held(&bus->name_registry->rwlock); |
8948 |
++ |
8949 |
++ down_read(&bus->conn_rwlock); |
8950 |
++ list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) { |
8951 |
++ /* |
8952 |
++ * Collect metadata requested by the destination connection. |
8953 |
++ * Ignore errors, as receivers need to check metadata |
8954 |
++ * availability, anyway. So it's still better to send messages |
8955 |
++ * that lack data, than to skip it entirely. |
8956 |
++ */ |
8957 |
++ if (conn_src) { |
8958 |
++ u64 attach_flags; |
8959 |
++ |
8960 |
++ attach_flags = kdbus_meta_calc_attach_flags(conn_src, |
8961 |
++ conn_dst); |
8962 |
++ if (!conn_src->faked_meta) |
8963 |
++ kdbus_meta_proc_collect(kmsg->proc_meta, |
8964 |
++ attach_flags); |
8965 |
++ kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src, |
8966 |
++ attach_flags); |
8967 |
++ } |
8968 |
++ |
8969 |
++ ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL); |
8970 |
++ if (ret < 0) |
8971 |
++ kdbus_conn_lost_message(conn_dst); |
8972 |
++ } |
8973 |
++ up_read(&bus->conn_rwlock); |
8974 |
++} |
8975 |
++ |
8976 |
++/** |
8977 |
++ * kdbus_cmd_bus_make() - handle KDBUS_CMD_BUS_MAKE |
8978 |
++ * @domain: domain to operate on |
8979 |
++ * @argp: command payload |
8980 |
++ * |
8981 |
++ * Return: Newly created bus on success, ERR_PTR on failure. |
8982 |
++ */ |
8983 |
++struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, |
8984 |
++ void __user *argp) |
8985 |
++{ |
8986 |
++ struct kdbus_bus *bus = NULL; |
8987 |
++ struct kdbus_cmd *cmd; |
8988 |
++ struct kdbus_ep *ep = NULL; |
8989 |
++ int ret; |
8990 |
++ |
8991 |
++ struct kdbus_arg argv[] = { |
8992 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
8993 |
++ { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, |
8994 |
++ { .type = KDBUS_ITEM_BLOOM_PARAMETER, .mandatory = true }, |
8995 |
++ { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND }, |
8996 |
++ { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV }, |
8997 |
++ }; |
8998 |
++ struct kdbus_args args = { |
8999 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
9000 |
++ KDBUS_MAKE_ACCESS_GROUP | |
9001 |
++ KDBUS_MAKE_ACCESS_WORLD, |
9002 |
++ .argv = argv, |
9003 |
++ .argc = ARRAY_SIZE(argv), |
9004 |
++ }; |
9005 |
++ |
9006 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
9007 |
++ if (ret < 0) |
9008 |
++ return ERR_PTR(ret); |
9009 |
++ if (ret > 0) |
9010 |
++ return NULL; |
9011 |
++ |
9012 |
++ bus = kdbus_bus_new(domain, |
9013 |
++ argv[1].item->str, &argv[2].item->bloom_parameter, |
9014 |
++ argv[3].item ? argv[3].item->data64 : NULL, |
9015 |
++ argv[4].item ? argv[4].item->data64 : NULL, |
9016 |
++ cmd->flags, current_euid(), current_egid()); |
9017 |
++ if (IS_ERR(bus)) { |
9018 |
++ ret = PTR_ERR(bus); |
9019 |
++ bus = NULL; |
9020 |
++ goto exit; |
9021 |
++ } |
9022 |
++ |
9023 |
++ if (atomic_inc_return(&bus->creator->buses) > KDBUS_USER_MAX_BUSES) { |
9024 |
++ atomic_dec(&bus->creator->buses); |
9025 |
++ ret = -EMFILE; |
9026 |
++ goto exit; |
9027 |
++ } |
9028 |
++ |
9029 |
++ if (!kdbus_node_activate(&bus->node)) { |
9030 |
++ atomic_dec(&bus->creator->buses); |
9031 |
++ ret = -ESHUTDOWN; |
9032 |
++ goto exit; |
9033 |
++ } |
9034 |
++ |
9035 |
++ ep = kdbus_ep_new(bus, "bus", cmd->flags, bus->node.uid, bus->node.gid, |
9036 |
++ false); |
9037 |
++ if (IS_ERR(ep)) { |
9038 |
++ ret = PTR_ERR(ep); |
9039 |
++ ep = NULL; |
9040 |
++ goto exit; |
9041 |
++ } |
9042 |
++ |
9043 |
++ if (!kdbus_node_activate(&ep->node)) { |
9044 |
++ ret = -ESHUTDOWN; |
9045 |
++ goto exit; |
9046 |
++ } |
9047 |
++ |
9048 |
++ /* |
9049 |
++ * Drop our own reference, effectively causing the endpoint to be |
9050 |
++ * deactivated and released when the parent bus is. |
9051 |
++ */ |
9052 |
++ ep = kdbus_ep_unref(ep); |
9053 |
++ |
9054 |
++exit: |
9055 |
++ ret = kdbus_args_clear(&args, ret); |
9056 |
++ if (ret < 0) { |
9057 |
++ if (ep) { |
9058 |
++ kdbus_node_deactivate(&ep->node); |
9059 |
++ kdbus_ep_unref(ep); |
9060 |
++ } |
9061 |
++ if (bus) { |
9062 |
++ kdbus_node_deactivate(&bus->node); |
9063 |
++ kdbus_bus_unref(bus); |
9064 |
++ } |
9065 |
++ return ERR_PTR(ret); |
9066 |
++ } |
9067 |
++ return bus; |
9068 |
++} |
9069 |
++ |
9070 |
++/** |
9071 |
++ * kdbus_cmd_bus_creator_info() - handle KDBUS_CMD_BUS_CREATOR_INFO |
9072 |
++ * @conn: connection to operate on |
9073 |
++ * @argp: command payload |
9074 |
++ * |
9075 |
++ * Return: 0 on success, negative error code on failure. |
9076 |
++ */ |
9077 |
++int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp) |
9078 |
++{ |
9079 |
++ struct kdbus_cmd_info *cmd; |
9080 |
++ struct kdbus_bus *bus = conn->ep->bus; |
9081 |
++ struct kdbus_pool_slice *slice = NULL; |
9082 |
++ struct kdbus_item_header item_hdr; |
9083 |
++ struct kdbus_info info = {}; |
9084 |
++ size_t meta_size, name_len; |
9085 |
++ struct kvec kvec[5]; |
9086 |
++ u64 hdr_size = 0; |
9087 |
++ u64 attach_flags; |
9088 |
++ size_t cnt = 0; |
9089 |
++ int ret; |
9090 |
++ |
9091 |
++ struct kdbus_arg argv[] = { |
9092 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
9093 |
++ }; |
9094 |
++ struct kdbus_args args = { |
9095 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
9096 |
++ .argv = argv, |
9097 |
++ .argc = ARRAY_SIZE(argv), |
9098 |
++ }; |
9099 |
++ |
9100 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
9101 |
++ if (ret != 0) |
9102 |
++ return ret; |
9103 |
++ |
9104 |
++ ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags); |
9105 |
++ if (ret < 0) |
9106 |
++ goto exit; |
9107 |
++ |
9108 |
++ attach_flags &= bus->attach_flags_owner; |
9109 |
++ |
9110 |
++ ret = kdbus_meta_export_prepare(bus->creator_meta, NULL, |
9111 |
++ &attach_flags, &meta_size); |
9112 |
++ if (ret < 0) |
9113 |
++ goto exit; |
9114 |
++ |
9115 |
++ name_len = strlen(bus->node.name) + 1; |
9116 |
++ info.id = bus->id; |
9117 |
++ info.flags = bus->bus_flags; |
9118 |
++ item_hdr.type = KDBUS_ITEM_MAKE_NAME; |
9119 |
++ item_hdr.size = KDBUS_ITEM_HEADER_SIZE + name_len; |
9120 |
++ |
9121 |
++ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &hdr_size); |
9122 |
++ kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &hdr_size); |
9123 |
++ kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &hdr_size); |
9124 |
++ cnt += !!kdbus_kvec_pad(&kvec[cnt], &hdr_size); |
9125 |
++ |
9126 |
++ slice = kdbus_pool_slice_alloc(conn->pool, hdr_size + meta_size, false); |
9127 |
++ if (IS_ERR(slice)) { |
9128 |
++ ret = PTR_ERR(slice); |
9129 |
++ slice = NULL; |
9130 |
++ goto exit; |
9131 |
++ } |
9132 |
++ |
9133 |
++ ret = kdbus_meta_export(bus->creator_meta, NULL, attach_flags, |
9134 |
++ slice, hdr_size, &meta_size); |
9135 |
++ if (ret < 0) |
9136 |
++ goto exit; |
9137 |
++ |
9138 |
++ info.size = hdr_size + meta_size; |
9139 |
++ |
9140 |
++ ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, hdr_size); |
9141 |
++ if (ret < 0) |
9142 |
++ goto exit; |
9143 |
++ |
9144 |
++ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size); |
9145 |
++ |
9146 |
++ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
9147 |
++ kdbus_member_set_user(&cmd->info_size, argp, |
9148 |
++ typeof(*cmd), info_size)) |
9149 |
++ ret = -EFAULT; |
9150 |
++ |
9151 |
++exit: |
9152 |
++ kdbus_pool_slice_release(slice); |
9153 |
++ |
9154 |
++ return kdbus_args_clear(&args, ret); |
9155 |
++} |
9156 |
+diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h |
9157 |
+new file mode 100644 |
9158 |
+index 0000000..5bea5ef |
9159 |
+--- /dev/null |
9160 |
++++ b/ipc/kdbus/bus.h |
9161 |
+@@ -0,0 +1,101 @@ |
9162 |
++/* |
9163 |
++ * Copyright (C) 2013-2015 Kay Sievers |
9164 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
9165 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
9166 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
9167 |
++ * Copyright (C) 2013-2015 Linux Foundation |
9168 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
9169 |
++ * |
9170 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
9171 |
++ * the terms of the GNU Lesser General Public License as published by the |
9172 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
9173 |
++ * your option) any later version. |
9174 |
++ */ |
9175 |
++ |
9176 |
++#ifndef __KDBUS_BUS_H |
9177 |
++#define __KDBUS_BUS_H |
9178 |
++ |
9179 |
++#include <linux/hashtable.h> |
9180 |
++#include <linux/list.h> |
9181 |
++#include <linux/mutex.h> |
9182 |
++#include <linux/rwsem.h> |
9183 |
++#include <linux/spinlock.h> |
9184 |
++#include <uapi/linux/kdbus.h> |
9185 |
++ |
9186 |
++#include "metadata.h" |
9187 |
++#include "names.h" |
9188 |
++#include "node.h" |
9189 |
++#include "policy.h" |
9190 |
++ |
9191 |
++struct kdbus_conn; |
9192 |
++struct kdbus_domain; |
9193 |
++struct kdbus_kmsg; |
9194 |
++struct kdbus_user; |
9195 |
++ |
9196 |
++/** |
9197 |
++ * struct kdbus_bus - bus in a domain |
9198 |
++ * @node: kdbus_node |
9199 |
++ * @id: ID of this bus in the domain |
9200 |
++ * @bus_flags: Simple pass-through flags from userspace to userspace |
9201 |
++ * @attach_flags_req: KDBUS_ATTACH_* flags required by connecting peers |
9202 |
++ * @attach_flags_owner: KDBUS_ATTACH_* flags of bus creator that other |
9203 |
++ * connections can see or query |
9204 |
++ * @id128: Unique random 128 bit ID of this bus |
9205 |
++ * @bloom: Bloom parameters |
9206 |
++ * @domain: Domain of this bus |
9207 |
++ * @creator: Creator of the bus |
9208 |
++ * @creator_meta: Meta information about the bus creator |
9209 |
++ * @policy_db: Policy database for this bus |
9210 |
++ * @name_registry: Name registry of this bus |
9211 |
++ * @conn_rwlock: Read/Write lock for all lists of child connections |
9212 |
++ * @conn_hash: Map of connection IDs |
9213 |
++ * @monitors_list: Connections that monitor this bus |
9214 |
++ * @notify_list: List of pending kernel-generated messages |
9215 |
++ * @notify_lock: Notification list lock |
9216 |
++ * @notify_flush_lock: Notification flushing lock |
9217 |
++ */ |
9218 |
++struct kdbus_bus { |
9219 |
++ struct kdbus_node node; |
9220 |
++ |
9221 |
++ /* static */ |
9222 |
++ u64 id; |
9223 |
++ u64 bus_flags; |
9224 |
++ u64 attach_flags_req; |
9225 |
++ u64 attach_flags_owner; |
9226 |
++ u8 id128[16]; |
9227 |
++ struct kdbus_bloom_parameter bloom; |
9228 |
++ struct kdbus_domain *domain; |
9229 |
++ struct kdbus_user *creator; |
9230 |
++ struct kdbus_meta_proc *creator_meta; |
9231 |
++ |
9232 |
++ /* protected by own locks */ |
9233 |
++ struct kdbus_policy_db policy_db; |
9234 |
++ struct kdbus_name_registry *name_registry; |
9235 |
++ |
9236 |
++ /* protected by conn_rwlock */ |
9237 |
++ struct rw_semaphore conn_rwlock; |
9238 |
++ DECLARE_HASHTABLE(conn_hash, 8); |
9239 |
++ struct list_head monitors_list; |
9240 |
++ |
9241 |
++ /* protected by notify_lock */ |
9242 |
++ struct list_head notify_list; |
9243 |
++ spinlock_t notify_lock; |
9244 |
++ struct mutex notify_flush_lock; |
9245 |
++}; |
9246 |
++ |
9247 |
++struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus); |
9248 |
++struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus); |
9249 |
++ |
9250 |
++struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id); |
9251 |
++void kdbus_bus_broadcast(struct kdbus_bus *bus, |
9252 |
++ struct kdbus_conn *conn_src, |
9253 |
++ struct kdbus_kmsg *kmsg); |
9254 |
++void kdbus_bus_eavesdrop(struct kdbus_bus *bus, |
9255 |
++ struct kdbus_conn *conn_src, |
9256 |
++ struct kdbus_kmsg *kmsg); |
9257 |
++ |
9258 |
++struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, |
9259 |
++ void __user *argp); |
9260 |
++int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp); |
9261 |
++ |
9262 |
++#endif |
9263 |
+diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c |
9264 |
+new file mode 100644 |
9265 |
+index 0000000..ab476fa |
9266 |
+--- /dev/null |
9267 |
++++ b/ipc/kdbus/connection.c |
9268 |
+@@ -0,0 +1,2214 @@ |
9269 |
++/* |
9270 |
++ * Copyright (C) 2013-2015 Kay Sievers |
9271 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
9272 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
9273 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
9274 |
++ * Copyright (C) 2013-2015 Linux Foundation |
9275 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
9276 |
++ * |
9277 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
9278 |
++ * the terms of the GNU Lesser General Public License as published by the |
9279 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
9280 |
++ * your option) any later version. |
9281 |
++ */ |
9282 |
++ |
9283 |
++#include <linux/audit.h> |
9284 |
++#include <linux/file.h> |
9285 |
++#include <linux/fs.h> |
9286 |
++#include <linux/fs_struct.h> |
9287 |
++#include <linux/hashtable.h> |
9288 |
++#include <linux/idr.h> |
9289 |
++#include <linux/init.h> |
9290 |
++#include <linux/math64.h> |
9291 |
++#include <linux/mm.h> |
9292 |
++#include <linux/module.h> |
9293 |
++#include <linux/mutex.h> |
9294 |
++#include <linux/path.h> |
9295 |
++#include <linux/poll.h> |
9296 |
++#include <linux/sched.h> |
9297 |
++#include <linux/shmem_fs.h> |
9298 |
++#include <linux/sizes.h> |
9299 |
++#include <linux/slab.h> |
9300 |
++#include <linux/syscalls.h> |
9301 |
++#include <linux/uio.h> |
9302 |
++ |
9303 |
++#include "bus.h" |
9304 |
++#include "connection.h" |
9305 |
++#include "endpoint.h" |
9306 |
++#include "handle.h" |
9307 |
++#include "match.h" |
9308 |
++#include "message.h" |
9309 |
++#include "metadata.h" |
9310 |
++#include "names.h" |
9311 |
++#include "domain.h" |
9312 |
++#include "item.h" |
9313 |
++#include "notify.h" |
9314 |
++#include "policy.h" |
9315 |
++#include "pool.h" |
9316 |
++#include "reply.h" |
9317 |
++#include "util.h" |
9318 |
++#include "queue.h" |
9319 |
++ |
9320 |
++#define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2) |
9321 |
++#define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1) |
9322 |
++ |
9323 |
++static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged, |
9324 |
++ struct kdbus_cmd_hello *hello, |
9325 |
++ const char *name, |
9326 |
++ const struct kdbus_creds *creds, |
9327 |
++ const struct kdbus_pids *pids, |
9328 |
++ const char *seclabel, |
9329 |
++ const char *conn_description) |
9330 |
++{ |
9331 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9332 |
++ static struct lock_class_key __key; |
9333 |
++#endif |
9334 |
++ struct kdbus_pool_slice *slice = NULL; |
9335 |
++ struct kdbus_bus *bus = ep->bus; |
9336 |
++ struct kdbus_conn *conn; |
9337 |
++ u64 attach_flags_send; |
9338 |
++ u64 attach_flags_recv; |
9339 |
++ u64 items_size = 0; |
9340 |
++ bool is_policy_holder; |
9341 |
++ bool is_activator; |
9342 |
++ bool is_monitor; |
9343 |
++ struct kvec kvec; |
9344 |
++ int ret; |
9345 |
++ |
9346 |
++ struct { |
9347 |
++ u64 size; |
9348 |
++ u64 type; |
9349 |
++ struct kdbus_bloom_parameter bloom; |
9350 |
++ } bloom_item; |
9351 |
++ |
9352 |
++ is_monitor = hello->flags & KDBUS_HELLO_MONITOR; |
9353 |
++ is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR; |
9354 |
++ is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER; |
9355 |
++ |
9356 |
++ if (!hello->pool_size || !IS_ALIGNED(hello->pool_size, PAGE_SIZE)) |
9357 |
++ return ERR_PTR(-EINVAL); |
9358 |
++ if (is_monitor + is_activator + is_policy_holder > 1) |
9359 |
++ return ERR_PTR(-EINVAL); |
9360 |
++ if (name && !is_activator && !is_policy_holder) |
9361 |
++ return ERR_PTR(-EINVAL); |
9362 |
++ if (!name && (is_activator || is_policy_holder)) |
9363 |
++ return ERR_PTR(-EINVAL); |
9364 |
++ if (name && !kdbus_name_is_valid(name, true)) |
9365 |
++ return ERR_PTR(-EINVAL); |
9366 |
++ if (is_monitor && ep->user) |
9367 |
++ return ERR_PTR(-EOPNOTSUPP); |
9368 |
++ if (!privileged && (is_activator || is_policy_holder || is_monitor)) |
9369 |
++ return ERR_PTR(-EPERM); |
9370 |
++ if ((creds || pids || seclabel) && !privileged) |
9371 |
++ return ERR_PTR(-EPERM); |
9372 |
++ |
9373 |
++ ret = kdbus_sanitize_attach_flags(hello->attach_flags_send, |
9374 |
++ &attach_flags_send); |
9375 |
++ if (ret < 0) |
9376 |
++ return ERR_PTR(ret); |
9377 |
++ |
9378 |
++ ret = kdbus_sanitize_attach_flags(hello->attach_flags_recv, |
9379 |
++ &attach_flags_recv); |
9380 |
++ if (ret < 0) |
9381 |
++ return ERR_PTR(ret); |
9382 |
++ |
9383 |
++ /* The attach flags must always satisfy the bus requirements. */ |
9384 |
++ if (bus->attach_flags_req & ~attach_flags_send) |
9385 |
++ return ERR_PTR(-ECONNREFUSED); |
9386 |
++ |
9387 |
++ conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
9388 |
++ if (!conn) |
9389 |
++ return ERR_PTR(-ENOMEM); |
9390 |
++ |
9391 |
++ kref_init(&conn->kref); |
9392 |
++ atomic_set(&conn->active, KDBUS_CONN_ACTIVE_NEW); |
9393 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9394 |
++ lockdep_init_map(&conn->dep_map, "s_active", &__key, 0); |
9395 |
++#endif |
9396 |
++ mutex_init(&conn->lock); |
9397 |
++ INIT_LIST_HEAD(&conn->names_list); |
9398 |
++ INIT_LIST_HEAD(&conn->names_queue_list); |
9399 |
++ INIT_LIST_HEAD(&conn->reply_list); |
9400 |
++ atomic_set(&conn->name_count, 0); |
9401 |
++ atomic_set(&conn->request_count, 0); |
9402 |
++ atomic_set(&conn->lost_count, 0); |
9403 |
++ INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work); |
9404 |
++ conn->cred = get_current_cred(); |
9405 |
++ init_waitqueue_head(&conn->wait); |
9406 |
++ kdbus_queue_init(&conn->queue); |
9407 |
++ conn->privileged = privileged; |
9408 |
++ conn->ep = kdbus_ep_ref(ep); |
9409 |
++ conn->id = atomic64_inc_return(&bus->domain->last_id); |
9410 |
++ conn->flags = hello->flags; |
9411 |
++ atomic64_set(&conn->attach_flags_send, attach_flags_send); |
9412 |
++ atomic64_set(&conn->attach_flags_recv, attach_flags_recv); |
9413 |
++ INIT_LIST_HEAD(&conn->monitor_entry); |
9414 |
++ |
9415 |
++ if (conn_description) { |
9416 |
++ conn->description = kstrdup(conn_description, GFP_KERNEL); |
9417 |
++ if (!conn->description) { |
9418 |
++ ret = -ENOMEM; |
9419 |
++ goto exit_unref; |
9420 |
++ } |
9421 |
++ } |
9422 |
++ |
9423 |
++ conn->pool = kdbus_pool_new(conn->description, hello->pool_size); |
9424 |
++ if (IS_ERR(conn->pool)) { |
9425 |
++ ret = PTR_ERR(conn->pool); |
9426 |
++ conn->pool = NULL; |
9427 |
++ goto exit_unref; |
9428 |
++ } |
9429 |
++ |
9430 |
++ conn->match_db = kdbus_match_db_new(); |
9431 |
++ if (IS_ERR(conn->match_db)) { |
9432 |
++ ret = PTR_ERR(conn->match_db); |
9433 |
++ conn->match_db = NULL; |
9434 |
++ goto exit_unref; |
9435 |
++ } |
9436 |
++ |
9437 |
++ /* return properties of this connection to the caller */ |
9438 |
++ hello->bus_flags = bus->bus_flags; |
9439 |
++ hello->id = conn->id; |
9440 |
++ |
9441 |
++ BUILD_BUG_ON(sizeof(bus->id128) != sizeof(hello->id128)); |
9442 |
++ memcpy(hello->id128, bus->id128, sizeof(hello->id128)); |
9443 |
++ |
9444 |
++ conn->meta = kdbus_meta_proc_new(); |
9445 |
++ if (IS_ERR(conn->meta)) { |
9446 |
++ ret = PTR_ERR(conn->meta); |
9447 |
++ conn->meta = NULL; |
9448 |
++ goto exit_unref; |
9449 |
++ } |
9450 |
++ |
9451 |
++ /* privileged processes can impersonate somebody else */ |
9452 |
++ if (creds || pids || seclabel) { |
9453 |
++ ret = kdbus_meta_proc_fake(conn->meta, creds, pids, seclabel); |
9454 |
++ if (ret < 0) |
9455 |
++ goto exit_unref; |
9456 |
++ |
9457 |
++ conn->faked_meta = true; |
9458 |
++ } else { |
9459 |
++ ret = kdbus_meta_proc_collect(conn->meta, |
9460 |
++ KDBUS_ATTACH_CREDS | |
9461 |
++ KDBUS_ATTACH_PIDS | |
9462 |
++ KDBUS_ATTACH_AUXGROUPS | |
9463 |
++ KDBUS_ATTACH_TID_COMM | |
9464 |
++ KDBUS_ATTACH_PID_COMM | |
9465 |
++ KDBUS_ATTACH_EXE | |
9466 |
++ KDBUS_ATTACH_CMDLINE | |
9467 |
++ KDBUS_ATTACH_CGROUP | |
9468 |
++ KDBUS_ATTACH_CAPS | |
9469 |
++ KDBUS_ATTACH_SECLABEL | |
9470 |
++ KDBUS_ATTACH_AUDIT); |
9471 |
++ if (ret < 0) |
9472 |
++ goto exit_unref; |
9473 |
++ } |
9474 |
++ |
9475 |
++ /* |
9476 |
++ * Account the connection against the current user (UID), or for |
9477 |
++ * custom endpoints use the anonymous user assigned to the endpoint. |
9478 |
++ * Note that limits are always accounted against the real UID, not |
9479 |
++ * the effective UID (cred->user always points to the accounting of |
9480 |
++ * cred->uid, not cred->euid). |
9481 |
++ */ |
9482 |
++ if (ep->user) { |
9483 |
++ conn->user = kdbus_user_ref(ep->user); |
9484 |
++ } else { |
9485 |
++ conn->user = kdbus_user_lookup(ep->bus->domain, current_uid()); |
9486 |
++ if (IS_ERR(conn->user)) { |
9487 |
++ ret = PTR_ERR(conn->user); |
9488 |
++ conn->user = NULL; |
9489 |
++ goto exit_unref; |
9490 |
++ } |
9491 |
++ } |
9492 |
++ |
9493 |
++ if (atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) { |
9494 |
++ /* decremented by destructor as conn->user is valid */ |
9495 |
++ ret = -EMFILE; |
9496 |
++ goto exit_unref; |
9497 |
++ } |
9498 |
++ |
9499 |
++ bloom_item.size = sizeof(bloom_item); |
9500 |
++ bloom_item.type = KDBUS_ITEM_BLOOM_PARAMETER; |
9501 |
++ bloom_item.bloom = bus->bloom; |
9502 |
++ kdbus_kvec_set(&kvec, &bloom_item, bloom_item.size, &items_size); |
9503 |
++ |
9504 |
++ slice = kdbus_pool_slice_alloc(conn->pool, items_size, false); |
9505 |
++ if (IS_ERR(slice)) { |
9506 |
++ ret = PTR_ERR(slice); |
9507 |
++ slice = NULL; |
9508 |
++ goto exit_unref; |
9509 |
++ } |
9510 |
++ |
9511 |
++ ret = kdbus_pool_slice_copy_kvec(slice, 0, &kvec, 1, items_size); |
9512 |
++ if (ret < 0) |
9513 |
++ goto exit_unref; |
9514 |
++ |
9515 |
++ kdbus_pool_slice_publish(slice, &hello->offset, &hello->items_size); |
9516 |
++ kdbus_pool_slice_release(slice); |
9517 |
++ |
9518 |
++ return conn; |
9519 |
++ |
9520 |
++exit_unref: |
9521 |
++ kdbus_pool_slice_release(slice); |
9522 |
++ kdbus_conn_unref(conn); |
9523 |
++ return ERR_PTR(ret); |
9524 |
++} |
9525 |
++ |
9526 |
++static void __kdbus_conn_free(struct kref *kref) |
9527 |
++{ |
9528 |
++ struct kdbus_conn *conn = container_of(kref, struct kdbus_conn, kref); |
9529 |
++ |
9530 |
++ WARN_ON(kdbus_conn_active(conn)); |
9531 |
++ WARN_ON(delayed_work_pending(&conn->work)); |
9532 |
++ WARN_ON(!list_empty(&conn->queue.msg_list)); |
9533 |
++ WARN_ON(!list_empty(&conn->names_list)); |
9534 |
++ WARN_ON(!list_empty(&conn->names_queue_list)); |
9535 |
++ WARN_ON(!list_empty(&conn->reply_list)); |
9536 |
++ |
9537 |
++ if (conn->user) { |
9538 |
++ atomic_dec(&conn->user->connections); |
9539 |
++ kdbus_user_unref(conn->user); |
9540 |
++ } |
9541 |
++ |
9542 |
++ kdbus_meta_proc_unref(conn->meta); |
9543 |
++ kdbus_match_db_free(conn->match_db); |
9544 |
++ kdbus_pool_free(conn->pool); |
9545 |
++ kdbus_ep_unref(conn->ep); |
9546 |
++ put_cred(conn->cred); |
9547 |
++ kfree(conn->description); |
9548 |
++ kfree(conn->quota); |
9549 |
++ kfree(conn); |
9550 |
++} |
9551 |
++ |
9552 |
++/** |
9553 |
++ * kdbus_conn_ref() - take a connection reference |
9554 |
++ * @conn: Connection, may be %NULL |
9555 |
++ * |
9556 |
++ * Return: the connection itself |
9557 |
++ */ |
9558 |
++struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn) |
9559 |
++{ |
9560 |
++ if (conn) |
9561 |
++ kref_get(&conn->kref); |
9562 |
++ return conn; |
9563 |
++} |
9564 |
++ |
9565 |
++/** |
9566 |
++ * kdbus_conn_unref() - drop a connection reference |
9567 |
++ * @conn: Connection (may be NULL) |
9568 |
++ * |
9569 |
++ * When the last reference is dropped, the connection's internal structure |
9570 |
++ * is freed. |
9571 |
++ * |
9572 |
++ * Return: NULL |
9573 |
++ */ |
9574 |
++struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn) |
9575 |
++{ |
9576 |
++ if (conn) |
9577 |
++ kref_put(&conn->kref, __kdbus_conn_free); |
9578 |
++ return NULL; |
9579 |
++} |
9580 |
++ |
9581 |
++/** |
9582 |
++ * kdbus_conn_active() - connection is not disconnected |
9583 |
++ * @conn: Connection to check |
9584 |
++ * |
9585 |
++ * Return true if the connection was not disconnected, yet. Note that a |
9586 |
++ * connection might be disconnected asynchronously, unless you hold the |
9587 |
++ * connection lock. If that's not suitable for you, see kdbus_conn_acquire() to |
9588 |
++ * suppress connection shutdown for a short period. |
9589 |
++ * |
9590 |
++ * Return: true if the connection is still active |
9591 |
++ */ |
9592 |
++bool kdbus_conn_active(const struct kdbus_conn *conn) |
9593 |
++{ |
9594 |
++ return atomic_read(&conn->active) >= 0; |
9595 |
++} |
9596 |
++ |
9597 |
++/** |
9598 |
++ * kdbus_conn_acquire() - acquire an active connection reference |
9599 |
++ * @conn: Connection |
9600 |
++ * |
9601 |
++ * Users can close a connection via KDBUS_BYEBYE (or by destroying the |
9602 |
++ * endpoint/bus/...) at any time. Whenever this happens, we should deny any |
9603 |
++ * user-visible action on this connection and signal ECONNRESET instead. |
9604 |
++ * To avoid testing for connection availability everytime you take the |
9605 |
++ * connection-lock, you can acquire a connection for short periods. |
9606 |
++ * |
9607 |
++ * By calling kdbus_conn_acquire(), you gain an "active reference" to the |
9608 |
++ * connection. You must also hold a regular reference at any time! As long as |
9609 |
++ * you hold the active-ref, the connection will not be shut down. However, if |
9610 |
++ * the connection was shut down, you can never acquire an active-ref again. |
9611 |
++ * |
9612 |
++ * kdbus_conn_disconnect() disables the connection and then waits for all active |
9613 |
++ * references to be dropped. It will also wake up any pending operation. |
9614 |
++ * However, you must not sleep for an indefinite period while holding an |
9615 |
++ * active-reference. Otherwise, kdbus_conn_disconnect() might stall. If you need |
9616 |
++ * to sleep for an indefinite period, either release the reference and try to |
9617 |
++ * acquire it again after waking up, or make kdbus_conn_disconnect() wake up |
9618 |
++ * your wait-queue. |
9619 |
++ * |
9620 |
++ * Return: 0 on success, negative error code on failure. |
9621 |
++ */ |
9622 |
++int kdbus_conn_acquire(struct kdbus_conn *conn) |
9623 |
++{ |
9624 |
++ if (!atomic_inc_unless_negative(&conn->active)) |
9625 |
++ return -ECONNRESET; |
9626 |
++ |
9627 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9628 |
++ rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_); |
9629 |
++#endif |
9630 |
++ |
9631 |
++ return 0; |
9632 |
++} |
9633 |
++ |
9634 |
++/** |
9635 |
++ * kdbus_conn_release() - release an active connection reference |
9636 |
++ * @conn: Connection |
9637 |
++ * |
9638 |
++ * This releases an active reference that has been acquired via |
9639 |
++ * kdbus_conn_acquire(). If the connection was already disabled and this is the |
9640 |
++ * last active-ref that is dropped, the disconnect-waiter will be woken up and |
9641 |
++ * properly close the connection. |
9642 |
++ */ |
9643 |
++void kdbus_conn_release(struct kdbus_conn *conn) |
9644 |
++{ |
9645 |
++ int v; |
9646 |
++ |
9647 |
++ if (!conn) |
9648 |
++ return; |
9649 |
++ |
9650 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9651 |
++ rwsem_release(&conn->dep_map, 1, _RET_IP_); |
9652 |
++#endif |
9653 |
++ |
9654 |
++ v = atomic_dec_return(&conn->active); |
9655 |
++ if (v != KDBUS_CONN_ACTIVE_BIAS) |
9656 |
++ return; |
9657 |
++ |
9658 |
++ wake_up_all(&conn->wait); |
9659 |
++} |
9660 |
++ |
9661 |
++static int kdbus_conn_connect(struct kdbus_conn *conn, const char *name) |
9662 |
++{ |
9663 |
++ struct kdbus_ep *ep = conn->ep; |
9664 |
++ struct kdbus_bus *bus = ep->bus; |
9665 |
++ int ret; |
9666 |
++ |
9667 |
++ if (WARN_ON(atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_NEW)) |
9668 |
++ return -EALREADY; |
9669 |
++ |
9670 |
++ /* make sure the ep-node is active while we add our connection */ |
9671 |
++ if (!kdbus_node_acquire(&ep->node)) |
9672 |
++ return -ESHUTDOWN; |
9673 |
++ |
9674 |
++ /* lock order: domain -> bus -> ep -> names -> conn */ |
9675 |
++ mutex_lock(&ep->lock); |
9676 |
++ down_write(&bus->conn_rwlock); |
9677 |
++ |
9678 |
++ /* link into monitor list */ |
9679 |
++ if (kdbus_conn_is_monitor(conn)) |
9680 |
++ list_add_tail(&conn->monitor_entry, &bus->monitors_list); |
9681 |
++ |
9682 |
++ /* link into bus and endpoint */ |
9683 |
++ list_add_tail(&conn->ep_entry, &ep->conn_list); |
9684 |
++ hash_add(bus->conn_hash, &conn->hentry, conn->id); |
9685 |
++ |
9686 |
++ /* enable lookups and acquire active ref */ |
9687 |
++ atomic_set(&conn->active, 1); |
9688 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9689 |
++ rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_); |
9690 |
++#endif |
9691 |
++ |
9692 |
++ up_write(&bus->conn_rwlock); |
9693 |
++ mutex_unlock(&ep->lock); |
9694 |
++ |
9695 |
++ kdbus_node_release(&ep->node); |
9696 |
++ |
9697 |
++ /* |
9698 |
++ * Notify subscribers about the new active connection, unless it is |
9699 |
++ * a monitor. Monitors are invisible on the bus, can't be addressed |
9700 |
++ * directly, and won't cause any notifications. |
9701 |
++ */ |
9702 |
++ if (!kdbus_conn_is_monitor(conn)) { |
9703 |
++ ret = kdbus_notify_id_change(conn->ep->bus, KDBUS_ITEM_ID_ADD, |
9704 |
++ conn->id, conn->flags); |
9705 |
++ if (ret < 0) |
9706 |
++ goto exit_disconnect; |
9707 |
++ } |
9708 |
++ |
9709 |
++ if (kdbus_conn_is_activator(conn)) { |
9710 |
++ u64 flags = KDBUS_NAME_ACTIVATOR; |
9711 |
++ |
9712 |
++ if (WARN_ON(!name)) { |
9713 |
++ ret = -EINVAL; |
9714 |
++ goto exit_disconnect; |
9715 |
++ } |
9716 |
++ |
9717 |
++ ret = kdbus_name_acquire(bus->name_registry, conn, name, |
9718 |
++ flags, NULL); |
9719 |
++ if (ret < 0) |
9720 |
++ goto exit_disconnect; |
9721 |
++ } |
9722 |
++ |
9723 |
++ kdbus_conn_release(conn); |
9724 |
++ kdbus_notify_flush(bus); |
9725 |
++ return 0; |
9726 |
++ |
9727 |
++exit_disconnect: |
9728 |
++ kdbus_conn_release(conn); |
9729 |
++ kdbus_conn_disconnect(conn, false); |
9730 |
++ return ret; |
9731 |
++} |
9732 |
++ |
9733 |
++/** |
9734 |
++ * kdbus_conn_disconnect() - disconnect a connection |
9735 |
++ * @conn: The connection to disconnect |
9736 |
++ * @ensure_queue_empty: Flag to indicate if the call should fail in |
9737 |
++ * case the connection's message list is not |
9738 |
++ * empty |
9739 |
++ * |
9740 |
++ * If @ensure_msg_list_empty is true, and the connection has pending messages, |
9741 |
++ * -EBUSY is returned. |
9742 |
++ * |
9743 |
++ * Return: 0 on success, negative errno on failure |
9744 |
++ */ |
9745 |
++int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty) |
9746 |
++{ |
9747 |
++ struct kdbus_queue_entry *entry, *tmp; |
9748 |
++ struct kdbus_bus *bus = conn->ep->bus; |
9749 |
++ struct kdbus_reply *r, *r_tmp; |
9750 |
++ struct kdbus_conn *c; |
9751 |
++ int i, v; |
9752 |
++ |
9753 |
++ mutex_lock(&conn->lock); |
9754 |
++ v = atomic_read(&conn->active); |
9755 |
++ if (v == KDBUS_CONN_ACTIVE_NEW) { |
9756 |
++ /* was never connected */ |
9757 |
++ mutex_unlock(&conn->lock); |
9758 |
++ return 0; |
9759 |
++ } |
9760 |
++ if (v < 0) { |
9761 |
++ /* already dead */ |
9762 |
++ mutex_unlock(&conn->lock); |
9763 |
++ return -ECONNRESET; |
9764 |
++ } |
9765 |
++ if (ensure_queue_empty && !list_empty(&conn->queue.msg_list)) { |
9766 |
++ /* still busy */ |
9767 |
++ mutex_unlock(&conn->lock); |
9768 |
++ return -EBUSY; |
9769 |
++ } |
9770 |
++ |
9771 |
++ atomic_add(KDBUS_CONN_ACTIVE_BIAS, &conn->active); |
9772 |
++ mutex_unlock(&conn->lock); |
9773 |
++ |
9774 |
++ wake_up_interruptible(&conn->wait); |
9775 |
++ |
9776 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9777 |
++ rwsem_acquire(&conn->dep_map, 0, 0, _RET_IP_); |
9778 |
++ if (atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_BIAS) |
9779 |
++ lock_contended(&conn->dep_map, _RET_IP_); |
9780 |
++#endif |
9781 |
++ |
9782 |
++ wait_event(conn->wait, |
9783 |
++ atomic_read(&conn->active) == KDBUS_CONN_ACTIVE_BIAS); |
9784 |
++ |
9785 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9786 |
++ lock_acquired(&conn->dep_map, _RET_IP_); |
9787 |
++ rwsem_release(&conn->dep_map, 1, _RET_IP_); |
9788 |
++#endif |
9789 |
++ |
9790 |
++ cancel_delayed_work_sync(&conn->work); |
9791 |
++ kdbus_policy_remove_owner(&conn->ep->bus->policy_db, conn); |
9792 |
++ |
9793 |
++ /* lock order: domain -> bus -> ep -> names -> conn */ |
9794 |
++ mutex_lock(&conn->ep->lock); |
9795 |
++ down_write(&bus->conn_rwlock); |
9796 |
++ |
9797 |
++ /* remove from bus and endpoint */ |
9798 |
++ hash_del(&conn->hentry); |
9799 |
++ list_del(&conn->monitor_entry); |
9800 |
++ list_del(&conn->ep_entry); |
9801 |
++ |
9802 |
++ up_write(&bus->conn_rwlock); |
9803 |
++ mutex_unlock(&conn->ep->lock); |
9804 |
++ |
9805 |
++ /* |
9806 |
++ * Remove all names associated with this connection; this possibly |
9807 |
++ * moves queued messages back to the activator connection. |
9808 |
++ */ |
9809 |
++ kdbus_name_release_all(bus->name_registry, conn); |
9810 |
++ |
9811 |
++ /* if we die while other connections wait for our reply, notify them */ |
9812 |
++ mutex_lock(&conn->lock); |
9813 |
++ list_for_each_entry_safe(entry, tmp, &conn->queue.msg_list, entry) { |
9814 |
++ if (entry->reply) |
9815 |
++ kdbus_notify_reply_dead(bus, |
9816 |
++ entry->reply->reply_dst->id, |
9817 |
++ entry->reply->cookie); |
9818 |
++ kdbus_queue_entry_free(entry); |
9819 |
++ } |
9820 |
++ |
9821 |
++ list_for_each_entry_safe(r, r_tmp, &conn->reply_list, entry) |
9822 |
++ kdbus_reply_unlink(r); |
9823 |
++ mutex_unlock(&conn->lock); |
9824 |
++ |
9825 |
++ /* lock order: domain -> bus -> ep -> names -> conn */ |
9826 |
++ down_read(&bus->conn_rwlock); |
9827 |
++ hash_for_each(bus->conn_hash, i, c, hentry) { |
9828 |
++ mutex_lock(&c->lock); |
9829 |
++ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) { |
9830 |
++ if (r->reply_src == conn) { |
9831 |
++ if (r->sync) { |
9832 |
++ kdbus_sync_reply_wakeup(r, -EPIPE); |
9833 |
++ kdbus_reply_unlink(r); |
9834 |
++ continue; |
9835 |
++ } |
9836 |
++ |
9837 |
++ /* send a 'connection dead' notification */ |
9838 |
++ kdbus_notify_reply_dead(bus, c->id, r->cookie); |
9839 |
++ kdbus_reply_unlink(r); |
9840 |
++ } |
9841 |
++ } |
9842 |
++ mutex_unlock(&c->lock); |
9843 |
++ } |
9844 |
++ up_read(&bus->conn_rwlock); |
9845 |
++ |
9846 |
++ if (!kdbus_conn_is_monitor(conn)) |
9847 |
++ kdbus_notify_id_change(bus, KDBUS_ITEM_ID_REMOVE, |
9848 |
++ conn->id, conn->flags); |
9849 |
++ |
9850 |
++ kdbus_notify_flush(bus); |
9851 |
++ |
9852 |
++ return 0; |
9853 |
++} |
9854 |
++ |
9855 |
++/** |
9856 |
++ * kdbus_conn_has_name() - check if a connection owns a name |
9857 |
++ * @conn: Connection |
9858 |
++ * @name: Well-know name to check for |
9859 |
++ * |
9860 |
++ * The caller must hold the registry lock of conn->ep->bus. |
9861 |
++ * |
9862 |
++ * Return: true if the name is currently owned by the connection |
9863 |
++ */ |
9864 |
++bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name) |
9865 |
++{ |
9866 |
++ struct kdbus_name_entry *e; |
9867 |
++ |
9868 |
++ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
9869 |
++ |
9870 |
++ list_for_each_entry(e, &conn->names_list, conn_entry) |
9871 |
++ if (strcmp(e->name, name) == 0) |
9872 |
++ return true; |
9873 |
++ |
9874 |
++ return false; |
9875 |
++} |
9876 |
++ |
9877 |
++struct kdbus_quota { |
9878 |
++ uint32_t memory; |
9879 |
++ uint16_t msgs; |
9880 |
++ uint8_t fds; |
9881 |
++}; |
9882 |
++ |
9883 |
++/** |
9884 |
++ * kdbus_conn_quota_inc() - increase quota accounting |
9885 |
++ * @c: connection owning the quota tracking |
9886 |
++ * @u: user to account for (or NULL for kernel accounting) |
9887 |
++ * @memory: size of memory to account for |
9888 |
++ * @fds: number of FDs to account for |
9889 |
++ * |
9890 |
++ * This call manages the quotas on resource @c. That is, it's used if other |
9891 |
++ * users want to use the resources of connection @c, which so far only concerns |
9892 |
++ * the receive queue of the destination. |
9893 |
++ * |
9894 |
++ * This increases the quota-accounting for user @u by @memory bytes and @fds |
9895 |
++ * file descriptors. If the user has already reached the quota limits, this call |
9896 |
++ * will not do any accounting but return a negative error code indicating the |
9897 |
++ * failure. |
9898 |
++ * |
9899 |
++ * Return: 0 on success, negative error code on failure. |
9900 |
++ */ |
9901 |
++int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, |
9902 |
++ size_t memory, size_t fds) |
9903 |
++{ |
9904 |
++ struct kdbus_quota *quota; |
9905 |
++ size_t available, accounted; |
9906 |
++ unsigned int id; |
9907 |
++ |
9908 |
++ /* |
9909 |
++ * Pool Layout: |
9910 |
++ * 50% of a pool is always owned by the connection. It is reserved for |
9911 |
++ * kernel queries, handling received messages and other tasks that are |
9912 |
++ * under control of the pool owner. The other 50% of the pool are used |
9913 |
++ * as incoming queue. |
9914 |
++ * As we optionally support user-space based policies, we need fair |
9915 |
++ * allocation schemes. Furthermore, resource utilization should be |
9916 |
++ * maximized, so only minimal resources stay reserved. However, we need |
9917 |
++ * to adapt to a dynamic number of users, as we cannot know how many |
9918 |
++ * users will talk to a connection. Therefore, the current allocations |
9919 |
++ * works like this: |
9920 |
++ * We limit the number of bytes in a destination's pool per sending |
9921 |
++ * user. The space available for a user is 33% of the unused pool space |
9922 |
++ * (whereas the space used by the user itself is also treated as |
9923 |
++ * 'unused'). This way, we favor users coming first, but keep enough |
9924 |
++ * pool space available for any following users. Given that messages are |
9925 |
++ * dequeued in FIFO order, this should balance nicely if the number of |
9926 |
++ * users grows. At the same time, this algorithm guarantees that the |
9927 |
++ * space available to a connection is reduced dynamically, the more |
9928 |
++ * concurrent users talk to a connection. |
9929 |
++ */ |
9930 |
++ |
9931 |
++ /* per user-accounting is expensive, so we keep state small */ |
9932 |
++ BUILD_BUG_ON(sizeof(quota->memory) != 4); |
9933 |
++ BUILD_BUG_ON(sizeof(quota->msgs) != 2); |
9934 |
++ BUILD_BUG_ON(sizeof(quota->fds) != 1); |
9935 |
++ BUILD_BUG_ON(KDBUS_CONN_MAX_MSGS > U16_MAX); |
9936 |
++ BUILD_BUG_ON(KDBUS_CONN_MAX_FDS_PER_USER > U8_MAX); |
9937 |
++ |
9938 |
++ id = u ? u->id : KDBUS_USER_KERNEL_ID; |
9939 |
++ if (id >= c->n_quota) { |
9940 |
++ unsigned int users; |
9941 |
++ |
9942 |
++ users = max(KDBUS_ALIGN8(id) + 8, id); |
9943 |
++ quota = krealloc(c->quota, users * sizeof(*quota), |
9944 |
++ GFP_KERNEL | __GFP_ZERO); |
9945 |
++ if (!quota) |
9946 |
++ return -ENOMEM; |
9947 |
++ |
9948 |
++ c->n_quota = users; |
9949 |
++ c->quota = quota; |
9950 |
++ } |
9951 |
++ |
9952 |
++ quota = &c->quota[id]; |
9953 |
++ kdbus_pool_accounted(c->pool, &available, &accounted); |
9954 |
++ |
9955 |
++ /* half the pool is _always_ reserved for the pool owner */ |
9956 |
++ available /= 2; |
9957 |
++ |
9958 |
++ /* |
9959 |
++ * Pool owner slices are un-accounted slices; they can claim more |
9960 |
++ * than 50% of the queue. However, the slice we're dealing with here |
9961 |
++ * belong to the incoming queue, hence they are 'accounted' slices |
9962 |
++ * to which the 50%-limit applies. |
9963 |
++ */ |
9964 |
++ if (available < accounted) |
9965 |
++ return -ENOBUFS; |
9966 |
++ |
9967 |
++ /* 1/3 of the remaining space (including your own memory) */ |
9968 |
++ available = (available - accounted + quota->memory) / 3; |
9969 |
++ |
9970 |
++ if (available < quota->memory || |
9971 |
++ available - quota->memory < memory || |
9972 |
++ quota->memory + memory > U32_MAX) |
9973 |
++ return -ENOBUFS; |
9974 |
++ if (quota->msgs >= KDBUS_CONN_MAX_MSGS) |
9975 |
++ return -ENOBUFS; |
9976 |
++ if (quota->fds + fds < quota->fds || |
9977 |
++ quota->fds + fds > KDBUS_CONN_MAX_FDS_PER_USER) |
9978 |
++ return -EMFILE; |
9979 |
++ |
9980 |
++ quota->memory += memory; |
9981 |
++ quota->fds += fds; |
9982 |
++ ++quota->msgs; |
9983 |
++ return 0; |
9984 |
++} |
9985 |
++ |
9986 |
++/** |
9987 |
++ * kdbus_conn_quota_dec() - decrease quota accounting |
9988 |
++ * @c: connection owning the quota tracking |
9989 |
++ * @u: user which was accounted for (or NULL for kernel accounting) |
9990 |
++ * @memory: size of memory which was accounted for |
9991 |
++ * @fds: number of FDs which were accounted for |
9992 |
++ * |
9993 |
++ * This does the reverse of kdbus_conn_quota_inc(). You have to release any |
9994 |
++ * accounted resources that you called kdbus_conn_quota_inc() for. However, you |
9995 |
++ * must not call kdbus_conn_quota_dec() if the accounting failed (that is, |
9996 |
++ * kdbus_conn_quota_inc() failed). |
9997 |
++ */ |
9998 |
++void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, |
9999 |
++ size_t memory, size_t fds) |
10000 |
++{ |
10001 |
++ struct kdbus_quota *quota; |
10002 |
++ unsigned int id; |
10003 |
++ |
10004 |
++ id = u ? u->id : KDBUS_USER_KERNEL_ID; |
10005 |
++ if (WARN_ON(id >= c->n_quota)) |
10006 |
++ return; |
10007 |
++ |
10008 |
++ quota = &c->quota[id]; |
10009 |
++ |
10010 |
++ if (!WARN_ON(quota->msgs == 0)) |
10011 |
++ --quota->msgs; |
10012 |
++ if (!WARN_ON(quota->memory < memory)) |
10013 |
++ quota->memory -= memory; |
10014 |
++ if (!WARN_ON(quota->fds < fds)) |
10015 |
++ quota->fds -= fds; |
10016 |
++} |
10017 |
++ |
10018 |
++/** |
10019 |
++ * kdbus_conn_lost_message() - handle lost messages |
10020 |
++ * @c: connection that lost a message |
10021 |
++ * |
10022 |
++ * kdbus is reliable. That means, we try hard to never lose messages. However, |
10023 |
++ * memory is limited, so we cannot rely on transmissions to never fail. |
10024 |
++ * Therefore, we use quota-limits to let callers know if there unicast message |
10025 |
++ * cannot be transmitted to a peer. This works fine for unicasts, but for |
10026 |
++ * broadcasts we cannot make the caller handle the transmission failure. |
10027 |
++ * Instead, we must let the destination know that it couldn't receive a |
10028 |
++ * broadcast. |
10029 |
++ * As this is an unlikely scenario, we keep it simple. A single lost-counter |
10030 |
++ * remembers the number of lost messages since the last call to RECV. The next |
10031 |
++ * message retrieval will notify the connection that it lost messages since the |
10032 |
++ * last message retrieval and thus should resync its state. |
10033 |
++ */ |
10034 |
++void kdbus_conn_lost_message(struct kdbus_conn *c) |
10035 |
++{ |
10036 |
++ if (atomic_inc_return(&c->lost_count) == 1) |
10037 |
++ wake_up_interruptible(&c->wait); |
10038 |
++} |
10039 |
++ |
10040 |
++/* Callers should take the conn_dst lock */ |
10041 |
++static struct kdbus_queue_entry * |
10042 |
++kdbus_conn_entry_make(struct kdbus_conn *conn_dst, |
10043 |
++ const struct kdbus_kmsg *kmsg, |
10044 |
++ struct kdbus_user *user) |
10045 |
++{ |
10046 |
++ struct kdbus_queue_entry *entry; |
10047 |
++ |
10048 |
++ /* The remote connection was disconnected */ |
10049 |
++ if (!kdbus_conn_active(conn_dst)) |
10050 |
++ return ERR_PTR(-ECONNRESET); |
10051 |
++ |
10052 |
++ /* |
10053 |
++ * If the connection does not accept file descriptors but the message |
10054 |
++ * has some attached, refuse it. |
10055 |
++ * |
10056 |
++ * If this is a monitor connection, accept the message. In that |
10057 |
++ * case, all file descriptors will be set to -1 at receive time. |
10058 |
++ */ |
10059 |
++ if (!kdbus_conn_is_monitor(conn_dst) && |
10060 |
++ !(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) && |
10061 |
++ kmsg->res && kmsg->res->fds_count > 0) |
10062 |
++ return ERR_PTR(-ECOMM); |
10063 |
++ |
10064 |
++ entry = kdbus_queue_entry_new(conn_dst, kmsg, user); |
10065 |
++ if (IS_ERR(entry)) |
10066 |
++ return entry; |
10067 |
++ |
10068 |
++ return entry; |
10069 |
++} |
10070 |
++ |
10071 |
++/* |
10072 |
++ * Synchronously responding to a message, allocate a queue entry |
10073 |
++ * and attach it to the reply tracking object. |
10074 |
++ * The connection's queue will never get to see it. |
10075 |
++ */ |
10076 |
++static int kdbus_conn_entry_sync_attach(struct kdbus_conn *conn_dst, |
10077 |
++ const struct kdbus_kmsg *kmsg, |
10078 |
++ struct kdbus_reply *reply_wake) |
10079 |
++{ |
10080 |
++ struct kdbus_queue_entry *entry; |
10081 |
++ int remote_ret; |
10082 |
++ int ret = 0; |
10083 |
++ |
10084 |
++ mutex_lock(&reply_wake->reply_dst->lock); |
10085 |
++ |
10086 |
++ /* |
10087 |
++ * If we are still waiting then proceed, allocate a queue |
10088 |
++ * entry and attach it to the reply object |
10089 |
++ */ |
10090 |
++ if (reply_wake->waiting) { |
10091 |
++ entry = kdbus_conn_entry_make(conn_dst, kmsg, |
10092 |
++ reply_wake->reply_src->user); |
10093 |
++ if (IS_ERR(entry)) |
10094 |
++ ret = PTR_ERR(entry); |
10095 |
++ else |
10096 |
++ /* Attach the entry to the reply object */ |
10097 |
++ reply_wake->queue_entry = entry; |
10098 |
++ } else { |
10099 |
++ ret = -ECONNRESET; |
10100 |
++ } |
10101 |
++ |
10102 |
++ /* |
10103 |
++ * Update the reply object and wake up remote peer only |
10104 |
++ * on appropriate return codes |
10105 |
++ * |
10106 |
++ * * -ECOMM: if the replying connection failed with -ECOMM |
10107 |
++ * then wakeup remote peer with -EREMOTEIO |
10108 |
++ * |
10109 |
++ * We do this to differenciate between -ECOMM errors |
10110 |
++ * from the original sender perspective: |
10111 |
++ * -ECOMM error during the sync send and |
10112 |
++ * -ECOMM error during the sync reply, this last |
10113 |
++ * one is rewritten to -EREMOTEIO |
10114 |
++ * |
10115 |
++ * * Wake up on all other return codes. |
10116 |
++ */ |
10117 |
++ remote_ret = ret; |
10118 |
++ |
10119 |
++ if (ret == -ECOMM) |
10120 |
++ remote_ret = -EREMOTEIO; |
10121 |
++ |
10122 |
++ kdbus_sync_reply_wakeup(reply_wake, remote_ret); |
10123 |
++ kdbus_reply_unlink(reply_wake); |
10124 |
++ mutex_unlock(&reply_wake->reply_dst->lock); |
10125 |
++ |
10126 |
++ return ret; |
10127 |
++} |
10128 |
++ |
10129 |
++/** |
10130 |
++ * kdbus_conn_entry_insert() - enqueue a message into the receiver's pool |
10131 |
++ * @conn_src: The sending connection |
10132 |
++ * @conn_dst: The connection to queue into |
10133 |
++ * @kmsg: The kmsg to queue |
10134 |
++ * @reply: The reply tracker to attach to the queue entry |
10135 |
++ * |
10136 |
++ * Return: 0 on success. negative error otherwise. |
10137 |
++ */ |
10138 |
++int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, |
10139 |
++ struct kdbus_conn *conn_dst, |
10140 |
++ const struct kdbus_kmsg *kmsg, |
10141 |
++ struct kdbus_reply *reply) |
10142 |
++{ |
10143 |
++ struct kdbus_queue_entry *entry; |
10144 |
++ int ret; |
10145 |
++ |
10146 |
++ kdbus_conn_lock2(conn_src, conn_dst); |
10147 |
++ |
10148 |
++ entry = kdbus_conn_entry_make(conn_dst, kmsg, |
10149 |
++ conn_src ? conn_src->user : NULL); |
10150 |
++ if (IS_ERR(entry)) { |
10151 |
++ ret = PTR_ERR(entry); |
10152 |
++ goto exit_unlock; |
10153 |
++ } |
10154 |
++ |
10155 |
++ if (reply) { |
10156 |
++ kdbus_reply_link(reply); |
10157 |
++ if (!reply->sync) |
10158 |
++ schedule_delayed_work(&conn_src->work, 0); |
10159 |
++ } |
10160 |
++ |
10161 |
++ kdbus_queue_entry_enqueue(entry, reply); |
10162 |
++ wake_up_interruptible(&conn_dst->wait); |
10163 |
++ |
10164 |
++ ret = 0; |
10165 |
++ |
10166 |
++exit_unlock: |
10167 |
++ kdbus_conn_unlock2(conn_src, conn_dst); |
10168 |
++ return ret; |
10169 |
++} |
10170 |
++ |
10171 |
++static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src, |
10172 |
++ struct kdbus_cmd_send *cmd_send, |
10173 |
++ struct file *ioctl_file, |
10174 |
++ struct file *cancel_fd, |
10175 |
++ struct kdbus_reply *reply_wait, |
10176 |
++ ktime_t expire) |
10177 |
++{ |
10178 |
++ struct kdbus_queue_entry *entry; |
10179 |
++ struct poll_wqueues pwq = {}; |
10180 |
++ int ret; |
10181 |
++ |
10182 |
++ if (WARN_ON(!reply_wait)) |
10183 |
++ return -EIO; |
10184 |
++ |
10185 |
++ /* |
10186 |
++ * Block until the reply arrives. reply_wait is left untouched |
10187 |
++ * by the timeout scans that might be conducted for other, |
10188 |
++ * asynchronous replies of conn_src. |
10189 |
++ */ |
10190 |
++ |
10191 |
++ poll_initwait(&pwq); |
10192 |
++ poll_wait(ioctl_file, &conn_src->wait, &pwq.pt); |
10193 |
++ |
10194 |
++ for (;;) { |
10195 |
++ /* |
10196 |
++ * Any of the following conditions will stop our synchronously |
10197 |
++ * blocking SEND command: |
10198 |
++ * |
10199 |
++ * a) The origin sender closed its connection |
10200 |
++ * b) The remote peer answered, setting reply_wait->waiting = 0 |
10201 |
++ * c) The cancel FD was written to |
10202 |
++ * d) A signal was received |
10203 |
++ * e) The specified timeout was reached, and none of the above |
10204 |
++ * conditions kicked in. |
10205 |
++ */ |
10206 |
++ |
10207 |
++ /* |
10208 |
++ * We have already acquired an active reference when |
10209 |
++ * entering here, but another thread may call |
10210 |
++ * KDBUS_CMD_BYEBYE which does not acquire an active |
10211 |
++ * reference, therefore kdbus_conn_disconnect() will |
10212 |
++ * not wait for us. |
10213 |
++ */ |
10214 |
++ if (!kdbus_conn_active(conn_src)) { |
10215 |
++ ret = -ECONNRESET; |
10216 |
++ break; |
10217 |
++ } |
10218 |
++ |
10219 |
++ /* |
10220 |
++ * After the replying peer unset the waiting variable |
10221 |
++ * it will wake up us. |
10222 |
++ */ |
10223 |
++ if (!reply_wait->waiting) { |
10224 |
++ ret = reply_wait->err; |
10225 |
++ break; |
10226 |
++ } |
10227 |
++ |
10228 |
++ if (cancel_fd) { |
10229 |
++ unsigned int r; |
10230 |
++ |
10231 |
++ r = cancel_fd->f_op->poll(cancel_fd, &pwq.pt); |
10232 |
++ if (r & POLLIN) { |
10233 |
++ ret = -ECANCELED; |
10234 |
++ break; |
10235 |
++ } |
10236 |
++ } |
10237 |
++ |
10238 |
++ if (signal_pending(current)) { |
10239 |
++ ret = -EINTR; |
10240 |
++ break; |
10241 |
++ } |
10242 |
++ |
10243 |
++ if (!poll_schedule_timeout(&pwq, TASK_INTERRUPTIBLE, |
10244 |
++ &expire, 0)) { |
10245 |
++ ret = -ETIMEDOUT; |
10246 |
++ break; |
10247 |
++ } |
10248 |
++ |
10249 |
++ /* |
10250 |
++ * Reset the poll worker func, so the waitqueues are not |
10251 |
++ * added to the poll table again. We just reuse what we've |
10252 |
++ * collected earlier for further iterations. |
10253 |
++ */ |
10254 |
++ init_poll_funcptr(&pwq.pt, NULL); |
10255 |
++ } |
10256 |
++ |
10257 |
++ poll_freewait(&pwq); |
10258 |
++ |
10259 |
++ if (ret == -EINTR) { |
10260 |
++ /* |
10261 |
++ * Interrupted system call. Unref the reply object, and pass |
10262 |
++ * the return value down the chain. Mark the reply as |
10263 |
++ * interrupted, so the cleanup work can remove it, but do not |
10264 |
++ * unlink it from the list. Once the syscall restarts, we'll |
10265 |
++ * pick it up and wait on it again. |
10266 |
++ */ |
10267 |
++ mutex_lock(&conn_src->lock); |
10268 |
++ reply_wait->interrupted = true; |
10269 |
++ schedule_delayed_work(&conn_src->work, 0); |
10270 |
++ mutex_unlock(&conn_src->lock); |
10271 |
++ |
10272 |
++ return -ERESTARTSYS; |
10273 |
++ } |
10274 |
++ |
10275 |
++ mutex_lock(&conn_src->lock); |
10276 |
++ reply_wait->waiting = false; |
10277 |
++ entry = reply_wait->queue_entry; |
10278 |
++ if (entry) { |
10279 |
++ ret = kdbus_queue_entry_install(entry, |
10280 |
++ &cmd_send->reply.return_flags, |
10281 |
++ true); |
10282 |
++ kdbus_pool_slice_publish(entry->slice, &cmd_send->reply.offset, |
10283 |
++ &cmd_send->reply.msg_size); |
10284 |
++ kdbus_queue_entry_free(entry); |
10285 |
++ } |
10286 |
++ kdbus_reply_unlink(reply_wait); |
10287 |
++ mutex_unlock(&conn_src->lock); |
10288 |
++ |
10289 |
++ return ret; |
10290 |
++} |
10291 |
++ |
10292 |
++static int kdbus_pin_dst(struct kdbus_bus *bus, |
10293 |
++ struct kdbus_kmsg *kmsg, |
10294 |
++ struct kdbus_name_entry **out_name, |
10295 |
++ struct kdbus_conn **out_dst) |
10296 |
++{ |
10297 |
++ struct kdbus_msg_resources *res = kmsg->res; |
10298 |
++ struct kdbus_name_entry *name = NULL; |
10299 |
++ struct kdbus_conn *dst = NULL; |
10300 |
++ struct kdbus_msg *msg = &kmsg->msg; |
10301 |
++ int ret; |
10302 |
++ |
10303 |
++ if (WARN_ON(!res)) |
10304 |
++ return -EINVAL; |
10305 |
++ |
10306 |
++ lockdep_assert_held(&bus->name_registry->rwlock); |
10307 |
++ |
10308 |
++ if (!res->dst_name) { |
10309 |
++ dst = kdbus_bus_find_conn_by_id(bus, msg->dst_id); |
10310 |
++ if (!dst) |
10311 |
++ return -ENXIO; |
10312 |
++ |
10313 |
++ if (!kdbus_conn_is_ordinary(dst)) { |
10314 |
++ ret = -ENXIO; |
10315 |
++ goto error; |
10316 |
++ } |
10317 |
++ } else { |
10318 |
++ name = kdbus_name_lookup_unlocked(bus->name_registry, |
10319 |
++ res->dst_name); |
10320 |
++ if (!name) |
10321 |
++ return -ESRCH; |
10322 |
++ |
10323 |
++ /* |
10324 |
++ * If both a name and a connection ID are given as destination |
10325 |
++ * of a message, check that the currently owning connection of |
10326 |
++ * the name matches the specified ID. |
10327 |
++ * This way, we allow userspace to send the message to a |
10328 |
++ * specific connection by ID only if the connection currently |
10329 |
++ * owns the given name. |
10330 |
++ */ |
10331 |
++ if (msg->dst_id != KDBUS_DST_ID_NAME && |
10332 |
++ msg->dst_id != name->conn->id) |
10333 |
++ return -EREMCHG; |
10334 |
++ |
10335 |
++ if (!name->conn && name->activator) |
10336 |
++ dst = kdbus_conn_ref(name->activator); |
10337 |
++ else |
10338 |
++ dst = kdbus_conn_ref(name->conn); |
10339 |
++ |
10340 |
++ if ((msg->flags & KDBUS_MSG_NO_AUTO_START) && |
10341 |
++ kdbus_conn_is_activator(dst)) { |
10342 |
++ ret = -EADDRNOTAVAIL; |
10343 |
++ goto error; |
10344 |
++ } |
10345 |
++ |
10346 |
++ /* |
10347 |
++ * Record the sequence number of the registered name; it will |
10348 |
++ * be passed on to the queue, in case messages addressed to a |
10349 |
++ * name need to be moved from or to an activator. |
10350 |
++ */ |
10351 |
++ kmsg->dst_name_id = name->name_id; |
10352 |
++ } |
10353 |
++ |
10354 |
++ *out_name = name; |
10355 |
++ *out_dst = dst; |
10356 |
++ return 0; |
10357 |
++ |
10358 |
++error: |
10359 |
++ kdbus_conn_unref(dst); |
10360 |
++ return ret; |
10361 |
++} |
10362 |
++ |
10363 |
++static int kdbus_conn_reply(struct kdbus_conn *src, struct kdbus_kmsg *kmsg) |
10364 |
++{ |
10365 |
++ struct kdbus_name_entry *name = NULL; |
10366 |
++ struct kdbus_reply *reply, *wake = NULL; |
10367 |
++ struct kdbus_conn *dst = NULL; |
10368 |
++ struct kdbus_bus *bus = src->ep->bus; |
10369 |
++ u64 attach; |
10370 |
++ int ret; |
10371 |
++ |
10372 |
++ if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) || |
10373 |
++ WARN_ON(kmsg->msg.flags & KDBUS_MSG_EXPECT_REPLY) || |
10374 |
++ WARN_ON(kmsg->msg.flags & KDBUS_MSG_SIGNAL)) |
10375 |
++ return -EINVAL; |
10376 |
++ |
10377 |
++ /* name-registry must be locked for lookup *and* collecting data */ |
10378 |
++ down_read(&bus->name_registry->rwlock); |
10379 |
++ |
10380 |
++ /* find and pin destination */ |
10381 |
++ |
10382 |
++ ret = kdbus_pin_dst(bus, kmsg, &name, &dst); |
10383 |
++ if (ret < 0) |
10384 |
++ goto exit; |
10385 |
++ |
10386 |
++ mutex_lock(&dst->lock); |
10387 |
++ reply = kdbus_reply_find(src, dst, kmsg->msg.cookie_reply); |
10388 |
++ if (reply) { |
10389 |
++ if (reply->sync) |
10390 |
++ wake = kdbus_reply_ref(reply); |
10391 |
++ kdbus_reply_unlink(reply); |
10392 |
++ } |
10393 |
++ mutex_unlock(&dst->lock); |
10394 |
++ |
10395 |
++ if (!reply) { |
10396 |
++ ret = -EPERM; |
10397 |
++ goto exit; |
10398 |
++ } |
10399 |
++ |
10400 |
++ /* attach metadata */ |
10401 |
++ |
10402 |
++ attach = kdbus_meta_calc_attach_flags(src, dst); |
10403 |
++ |
10404 |
++ if (!src->faked_meta) { |
10405 |
++ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach); |
10406 |
++ if (ret < 0) |
10407 |
++ goto exit; |
10408 |
++ } |
10409 |
++ |
10410 |
++ ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach); |
10411 |
++ if (ret < 0) |
10412 |
++ goto exit; |
10413 |
++ |
10414 |
++ /* send message */ |
10415 |
++ |
10416 |
++ kdbus_bus_eavesdrop(bus, src, kmsg); |
10417 |
++ |
10418 |
++ if (wake) |
10419 |
++ ret = kdbus_conn_entry_sync_attach(dst, kmsg, wake); |
10420 |
++ else |
10421 |
++ ret = kdbus_conn_entry_insert(src, dst, kmsg, NULL); |
10422 |
++ |
10423 |
++exit: |
10424 |
++ up_read(&bus->name_registry->rwlock); |
10425 |
++ kdbus_reply_unref(wake); |
10426 |
++ kdbus_conn_unref(dst); |
10427 |
++ return ret; |
10428 |
++} |
10429 |
++ |
10430 |
++static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src, |
10431 |
++ struct kdbus_kmsg *kmsg, |
10432 |
++ ktime_t exp) |
10433 |
++{ |
10434 |
++ struct kdbus_name_entry *name = NULL; |
10435 |
++ struct kdbus_reply *wait = NULL; |
10436 |
++ struct kdbus_conn *dst = NULL; |
10437 |
++ struct kdbus_bus *bus = src->ep->bus; |
10438 |
++ u64 attach; |
10439 |
++ int ret; |
10440 |
++ |
10441 |
++ if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) || |
10442 |
++ WARN_ON(kmsg->msg.flags & KDBUS_MSG_SIGNAL) || |
10443 |
++ WARN_ON(!(kmsg->msg.flags & KDBUS_MSG_EXPECT_REPLY))) |
10444 |
++ return ERR_PTR(-EINVAL); |
10445 |
++ |
10446 |
++ /* resume previous wait-context, if available */ |
10447 |
++ |
10448 |
++ mutex_lock(&src->lock); |
10449 |
++ wait = kdbus_reply_find(NULL, src, kmsg->msg.cookie); |
10450 |
++ if (wait) { |
10451 |
++ if (wait->interrupted) { |
10452 |
++ kdbus_reply_ref(wait); |
10453 |
++ wait->interrupted = false; |
10454 |
++ } else { |
10455 |
++ wait = NULL; |
10456 |
++ } |
10457 |
++ } |
10458 |
++ mutex_unlock(&src->lock); |
10459 |
++ |
10460 |
++ if (wait) |
10461 |
++ return wait; |
10462 |
++ |
10463 |
++ if (ktime_compare(ktime_get(), exp) >= 0) |
10464 |
++ return ERR_PTR(-ETIMEDOUT); |
10465 |
++ |
10466 |
++ /* name-registry must be locked for lookup *and* collecting data */ |
10467 |
++ down_read(&bus->name_registry->rwlock); |
10468 |
++ |
10469 |
++ /* find and pin destination */ |
10470 |
++ |
10471 |
++ ret = kdbus_pin_dst(bus, kmsg, &name, &dst); |
10472 |
++ if (ret < 0) |
10473 |
++ goto exit; |
10474 |
++ |
10475 |
++ if (!kdbus_conn_policy_talk(src, current_cred(), dst)) { |
10476 |
++ ret = -EPERM; |
10477 |
++ goto exit; |
10478 |
++ } |
10479 |
++ |
10480 |
++ wait = kdbus_reply_new(dst, src, &kmsg->msg, name, true); |
10481 |
++ if (IS_ERR(wait)) { |
10482 |
++ ret = PTR_ERR(wait); |
10483 |
++ wait = NULL; |
10484 |
++ goto exit; |
10485 |
++ } |
10486 |
++ |
10487 |
++ /* attach metadata */ |
10488 |
++ |
10489 |
++ attach = kdbus_meta_calc_attach_flags(src, dst); |
10490 |
++ |
10491 |
++ if (!src->faked_meta) { |
10492 |
++ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach); |
10493 |
++ if (ret < 0) |
10494 |
++ goto exit; |
10495 |
++ } |
10496 |
++ |
10497 |
++ ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach); |
10498 |
++ if (ret < 0) |
10499 |
++ goto exit; |
10500 |
++ |
10501 |
++ /* send message */ |
10502 |
++ |
10503 |
++ kdbus_bus_eavesdrop(bus, src, kmsg); |
10504 |
++ |
10505 |
++ ret = kdbus_conn_entry_insert(src, dst, kmsg, wait); |
10506 |
++ if (ret < 0) |
10507 |
++ goto exit; |
10508 |
++ |
10509 |
++ ret = 0; |
10510 |
++ |
10511 |
++exit: |
10512 |
++ up_read(&bus->name_registry->rwlock); |
10513 |
++ if (ret < 0) { |
10514 |
++ kdbus_reply_unref(wait); |
10515 |
++ wait = ERR_PTR(ret); |
10516 |
++ } |
10517 |
++ kdbus_conn_unref(dst); |
10518 |
++ return wait; |
10519 |
++} |
10520 |
++ |
10521 |
++static int kdbus_conn_unicast(struct kdbus_conn *src, struct kdbus_kmsg *kmsg) |
10522 |
++{ |
10523 |
++ struct kdbus_name_entry *name = NULL; |
10524 |
++ struct kdbus_reply *wait = NULL; |
10525 |
++ struct kdbus_conn *dst = NULL; |
10526 |
++ struct kdbus_bus *bus = src->ep->bus; |
10527 |
++ bool is_signal = (kmsg->msg.flags & KDBUS_MSG_SIGNAL); |
10528 |
++ u64 attach; |
10529 |
++ int ret = 0; |
10530 |
++ |
10531 |
++ if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) || |
10532 |
++ WARN_ON(!(kmsg->msg.flags & KDBUS_MSG_EXPECT_REPLY) && |
10533 |
++ kmsg->msg.cookie_reply != 0)) |
10534 |
++ return -EINVAL; |
10535 |
++ |
10536 |
++ /* name-registry must be locked for lookup *and* collecting data */ |
10537 |
++ down_read(&bus->name_registry->rwlock); |
10538 |
++ |
10539 |
++ /* find and pin destination */ |
10540 |
++ |
10541 |
++ ret = kdbus_pin_dst(bus, kmsg, &name, &dst); |
10542 |
++ if (ret < 0) |
10543 |
++ goto exit; |
10544 |
++ |
10545 |
++ if (is_signal) { |
10546 |
++ /* like broadcasts we eavesdrop even if the msg is dropped */ |
10547 |
++ kdbus_bus_eavesdrop(bus, src, kmsg); |
10548 |
++ |
10549 |
++ /* drop silently if peer is not interested or not privileged */ |
10550 |
++ if (!kdbus_match_db_match_kmsg(dst->match_db, src, kmsg) || |
10551 |
++ !kdbus_conn_policy_talk(dst, NULL, src)) |
10552 |
++ goto exit; |
10553 |
++ } else if (!kdbus_conn_policy_talk(src, current_cred(), dst)) { |
10554 |
++ ret = -EPERM; |
10555 |
++ goto exit; |
10556 |
++ } else if (kmsg->msg.flags & KDBUS_MSG_EXPECT_REPLY) { |
10557 |
++ wait = kdbus_reply_new(dst, src, &kmsg->msg, name, false); |
10558 |
++ if (IS_ERR(wait)) { |
10559 |
++ ret = PTR_ERR(wait); |
10560 |
++ wait = NULL; |
10561 |
++ goto exit; |
10562 |
++ } |
10563 |
++ } |
10564 |
++ |
10565 |
++ /* attach metadata */ |
10566 |
++ |
10567 |
++ attach = kdbus_meta_calc_attach_flags(src, dst); |
10568 |
++ |
10569 |
++ if (!src->faked_meta) { |
10570 |
++ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach); |
10571 |
++ if (ret < 0 && !is_signal) |
10572 |
++ goto exit; |
10573 |
++ } |
10574 |
++ |
10575 |
++ ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach); |
10576 |
++ if (ret < 0 && !is_signal) |
10577 |
++ goto exit; |
10578 |
++ |
10579 |
++ /* send message */ |
10580 |
++ |
10581 |
++ if (!is_signal) |
10582 |
++ kdbus_bus_eavesdrop(bus, src, kmsg); |
10583 |
++ |
10584 |
++ ret = kdbus_conn_entry_insert(src, dst, kmsg, wait); |
10585 |
++ if (ret < 0 && !is_signal) |
10586 |
++ goto exit; |
10587 |
++ |
10588 |
++ /* signals are treated like broadcasts, recv-errors are ignored */ |
10589 |
++ ret = 0; |
10590 |
++ |
10591 |
++exit: |
10592 |
++ up_read(&bus->name_registry->rwlock); |
10593 |
++ kdbus_reply_unref(wait); |
10594 |
++ kdbus_conn_unref(dst); |
10595 |
++ return ret; |
10596 |
++} |
10597 |
++ |
10598 |
++/** |
10599 |
++ * kdbus_conn_move_messages() - move messages from one connection to another |
10600 |
++ * @conn_dst: Connection to copy to |
10601 |
++ * @conn_src: Connection to copy from |
10602 |
++ * @name_id: Filter for the sequence number of the registered |
10603 |
++ * name, 0 means no filtering. |
10604 |
++ * |
10605 |
++ * Move all messages from one connection to another. This is used when |
10606 |
++ * an implementer connection is taking over/giving back a well-known name |
10607 |
++ * from/to an activator connection. |
10608 |
++ */ |
10609 |
++void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, |
10610 |
++ struct kdbus_conn *conn_src, |
10611 |
++ u64 name_id) |
10612 |
++{ |
10613 |
++ struct kdbus_queue_entry *e, *e_tmp; |
10614 |
++ struct kdbus_reply *r, *r_tmp; |
10615 |
++ struct kdbus_bus *bus; |
10616 |
++ struct kdbus_conn *c; |
10617 |
++ LIST_HEAD(msg_list); |
10618 |
++ int i, ret = 0; |
10619 |
++ |
10620 |
++ if (WARN_ON(conn_src == conn_dst)) |
10621 |
++ return; |
10622 |
++ |
10623 |
++ bus = conn_src->ep->bus; |
10624 |
++ |
10625 |
++ /* lock order: domain -> bus -> ep -> names -> conn */ |
10626 |
++ down_read(&bus->conn_rwlock); |
10627 |
++ hash_for_each(bus->conn_hash, i, c, hentry) { |
10628 |
++ if (c == conn_src || c == conn_dst) |
10629 |
++ continue; |
10630 |
++ |
10631 |
++ mutex_lock(&c->lock); |
10632 |
++ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) { |
10633 |
++ if (r->reply_src != conn_src) |
10634 |
++ continue; |
10635 |
++ |
10636 |
++ /* filter messages for a specific name */ |
10637 |
++ if (name_id > 0 && r->name_id != name_id) |
10638 |
++ continue; |
10639 |
++ |
10640 |
++ kdbus_conn_unref(r->reply_src); |
10641 |
++ r->reply_src = kdbus_conn_ref(conn_dst); |
10642 |
++ } |
10643 |
++ mutex_unlock(&c->lock); |
10644 |
++ } |
10645 |
++ up_read(&bus->conn_rwlock); |
10646 |
++ |
10647 |
++ kdbus_conn_lock2(conn_src, conn_dst); |
10648 |
++ list_for_each_entry_safe(e, e_tmp, &conn_src->queue.msg_list, entry) { |
10649 |
++ /* filter messages for a specific name */ |
10650 |
++ if (name_id > 0 && e->dst_name_id != name_id) |
10651 |
++ continue; |
10652 |
++ |
10653 |
++ if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) && |
10654 |
++ e->msg_res && e->msg_res->fds_count > 0) { |
10655 |
++ kdbus_conn_lost_message(conn_dst); |
10656 |
++ kdbus_queue_entry_free(e); |
10657 |
++ continue; |
10658 |
++ } |
10659 |
++ |
10660 |
++ ret = kdbus_queue_entry_move(e, conn_dst); |
10661 |
++ if (ret < 0) { |
10662 |
++ kdbus_conn_lost_message(conn_dst); |
10663 |
++ kdbus_queue_entry_free(e); |
10664 |
++ continue; |
10665 |
++ } |
10666 |
++ } |
10667 |
++ kdbus_conn_unlock2(conn_src, conn_dst); |
10668 |
++ |
10669 |
++ /* wake up poll() */ |
10670 |
++ wake_up_interruptible(&conn_dst->wait); |
10671 |
++} |
10672 |
++ |
10673 |
++/* query the policy-database for all names of @whom */ |
10674 |
++static bool kdbus_conn_policy_query_all(struct kdbus_conn *conn, |
10675 |
++ const struct cred *conn_creds, |
10676 |
++ struct kdbus_policy_db *db, |
10677 |
++ struct kdbus_conn *whom, |
10678 |
++ unsigned int access) |
10679 |
++{ |
10680 |
++ struct kdbus_name_entry *ne; |
10681 |
++ bool pass = false; |
10682 |
++ int res; |
10683 |
++ |
10684 |
++ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
10685 |
++ |
10686 |
++ down_read(&db->entries_rwlock); |
10687 |
++ mutex_lock(&whom->lock); |
10688 |
++ |
10689 |
++ list_for_each_entry(ne, &whom->names_list, conn_entry) { |
10690 |
++ res = kdbus_policy_query_unlocked(db, conn_creds ? : conn->cred, |
10691 |
++ ne->name, |
10692 |
++ kdbus_strhash(ne->name)); |
10693 |
++ if (res >= (int)access) { |
10694 |
++ pass = true; |
10695 |
++ break; |
10696 |
++ } |
10697 |
++ } |
10698 |
++ |
10699 |
++ mutex_unlock(&whom->lock); |
10700 |
++ up_read(&db->entries_rwlock); |
10701 |
++ |
10702 |
++ return pass; |
10703 |
++} |
10704 |
++ |
10705 |
++/** |
10706 |
++ * kdbus_conn_policy_own_name() - verify a connection can own the given name |
10707 |
++ * @conn: Connection |
10708 |
++ * @conn_creds: Credentials of @conn to use for policy check |
10709 |
++ * @name: Name |
10710 |
++ * |
10711 |
++ * This verifies that @conn is allowed to acquire the well-known name @name. |
10712 |
++ * |
10713 |
++ * Return: true if allowed, false if not. |
10714 |
++ */ |
10715 |
++bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, |
10716 |
++ const struct cred *conn_creds, |
10717 |
++ const char *name) |
10718 |
++{ |
10719 |
++ unsigned int hash = kdbus_strhash(name); |
10720 |
++ int res; |
10721 |
++ |
10722 |
++ if (!conn_creds) |
10723 |
++ conn_creds = conn->cred; |
10724 |
++ |
10725 |
++ if (conn->ep->user) { |
10726 |
++ res = kdbus_policy_query(&conn->ep->policy_db, conn_creds, |
10727 |
++ name, hash); |
10728 |
++ if (res < KDBUS_POLICY_OWN) |
10729 |
++ return false; |
10730 |
++ } |
10731 |
++ |
10732 |
++ if (conn->privileged) |
10733 |
++ return true; |
10734 |
++ |
10735 |
++ res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds, |
10736 |
++ name, hash); |
10737 |
++ return res >= KDBUS_POLICY_OWN; |
10738 |
++} |
10739 |
++ |
10740 |
++/** |
10741 |
++ * kdbus_conn_policy_talk() - verify a connection can talk to a given peer |
10742 |
++ * @conn: Connection that tries to talk |
10743 |
++ * @conn_creds: Credentials of @conn to use for policy check |
10744 |
++ * @to: Connection that is talked to |
10745 |
++ * |
10746 |
++ * This verifies that @conn is allowed to talk to @to. |
10747 |
++ * |
10748 |
++ * Return: true if allowed, false if not. |
10749 |
++ */ |
10750 |
++bool kdbus_conn_policy_talk(struct kdbus_conn *conn, |
10751 |
++ const struct cred *conn_creds, |
10752 |
++ struct kdbus_conn *to) |
10753 |
++{ |
10754 |
++ if (!conn_creds) |
10755 |
++ conn_creds = conn->cred; |
10756 |
++ |
10757 |
++ if (conn->ep->user && |
10758 |
++ !kdbus_conn_policy_query_all(conn, conn_creds, &conn->ep->policy_db, |
10759 |
++ to, KDBUS_POLICY_TALK)) |
10760 |
++ return false; |
10761 |
++ |
10762 |
++ if (conn->privileged) |
10763 |
++ return true; |
10764 |
++ if (uid_eq(conn_creds->euid, to->cred->uid)) |
10765 |
++ return true; |
10766 |
++ |
10767 |
++ return kdbus_conn_policy_query_all(conn, conn_creds, |
10768 |
++ &conn->ep->bus->policy_db, to, |
10769 |
++ KDBUS_POLICY_TALK); |
10770 |
++} |
10771 |
++ |
10772 |
++/** |
10773 |
++ * kdbus_conn_policy_see_name_unlocked() - verify a connection can see a given |
10774 |
++ * name |
10775 |
++ * @conn: Connection |
10776 |
++ * @conn_creds: Credentials of @conn to use for policy check |
10777 |
++ * @name: Name |
10778 |
++ * |
10779 |
++ * This verifies that @conn is allowed to see the well-known name @name. Caller |
10780 |
++ * must hold policy-lock. |
10781 |
++ * |
10782 |
++ * Return: true if allowed, false if not. |
10783 |
++ */ |
10784 |
++bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, |
10785 |
++ const struct cred *conn_creds, |
10786 |
++ const char *name) |
10787 |
++{ |
10788 |
++ int res; |
10789 |
++ |
10790 |
++ /* |
10791 |
++ * By default, all names are visible on a bus. SEE policies can only be |
10792 |
++ * installed on custom endpoints, where by default no name is visible. |
10793 |
++ */ |
10794 |
++ if (!conn->ep->user) |
10795 |
++ return true; |
10796 |
++ |
10797 |
++ res = kdbus_policy_query_unlocked(&conn->ep->policy_db, |
10798 |
++ conn_creds ? : conn->cred, |
10799 |
++ name, kdbus_strhash(name)); |
10800 |
++ return res >= KDBUS_POLICY_SEE; |
10801 |
++} |
10802 |
++ |
10803 |
++static bool kdbus_conn_policy_see_name(struct kdbus_conn *conn, |
10804 |
++ const struct cred *conn_creds, |
10805 |
++ const char *name) |
10806 |
++{ |
10807 |
++ bool res; |
10808 |
++ |
10809 |
++ down_read(&conn->ep->policy_db.entries_rwlock); |
10810 |
++ res = kdbus_conn_policy_see_name_unlocked(conn, conn_creds, name); |
10811 |
++ up_read(&conn->ep->policy_db.entries_rwlock); |
10812 |
++ |
10813 |
++ return res; |
10814 |
++} |
10815 |
++ |
10816 |
++static bool kdbus_conn_policy_see(struct kdbus_conn *conn, |
10817 |
++ const struct cred *conn_creds, |
10818 |
++ struct kdbus_conn *whom) |
10819 |
++{ |
10820 |
++ /* |
10821 |
++ * By default, all names are visible on a bus, so a connection can |
10822 |
++ * always see other connections. SEE policies can only be installed on |
10823 |
++ * custom endpoints, where by default no name is visible and we hide |
10824 |
++ * peers from each other, unless you see at least _one_ name of the |
10825 |
++ * peer. |
10826 |
++ */ |
10827 |
++ return !conn->ep->user || |
10828 |
++ kdbus_conn_policy_query_all(conn, conn_creds, |
10829 |
++ &conn->ep->policy_db, whom, |
10830 |
++ KDBUS_POLICY_SEE); |
10831 |
++} |
10832 |
++ |
10833 |
++/** |
10834 |
++ * kdbus_conn_policy_see_notification() - verify a connection is allowed to |
10835 |
++ * receive a given kernel notification |
10836 |
++ * @conn: Connection |
10837 |
++ * @conn_creds: Credentials of @conn to use for policy check |
10838 |
++ * @kmsg: The message carrying the notification |
10839 |
++ * |
10840 |
++ * This checks whether @conn is allowed to see the kernel notification @kmsg. |
10841 |
++ * |
10842 |
++ * Return: true if allowed, false if not. |
10843 |
++ */ |
10844 |
++bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, |
10845 |
++ const struct cred *conn_creds, |
10846 |
++ const struct kdbus_kmsg *kmsg) |
10847 |
++{ |
10848 |
++ if (WARN_ON(kmsg->msg.src_id != KDBUS_SRC_ID_KERNEL)) |
10849 |
++ return false; |
10850 |
++ |
10851 |
++ /* |
10852 |
++ * Depending on the notification type, broadcasted kernel notifications |
10853 |
++ * have to be filtered: |
10854 |
++ * |
10855 |
++ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}: This notification is forwarded |
10856 |
++ * to a peer if, and only if, that peer can see the name this |
10857 |
++ * notification is for. |
10858 |
++ * |
10859 |
++ * KDBUS_ITEM_ID_{ADD,REMOVE}: As new peers cannot have names, and all |
10860 |
++ * names are dropped before a peer is removed, those notifications |
10861 |
++ * cannot be seen on custom endpoints. Thus, we only pass them |
10862 |
++ * through on default endpoints. |
10863 |
++ */ |
10864 |
++ |
10865 |
++ switch (kmsg->notify_type) { |
10866 |
++ case KDBUS_ITEM_NAME_ADD: |
10867 |
++ case KDBUS_ITEM_NAME_REMOVE: |
10868 |
++ case KDBUS_ITEM_NAME_CHANGE: |
10869 |
++ return kdbus_conn_policy_see_name(conn, conn_creds, |
10870 |
++ kmsg->notify_name); |
10871 |
++ |
10872 |
++ case KDBUS_ITEM_ID_ADD: |
10873 |
++ case KDBUS_ITEM_ID_REMOVE: |
10874 |
++ return !conn->ep->user; |
10875 |
++ |
10876 |
++ default: |
10877 |
++ WARN(1, "Invalid type for notification broadcast: %llu\n", |
10878 |
++ (unsigned long long)kmsg->notify_type); |
10879 |
++ return false; |
10880 |
++ } |
10881 |
++} |
10882 |
++ |
10883 |
++/** |
10884 |
++ * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO |
10885 |
++ * @ep: Endpoint to operate on |
10886 |
++ * @privileged: Whether the caller is privileged |
10887 |
++ * @argp: Command payload |
10888 |
++ * |
10889 |
++ * Return: Newly created connection on success, ERR_PTR on failure. |
10890 |
++ */ |
10891 |
++struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged, |
10892 |
++ void __user *argp) |
10893 |
++{ |
10894 |
++ struct kdbus_cmd_hello *cmd; |
10895 |
++ struct kdbus_conn *c = NULL; |
10896 |
++ const char *item_name; |
10897 |
++ int ret; |
10898 |
++ |
10899 |
++ struct kdbus_arg argv[] = { |
10900 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
10901 |
++ { .type = KDBUS_ITEM_NAME }, |
10902 |
++ { .type = KDBUS_ITEM_CREDS }, |
10903 |
++ { .type = KDBUS_ITEM_PIDS }, |
10904 |
++ { .type = KDBUS_ITEM_SECLABEL }, |
10905 |
++ { .type = KDBUS_ITEM_CONN_DESCRIPTION }, |
10906 |
++ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
10907 |
++ }; |
10908 |
++ struct kdbus_args args = { |
10909 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
10910 |
++ KDBUS_HELLO_ACCEPT_FD | |
10911 |
++ KDBUS_HELLO_ACTIVATOR | |
10912 |
++ KDBUS_HELLO_POLICY_HOLDER | |
10913 |
++ KDBUS_HELLO_MONITOR, |
10914 |
++ .argv = argv, |
10915 |
++ .argc = ARRAY_SIZE(argv), |
10916 |
++ }; |
10917 |
++ |
10918 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
10919 |
++ if (ret < 0) |
10920 |
++ return ERR_PTR(ret); |
10921 |
++ if (ret > 0) |
10922 |
++ return NULL; |
10923 |
++ |
10924 |
++ item_name = argv[1].item ? argv[1].item->str : NULL; |
10925 |
++ |
10926 |
++ c = kdbus_conn_new(ep, privileged, cmd, item_name, |
10927 |
++ argv[2].item ? &argv[2].item->creds : NULL, |
10928 |
++ argv[3].item ? &argv[3].item->pids : NULL, |
10929 |
++ argv[4].item ? argv[4].item->str : NULL, |
10930 |
++ argv[5].item ? argv[5].item->str : NULL); |
10931 |
++ if (IS_ERR(c)) { |
10932 |
++ ret = PTR_ERR(c); |
10933 |
++ c = NULL; |
10934 |
++ goto exit; |
10935 |
++ } |
10936 |
++ |
10937 |
++ ret = kdbus_conn_connect(c, item_name); |
10938 |
++ if (ret < 0) |
10939 |
++ goto exit; |
10940 |
++ |
10941 |
++ if (kdbus_conn_is_activator(c) || kdbus_conn_is_policy_holder(c)) { |
10942 |
++ ret = kdbus_conn_acquire(c); |
10943 |
++ if (ret < 0) |
10944 |
++ goto exit; |
10945 |
++ |
10946 |
++ ret = kdbus_policy_set(&c->ep->bus->policy_db, args.items, |
10947 |
++ args.items_size, 1, |
10948 |
++ kdbus_conn_is_policy_holder(c), c); |
10949 |
++ kdbus_conn_release(c); |
10950 |
++ if (ret < 0) |
10951 |
++ goto exit; |
10952 |
++ } |
10953 |
++ |
10954 |
++ if (copy_to_user(argp, cmd, sizeof(*cmd))) |
10955 |
++ ret = -EFAULT; |
10956 |
++ |
10957 |
++exit: |
10958 |
++ ret = kdbus_args_clear(&args, ret); |
10959 |
++ if (ret < 0) { |
10960 |
++ if (c) { |
10961 |
++ kdbus_conn_disconnect(c, false); |
10962 |
++ kdbus_conn_unref(c); |
10963 |
++ } |
10964 |
++ return ERR_PTR(ret); |
10965 |
++ } |
10966 |
++ return c; |
10967 |
++} |
10968 |
++ |
10969 |
++/** |
10970 |
++ * kdbus_cmd_byebye_unlocked() - handle KDBUS_CMD_BYEBYE |
10971 |
++ * @conn: connection to operate on |
10972 |
++ * @argp: command payload |
10973 |
++ * |
10974 |
++ * The caller must not hold any active reference to @conn or this will deadlock. |
10975 |
++ * |
10976 |
++ * Return: 0 on success, negative error code on failure. |
10977 |
++ */ |
10978 |
++int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp) |
10979 |
++{ |
10980 |
++ struct kdbus_cmd *cmd; |
10981 |
++ int ret; |
10982 |
++ |
10983 |
++ struct kdbus_arg argv[] = { |
10984 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
10985 |
++ }; |
10986 |
++ struct kdbus_args args = { |
10987 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
10988 |
++ .argv = argv, |
10989 |
++ .argc = ARRAY_SIZE(argv), |
10990 |
++ }; |
10991 |
++ |
10992 |
++ if (!kdbus_conn_is_ordinary(conn)) |
10993 |
++ return -EOPNOTSUPP; |
10994 |
++ |
10995 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
10996 |
++ if (ret != 0) |
10997 |
++ return ret; |
10998 |
++ |
10999 |
++ ret = kdbus_conn_disconnect(conn, true); |
11000 |
++ return kdbus_args_clear(&args, ret); |
11001 |
++} |
11002 |
++ |
11003 |
++/** |
11004 |
++ * kdbus_cmd_conn_info() - handle KDBUS_CMD_CONN_INFO |
11005 |
++ * @conn: connection to operate on |
11006 |
++ * @argp: command payload |
11007 |
++ * |
11008 |
++ * Return: 0 on success, negative error code on failure. |
11009 |
++ */ |
11010 |
++int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp) |
11011 |
++{ |
11012 |
++ struct kdbus_meta_conn *conn_meta = NULL; |
11013 |
++ struct kdbus_pool_slice *slice = NULL; |
11014 |
++ struct kdbus_name_entry *entry = NULL; |
11015 |
++ struct kdbus_conn *owner_conn = NULL; |
11016 |
++ struct kdbus_info info = {}; |
11017 |
++ struct kdbus_cmd_info *cmd; |
11018 |
++ struct kdbus_bus *bus = conn->ep->bus; |
11019 |
++ struct kvec kvec; |
11020 |
++ size_t meta_size; |
11021 |
++ const char *name; |
11022 |
++ u64 attach_flags; |
11023 |
++ int ret; |
11024 |
++ |
11025 |
++ struct kdbus_arg argv[] = { |
11026 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
11027 |
++ { .type = KDBUS_ITEM_NAME }, |
11028 |
++ }; |
11029 |
++ struct kdbus_args args = { |
11030 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11031 |
++ .argv = argv, |
11032 |
++ .argc = ARRAY_SIZE(argv), |
11033 |
++ }; |
11034 |
++ |
11035 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
11036 |
++ if (ret != 0) |
11037 |
++ return ret; |
11038 |
++ |
11039 |
++ /* registry must be held throughout lookup *and* collecting data */ |
11040 |
++ down_read(&bus->name_registry->rwlock); |
11041 |
++ |
11042 |
++ ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags); |
11043 |
++ if (ret < 0) |
11044 |
++ goto exit; |
11045 |
++ |
11046 |
++ name = argv[1].item ? argv[1].item->str : NULL; |
11047 |
++ |
11048 |
++ if (name) { |
11049 |
++ entry = kdbus_name_lookup_unlocked(bus->name_registry, name); |
11050 |
++ if (!entry || !entry->conn || |
11051 |
++ !kdbus_conn_policy_see_name(conn, current_cred(), name) || |
11052 |
++ (cmd->id != 0 && entry->conn->id != cmd->id)) { |
11053 |
++ /* pretend a name doesn't exist if you cannot see it */ |
11054 |
++ ret = -ESRCH; |
11055 |
++ goto exit; |
11056 |
++ } |
11057 |
++ |
11058 |
++ owner_conn = kdbus_conn_ref(entry->conn); |
11059 |
++ } else if (cmd->id > 0) { |
11060 |
++ owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id); |
11061 |
++ if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(), |
11062 |
++ owner_conn)) { |
11063 |
++ /* pretend an id doesn't exist if you cannot see it */ |
11064 |
++ ret = -ENXIO; |
11065 |
++ goto exit; |
11066 |
++ } |
11067 |
++ } else { |
11068 |
++ ret = -EINVAL; |
11069 |
++ goto exit; |
11070 |
++ } |
11071 |
++ |
11072 |
++ info.id = owner_conn->id; |
11073 |
++ info.flags = owner_conn->flags; |
11074 |
++ kdbus_kvec_set(&kvec, &info, sizeof(info), &info.size); |
11075 |
++ |
11076 |
++ attach_flags &= atomic64_read(&owner_conn->attach_flags_send); |
11077 |
++ |
11078 |
++ conn_meta = kdbus_meta_conn_new(); |
11079 |
++ if (IS_ERR(conn_meta)) { |
11080 |
++ ret = PTR_ERR(conn_meta); |
11081 |
++ conn_meta = NULL; |
11082 |
++ goto exit; |
11083 |
++ } |
11084 |
++ |
11085 |
++ ret = kdbus_meta_conn_collect(conn_meta, NULL, owner_conn, |
11086 |
++ attach_flags); |
11087 |
++ if (ret < 0) |
11088 |
++ goto exit; |
11089 |
++ |
11090 |
++ ret = kdbus_meta_export_prepare(owner_conn->meta, conn_meta, |
11091 |
++ &attach_flags, &meta_size); |
11092 |
++ if (ret < 0) |
11093 |
++ goto exit; |
11094 |
++ |
11095 |
++ slice = kdbus_pool_slice_alloc(conn->pool, |
11096 |
++ info.size + meta_size, false); |
11097 |
++ if (IS_ERR(slice)) { |
11098 |
++ ret = PTR_ERR(slice); |
11099 |
++ slice = NULL; |
11100 |
++ goto exit; |
11101 |
++ } |
11102 |
++ |
11103 |
++ ret = kdbus_meta_export(owner_conn->meta, conn_meta, attach_flags, |
11104 |
++ slice, sizeof(info), &meta_size); |
11105 |
++ if (ret < 0) |
11106 |
++ goto exit; |
11107 |
++ |
11108 |
++ info.size += meta_size; |
11109 |
++ |
11110 |
++ ret = kdbus_pool_slice_copy_kvec(slice, 0, &kvec, 1, sizeof(info)); |
11111 |
++ if (ret < 0) |
11112 |
++ goto exit; |
11113 |
++ |
11114 |
++ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size); |
11115 |
++ |
11116 |
++ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
11117 |
++ kdbus_member_set_user(&cmd->info_size, argp, |
11118 |
++ typeof(*cmd), info_size)) { |
11119 |
++ ret = -EFAULT; |
11120 |
++ goto exit; |
11121 |
++ } |
11122 |
++ |
11123 |
++ ret = 0; |
11124 |
++ |
11125 |
++exit: |
11126 |
++ up_read(&bus->name_registry->rwlock); |
11127 |
++ kdbus_pool_slice_release(slice); |
11128 |
++ kdbus_meta_conn_unref(conn_meta); |
11129 |
++ kdbus_conn_unref(owner_conn); |
11130 |
++ return kdbus_args_clear(&args, ret); |
11131 |
++} |
11132 |
++ |
11133 |
++/** |
11134 |
++ * kdbus_cmd_update() - handle KDBUS_CMD_UPDATE |
11135 |
++ * @conn: connection to operate on |
11136 |
++ * @argp: command payload |
11137 |
++ * |
11138 |
++ * Return: 0 on success, negative error code on failure. |
11139 |
++ */ |
11140 |
++int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp) |
11141 |
++{ |
11142 |
++ struct kdbus_bus *bus = conn->ep->bus; |
11143 |
++ struct kdbus_item *item_policy; |
11144 |
++ u64 *item_attach_send = NULL; |
11145 |
++ u64 *item_attach_recv = NULL; |
11146 |
++ struct kdbus_cmd *cmd; |
11147 |
++ u64 attach_send; |
11148 |
++ u64 attach_recv; |
11149 |
++ int ret; |
11150 |
++ |
11151 |
++ struct kdbus_arg argv[] = { |
11152 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
11153 |
++ { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND }, |
11154 |
++ { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV }, |
11155 |
++ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
11156 |
++ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
11157 |
++ }; |
11158 |
++ struct kdbus_args args = { |
11159 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11160 |
++ .argv = argv, |
11161 |
++ .argc = ARRAY_SIZE(argv), |
11162 |
++ }; |
11163 |
++ |
11164 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
11165 |
++ if (ret != 0) |
11166 |
++ return ret; |
11167 |
++ |
11168 |
++ item_attach_send = argv[1].item ? &argv[1].item->data64[0] : NULL; |
11169 |
++ item_attach_recv = argv[2].item ? &argv[2].item->data64[0] : NULL; |
11170 |
++ item_policy = argv[3].item ? : argv[4].item; |
11171 |
++ |
11172 |
++ if (item_attach_send) { |
11173 |
++ if (!kdbus_conn_is_ordinary(conn) && |
11174 |
++ !kdbus_conn_is_monitor(conn)) { |
11175 |
++ ret = -EOPNOTSUPP; |
11176 |
++ goto exit; |
11177 |
++ } |
11178 |
++ |
11179 |
++ ret = kdbus_sanitize_attach_flags(*item_attach_send, |
11180 |
++ &attach_send); |
11181 |
++ if (ret < 0) |
11182 |
++ goto exit; |
11183 |
++ |
11184 |
++ if (bus->attach_flags_req & ~attach_send) { |
11185 |
++ ret = -EINVAL; |
11186 |
++ goto exit; |
11187 |
++ } |
11188 |
++ } |
11189 |
++ |
11190 |
++ if (item_attach_recv) { |
11191 |
++ if (!kdbus_conn_is_ordinary(conn) && |
11192 |
++ !kdbus_conn_is_monitor(conn) && |
11193 |
++ !kdbus_conn_is_activator(conn)) { |
11194 |
++ ret = -EOPNOTSUPP; |
11195 |
++ goto exit; |
11196 |
++ } |
11197 |
++ |
11198 |
++ ret = kdbus_sanitize_attach_flags(*item_attach_recv, |
11199 |
++ &attach_recv); |
11200 |
++ if (ret < 0) |
11201 |
++ goto exit; |
11202 |
++ } |
11203 |
++ |
11204 |
++ if (item_policy && !kdbus_conn_is_policy_holder(conn)) { |
11205 |
++ ret = -EOPNOTSUPP; |
11206 |
++ goto exit; |
11207 |
++ } |
11208 |
++ |
11209 |
++ /* now that we verified the input, update the connection */ |
11210 |
++ |
11211 |
++ if (item_policy) { |
11212 |
++ ret = kdbus_policy_set(&conn->ep->bus->policy_db, cmd->items, |
11213 |
++ KDBUS_ITEMS_SIZE(cmd, items), |
11214 |
++ 1, true, conn); |
11215 |
++ if (ret < 0) |
11216 |
++ goto exit; |
11217 |
++ } |
11218 |
++ |
11219 |
++ if (item_attach_send) |
11220 |
++ atomic64_set(&conn->attach_flags_send, attach_send); |
11221 |
++ |
11222 |
++ if (item_attach_recv) |
11223 |
++ atomic64_set(&conn->attach_flags_recv, attach_recv); |
11224 |
++ |
11225 |
++exit: |
11226 |
++ return kdbus_args_clear(&args, ret); |
11227 |
++} |
11228 |
++ |
11229 |
++/** |
11230 |
++ * kdbus_cmd_send() - handle KDBUS_CMD_SEND |
11231 |
++ * @conn: connection to operate on |
11232 |
++ * @f: file this command was called on |
11233 |
++ * @argp: command payload |
11234 |
++ * |
11235 |
++ * Return: 0 on success, negative error code on failure. |
11236 |
++ */ |
11237 |
++int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp) |
11238 |
++{ |
11239 |
++ struct kdbus_cmd_send *cmd; |
11240 |
++ struct kdbus_kmsg *kmsg = NULL; |
11241 |
++ struct file *cancel_fd = NULL; |
11242 |
++ int ret; |
11243 |
++ |
11244 |
++ struct kdbus_arg argv[] = { |
11245 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
11246 |
++ { .type = KDBUS_ITEM_CANCEL_FD }, |
11247 |
++ }; |
11248 |
++ struct kdbus_args args = { |
11249 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11250 |
++ KDBUS_SEND_SYNC_REPLY, |
11251 |
++ .argv = argv, |
11252 |
++ .argc = ARRAY_SIZE(argv), |
11253 |
++ }; |
11254 |
++ |
11255 |
++ if (!kdbus_conn_is_ordinary(conn)) |
11256 |
++ return -EOPNOTSUPP; |
11257 |
++ |
11258 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
11259 |
++ if (ret != 0) |
11260 |
++ return ret; |
11261 |
++ |
11262 |
++ cmd->reply.return_flags = 0; |
11263 |
++ kdbus_pool_publish_empty(conn->pool, &cmd->reply.offset, |
11264 |
++ &cmd->reply.msg_size); |
11265 |
++ |
11266 |
++ if (argv[1].item) { |
11267 |
++ cancel_fd = fget(argv[1].item->fds[0]); |
11268 |
++ if (!cancel_fd) { |
11269 |
++ ret = -EBADF; |
11270 |
++ goto exit; |
11271 |
++ } |
11272 |
++ |
11273 |
++ if (!cancel_fd->f_op->poll) { |
11274 |
++ ret = -EINVAL; |
11275 |
++ goto exit; |
11276 |
++ } |
11277 |
++ } |
11278 |
++ |
11279 |
++ kmsg = kdbus_kmsg_new_from_cmd(conn, cmd); |
11280 |
++ if (IS_ERR(kmsg)) { |
11281 |
++ ret = PTR_ERR(kmsg); |
11282 |
++ kmsg = NULL; |
11283 |
++ goto exit; |
11284 |
++ } |
11285 |
++ |
11286 |
++ if (kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) { |
11287 |
++ down_read(&conn->ep->bus->name_registry->rwlock); |
11288 |
++ kdbus_bus_broadcast(conn->ep->bus, conn, kmsg); |
11289 |
++ up_read(&conn->ep->bus->name_registry->rwlock); |
11290 |
++ } else if (cmd->flags & KDBUS_SEND_SYNC_REPLY) { |
11291 |
++ struct kdbus_reply *r; |
11292 |
++ ktime_t exp; |
11293 |
++ |
11294 |
++ exp = ns_to_ktime(kmsg->msg.timeout_ns); |
11295 |
++ r = kdbus_conn_call(conn, kmsg, exp); |
11296 |
++ if (IS_ERR(r)) { |
11297 |
++ ret = PTR_ERR(r); |
11298 |
++ goto exit; |
11299 |
++ } |
11300 |
++ |
11301 |
++ ret = kdbus_conn_wait_reply(conn, cmd, f, cancel_fd, r, exp); |
11302 |
++ kdbus_reply_unref(r); |
11303 |
++ if (ret < 0) |
11304 |
++ goto exit; |
11305 |
++ } else if ((kmsg->msg.flags & KDBUS_MSG_EXPECT_REPLY) || |
11306 |
++ kmsg->msg.cookie_reply == 0) { |
11307 |
++ ret = kdbus_conn_unicast(conn, kmsg); |
11308 |
++ if (ret < 0) |
11309 |
++ goto exit; |
11310 |
++ } else { |
11311 |
++ ret = kdbus_conn_reply(conn, kmsg); |
11312 |
++ if (ret < 0) |
11313 |
++ goto exit; |
11314 |
++ } |
11315 |
++ |
11316 |
++ if (kdbus_member_set_user(&cmd->reply, argp, typeof(*cmd), reply)) |
11317 |
++ ret = -EFAULT; |
11318 |
++ |
11319 |
++exit: |
11320 |
++ if (cancel_fd) |
11321 |
++ fput(cancel_fd); |
11322 |
++ kdbus_kmsg_free(kmsg); |
11323 |
++ return kdbus_args_clear(&args, ret); |
11324 |
++} |
11325 |
++ |
11326 |
++/** |
11327 |
++ * kdbus_cmd_recv() - handle KDBUS_CMD_RECV |
11328 |
++ * @conn: connection to operate on |
11329 |
++ * @argp: command payload |
11330 |
++ * |
11331 |
++ * Return: 0 on success, negative error code on failure. |
11332 |
++ */ |
11333 |
++int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp) |
11334 |
++{ |
11335 |
++ struct kdbus_queue_entry *entry; |
11336 |
++ struct kdbus_cmd_recv *cmd; |
11337 |
++ int ret; |
11338 |
++ |
11339 |
++ struct kdbus_arg argv[] = { |
11340 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
11341 |
++ }; |
11342 |
++ struct kdbus_args args = { |
11343 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11344 |
++ KDBUS_RECV_PEEK | |
11345 |
++ KDBUS_RECV_DROP | |
11346 |
++ KDBUS_RECV_USE_PRIORITY, |
11347 |
++ .argv = argv, |
11348 |
++ .argc = ARRAY_SIZE(argv), |
11349 |
++ }; |
11350 |
++ |
11351 |
++ if (!kdbus_conn_is_ordinary(conn) && |
11352 |
++ !kdbus_conn_is_monitor(conn) && |
11353 |
++ !kdbus_conn_is_activator(conn)) |
11354 |
++ return -EOPNOTSUPP; |
11355 |
++ |
11356 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
11357 |
++ if (ret != 0) |
11358 |
++ return ret; |
11359 |
++ |
11360 |
++ cmd->dropped_msgs = 0; |
11361 |
++ cmd->msg.return_flags = 0; |
11362 |
++ kdbus_pool_publish_empty(conn->pool, &cmd->msg.offset, |
11363 |
++ &cmd->msg.msg_size); |
11364 |
++ |
11365 |
++ /* DROP+priority is not realiably, so prevent it */ |
11366 |
++ if ((cmd->flags & KDBUS_RECV_DROP) && |
11367 |
++ (cmd->flags & KDBUS_RECV_USE_PRIORITY)) { |
11368 |
++ ret = -EINVAL; |
11369 |
++ goto exit; |
11370 |
++ } |
11371 |
++ |
11372 |
++ mutex_lock(&conn->lock); |
11373 |
++ |
11374 |
++ entry = kdbus_queue_peek(&conn->queue, cmd->priority, |
11375 |
++ cmd->flags & KDBUS_RECV_USE_PRIORITY); |
11376 |
++ if (!entry) { |
11377 |
++ mutex_unlock(&conn->lock); |
11378 |
++ ret = -EAGAIN; |
11379 |
++ } else if (cmd->flags & KDBUS_RECV_DROP) { |
11380 |
++ struct kdbus_reply *reply = kdbus_reply_ref(entry->reply); |
11381 |
++ |
11382 |
++ kdbus_queue_entry_free(entry); |
11383 |
++ |
11384 |
++ mutex_unlock(&conn->lock); |
11385 |
++ |
11386 |
++ if (reply) { |
11387 |
++ mutex_lock(&reply->reply_dst->lock); |
11388 |
++ if (!list_empty(&reply->entry)) { |
11389 |
++ kdbus_reply_unlink(reply); |
11390 |
++ if (reply->sync) |
11391 |
++ kdbus_sync_reply_wakeup(reply, -EPIPE); |
11392 |
++ else |
11393 |
++ kdbus_notify_reply_dead(conn->ep->bus, |
11394 |
++ reply->reply_dst->id, |
11395 |
++ reply->cookie); |
11396 |
++ } |
11397 |
++ mutex_unlock(&reply->reply_dst->lock); |
11398 |
++ kdbus_notify_flush(conn->ep->bus); |
11399 |
++ } |
11400 |
++ |
11401 |
++ kdbus_reply_unref(reply); |
11402 |
++ } else { |
11403 |
++ bool install_fds; |
11404 |
++ |
11405 |
++ /* |
11406 |
++ * PEEK just returns the location of the next message. Do not |
11407 |
++ * install FDs nor memfds nor anything else. The only |
11408 |
++ * information of interest should be the message header and |
11409 |
++ * metadata. Any FD numbers in the payload is undefined for |
11410 |
++ * PEEK'ed messages. |
11411 |
++ * Also make sure to never install fds into a connection that |
11412 |
++ * has refused to receive any. Ordinary connections will not get |
11413 |
++ * messages with FDs queued (the receiver will get -ECOMM), but |
11414 |
++ * eavesdroppers might. |
11415 |
++ */ |
11416 |
++ install_fds = (conn->flags & KDBUS_HELLO_ACCEPT_FD) && |
11417 |
++ !(cmd->flags & KDBUS_RECV_PEEK); |
11418 |
++ |
11419 |
++ ret = kdbus_queue_entry_install(entry, |
11420 |
++ &cmd->msg.return_flags, |
11421 |
++ install_fds); |
11422 |
++ if (ret < 0) { |
11423 |
++ mutex_unlock(&conn->lock); |
11424 |
++ goto exit; |
11425 |
++ } |
11426 |
++ |
11427 |
++ kdbus_pool_slice_publish(entry->slice, &cmd->msg.offset, |
11428 |
++ &cmd->msg.msg_size); |
11429 |
++ |
11430 |
++ if (!(cmd->flags & KDBUS_RECV_PEEK)) |
11431 |
++ kdbus_queue_entry_free(entry); |
11432 |
++ |
11433 |
++ mutex_unlock(&conn->lock); |
11434 |
++ } |
11435 |
++ |
11436 |
++ cmd->dropped_msgs = atomic_xchg(&conn->lost_count, 0); |
11437 |
++ if (cmd->dropped_msgs > 0) |
11438 |
++ cmd->return_flags |= KDBUS_RECV_RETURN_DROPPED_MSGS; |
11439 |
++ |
11440 |
++ if (kdbus_member_set_user(&cmd->msg, argp, typeof(*cmd), msg) || |
11441 |
++ kdbus_member_set_user(&cmd->dropped_msgs, argp, typeof(*cmd), |
11442 |
++ dropped_msgs)) |
11443 |
++ ret = -EFAULT; |
11444 |
++ |
11445 |
++exit: |
11446 |
++ return kdbus_args_clear(&args, ret); |
11447 |
++} |
11448 |
++ |
11449 |
++/** |
11450 |
++ * kdbus_cmd_free() - handle KDBUS_CMD_FREE |
11451 |
++ * @conn: connection to operate on |
11452 |
++ * @argp: command payload |
11453 |
++ * |
11454 |
++ * Return: 0 on success, negative error code on failure. |
11455 |
++ */ |
11456 |
++int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp) |
11457 |
++{ |
11458 |
++ struct kdbus_cmd_free *cmd; |
11459 |
++ int ret; |
11460 |
++ |
11461 |
++ struct kdbus_arg argv[] = { |
11462 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
11463 |
++ }; |
11464 |
++ struct kdbus_args args = { |
11465 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11466 |
++ .argv = argv, |
11467 |
++ .argc = ARRAY_SIZE(argv), |
11468 |
++ }; |
11469 |
++ |
11470 |
++ if (!kdbus_conn_is_ordinary(conn) && |
11471 |
++ !kdbus_conn_is_monitor(conn) && |
11472 |
++ !kdbus_conn_is_activator(conn)) |
11473 |
++ return -EOPNOTSUPP; |
11474 |
++ |
11475 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
11476 |
++ if (ret != 0) |
11477 |
++ return ret; |
11478 |
++ |
11479 |
++ ret = kdbus_pool_release_offset(conn->pool, cmd->offset); |
11480 |
++ |
11481 |
++ return kdbus_args_clear(&args, ret); |
11482 |
++} |
11483 |
+diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h |
11484 |
+new file mode 100644 |
11485 |
+index 0000000..d1ffe90 |
11486 |
+--- /dev/null |
11487 |
++++ b/ipc/kdbus/connection.h |
11488 |
+@@ -0,0 +1,257 @@ |
11489 |
++/* |
11490 |
++ * Copyright (C) 2013-2015 Kay Sievers |
11491 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
11492 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
11493 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
11494 |
++ * Copyright (C) 2013-2015 Linux Foundation |
11495 |
++ * Copyright (C) 2014-2015 Djalal Harouni |
11496 |
++ * |
11497 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
11498 |
++ * the terms of the GNU Lesser General Public License as published by the |
11499 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
11500 |
++ * your option) any later version. |
11501 |
++ */ |
11502 |
++ |
11503 |
++#ifndef __KDBUS_CONNECTION_H |
11504 |
++#define __KDBUS_CONNECTION_H |
11505 |
++ |
11506 |
++#include <linux/atomic.h> |
11507 |
++#include <linux/kref.h> |
11508 |
++#include <linux/lockdep.h> |
11509 |
++#include <linux/path.h> |
11510 |
++ |
11511 |
++#include "limits.h" |
11512 |
++#include "metadata.h" |
11513 |
++#include "pool.h" |
11514 |
++#include "queue.h" |
11515 |
++#include "util.h" |
11516 |
++ |
11517 |
++#define KDBUS_HELLO_SPECIAL_CONN (KDBUS_HELLO_ACTIVATOR | \ |
11518 |
++ KDBUS_HELLO_POLICY_HOLDER | \ |
11519 |
++ KDBUS_HELLO_MONITOR) |
11520 |
++ |
11521 |
++struct kdbus_quota; |
11522 |
++struct kdbus_kmsg; |
11523 |
++ |
11524 |
++/** |
11525 |
++ * struct kdbus_conn - connection to a bus |
11526 |
++ * @kref: Reference count |
11527 |
++ * @active: Active references to the connection |
11528 |
++ * @id: Connection ID |
11529 |
++ * @flags: KDBUS_HELLO_* flags |
11530 |
++ * @attach_flags_send: KDBUS_ATTACH_* flags for sending |
11531 |
++ * @attach_flags_recv: KDBUS_ATTACH_* flags for receiving |
11532 |
++ * @description: Human-readable connection description, used for |
11533 |
++ * debugging. This field is only set when the |
11534 |
++ * connection is created. |
11535 |
++ * @ep: The endpoint this connection belongs to |
11536 |
++ * @lock: Connection data lock |
11537 |
++ * @hentry: Entry in ID <-> connection map |
11538 |
++ * @ep_entry: Entry in endpoint |
11539 |
++ * @monitor_entry: Entry in monitor, if the connection is a monitor |
11540 |
++ * @reply_list: List of connections this connection should |
11541 |
++ * reply to |
11542 |
++ * @work: Delayed work to handle timeouts |
11543 |
++ * activator for |
11544 |
++ * @match_db: Subscription filter to broadcast messages |
11545 |
++ * @meta: Active connection creator's metadata/credentials, |
11546 |
++ * either from the handle or from HELLO |
11547 |
++ * @pool: The user's buffer to receive messages |
11548 |
++ * @user: Owner of the connection |
11549 |
++ * @cred: The credentials of the connection at creation time |
11550 |
++ * @name_count: Number of owned well-known names |
11551 |
++ * @request_count: Number of pending requests issued by this |
11552 |
++ * connection that are waiting for replies from |
11553 |
++ * other peers |
11554 |
++ * @lost_count: Number of lost broadcast messages |
11555 |
++ * @wait: Wake up this endpoint |
11556 |
++ * @queue: The message queue associated with this connection |
11557 |
++ * @quota: Array of per-user quota indexed by user->id |
11558 |
++ * @n_quota: Number of elements in quota array |
11559 |
++ * @activator_of: Well-known name entry this connection acts as an |
11560 |
++ * @names_list: List of well-known names |
11561 |
++ * @names_queue_list: Well-known names this connection waits for |
11562 |
++ * @privileged: Whether this connection is privileged on the bus |
11563 |
++ * @faked_meta: Whether the metadata was faked on HELLO |
11564 |
++ */ |
11565 |
++struct kdbus_conn { |
11566 |
++ struct kref kref; |
11567 |
++ atomic_t active; |
11568 |
++#ifdef CONFIG_DEBUG_LOCK_ALLOC |
11569 |
++ struct lockdep_map dep_map; |
11570 |
++#endif |
11571 |
++ u64 id; |
11572 |
++ u64 flags; |
11573 |
++ atomic64_t attach_flags_send; |
11574 |
++ atomic64_t attach_flags_recv; |
11575 |
++ const char *description; |
11576 |
++ struct kdbus_ep *ep; |
11577 |
++ struct mutex lock; |
11578 |
++ struct hlist_node hentry; |
11579 |
++ struct list_head ep_entry; |
11580 |
++ struct list_head monitor_entry; |
11581 |
++ struct list_head reply_list; |
11582 |
++ struct delayed_work work; |
11583 |
++ struct kdbus_match_db *match_db; |
11584 |
++ struct kdbus_meta_proc *meta; |
11585 |
++ struct kdbus_pool *pool; |
11586 |
++ struct kdbus_user *user; |
11587 |
++ const struct cred *cred; |
11588 |
++ atomic_t name_count; |
11589 |
++ atomic_t request_count; |
11590 |
++ atomic_t lost_count; |
11591 |
++ wait_queue_head_t wait; |
11592 |
++ struct kdbus_queue queue; |
11593 |
++ |
11594 |
++ struct kdbus_quota *quota; |
11595 |
++ unsigned int n_quota; |
11596 |
++ |
11597 |
++ /* protected by registry->rwlock */ |
11598 |
++ struct kdbus_name_entry *activator_of; |
11599 |
++ struct list_head names_list; |
11600 |
++ struct list_head names_queue_list; |
11601 |
++ |
11602 |
++ bool privileged:1; |
11603 |
++ bool faked_meta:1; |
11604 |
++}; |
11605 |
++ |
11606 |
++struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn); |
11607 |
++struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn); |
11608 |
++bool kdbus_conn_active(const struct kdbus_conn *conn); |
11609 |
++int kdbus_conn_acquire(struct kdbus_conn *conn); |
11610 |
++void kdbus_conn_release(struct kdbus_conn *conn); |
11611 |
++int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty); |
11612 |
++bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name); |
11613 |
++int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, |
11614 |
++ size_t memory, size_t fds); |
11615 |
++void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, |
11616 |
++ size_t memory, size_t fds); |
11617 |
++void kdbus_conn_lost_message(struct kdbus_conn *c); |
11618 |
++int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, |
11619 |
++ struct kdbus_conn *conn_dst, |
11620 |
++ const struct kdbus_kmsg *kmsg, |
11621 |
++ struct kdbus_reply *reply); |
11622 |
++void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, |
11623 |
++ struct kdbus_conn *conn_src, |
11624 |
++ u64 name_id); |
11625 |
++ |
11626 |
++/* policy */ |
11627 |
++bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, |
11628 |
++ const struct cred *conn_creds, |
11629 |
++ const char *name); |
11630 |
++bool kdbus_conn_policy_talk(struct kdbus_conn *conn, |
11631 |
++ const struct cred *conn_creds, |
11632 |
++ struct kdbus_conn *to); |
11633 |
++bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, |
11634 |
++ const struct cred *curr_creds, |
11635 |
++ const char *name); |
11636 |
++bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, |
11637 |
++ const struct cred *curr_creds, |
11638 |
++ const struct kdbus_kmsg *kmsg); |
11639 |
++ |
11640 |
++/* command dispatcher */ |
11641 |
++struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged, |
11642 |
++ void __user *argp); |
11643 |
++int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp); |
11644 |
++int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp); |
11645 |
++int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp); |
11646 |
++int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp); |
11647 |
++int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp); |
11648 |
++int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp); |
11649 |
++ |
11650 |
++/** |
11651 |
++ * kdbus_conn_is_ordinary() - Check if connection is ordinary |
11652 |
++ * @conn: The connection to check |
11653 |
++ * |
11654 |
++ * Return: Non-zero if the connection is an ordinary connection |
11655 |
++ */ |
11656 |
++static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn) |
11657 |
++{ |
11658 |
++ return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN); |
11659 |
++} |
11660 |
++ |
11661 |
++/** |
11662 |
++ * kdbus_conn_is_activator() - Check if connection is an activator |
11663 |
++ * @conn: The connection to check |
11664 |
++ * |
11665 |
++ * Return: Non-zero if the connection is an activator |
11666 |
++ */ |
11667 |
++static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn) |
11668 |
++{ |
11669 |
++ return conn->flags & KDBUS_HELLO_ACTIVATOR; |
11670 |
++} |
11671 |
++ |
11672 |
++/** |
11673 |
++ * kdbus_conn_is_policy_holder() - Check if connection is a policy holder |
11674 |
++ * @conn: The connection to check |
11675 |
++ * |
11676 |
++ * Return: Non-zero if the connection is a policy holder |
11677 |
++ */ |
11678 |
++static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn) |
11679 |
++{ |
11680 |
++ return conn->flags & KDBUS_HELLO_POLICY_HOLDER; |
11681 |
++} |
11682 |
++ |
11683 |
++/** |
11684 |
++ * kdbus_conn_is_monitor() - Check if connection is a monitor |
11685 |
++ * @conn: The connection to check |
11686 |
++ * |
11687 |
++ * Return: Non-zero if the connection is a monitor |
11688 |
++ */ |
11689 |
++static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn) |
11690 |
++{ |
11691 |
++ return conn->flags & KDBUS_HELLO_MONITOR; |
11692 |
++} |
11693 |
++ |
11694 |
++/** |
11695 |
++ * kdbus_conn_lock2() - Lock two connections |
11696 |
++ * @a: connection A to lock or NULL |
11697 |
++ * @b: connection B to lock or NULL |
11698 |
++ * |
11699 |
++ * Lock two connections at once. As we need to have a stable locking order, we |
11700 |
++ * always lock the connection with lower memory address first. |
11701 |
++ */ |
11702 |
++static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b) |
11703 |
++{ |
11704 |
++ if (a < b) { |
11705 |
++ if (a) |
11706 |
++ mutex_lock(&a->lock); |
11707 |
++ if (b && b != a) |
11708 |
++ mutex_lock_nested(&b->lock, !!a); |
11709 |
++ } else { |
11710 |
++ if (b) |
11711 |
++ mutex_lock(&b->lock); |
11712 |
++ if (a && a != b) |
11713 |
++ mutex_lock_nested(&a->lock, !!b); |
11714 |
++ } |
11715 |
++} |
11716 |
++ |
11717 |
++/** |
11718 |
++ * kdbus_conn_unlock2() - Unlock two connections |
11719 |
++ * @a: connection A to unlock or NULL |
11720 |
++ * @b: connection B to unlock or NULL |
11721 |
++ * |
11722 |
++ * Unlock two connections at once. See kdbus_conn_lock2(). |
11723 |
++ */ |
11724 |
++static inline void kdbus_conn_unlock2(struct kdbus_conn *a, |
11725 |
++ struct kdbus_conn *b) |
11726 |
++{ |
11727 |
++ if (a) |
11728 |
++ mutex_unlock(&a->lock); |
11729 |
++ if (b && b != a) |
11730 |
++ mutex_unlock(&b->lock); |
11731 |
++} |
11732 |
++ |
11733 |
++/** |
11734 |
++ * kdbus_conn_assert_active() - lockdep assert on active lock |
11735 |
++ * @conn: connection that shall be active |
11736 |
++ * |
11737 |
++ * This verifies via lockdep that the caller holds an active reference to the |
11738 |
++ * given connection. |
11739 |
++ */ |
11740 |
++static inline void kdbus_conn_assert_active(struct kdbus_conn *conn) |
11741 |
++{ |
11742 |
++ lockdep_assert_held(conn); |
11743 |
++} |
11744 |
++ |
11745 |
++#endif |
11746 |
+diff --git a/ipc/kdbus/domain.c b/ipc/kdbus/domain.c |
11747 |
+new file mode 100644 |
11748 |
+index 0000000..ac9f760 |
11749 |
+--- /dev/null |
11750 |
++++ b/ipc/kdbus/domain.c |
11751 |
+@@ -0,0 +1,296 @@ |
11752 |
++/* |
11753 |
++ * Copyright (C) 2013-2015 Kay Sievers |
11754 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
11755 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
11756 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
11757 |
++ * Copyright (C) 2013-2015 Linux Foundation |
11758 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
11759 |
++ * |
11760 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
11761 |
++ * the terms of the GNU Lesser General Public License as published by the |
11762 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
11763 |
++ * your option) any later version. |
11764 |
++ */ |
11765 |
++ |
11766 |
++#include <linux/fs.h> |
11767 |
++#include <linux/idr.h> |
11768 |
++#include <linux/init.h> |
11769 |
++#include <linux/module.h> |
11770 |
++#include <linux/sched.h> |
11771 |
++#include <linux/sizes.h> |
11772 |
++#include <linux/slab.h> |
11773 |
++#include <linux/uaccess.h> |
11774 |
++ |
11775 |
++#include "bus.h" |
11776 |
++#include "domain.h" |
11777 |
++#include "handle.h" |
11778 |
++#include "item.h" |
11779 |
++#include "limits.h" |
11780 |
++#include "util.h" |
11781 |
++ |
11782 |
++static void kdbus_domain_control_free(struct kdbus_node *node) |
11783 |
++{ |
11784 |
++ kfree(node); |
11785 |
++} |
11786 |
++ |
11787 |
++static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain, |
11788 |
++ unsigned int access) |
11789 |
++{ |
11790 |
++ struct kdbus_node *node; |
11791 |
++ int ret; |
11792 |
++ |
11793 |
++ node = kzalloc(sizeof(*node), GFP_KERNEL); |
11794 |
++ if (!node) |
11795 |
++ return ERR_PTR(-ENOMEM); |
11796 |
++ |
11797 |
++ kdbus_node_init(node, KDBUS_NODE_CONTROL); |
11798 |
++ |
11799 |
++ node->free_cb = kdbus_domain_control_free; |
11800 |
++ node->mode = domain->node.mode; |
11801 |
++ node->mode = S_IRUSR | S_IWUSR; |
11802 |
++ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
11803 |
++ node->mode |= S_IRGRP | S_IWGRP; |
11804 |
++ if (access & KDBUS_MAKE_ACCESS_WORLD) |
11805 |
++ node->mode |= S_IROTH | S_IWOTH; |
11806 |
++ |
11807 |
++ ret = kdbus_node_link(node, &domain->node, "control"); |
11808 |
++ if (ret < 0) |
11809 |
++ goto exit_free; |
11810 |
++ |
11811 |
++ return node; |
11812 |
++ |
11813 |
++exit_free: |
11814 |
++ kdbus_node_deactivate(node); |
11815 |
++ kdbus_node_unref(node); |
11816 |
++ return ERR_PTR(ret); |
11817 |
++} |
11818 |
++ |
11819 |
++static void kdbus_domain_free(struct kdbus_node *node) |
11820 |
++{ |
11821 |
++ struct kdbus_domain *domain = |
11822 |
++ container_of(node, struct kdbus_domain, node); |
11823 |
++ |
11824 |
++ put_user_ns(domain->user_namespace); |
11825 |
++ ida_destroy(&domain->user_ida); |
11826 |
++ idr_destroy(&domain->user_idr); |
11827 |
++ kfree(domain); |
11828 |
++} |
11829 |
++ |
11830 |
++/** |
11831 |
++ * kdbus_domain_new() - create a new domain |
11832 |
++ * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*) |
11833 |
++ * |
11834 |
++ * Return: a new kdbus_domain on success, ERR_PTR on failure |
11835 |
++ */ |
11836 |
++struct kdbus_domain *kdbus_domain_new(unsigned int access) |
11837 |
++{ |
11838 |
++ struct kdbus_domain *d; |
11839 |
++ int ret; |
11840 |
++ |
11841 |
++ d = kzalloc(sizeof(*d), GFP_KERNEL); |
11842 |
++ if (!d) |
11843 |
++ return ERR_PTR(-ENOMEM); |
11844 |
++ |
11845 |
++ kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN); |
11846 |
++ |
11847 |
++ d->node.free_cb = kdbus_domain_free; |
11848 |
++ d->node.mode = S_IRUSR | S_IXUSR; |
11849 |
++ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
11850 |
++ d->node.mode |= S_IRGRP | S_IXGRP; |
11851 |
++ if (access & KDBUS_MAKE_ACCESS_WORLD) |
11852 |
++ d->node.mode |= S_IROTH | S_IXOTH; |
11853 |
++ |
11854 |
++ mutex_init(&d->lock); |
11855 |
++ idr_init(&d->user_idr); |
11856 |
++ ida_init(&d->user_ida); |
11857 |
++ |
11858 |
++ /* Pin user namespace so we can guarantee domain-unique bus * names. */ |
11859 |
++ d->user_namespace = get_user_ns(current_user_ns()); |
11860 |
++ |
11861 |
++ ret = kdbus_node_link(&d->node, NULL, NULL); |
11862 |
++ if (ret < 0) |
11863 |
++ goto exit_unref; |
11864 |
++ |
11865 |
++ return d; |
11866 |
++ |
11867 |
++exit_unref: |
11868 |
++ kdbus_node_deactivate(&d->node); |
11869 |
++ kdbus_node_unref(&d->node); |
11870 |
++ return ERR_PTR(ret); |
11871 |
++} |
11872 |
++ |
11873 |
++/** |
11874 |
++ * kdbus_domain_ref() - take a domain reference |
11875 |
++ * @domain: Domain |
11876 |
++ * |
11877 |
++ * Return: the domain itself |
11878 |
++ */ |
11879 |
++struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain) |
11880 |
++{ |
11881 |
++ if (domain) |
11882 |
++ kdbus_node_ref(&domain->node); |
11883 |
++ return domain; |
11884 |
++} |
11885 |
++ |
11886 |
++/** |
11887 |
++ * kdbus_domain_unref() - drop a domain reference |
11888 |
++ * @domain: Domain |
11889 |
++ * |
11890 |
++ * When the last reference is dropped, the domain internal structure |
11891 |
++ * is freed. |
11892 |
++ * |
11893 |
++ * Return: NULL |
11894 |
++ */ |
11895 |
++struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain) |
11896 |
++{ |
11897 |
++ if (domain) |
11898 |
++ kdbus_node_unref(&domain->node); |
11899 |
++ return NULL; |
11900 |
++} |
11901 |
++ |
11902 |
++/** |
11903 |
++ * kdbus_domain_populate() - populate static domain nodes |
11904 |
++ * @domain: domain to populate |
11905 |
++ * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes |
11906 |
++ * |
11907 |
++ * Allocate and activate static sub-nodes of the given domain. This will fail if |
11908 |
++ * you call it on a non-active node or if the domain was already populated. |
11909 |
++ * |
11910 |
++ * Return: 0 on success, negative error code on failure. |
11911 |
++ */ |
11912 |
++int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access) |
11913 |
++{ |
11914 |
++ struct kdbus_node *control; |
11915 |
++ |
11916 |
++ /* |
11917 |
++ * Create a control-node for this domain. We drop our own reference |
11918 |
++ * immediately, effectively causing the node to be deactivated and |
11919 |
++ * released when the parent domain is. |
11920 |
++ */ |
11921 |
++ control = kdbus_domain_control_new(domain, access); |
11922 |
++ if (IS_ERR(control)) |
11923 |
++ return PTR_ERR(control); |
11924 |
++ |
11925 |
++ kdbus_node_activate(control); |
11926 |
++ kdbus_node_unref(control); |
11927 |
++ return 0; |
11928 |
++} |
11929 |
++ |
11930 |
++/** |
11931 |
++ * kdbus_user_lookup() - lookup a kdbus_user object |
11932 |
++ * @domain: domain of the user |
11933 |
++ * @uid: uid of the user; INVALID_UID for an anon user |
11934 |
++ * |
11935 |
++ * Lookup the kdbus user accounting object for the given domain. If INVALID_UID |
11936 |
++ * is passed, a new anonymous user is created which is private to the caller. |
11937 |
++ * |
11938 |
++ * Return: The user object is returned, ERR_PTR on failure. |
11939 |
++ */ |
11940 |
++struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid) |
11941 |
++{ |
11942 |
++ struct kdbus_user *u = NULL, *old = NULL; |
11943 |
++ int ret; |
11944 |
++ |
11945 |
++ mutex_lock(&domain->lock); |
11946 |
++ |
11947 |
++ if (uid_valid(uid)) { |
11948 |
++ old = idr_find(&domain->user_idr, __kuid_val(uid)); |
11949 |
++ /* |
11950 |
++ * If the object is about to be destroyed, ignore it and |
11951 |
++ * replace the slot in the IDR later on. |
11952 |
++ */ |
11953 |
++ if (old && kref_get_unless_zero(&old->kref)) { |
11954 |
++ mutex_unlock(&domain->lock); |
11955 |
++ return old; |
11956 |
++ } |
11957 |
++ } |
11958 |
++ |
11959 |
++ u = kzalloc(sizeof(*u), GFP_KERNEL); |
11960 |
++ if (!u) { |
11961 |
++ ret = -ENOMEM; |
11962 |
++ goto exit; |
11963 |
++ } |
11964 |
++ |
11965 |
++ kref_init(&u->kref); |
11966 |
++ u->domain = kdbus_domain_ref(domain); |
11967 |
++ u->uid = uid; |
11968 |
++ atomic_set(&u->buses, 0); |
11969 |
++ atomic_set(&u->connections, 0); |
11970 |
++ |
11971 |
++ if (uid_valid(uid)) { |
11972 |
++ if (old) { |
11973 |
++ idr_replace(&domain->user_idr, u, __kuid_val(uid)); |
11974 |
++ old->uid = INVALID_UID; /* mark old as removed */ |
11975 |
++ } else { |
11976 |
++ ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid), |
11977 |
++ __kuid_val(uid) + 1, GFP_KERNEL); |
11978 |
++ if (ret < 0) |
11979 |
++ goto exit; |
11980 |
++ } |
11981 |
++ } |
11982 |
++ |
11983 |
++ /* |
11984 |
++ * Allocate the smallest possible index for this user; used |
11985 |
++ * in arrays for accounting user quota in receiver queues. |
11986 |
++ */ |
11987 |
++ ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL); |
11988 |
++ if (ret < 0) |
11989 |
++ goto exit; |
11990 |
++ |
11991 |
++ u->id = ret; |
11992 |
++ mutex_unlock(&domain->lock); |
11993 |
++ return u; |
11994 |
++ |
11995 |
++exit: |
11996 |
++ if (u) { |
11997 |
++ if (uid_valid(u->uid)) |
11998 |
++ idr_remove(&domain->user_idr, __kuid_val(u->uid)); |
11999 |
++ kdbus_domain_unref(u->domain); |
12000 |
++ kfree(u); |
12001 |
++ } |
12002 |
++ mutex_unlock(&domain->lock); |
12003 |
++ return ERR_PTR(ret); |
12004 |
++} |
12005 |
++ |
12006 |
++static void __kdbus_user_free(struct kref *kref) |
12007 |
++{ |
12008 |
++ struct kdbus_user *user = container_of(kref, struct kdbus_user, kref); |
12009 |
++ |
12010 |
++ WARN_ON(atomic_read(&user->buses) > 0); |
12011 |
++ WARN_ON(atomic_read(&user->connections) > 0); |
12012 |
++ |
12013 |
++ mutex_lock(&user->domain->lock); |
12014 |
++ ida_simple_remove(&user->domain->user_ida, user->id); |
12015 |
++ if (uid_valid(user->uid)) |
12016 |
++ idr_remove(&user->domain->user_idr, __kuid_val(user->uid)); |
12017 |
++ mutex_unlock(&user->domain->lock); |
12018 |
++ |
12019 |
++ kdbus_domain_unref(user->domain); |
12020 |
++ kfree(user); |
12021 |
++} |
12022 |
++ |
12023 |
++/** |
12024 |
++ * kdbus_user_ref() - take a user reference |
12025 |
++ * @u: User |
12026 |
++ * |
12027 |
++ * Return: @u is returned |
12028 |
++ */ |
12029 |
++struct kdbus_user *kdbus_user_ref(struct kdbus_user *u) |
12030 |
++{ |
12031 |
++ if (u) |
12032 |
++ kref_get(&u->kref); |
12033 |
++ return u; |
12034 |
++} |
12035 |
++ |
12036 |
++/** |
12037 |
++ * kdbus_user_unref() - drop a user reference |
12038 |
++ * @u: User |
12039 |
++ * |
12040 |
++ * Return: NULL |
12041 |
++ */ |
12042 |
++struct kdbus_user *kdbus_user_unref(struct kdbus_user *u) |
12043 |
++{ |
12044 |
++ if (u) |
12045 |
++ kref_put(&u->kref, __kdbus_user_free); |
12046 |
++ return NULL; |
12047 |
++} |
12048 |
+diff --git a/ipc/kdbus/domain.h b/ipc/kdbus/domain.h |
12049 |
+new file mode 100644 |
12050 |
+index 0000000..447a2bd |
12051 |
+--- /dev/null |
12052 |
++++ b/ipc/kdbus/domain.h |
12053 |
+@@ -0,0 +1,77 @@ |
12054 |
++/* |
12055 |
++ * Copyright (C) 2013-2015 Kay Sievers |
12056 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12057 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12058 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12059 |
++ * Copyright (C) 2013-2015 Linux Foundation |
12060 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12061 |
++ * |
12062 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
12063 |
++ * the terms of the GNU Lesser General Public License as published by the |
12064 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
12065 |
++ * your option) any later version. |
12066 |
++ */ |
12067 |
++ |
12068 |
++#ifndef __KDBUS_DOMAIN_H |
12069 |
++#define __KDBUS_DOMAIN_H |
12070 |
++ |
12071 |
++#include <linux/fs.h> |
12072 |
++#include <linux/idr.h> |
12073 |
++#include <linux/kref.h> |
12074 |
++#include <linux/user_namespace.h> |
12075 |
++ |
12076 |
++#include "node.h" |
12077 |
++ |
12078 |
++/** |
12079 |
++ * struct kdbus_domain - domain for buses |
12080 |
++ * @node: Underlying API node |
12081 |
++ * @lock: Domain data lock |
12082 |
++ * @last_id: Last used object id |
12083 |
++ * @user_idr: Set of all users indexed by UID |
12084 |
++ * @user_ida: Set of all users to compute small indices |
12085 |
++ * @user_namespace: User namespace, pinned at creation time |
12086 |
++ * @dentry: Root dentry of VFS mount (don't use outside of kdbusfs) |
12087 |
++ */ |
12088 |
++struct kdbus_domain { |
12089 |
++ struct kdbus_node node; |
12090 |
++ struct mutex lock; |
12091 |
++ atomic64_t last_id; |
12092 |
++ struct idr user_idr; |
12093 |
++ struct ida user_ida; |
12094 |
++ struct user_namespace *user_namespace; |
12095 |
++ struct dentry *dentry; |
12096 |
++}; |
12097 |
++ |
12098 |
++/** |
12099 |
++ * struct kdbus_user - resource accounting for users |
12100 |
++ * @kref: Reference counter |
12101 |
++ * @domain: Domain of the user |
12102 |
++ * @id: Index of this user |
12103 |
++ * @uid: UID of the user |
12104 |
++ * @buses: Number of buses the user has created |
12105 |
++ * @connections: Number of connections the user has created |
12106 |
++ */ |
12107 |
++struct kdbus_user { |
12108 |
++ struct kref kref; |
12109 |
++ struct kdbus_domain *domain; |
12110 |
++ unsigned int id; |
12111 |
++ kuid_t uid; |
12112 |
++ atomic_t buses; |
12113 |
++ atomic_t connections; |
12114 |
++}; |
12115 |
++ |
12116 |
++#define kdbus_domain_from_node(_node) \ |
12117 |
++ container_of((_node), struct kdbus_domain, node) |
12118 |
++ |
12119 |
++struct kdbus_domain *kdbus_domain_new(unsigned int access); |
12120 |
++struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain); |
12121 |
++struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain); |
12122 |
++int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access); |
12123 |
++ |
12124 |
++#define KDBUS_USER_KERNEL_ID 0 /* ID 0 is reserved for kernel accounting */ |
12125 |
++ |
12126 |
++struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid); |
12127 |
++struct kdbus_user *kdbus_user_ref(struct kdbus_user *u); |
12128 |
++struct kdbus_user *kdbus_user_unref(struct kdbus_user *u); |
12129 |
++ |
12130 |
++#endif |
12131 |
+diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c |
12132 |
+new file mode 100644 |
12133 |
+index 0000000..174d274 |
12134 |
+--- /dev/null |
12135 |
++++ b/ipc/kdbus/endpoint.c |
12136 |
+@@ -0,0 +1,275 @@ |
12137 |
++/* |
12138 |
++ * Copyright (C) 2013-2015 Kay Sievers |
12139 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12140 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12141 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12142 |
++ * Copyright (C) 2013-2015 Linux Foundation |
12143 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12144 |
++ * |
12145 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
12146 |
++ * the terms of the GNU Lesser General Public License as published by the |
12147 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
12148 |
++ * your option) any later version. |
12149 |
++ */ |
12150 |
++ |
12151 |
++#include <linux/fs.h> |
12152 |
++#include <linux/idr.h> |
12153 |
++#include <linux/init.h> |
12154 |
++#include <linux/module.h> |
12155 |
++#include <linux/sched.h> |
12156 |
++#include <linux/sizes.h> |
12157 |
++#include <linux/slab.h> |
12158 |
++#include <linux/uaccess.h> |
12159 |
++#include <linux/uio.h> |
12160 |
++ |
12161 |
++#include "bus.h" |
12162 |
++#include "connection.h" |
12163 |
++#include "domain.h" |
12164 |
++#include "endpoint.h" |
12165 |
++#include "handle.h" |
12166 |
++#include "item.h" |
12167 |
++#include "message.h" |
12168 |
++#include "policy.h" |
12169 |
++ |
12170 |
++static void kdbus_ep_free(struct kdbus_node *node) |
12171 |
++{ |
12172 |
++ struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); |
12173 |
++ |
12174 |
++ WARN_ON(!list_empty(&ep->conn_list)); |
12175 |
++ |
12176 |
++ kdbus_policy_db_clear(&ep->policy_db); |
12177 |
++ kdbus_bus_unref(ep->bus); |
12178 |
++ kdbus_user_unref(ep->user); |
12179 |
++ kfree(ep); |
12180 |
++} |
12181 |
++ |
12182 |
++static void kdbus_ep_release(struct kdbus_node *node, bool was_active) |
12183 |
++{ |
12184 |
++ struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); |
12185 |
++ |
12186 |
++ /* disconnect all connections to this endpoint */ |
12187 |
++ for (;;) { |
12188 |
++ struct kdbus_conn *conn; |
12189 |
++ |
12190 |
++ mutex_lock(&ep->lock); |
12191 |
++ conn = list_first_entry_or_null(&ep->conn_list, |
12192 |
++ struct kdbus_conn, |
12193 |
++ ep_entry); |
12194 |
++ if (!conn) { |
12195 |
++ mutex_unlock(&ep->lock); |
12196 |
++ break; |
12197 |
++ } |
12198 |
++ |
12199 |
++ /* take reference, release lock, disconnect without lock */ |
12200 |
++ kdbus_conn_ref(conn); |
12201 |
++ mutex_unlock(&ep->lock); |
12202 |
++ |
12203 |
++ kdbus_conn_disconnect(conn, false); |
12204 |
++ kdbus_conn_unref(conn); |
12205 |
++ } |
12206 |
++} |
12207 |
++ |
12208 |
++/** |
12209 |
++ * kdbus_ep_new() - create a new endpoint |
12210 |
++ * @bus: The bus this endpoint will be created for |
12211 |
++ * @name: The name of the endpoint |
12212 |
++ * @access: The access flags for this node (KDBUS_MAKE_ACCESS_*) |
12213 |
++ * @uid: The uid of the node |
12214 |
++ * @gid: The gid of the node |
12215 |
++ * @is_custom: Whether this is a custom endpoint |
12216 |
++ * |
12217 |
++ * This function will create a new enpoint with the given |
12218 |
++ * name and properties for a given bus. |
12219 |
++ * |
12220 |
++ * Return: a new kdbus_ep on success, ERR_PTR on failure. |
12221 |
++ */ |
12222 |
++struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, |
12223 |
++ unsigned int access, kuid_t uid, kgid_t gid, |
12224 |
++ bool is_custom) |
12225 |
++{ |
12226 |
++ struct kdbus_ep *e; |
12227 |
++ int ret; |
12228 |
++ |
12229 |
++ /* |
12230 |
++ * Validate only custom endpoints names, default endpoints |
12231 |
++ * with a "bus" name are created when the bus is created |
12232 |
++ */ |
12233 |
++ if (is_custom) { |
12234 |
++ ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace, |
12235 |
++ uid); |
12236 |
++ if (ret < 0) |
12237 |
++ return ERR_PTR(ret); |
12238 |
++ } |
12239 |
++ |
12240 |
++ e = kzalloc(sizeof(*e), GFP_KERNEL); |
12241 |
++ if (!e) |
12242 |
++ return ERR_PTR(-ENOMEM); |
12243 |
++ |
12244 |
++ kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT); |
12245 |
++ |
12246 |
++ e->node.free_cb = kdbus_ep_free; |
12247 |
++ e->node.release_cb = kdbus_ep_release; |
12248 |
++ e->node.uid = uid; |
12249 |
++ e->node.gid = gid; |
12250 |
++ e->node.mode = S_IRUSR | S_IWUSR; |
12251 |
++ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
12252 |
++ e->node.mode |= S_IRGRP | S_IWGRP; |
12253 |
++ if (access & KDBUS_MAKE_ACCESS_WORLD) |
12254 |
++ e->node.mode |= S_IROTH | S_IWOTH; |
12255 |
++ |
12256 |
++ mutex_init(&e->lock); |
12257 |
++ INIT_LIST_HEAD(&e->conn_list); |
12258 |
++ kdbus_policy_db_init(&e->policy_db); |
12259 |
++ e->bus = kdbus_bus_ref(bus); |
12260 |
++ |
12261 |
++ ret = kdbus_node_link(&e->node, &bus->node, name); |
12262 |
++ if (ret < 0) |
12263 |
++ goto exit_unref; |
12264 |
++ |
12265 |
++ /* |
12266 |
++ * Transactions on custom endpoints are never accounted on the global |
12267 |
++ * user limits. Instead, for each custom endpoint, we create a custom, |
12268 |
++ * unique user, which all transactions are accounted on. Regardless of |
12269 |
++ * the user using that endpoint, it is always accounted on the same |
12270 |
++ * user-object. This budget is not shared with ordinary users on |
12271 |
++ * non-custom endpoints. |
12272 |
++ */ |
12273 |
++ if (is_custom) { |
12274 |
++ e->user = kdbus_user_lookup(bus->domain, INVALID_UID); |
12275 |
++ if (IS_ERR(e->user)) { |
12276 |
++ ret = PTR_ERR(e->user); |
12277 |
++ e->user = NULL; |
12278 |
++ goto exit_unref; |
12279 |
++ } |
12280 |
++ } |
12281 |
++ |
12282 |
++ return e; |
12283 |
++ |
12284 |
++exit_unref: |
12285 |
++ kdbus_node_deactivate(&e->node); |
12286 |
++ kdbus_node_unref(&e->node); |
12287 |
++ return ERR_PTR(ret); |
12288 |
++} |
12289 |
++ |
12290 |
++/** |
12291 |
++ * kdbus_ep_ref() - increase the reference counter of a kdbus_ep |
12292 |
++ * @ep: The endpoint to reference |
12293 |
++ * |
12294 |
++ * Every user of an endpoint, except for its creator, must add a reference to |
12295 |
++ * the kdbus_ep instance using this function. |
12296 |
++ * |
12297 |
++ * Return: the ep itself |
12298 |
++ */ |
12299 |
++struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep) |
12300 |
++{ |
12301 |
++ if (ep) |
12302 |
++ kdbus_node_ref(&ep->node); |
12303 |
++ return ep; |
12304 |
++} |
12305 |
++ |
12306 |
++/** |
12307 |
++ * kdbus_ep_unref() - decrease the reference counter of a kdbus_ep |
12308 |
++ * @ep: The ep to unref |
12309 |
++ * |
12310 |
++ * Release a reference. If the reference count drops to 0, the ep will be |
12311 |
++ * freed. |
12312 |
++ * |
12313 |
++ * Return: NULL |
12314 |
++ */ |
12315 |
++struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep) |
12316 |
++{ |
12317 |
++ if (ep) |
12318 |
++ kdbus_node_unref(&ep->node); |
12319 |
++ return NULL; |
12320 |
++} |
12321 |
++ |
12322 |
++/** |
12323 |
++ * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE |
12324 |
++ * @bus: bus to operate on |
12325 |
++ * @argp: command payload |
12326 |
++ * |
12327 |
++ * Return: Newly created endpoint on success, ERR_PTR on failure. |
12328 |
++ */ |
12329 |
++struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp) |
12330 |
++{ |
12331 |
++ const char *item_make_name; |
12332 |
++ struct kdbus_ep *ep = NULL; |
12333 |
++ struct kdbus_cmd *cmd; |
12334 |
++ int ret; |
12335 |
++ |
12336 |
++ struct kdbus_arg argv[] = { |
12337 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
12338 |
++ { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, |
12339 |
++ }; |
12340 |
++ struct kdbus_args args = { |
12341 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
12342 |
++ KDBUS_MAKE_ACCESS_GROUP | |
12343 |
++ KDBUS_MAKE_ACCESS_WORLD, |
12344 |
++ .argv = argv, |
12345 |
++ .argc = ARRAY_SIZE(argv), |
12346 |
++ }; |
12347 |
++ |
12348 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
12349 |
++ if (ret < 0) |
12350 |
++ return ERR_PTR(ret); |
12351 |
++ if (ret > 0) |
12352 |
++ return NULL; |
12353 |
++ |
12354 |
++ item_make_name = argv[1].item->str; |
12355 |
++ |
12356 |
++ ep = kdbus_ep_new(bus, item_make_name, cmd->flags, |
12357 |
++ current_euid(), current_egid(), true); |
12358 |
++ if (IS_ERR(ep)) { |
12359 |
++ ret = PTR_ERR(ep); |
12360 |
++ ep = NULL; |
12361 |
++ goto exit; |
12362 |
++ } |
12363 |
++ |
12364 |
++ if (!kdbus_node_activate(&ep->node)) { |
12365 |
++ ret = -ESHUTDOWN; |
12366 |
++ goto exit; |
12367 |
++ } |
12368 |
++ |
12369 |
++exit: |
12370 |
++ ret = kdbus_args_clear(&args, ret); |
12371 |
++ if (ret < 0) { |
12372 |
++ if (ep) { |
12373 |
++ kdbus_node_deactivate(&ep->node); |
12374 |
++ kdbus_ep_unref(ep); |
12375 |
++ } |
12376 |
++ return ERR_PTR(ret); |
12377 |
++ } |
12378 |
++ return ep; |
12379 |
++} |
12380 |
++ |
12381 |
++/** |
12382 |
++ * kdbus_cmd_ep_update() - handle KDBUS_CMD_ENDPOINT_UPDATE |
12383 |
++ * @ep: endpoint to operate on |
12384 |
++ * @argp: command payload |
12385 |
++ * |
12386 |
++ * Return: Newly created endpoint on success, ERR_PTR on failure. |
12387 |
++ */ |
12388 |
++int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp) |
12389 |
++{ |
12390 |
++ struct kdbus_cmd *cmd; |
12391 |
++ int ret; |
12392 |
++ |
12393 |
++ struct kdbus_arg argv[] = { |
12394 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
12395 |
++ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
12396 |
++ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
12397 |
++ }; |
12398 |
++ struct kdbus_args args = { |
12399 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
12400 |
++ .argv = argv, |
12401 |
++ .argc = ARRAY_SIZE(argv), |
12402 |
++ }; |
12403 |
++ |
12404 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
12405 |
++ if (ret != 0) |
12406 |
++ return ret; |
12407 |
++ |
12408 |
++ ret = kdbus_policy_set(&ep->policy_db, args.items, args.items_size, |
12409 |
++ 0, true, ep); |
12410 |
++ return kdbus_args_clear(&args, ret); |
12411 |
++} |
12412 |
+diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h |
12413 |
+new file mode 100644 |
12414 |
+index 0000000..d31954b |
12415 |
+--- /dev/null |
12416 |
++++ b/ipc/kdbus/endpoint.h |
12417 |
+@@ -0,0 +1,67 @@ |
12418 |
++/* |
12419 |
++ * Copyright (C) 2013-2015 Kay Sievers |
12420 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12421 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12422 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12423 |
++ * Copyright (C) 2013-2015 Linux Foundation |
12424 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12425 |
++ * |
12426 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
12427 |
++ * the terms of the GNU Lesser General Public License as published by the |
12428 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
12429 |
++ * your option) any later version. |
12430 |
++ */ |
12431 |
++ |
12432 |
++#ifndef __KDBUS_ENDPOINT_H |
12433 |
++#define __KDBUS_ENDPOINT_H |
12434 |
++ |
12435 |
++#include <linux/list.h> |
12436 |
++#include <linux/mutex.h> |
12437 |
++#include <linux/uidgid.h> |
12438 |
++#include "node.h" |
12439 |
++#include "policy.h" |
12440 |
++ |
12441 |
++struct kdbus_bus; |
12442 |
++struct kdbus_user; |
12443 |
++ |
12444 |
++/** |
12445 |
++ * struct kdbus_ep - enpoint to access a bus |
12446 |
++ * @node: The kdbus node |
12447 |
++ * @lock: Endpoint data lock |
12448 |
++ * @bus: Bus behind this endpoint |
12449 |
++ * @user: Custom enpoints account against an anonymous user |
12450 |
++ * @policy_db: Uploaded policy |
12451 |
++ * @conn_list: Connections of this endpoint |
12452 |
++ * |
12453 |
++ * An enpoint offers access to a bus; the default endpoint node name is "bus". |
12454 |
++ * Additional custom endpoints to the same bus can be created and they can |
12455 |
++ * carry their own policies/filters. |
12456 |
++ */ |
12457 |
++struct kdbus_ep { |
12458 |
++ struct kdbus_node node; |
12459 |
++ struct mutex lock; |
12460 |
++ |
12461 |
++ /* static */ |
12462 |
++ struct kdbus_bus *bus; |
12463 |
++ struct kdbus_user *user; |
12464 |
++ |
12465 |
++ /* protected by own locks */ |
12466 |
++ struct kdbus_policy_db policy_db; |
12467 |
++ |
12468 |
++ /* protected by ep->lock */ |
12469 |
++ struct list_head conn_list; |
12470 |
++}; |
12471 |
++ |
12472 |
++#define kdbus_ep_from_node(_node) \ |
12473 |
++ container_of((_node), struct kdbus_ep, node) |
12474 |
++ |
12475 |
++struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, |
12476 |
++ unsigned int access, kuid_t uid, kgid_t gid, |
12477 |
++ bool policy); |
12478 |
++struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep); |
12479 |
++struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep); |
12480 |
++ |
12481 |
++struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp); |
12482 |
++int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp); |
12483 |
++ |
12484 |
++#endif |
12485 |
+diff --git a/ipc/kdbus/fs.c b/ipc/kdbus/fs.c |
12486 |
+new file mode 100644 |
12487 |
+index 0000000..d01f33b |
12488 |
+--- /dev/null |
12489 |
++++ b/ipc/kdbus/fs.c |
12490 |
+@@ -0,0 +1,510 @@ |
12491 |
++/* |
12492 |
++ * Copyright (C) 2013-2015 Kay Sievers |
12493 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12494 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12495 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12496 |
++ * Copyright (C) 2013-2015 Linux Foundation |
12497 |
++ * |
12498 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
12499 |
++ * the terms of the GNU Lesser General Public License as published by the |
12500 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
12501 |
++ * your option) any later version. |
12502 |
++ */ |
12503 |
++ |
12504 |
++#include <linux/dcache.h> |
12505 |
++#include <linux/fs.h> |
12506 |
++#include <linux/fsnotify.h> |
12507 |
++#include <linux/init.h> |
12508 |
++#include <linux/ipc_namespace.h> |
12509 |
++#include <linux/magic.h> |
12510 |
++#include <linux/module.h> |
12511 |
++#include <linux/mount.h> |
12512 |
++#include <linux/mutex.h> |
12513 |
++#include <linux/namei.h> |
12514 |
++#include <linux/pagemap.h> |
12515 |
++#include <linux/sched.h> |
12516 |
++#include <linux/slab.h> |
12517 |
++ |
12518 |
++#include "bus.h" |
12519 |
++#include "domain.h" |
12520 |
++#include "endpoint.h" |
12521 |
++#include "fs.h" |
12522 |
++#include "handle.h" |
12523 |
++#include "node.h" |
12524 |
++ |
12525 |
++#define kdbus_node_from_dentry(_dentry) \ |
12526 |
++ ((struct kdbus_node *)(_dentry)->d_fsdata) |
12527 |
++ |
12528 |
++static struct inode *fs_inode_get(struct super_block *sb, |
12529 |
++ struct kdbus_node *node); |
12530 |
++ |
12531 |
++/* |
12532 |
++ * Directory Management |
12533 |
++ */ |
12534 |
++ |
12535 |
++static inline unsigned char kdbus_dt_type(struct kdbus_node *node) |
12536 |
++{ |
12537 |
++ switch (node->type) { |
12538 |
++ case KDBUS_NODE_DOMAIN: |
12539 |
++ case KDBUS_NODE_BUS: |
12540 |
++ return DT_DIR; |
12541 |
++ case KDBUS_NODE_CONTROL: |
12542 |
++ case KDBUS_NODE_ENDPOINT: |
12543 |
++ return DT_REG; |
12544 |
++ } |
12545 |
++ |
12546 |
++ return DT_UNKNOWN; |
12547 |
++} |
12548 |
++ |
12549 |
++static int fs_dir_fop_iterate(struct file *file, struct dir_context *ctx) |
12550 |
++{ |
12551 |
++ struct dentry *dentry = file->f_path.dentry; |
12552 |
++ struct kdbus_node *parent = kdbus_node_from_dentry(dentry); |
12553 |
++ struct kdbus_node *old, *next = file->private_data; |
12554 |
++ |
12555 |
++ /* |
12556 |
++ * kdbusfs directory iterator (modelled after sysfs/kernfs) |
12557 |
++ * When iterating kdbusfs directories, we iterate all children of the |
12558 |
++ * parent kdbus_node object. We use ctx->pos to store the hash of the |
12559 |
++ * child and file->private_data to store a reference to the next node |
12560 |
++ * object. If ctx->pos is not modified via llseek while you iterate a |
12561 |
++ * directory, then we use the file->private_data node pointer to |
12562 |
++ * directly access the next node in the tree. |
12563 |
++ * However, if you directly seek on the directory, we have to find the |
12564 |
++ * closest node to that position and cannot use our node pointer. This |
12565 |
++ * means iterating the rb-tree to find the closest match and start over |
12566 |
++ * from there. |
12567 |
++ * Note that hash values are not neccessarily unique. Therefore, llseek |
12568 |
++ * is not guaranteed to seek to the same node that you got when you |
12569 |
++ * retrieved the position. Seeking to 0, 1, 2 and >=INT_MAX is safe, |
12570 |
++ * though. We could use the inode-number as position, but this would |
12571 |
++ * require another rb-tree for fast access. Kernfs and others already |
12572 |
++ * ignore those conflicts, so we should be fine, too. |
12573 |
++ */ |
12574 |
++ |
12575 |
++ if (!dir_emit_dots(file, ctx)) |
12576 |
++ return 0; |
12577 |
++ |
12578 |
++ /* acquire @next; if deactivated, or seek detected, find next node */ |
12579 |
++ old = next; |
12580 |
++ if (next && ctx->pos == next->hash) { |
12581 |
++ if (kdbus_node_acquire(next)) |
12582 |
++ kdbus_node_ref(next); |
12583 |
++ else |
12584 |
++ next = kdbus_node_next_child(parent, next); |
12585 |
++ } else { |
12586 |
++ next = kdbus_node_find_closest(parent, ctx->pos); |
12587 |
++ } |
12588 |
++ kdbus_node_unref(old); |
12589 |
++ |
12590 |
++ while (next) { |
12591 |
++ /* emit @next */ |
12592 |
++ file->private_data = next; |
12593 |
++ ctx->pos = next->hash; |
12594 |
++ |
12595 |
++ kdbus_node_release(next); |
12596 |
++ |
12597 |
++ if (!dir_emit(ctx, next->name, strlen(next->name), next->id, |
12598 |
++ kdbus_dt_type(next))) |
12599 |
++ return 0; |
12600 |
++ |
12601 |
++ /* find next node after @next */ |
12602 |
++ old = next; |
12603 |
++ next = kdbus_node_next_child(parent, next); |
12604 |
++ kdbus_node_unref(old); |
12605 |
++ } |
12606 |
++ |
12607 |
++ file->private_data = NULL; |
12608 |
++ ctx->pos = INT_MAX; |
12609 |
++ |
12610 |
++ return 0; |
12611 |
++} |
12612 |
++ |
12613 |
++static loff_t fs_dir_fop_llseek(struct file *file, loff_t offset, int whence) |
12614 |
++{ |
12615 |
++ struct inode *inode = file_inode(file); |
12616 |
++ loff_t ret; |
12617 |
++ |
12618 |
++ /* protect f_off against fop_iterate */ |
12619 |
++ mutex_lock(&inode->i_mutex); |
12620 |
++ ret = generic_file_llseek(file, offset, whence); |
12621 |
++ mutex_unlock(&inode->i_mutex); |
12622 |
++ |
12623 |
++ return ret; |
12624 |
++} |
12625 |
++ |
12626 |
++static int fs_dir_fop_release(struct inode *inode, struct file *file) |
12627 |
++{ |
12628 |
++ kdbus_node_unref(file->private_data); |
12629 |
++ return 0; |
12630 |
++} |
12631 |
++ |
12632 |
++static const struct file_operations fs_dir_fops = { |
12633 |
++ .read = generic_read_dir, |
12634 |
++ .iterate = fs_dir_fop_iterate, |
12635 |
++ .llseek = fs_dir_fop_llseek, |
12636 |
++ .release = fs_dir_fop_release, |
12637 |
++}; |
12638 |
++ |
12639 |
++static struct dentry *fs_dir_iop_lookup(struct inode *dir, |
12640 |
++ struct dentry *dentry, |
12641 |
++ unsigned int flags) |
12642 |
++{ |
12643 |
++ struct dentry *dnew = NULL; |
12644 |
++ struct kdbus_node *parent; |
12645 |
++ struct kdbus_node *node; |
12646 |
++ struct inode *inode; |
12647 |
++ |
12648 |
++ parent = kdbus_node_from_dentry(dentry->d_parent); |
12649 |
++ if (!kdbus_node_acquire(parent)) |
12650 |
++ return NULL; |
12651 |
++ |
12652 |
++ /* returns reference to _acquired_ child node */ |
12653 |
++ node = kdbus_node_find_child(parent, dentry->d_name.name); |
12654 |
++ if (node) { |
12655 |
++ dentry->d_fsdata = node; |
12656 |
++ inode = fs_inode_get(dir->i_sb, node); |
12657 |
++ if (IS_ERR(inode)) |
12658 |
++ dnew = ERR_CAST(inode); |
12659 |
++ else |
12660 |
++ dnew = d_splice_alias(inode, dentry); |
12661 |
++ |
12662 |
++ kdbus_node_release(node); |
12663 |
++ } |
12664 |
++ |
12665 |
++ kdbus_node_release(parent); |
12666 |
++ return dnew; |
12667 |
++} |
12668 |
++ |
12669 |
++static const struct inode_operations fs_dir_iops = { |
12670 |
++ .permission = generic_permission, |
12671 |
++ .lookup = fs_dir_iop_lookup, |
12672 |
++}; |
12673 |
++ |
12674 |
++/* |
12675 |
++ * Inode Management |
12676 |
++ */ |
12677 |
++ |
12678 |
++static const struct inode_operations fs_inode_iops = { |
12679 |
++ .permission = generic_permission, |
12680 |
++}; |
12681 |
++ |
12682 |
++static struct inode *fs_inode_get(struct super_block *sb, |
12683 |
++ struct kdbus_node *node) |
12684 |
++{ |
12685 |
++ struct inode *inode; |
12686 |
++ |
12687 |
++ inode = iget_locked(sb, node->id); |
12688 |
++ if (!inode) |
12689 |
++ return ERR_PTR(-ENOMEM); |
12690 |
++ if (!(inode->i_state & I_NEW)) |
12691 |
++ return inode; |
12692 |
++ |
12693 |
++ inode->i_private = kdbus_node_ref(node); |
12694 |
++ inode->i_mapping->a_ops = &empty_aops; |
12695 |
++ inode->i_mode = node->mode & S_IALLUGO; |
12696 |
++ inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
12697 |
++ inode->i_uid = node->uid; |
12698 |
++ inode->i_gid = node->gid; |
12699 |
++ |
12700 |
++ switch (node->type) { |
12701 |
++ case KDBUS_NODE_DOMAIN: |
12702 |
++ case KDBUS_NODE_BUS: |
12703 |
++ inode->i_mode |= S_IFDIR; |
12704 |
++ inode->i_op = &fs_dir_iops; |
12705 |
++ inode->i_fop = &fs_dir_fops; |
12706 |
++ set_nlink(inode, 2); |
12707 |
++ break; |
12708 |
++ case KDBUS_NODE_CONTROL: |
12709 |
++ case KDBUS_NODE_ENDPOINT: |
12710 |
++ inode->i_mode |= S_IFREG; |
12711 |
++ inode->i_op = &fs_inode_iops; |
12712 |
++ inode->i_fop = &kdbus_handle_ops; |
12713 |
++ break; |
12714 |
++ } |
12715 |
++ |
12716 |
++ unlock_new_inode(inode); |
12717 |
++ |
12718 |
++ return inode; |
12719 |
++} |
12720 |
++ |
12721 |
++/* |
12722 |
++ * Superblock Management |
12723 |
++ */ |
12724 |
++ |
12725 |
++static int fs_super_dop_revalidate(struct dentry *dentry, unsigned int flags) |
12726 |
++{ |
12727 |
++ struct kdbus_node *node; |
12728 |
++ |
12729 |
++ /* Force lookup on negatives */ |
12730 |
++ if (!dentry->d_inode) |
12731 |
++ return 0; |
12732 |
++ |
12733 |
++ node = kdbus_node_from_dentry(dentry); |
12734 |
++ |
12735 |
++ /* see whether the node has been removed */ |
12736 |
++ if (!kdbus_node_is_active(node)) |
12737 |
++ return 0; |
12738 |
++ |
12739 |
++ return 1; |
12740 |
++} |
12741 |
++ |
12742 |
++static void fs_super_dop_release(struct dentry *dentry) |
12743 |
++{ |
12744 |
++ kdbus_node_unref(dentry->d_fsdata); |
12745 |
++} |
12746 |
++ |
12747 |
++static const struct dentry_operations fs_super_dops = { |
12748 |
++ .d_revalidate = fs_super_dop_revalidate, |
12749 |
++ .d_release = fs_super_dop_release, |
12750 |
++}; |
12751 |
++ |
12752 |
++static void fs_super_sop_evict_inode(struct inode *inode) |
12753 |
++{ |
12754 |
++ struct kdbus_node *node = kdbus_node_from_inode(inode); |
12755 |
++ |
12756 |
++ truncate_inode_pages_final(&inode->i_data); |
12757 |
++ clear_inode(inode); |
12758 |
++ kdbus_node_unref(node); |
12759 |
++} |
12760 |
++ |
12761 |
++static const struct super_operations fs_super_sops = { |
12762 |
++ .statfs = simple_statfs, |
12763 |
++ .drop_inode = generic_delete_inode, |
12764 |
++ .evict_inode = fs_super_sop_evict_inode, |
12765 |
++}; |
12766 |
++ |
12767 |
++static int fs_super_fill(struct super_block *sb) |
12768 |
++{ |
12769 |
++ struct kdbus_domain *domain = sb->s_fs_info; |
12770 |
++ struct inode *inode; |
12771 |
++ int ret; |
12772 |
++ |
12773 |
++ sb->s_blocksize = PAGE_CACHE_SIZE; |
12774 |
++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
12775 |
++ sb->s_magic = KDBUS_SUPER_MAGIC; |
12776 |
++ sb->s_maxbytes = MAX_LFS_FILESIZE; |
12777 |
++ sb->s_op = &fs_super_sops; |
12778 |
++ sb->s_time_gran = 1; |
12779 |
++ |
12780 |
++ inode = fs_inode_get(sb, &domain->node); |
12781 |
++ if (IS_ERR(inode)) |
12782 |
++ return PTR_ERR(inode); |
12783 |
++ |
12784 |
++ sb->s_root = d_make_root(inode); |
12785 |
++ if (!sb->s_root) { |
12786 |
++ /* d_make_root iput()s the inode on failure */ |
12787 |
++ return -ENOMEM; |
12788 |
++ } |
12789 |
++ |
12790 |
++ /* sb holds domain reference */ |
12791 |
++ sb->s_root->d_fsdata = &domain->node; |
12792 |
++ sb->s_d_op = &fs_super_dops; |
12793 |
++ |
12794 |
++ /* sb holds root reference */ |
12795 |
++ domain->dentry = sb->s_root; |
12796 |
++ |
12797 |
++ if (!kdbus_node_activate(&domain->node)) |
12798 |
++ return -ESHUTDOWN; |
12799 |
++ |
12800 |
++ ret = kdbus_domain_populate(domain, KDBUS_MAKE_ACCESS_WORLD); |
12801 |
++ if (ret < 0) |
12802 |
++ return ret; |
12803 |
++ |
12804 |
++ sb->s_flags |= MS_ACTIVE; |
12805 |
++ return 0; |
12806 |
++} |
12807 |
++ |
12808 |
++static void fs_super_kill(struct super_block *sb) |
12809 |
++{ |
12810 |
++ struct kdbus_domain *domain = sb->s_fs_info; |
12811 |
++ |
12812 |
++ if (domain) { |
12813 |
++ kdbus_node_deactivate(&domain->node); |
12814 |
++ domain->dentry = NULL; |
12815 |
++ } |
12816 |
++ |
12817 |
++ kill_anon_super(sb); |
12818 |
++ |
12819 |
++ if (domain) |
12820 |
++ kdbus_domain_unref(domain); |
12821 |
++} |
12822 |
++ |
12823 |
++static int fs_super_set(struct super_block *sb, void *data) |
12824 |
++{ |
12825 |
++ int ret; |
12826 |
++ |
12827 |
++ ret = set_anon_super(sb, data); |
12828 |
++ if (!ret) |
12829 |
++ sb->s_fs_info = data; |
12830 |
++ |
12831 |
++ return ret; |
12832 |
++} |
12833 |
++ |
12834 |
++static struct dentry *fs_super_mount(struct file_system_type *fs_type, |
12835 |
++ int flags, const char *dev_name, |
12836 |
++ void *data) |
12837 |
++{ |
12838 |
++ struct kdbus_domain *domain; |
12839 |
++ struct super_block *sb; |
12840 |
++ int ret; |
12841 |
++ |
12842 |
++ domain = kdbus_domain_new(KDBUS_MAKE_ACCESS_WORLD); |
12843 |
++ if (IS_ERR(domain)) |
12844 |
++ return ERR_CAST(domain); |
12845 |
++ |
12846 |
++ sb = sget(fs_type, NULL, fs_super_set, flags, domain); |
12847 |
++ if (IS_ERR(sb)) { |
12848 |
++ kdbus_node_deactivate(&domain->node); |
12849 |
++ kdbus_domain_unref(domain); |
12850 |
++ return ERR_CAST(sb); |
12851 |
++ } |
12852 |
++ |
12853 |
++ WARN_ON(sb->s_fs_info != domain); |
12854 |
++ WARN_ON(sb->s_root); |
12855 |
++ |
12856 |
++ ret = fs_super_fill(sb); |
12857 |
++ if (ret < 0) { |
12858 |
++ /* calls into ->kill_sb() when done */ |
12859 |
++ deactivate_locked_super(sb); |
12860 |
++ return ERR_PTR(ret); |
12861 |
++ } |
12862 |
++ |
12863 |
++ return dget(sb->s_root); |
12864 |
++} |
12865 |
++ |
12866 |
++static struct file_system_type fs_type = { |
12867 |
++ .name = KBUILD_MODNAME "fs", |
12868 |
++ .owner = THIS_MODULE, |
12869 |
++ .mount = fs_super_mount, |
12870 |
++ .kill_sb = fs_super_kill, |
12871 |
++ .fs_flags = FS_USERNS_MOUNT, |
12872 |
++}; |
12873 |
++ |
12874 |
++/** |
12875 |
++ * kdbus_fs_init() - register kdbus filesystem |
12876 |
++ * |
12877 |
++ * This registers a filesystem with the VFS layer. The filesystem is called |
12878 |
++ * `KBUILD_MODNAME "fs"', which usually resolves to `kdbusfs'. The nameing |
12879 |
++ * scheme allows to set KBUILD_MODNAME to "kdbus2" and you will get an |
12880 |
++ * independent filesystem for developers. |
12881 |
++ * |
12882 |
++ * Each mount of the kdbusfs filesystem has an kdbus_domain attached. |
12883 |
++ * Operations on this mount will only affect the attached domain. On each mount |
12884 |
++ * a new domain is automatically created and used for this mount exclusively. |
12885 |
++ * If you want to share a domain across multiple mounts, you need to bind-mount |
12886 |
++ * it. |
12887 |
++ * |
12888 |
++ * Mounts of kdbusfs (with a different domain each) are unrelated to each other |
12889 |
++ * and will never have any effect on any domain but their own. |
12890 |
++ * |
12891 |
++ * Return: 0 on success, negative error otherwise. |
12892 |
++ */ |
12893 |
++int kdbus_fs_init(void) |
12894 |
++{ |
12895 |
++ return register_filesystem(&fs_type); |
12896 |
++} |
12897 |
++ |
12898 |
++/** |
12899 |
++ * kdbus_fs_exit() - unregister kdbus filesystem |
12900 |
++ * |
12901 |
++ * This does the reverse to kdbus_fs_init(). It unregisters the kdbusfs |
12902 |
++ * filesystem from VFS and cleans up any allocated resources. |
12903 |
++ */ |
12904 |
++void kdbus_fs_exit(void) |
12905 |
++{ |
12906 |
++ unregister_filesystem(&fs_type); |
12907 |
++} |
12908 |
++ |
12909 |
++/* acquire domain of @node, making sure all ancestors are active */ |
12910 |
++static struct kdbus_domain *fs_acquire_domain(struct kdbus_node *node) |
12911 |
++{ |
12912 |
++ struct kdbus_domain *domain; |
12913 |
++ struct kdbus_node *iter; |
12914 |
++ |
12915 |
++ /* caller must guarantee that @node is linked */ |
12916 |
++ for (iter = node; iter->parent; iter = iter->parent) |
12917 |
++ if (!kdbus_node_is_active(iter->parent)) |
12918 |
++ return NULL; |
12919 |
++ |
12920 |
++ /* root nodes are always domains */ |
12921 |
++ if (WARN_ON(iter->type != KDBUS_NODE_DOMAIN)) |
12922 |
++ return NULL; |
12923 |
++ |
12924 |
++ domain = kdbus_domain_from_node(iter); |
12925 |
++ if (!kdbus_node_acquire(&domain->node)) |
12926 |
++ return NULL; |
12927 |
++ |
12928 |
++ return domain; |
12929 |
++} |
12930 |
++ |
12931 |
++/** |
12932 |
++ * kdbus_fs_flush() - flush dcache entries of a node |
12933 |
++ * @node: Node to flush entries of |
12934 |
++ * |
12935 |
++ * This flushes all VFS filesystem cache entries for a node and all its |
12936 |
++ * children. This should be called whenever a node is destroyed during |
12937 |
++ * runtime. It will flush the cache entries so the linked objects can be |
12938 |
++ * deallocated. |
12939 |
++ * |
12940 |
++ * This is a no-op if you call it on active nodes (they really should stay in |
12941 |
++ * cache) or on nodes with deactivated parents (flushing the parent is enough). |
12942 |
++ * Furthermore, there is no need to call it on nodes whose lifetime is bound to |
12943 |
++ * their parents'. In those cases, the parent-flush will always also flush the |
12944 |
++ * children. |
12945 |
++ */ |
12946 |
++void kdbus_fs_flush(struct kdbus_node *node) |
12947 |
++{ |
12948 |
++ struct dentry *dentry, *parent_dentry = NULL; |
12949 |
++ struct kdbus_domain *domain; |
12950 |
++ struct qstr name; |
12951 |
++ |
12952 |
++ /* active nodes should remain in cache */ |
12953 |
++ if (!kdbus_node_is_deactivated(node)) |
12954 |
++ return; |
12955 |
++ |
12956 |
++ /* nodes that were never linked were never instantiated */ |
12957 |
++ if (!node->parent) |
12958 |
++ return; |
12959 |
++ |
12960 |
++ /* acquire domain and verify all ancestors are active */ |
12961 |
++ domain = fs_acquire_domain(node); |
12962 |
++ if (!domain) |
12963 |
++ return; |
12964 |
++ |
12965 |
++ switch (node->type) { |
12966 |
++ case KDBUS_NODE_ENDPOINT: |
12967 |
++ if (WARN_ON(!node->parent || !node->parent->name)) |
12968 |
++ goto exit; |
12969 |
++ |
12970 |
++ name.name = node->parent->name; |
12971 |
++ name.len = strlen(node->parent->name); |
12972 |
++ parent_dentry = d_hash_and_lookup(domain->dentry, &name); |
12973 |
++ if (IS_ERR_OR_NULL(parent_dentry)) |
12974 |
++ goto exit; |
12975 |
++ |
12976 |
++ /* fallthrough */ |
12977 |
++ case KDBUS_NODE_BUS: |
12978 |
++ if (WARN_ON(!node->name)) |
12979 |
++ goto exit; |
12980 |
++ |
12981 |
++ name.name = node->name; |
12982 |
++ name.len = strlen(node->name); |
12983 |
++ dentry = d_hash_and_lookup(parent_dentry ? : domain->dentry, |
12984 |
++ &name); |
12985 |
++ if (!IS_ERR_OR_NULL(dentry)) { |
12986 |
++ d_invalidate(dentry); |
12987 |
++ dput(dentry); |
12988 |
++ } |
12989 |
++ |
12990 |
++ dput(parent_dentry); |
12991 |
++ break; |
12992 |
++ |
12993 |
++ default: |
12994 |
++ /* all other types are bound to their parent lifetime */ |
12995 |
++ break; |
12996 |
++ } |
12997 |
++ |
12998 |
++exit: |
12999 |
++ kdbus_node_release(&domain->node); |
13000 |
++} |
13001 |
+diff --git a/ipc/kdbus/fs.h b/ipc/kdbus/fs.h |
13002 |
+new file mode 100644 |
13003 |
+index 0000000..62f7d6a |
13004 |
+--- /dev/null |
13005 |
++++ b/ipc/kdbus/fs.h |
13006 |
+@@ -0,0 +1,28 @@ |
13007 |
++/* |
13008 |
++ * Copyright (C) 2013-2015 Kay Sievers |
13009 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13010 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13011 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13012 |
++ * Copyright (C) 2013-2015 Linux Foundation |
13013 |
++ * |
13014 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
13015 |
++ * the terms of the GNU Lesser General Public License as published by the |
13016 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
13017 |
++ * your option) any later version. |
13018 |
++ */ |
13019 |
++ |
13020 |
++#ifndef __KDBUSFS_H |
13021 |
++#define __KDBUSFS_H |
13022 |
++ |
13023 |
++#include <linux/kernel.h> |
13024 |
++ |
13025 |
++struct kdbus_node; |
13026 |
++ |
13027 |
++int kdbus_fs_init(void); |
13028 |
++void kdbus_fs_exit(void); |
13029 |
++void kdbus_fs_flush(struct kdbus_node *node); |
13030 |
++ |
13031 |
++#define kdbus_node_from_inode(_inode) \ |
13032 |
++ ((struct kdbus_node *)(_inode)->i_private) |
13033 |
++ |
13034 |
++#endif |
13035 |
+diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c |
13036 |
+new file mode 100644 |
13037 |
+index 0000000..f72dbe5 |
13038 |
+--- /dev/null |
13039 |
++++ b/ipc/kdbus/handle.c |
13040 |
+@@ -0,0 +1,617 @@ |
13041 |
++/* |
13042 |
++ * Copyright (C) 2013-2015 Kay Sievers |
13043 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13044 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13045 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13046 |
++ * Copyright (C) 2013-2015 Linux Foundation |
13047 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
13048 |
++ * |
13049 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
13050 |
++ * the terms of the GNU Lesser General Public License as published by the |
13051 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
13052 |
++ * your option) any later version. |
13053 |
++ */ |
13054 |
++ |
13055 |
++#include <linux/file.h> |
13056 |
++#include <linux/fs.h> |
13057 |
++#include <linux/idr.h> |
13058 |
++#include <linux/init.h> |
13059 |
++#include <linux/kdev_t.h> |
13060 |
++#include <linux/module.h> |
13061 |
++#include <linux/poll.h> |
13062 |
++#include <linux/rwsem.h> |
13063 |
++#include <linux/sched.h> |
13064 |
++#include <linux/sizes.h> |
13065 |
++#include <linux/slab.h> |
13066 |
++#include <linux/uaccess.h> |
13067 |
++#include <linux/syscalls.h> |
13068 |
++ |
13069 |
++#include "bus.h" |
13070 |
++#include "connection.h" |
13071 |
++#include "endpoint.h" |
13072 |
++#include "fs.h" |
13073 |
++#include "handle.h" |
13074 |
++#include "item.h" |
13075 |
++#include "match.h" |
13076 |
++#include "message.h" |
13077 |
++#include "names.h" |
13078 |
++#include "domain.h" |
13079 |
++#include "policy.h" |
13080 |
++ |
13081 |
++static int kdbus_args_verify(struct kdbus_args *args) |
13082 |
++{ |
13083 |
++ struct kdbus_item *item; |
13084 |
++ size_t i; |
13085 |
++ int ret; |
13086 |
++ |
13087 |
++ KDBUS_ITEMS_FOREACH(item, args->items, args->items_size) { |
13088 |
++ struct kdbus_arg *arg = NULL; |
13089 |
++ |
13090 |
++ if (!KDBUS_ITEM_VALID(item, args->items, args->items_size)) |
13091 |
++ return -EINVAL; |
13092 |
++ |
13093 |
++ for (i = 0; i < args->argc; ++i) |
13094 |
++ if (args->argv[i].type == item->type) |
13095 |
++ break; |
13096 |
++ if (i >= args->argc) |
13097 |
++ return -EINVAL; |
13098 |
++ |
13099 |
++ arg = &args->argv[i]; |
13100 |
++ |
13101 |
++ ret = kdbus_item_validate(item); |
13102 |
++ if (ret < 0) |
13103 |
++ return ret; |
13104 |
++ |
13105 |
++ if (arg->item && !arg->multiple) |
13106 |
++ return -EINVAL; |
13107 |
++ |
13108 |
++ arg->item = item; |
13109 |
++ } |
13110 |
++ |
13111 |
++ if (!KDBUS_ITEMS_END(item, args->items, args->items_size)) |
13112 |
++ return -EINVAL; |
13113 |
++ |
13114 |
++ for (i = 0; i < args->argc; ++i) |
13115 |
++ if (args->argv[i].mandatory && !args->argv[i].item) |
13116 |
++ return -EINVAL; |
13117 |
++ |
13118 |
++ return 0; |
13119 |
++} |
13120 |
++ |
13121 |
++static int kdbus_args_negotiate(struct kdbus_args *args) |
13122 |
++{ |
13123 |
++ struct kdbus_item __user *user; |
13124 |
++ struct kdbus_item *negotiation; |
13125 |
++ size_t i, j, num; |
13126 |
++ |
13127 |
++ /* |
13128 |
++ * If KDBUS_FLAG_NEGOTIATE is set, we overwrite the flags field with |
13129 |
++ * the set of supported flags. Furthermore, if an KDBUS_ITEM_NEGOTIATE |
13130 |
++ * item is passed, we iterate its payload (array of u64, each set to an |
13131 |
++ * item type) and clear all unsupported item-types to 0. |
13132 |
++ * The caller might do this recursively, if other flags or objects are |
13133 |
++ * embedded in the payload itself. |
13134 |
++ */ |
13135 |
++ |
13136 |
++ if (args->cmd->flags & KDBUS_FLAG_NEGOTIATE) { |
13137 |
++ if (put_user(args->allowed_flags & ~KDBUS_FLAG_NEGOTIATE, |
13138 |
++ &args->user->flags)) |
13139 |
++ return -EFAULT; |
13140 |
++ } |
13141 |
++ |
13142 |
++ if (args->argc < 1 || args->argv[0].type != KDBUS_ITEM_NEGOTIATE || |
13143 |
++ !args->argv[0].item) |
13144 |
++ return 0; |
13145 |
++ |
13146 |
++ negotiation = args->argv[0].item; |
13147 |
++ user = (struct kdbus_item __user *) |
13148 |
++ ((u8 __user *)args->user + |
13149 |
++ ((u8 *)negotiation - (u8 *)args->cmd)); |
13150 |
++ num = KDBUS_ITEM_PAYLOAD_SIZE(negotiation) / sizeof(u64); |
13151 |
++ |
13152 |
++ for (i = 0; i < num; ++i) { |
13153 |
++ for (j = 0; j < args->argc; ++j) |
13154 |
++ if (negotiation->data64[i] == args->argv[j].type) |
13155 |
++ break; |
13156 |
++ |
13157 |
++ if (j < args->argc) |
13158 |
++ continue; |
13159 |
++ |
13160 |
++ /* this item is not supported, clear it out */ |
13161 |
++ negotiation->data64[i] = 0; |
13162 |
++ if (put_user(negotiation->data64[i], &user->data64[i])) |
13163 |
++ return -EFAULT; |
13164 |
++ } |
13165 |
++ |
13166 |
++ return 0; |
13167 |
++} |
13168 |
++ |
13169 |
++/** |
13170 |
++ * __kdbus_args_parse() - parse payload of kdbus command |
13171 |
++ * @args: object to parse data into |
13172 |
++ * @argp: user-space location of command payload to parse |
13173 |
++ * @type_size: overall size of command payload to parse |
13174 |
++ * @items_offset: offset of items array in command payload |
13175 |
++ * @out: output variable to store pointer to copied payload |
13176 |
++ * |
13177 |
++ * This parses the ioctl payload at user-space location @argp into @args. @args |
13178 |
++ * must be pre-initialized by the caller to reflect the supported flags and |
13179 |
++ * items of this command. This parser will then copy the command payload into |
13180 |
++ * kernel-space, verify correctness and consistency and cache pointers to parsed |
13181 |
++ * items and other data in @args. |
13182 |
++ * |
13183 |
++ * If this function succeeded, you must call kdbus_args_clear() to release |
13184 |
++ * allocated resources before destroying @args. |
13185 |
++ * |
13186 |
++ * Return: On failure a negative error code is returned. Otherwise, 1 is |
13187 |
++ * returned if negotiation was requested, 0 if not. |
13188 |
++ */ |
13189 |
++int __kdbus_args_parse(struct kdbus_args *args, void __user *argp, |
13190 |
++ size_t type_size, size_t items_offset, void **out) |
13191 |
++{ |
13192 |
++ int ret; |
13193 |
++ |
13194 |
++ args->cmd = kdbus_memdup_user(argp, type_size, KDBUS_CMD_MAX_SIZE); |
13195 |
++ if (IS_ERR(args->cmd)) |
13196 |
++ return PTR_ERR(args->cmd); |
13197 |
++ |
13198 |
++ args->cmd->return_flags = 0; |
13199 |
++ args->user = argp; |
13200 |
++ args->items = (void *)((u8 *)args->cmd + items_offset); |
13201 |
++ args->items_size = args->cmd->size - items_offset; |
13202 |
++ |
13203 |
++ if (args->cmd->flags & ~args->allowed_flags) { |
13204 |
++ ret = -EINVAL; |
13205 |
++ goto error; |
13206 |
++ } |
13207 |
++ |
13208 |
++ ret = kdbus_args_verify(args); |
13209 |
++ if (ret < 0) |
13210 |
++ goto error; |
13211 |
++ |
13212 |
++ ret = kdbus_args_negotiate(args); |
13213 |
++ if (ret < 0) |
13214 |
++ goto error; |
13215 |
++ |
13216 |
++ *out = args->cmd; |
13217 |
++ return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE); |
13218 |
++ |
13219 |
++error: |
13220 |
++ return kdbus_args_clear(args, ret); |
13221 |
++} |
13222 |
++ |
13223 |
++/** |
13224 |
++ * kdbus_args_clear() - release allocated command resources |
13225 |
++ * @args: object to release resources of |
13226 |
++ * @ret: return value of this command |
13227 |
++ * |
13228 |
++ * This frees all allocated resources on @args and copies the command result |
13229 |
++ * flags into user-space. @ret is usually returned unchanged by this function, |
13230 |
++ * so it can be used in the final 'return' statement of the command handler. |
13231 |
++ * |
13232 |
++ * Return: -EFAULT if return values cannot be copied into user-space, otherwise |
13233 |
++ * @ret is returned unchanged. |
13234 |
++ */ |
13235 |
++int kdbus_args_clear(struct kdbus_args *args, int ret) |
13236 |
++{ |
13237 |
++ if (!args) |
13238 |
++ return ret; |
13239 |
++ |
13240 |
++ if (!IS_ERR_OR_NULL(args->cmd)) { |
13241 |
++ if (put_user(args->cmd->return_flags, |
13242 |
++ &args->user->return_flags)) |
13243 |
++ ret = -EFAULT; |
13244 |
++ kfree(args->cmd); |
13245 |
++ args->cmd = NULL; |
13246 |
++ } |
13247 |
++ |
13248 |
++ return ret; |
13249 |
++} |
13250 |
++ |
13251 |
++/** |
13252 |
++ * enum kdbus_handle_type - type an handle can be of |
13253 |
++ * @KDBUS_HANDLE_NONE: no type set, yet |
13254 |
++ * @KDBUS_HANDLE_BUS_OWNER: bus owner |
13255 |
++ * @KDBUS_HANDLE_EP_OWNER: endpoint owner |
13256 |
++ * @KDBUS_HANDLE_CONNECTED: endpoint connection after HELLO |
13257 |
++ */ |
13258 |
++enum kdbus_handle_type { |
13259 |
++ KDBUS_HANDLE_NONE, |
13260 |
++ KDBUS_HANDLE_BUS_OWNER, |
13261 |
++ KDBUS_HANDLE_EP_OWNER, |
13262 |
++ KDBUS_HANDLE_CONNECTED, |
13263 |
++}; |
13264 |
++ |
13265 |
++/** |
13266 |
++ * struct kdbus_handle - handle to the kdbus system |
13267 |
++ * @rwlock: handle lock |
13268 |
++ * @type: type of this handle (KDBUS_HANDLE_*) |
13269 |
++ * @bus_owner: bus this handle owns |
13270 |
++ * @ep_owner: endpoint this handle owns |
13271 |
++ * @conn: connection this handle owns |
13272 |
++ * @privileged: Flag to mark a handle as privileged |
13273 |
++ */ |
13274 |
++struct kdbus_handle { |
13275 |
++ struct rw_semaphore rwlock; |
13276 |
++ |
13277 |
++ enum kdbus_handle_type type; |
13278 |
++ union { |
13279 |
++ struct kdbus_bus *bus_owner; |
13280 |
++ struct kdbus_ep *ep_owner; |
13281 |
++ struct kdbus_conn *conn; |
13282 |
++ }; |
13283 |
++ |
13284 |
++ bool privileged:1; |
13285 |
++}; |
13286 |
++ |
13287 |
++static int kdbus_handle_open(struct inode *inode, struct file *file) |
13288 |
++{ |
13289 |
++ struct kdbus_handle *handle; |
13290 |
++ struct kdbus_node *node; |
13291 |
++ int ret; |
13292 |
++ |
13293 |
++ node = kdbus_node_from_inode(inode); |
13294 |
++ if (!kdbus_node_acquire(node)) |
13295 |
++ return -ESHUTDOWN; |
13296 |
++ |
13297 |
++ handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
13298 |
++ if (!handle) { |
13299 |
++ ret = -ENOMEM; |
13300 |
++ goto exit; |
13301 |
++ } |
13302 |
++ |
13303 |
++ init_rwsem(&handle->rwlock); |
13304 |
++ handle->type = KDBUS_HANDLE_NONE; |
13305 |
++ |
13306 |
++ if (node->type == KDBUS_NODE_ENDPOINT) { |
13307 |
++ struct kdbus_ep *ep = kdbus_ep_from_node(node); |
13308 |
++ struct kdbus_bus *bus = ep->bus; |
13309 |
++ |
13310 |
++ /* |
13311 |
++ * A connection is privileged if it is opened on an endpoint |
13312 |
++ * without custom policy and either: |
13313 |
++ * * the user has CAP_IPC_OWNER in the domain user namespace |
13314 |
++ * or |
13315 |
++ * * the callers euid matches the uid of the bus creator |
13316 |
++ */ |
13317 |
++ if (!ep->user && |
13318 |
++ (ns_capable(bus->domain->user_namespace, CAP_IPC_OWNER) || |
13319 |
++ uid_eq(file->f_cred->euid, bus->node.uid))) |
13320 |
++ handle->privileged = true; |
13321 |
++ } |
13322 |
++ |
13323 |
++ file->private_data = handle; |
13324 |
++ ret = 0; |
13325 |
++ |
13326 |
++exit: |
13327 |
++ kdbus_node_release(node); |
13328 |
++ return ret; |
13329 |
++} |
13330 |
++ |
13331 |
++static int kdbus_handle_release(struct inode *inode, struct file *file) |
13332 |
++{ |
13333 |
++ struct kdbus_handle *handle = file->private_data; |
13334 |
++ |
13335 |
++ switch (handle->type) { |
13336 |
++ case KDBUS_HANDLE_BUS_OWNER: |
13337 |
++ if (handle->bus_owner) { |
13338 |
++ kdbus_node_deactivate(&handle->bus_owner->node); |
13339 |
++ kdbus_bus_unref(handle->bus_owner); |
13340 |
++ } |
13341 |
++ break; |
13342 |
++ case KDBUS_HANDLE_EP_OWNER: |
13343 |
++ if (handle->ep_owner) { |
13344 |
++ kdbus_node_deactivate(&handle->ep_owner->node); |
13345 |
++ kdbus_ep_unref(handle->ep_owner); |
13346 |
++ } |
13347 |
++ break; |
13348 |
++ case KDBUS_HANDLE_CONNECTED: |
13349 |
++ kdbus_conn_disconnect(handle->conn, false); |
13350 |
++ kdbus_conn_unref(handle->conn); |
13351 |
++ break; |
13352 |
++ case KDBUS_HANDLE_NONE: |
13353 |
++ /* nothing to clean up */ |
13354 |
++ break; |
13355 |
++ } |
13356 |
++ |
13357 |
++ kfree(handle); |
13358 |
++ |
13359 |
++ return 0; |
13360 |
++} |
13361 |
++ |
13362 |
++static long kdbus_handle_ioctl_control(struct file *file, unsigned int cmd, |
13363 |
++ void __user *argp) |
13364 |
++{ |
13365 |
++ struct kdbus_handle *handle = file->private_data; |
13366 |
++ struct kdbus_node *node = file_inode(file)->i_private; |
13367 |
++ struct kdbus_domain *domain; |
13368 |
++ int ret = 0; |
13369 |
++ |
13370 |
++ if (!kdbus_node_acquire(node)) |
13371 |
++ return -ESHUTDOWN; |
13372 |
++ |
13373 |
++ /* |
13374 |
++ * The parent of control-nodes is always a domain, make sure to pin it |
13375 |
++ * so the parent is actually valid. |
13376 |
++ */ |
13377 |
++ domain = kdbus_domain_from_node(node->parent); |
13378 |
++ if (!kdbus_node_acquire(&domain->node)) { |
13379 |
++ kdbus_node_release(node); |
13380 |
++ return -ESHUTDOWN; |
13381 |
++ } |
13382 |
++ |
13383 |
++ switch (cmd) { |
13384 |
++ case KDBUS_CMD_BUS_MAKE: { |
13385 |
++ struct kdbus_bus *bus; |
13386 |
++ |
13387 |
++ bus = kdbus_cmd_bus_make(domain, argp); |
13388 |
++ if (IS_ERR_OR_NULL(bus)) { |
13389 |
++ ret = PTR_ERR_OR_ZERO(bus); |
13390 |
++ break; |
13391 |
++ } |
13392 |
++ |
13393 |
++ handle->type = KDBUS_HANDLE_BUS_OWNER; |
13394 |
++ handle->bus_owner = bus; |
13395 |
++ break; |
13396 |
++ } |
13397 |
++ |
13398 |
++ default: |
13399 |
++ ret = -EBADFD; |
13400 |
++ break; |
13401 |
++ } |
13402 |
++ |
13403 |
++ kdbus_node_release(&domain->node); |
13404 |
++ kdbus_node_release(node); |
13405 |
++ return ret; |
13406 |
++} |
13407 |
++ |
13408 |
++static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd, |
13409 |
++ void __user *buf) |
13410 |
++{ |
13411 |
++ struct kdbus_handle *handle = file->private_data; |
13412 |
++ struct kdbus_node *node = file_inode(file)->i_private; |
13413 |
++ struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node); |
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 (!handle->privileged) { |
13424 |
++ ret = -EPERM; |
13425 |
++ break; |
13426 |
++ } |
13427 |
++ |
13428 |
++ ep = kdbus_cmd_ep_make(file_ep->bus, buf); |
13429 |
++ if (IS_ERR_OR_NULL(ep)) { |
13430 |
++ ret = PTR_ERR_OR_ZERO(ep); |
13431 |
++ break; |
13432 |
++ } |
13433 |
++ |
13434 |
++ handle->type = KDBUS_HANDLE_EP_OWNER; |
13435 |
++ handle->ep_owner = ep; |
13436 |
++ break; |
13437 |
++ |
13438 |
++ case KDBUS_CMD_HELLO: |
13439 |
++ conn = kdbus_cmd_hello(file_ep, handle->privileged, buf); |
13440 |
++ if (IS_ERR_OR_NULL(conn)) { |
13441 |
++ ret = PTR_ERR_OR_ZERO(conn); |
13442 |
++ break; |
13443 |
++ } |
13444 |
++ |
13445 |
++ handle->type = KDBUS_HANDLE_CONNECTED; |
13446 |
++ handle->conn = conn; |
13447 |
++ break; |
13448 |
++ |
13449 |
++ default: |
13450 |
++ ret = -EBADFD; |
13451 |
++ break; |
13452 |
++ } |
13453 |
++ |
13454 |
++ kdbus_node_release(node); |
13455 |
++ return ret; |
13456 |
++} |
13457 |
++ |
13458 |
++static long kdbus_handle_ioctl_ep_owner(struct file *file, unsigned int command, |
13459 |
++ void __user *buf) |
13460 |
++{ |
13461 |
++ struct kdbus_handle *handle = file->private_data; |
13462 |
++ struct kdbus_ep *ep = handle->ep_owner; |
13463 |
++ int ret; |
13464 |
++ |
13465 |
++ if (!kdbus_node_acquire(&ep->node)) |
13466 |
++ return -ESHUTDOWN; |
13467 |
++ |
13468 |
++ switch (command) { |
13469 |
++ case KDBUS_CMD_ENDPOINT_UPDATE: |
13470 |
++ ret = kdbus_cmd_ep_update(ep, buf); |
13471 |
++ break; |
13472 |
++ default: |
13473 |
++ ret = -EBADFD; |
13474 |
++ break; |
13475 |
++ } |
13476 |
++ |
13477 |
++ kdbus_node_release(&ep->node); |
13478 |
++ return ret; |
13479 |
++} |
13480 |
++ |
13481 |
++static long kdbus_handle_ioctl_connected(struct file *file, |
13482 |
++ unsigned int command, void __user *buf) |
13483 |
++{ |
13484 |
++ struct kdbus_handle *handle = file->private_data; |
13485 |
++ struct kdbus_conn *conn = handle->conn; |
13486 |
++ struct kdbus_conn *release_conn = NULL; |
13487 |
++ int ret; |
13488 |
++ |
13489 |
++ release_conn = conn; |
13490 |
++ ret = kdbus_conn_acquire(release_conn); |
13491 |
++ if (ret < 0) |
13492 |
++ return ret; |
13493 |
++ |
13494 |
++ switch (command) { |
13495 |
++ case KDBUS_CMD_BYEBYE: |
13496 |
++ /* |
13497 |
++ * BYEBYE is special; we must not acquire a connection when |
13498 |
++ * calling into kdbus_conn_disconnect() or we will deadlock, |
13499 |
++ * because kdbus_conn_disconnect() will wait for all acquired |
13500 |
++ * references to be dropped. |
13501 |
++ */ |
13502 |
++ kdbus_conn_release(release_conn); |
13503 |
++ release_conn = NULL; |
13504 |
++ ret = kdbus_cmd_byebye_unlocked(conn, buf); |
13505 |
++ break; |
13506 |
++ case KDBUS_CMD_NAME_ACQUIRE: |
13507 |
++ ret = kdbus_cmd_name_acquire(conn, buf); |
13508 |
++ break; |
13509 |
++ case KDBUS_CMD_NAME_RELEASE: |
13510 |
++ ret = kdbus_cmd_name_release(conn, buf); |
13511 |
++ break; |
13512 |
++ case KDBUS_CMD_LIST: |
13513 |
++ ret = kdbus_cmd_list(conn, buf); |
13514 |
++ break; |
13515 |
++ case KDBUS_CMD_CONN_INFO: |
13516 |
++ ret = kdbus_cmd_conn_info(conn, buf); |
13517 |
++ break; |
13518 |
++ case KDBUS_CMD_BUS_CREATOR_INFO: |
13519 |
++ ret = kdbus_cmd_bus_creator_info(conn, buf); |
13520 |
++ break; |
13521 |
++ case KDBUS_CMD_UPDATE: |
13522 |
++ ret = kdbus_cmd_update(conn, buf); |
13523 |
++ break; |
13524 |
++ case KDBUS_CMD_MATCH_ADD: |
13525 |
++ ret = kdbus_cmd_match_add(conn, buf); |
13526 |
++ break; |
13527 |
++ case KDBUS_CMD_MATCH_REMOVE: |
13528 |
++ ret = kdbus_cmd_match_remove(conn, buf); |
13529 |
++ break; |
13530 |
++ case KDBUS_CMD_SEND: |
13531 |
++ ret = kdbus_cmd_send(conn, file, buf); |
13532 |
++ break; |
13533 |
++ case KDBUS_CMD_RECV: |
13534 |
++ ret = kdbus_cmd_recv(conn, buf); |
13535 |
++ break; |
13536 |
++ case KDBUS_CMD_FREE: |
13537 |
++ ret = kdbus_cmd_free(conn, buf); |
13538 |
++ break; |
13539 |
++ default: |
13540 |
++ ret = -EBADFD; |
13541 |
++ break; |
13542 |
++ } |
13543 |
++ |
13544 |
++ kdbus_conn_release(release_conn); |
13545 |
++ return ret; |
13546 |
++} |
13547 |
++ |
13548 |
++static long kdbus_handle_ioctl(struct file *file, unsigned int cmd, |
13549 |
++ unsigned long arg) |
13550 |
++{ |
13551 |
++ struct kdbus_handle *handle = file->private_data; |
13552 |
++ struct kdbus_node *node = kdbus_node_from_inode(file_inode(file)); |
13553 |
++ void __user *argp = (void __user *)arg; |
13554 |
++ long ret = -EBADFD; |
13555 |
++ |
13556 |
++ switch (cmd) { |
13557 |
++ case KDBUS_CMD_BUS_MAKE: |
13558 |
++ case KDBUS_CMD_ENDPOINT_MAKE: |
13559 |
++ case KDBUS_CMD_HELLO: |
13560 |
++ /* bail out early if already typed */ |
13561 |
++ if (handle->type != KDBUS_HANDLE_NONE) |
13562 |
++ break; |
13563 |
++ |
13564 |
++ down_write(&handle->rwlock); |
13565 |
++ if (handle->type == KDBUS_HANDLE_NONE) { |
13566 |
++ if (node->type == KDBUS_NODE_CONTROL) |
13567 |
++ ret = kdbus_handle_ioctl_control(file, cmd, |
13568 |
++ argp); |
13569 |
++ else if (node->type == KDBUS_NODE_ENDPOINT) |
13570 |
++ ret = kdbus_handle_ioctl_ep(file, cmd, argp); |
13571 |
++ } |
13572 |
++ up_write(&handle->rwlock); |
13573 |
++ break; |
13574 |
++ |
13575 |
++ case KDBUS_CMD_ENDPOINT_UPDATE: |
13576 |
++ case KDBUS_CMD_BYEBYE: |
13577 |
++ case KDBUS_CMD_NAME_ACQUIRE: |
13578 |
++ case KDBUS_CMD_NAME_RELEASE: |
13579 |
++ case KDBUS_CMD_LIST: |
13580 |
++ case KDBUS_CMD_CONN_INFO: |
13581 |
++ case KDBUS_CMD_BUS_CREATOR_INFO: |
13582 |
++ case KDBUS_CMD_UPDATE: |
13583 |
++ case KDBUS_CMD_MATCH_ADD: |
13584 |
++ case KDBUS_CMD_MATCH_REMOVE: |
13585 |
++ case KDBUS_CMD_SEND: |
13586 |
++ case KDBUS_CMD_RECV: |
13587 |
++ case KDBUS_CMD_FREE: |
13588 |
++ down_read(&handle->rwlock); |
13589 |
++ if (handle->type == KDBUS_HANDLE_EP_OWNER) |
13590 |
++ ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp); |
13591 |
++ else if (handle->type == KDBUS_HANDLE_CONNECTED) |
13592 |
++ ret = kdbus_handle_ioctl_connected(file, cmd, argp); |
13593 |
++ up_read(&handle->rwlock); |
13594 |
++ break; |
13595 |
++ default: |
13596 |
++ ret = -ENOTTY; |
13597 |
++ break; |
13598 |
++ } |
13599 |
++ |
13600 |
++ return ret < 0 ? ret : 0; |
13601 |
++} |
13602 |
++ |
13603 |
++static unsigned int kdbus_handle_poll(struct file *file, |
13604 |
++ struct poll_table_struct *wait) |
13605 |
++{ |
13606 |
++ struct kdbus_handle *handle = file->private_data; |
13607 |
++ unsigned int mask = POLLOUT | POLLWRNORM; |
13608 |
++ int ret; |
13609 |
++ |
13610 |
++ /* Only a connected endpoint can read/write data */ |
13611 |
++ down_read(&handle->rwlock); |
13612 |
++ if (handle->type != KDBUS_HANDLE_CONNECTED) { |
13613 |
++ up_read(&handle->rwlock); |
13614 |
++ return POLLERR | POLLHUP; |
13615 |
++ } |
13616 |
++ up_read(&handle->rwlock); |
13617 |
++ |
13618 |
++ ret = kdbus_conn_acquire(handle->conn); |
13619 |
++ if (ret < 0) |
13620 |
++ return POLLERR | POLLHUP; |
13621 |
++ |
13622 |
++ poll_wait(file, &handle->conn->wait, wait); |
13623 |
++ |
13624 |
++ if (!list_empty(&handle->conn->queue.msg_list) || |
13625 |
++ atomic_read(&handle->conn->lost_count) > 0) |
13626 |
++ mask |= POLLIN | POLLRDNORM; |
13627 |
++ |
13628 |
++ kdbus_conn_release(handle->conn); |
13629 |
++ |
13630 |
++ return mask; |
13631 |
++} |
13632 |
++ |
13633 |
++static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma) |
13634 |
++{ |
13635 |
++ struct kdbus_handle *handle = file->private_data; |
13636 |
++ int ret = -EBADFD; |
13637 |
++ |
13638 |
++ if (down_read_trylock(&handle->rwlock)) { |
13639 |
++ if (handle->type == KDBUS_HANDLE_CONNECTED) |
13640 |
++ ret = kdbus_pool_mmap(handle->conn->pool, vma); |
13641 |
++ up_read(&handle->rwlock); |
13642 |
++ } |
13643 |
++ return ret; |
13644 |
++} |
13645 |
++ |
13646 |
++const struct file_operations kdbus_handle_ops = { |
13647 |
++ .owner = THIS_MODULE, |
13648 |
++ .open = kdbus_handle_open, |
13649 |
++ .release = kdbus_handle_release, |
13650 |
++ .poll = kdbus_handle_poll, |
13651 |
++ .llseek = noop_llseek, |
13652 |
++ .unlocked_ioctl = kdbus_handle_ioctl, |
13653 |
++ .mmap = kdbus_handle_mmap, |
13654 |
++#ifdef CONFIG_COMPAT |
13655 |
++ .compat_ioctl = kdbus_handle_ioctl, |
13656 |
++#endif |
13657 |
++}; |
13658 |
+diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h |
13659 |
+new file mode 100644 |
13660 |
+index 0000000..93a372d |
13661 |
+--- /dev/null |
13662 |
++++ b/ipc/kdbus/handle.h |
13663 |
+@@ -0,0 +1,85 @@ |
13664 |
++/* |
13665 |
++ * Copyright (C) 2013-2015 Kay Sievers |
13666 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13667 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13668 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13669 |
++ * Copyright (C) 2013-2015 Linux Foundation |
13670 |
++ * |
13671 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
13672 |
++ * the terms of the GNU Lesser General Public License as published by the |
13673 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
13674 |
++ * your option) any later version. |
13675 |
++ */ |
13676 |
++ |
13677 |
++#ifndef __KDBUS_HANDLE_H |
13678 |
++#define __KDBUS_HANDLE_H |
13679 |
++ |
13680 |
++#include <linux/fs.h> |
13681 |
++#include <uapi/linux/kdbus.h> |
13682 |
++ |
13683 |
++extern const struct file_operations kdbus_handle_ops; |
13684 |
++ |
13685 |
++/** |
13686 |
++ * kdbus_arg - information and state of a single ioctl command item |
13687 |
++ * @type: item type |
13688 |
++ * @item: set by the parser to the first found item of this type |
13689 |
++ * @multiple: whether multiple items of this type are allowed |
13690 |
++ * @mandatory: whether at least one item of this type is required |
13691 |
++ * |
13692 |
++ * This structure describes a single item in an ioctl command payload. The |
13693 |
++ * caller has to pre-fill the type and flags, the parser will then use this |
13694 |
++ * information to verify the ioctl payload. @item is set by the parser to point |
13695 |
++ * to the first occurrence of the item. |
13696 |
++ */ |
13697 |
++struct kdbus_arg { |
13698 |
++ u64 type; |
13699 |
++ struct kdbus_item *item; |
13700 |
++ bool multiple : 1; |
13701 |
++ bool mandatory : 1; |
13702 |
++}; |
13703 |
++ |
13704 |
++/** |
13705 |
++ * kdbus_args - information and state of ioctl command parser |
13706 |
++ * @allowed_flags: set of flags this command supports |
13707 |
++ * @argc: number of items in @argv |
13708 |
++ * @argv: array of items this command supports |
13709 |
++ * @user: set by parser to user-space location of current command |
13710 |
++ * @cmd: set by parser to kernel copy of command payload |
13711 |
++ * @items: points to item array in @cmd |
13712 |
++ * @items_size: size of @items in bytes |
13713 |
++ * |
13714 |
++ * This structure is used to parse ioctl command payloads on each invocation. |
13715 |
++ * The ioctl handler has to pre-fill the flags and allowed items before passing |
13716 |
++ * the object to kdbus_args_parse(). The parser will copy the command payload |
13717 |
++ * into kernel-space and verify the correctness of the data. |
13718 |
++ */ |
13719 |
++struct kdbus_args { |
13720 |
++ u64 allowed_flags; |
13721 |
++ size_t argc; |
13722 |
++ struct kdbus_arg *argv; |
13723 |
++ |
13724 |
++ struct kdbus_cmd __user *user; |
13725 |
++ struct kdbus_cmd *cmd; |
13726 |
++ |
13727 |
++ struct kdbus_item *items; |
13728 |
++ size_t items_size; |
13729 |
++}; |
13730 |
++ |
13731 |
++int __kdbus_args_parse(struct kdbus_args *args, void __user *argp, |
13732 |
++ size_t type_size, size_t items_offset, void **out); |
13733 |
++int kdbus_args_clear(struct kdbus_args *args, int ret); |
13734 |
++ |
13735 |
++#define kdbus_args_parse(_args, _argp, _v) \ |
13736 |
++ ({ \ |
13737 |
++ BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ |
13738 |
++ offsetof(struct kdbus_cmd, size)); \ |
13739 |
++ BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ |
13740 |
++ offsetof(struct kdbus_cmd, flags)); \ |
13741 |
++ BUILD_BUG_ON(offsetof(typeof(**(_v)), return_flags) != \ |
13742 |
++ offsetof(struct kdbus_cmd, return_flags)); \ |
13743 |
++ __kdbus_args_parse((_args), (_argp), sizeof(**(_v)), \ |
13744 |
++ offsetof(typeof(**(_v)), items), \ |
13745 |
++ (void **)(_v)); \ |
13746 |
++ }) |
13747 |
++ |
13748 |
++#endif |
13749 |
+diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c |
13750 |
+new file mode 100644 |
13751 |
+index 0000000..745ad54 |
13752 |
+--- /dev/null |
13753 |
++++ b/ipc/kdbus/item.c |
13754 |
+@@ -0,0 +1,339 @@ |
13755 |
++/* |
13756 |
++ * Copyright (C) 2013-2015 Kay Sievers |
13757 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13758 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13759 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13760 |
++ * Copyright (C) 2013-2015 Linux Foundation |
13761 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
13762 |
++ * |
13763 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
13764 |
++ * the terms of the GNU Lesser General Public License as published by the |
13765 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
13766 |
++ * your option) any later version. |
13767 |
++ */ |
13768 |
++ |
13769 |
++#include <linux/ctype.h> |
13770 |
++#include <linux/fs.h> |
13771 |
++#include <linux/string.h> |
13772 |
++ |
13773 |
++#include "item.h" |
13774 |
++#include "limits.h" |
13775 |
++#include "util.h" |
13776 |
++ |
13777 |
++/* |
13778 |
++ * This verifies the string at position @str with size @size is properly |
13779 |
++ * zero-terminated and does not contain a 0-byte but at the end. |
13780 |
++ */ |
13781 |
++static bool kdbus_str_valid(const char *str, size_t size) |
13782 |
++{ |
13783 |
++ return size > 0 && memchr(str, '\0', size) == str + size - 1; |
13784 |
++} |
13785 |
++ |
13786 |
++/** |
13787 |
++ * kdbus_item_validate_name() - validate an item containing a name |
13788 |
++ * @item: Item to validate |
13789 |
++ * |
13790 |
++ * Return: zero on success or an negative error code on failure |
13791 |
++ */ |
13792 |
++int kdbus_item_validate_name(const struct kdbus_item *item) |
13793 |
++{ |
13794 |
++ const char *name = item->str; |
13795 |
++ unsigned int i; |
13796 |
++ size_t len; |
13797 |
++ |
13798 |
++ if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) |
13799 |
++ return -EINVAL; |
13800 |
++ |
13801 |
++ if (item->size > KDBUS_ITEM_HEADER_SIZE + |
13802 |
++ KDBUS_SYSNAME_MAX_LEN + 1) |
13803 |
++ return -ENAMETOOLONG; |
13804 |
++ |
13805 |
++ if (!kdbus_str_valid(name, KDBUS_ITEM_PAYLOAD_SIZE(item))) |
13806 |
++ return -EINVAL; |
13807 |
++ |
13808 |
++ len = strlen(name); |
13809 |
++ if (len == 0) |
13810 |
++ return -EINVAL; |
13811 |
++ |
13812 |
++ for (i = 0; i < len; i++) { |
13813 |
++ if (isalpha(name[i])) |
13814 |
++ continue; |
13815 |
++ if (isdigit(name[i])) |
13816 |
++ continue; |
13817 |
++ if (name[i] == '_') |
13818 |
++ continue; |
13819 |
++ if (i > 0 && i + 1 < len && (name[i] == '-' || name[i] == '.')) |
13820 |
++ continue; |
13821 |
++ |
13822 |
++ return -EINVAL; |
13823 |
++ } |
13824 |
++ |
13825 |
++ return 0; |
13826 |
++} |
13827 |
++ |
13828 |
++/** |
13829 |
++ * kdbus_item_validate() - validate a single item |
13830 |
++ * @item: item to validate |
13831 |
++ * |
13832 |
++ * Return: 0 if item is valid, negative error code if not. |
13833 |
++ */ |
13834 |
++int kdbus_item_validate(const struct kdbus_item *item) |
13835 |
++{ |
13836 |
++ size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item); |
13837 |
++ size_t l; |
13838 |
++ int ret; |
13839 |
++ |
13840 |
++ BUILD_BUG_ON(KDBUS_ITEM_HEADER_SIZE != |
13841 |
++ sizeof(struct kdbus_item_header)); |
13842 |
++ |
13843 |
++ if (item->size < KDBUS_ITEM_HEADER_SIZE) |
13844 |
++ return -EINVAL; |
13845 |
++ |
13846 |
++ switch (item->type) { |
13847 |
++ case KDBUS_ITEM_NEGOTIATE: |
13848 |
++ if (payload_size % sizeof(u64) != 0) |
13849 |
++ return -EINVAL; |
13850 |
++ break; |
13851 |
++ |
13852 |
++ case KDBUS_ITEM_PAYLOAD_VEC: |
13853 |
++ if (payload_size != sizeof(struct kdbus_vec)) |
13854 |
++ return -EINVAL; |
13855 |
++ if (item->vec.size == 0 || item->vec.size > SIZE_MAX) |
13856 |
++ return -EINVAL; |
13857 |
++ break; |
13858 |
++ |
13859 |
++ case KDBUS_ITEM_PAYLOAD_OFF: |
13860 |
++ if (payload_size != sizeof(struct kdbus_vec)) |
13861 |
++ return -EINVAL; |
13862 |
++ if (item->vec.size == 0 || item->vec.size > SIZE_MAX) |
13863 |
++ return -EINVAL; |
13864 |
++ break; |
13865 |
++ |
13866 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: |
13867 |
++ if (payload_size != sizeof(struct kdbus_memfd)) |
13868 |
++ return -EINVAL; |
13869 |
++ if (item->memfd.size == 0 || item->memfd.size > SIZE_MAX) |
13870 |
++ return -EINVAL; |
13871 |
++ if (item->memfd.fd < 0) |
13872 |
++ return -EBADF; |
13873 |
++ break; |
13874 |
++ |
13875 |
++ case KDBUS_ITEM_FDS: |
13876 |
++ if (payload_size % sizeof(int) != 0) |
13877 |
++ return -EINVAL; |
13878 |
++ break; |
13879 |
++ |
13880 |
++ case KDBUS_ITEM_CANCEL_FD: |
13881 |
++ if (payload_size != sizeof(int)) |
13882 |
++ return -EINVAL; |
13883 |
++ break; |
13884 |
++ |
13885 |
++ case KDBUS_ITEM_BLOOM_PARAMETER: |
13886 |
++ if (payload_size != sizeof(struct kdbus_bloom_parameter)) |
13887 |
++ return -EINVAL; |
13888 |
++ break; |
13889 |
++ |
13890 |
++ case KDBUS_ITEM_BLOOM_FILTER: |
13891 |
++ /* followed by the bloom-mask, depends on the bloom-size */ |
13892 |
++ if (payload_size < sizeof(struct kdbus_bloom_filter)) |
13893 |
++ return -EINVAL; |
13894 |
++ break; |
13895 |
++ |
13896 |
++ case KDBUS_ITEM_BLOOM_MASK: |
13897 |
++ /* size depends on bloom-size of bus */ |
13898 |
++ break; |
13899 |
++ |
13900 |
++ case KDBUS_ITEM_CONN_DESCRIPTION: |
13901 |
++ case KDBUS_ITEM_MAKE_NAME: |
13902 |
++ ret = kdbus_item_validate_name(item); |
13903 |
++ if (ret < 0) |
13904 |
++ return ret; |
13905 |
++ break; |
13906 |
++ |
13907 |
++ case KDBUS_ITEM_ATTACH_FLAGS_SEND: |
13908 |
++ case KDBUS_ITEM_ATTACH_FLAGS_RECV: |
13909 |
++ case KDBUS_ITEM_ID: |
13910 |
++ if (payload_size != sizeof(u64)) |
13911 |
++ return -EINVAL; |
13912 |
++ break; |
13913 |
++ |
13914 |
++ case KDBUS_ITEM_TIMESTAMP: |
13915 |
++ if (payload_size != sizeof(struct kdbus_timestamp)) |
13916 |
++ return -EINVAL; |
13917 |
++ break; |
13918 |
++ |
13919 |
++ case KDBUS_ITEM_CREDS: |
13920 |
++ if (payload_size != sizeof(struct kdbus_creds)) |
13921 |
++ return -EINVAL; |
13922 |
++ break; |
13923 |
++ |
13924 |
++ case KDBUS_ITEM_AUXGROUPS: |
13925 |
++ if (payload_size % sizeof(u32) != 0) |
13926 |
++ return -EINVAL; |
13927 |
++ break; |
13928 |
++ |
13929 |
++ case KDBUS_ITEM_NAME: |
13930 |
++ case KDBUS_ITEM_DST_NAME: |
13931 |
++ case KDBUS_ITEM_PID_COMM: |
13932 |
++ case KDBUS_ITEM_TID_COMM: |
13933 |
++ case KDBUS_ITEM_EXE: |
13934 |
++ case KDBUS_ITEM_CMDLINE: |
13935 |
++ case KDBUS_ITEM_CGROUP: |
13936 |
++ case KDBUS_ITEM_SECLABEL: |
13937 |
++ if (!kdbus_str_valid(item->str, payload_size)) |
13938 |
++ return -EINVAL; |
13939 |
++ break; |
13940 |
++ |
13941 |
++ case KDBUS_ITEM_CAPS: |
13942 |
++ if (payload_size < sizeof(u32)) |
13943 |
++ return -EINVAL; |
13944 |
++ if (payload_size < sizeof(u32) + |
13945 |
++ 4 * CAP_TO_INDEX(item->caps.last_cap) * sizeof(u32)) |
13946 |
++ return -EINVAL; |
13947 |
++ break; |
13948 |
++ |
13949 |
++ case KDBUS_ITEM_AUDIT: |
13950 |
++ if (payload_size != sizeof(struct kdbus_audit)) |
13951 |
++ return -EINVAL; |
13952 |
++ break; |
13953 |
++ |
13954 |
++ case KDBUS_ITEM_POLICY_ACCESS: |
13955 |
++ if (payload_size != sizeof(struct kdbus_policy_access)) |
13956 |
++ return -EINVAL; |
13957 |
++ break; |
13958 |
++ |
13959 |
++ case KDBUS_ITEM_NAME_ADD: |
13960 |
++ case KDBUS_ITEM_NAME_REMOVE: |
13961 |
++ case KDBUS_ITEM_NAME_CHANGE: |
13962 |
++ if (payload_size < sizeof(struct kdbus_notify_name_change)) |
13963 |
++ return -EINVAL; |
13964 |
++ l = payload_size - offsetof(struct kdbus_notify_name_change, |
13965 |
++ name); |
13966 |
++ if (l > 0 && !kdbus_str_valid(item->name_change.name, l)) |
13967 |
++ return -EINVAL; |
13968 |
++ break; |
13969 |
++ |
13970 |
++ case KDBUS_ITEM_ID_ADD: |
13971 |
++ case KDBUS_ITEM_ID_REMOVE: |
13972 |
++ if (payload_size != sizeof(struct kdbus_notify_id_change)) |
13973 |
++ return -EINVAL; |
13974 |
++ break; |
13975 |
++ |
13976 |
++ case KDBUS_ITEM_REPLY_TIMEOUT: |
13977 |
++ case KDBUS_ITEM_REPLY_DEAD: |
13978 |
++ if (payload_size != 0) |
13979 |
++ return -EINVAL; |
13980 |
++ break; |
13981 |
++ |
13982 |
++ default: |
13983 |
++ break; |
13984 |
++ } |
13985 |
++ |
13986 |
++ return 0; |
13987 |
++} |
13988 |
++ |
13989 |
++/** |
13990 |
++ * kdbus_items_validate() - validate items passed by user-space |
13991 |
++ * @items: items to validate |
13992 |
++ * @items_size: number of items |
13993 |
++ * |
13994 |
++ * This verifies that the passed items pointer is consistent and valid. |
13995 |
++ * Furthermore, each item is checked for: |
13996 |
++ * - valid "size" value |
13997 |
++ * - payload is of expected type |
13998 |
++ * - payload is fully included in the item |
13999 |
++ * - string payloads are zero-terminated |
14000 |
++ * |
14001 |
++ * Return: 0 on success, negative error code on failure. |
14002 |
++ */ |
14003 |
++int kdbus_items_validate(const struct kdbus_item *items, size_t items_size) |
14004 |
++{ |
14005 |
++ const struct kdbus_item *item; |
14006 |
++ int ret; |
14007 |
++ |
14008 |
++ KDBUS_ITEMS_FOREACH(item, items, items_size) { |
14009 |
++ if (!KDBUS_ITEM_VALID(item, items, items_size)) |
14010 |
++ return -EINVAL; |
14011 |
++ |
14012 |
++ ret = kdbus_item_validate(item); |
14013 |
++ if (ret < 0) |
14014 |
++ return ret; |
14015 |
++ } |
14016 |
++ |
14017 |
++ if (!KDBUS_ITEMS_END(item, items, items_size)) |
14018 |
++ return -EINVAL; |
14019 |
++ |
14020 |
++ return 0; |
14021 |
++} |
14022 |
++ |
14023 |
++static struct kdbus_item *kdbus_items_get(const struct kdbus_item *items, |
14024 |
++ size_t items_size, |
14025 |
++ unsigned int item_type) |
14026 |
++{ |
14027 |
++ const struct kdbus_item *iter, *found = NULL; |
14028 |
++ |
14029 |
++ KDBUS_ITEMS_FOREACH(iter, items, items_size) { |
14030 |
++ if (iter->type == item_type) { |
14031 |
++ if (found) |
14032 |
++ return ERR_PTR(-EEXIST); |
14033 |
++ found = iter; |
14034 |
++ } |
14035 |
++ } |
14036 |
++ |
14037 |
++ return (struct kdbus_item *)found ? : ERR_PTR(-EBADMSG); |
14038 |
++} |
14039 |
++ |
14040 |
++/** |
14041 |
++ * kdbus_items_get_str() - get string from a list of items |
14042 |
++ * @items: The items to walk |
14043 |
++ * @items_size: The size of all items |
14044 |
++ * @item_type: The item type to look for |
14045 |
++ * |
14046 |
++ * This function walks a list of items and searches for items of type |
14047 |
++ * @item_type. If it finds exactly one such item, @str_ret will be set to |
14048 |
++ * the .str member of the item. |
14049 |
++ * |
14050 |
++ * Return: the string, if the item was found exactly once, ERR_PTR(-EEXIST) |
14051 |
++ * if the item was found more than once, and ERR_PTR(-EBADMSG) if there was |
14052 |
++ * no item of the given type. |
14053 |
++ */ |
14054 |
++const char *kdbus_items_get_str(const struct kdbus_item *items, |
14055 |
++ size_t items_size, |
14056 |
++ unsigned int item_type) |
14057 |
++{ |
14058 |
++ const struct kdbus_item *item; |
14059 |
++ |
14060 |
++ item = kdbus_items_get(items, items_size, item_type); |
14061 |
++ return IS_ERR(item) ? ERR_CAST(item) : item->str; |
14062 |
++} |
14063 |
++ |
14064 |
++/** |
14065 |
++ * kdbus_item_set() - Set item content |
14066 |
++ * @item: The item to modify |
14067 |
++ * @type: The item type to set (KDBUS_ITEM_*) |
14068 |
++ * @data: Data to copy to item->data, may be %NULL |
14069 |
++ * @len: Number of bytes in @data |
14070 |
++ * |
14071 |
++ * This sets type, size and data fields of an item. If @data is NULL, the data |
14072 |
++ * memory is cleared. |
14073 |
++ * |
14074 |
++ * Note that you must align your @data memory to 8 bytes. Trailing padding (in |
14075 |
++ * case @len is not 8byte aligned) is cleared by this call. |
14076 |
++ * |
14077 |
++ * Returns: Pointer to the following item. |
14078 |
++ */ |
14079 |
++struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, |
14080 |
++ const void *data, size_t len) |
14081 |
++{ |
14082 |
++ item->type = type; |
14083 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + len; |
14084 |
++ |
14085 |
++ if (data) { |
14086 |
++ memcpy(item->data, data, len); |
14087 |
++ memset(item->data + len, 0, KDBUS_ALIGN8(len) - len); |
14088 |
++ } else { |
14089 |
++ memset(item->data, 0, KDBUS_ALIGN8(len)); |
14090 |
++ } |
14091 |
++ |
14092 |
++ return KDBUS_ITEM_NEXT(item); |
14093 |
++} |
14094 |
+diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h |
14095 |
+new file mode 100644 |
14096 |
+index 0000000..eeefd8b |
14097 |
+--- /dev/null |
14098 |
++++ b/ipc/kdbus/item.h |
14099 |
+@@ -0,0 +1,64 @@ |
14100 |
++/* |
14101 |
++ * Copyright (C) 2013-2015 Kay Sievers |
14102 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14103 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14104 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14105 |
++ * Copyright (C) 2013-2015 Linux Foundation |
14106 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14107 |
++ * |
14108 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
14109 |
++ * the terms of the GNU Lesser General Public License as published by the |
14110 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
14111 |
++ * your option) any later version. |
14112 |
++ */ |
14113 |
++ |
14114 |
++#ifndef __KDBUS_ITEM_H |
14115 |
++#define __KDBUS_ITEM_H |
14116 |
++ |
14117 |
++#include <linux/kernel.h> |
14118 |
++#include <uapi/linux/kdbus.h> |
14119 |
++ |
14120 |
++#include "util.h" |
14121 |
++ |
14122 |
++/* generic access and iterators over a stream of items */ |
14123 |
++#define KDBUS_ITEM_NEXT(_i) (typeof(_i))(((u8 *)_i) + KDBUS_ALIGN8((_i)->size)) |
14124 |
++#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*_h), _is)) |
14125 |
++#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
14126 |
++#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s)) |
14127 |
++#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE) |
14128 |
++ |
14129 |
++#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \ |
14130 |
++ for (_i = _is; \ |
14131 |
++ ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \ |
14132 |
++ ((u8 *)(_i) >= (u8 *)(_is)); \ |
14133 |
++ _i = KDBUS_ITEM_NEXT(_i)) |
14134 |
++ |
14135 |
++#define KDBUS_ITEM_VALID(_i, _is, _s) \ |
14136 |
++ ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \ |
14137 |
++ (u8 *)(_i) + (_i)->size > (u8 *)(_i) && \ |
14138 |
++ (u8 *)(_i) + (_i)->size <= (u8 *)(_is) + (_s) && \ |
14139 |
++ (u8 *)(_i) >= (u8 *)(_is)) |
14140 |
++ |
14141 |
++#define KDBUS_ITEMS_END(_i, _is, _s) \ |
14142 |
++ ((u8 *)_i == ((u8 *)(_is) + KDBUS_ALIGN8(_s))) |
14143 |
++ |
14144 |
++/** |
14145 |
++ * struct kdbus_item_header - Describes the fix part of an item |
14146 |
++ * @size: The total size of the item |
14147 |
++ * @type: The item type, one of KDBUS_ITEM_* |
14148 |
++ */ |
14149 |
++struct kdbus_item_header { |
14150 |
++ u64 size; |
14151 |
++ u64 type; |
14152 |
++}; |
14153 |
++ |
14154 |
++int kdbus_item_validate_name(const struct kdbus_item *item); |
14155 |
++int kdbus_item_validate(const struct kdbus_item *item); |
14156 |
++int kdbus_items_validate(const struct kdbus_item *items, size_t items_size); |
14157 |
++const char *kdbus_items_get_str(const struct kdbus_item *items, |
14158 |
++ size_t items_size, |
14159 |
++ unsigned int item_type); |
14160 |
++struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, |
14161 |
++ const void *data, size_t len); |
14162 |
++ |
14163 |
++#endif |
14164 |
+diff --git a/ipc/kdbus/limits.h b/ipc/kdbus/limits.h |
14165 |
+new file mode 100644 |
14166 |
+index 0000000..6450f58 |
14167 |
+--- /dev/null |
14168 |
++++ b/ipc/kdbus/limits.h |
14169 |
+@@ -0,0 +1,64 @@ |
14170 |
++/* |
14171 |
++ * Copyright (C) 2013-2015 Kay Sievers |
14172 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14173 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14174 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14175 |
++ * Copyright (C) 2013-2015 Linux Foundation |
14176 |
++ * |
14177 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
14178 |
++ * the terms of the GNU Lesser General Public License as published by the |
14179 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
14180 |
++ * your option) any later version. |
14181 |
++ */ |
14182 |
++ |
14183 |
++#ifndef __KDBUS_DEFAULTS_H |
14184 |
++#define __KDBUS_DEFAULTS_H |
14185 |
++ |
14186 |
++#include <linux/kernel.h> |
14187 |
++ |
14188 |
++/* maximum size of message header and items */ |
14189 |
++#define KDBUS_MSG_MAX_SIZE SZ_8K |
14190 |
++ |
14191 |
++/* maximum number of message items */ |
14192 |
++#define KDBUS_MSG_MAX_ITEMS 128 |
14193 |
++ |
14194 |
++/* maximum number of memfd items per message */ |
14195 |
++#define KDBUS_MSG_MAX_MEMFD_ITEMS 16 |
14196 |
++ |
14197 |
++/* max size of ioctl command data */ |
14198 |
++#define KDBUS_CMD_MAX_SIZE SZ_32K |
14199 |
++ |
14200 |
++/* maximum number of inflight fds in a target queue per user */ |
14201 |
++#define KDBUS_CONN_MAX_FDS_PER_USER 16 |
14202 |
++ |
14203 |
++/* maximum message payload size */ |
14204 |
++#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE SZ_2M |
14205 |
++ |
14206 |
++/* maximum size of bloom bit field in bytes */ |
14207 |
++#define KDBUS_BUS_BLOOM_MAX_SIZE SZ_4K |
14208 |
++ |
14209 |
++/* maximum length of well-known bus name */ |
14210 |
++#define KDBUS_NAME_MAX_LEN 255 |
14211 |
++ |
14212 |
++/* maximum length of bus, domain, ep name */ |
14213 |
++#define KDBUS_SYSNAME_MAX_LEN 63 |
14214 |
++ |
14215 |
++/* maximum number of matches per connection */ |
14216 |
++#define KDBUS_MATCH_MAX 256 |
14217 |
++ |
14218 |
++/* maximum number of queued messages from the same individual user */ |
14219 |
++#define KDBUS_CONN_MAX_MSGS 256 |
14220 |
++ |
14221 |
++/* maximum number of well-known names per connection */ |
14222 |
++#define KDBUS_CONN_MAX_NAMES 256 |
14223 |
++ |
14224 |
++/* maximum number of queued requests waiting for a reply */ |
14225 |
++#define KDBUS_CONN_MAX_REQUESTS_PENDING 128 |
14226 |
++ |
14227 |
++/* maximum number of connections per user in one domain */ |
14228 |
++#define KDBUS_USER_MAX_CONN 1024 |
14229 |
++ |
14230 |
++/* maximum number of buses per user in one domain */ |
14231 |
++#define KDBUS_USER_MAX_BUSES 16 |
14232 |
++ |
14233 |
++#endif |
14234 |
+diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c |
14235 |
+new file mode 100644 |
14236 |
+index 0000000..785f529 |
14237 |
+--- /dev/null |
14238 |
++++ b/ipc/kdbus/main.c |
14239 |
+@@ -0,0 +1,125 @@ |
14240 |
++/* |
14241 |
++ * Copyright (C) 2013-2015 Kay Sievers |
14242 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14243 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14244 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14245 |
++ * Copyright (C) 2013-2015 Linux Foundation |
14246 |
++ * |
14247 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
14248 |
++ * the terms of the GNU Lesser General Public License as published by the |
14249 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
14250 |
++ * your option) any later version. |
14251 |
++ */ |
14252 |
++ |
14253 |
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14254 |
++#include <linux/fs.h> |
14255 |
++#include <linux/init.h> |
14256 |
++#include <linux/module.h> |
14257 |
++#include <linux/moduleparam.h> |
14258 |
++ |
14259 |
++#include "util.h" |
14260 |
++#include "fs.h" |
14261 |
++#include "handle.h" |
14262 |
++#include "metadata.h" |
14263 |
++#include "node.h" |
14264 |
++ |
14265 |
++/* |
14266 |
++ * This is a simplified outline of the internal kdbus object relations, for |
14267 |
++ * those interested in the inner life of the driver implementation. |
14268 |
++ * |
14269 |
++ * From a mount point's (domain's) perspective: |
14270 |
++ * |
14271 |
++ * struct kdbus_domain |
14272 |
++ * |» struct kdbus_user *user (many, owned) |
14273 |
++ * '» struct kdbus_node node (embedded) |
14274 |
++ * |» struct kdbus_node children (many, referenced) |
14275 |
++ * |» struct kdbus_node *parent (pinned) |
14276 |
++ * '» struct kdbus_bus (many, pinned) |
14277 |
++ * |» struct kdbus_node node (embedded) |
14278 |
++ * '» struct kdbus_ep (many, pinned) |
14279 |
++ * |» struct kdbus_node node (embedded) |
14280 |
++ * |» struct kdbus_bus *bus (pinned) |
14281 |
++ * |» struct kdbus_conn conn_list (many, pinned) |
14282 |
++ * | |» struct kdbus_ep *ep (pinned) |
14283 |
++ * | |» struct kdbus_name_entry *activator_of (owned) |
14284 |
++ * | |» struct kdbus_match_db *match_db (owned) |
14285 |
++ * | |» struct kdbus_meta *meta (owned) |
14286 |
++ * | |» struct kdbus_match_db *match_db (owned) |
14287 |
++ * | | '» struct kdbus_match_entry (many, owned) |
14288 |
++ * | | |
14289 |
++ * | |» struct kdbus_pool *pool (owned) |
14290 |
++ * | | '» struct kdbus_pool_slice *slices (many, owned) |
14291 |
++ * | | '» struct kdbus_pool *pool (pinned) |
14292 |
++ * | | |
14293 |
++ * | |» struct kdbus_user *user (pinned) |
14294 |
++ * | `» struct kdbus_queue_entry entries (many, embedded) |
14295 |
++ * | |» struct kdbus_pool_slice *slice (pinned) |
14296 |
++ * | |» struct kdbus_conn_reply *reply (owned) |
14297 |
++ * | '» struct kdbus_user *user (pinned) |
14298 |
++ * | |
14299 |
++ * '» struct kdbus_user *user (pinned) |
14300 |
++ * '» struct kdbus_policy_db policy_db (embedded) |
14301 |
++ * |» struct kdbus_policy_db_entry (many, owned) |
14302 |
++ * | |» struct kdbus_conn (pinned) |
14303 |
++ * | '» struct kdbus_ep (pinned) |
14304 |
++ * | |
14305 |
++ * '» struct kdbus_policy_db_cache_entry (many, owned) |
14306 |
++ * '» struct kdbus_conn (pinned) |
14307 |
++ * |
14308 |
++ * For the life-time of a file descriptor derived from calling open() on a file |
14309 |
++ * inside the mount point: |
14310 |
++ * |
14311 |
++ * struct kdbus_handle |
14312 |
++ * |» struct kdbus_meta *meta (owned) |
14313 |
++ * |» struct kdbus_ep *ep (pinned) |
14314 |
++ * |» struct kdbus_conn *conn (owned) |
14315 |
++ * '» struct kdbus_ep *ep (owned) |
14316 |
++ */ |
14317 |
++ |
14318 |
++/* kdbus mount-point /sys/fs/kdbus */ |
14319 |
++static struct kobject *kdbus_dir; |
14320 |
++ |
14321 |
++/* global module option to apply a mask to exported metadata */ |
14322 |
++unsigned long long kdbus_meta_attach_mask = KDBUS_ATTACH_TIMESTAMP | |
14323 |
++ KDBUS_ATTACH_CREDS | |
14324 |
++ KDBUS_ATTACH_PIDS | |
14325 |
++ KDBUS_ATTACH_AUXGROUPS | |
14326 |
++ KDBUS_ATTACH_NAMES | |
14327 |
++ KDBUS_ATTACH_SECLABEL | |
14328 |
++ KDBUS_ATTACH_CONN_DESCRIPTION; |
14329 |
++MODULE_PARM_DESC(attach_flags_mask, "Attach-flags mask for exported metadata"); |
14330 |
++module_param_named(attach_flags_mask, kdbus_meta_attach_mask, ullong, 0644); |
14331 |
++ |
14332 |
++static int __init kdbus_init(void) |
14333 |
++{ |
14334 |
++ int ret; |
14335 |
++ |
14336 |
++ kdbus_dir = kobject_create_and_add(KBUILD_MODNAME, fs_kobj); |
14337 |
++ if (!kdbus_dir) |
14338 |
++ return -ENOMEM; |
14339 |
++ |
14340 |
++ ret = kdbus_fs_init(); |
14341 |
++ if (ret < 0) { |
14342 |
++ pr_err("cannot register filesystem: %d\n", ret); |
14343 |
++ goto exit_dir; |
14344 |
++ } |
14345 |
++ |
14346 |
++ pr_info("initialized\n"); |
14347 |
++ return 0; |
14348 |
++ |
14349 |
++exit_dir: |
14350 |
++ kobject_put(kdbus_dir); |
14351 |
++ return ret; |
14352 |
++} |
14353 |
++ |
14354 |
++static void __exit kdbus_exit(void) |
14355 |
++{ |
14356 |
++ kdbus_fs_exit(); |
14357 |
++ kobject_put(kdbus_dir); |
14358 |
++} |
14359 |
++ |
14360 |
++module_init(kdbus_init); |
14361 |
++module_exit(kdbus_exit); |
14362 |
++MODULE_LICENSE("GPL"); |
14363 |
++MODULE_DESCRIPTION("D-Bus, powerful, easy to use interprocess communication"); |
14364 |
++MODULE_ALIAS_FS(KBUILD_MODNAME "fs"); |
14365 |
+diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c |
14366 |
+new file mode 100644 |
14367 |
+index 0000000..30cec1c |
14368 |
+--- /dev/null |
14369 |
++++ b/ipc/kdbus/match.c |
14370 |
+@@ -0,0 +1,559 @@ |
14371 |
++/* |
14372 |
++ * Copyright (C) 2013-2015 Kay Sievers |
14373 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14374 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14375 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14376 |
++ * Copyright (C) 2013-2015 Linux Foundation |
14377 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14378 |
++ * |
14379 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
14380 |
++ * the terms of the GNU Lesser General Public License as published by the |
14381 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
14382 |
++ * your option) any later version. |
14383 |
++ */ |
14384 |
++ |
14385 |
++#include <linux/fs.h> |
14386 |
++#include <linux/hash.h> |
14387 |
++#include <linux/init.h> |
14388 |
++#include <linux/mutex.h> |
14389 |
++#include <linux/sched.h> |
14390 |
++#include <linux/sizes.h> |
14391 |
++#include <linux/slab.h> |
14392 |
++#include <linux/uaccess.h> |
14393 |
++ |
14394 |
++#include "bus.h" |
14395 |
++#include "connection.h" |
14396 |
++#include "endpoint.h" |
14397 |
++#include "handle.h" |
14398 |
++#include "item.h" |
14399 |
++#include "match.h" |
14400 |
++#include "message.h" |
14401 |
++#include "names.h" |
14402 |
++ |
14403 |
++/** |
14404 |
++ * struct kdbus_match_db - message filters |
14405 |
++ * @entries_list: List of matches |
14406 |
++ * @mdb_rwlock: Match data lock |
14407 |
++ * @entries_count: Number of entries in database |
14408 |
++ */ |
14409 |
++struct kdbus_match_db { |
14410 |
++ struct list_head entries_list; |
14411 |
++ struct rw_semaphore mdb_rwlock; |
14412 |
++ unsigned int entries_count; |
14413 |
++}; |
14414 |
++ |
14415 |
++/** |
14416 |
++ * struct kdbus_match_entry - a match database entry |
14417 |
++ * @cookie: User-supplied cookie to lookup the entry |
14418 |
++ * @list_entry: The list entry element for the db list |
14419 |
++ * @rules_list: The list head for tracking rules of this entry |
14420 |
++ */ |
14421 |
++struct kdbus_match_entry { |
14422 |
++ u64 cookie; |
14423 |
++ struct list_head list_entry; |
14424 |
++ struct list_head rules_list; |
14425 |
++}; |
14426 |
++ |
14427 |
++/** |
14428 |
++ * struct kdbus_bloom_mask - mask to match against filter |
14429 |
++ * @generations: Number of generations carried |
14430 |
++ * @data: Array of bloom bit fields |
14431 |
++ */ |
14432 |
++struct kdbus_bloom_mask { |
14433 |
++ u64 generations; |
14434 |
++ u64 *data; |
14435 |
++}; |
14436 |
++ |
14437 |
++/** |
14438 |
++ * struct kdbus_match_rule - a rule appended to a match entry |
14439 |
++ * @type: An item type to match agains |
14440 |
++ * @bloom_mask: Bloom mask to match a message's filter against, used |
14441 |
++ * with KDBUS_ITEM_BLOOM_MASK |
14442 |
++ * @name: Name to match against, used with KDBUS_ITEM_NAME, |
14443 |
++ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} |
14444 |
++ * @old_id: ID to match against, used with |
14445 |
++ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}, |
14446 |
++ * KDBUS_ITEM_ID_REMOVE |
14447 |
++ * @new_id: ID to match against, used with |
14448 |
++ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}, |
14449 |
++ * KDBUS_ITEM_ID_REMOVE |
14450 |
++ * @src_id: ID to match against, used with KDBUS_ITEM_ID |
14451 |
++ * @rules_entry: Entry in the entry's rules list |
14452 |
++ */ |
14453 |
++struct kdbus_match_rule { |
14454 |
++ u64 type; |
14455 |
++ union { |
14456 |
++ struct kdbus_bloom_mask bloom_mask; |
14457 |
++ struct { |
14458 |
++ char *name; |
14459 |
++ u64 old_id; |
14460 |
++ u64 new_id; |
14461 |
++ }; |
14462 |
++ u64 src_id; |
14463 |
++ }; |
14464 |
++ struct list_head rules_entry; |
14465 |
++}; |
14466 |
++ |
14467 |
++static void kdbus_match_rule_free(struct kdbus_match_rule *rule) |
14468 |
++{ |
14469 |
++ if (!rule) |
14470 |
++ return; |
14471 |
++ |
14472 |
++ switch (rule->type) { |
14473 |
++ case KDBUS_ITEM_BLOOM_MASK: |
14474 |
++ kfree(rule->bloom_mask.data); |
14475 |
++ break; |
14476 |
++ |
14477 |
++ case KDBUS_ITEM_NAME: |
14478 |
++ case KDBUS_ITEM_NAME_ADD: |
14479 |
++ case KDBUS_ITEM_NAME_REMOVE: |
14480 |
++ case KDBUS_ITEM_NAME_CHANGE: |
14481 |
++ kfree(rule->name); |
14482 |
++ break; |
14483 |
++ |
14484 |
++ case KDBUS_ITEM_ID: |
14485 |
++ case KDBUS_ITEM_ID_ADD: |
14486 |
++ case KDBUS_ITEM_ID_REMOVE: |
14487 |
++ break; |
14488 |
++ |
14489 |
++ default: |
14490 |
++ BUG(); |
14491 |
++ } |
14492 |
++ |
14493 |
++ list_del(&rule->rules_entry); |
14494 |
++ kfree(rule); |
14495 |
++} |
14496 |
++ |
14497 |
++static void kdbus_match_entry_free(struct kdbus_match_entry *entry) |
14498 |
++{ |
14499 |
++ struct kdbus_match_rule *r, *tmp; |
14500 |
++ |
14501 |
++ if (!entry) |
14502 |
++ return; |
14503 |
++ |
14504 |
++ list_for_each_entry_safe(r, tmp, &entry->rules_list, rules_entry) |
14505 |
++ kdbus_match_rule_free(r); |
14506 |
++ |
14507 |
++ list_del(&entry->list_entry); |
14508 |
++ kfree(entry); |
14509 |
++} |
14510 |
++ |
14511 |
++/** |
14512 |
++ * kdbus_match_db_free() - free match db resources |
14513 |
++ * @mdb: The match database |
14514 |
++ */ |
14515 |
++void kdbus_match_db_free(struct kdbus_match_db *mdb) |
14516 |
++{ |
14517 |
++ struct kdbus_match_entry *entry, *tmp; |
14518 |
++ |
14519 |
++ if (!mdb) |
14520 |
++ return; |
14521 |
++ |
14522 |
++ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry) |
14523 |
++ kdbus_match_entry_free(entry); |
14524 |
++ |
14525 |
++ kfree(mdb); |
14526 |
++} |
14527 |
++ |
14528 |
++/** |
14529 |
++ * kdbus_match_db_new() - create a new match database |
14530 |
++ * |
14531 |
++ * Return: a new kdbus_match_db on success, ERR_PTR on failure. |
14532 |
++ */ |
14533 |
++struct kdbus_match_db *kdbus_match_db_new(void) |
14534 |
++{ |
14535 |
++ struct kdbus_match_db *d; |
14536 |
++ |
14537 |
++ d = kzalloc(sizeof(*d), GFP_KERNEL); |
14538 |
++ if (!d) |
14539 |
++ return ERR_PTR(-ENOMEM); |
14540 |
++ |
14541 |
++ init_rwsem(&d->mdb_rwlock); |
14542 |
++ INIT_LIST_HEAD(&d->entries_list); |
14543 |
++ |
14544 |
++ return d; |
14545 |
++} |
14546 |
++ |
14547 |
++static bool kdbus_match_bloom(const struct kdbus_bloom_filter *filter, |
14548 |
++ const struct kdbus_bloom_mask *mask, |
14549 |
++ const struct kdbus_conn *conn) |
14550 |
++{ |
14551 |
++ size_t n = conn->ep->bus->bloom.size / sizeof(u64); |
14552 |
++ const u64 *m; |
14553 |
++ size_t i; |
14554 |
++ |
14555 |
++ /* |
14556 |
++ * The message's filter carries a generation identifier, the |
14557 |
++ * match's mask possibly carries an array of multiple generations |
14558 |
++ * of the mask. Select the mask with the closest match of the |
14559 |
++ * filter's generation. |
14560 |
++ */ |
14561 |
++ m = mask->data + (min(filter->generation, mask->generations - 1) * n); |
14562 |
++ |
14563 |
++ /* |
14564 |
++ * The message's filter contains the messages properties, |
14565 |
++ * the match's mask contains the properties to look for in the |
14566 |
++ * message. Check the mask bit field against the filter bit field, |
14567 |
++ * if the message possibly carries the properties the connection |
14568 |
++ * has subscribed to. |
14569 |
++ */ |
14570 |
++ for (i = 0; i < n; i++) |
14571 |
++ if ((filter->data[i] & m[i]) != m[i]) |
14572 |
++ return false; |
14573 |
++ |
14574 |
++ return true; |
14575 |
++} |
14576 |
++ |
14577 |
++static bool kdbus_match_rules(const struct kdbus_match_entry *entry, |
14578 |
++ struct kdbus_conn *conn_src, |
14579 |
++ struct kdbus_kmsg *kmsg) |
14580 |
++{ |
14581 |
++ struct kdbus_match_rule *r; |
14582 |
++ |
14583 |
++ if (conn_src) |
14584 |
++ lockdep_assert_held(&conn_src->ep->bus->name_registry->rwlock); |
14585 |
++ |
14586 |
++ /* |
14587 |
++ * Walk all the rules and bail out immediately |
14588 |
++ * if any of them is unsatisfied. |
14589 |
++ */ |
14590 |
++ |
14591 |
++ list_for_each_entry(r, &entry->rules_list, rules_entry) { |
14592 |
++ if (conn_src) { |
14593 |
++ /* messages from userspace */ |
14594 |
++ |
14595 |
++ switch (r->type) { |
14596 |
++ case KDBUS_ITEM_BLOOM_MASK: |
14597 |
++ if (!kdbus_match_bloom(kmsg->bloom_filter, |
14598 |
++ &r->bloom_mask, |
14599 |
++ conn_src)) |
14600 |
++ return false; |
14601 |
++ break; |
14602 |
++ |
14603 |
++ case KDBUS_ITEM_ID: |
14604 |
++ if (r->src_id != conn_src->id && |
14605 |
++ r->src_id != KDBUS_MATCH_ID_ANY) |
14606 |
++ return false; |
14607 |
++ |
14608 |
++ break; |
14609 |
++ |
14610 |
++ case KDBUS_ITEM_NAME: |
14611 |
++ if (!kdbus_conn_has_name(conn_src, r->name)) |
14612 |
++ return false; |
14613 |
++ |
14614 |
++ break; |
14615 |
++ |
14616 |
++ default: |
14617 |
++ return false; |
14618 |
++ } |
14619 |
++ } else { |
14620 |
++ /* kernel notifications */ |
14621 |
++ |
14622 |
++ if (kmsg->notify_type != r->type) |
14623 |
++ return false; |
14624 |
++ |
14625 |
++ switch (r->type) { |
14626 |
++ case KDBUS_ITEM_ID_ADD: |
14627 |
++ if (r->new_id != KDBUS_MATCH_ID_ANY && |
14628 |
++ r->new_id != kmsg->notify_new_id) |
14629 |
++ return false; |
14630 |
++ |
14631 |
++ break; |
14632 |
++ |
14633 |
++ case KDBUS_ITEM_ID_REMOVE: |
14634 |
++ if (r->old_id != KDBUS_MATCH_ID_ANY && |
14635 |
++ r->old_id != kmsg->notify_old_id) |
14636 |
++ return false; |
14637 |
++ |
14638 |
++ break; |
14639 |
++ |
14640 |
++ case KDBUS_ITEM_NAME_ADD: |
14641 |
++ case KDBUS_ITEM_NAME_CHANGE: |
14642 |
++ case KDBUS_ITEM_NAME_REMOVE: |
14643 |
++ if ((r->old_id != KDBUS_MATCH_ID_ANY && |
14644 |
++ r->old_id != kmsg->notify_old_id) || |
14645 |
++ (r->new_id != KDBUS_MATCH_ID_ANY && |
14646 |
++ r->new_id != kmsg->notify_new_id) || |
14647 |
++ (r->name && kmsg->notify_name && |
14648 |
++ strcmp(r->name, kmsg->notify_name) != 0)) |
14649 |
++ return false; |
14650 |
++ |
14651 |
++ break; |
14652 |
++ |
14653 |
++ default: |
14654 |
++ return false; |
14655 |
++ } |
14656 |
++ } |
14657 |
++ } |
14658 |
++ |
14659 |
++ return true; |
14660 |
++} |
14661 |
++ |
14662 |
++/** |
14663 |
++ * kdbus_match_db_match_kmsg() - match a kmsg object agains the database entries |
14664 |
++ * @mdb: The match database |
14665 |
++ * @conn_src: The connection object originating the message |
14666 |
++ * @kmsg: The kmsg to perform the match on |
14667 |
++ * |
14668 |
++ * This function will walk through all the database entries previously uploaded |
14669 |
++ * with kdbus_match_db_add(). As soon as any of them has an all-satisfied rule |
14670 |
++ * set, this function will return true. |
14671 |
++ * |
14672 |
++ * The caller must hold the registry lock of conn_src->ep->bus, in case conn_src |
14673 |
++ * is non-NULL. |
14674 |
++ * |
14675 |
++ * Return: true if there was a matching database entry, false otherwise. |
14676 |
++ */ |
14677 |
++bool kdbus_match_db_match_kmsg(struct kdbus_match_db *mdb, |
14678 |
++ struct kdbus_conn *conn_src, |
14679 |
++ struct kdbus_kmsg *kmsg) |
14680 |
++{ |
14681 |
++ struct kdbus_match_entry *entry; |
14682 |
++ bool matched = false; |
14683 |
++ |
14684 |
++ down_read(&mdb->mdb_rwlock); |
14685 |
++ list_for_each_entry(entry, &mdb->entries_list, list_entry) { |
14686 |
++ matched = kdbus_match_rules(entry, conn_src, kmsg); |
14687 |
++ if (matched) |
14688 |
++ break; |
14689 |
++ } |
14690 |
++ up_read(&mdb->mdb_rwlock); |
14691 |
++ |
14692 |
++ return matched; |
14693 |
++} |
14694 |
++ |
14695 |
++static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb, |
14696 |
++ u64 cookie) |
14697 |
++{ |
14698 |
++ struct kdbus_match_entry *entry, *tmp; |
14699 |
++ bool found = false; |
14700 |
++ |
14701 |
++ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry) |
14702 |
++ if (entry->cookie == cookie) { |
14703 |
++ kdbus_match_entry_free(entry); |
14704 |
++ --mdb->entries_count; |
14705 |
++ found = true; |
14706 |
++ } |
14707 |
++ |
14708 |
++ return found ? 0 : -EBADSLT; |
14709 |
++} |
14710 |
++ |
14711 |
++/** |
14712 |
++ * kdbus_cmd_match_add() - handle KDBUS_CMD_MATCH_ADD |
14713 |
++ * @conn: connection to operate on |
14714 |
++ * @argp: command payload |
14715 |
++ * |
14716 |
++ * One call to this function (or one ioctl(KDBUS_CMD_MATCH_ADD), respectively, |
14717 |
++ * adds one new database entry with n rules attached to it. Each rule is |
14718 |
++ * described with an kdbus_item, and an entry is considered matching if all |
14719 |
++ * its rules are satisfied. |
14720 |
++ * |
14721 |
++ * The items attached to a kdbus_cmd_match struct have the following mapping: |
14722 |
++ * |
14723 |
++ * KDBUS_ITEM_BLOOM_MASK: A bloom mask |
14724 |
++ * KDBUS_ITEM_NAME: A connection's source name |
14725 |
++ * KDBUS_ITEM_ID: A connection ID |
14726 |
++ * KDBUS_ITEM_NAME_ADD: |
14727 |
++ * KDBUS_ITEM_NAME_REMOVE: |
14728 |
++ * KDBUS_ITEM_NAME_CHANGE: Well-known name changes, carry |
14729 |
++ * kdbus_notify_name_change |
14730 |
++ * KDBUS_ITEM_ID_ADD: |
14731 |
++ * KDBUS_ITEM_ID_REMOVE: Connection ID changes, carry |
14732 |
++ * kdbus_notify_id_change |
14733 |
++ * |
14734 |
++ * For kdbus_notify_{id,name}_change structs, only the ID and name fields |
14735 |
++ * are looked at when adding an entry. The flags are unused. |
14736 |
++ * |
14737 |
++ * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME and KDBUS_ITEM_ID |
14738 |
++ * are used to match messages from userspace, while the others apply to |
14739 |
++ * kernel-generated notifications. |
14740 |
++ * |
14741 |
++ * Return: 0 on success, negative error code on failure. |
14742 |
++ */ |
14743 |
++int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp) |
14744 |
++{ |
14745 |
++ struct kdbus_match_db *mdb = conn->match_db; |
14746 |
++ struct kdbus_match_entry *entry = NULL; |
14747 |
++ struct kdbus_cmd_match *cmd; |
14748 |
++ struct kdbus_item *item; |
14749 |
++ int ret; |
14750 |
++ |
14751 |
++ struct kdbus_arg argv[] = { |
14752 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
14753 |
++ { .type = KDBUS_ITEM_BLOOM_MASK, .multiple = true }, |
14754 |
++ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
14755 |
++ { .type = KDBUS_ITEM_ID, .multiple = true }, |
14756 |
++ { .type = KDBUS_ITEM_NAME_ADD, .multiple = true }, |
14757 |
++ { .type = KDBUS_ITEM_NAME_REMOVE, .multiple = true }, |
14758 |
++ { .type = KDBUS_ITEM_NAME_CHANGE, .multiple = true }, |
14759 |
++ { .type = KDBUS_ITEM_ID_ADD, .multiple = true }, |
14760 |
++ { .type = KDBUS_ITEM_ID_REMOVE, .multiple = true }, |
14761 |
++ }; |
14762 |
++ struct kdbus_args args = { |
14763 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
14764 |
++ KDBUS_MATCH_REPLACE, |
14765 |
++ .argv = argv, |
14766 |
++ .argc = ARRAY_SIZE(argv), |
14767 |
++ }; |
14768 |
++ |
14769 |
++ if (!kdbus_conn_is_ordinary(conn)) |
14770 |
++ return -EOPNOTSUPP; |
14771 |
++ |
14772 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
14773 |
++ if (ret != 0) |
14774 |
++ return ret; |
14775 |
++ |
14776 |
++ entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
14777 |
++ if (!entry) { |
14778 |
++ ret = -ENOMEM; |
14779 |
++ goto exit; |
14780 |
++ } |
14781 |
++ |
14782 |
++ entry->cookie = cmd->cookie; |
14783 |
++ INIT_LIST_HEAD(&entry->list_entry); |
14784 |
++ INIT_LIST_HEAD(&entry->rules_list); |
14785 |
++ |
14786 |
++ KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) { |
14787 |
++ struct kdbus_match_rule *rule; |
14788 |
++ size_t size = item->size - offsetof(struct kdbus_item, data); |
14789 |
++ |
14790 |
++ rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
14791 |
++ if (!rule) { |
14792 |
++ ret = -ENOMEM; |
14793 |
++ goto exit; |
14794 |
++ } |
14795 |
++ |
14796 |
++ rule->type = item->type; |
14797 |
++ INIT_LIST_HEAD(&rule->rules_entry); |
14798 |
++ |
14799 |
++ switch (item->type) { |
14800 |
++ case KDBUS_ITEM_BLOOM_MASK: { |
14801 |
++ u64 bsize = conn->ep->bus->bloom.size; |
14802 |
++ u64 generations; |
14803 |
++ u64 remainder; |
14804 |
++ |
14805 |
++ generations = div64_u64_rem(size, bsize, &remainder); |
14806 |
++ if (size < bsize || remainder > 0) { |
14807 |
++ ret = -EDOM; |
14808 |
++ break; |
14809 |
++ } |
14810 |
++ |
14811 |
++ rule->bloom_mask.data = kmemdup(item->data, |
14812 |
++ size, GFP_KERNEL); |
14813 |
++ if (!rule->bloom_mask.data) { |
14814 |
++ ret = -ENOMEM; |
14815 |
++ break; |
14816 |
++ } |
14817 |
++ |
14818 |
++ rule->bloom_mask.generations = generations; |
14819 |
++ break; |
14820 |
++ } |
14821 |
++ |
14822 |
++ case KDBUS_ITEM_NAME: |
14823 |
++ if (!kdbus_name_is_valid(item->str, false)) { |
14824 |
++ ret = -EINVAL; |
14825 |
++ break; |
14826 |
++ } |
14827 |
++ |
14828 |
++ rule->name = kstrdup(item->str, GFP_KERNEL); |
14829 |
++ if (!rule->name) |
14830 |
++ ret = -ENOMEM; |
14831 |
++ |
14832 |
++ break; |
14833 |
++ |
14834 |
++ case KDBUS_ITEM_ID: |
14835 |
++ rule->src_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..ea42929 |
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_kmsg; |
14955 |
++struct kdbus_match_db; |
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_kmsg(struct kdbus_match_db *db, |
14964 |
++ struct kdbus_conn *conn_src, |
14965 |
++ struct kdbus_kmsg *kmsg); |
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..8096075 |
14974 |
+--- /dev/null |
14975 |
++++ b/ipc/kdbus/message.c |
14976 |
+@@ -0,0 +1,616 @@ |
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 |
++#define KDBUS_KMSG_HEADER_SIZE offsetof(struct kdbus_kmsg, msg) |
15017 |
++ |
15018 |
++static struct kdbus_msg_resources *kdbus_msg_resources_new(void) |
15019 |
++{ |
15020 |
++ struct kdbus_msg_resources *r; |
15021 |
++ |
15022 |
++ r = kzalloc(sizeof(*r), GFP_KERNEL); |
15023 |
++ if (!r) |
15024 |
++ return ERR_PTR(-ENOMEM); |
15025 |
++ |
15026 |
++ kref_init(&r->kref); |
15027 |
++ |
15028 |
++ return r; |
15029 |
++} |
15030 |
++ |
15031 |
++static void __kdbus_msg_resources_free(struct kref *kref) |
15032 |
++{ |
15033 |
++ struct kdbus_msg_resources *r = |
15034 |
++ container_of(kref, struct kdbus_msg_resources, kref); |
15035 |
++ size_t i; |
15036 |
++ |
15037 |
++ for (i = 0; i < r->data_count; ++i) { |
15038 |
++ switch (r->data[i].type) { |
15039 |
++ case KDBUS_MSG_DATA_VEC: |
15040 |
++ /* nothing to do */ |
15041 |
++ break; |
15042 |
++ case KDBUS_MSG_DATA_MEMFD: |
15043 |
++ if (r->data[i].memfd.file) |
15044 |
++ fput(r->data[i].memfd.file); |
15045 |
++ break; |
15046 |
++ } |
15047 |
++ } |
15048 |
++ |
15049 |
++ for (i = 0; i < r->fds_count; i++) |
15050 |
++ if (r->fds[i]) |
15051 |
++ fput(r->fds[i]); |
15052 |
++ |
15053 |
++ kfree(r->dst_name); |
15054 |
++ kfree(r->data); |
15055 |
++ kfree(r->fds); |
15056 |
++ kfree(r); |
15057 |
++} |
15058 |
++ |
15059 |
++/** |
15060 |
++ * kdbus_msg_resources_ref() - Acquire reference to msg resources |
15061 |
++ * @r: resources to acquire ref to |
15062 |
++ * |
15063 |
++ * Return: The acquired resource |
15064 |
++ */ |
15065 |
++struct kdbus_msg_resources * |
15066 |
++kdbus_msg_resources_ref(struct kdbus_msg_resources *r) |
15067 |
++{ |
15068 |
++ if (r) |
15069 |
++ kref_get(&r->kref); |
15070 |
++ return r; |
15071 |
++} |
15072 |
++ |
15073 |
++/** |
15074 |
++ * kdbus_msg_resources_unref() - Drop reference to msg resources |
15075 |
++ * @r: resources to drop reference of |
15076 |
++ * |
15077 |
++ * Return: NULL |
15078 |
++ */ |
15079 |
++struct kdbus_msg_resources * |
15080 |
++kdbus_msg_resources_unref(struct kdbus_msg_resources *r) |
15081 |
++{ |
15082 |
++ if (r) |
15083 |
++ kref_put(&r->kref, __kdbus_msg_resources_free); |
15084 |
++ return NULL; |
15085 |
++} |
15086 |
++ |
15087 |
++/** |
15088 |
++ * kdbus_kmsg_free() - free allocated message |
15089 |
++ * @kmsg: Message |
15090 |
++ */ |
15091 |
++void kdbus_kmsg_free(struct kdbus_kmsg *kmsg) |
15092 |
++{ |
15093 |
++ if (!kmsg) |
15094 |
++ return; |
15095 |
++ |
15096 |
++ kdbus_msg_resources_unref(kmsg->res); |
15097 |
++ kdbus_meta_conn_unref(kmsg->conn_meta); |
15098 |
++ kdbus_meta_proc_unref(kmsg->proc_meta); |
15099 |
++ kfree(kmsg->iov); |
15100 |
++ kfree(kmsg); |
15101 |
++} |
15102 |
++ |
15103 |
++/** |
15104 |
++ * kdbus_kmsg_new() - allocate message |
15105 |
++ * @bus: Bus this message is allocated on |
15106 |
++ * @extra_size: Additional size to reserve for data |
15107 |
++ * |
15108 |
++ * Return: new kdbus_kmsg on success, ERR_PTR on failure. |
15109 |
++ */ |
15110 |
++struct kdbus_kmsg *kdbus_kmsg_new(struct kdbus_bus *bus, size_t extra_size) |
15111 |
++{ |
15112 |
++ struct kdbus_kmsg *m; |
15113 |
++ size_t size; |
15114 |
++ int ret; |
15115 |
++ |
15116 |
++ size = sizeof(struct kdbus_kmsg) + KDBUS_ITEM_SIZE(extra_size); |
15117 |
++ m = kzalloc(size, GFP_KERNEL); |
15118 |
++ if (!m) |
15119 |
++ return ERR_PTR(-ENOMEM); |
15120 |
++ |
15121 |
++ m->seq = atomic64_inc_return(&bus->domain->last_id); |
15122 |
++ m->msg.size = size - KDBUS_KMSG_HEADER_SIZE; |
15123 |
++ m->msg.items[0].size = KDBUS_ITEM_SIZE(extra_size); |
15124 |
++ |
15125 |
++ m->proc_meta = kdbus_meta_proc_new(); |
15126 |
++ if (IS_ERR(m->proc_meta)) { |
15127 |
++ ret = PTR_ERR(m->proc_meta); |
15128 |
++ m->proc_meta = NULL; |
15129 |
++ goto exit; |
15130 |
++ } |
15131 |
++ |
15132 |
++ m->conn_meta = kdbus_meta_conn_new(); |
15133 |
++ if (IS_ERR(m->conn_meta)) { |
15134 |
++ ret = PTR_ERR(m->conn_meta); |
15135 |
++ m->conn_meta = NULL; |
15136 |
++ goto exit; |
15137 |
++ } |
15138 |
++ |
15139 |
++ return m; |
15140 |
++ |
15141 |
++exit: |
15142 |
++ kdbus_kmsg_free(m); |
15143 |
++ return ERR_PTR(ret); |
15144 |
++} |
15145 |
++ |
15146 |
++static int kdbus_handle_check_file(struct file *file) |
15147 |
++{ |
15148 |
++ struct inode *inode = file_inode(file); |
15149 |
++ struct socket *sock; |
15150 |
++ |
15151 |
++ /* |
15152 |
++ * Don't allow file descriptors in the transport that themselves allow |
15153 |
++ * file descriptor queueing. This will eventually be allowed once both |
15154 |
++ * unix domain sockets and kdbus share a generic garbage collector. |
15155 |
++ */ |
15156 |
++ |
15157 |
++ if (file->f_op == &kdbus_handle_ops) |
15158 |
++ return -EOPNOTSUPP; |
15159 |
++ |
15160 |
++ if (!S_ISSOCK(inode->i_mode)) |
15161 |
++ return 0; |
15162 |
++ |
15163 |
++ if (file->f_mode & FMODE_PATH) |
15164 |
++ return 0; |
15165 |
++ |
15166 |
++ sock = SOCKET_I(inode); |
15167 |
++ if (sock->sk && sock->ops && sock->ops->family == PF_UNIX) |
15168 |
++ return -EOPNOTSUPP; |
15169 |
++ |
15170 |
++ return 0; |
15171 |
++} |
15172 |
++ |
15173 |
++static const char * const zeros = "\0\0\0\0\0\0\0"; |
15174 |
++ |
15175 |
++/* |
15176 |
++ * kdbus_msg_scan_items() - validate incoming data and prepare parsing |
15177 |
++ * @kmsg: Message |
15178 |
++ * @bus: Bus the message is sent over |
15179 |
++ * |
15180 |
++ * Return: 0 on success, negative errno on failure. |
15181 |
++ * |
15182 |
++ * Files references in MEMFD or FDS items are pinned. |
15183 |
++ * |
15184 |
++ * On errors, the caller should drop any taken reference with |
15185 |
++ * kdbus_kmsg_free() |
15186 |
++ */ |
15187 |
++static int kdbus_msg_scan_items(struct kdbus_kmsg *kmsg, |
15188 |
++ struct kdbus_bus *bus) |
15189 |
++{ |
15190 |
++ struct kdbus_msg_resources *res = kmsg->res; |
15191 |
++ const struct kdbus_msg *msg = &kmsg->msg; |
15192 |
++ const struct kdbus_item *item; |
15193 |
++ size_t n, n_vecs, n_memfds; |
15194 |
++ bool has_bloom = false; |
15195 |
++ bool has_name = false; |
15196 |
++ bool has_fds = false; |
15197 |
++ bool is_broadcast; |
15198 |
++ bool is_signal; |
15199 |
++ u64 vec_size; |
15200 |
++ |
15201 |
++ is_broadcast = (msg->dst_id == KDBUS_DST_ID_BROADCAST); |
15202 |
++ is_signal = !!(msg->flags & KDBUS_MSG_SIGNAL); |
15203 |
++ |
15204 |
++ /* count data payloads */ |
15205 |
++ n_vecs = 0; |
15206 |
++ n_memfds = 0; |
15207 |
++ KDBUS_ITEMS_FOREACH(item, msg->items, KDBUS_ITEMS_SIZE(msg, items)) { |
15208 |
++ switch (item->type) { |
15209 |
++ case KDBUS_ITEM_PAYLOAD_VEC: |
15210 |
++ ++n_vecs; |
15211 |
++ break; |
15212 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: |
15213 |
++ ++n_memfds; |
15214 |
++ if (item->memfd.size % 8) |
15215 |
++ ++n_vecs; |
15216 |
++ break; |
15217 |
++ default: |
15218 |
++ break; |
15219 |
++ } |
15220 |
++ } |
15221 |
++ |
15222 |
++ n = n_vecs + n_memfds; |
15223 |
++ if (n > 0) { |
15224 |
++ res->data = kcalloc(n, sizeof(*res->data), GFP_KERNEL); |
15225 |
++ if (!res->data) |
15226 |
++ return -ENOMEM; |
15227 |
++ } |
15228 |
++ |
15229 |
++ if (n_vecs > 0) { |
15230 |
++ kmsg->iov = kcalloc(n_vecs, sizeof(*kmsg->iov), GFP_KERNEL); |
15231 |
++ if (!kmsg->iov) |
15232 |
++ return -ENOMEM; |
15233 |
++ } |
15234 |
++ |
15235 |
++ /* import data payloads */ |
15236 |
++ n = 0; |
15237 |
++ vec_size = 0; |
15238 |
++ KDBUS_ITEMS_FOREACH(item, msg->items, KDBUS_ITEMS_SIZE(msg, items)) { |
15239 |
++ size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item); |
15240 |
++ struct iovec *iov = kmsg->iov + kmsg->iov_count; |
15241 |
++ |
15242 |
++ if (++n > KDBUS_MSG_MAX_ITEMS) |
15243 |
++ return -E2BIG; |
15244 |
++ |
15245 |
++ switch (item->type) { |
15246 |
++ case KDBUS_ITEM_PAYLOAD_VEC: { |
15247 |
++ struct kdbus_msg_data *d = res->data + res->data_count; |
15248 |
++ void __force __user *ptr = KDBUS_PTR(item->vec.address); |
15249 |
++ size_t size = item->vec.size; |
15250 |
++ |
15251 |
++ if (vec_size + size < vec_size) |
15252 |
++ return -EMSGSIZE; |
15253 |
++ if (vec_size + size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE) |
15254 |
++ return -EMSGSIZE; |
15255 |
++ |
15256 |
++ d->type = KDBUS_MSG_DATA_VEC; |
15257 |
++ d->size = size; |
15258 |
++ |
15259 |
++ if (ptr) { |
15260 |
++ if (unlikely(!access_ok(VERIFY_READ, ptr, |
15261 |
++ size))) |
15262 |
++ return -EFAULT; |
15263 |
++ |
15264 |
++ d->vec.off = kmsg->pool_size; |
15265 |
++ iov->iov_base = ptr; |
15266 |
++ iov->iov_len = size; |
15267 |
++ } else { |
15268 |
++ d->vec.off = ~0ULL; |
15269 |
++ iov->iov_base = (char __user *)zeros; |
15270 |
++ iov->iov_len = size % 8; |
15271 |
++ } |
15272 |
++ |
15273 |
++ if (kmsg->pool_size + iov->iov_len < kmsg->pool_size) |
15274 |
++ return -EMSGSIZE; |
15275 |
++ |
15276 |
++ kmsg->pool_size += iov->iov_len; |
15277 |
++ ++kmsg->iov_count; |
15278 |
++ ++res->vec_count; |
15279 |
++ ++res->data_count; |
15280 |
++ vec_size += size; |
15281 |
++ |
15282 |
++ break; |
15283 |
++ } |
15284 |
++ |
15285 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
15286 |
++ struct kdbus_msg_data *d = res->data + res->data_count; |
15287 |
++ u64 start = item->memfd.start; |
15288 |
++ u64 size = item->memfd.size; |
15289 |
++ size_t pad = size % 8; |
15290 |
++ int seals, mask; |
15291 |
++ struct file *f; |
15292 |
++ |
15293 |
++ if (kmsg->pool_size + size % 8 < kmsg->pool_size) |
15294 |
++ return -EMSGSIZE; |
15295 |
++ if (start + size < start) |
15296 |
++ return -EMSGSIZE; |
15297 |
++ |
15298 |
++ if (item->memfd.fd < 0) |
15299 |
++ return -EBADF; |
15300 |
++ |
15301 |
++ if (res->memfd_count >= KDBUS_MSG_MAX_MEMFD_ITEMS) |
15302 |
++ return -E2BIG; |
15303 |
++ |
15304 |
++ f = fget(item->memfd.fd); |
15305 |
++ if (!f) |
15306 |
++ return -EBADF; |
15307 |
++ |
15308 |
++ if (pad) { |
15309 |
++ iov->iov_base = (char __user *)zeros; |
15310 |
++ iov->iov_len = pad; |
15311 |
++ |
15312 |
++ kmsg->pool_size += pad; |
15313 |
++ ++kmsg->iov_count; |
15314 |
++ } |
15315 |
++ |
15316 |
++ ++res->data_count; |
15317 |
++ ++res->memfd_count; |
15318 |
++ |
15319 |
++ d->type = KDBUS_MSG_DATA_MEMFD; |
15320 |
++ d->size = size; |
15321 |
++ d->memfd.start = start; |
15322 |
++ d->memfd.file = f; |
15323 |
++ |
15324 |
++ /* |
15325 |
++ * We only accept a sealed memfd file whose content |
15326 |
++ * cannot be altered by the sender or anybody else |
15327 |
++ * while it is shared or in-flight. Other files need |
15328 |
++ * to be passed with KDBUS_MSG_FDS. |
15329 |
++ */ |
15330 |
++ seals = shmem_get_seals(f); |
15331 |
++ if (seals < 0) |
15332 |
++ return -EMEDIUMTYPE; |
15333 |
++ |
15334 |
++ mask = F_SEAL_SHRINK | F_SEAL_GROW | |
15335 |
++ F_SEAL_WRITE | F_SEAL_SEAL; |
15336 |
++ if ((seals & mask) != mask) |
15337 |
++ return -ETXTBSY; |
15338 |
++ |
15339 |
++ if (start + size > (u64)i_size_read(file_inode(f))) |
15340 |
++ return -EBADF; |
15341 |
++ |
15342 |
++ break; |
15343 |
++ } |
15344 |
++ |
15345 |
++ case KDBUS_ITEM_FDS: { |
15346 |
++ unsigned int i; |
15347 |
++ unsigned int fds_count = payload_size / sizeof(int); |
15348 |
++ |
15349 |
++ /* do not allow multiple fd arrays */ |
15350 |
++ if (has_fds) |
15351 |
++ return -EEXIST; |
15352 |
++ has_fds = true; |
15353 |
++ |
15354 |
++ /* Do not allow to broadcast file descriptors */ |
15355 |
++ if (is_broadcast) |
15356 |
++ return -ENOTUNIQ; |
15357 |
++ |
15358 |
++ if (fds_count > KDBUS_CONN_MAX_FDS_PER_USER) |
15359 |
++ return -EMFILE; |
15360 |
++ |
15361 |
++ res->fds = kcalloc(fds_count, sizeof(struct file *), |
15362 |
++ GFP_KERNEL); |
15363 |
++ if (!res->fds) |
15364 |
++ return -ENOMEM; |
15365 |
++ |
15366 |
++ for (i = 0; i < fds_count; i++) { |
15367 |
++ int fd = item->fds[i]; |
15368 |
++ int ret; |
15369 |
++ |
15370 |
++ /* |
15371 |
++ * Verify the fd and increment the usage count. |
15372 |
++ * Use fget_raw() to allow passing O_PATH fds. |
15373 |
++ */ |
15374 |
++ if (fd < 0) |
15375 |
++ return -EBADF; |
15376 |
++ |
15377 |
++ res->fds[i] = fget_raw(fd); |
15378 |
++ if (!res->fds[i]) |
15379 |
++ return -EBADF; |
15380 |
++ |
15381 |
++ res->fds_count++; |
15382 |
++ |
15383 |
++ ret = kdbus_handle_check_file(res->fds[i]); |
15384 |
++ if (ret < 0) |
15385 |
++ return ret; |
15386 |
++ } |
15387 |
++ |
15388 |
++ break; |
15389 |
++ } |
15390 |
++ |
15391 |
++ case KDBUS_ITEM_BLOOM_FILTER: { |
15392 |
++ u64 bloom_size; |
15393 |
++ |
15394 |
++ /* do not allow multiple bloom filters */ |
15395 |
++ if (has_bloom) |
15396 |
++ return -EEXIST; |
15397 |
++ has_bloom = true; |
15398 |
++ |
15399 |
++ bloom_size = payload_size - |
15400 |
++ offsetof(struct kdbus_bloom_filter, data); |
15401 |
++ |
15402 |
++ /* |
15403 |
++ * Allow only bloom filter sizes of a multiple of 64bit. |
15404 |
++ */ |
15405 |
++ if (!KDBUS_IS_ALIGNED8(bloom_size)) |
15406 |
++ return -EFAULT; |
15407 |
++ |
15408 |
++ /* do not allow mismatching bloom filter sizes */ |
15409 |
++ if (bloom_size != bus->bloom.size) |
15410 |
++ return -EDOM; |
15411 |
++ |
15412 |
++ kmsg->bloom_filter = &item->bloom_filter; |
15413 |
++ break; |
15414 |
++ } |
15415 |
++ |
15416 |
++ case KDBUS_ITEM_DST_NAME: |
15417 |
++ /* do not allow multiple names */ |
15418 |
++ if (has_name) |
15419 |
++ return -EEXIST; |
15420 |
++ has_name = true; |
15421 |
++ |
15422 |
++ if (!kdbus_name_is_valid(item->str, false)) |
15423 |
++ return -EINVAL; |
15424 |
++ |
15425 |
++ res->dst_name = kstrdup(item->str, GFP_KERNEL); |
15426 |
++ if (!res->dst_name) |
15427 |
++ return -ENOMEM; |
15428 |
++ break; |
15429 |
++ |
15430 |
++ default: |
15431 |
++ return -EINVAL; |
15432 |
++ } |
15433 |
++ } |
15434 |
++ |
15435 |
++ /* name is needed if no ID is given */ |
15436 |
++ if (msg->dst_id == KDBUS_DST_ID_NAME && !has_name) |
15437 |
++ return -EDESTADDRREQ; |
15438 |
++ |
15439 |
++ if (is_broadcast) { |
15440 |
++ /* Broadcasts can't take names */ |
15441 |
++ if (has_name) |
15442 |
++ return -EBADMSG; |
15443 |
++ |
15444 |
++ /* All broadcasts have to be signals */ |
15445 |
++ if (!is_signal) |
15446 |
++ return -EBADMSG; |
15447 |
++ |
15448 |
++ /* Timeouts are not allowed for broadcasts */ |
15449 |
++ if (msg->timeout_ns > 0) |
15450 |
++ return -ENOTUNIQ; |
15451 |
++ } |
15452 |
++ |
15453 |
++ /* |
15454 |
++ * Signal messages require a bloom filter, and bloom filters are |
15455 |
++ * only valid with signals. |
15456 |
++ */ |
15457 |
++ if (is_signal ^ has_bloom) |
15458 |
++ return -EBADMSG; |
15459 |
++ |
15460 |
++ return 0; |
15461 |
++} |
15462 |
++ |
15463 |
++/** |
15464 |
++ * kdbus_kmsg_new_from_cmd() - create kernel message from send payload |
15465 |
++ * @conn: Connection |
15466 |
++ * @cmd_send: Payload of KDBUS_CMD_SEND |
15467 |
++ * |
15468 |
++ * Return: a new kdbus_kmsg on success, ERR_PTR on failure. |
15469 |
++ */ |
15470 |
++struct kdbus_kmsg *kdbus_kmsg_new_from_cmd(struct kdbus_conn *conn, |
15471 |
++ struct kdbus_cmd_send *cmd_send) |
15472 |
++{ |
15473 |
++ struct kdbus_kmsg *m; |
15474 |
++ u64 size; |
15475 |
++ int ret; |
15476 |
++ |
15477 |
++ ret = kdbus_copy_from_user(&size, KDBUS_PTR(cmd_send->msg_address), |
15478 |
++ sizeof(size)); |
15479 |
++ if (ret < 0) |
15480 |
++ return ERR_PTR(ret); |
15481 |
++ |
15482 |
++ if (size < sizeof(struct kdbus_msg) || size > KDBUS_MSG_MAX_SIZE) |
15483 |
++ return ERR_PTR(-EINVAL); |
15484 |
++ |
15485 |
++ m = kmalloc(size + KDBUS_KMSG_HEADER_SIZE, GFP_KERNEL); |
15486 |
++ if (!m) |
15487 |
++ return ERR_PTR(-ENOMEM); |
15488 |
++ |
15489 |
++ memset(m, 0, KDBUS_KMSG_HEADER_SIZE); |
15490 |
++ m->seq = atomic64_inc_return(&conn->ep->bus->domain->last_id); |
15491 |
++ |
15492 |
++ m->proc_meta = kdbus_meta_proc_new(); |
15493 |
++ if (IS_ERR(m->proc_meta)) { |
15494 |
++ ret = PTR_ERR(m->proc_meta); |
15495 |
++ m->proc_meta = NULL; |
15496 |
++ goto exit_free; |
15497 |
++ } |
15498 |
++ |
15499 |
++ m->conn_meta = kdbus_meta_conn_new(); |
15500 |
++ if (IS_ERR(m->conn_meta)) { |
15501 |
++ ret = PTR_ERR(m->conn_meta); |
15502 |
++ m->conn_meta = NULL; |
15503 |
++ goto exit_free; |
15504 |
++ } |
15505 |
++ |
15506 |
++ if (copy_from_user(&m->msg, KDBUS_PTR(cmd_send->msg_address), size)) { |
15507 |
++ ret = -EFAULT; |
15508 |
++ goto exit_free; |
15509 |
++ } |
15510 |
++ |
15511 |
++ if (m->msg.size != size) { |
15512 |
++ ret = -EINVAL; |
15513 |
++ goto exit_free; |
15514 |
++ } |
15515 |
++ |
15516 |
++ if (m->msg.flags & ~(KDBUS_MSG_EXPECT_REPLY | |
15517 |
++ KDBUS_MSG_NO_AUTO_START | |
15518 |
++ KDBUS_MSG_SIGNAL)) { |
15519 |
++ ret = -EINVAL; |
15520 |
++ goto exit_free; |
15521 |
++ } |
15522 |
++ |
15523 |
++ ret = kdbus_items_validate(m->msg.items, |
15524 |
++ KDBUS_ITEMS_SIZE(&m->msg, items)); |
15525 |
++ if (ret < 0) |
15526 |
++ goto exit_free; |
15527 |
++ |
15528 |
++ m->res = kdbus_msg_resources_new(); |
15529 |
++ if (IS_ERR(m->res)) { |
15530 |
++ ret = PTR_ERR(m->res); |
15531 |
++ m->res = NULL; |
15532 |
++ goto exit_free; |
15533 |
++ } |
15534 |
++ |
15535 |
++ /* do not accept kernel-generated messages */ |
15536 |
++ if (m->msg.payload_type == KDBUS_PAYLOAD_KERNEL) { |
15537 |
++ ret = -EINVAL; |
15538 |
++ goto exit_free; |
15539 |
++ } |
15540 |
++ |
15541 |
++ if (m->msg.flags & KDBUS_MSG_EXPECT_REPLY) { |
15542 |
++ /* requests for replies need timeout and cookie */ |
15543 |
++ if (m->msg.timeout_ns == 0 || m->msg.cookie == 0) { |
15544 |
++ ret = -EINVAL; |
15545 |
++ goto exit_free; |
15546 |
++ } |
15547 |
++ |
15548 |
++ /* replies may not be expected for broadcasts */ |
15549 |
++ if (m->msg.dst_id == KDBUS_DST_ID_BROADCAST) { |
15550 |
++ ret = -ENOTUNIQ; |
15551 |
++ goto exit_free; |
15552 |
++ } |
15553 |
++ |
15554 |
++ /* replies may not be expected for signals */ |
15555 |
++ if (m->msg.flags & KDBUS_MSG_SIGNAL) { |
15556 |
++ ret = -EINVAL; |
15557 |
++ goto exit_free; |
15558 |
++ } |
15559 |
++ } else { |
15560 |
++ /* |
15561 |
++ * KDBUS_SEND_SYNC_REPLY is only valid together with |
15562 |
++ * KDBUS_MSG_EXPECT_REPLY |
15563 |
++ */ |
15564 |
++ if (cmd_send->flags & KDBUS_SEND_SYNC_REPLY) { |
15565 |
++ ret = -EINVAL; |
15566 |
++ goto exit_free; |
15567 |
++ } |
15568 |
++ |
15569 |
++ /* replies cannot be signals */ |
15570 |
++ if (m->msg.cookie_reply && (m->msg.flags & KDBUS_MSG_SIGNAL)) { |
15571 |
++ ret = -EINVAL; |
15572 |
++ goto exit_free; |
15573 |
++ } |
15574 |
++ } |
15575 |
++ |
15576 |
++ ret = kdbus_msg_scan_items(m, conn->ep->bus); |
15577 |
++ if (ret < 0) |
15578 |
++ goto exit_free; |
15579 |
++ |
15580 |
++ /* patch-in the source of this message */ |
15581 |
++ if (m->msg.src_id > 0 && m->msg.src_id != conn->id) { |
15582 |
++ ret = -EINVAL; |
15583 |
++ goto exit_free; |
15584 |
++ } |
15585 |
++ m->msg.src_id = conn->id; |
15586 |
++ |
15587 |
++ return m; |
15588 |
++ |
15589 |
++exit_free: |
15590 |
++ kdbus_kmsg_free(m); |
15591 |
++ return ERR_PTR(ret); |
15592 |
++} |
15593 |
+diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h |
15594 |
+new file mode 100644 |
15595 |
+index 0000000..af47758 |
15596 |
+--- /dev/null |
15597 |
++++ b/ipc/kdbus/message.h |
15598 |
+@@ -0,0 +1,133 @@ |
15599 |
++/* |
15600 |
++ * Copyright (C) 2013-2015 Kay Sievers |
15601 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
15602 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
15603 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
15604 |
++ * Copyright (C) 2013-2015 Linux Foundation |
15605 |
++ * |
15606 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
15607 |
++ * the terms of the GNU Lesser General Public License as published by the |
15608 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
15609 |
++ * your option) any later version. |
15610 |
++ */ |
15611 |
++ |
15612 |
++#ifndef __KDBUS_MESSAGE_H |
15613 |
++#define __KDBUS_MESSAGE_H |
15614 |
++ |
15615 |
++#include "util.h" |
15616 |
++#include "metadata.h" |
15617 |
++ |
15618 |
++/** |
15619 |
++ * enum kdbus_msg_data_type - Type of kdbus_msg_data payloads |
15620 |
++ * @KDBUS_MSG_DATA_VEC: Data vector provided by user-space |
15621 |
++ * @KDBUS_MSG_DATA_MEMFD: Memfd payload |
15622 |
++ */ |
15623 |
++enum kdbus_msg_data_type { |
15624 |
++ KDBUS_MSG_DATA_VEC, |
15625 |
++ KDBUS_MSG_DATA_MEMFD, |
15626 |
++}; |
15627 |
++ |
15628 |
++/** |
15629 |
++ * struct kdbus_msg_data - Data payload as stored by messages |
15630 |
++ * @type: Type of payload (KDBUS_MSG_DATA_*) |
15631 |
++ * @size: Size of the described payload |
15632 |
++ * @off: The offset, relative to the vec slice |
15633 |
++ * @start: Offset inside the memfd |
15634 |
++ * @file: Backing file referenced by the memfd |
15635 |
++ */ |
15636 |
++struct kdbus_msg_data { |
15637 |
++ unsigned int type; |
15638 |
++ u64 size; |
15639 |
++ |
15640 |
++ union { |
15641 |
++ struct { |
15642 |
++ u64 off; |
15643 |
++ } vec; |
15644 |
++ struct { |
15645 |
++ u64 start; |
15646 |
++ struct file *file; |
15647 |
++ } memfd; |
15648 |
++ }; |
15649 |
++}; |
15650 |
++ |
15651 |
++/** |
15652 |
++ * struct kdbus_kmsg_resources - resources of a message |
15653 |
++ * @kref: Reference counter |
15654 |
++ * @dst_name: Short-cut to msg for faster lookup |
15655 |
++ * @fds: Array of file descriptors to pass |
15656 |
++ * @fds_count: Number of file descriptors to pass |
15657 |
++ * @data: Array of data payloads |
15658 |
++ * @vec_count: Number of VEC entries |
15659 |
++ * @memfd_count: Number of MEMFD entries in @data |
15660 |
++ * @data_count: Sum of @vec_count + @memfd_count |
15661 |
++ */ |
15662 |
++struct kdbus_msg_resources { |
15663 |
++ struct kref kref; |
15664 |
++ const char *dst_name; |
15665 |
++ |
15666 |
++ struct file **fds; |
15667 |
++ unsigned int fds_count; |
15668 |
++ |
15669 |
++ struct kdbus_msg_data *data; |
15670 |
++ size_t vec_count; |
15671 |
++ size_t memfd_count; |
15672 |
++ size_t data_count; |
15673 |
++}; |
15674 |
++ |
15675 |
++struct kdbus_msg_resources * |
15676 |
++kdbus_msg_resources_ref(struct kdbus_msg_resources *r); |
15677 |
++struct kdbus_msg_resources * |
15678 |
++kdbus_msg_resources_unref(struct kdbus_msg_resources *r); |
15679 |
++ |
15680 |
++/** |
15681 |
++ * struct kdbus_kmsg - internal message handling data |
15682 |
++ * @seq: Domain-global message sequence number |
15683 |
++ * @notify_type: Short-cut for faster lookup |
15684 |
++ * @notify_old_id: Short-cut for faster lookup |
15685 |
++ * @notify_new_id: Short-cut for faster lookup |
15686 |
++ * @notify_name: Short-cut for faster lookup |
15687 |
++ * @dst_name_id: Short-cut to msg for faster lookup |
15688 |
++ * @bloom_filter: Bloom filter to match message properties |
15689 |
++ * @bloom_generation: Generation of bloom element set |
15690 |
++ * @notify_entry: List of kernel-generated notifications |
15691 |
++ * @iov: Array of iovec, describing the payload to copy |
15692 |
++ * @iov_count: Number of array members in @iov |
15693 |
++ * @pool_size: Overall size of inlined data referenced by @iov |
15694 |
++ * @proc_meta: Appended SCM-like metadata of the sending process |
15695 |
++ * @conn_meta: Appended SCM-like metadata of the sending connection |
15696 |
++ * @res: Message resources |
15697 |
++ * @msg: Message from or to userspace |
15698 |
++ */ |
15699 |
++struct kdbus_kmsg { |
15700 |
++ u64 seq; |
15701 |
++ u64 notify_type; |
15702 |
++ u64 notify_old_id; |
15703 |
++ u64 notify_new_id; |
15704 |
++ const char *notify_name; |
15705 |
++ |
15706 |
++ u64 dst_name_id; |
15707 |
++ const struct kdbus_bloom_filter *bloom_filter; |
15708 |
++ u64 bloom_generation; |
15709 |
++ struct list_head notify_entry; |
15710 |
++ |
15711 |
++ struct iovec *iov; |
15712 |
++ size_t iov_count; |
15713 |
++ u64 pool_size; |
15714 |
++ |
15715 |
++ struct kdbus_meta_proc *proc_meta; |
15716 |
++ struct kdbus_meta_conn *conn_meta; |
15717 |
++ struct kdbus_msg_resources *res; |
15718 |
++ |
15719 |
++ /* variable size, must be the last member */ |
15720 |
++ struct kdbus_msg msg; |
15721 |
++}; |
15722 |
++ |
15723 |
++struct kdbus_bus; |
15724 |
++struct kdbus_conn; |
15725 |
++ |
15726 |
++struct kdbus_kmsg *kdbus_kmsg_new(struct kdbus_bus *bus, size_t extra_size); |
15727 |
++struct kdbus_kmsg *kdbus_kmsg_new_from_cmd(struct kdbus_conn *conn, |
15728 |
++ struct kdbus_cmd_send *cmd_send); |
15729 |
++void kdbus_kmsg_free(struct kdbus_kmsg *kmsg); |
15730 |
++ |
15731 |
++#endif |
15732 |
+diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c |
15733 |
+new file mode 100644 |
15734 |
+index 0000000..3adc6c2 |
15735 |
+--- /dev/null |
15736 |
++++ b/ipc/kdbus/metadata.c |
15737 |
+@@ -0,0 +1,1159 @@ |
15738 |
++/* |
15739 |
++ * Copyright (C) 2013-2015 Kay Sievers |
15740 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
15741 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
15742 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
15743 |
++ * Copyright (C) 2013-2015 Linux Foundation |
15744 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
15745 |
++ * |
15746 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
15747 |
++ * the terms of the GNU Lesser General Public License as published by the |
15748 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
15749 |
++ * your option) any later version. |
15750 |
++ */ |
15751 |
++ |
15752 |
++#include <linux/audit.h> |
15753 |
++#include <linux/capability.h> |
15754 |
++#include <linux/cgroup.h> |
15755 |
++#include <linux/cred.h> |
15756 |
++#include <linux/file.h> |
15757 |
++#include <linux/fs_struct.h> |
15758 |
++#include <linux/init.h> |
15759 |
++#include <linux/kref.h> |
15760 |
++#include <linux/mutex.h> |
15761 |
++#include <linux/sched.h> |
15762 |
++#include <linux/security.h> |
15763 |
++#include <linux/sizes.h> |
15764 |
++#include <linux/slab.h> |
15765 |
++#include <linux/uaccess.h> |
15766 |
++#include <linux/uidgid.h> |
15767 |
++#include <linux/uio.h> |
15768 |
++#include <linux/user_namespace.h> |
15769 |
++#include <linux/version.h> |
15770 |
++ |
15771 |
++#include "bus.h" |
15772 |
++#include "connection.h" |
15773 |
++#include "endpoint.h" |
15774 |
++#include "item.h" |
15775 |
++#include "message.h" |
15776 |
++#include "metadata.h" |
15777 |
++#include "names.h" |
15778 |
++ |
15779 |
++/** |
15780 |
++ * struct kdbus_meta_proc - Process metadata |
15781 |
++ * @kref: Reference counting |
15782 |
++ * @lock: Object lock |
15783 |
++ * @collected: Bitmask of collected items |
15784 |
++ * @valid: Bitmask of collected and valid items |
15785 |
++ * @uid: UID of process |
15786 |
++ * @euid: EUID of process |
15787 |
++ * @suid: SUID of process |
15788 |
++ * @fsuid: FSUID of process |
15789 |
++ * @gid: GID of process |
15790 |
++ * @egid: EGID of process |
15791 |
++ * @sgid: SGID of process |
15792 |
++ * @fsgid: FSGID of process |
15793 |
++ * @pid: PID of process |
15794 |
++ * @tgid: TGID of process |
15795 |
++ * @ppid: PPID of process |
15796 |
++ * @auxgrps: Auxiliary groups |
15797 |
++ * @n_auxgrps: Number of items in @auxgrps |
15798 |
++ * @tid_comm: TID comm line |
15799 |
++ * @pid_comm: PID comm line |
15800 |
++ * @exe_path: Executable path |
15801 |
++ * @root_path: Root-FS path |
15802 |
++ * @cmdline: Command-line |
15803 |
++ * @cgroup: Full cgroup path |
15804 |
++ * @caps: Capabilities |
15805 |
++ * @caps_namespace: User-namespace of @caps |
15806 |
++ * @seclabel: Seclabel |
15807 |
++ * @audit_loginuid: Audit login-UID |
15808 |
++ * @audit_sessionid: Audit session-ID |
15809 |
++ */ |
15810 |
++struct kdbus_meta_proc { |
15811 |
++ struct kref kref; |
15812 |
++ struct mutex lock; |
15813 |
++ u64 collected; |
15814 |
++ u64 valid; |
15815 |
++ |
15816 |
++ /* KDBUS_ITEM_CREDS */ |
15817 |
++ kuid_t uid, euid, suid, fsuid; |
15818 |
++ kgid_t gid, egid, sgid, fsgid; |
15819 |
++ |
15820 |
++ /* KDBUS_ITEM_PIDS */ |
15821 |
++ struct pid *pid; |
15822 |
++ struct pid *tgid; |
15823 |
++ struct pid *ppid; |
15824 |
++ |
15825 |
++ /* KDBUS_ITEM_AUXGROUPS */ |
15826 |
++ kgid_t *auxgrps; |
15827 |
++ size_t n_auxgrps; |
15828 |
++ |
15829 |
++ /* KDBUS_ITEM_TID_COMM */ |
15830 |
++ char tid_comm[TASK_COMM_LEN]; |
15831 |
++ /* KDBUS_ITEM_PID_COMM */ |
15832 |
++ char pid_comm[TASK_COMM_LEN]; |
15833 |
++ |
15834 |
++ /* KDBUS_ITEM_EXE */ |
15835 |
++ struct path exe_path; |
15836 |
++ struct path root_path; |
15837 |
++ |
15838 |
++ /* KDBUS_ITEM_CMDLINE */ |
15839 |
++ char *cmdline; |
15840 |
++ |
15841 |
++ /* KDBUS_ITEM_CGROUP */ |
15842 |
++ char *cgroup; |
15843 |
++ |
15844 |
++ /* KDBUS_ITEM_CAPS */ |
15845 |
++ struct caps { |
15846 |
++ /* binary compatible to kdbus_caps */ |
15847 |
++ u32 last_cap; |
15848 |
++ struct { |
15849 |
++ u32 caps[_KERNEL_CAPABILITY_U32S]; |
15850 |
++ } set[4]; |
15851 |
++ } caps; |
15852 |
++ struct user_namespace *caps_namespace; |
15853 |
++ |
15854 |
++ /* KDBUS_ITEM_SECLABEL */ |
15855 |
++ char *seclabel; |
15856 |
++ |
15857 |
++ /* KDBUS_ITEM_AUDIT */ |
15858 |
++ kuid_t audit_loginuid; |
15859 |
++ unsigned int audit_sessionid; |
15860 |
++}; |
15861 |
++ |
15862 |
++/** |
15863 |
++ * struct kdbus_meta_conn |
15864 |
++ * @kref: Reference counting |
15865 |
++ * @lock: Object lock |
15866 |
++ * @collected: Bitmask of collected items |
15867 |
++ * @valid: Bitmask of collected and valid items |
15868 |
++ * @ts: Timestamp values |
15869 |
++ * @owned_names_items: Serialized items for owned names |
15870 |
++ * @owned_names_size: Size of @owned_names_items |
15871 |
++ * @conn_description: Connection description |
15872 |
++ */ |
15873 |
++struct kdbus_meta_conn { |
15874 |
++ struct kref kref; |
15875 |
++ struct mutex lock; |
15876 |
++ u64 collected; |
15877 |
++ u64 valid; |
15878 |
++ |
15879 |
++ /* KDBUS_ITEM_TIMESTAMP */ |
15880 |
++ struct kdbus_timestamp ts; |
15881 |
++ |
15882 |
++ /* KDBUS_ITEM_OWNED_NAME */ |
15883 |
++ struct kdbus_item *owned_names_items; |
15884 |
++ size_t owned_names_size; |
15885 |
++ |
15886 |
++ /* KDBUS_ITEM_CONN_DESCRIPTION */ |
15887 |
++ char *conn_description; |
15888 |
++}; |
15889 |
++ |
15890 |
++/** |
15891 |
++ * kdbus_meta_proc_new() - Create process metadata object |
15892 |
++ * |
15893 |
++ * Return: Pointer to new object on success, ERR_PTR on failure. |
15894 |
++ */ |
15895 |
++struct kdbus_meta_proc *kdbus_meta_proc_new(void) |
15896 |
++{ |
15897 |
++ struct kdbus_meta_proc *mp; |
15898 |
++ |
15899 |
++ mp = kzalloc(sizeof(*mp), GFP_KERNEL); |
15900 |
++ if (!mp) |
15901 |
++ return ERR_PTR(-ENOMEM); |
15902 |
++ |
15903 |
++ kref_init(&mp->kref); |
15904 |
++ mutex_init(&mp->lock); |
15905 |
++ |
15906 |
++ return mp; |
15907 |
++} |
15908 |
++ |
15909 |
++static void kdbus_meta_proc_free(struct kref *kref) |
15910 |
++{ |
15911 |
++ struct kdbus_meta_proc *mp = container_of(kref, struct kdbus_meta_proc, |
15912 |
++ kref); |
15913 |
++ |
15914 |
++ path_put(&mp->exe_path); |
15915 |
++ path_put(&mp->root_path); |
15916 |
++ put_user_ns(mp->caps_namespace); |
15917 |
++ put_pid(mp->ppid); |
15918 |
++ put_pid(mp->tgid); |
15919 |
++ put_pid(mp->pid); |
15920 |
++ |
15921 |
++ kfree(mp->seclabel); |
15922 |
++ kfree(mp->auxgrps); |
15923 |
++ kfree(mp->cmdline); |
15924 |
++ kfree(mp->cgroup); |
15925 |
++ kfree(mp); |
15926 |
++} |
15927 |
++ |
15928 |
++/** |
15929 |
++ * kdbus_meta_proc_ref() - Gain reference |
15930 |
++ * @mp: Process metadata object |
15931 |
++ * |
15932 |
++ * Return: @mp is returned |
15933 |
++ */ |
15934 |
++struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp) |
15935 |
++{ |
15936 |
++ if (mp) |
15937 |
++ kref_get(&mp->kref); |
15938 |
++ return mp; |
15939 |
++} |
15940 |
++ |
15941 |
++/** |
15942 |
++ * kdbus_meta_proc_unref() - Drop reference |
15943 |
++ * @mp: Process metadata object |
15944 |
++ * |
15945 |
++ * Return: NULL |
15946 |
++ */ |
15947 |
++struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp) |
15948 |
++{ |
15949 |
++ if (mp) |
15950 |
++ kref_put(&mp->kref, kdbus_meta_proc_free); |
15951 |
++ return NULL; |
15952 |
++} |
15953 |
++ |
15954 |
++static void kdbus_meta_proc_collect_creds(struct kdbus_meta_proc *mp) |
15955 |
++{ |
15956 |
++ mp->uid = current_uid(); |
15957 |
++ mp->euid = current_euid(); |
15958 |
++ mp->suid = current_suid(); |
15959 |
++ mp->fsuid = current_fsuid(); |
15960 |
++ |
15961 |
++ mp->gid = current_gid(); |
15962 |
++ mp->egid = current_egid(); |
15963 |
++ mp->sgid = current_sgid(); |
15964 |
++ mp->fsgid = current_fsgid(); |
15965 |
++ |
15966 |
++ mp->valid |= KDBUS_ATTACH_CREDS; |
15967 |
++} |
15968 |
++ |
15969 |
++static void kdbus_meta_proc_collect_pids(struct kdbus_meta_proc *mp) |
15970 |
++{ |
15971 |
++ struct task_struct *parent; |
15972 |
++ |
15973 |
++ mp->pid = get_pid(task_pid(current)); |
15974 |
++ mp->tgid = get_pid(task_tgid(current)); |
15975 |
++ |
15976 |
++ rcu_read_lock(); |
15977 |
++ parent = rcu_dereference(current->real_parent); |
15978 |
++ mp->ppid = get_pid(task_tgid(parent)); |
15979 |
++ rcu_read_unlock(); |
15980 |
++ |
15981 |
++ mp->valid |= KDBUS_ATTACH_PIDS; |
15982 |
++} |
15983 |
++ |
15984 |
++static int kdbus_meta_proc_collect_auxgroups(struct kdbus_meta_proc *mp) |
15985 |
++{ |
15986 |
++ struct group_info *info; |
15987 |
++ size_t i; |
15988 |
++ |
15989 |
++ info = get_current_groups(); |
15990 |
++ |
15991 |
++ if (info->ngroups > 0) { |
15992 |
++ mp->auxgrps = kmalloc_array(info->ngroups, sizeof(kgid_t), |
15993 |
++ GFP_KERNEL); |
15994 |
++ if (!mp->auxgrps) { |
15995 |
++ put_group_info(info); |
15996 |
++ return -ENOMEM; |
15997 |
++ } |
15998 |
++ |
15999 |
++ for (i = 0; i < info->ngroups; i++) |
16000 |
++ mp->auxgrps[i] = GROUP_AT(info, i); |
16001 |
++ } |
16002 |
++ |
16003 |
++ mp->n_auxgrps = info->ngroups; |
16004 |
++ put_group_info(info); |
16005 |
++ mp->valid |= KDBUS_ATTACH_AUXGROUPS; |
16006 |
++ |
16007 |
++ return 0; |
16008 |
++} |
16009 |
++ |
16010 |
++static void kdbus_meta_proc_collect_tid_comm(struct kdbus_meta_proc *mp) |
16011 |
++{ |
16012 |
++ get_task_comm(mp->tid_comm, current); |
16013 |
++ mp->valid |= KDBUS_ATTACH_TID_COMM; |
16014 |
++} |
16015 |
++ |
16016 |
++static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp) |
16017 |
++{ |
16018 |
++ get_task_comm(mp->pid_comm, current->group_leader); |
16019 |
++ mp->valid |= KDBUS_ATTACH_PID_COMM; |
16020 |
++} |
16021 |
++ |
16022 |
++static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp) |
16023 |
++{ |
16024 |
++ struct mm_struct *mm; |
16025 |
++ |
16026 |
++ mm = get_task_mm(current); |
16027 |
++ if (!mm) |
16028 |
++ return; |
16029 |
++ |
16030 |
++ down_read(&mm->mmap_sem); |
16031 |
++ if (mm->exe_file) { |
16032 |
++ mp->exe_path = mm->exe_file->f_path; |
16033 |
++ path_get(&mp->exe_path); |
16034 |
++ get_fs_root(current->fs, &mp->root_path); |
16035 |
++ mp->valid |= KDBUS_ATTACH_EXE; |
16036 |
++ } |
16037 |
++ up_read(&mm->mmap_sem); |
16038 |
++ |
16039 |
++ mmput(mm); |
16040 |
++} |
16041 |
++ |
16042 |
++static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp) |
16043 |
++{ |
16044 |
++ struct mm_struct *mm; |
16045 |
++ char *cmdline; |
16046 |
++ |
16047 |
++ mm = get_task_mm(current); |
16048 |
++ if (!mm) |
16049 |
++ return 0; |
16050 |
++ |
16051 |
++ if (!mm->arg_end) { |
16052 |
++ mmput(mm); |
16053 |
++ return 0; |
16054 |
++ } |
16055 |
++ |
16056 |
++ cmdline = strndup_user((const char __user *)mm->arg_start, |
16057 |
++ mm->arg_end - mm->arg_start); |
16058 |
++ mmput(mm); |
16059 |
++ |
16060 |
++ if (IS_ERR(cmdline)) |
16061 |
++ return PTR_ERR(cmdline); |
16062 |
++ |
16063 |
++ mp->cmdline = cmdline; |
16064 |
++ mp->valid |= KDBUS_ATTACH_CMDLINE; |
16065 |
++ |
16066 |
++ return 0; |
16067 |
++} |
16068 |
++ |
16069 |
++static int kdbus_meta_proc_collect_cgroup(struct kdbus_meta_proc *mp) |
16070 |
++{ |
16071 |
++#ifdef CONFIG_CGROUPS |
16072 |
++ void *page; |
16073 |
++ char *s; |
16074 |
++ |
16075 |
++ page = (void *)__get_free_page(GFP_TEMPORARY); |
16076 |
++ if (!page) |
16077 |
++ return -ENOMEM; |
16078 |
++ |
16079 |
++ s = task_cgroup_path(current, page, PAGE_SIZE); |
16080 |
++ if (s) { |
16081 |
++ mp->cgroup = kstrdup(s, GFP_KERNEL); |
16082 |
++ if (!mp->cgroup) { |
16083 |
++ free_page((unsigned long)page); |
16084 |
++ return -ENOMEM; |
16085 |
++ } |
16086 |
++ } |
16087 |
++ |
16088 |
++ free_page((unsigned long)page); |
16089 |
++ mp->valid |= KDBUS_ATTACH_CGROUP; |
16090 |
++#endif |
16091 |
++ |
16092 |
++ return 0; |
16093 |
++} |
16094 |
++ |
16095 |
++static void kdbus_meta_proc_collect_caps(struct kdbus_meta_proc *mp) |
16096 |
++{ |
16097 |
++ const struct cred *c = current_cred(); |
16098 |
++ int i; |
16099 |
++ |
16100 |
++ /* ABI: "last_cap" equals /proc/sys/kernel/cap_last_cap */ |
16101 |
++ mp->caps.last_cap = CAP_LAST_CAP; |
16102 |
++ mp->caps_namespace = get_user_ns(current_user_ns()); |
16103 |
++ |
16104 |
++ CAP_FOR_EACH_U32(i) { |
16105 |
++ mp->caps.set[0].caps[i] = c->cap_inheritable.cap[i]; |
16106 |
++ mp->caps.set[1].caps[i] = c->cap_permitted.cap[i]; |
16107 |
++ mp->caps.set[2].caps[i] = c->cap_effective.cap[i]; |
16108 |
++ mp->caps.set[3].caps[i] = c->cap_bset.cap[i]; |
16109 |
++ } |
16110 |
++ |
16111 |
++ /* clear unused bits */ |
16112 |
++ for (i = 0; i < 4; i++) |
16113 |
++ mp->caps.set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &= |
16114 |
++ CAP_LAST_U32_VALID_MASK; |
16115 |
++ |
16116 |
++ mp->valid |= KDBUS_ATTACH_CAPS; |
16117 |
++} |
16118 |
++ |
16119 |
++static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp) |
16120 |
++{ |
16121 |
++#ifdef CONFIG_SECURITY |
16122 |
++ char *ctx = NULL; |
16123 |
++ u32 sid, len; |
16124 |
++ int ret; |
16125 |
++ |
16126 |
++ security_task_getsecid(current, &sid); |
16127 |
++ ret = security_secid_to_secctx(sid, &ctx, &len); |
16128 |
++ if (ret < 0) { |
16129 |
++ /* |
16130 |
++ * EOPNOTSUPP means no security module is active, |
16131 |
++ * lets skip adding the seclabel then. This effectively |
16132 |
++ * drops the SECLABEL item. |
16133 |
++ */ |
16134 |
++ return (ret == -EOPNOTSUPP) ? 0 : ret; |
16135 |
++ } |
16136 |
++ |
16137 |
++ mp->seclabel = kstrdup(ctx, GFP_KERNEL); |
16138 |
++ security_release_secctx(ctx, len); |
16139 |
++ if (!mp->seclabel) |
16140 |
++ return -ENOMEM; |
16141 |
++ |
16142 |
++ mp->valid |= KDBUS_ATTACH_SECLABEL; |
16143 |
++#endif |
16144 |
++ |
16145 |
++ return 0; |
16146 |
++} |
16147 |
++ |
16148 |
++static void kdbus_meta_proc_collect_audit(struct kdbus_meta_proc *mp) |
16149 |
++{ |
16150 |
++#ifdef CONFIG_AUDITSYSCALL |
16151 |
++ mp->audit_loginuid = audit_get_loginuid(current); |
16152 |
++ mp->audit_sessionid = audit_get_sessionid(current); |
16153 |
++ mp->valid |= KDBUS_ATTACH_AUDIT; |
16154 |
++#endif |
16155 |
++} |
16156 |
++ |
16157 |
++/** |
16158 |
++ * kdbus_meta_proc_collect() - Collect process metadata |
16159 |
++ * @mp: Process metadata object |
16160 |
++ * @what: Attach flags to collect |
16161 |
++ * |
16162 |
++ * This collects process metadata from current and saves it in @mp. |
16163 |
++ * |
16164 |
++ * Return: 0 on success, negative error code on failure. |
16165 |
++ */ |
16166 |
++int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what) |
16167 |
++{ |
16168 |
++ int ret; |
16169 |
++ |
16170 |
++ if (!mp || !(what & (KDBUS_ATTACH_CREDS | |
16171 |
++ KDBUS_ATTACH_PIDS | |
16172 |
++ KDBUS_ATTACH_AUXGROUPS | |
16173 |
++ KDBUS_ATTACH_TID_COMM | |
16174 |
++ KDBUS_ATTACH_PID_COMM | |
16175 |
++ KDBUS_ATTACH_EXE | |
16176 |
++ KDBUS_ATTACH_CMDLINE | |
16177 |
++ KDBUS_ATTACH_CGROUP | |
16178 |
++ KDBUS_ATTACH_CAPS | |
16179 |
++ KDBUS_ATTACH_SECLABEL | |
16180 |
++ KDBUS_ATTACH_AUDIT))) |
16181 |
++ return 0; |
16182 |
++ |
16183 |
++ mutex_lock(&mp->lock); |
16184 |
++ |
16185 |
++ if ((what & KDBUS_ATTACH_CREDS) && |
16186 |
++ !(mp->collected & KDBUS_ATTACH_CREDS)) { |
16187 |
++ kdbus_meta_proc_collect_creds(mp); |
16188 |
++ mp->collected |= KDBUS_ATTACH_CREDS; |
16189 |
++ } |
16190 |
++ |
16191 |
++ if ((what & KDBUS_ATTACH_PIDS) && |
16192 |
++ !(mp->collected & KDBUS_ATTACH_PIDS)) { |
16193 |
++ kdbus_meta_proc_collect_pids(mp); |
16194 |
++ mp->collected |= KDBUS_ATTACH_PIDS; |
16195 |
++ } |
16196 |
++ |
16197 |
++ if ((what & KDBUS_ATTACH_AUXGROUPS) && |
16198 |
++ !(mp->collected & KDBUS_ATTACH_AUXGROUPS)) { |
16199 |
++ ret = kdbus_meta_proc_collect_auxgroups(mp); |
16200 |
++ if (ret < 0) |
16201 |
++ goto exit_unlock; |
16202 |
++ mp->collected |= KDBUS_ATTACH_AUXGROUPS; |
16203 |
++ } |
16204 |
++ |
16205 |
++ if ((what & KDBUS_ATTACH_TID_COMM) && |
16206 |
++ !(mp->collected & KDBUS_ATTACH_TID_COMM)) { |
16207 |
++ kdbus_meta_proc_collect_tid_comm(mp); |
16208 |
++ mp->collected |= KDBUS_ATTACH_TID_COMM; |
16209 |
++ } |
16210 |
++ |
16211 |
++ if ((what & KDBUS_ATTACH_PID_COMM) && |
16212 |
++ !(mp->collected & KDBUS_ATTACH_PID_COMM)) { |
16213 |
++ kdbus_meta_proc_collect_pid_comm(mp); |
16214 |
++ mp->collected |= KDBUS_ATTACH_PID_COMM; |
16215 |
++ } |
16216 |
++ |
16217 |
++ if ((what & KDBUS_ATTACH_EXE) && |
16218 |
++ !(mp->collected & KDBUS_ATTACH_EXE)) { |
16219 |
++ kdbus_meta_proc_collect_exe(mp); |
16220 |
++ mp->collected |= KDBUS_ATTACH_EXE; |
16221 |
++ } |
16222 |
++ |
16223 |
++ if ((what & KDBUS_ATTACH_CMDLINE) && |
16224 |
++ !(mp->collected & KDBUS_ATTACH_CMDLINE)) { |
16225 |
++ ret = kdbus_meta_proc_collect_cmdline(mp); |
16226 |
++ if (ret < 0) |
16227 |
++ goto exit_unlock; |
16228 |
++ mp->collected |= KDBUS_ATTACH_CMDLINE; |
16229 |
++ } |
16230 |
++ |
16231 |
++ if ((what & KDBUS_ATTACH_CGROUP) && |
16232 |
++ !(mp->collected & KDBUS_ATTACH_CGROUP)) { |
16233 |
++ ret = kdbus_meta_proc_collect_cgroup(mp); |
16234 |
++ if (ret < 0) |
16235 |
++ goto exit_unlock; |
16236 |
++ mp->collected |= KDBUS_ATTACH_CGROUP; |
16237 |
++ } |
16238 |
++ |
16239 |
++ if ((what & KDBUS_ATTACH_CAPS) && |
16240 |
++ !(mp->collected & KDBUS_ATTACH_CAPS)) { |
16241 |
++ kdbus_meta_proc_collect_caps(mp); |
16242 |
++ mp->collected |= KDBUS_ATTACH_CAPS; |
16243 |
++ } |
16244 |
++ |
16245 |
++ if ((what & KDBUS_ATTACH_SECLABEL) && |
16246 |
++ !(mp->collected & KDBUS_ATTACH_SECLABEL)) { |
16247 |
++ ret = kdbus_meta_proc_collect_seclabel(mp); |
16248 |
++ if (ret < 0) |
16249 |
++ goto exit_unlock; |
16250 |
++ mp->collected |= KDBUS_ATTACH_SECLABEL; |
16251 |
++ } |
16252 |
++ |
16253 |
++ if ((what & KDBUS_ATTACH_AUDIT) && |
16254 |
++ !(mp->collected & KDBUS_ATTACH_AUDIT)) { |
16255 |
++ kdbus_meta_proc_collect_audit(mp); |
16256 |
++ mp->collected |= KDBUS_ATTACH_AUDIT; |
16257 |
++ } |
16258 |
++ |
16259 |
++ ret = 0; |
16260 |
++ |
16261 |
++exit_unlock: |
16262 |
++ mutex_unlock(&mp->lock); |
16263 |
++ return ret; |
16264 |
++} |
16265 |
++ |
16266 |
++/** |
16267 |
++ * kdbus_meta_proc_fake() - Fill process metadata from faked credentials |
16268 |
++ * @mp: Metadata |
16269 |
++ * @creds: Creds to set, may be %NULL |
16270 |
++ * @pids: PIDs to set, may be %NULL |
16271 |
++ * @seclabel: Seclabel to set, may be %NULL |
16272 |
++ * |
16273 |
++ * This function takes information stored in @creds, @pids and @seclabel and |
16274 |
++ * resolves them to kernel-representations, if possible. A call to this function |
16275 |
++ * is considered an alternative to calling kdbus_meta_add_current(), which |
16276 |
++ * derives the same information from the 'current' task. |
16277 |
++ * |
16278 |
++ * This call uses the current task's namespaces to resolve the given |
16279 |
++ * information. |
16280 |
++ * |
16281 |
++ * Return: 0 on success, negative error number otherwise. |
16282 |
++ */ |
16283 |
++int kdbus_meta_proc_fake(struct kdbus_meta_proc *mp, |
16284 |
++ const struct kdbus_creds *creds, |
16285 |
++ const struct kdbus_pids *pids, |
16286 |
++ const char *seclabel) |
16287 |
++{ |
16288 |
++ int ret; |
16289 |
++ |
16290 |
++ if (!mp) |
16291 |
++ return 0; |
16292 |
++ |
16293 |
++ mutex_lock(&mp->lock); |
16294 |
++ |
16295 |
++ if (creds && !(mp->collected & KDBUS_ATTACH_CREDS)) { |
16296 |
++ struct user_namespace *ns = current_user_ns(); |
16297 |
++ |
16298 |
++ mp->uid = make_kuid(ns, creds->uid); |
16299 |
++ mp->euid = make_kuid(ns, creds->euid); |
16300 |
++ mp->suid = make_kuid(ns, creds->suid); |
16301 |
++ mp->fsuid = make_kuid(ns, creds->fsuid); |
16302 |
++ |
16303 |
++ mp->gid = make_kgid(ns, creds->gid); |
16304 |
++ mp->egid = make_kgid(ns, creds->egid); |
16305 |
++ mp->sgid = make_kgid(ns, creds->sgid); |
16306 |
++ mp->fsgid = make_kgid(ns, creds->fsgid); |
16307 |
++ |
16308 |
++ if ((creds->uid != (uid_t)-1 && !uid_valid(mp->uid)) || |
16309 |
++ (creds->euid != (uid_t)-1 && !uid_valid(mp->euid)) || |
16310 |
++ (creds->suid != (uid_t)-1 && !uid_valid(mp->suid)) || |
16311 |
++ (creds->fsuid != (uid_t)-1 && !uid_valid(mp->fsuid)) || |
16312 |
++ (creds->gid != (gid_t)-1 && !gid_valid(mp->gid)) || |
16313 |
++ (creds->egid != (gid_t)-1 && !gid_valid(mp->egid)) || |
16314 |
++ (creds->sgid != (gid_t)-1 && !gid_valid(mp->sgid)) || |
16315 |
++ (creds->fsgid != (gid_t)-1 && !gid_valid(mp->fsgid))) { |
16316 |
++ ret = -EINVAL; |
16317 |
++ goto exit_unlock; |
16318 |
++ } |
16319 |
++ |
16320 |
++ mp->valid |= KDBUS_ATTACH_CREDS; |
16321 |
++ mp->collected |= KDBUS_ATTACH_CREDS; |
16322 |
++ } |
16323 |
++ |
16324 |
++ if (pids && !(mp->collected & KDBUS_ATTACH_PIDS)) { |
16325 |
++ mp->pid = get_pid(find_vpid(pids->tid)); |
16326 |
++ mp->tgid = get_pid(find_vpid(pids->pid)); |
16327 |
++ mp->ppid = get_pid(find_vpid(pids->ppid)); |
16328 |
++ |
16329 |
++ if ((pids->tid != 0 && !mp->pid) || |
16330 |
++ (pids->pid != 0 && !mp->tgid) || |
16331 |
++ (pids->ppid != 0 && !mp->ppid)) { |
16332 |
++ put_pid(mp->pid); |
16333 |
++ put_pid(mp->tgid); |
16334 |
++ put_pid(mp->ppid); |
16335 |
++ mp->pid = NULL; |
16336 |
++ mp->tgid = NULL; |
16337 |
++ mp->ppid = NULL; |
16338 |
++ ret = -EINVAL; |
16339 |
++ goto exit_unlock; |
16340 |
++ } |
16341 |
++ |
16342 |
++ mp->valid |= KDBUS_ATTACH_PIDS; |
16343 |
++ mp->collected |= KDBUS_ATTACH_PIDS; |
16344 |
++ } |
16345 |
++ |
16346 |
++ if (seclabel && !(mp->collected & KDBUS_ATTACH_SECLABEL)) { |
16347 |
++ mp->seclabel = kstrdup(seclabel, GFP_KERNEL); |
16348 |
++ if (!mp->seclabel) { |
16349 |
++ ret = -ENOMEM; |
16350 |
++ goto exit_unlock; |
16351 |
++ } |
16352 |
++ |
16353 |
++ mp->valid |= KDBUS_ATTACH_SECLABEL; |
16354 |
++ mp->collected |= KDBUS_ATTACH_SECLABEL; |
16355 |
++ } |
16356 |
++ |
16357 |
++ ret = 0; |
16358 |
++ |
16359 |
++exit_unlock: |
16360 |
++ mutex_unlock(&mp->lock); |
16361 |
++ return ret; |
16362 |
++} |
16363 |
++ |
16364 |
++/** |
16365 |
++ * kdbus_meta_conn_new() - Create connection metadata object |
16366 |
++ * |
16367 |
++ * Return: Pointer to new object on success, ERR_PTR on failure. |
16368 |
++ */ |
16369 |
++struct kdbus_meta_conn *kdbus_meta_conn_new(void) |
16370 |
++{ |
16371 |
++ struct kdbus_meta_conn *mc; |
16372 |
++ |
16373 |
++ mc = kzalloc(sizeof(*mc), GFP_KERNEL); |
16374 |
++ if (!mc) |
16375 |
++ return ERR_PTR(-ENOMEM); |
16376 |
++ |
16377 |
++ kref_init(&mc->kref); |
16378 |
++ mutex_init(&mc->lock); |
16379 |
++ |
16380 |
++ return mc; |
16381 |
++} |
16382 |
++ |
16383 |
++static void kdbus_meta_conn_free(struct kref *kref) |
16384 |
++{ |
16385 |
++ struct kdbus_meta_conn *mc = |
16386 |
++ container_of(kref, struct kdbus_meta_conn, kref); |
16387 |
++ |
16388 |
++ kfree(mc->conn_description); |
16389 |
++ kfree(mc->owned_names_items); |
16390 |
++ kfree(mc); |
16391 |
++} |
16392 |
++ |
16393 |
++/** |
16394 |
++ * kdbus_meta_conn_ref() - Gain reference |
16395 |
++ * @mc: Connection metadata object |
16396 |
++ */ |
16397 |
++struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc) |
16398 |
++{ |
16399 |
++ if (mc) |
16400 |
++ kref_get(&mc->kref); |
16401 |
++ return mc; |
16402 |
++} |
16403 |
++ |
16404 |
++/** |
16405 |
++ * kdbus_meta_conn_unref() - Drop reference |
16406 |
++ * @mc: Connection metadata object |
16407 |
++ */ |
16408 |
++struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc) |
16409 |
++{ |
16410 |
++ if (mc) |
16411 |
++ kref_put(&mc->kref, kdbus_meta_conn_free); |
16412 |
++ return NULL; |
16413 |
++} |
16414 |
++ |
16415 |
++static void kdbus_meta_conn_collect_timestamp(struct kdbus_meta_conn *mc, |
16416 |
++ struct kdbus_kmsg *kmsg) |
16417 |
++{ |
16418 |
++ mc->ts.monotonic_ns = ktime_get_ns(); |
16419 |
++ mc->ts.realtime_ns = ktime_get_real_ns(); |
16420 |
++ |
16421 |
++ if (kmsg) |
16422 |
++ mc->ts.seqnum = kmsg->seq; |
16423 |
++ |
16424 |
++ mc->valid |= KDBUS_ATTACH_TIMESTAMP; |
16425 |
++} |
16426 |
++ |
16427 |
++static int kdbus_meta_conn_collect_names(struct kdbus_meta_conn *mc, |
16428 |
++ struct kdbus_conn *conn) |
16429 |
++{ |
16430 |
++ const struct kdbus_name_entry *e; |
16431 |
++ struct kdbus_item *item; |
16432 |
++ size_t slen, size; |
16433 |
++ |
16434 |
++ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
16435 |
++ |
16436 |
++ size = 0; |
16437 |
++ list_for_each_entry(e, &conn->names_list, conn_entry) |
16438 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_name) + |
16439 |
++ strlen(e->name) + 1); |
16440 |
++ |
16441 |
++ if (!size) |
16442 |
++ return 0; |
16443 |
++ |
16444 |
++ item = kmalloc(size, GFP_KERNEL); |
16445 |
++ if (!item) |
16446 |
++ return -ENOMEM; |
16447 |
++ |
16448 |
++ mc->owned_names_items = item; |
16449 |
++ mc->owned_names_size = size; |
16450 |
++ |
16451 |
++ list_for_each_entry(e, &conn->names_list, conn_entry) { |
16452 |
++ slen = strlen(e->name) + 1; |
16453 |
++ kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL, |
16454 |
++ sizeof(struct kdbus_name) + slen); |
16455 |
++ item->name.flags = e->flags; |
16456 |
++ memcpy(item->name.name, e->name, slen); |
16457 |
++ item = KDBUS_ITEM_NEXT(item); |
16458 |
++ } |
16459 |
++ |
16460 |
++ /* sanity check: the buffer should be completely written now */ |
16461 |
++ WARN_ON((u8 *)item != (u8 *)mc->owned_names_items + size); |
16462 |
++ |
16463 |
++ mc->valid |= KDBUS_ATTACH_NAMES; |
16464 |
++ return 0; |
16465 |
++} |
16466 |
++ |
16467 |
++static int kdbus_meta_conn_collect_description(struct kdbus_meta_conn *mc, |
16468 |
++ struct kdbus_conn *conn) |
16469 |
++{ |
16470 |
++ if (!conn->description) |
16471 |
++ return 0; |
16472 |
++ |
16473 |
++ mc->conn_description = kstrdup(conn->description, GFP_KERNEL); |
16474 |
++ if (!mc->conn_description) |
16475 |
++ return -ENOMEM; |
16476 |
++ |
16477 |
++ mc->valid |= KDBUS_ATTACH_CONN_DESCRIPTION; |
16478 |
++ return 0; |
16479 |
++} |
16480 |
++ |
16481 |
++/** |
16482 |
++ * kdbus_meta_conn_collect() - Collect connection metadata |
16483 |
++ * @mc: Message metadata object |
16484 |
++ * @kmsg: Kmsg to collect data from |
16485 |
++ * @conn: Connection to collect data from |
16486 |
++ * @what: Attach flags to collect |
16487 |
++ * |
16488 |
++ * This collects connection metadata from @kmsg and @conn and saves it in @mc. |
16489 |
++ * |
16490 |
++ * If KDBUS_ATTACH_NAMES is set in @what and @conn is non-NULL, the caller must |
16491 |
++ * hold the name-registry read-lock of conn->ep->bus->registry. |
16492 |
++ * |
16493 |
++ * Return: 0 on success, negative error code on failure. |
16494 |
++ */ |
16495 |
++int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, |
16496 |
++ struct kdbus_kmsg *kmsg, |
16497 |
++ struct kdbus_conn *conn, |
16498 |
++ u64 what) |
16499 |
++{ |
16500 |
++ int ret; |
16501 |
++ |
16502 |
++ if (!mc || !(what & (KDBUS_ATTACH_TIMESTAMP | |
16503 |
++ KDBUS_ATTACH_NAMES | |
16504 |
++ KDBUS_ATTACH_CONN_DESCRIPTION))) |
16505 |
++ return 0; |
16506 |
++ |
16507 |
++ mutex_lock(&mc->lock); |
16508 |
++ |
16509 |
++ if (kmsg && (what & KDBUS_ATTACH_TIMESTAMP) && |
16510 |
++ !(mc->collected & KDBUS_ATTACH_TIMESTAMP)) { |
16511 |
++ kdbus_meta_conn_collect_timestamp(mc, kmsg); |
16512 |
++ mc->collected |= KDBUS_ATTACH_TIMESTAMP; |
16513 |
++ } |
16514 |
++ |
16515 |
++ if (conn && (what & KDBUS_ATTACH_NAMES) && |
16516 |
++ !(mc->collected & KDBUS_ATTACH_NAMES)) { |
16517 |
++ ret = kdbus_meta_conn_collect_names(mc, conn); |
16518 |
++ if (ret < 0) |
16519 |
++ goto exit_unlock; |
16520 |
++ mc->collected |= KDBUS_ATTACH_NAMES; |
16521 |
++ } |
16522 |
++ |
16523 |
++ if (conn && (what & KDBUS_ATTACH_CONN_DESCRIPTION) && |
16524 |
++ !(mc->collected & KDBUS_ATTACH_CONN_DESCRIPTION)) { |
16525 |
++ ret = kdbus_meta_conn_collect_description(mc, conn); |
16526 |
++ if (ret < 0) |
16527 |
++ goto exit_unlock; |
16528 |
++ mc->collected |= KDBUS_ATTACH_CONN_DESCRIPTION; |
16529 |
++ } |
16530 |
++ |
16531 |
++ ret = 0; |
16532 |
++ |
16533 |
++exit_unlock: |
16534 |
++ mutex_unlock(&mc->lock); |
16535 |
++ return ret; |
16536 |
++} |
16537 |
++ |
16538 |
++/* |
16539 |
++ * kdbus_meta_export_prepare() - Prepare metadata for export |
16540 |
++ * @mp: Process metadata, or NULL |
16541 |
++ * @mc: Connection metadata, or NULL |
16542 |
++ * @mask: Pointer to mask of KDBUS_ATTACH_* flags to export |
16543 |
++ * @sz: Pointer to return the size needed by the metadata |
16544 |
++ * |
16545 |
++ * Does a conservative calculation of how much space metadata information |
16546 |
++ * will take up during export. It is 'conservative' because for string |
16547 |
++ * translations in namespaces, it will use the kernel namespaces, which is |
16548 |
++ * the longest possible version. |
16549 |
++ * |
16550 |
++ * The actual size consumed by kdbus_meta_export() may hence vary from the |
16551 |
++ * one reported here, but it is guaranteed never to be greater. |
16552 |
++ * |
16553 |
++ * Return: 0 on success, negative error number otherwise. |
16554 |
++ */ |
16555 |
++int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp, |
16556 |
++ struct kdbus_meta_conn *mc, |
16557 |
++ u64 *mask, size_t *sz) |
16558 |
++{ |
16559 |
++ char *exe_pathname = NULL; |
16560 |
++ void *exe_page = NULL; |
16561 |
++ size_t size = 0; |
16562 |
++ u64 valid = 0; |
16563 |
++ int ret = 0; |
16564 |
++ |
16565 |
++ if (mp) { |
16566 |
++ mutex_lock(&mp->lock); |
16567 |
++ valid |= mp->valid; |
16568 |
++ mutex_unlock(&mp->lock); |
16569 |
++ } |
16570 |
++ |
16571 |
++ if (mc) { |
16572 |
++ mutex_lock(&mc->lock); |
16573 |
++ valid |= mc->valid; |
16574 |
++ mutex_unlock(&mc->lock); |
16575 |
++ } |
16576 |
++ |
16577 |
++ *mask &= valid; |
16578 |
++ *mask &= kdbus_meta_attach_mask; |
16579 |
++ |
16580 |
++ if (!*mask) |
16581 |
++ goto exit; |
16582 |
++ |
16583 |
++ /* process metadata */ |
16584 |
++ |
16585 |
++ if (mp && (*mask & KDBUS_ATTACH_CREDS)) |
16586 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds)); |
16587 |
++ |
16588 |
++ if (mp && (*mask & KDBUS_ATTACH_PIDS)) |
16589 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids)); |
16590 |
++ |
16591 |
++ if (mp && (*mask & KDBUS_ATTACH_AUXGROUPS)) |
16592 |
++ size += KDBUS_ITEM_SIZE(mp->n_auxgrps * sizeof(u64)); |
16593 |
++ |
16594 |
++ if (mp && (*mask & KDBUS_ATTACH_TID_COMM)) |
16595 |
++ size += KDBUS_ITEM_SIZE(strlen(mp->tid_comm) + 1); |
16596 |
++ |
16597 |
++ if (mp && (*mask & KDBUS_ATTACH_PID_COMM)) |
16598 |
++ size += KDBUS_ITEM_SIZE(strlen(mp->pid_comm) + 1); |
16599 |
++ |
16600 |
++ if (mp && (*mask & KDBUS_ATTACH_EXE)) { |
16601 |
++ exe_page = (void *)__get_free_page(GFP_TEMPORARY); |
16602 |
++ if (!exe_page) { |
16603 |
++ ret = -ENOMEM; |
16604 |
++ goto exit; |
16605 |
++ } |
16606 |
++ |
16607 |
++ exe_pathname = d_path(&mp->exe_path, exe_page, PAGE_SIZE); |
16608 |
++ if (IS_ERR(exe_pathname)) { |
16609 |
++ ret = PTR_ERR(exe_pathname); |
16610 |
++ goto exit; |
16611 |
++ } |
16612 |
++ |
16613 |
++ size += KDBUS_ITEM_SIZE(strlen(exe_pathname) + 1); |
16614 |
++ free_page((unsigned long)exe_page); |
16615 |
++ } |
16616 |
++ |
16617 |
++ if (mp && (*mask & KDBUS_ATTACH_CMDLINE)) |
16618 |
++ size += KDBUS_ITEM_SIZE(strlen(mp->cmdline) + 1); |
16619 |
++ |
16620 |
++ if (mp && (*mask & KDBUS_ATTACH_CGROUP)) |
16621 |
++ size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1); |
16622 |
++ |
16623 |
++ if (mp && (*mask & KDBUS_ATTACH_CAPS)) |
16624 |
++ size += KDBUS_ITEM_SIZE(sizeof(mp->caps)); |
16625 |
++ |
16626 |
++ if (mp && (*mask & KDBUS_ATTACH_SECLABEL)) |
16627 |
++ size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1); |
16628 |
++ |
16629 |
++ if (mp && (*mask & KDBUS_ATTACH_AUDIT)) |
16630 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit)); |
16631 |
++ |
16632 |
++ /* connection metadata */ |
16633 |
++ |
16634 |
++ if (mc && (*mask & KDBUS_ATTACH_NAMES)) |
16635 |
++ size += mc->owned_names_size; |
16636 |
++ |
16637 |
++ if (mc && (*mask & KDBUS_ATTACH_CONN_DESCRIPTION)) |
16638 |
++ size += KDBUS_ITEM_SIZE(strlen(mc->conn_description) + 1); |
16639 |
++ |
16640 |
++ if (mc && (*mask & KDBUS_ATTACH_TIMESTAMP)) |
16641 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_timestamp)); |
16642 |
++ |
16643 |
++exit: |
16644 |
++ *sz = size; |
16645 |
++ |
16646 |
++ return ret; |
16647 |
++} |
16648 |
++ |
16649 |
++static int kdbus_meta_push_kvec(struct kvec *kvec, |
16650 |
++ struct kdbus_item_header *hdr, |
16651 |
++ u64 type, void *payload, |
16652 |
++ size_t payload_size, u64 *size) |
16653 |
++{ |
16654 |
++ hdr->type = type; |
16655 |
++ hdr->size = KDBUS_ITEM_HEADER_SIZE + payload_size; |
16656 |
++ kdbus_kvec_set(kvec++, hdr, sizeof(*hdr), size); |
16657 |
++ kdbus_kvec_set(kvec++, payload, payload_size, size); |
16658 |
++ return 2 + !!kdbus_kvec_pad(kvec++, size); |
16659 |
++} |
16660 |
++ |
16661 |
++/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */ |
16662 |
++static uid_t kdbus_from_kuid_keep(kuid_t uid) |
16663 |
++{ |
16664 |
++ return uid_valid(uid) ? |
16665 |
++ from_kuid_munged(current_user_ns(), uid) : ((uid_t)-1); |
16666 |
++} |
16667 |
++ |
16668 |
++/* This is equivalent to from_kgid_munged(), but maps INVALID_GID to itself */ |
16669 |
++static gid_t kdbus_from_kgid_keep(kgid_t gid) |
16670 |
++{ |
16671 |
++ return gid_valid(gid) ? |
16672 |
++ from_kgid_munged(current_user_ns(), gid) : ((gid_t)-1); |
16673 |
++} |
16674 |
++ |
16675 |
++/** |
16676 |
++ * kdbus_meta_export() - export information from metadata into a slice |
16677 |
++ * @mp: Process metadata, or NULL |
16678 |
++ * @mc: Connection metadata, or NULL |
16679 |
++ * @mask: Mask of KDBUS_ATTACH_* flags to export |
16680 |
++ * @slice: The slice to export to |
16681 |
++ * @offset: The offset inside @slice to write to |
16682 |
++ * @real_size: The real size the metadata consumed |
16683 |
++ * |
16684 |
++ * This function exports information from metadata into @slice at offset |
16685 |
++ * @offset inside that slice. Only information that is requested in @mask |
16686 |
++ * and that has been collected before is exported. |
16687 |
++ * |
16688 |
++ * In order to make sure not to write out of bounds, @mask must be the same |
16689 |
++ * value that was previously returned from kdbus_meta_export_prepare(). The |
16690 |
++ * function will, however, not necessarily write as many bytes as returned by |
16691 |
++ * kdbus_meta_export_prepare(); depending on the namespaces in question, it |
16692 |
++ * might use up less than that. |
16693 |
++ * |
16694 |
++ * All information will be translated using the current namespaces. |
16695 |
++ * |
16696 |
++ * Return: 0 on success, negative error number otherwise. |
16697 |
++ */ |
16698 |
++int kdbus_meta_export(struct kdbus_meta_proc *mp, |
16699 |
++ struct kdbus_meta_conn *mc, |
16700 |
++ u64 mask, |
16701 |
++ struct kdbus_pool_slice *slice, |
16702 |
++ off_t offset, |
16703 |
++ size_t *real_size) |
16704 |
++{ |
16705 |
++ struct user_namespace *user_ns = current_user_ns(); |
16706 |
++ struct kdbus_item_header item_hdr[13], *hdr; |
16707 |
++ char *exe_pathname = NULL; |
16708 |
++ struct kdbus_creds creds; |
16709 |
++ struct kdbus_pids pids; |
16710 |
++ void *exe_page = NULL; |
16711 |
++ struct kvec kvec[40]; |
16712 |
++ u64 *auxgrps = NULL; |
16713 |
++ size_t cnt = 0; |
16714 |
++ u64 size = 0; |
16715 |
++ int ret = 0; |
16716 |
++ |
16717 |
++ hdr = &item_hdr[0]; |
16718 |
++ |
16719 |
++ /* |
16720 |
++ * TODO: We currently have no sane way of translating a set of caps |
16721 |
++ * between different user namespaces. Until that changes, we have |
16722 |
++ * to drop such items. |
16723 |
++ */ |
16724 |
++ if (mp && mp->caps_namespace != user_ns) |
16725 |
++ mask &= ~KDBUS_ATTACH_CAPS; |
16726 |
++ |
16727 |
++ if (mask == 0) { |
16728 |
++ *real_size = 0; |
16729 |
++ return 0; |
16730 |
++ } |
16731 |
++ |
16732 |
++ /* process metadata */ |
16733 |
++ |
16734 |
++ if (mp && (mask & KDBUS_ATTACH_CREDS)) { |
16735 |
++ creds.uid = kdbus_from_kuid_keep(mp->uid); |
16736 |
++ creds.euid = kdbus_from_kuid_keep(mp->euid); |
16737 |
++ creds.suid = kdbus_from_kuid_keep(mp->suid); |
16738 |
++ creds.fsuid = kdbus_from_kuid_keep(mp->fsuid); |
16739 |
++ creds.gid = kdbus_from_kgid_keep(mp->gid); |
16740 |
++ creds.egid = kdbus_from_kgid_keep(mp->egid); |
16741 |
++ creds.sgid = kdbus_from_kgid_keep(mp->sgid); |
16742 |
++ creds.fsgid = kdbus_from_kgid_keep(mp->fsgid); |
16743 |
++ |
16744 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, KDBUS_ITEM_CREDS, |
16745 |
++ &creds, sizeof(creds), &size); |
16746 |
++ } |
16747 |
++ |
16748 |
++ if (mp && (mask & KDBUS_ATTACH_PIDS)) { |
16749 |
++ pids.pid = pid_vnr(mp->tgid); |
16750 |
++ pids.tid = pid_vnr(mp->pid); |
16751 |
++ pids.ppid = pid_vnr(mp->ppid); |
16752 |
++ |
16753 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, KDBUS_ITEM_PIDS, |
16754 |
++ &pids, sizeof(pids), &size); |
16755 |
++ } |
16756 |
++ |
16757 |
++ if (mp && (mask & KDBUS_ATTACH_AUXGROUPS)) { |
16758 |
++ size_t payload_size = mp->n_auxgrps * sizeof(u64); |
16759 |
++ int i; |
16760 |
++ |
16761 |
++ auxgrps = kmalloc(payload_size, GFP_KERNEL); |
16762 |
++ if (!auxgrps) { |
16763 |
++ ret = -ENOMEM; |
16764 |
++ goto exit; |
16765 |
++ } |
16766 |
++ |
16767 |
++ for (i = 0; i < mp->n_auxgrps; i++) |
16768 |
++ auxgrps[i] = from_kgid_munged(user_ns, mp->auxgrps[i]); |
16769 |
++ |
16770 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16771 |
++ KDBUS_ITEM_AUXGROUPS, |
16772 |
++ auxgrps, payload_size, &size); |
16773 |
++ } |
16774 |
++ |
16775 |
++ if (mp && (mask & KDBUS_ATTACH_TID_COMM)) |
16776 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16777 |
++ KDBUS_ITEM_TID_COMM, mp->tid_comm, |
16778 |
++ strlen(mp->tid_comm) + 1, &size); |
16779 |
++ |
16780 |
++ if (mp && (mask & KDBUS_ATTACH_PID_COMM)) |
16781 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16782 |
++ KDBUS_ITEM_PID_COMM, mp->pid_comm, |
16783 |
++ strlen(mp->pid_comm) + 1, &size); |
16784 |
++ |
16785 |
++ if (mp && (mask & KDBUS_ATTACH_EXE)) { |
16786 |
++ struct path p; |
16787 |
++ |
16788 |
++ /* |
16789 |
++ * TODO: We need access to __d_path() so we can write the path |
16790 |
++ * relative to conn->root_path. Once upstream, we need |
16791 |
++ * EXPORT_SYMBOL(__d_path) or an equivalent of d_path() that |
16792 |
++ * takes the root path directly. Until then, we drop this item |
16793 |
++ * if the root-paths differ. |
16794 |
++ */ |
16795 |
++ |
16796 |
++ get_fs_root(current->fs, &p); |
16797 |
++ if (path_equal(&p, &mp->root_path)) { |
16798 |
++ exe_page = (void *)__get_free_page(GFP_TEMPORARY); |
16799 |
++ if (!exe_page) { |
16800 |
++ path_put(&p); |
16801 |
++ ret = -ENOMEM; |
16802 |
++ goto exit; |
16803 |
++ } |
16804 |
++ |
16805 |
++ exe_pathname = d_path(&mp->exe_path, exe_page, |
16806 |
++ PAGE_SIZE); |
16807 |
++ if (IS_ERR(exe_pathname)) { |
16808 |
++ path_put(&p); |
16809 |
++ ret = PTR_ERR(exe_pathname); |
16810 |
++ goto exit; |
16811 |
++ } |
16812 |
++ |
16813 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16814 |
++ KDBUS_ITEM_EXE, |
16815 |
++ exe_pathname, |
16816 |
++ strlen(exe_pathname) + 1, |
16817 |
++ &size); |
16818 |
++ } |
16819 |
++ path_put(&p); |
16820 |
++ } |
16821 |
++ |
16822 |
++ if (mp && (mask & KDBUS_ATTACH_CMDLINE)) |
16823 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16824 |
++ KDBUS_ITEM_CMDLINE, mp->cmdline, |
16825 |
++ strlen(mp->cmdline) + 1, &size); |
16826 |
++ |
16827 |
++ if (mp && (mask & KDBUS_ATTACH_CGROUP)) |
16828 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16829 |
++ KDBUS_ITEM_CGROUP, mp->cgroup, |
16830 |
++ strlen(mp->cgroup) + 1, &size); |
16831 |
++ |
16832 |
++ if (mp && (mask & KDBUS_ATTACH_CAPS)) |
16833 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16834 |
++ KDBUS_ITEM_CAPS, &mp->caps, |
16835 |
++ sizeof(mp->caps), &size); |
16836 |
++ |
16837 |
++ if (mp && (mask & KDBUS_ATTACH_SECLABEL)) |
16838 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16839 |
++ KDBUS_ITEM_SECLABEL, mp->seclabel, |
16840 |
++ strlen(mp->seclabel) + 1, &size); |
16841 |
++ |
16842 |
++ if (mp && (mask & KDBUS_ATTACH_AUDIT)) { |
16843 |
++ struct kdbus_audit a = { |
16844 |
++ .loginuid = from_kuid(user_ns, mp->audit_loginuid), |
16845 |
++ .sessionid = mp->audit_sessionid, |
16846 |
++ }; |
16847 |
++ |
16848 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, KDBUS_ITEM_AUDIT, |
16849 |
++ &a, sizeof(a), &size); |
16850 |
++ } |
16851 |
++ |
16852 |
++ /* connection metadata */ |
16853 |
++ |
16854 |
++ if (mc && (mask & KDBUS_ATTACH_NAMES)) |
16855 |
++ kdbus_kvec_set(&kvec[cnt++], mc->owned_names_items, |
16856 |
++ mc->owned_names_size, &size); |
16857 |
++ |
16858 |
++ if (mc && (mask & KDBUS_ATTACH_CONN_DESCRIPTION)) |
16859 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16860 |
++ KDBUS_ITEM_CONN_DESCRIPTION, |
16861 |
++ mc->conn_description, |
16862 |
++ strlen(mc->conn_description) + 1, |
16863 |
++ &size); |
16864 |
++ |
16865 |
++ if (mc && (mask & KDBUS_ATTACH_TIMESTAMP)) |
16866 |
++ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, |
16867 |
++ KDBUS_ITEM_TIMESTAMP, &mc->ts, |
16868 |
++ sizeof(mc->ts), &size); |
16869 |
++ |
16870 |
++ ret = kdbus_pool_slice_copy_kvec(slice, offset, kvec, cnt, size); |
16871 |
++ *real_size = size; |
16872 |
++ |
16873 |
++exit: |
16874 |
++ kfree(auxgrps); |
16875 |
++ |
16876 |
++ if (exe_page) |
16877 |
++ free_page((unsigned long)exe_page); |
16878 |
++ |
16879 |
++ return ret; |
16880 |
++} |
16881 |
++ |
16882 |
++/** |
16883 |
++ * kdbus_meta_calc_attach_flags() - calculate attach flags for a sender |
16884 |
++ * and a receiver |
16885 |
++ * @sender: Sending connection |
16886 |
++ * @receiver: Receiving connection |
16887 |
++ * |
16888 |
++ * Return: the attach flags both the sender and the receiver have opted-in |
16889 |
++ * for. |
16890 |
++ */ |
16891 |
++u64 kdbus_meta_calc_attach_flags(const struct kdbus_conn *sender, |
16892 |
++ const struct kdbus_conn *receiver) |
16893 |
++{ |
16894 |
++ return atomic64_read(&sender->attach_flags_send) & |
16895 |
++ atomic64_read(&receiver->attach_flags_recv); |
16896 |
++} |
16897 |
+diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h |
16898 |
+new file mode 100644 |
16899 |
+index 0000000..42c942b |
16900 |
+--- /dev/null |
16901 |
++++ b/ipc/kdbus/metadata.h |
16902 |
+@@ -0,0 +1,57 @@ |
16903 |
++/* |
16904 |
++ * Copyright (C) 2013-2015 Kay Sievers |
16905 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
16906 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
16907 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
16908 |
++ * Copyright (C) 2013-2015 Linux Foundation |
16909 |
++ * Copyright (C) 2014-2015 Djalal Harouni |
16910 |
++ * |
16911 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
16912 |
++ * the terms of the GNU Lesser General Public License as published by the |
16913 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
16914 |
++ * your option) any later version. |
16915 |
++ */ |
16916 |
++ |
16917 |
++#ifndef __KDBUS_METADATA_H |
16918 |
++#define __KDBUS_METADATA_H |
16919 |
++ |
16920 |
++#include <linux/kernel.h> |
16921 |
++ |
16922 |
++struct kdbus_conn; |
16923 |
++struct kdbus_kmsg; |
16924 |
++struct kdbus_pool_slice; |
16925 |
++ |
16926 |
++struct kdbus_meta_proc; |
16927 |
++struct kdbus_meta_conn; |
16928 |
++ |
16929 |
++extern unsigned long long kdbus_meta_attach_mask; |
16930 |
++ |
16931 |
++struct kdbus_meta_proc *kdbus_meta_proc_new(void); |
16932 |
++struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp); |
16933 |
++struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp); |
16934 |
++int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what); |
16935 |
++int kdbus_meta_proc_fake(struct kdbus_meta_proc *mp, |
16936 |
++ const struct kdbus_creds *creds, |
16937 |
++ const struct kdbus_pids *pids, |
16938 |
++ const char *seclabel); |
16939 |
++ |
16940 |
++struct kdbus_meta_conn *kdbus_meta_conn_new(void); |
16941 |
++struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc); |
16942 |
++struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc); |
16943 |
++int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, |
16944 |
++ struct kdbus_kmsg *kmsg, |
16945 |
++ struct kdbus_conn *conn, |
16946 |
++ u64 what); |
16947 |
++ |
16948 |
++int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp, |
16949 |
++ struct kdbus_meta_conn *mc, |
16950 |
++ u64 *mask, size_t *sz); |
16951 |
++int kdbus_meta_export(struct kdbus_meta_proc *mp, |
16952 |
++ struct kdbus_meta_conn *mc, |
16953 |
++ u64 mask, |
16954 |
++ struct kdbus_pool_slice *slice, |
16955 |
++ off_t offset, size_t *real_size); |
16956 |
++u64 kdbus_meta_calc_attach_flags(const struct kdbus_conn *sender, |
16957 |
++ const struct kdbus_conn *receiver); |
16958 |
++ |
16959 |
++#endif |
16960 |
+diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c |
16961 |
+new file mode 100644 |
16962 |
+index 0000000..657008e |
16963 |
+--- /dev/null |
16964 |
++++ b/ipc/kdbus/names.c |
16965 |
+@@ -0,0 +1,772 @@ |
16966 |
++/* |
16967 |
++ * Copyright (C) 2013-2015 Kay Sievers |
16968 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
16969 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
16970 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
16971 |
++ * Copyright (C) 2013-2015 Linux Foundation |
16972 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
16973 |
++ * |
16974 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
16975 |
++ * the terms of the GNU Lesser General Public License as published by the |
16976 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
16977 |
++ * your option) any later version. |
16978 |
++ */ |
16979 |
++ |
16980 |
++#include <linux/ctype.h> |
16981 |
++#include <linux/fs.h> |
16982 |
++#include <linux/hash.h> |
16983 |
++#include <linux/idr.h> |
16984 |
++#include <linux/init.h> |
16985 |
++#include <linux/module.h> |
16986 |
++#include <linux/mutex.h> |
16987 |
++#include <linux/rwsem.h> |
16988 |
++#include <linux/sched.h> |
16989 |
++#include <linux/slab.h> |
16990 |
++#include <linux/uaccess.h> |
16991 |
++#include <linux/uio.h> |
16992 |
++ |
16993 |
++#include "bus.h" |
16994 |
++#include "connection.h" |
16995 |
++#include "endpoint.h" |
16996 |
++#include "handle.h" |
16997 |
++#include "item.h" |
16998 |
++#include "names.h" |
16999 |
++#include "notify.h" |
17000 |
++#include "policy.h" |
17001 |
++ |
17002 |
++struct kdbus_name_pending { |
17003 |
++ u64 flags; |
17004 |
++ struct kdbus_conn *conn; |
17005 |
++ struct kdbus_name_entry *name; |
17006 |
++ struct list_head conn_entry; |
17007 |
++ struct list_head name_entry; |
17008 |
++}; |
17009 |
++ |
17010 |
++static int kdbus_name_pending_new(struct kdbus_name_entry *e, |
17011 |
++ struct kdbus_conn *conn, u64 flags) |
17012 |
++{ |
17013 |
++ struct kdbus_name_pending *p; |
17014 |
++ |
17015 |
++ kdbus_conn_assert_active(conn); |
17016 |
++ |
17017 |
++ p = kmalloc(sizeof(*p), GFP_KERNEL); |
17018 |
++ if (!p) |
17019 |
++ return -ENOMEM; |
17020 |
++ |
17021 |
++ p->flags = flags; |
17022 |
++ p->conn = conn; |
17023 |
++ p->name = e; |
17024 |
++ list_add_tail(&p->conn_entry, &conn->names_queue_list); |
17025 |
++ list_add_tail(&p->name_entry, &e->queue); |
17026 |
++ |
17027 |
++ return 0; |
17028 |
++} |
17029 |
++ |
17030 |
++static void kdbus_name_pending_free(struct kdbus_name_pending *p) |
17031 |
++{ |
17032 |
++ if (!p) |
17033 |
++ return; |
17034 |
++ |
17035 |
++ list_del(&p->name_entry); |
17036 |
++ list_del(&p->conn_entry); |
17037 |
++ kfree(p); |
17038 |
++} |
17039 |
++ |
17040 |
++static struct kdbus_name_entry * |
17041 |
++kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash, const char *name) |
17042 |
++{ |
17043 |
++ struct kdbus_name_entry *e; |
17044 |
++ size_t namelen; |
17045 |
++ |
17046 |
++ namelen = strlen(name); |
17047 |
++ |
17048 |
++ e = kmalloc(sizeof(*e) + namelen + 1, GFP_KERNEL); |
17049 |
++ if (!e) |
17050 |
++ return ERR_PTR(-ENOMEM); |
17051 |
++ |
17052 |
++ e->name_id = ++r->name_seq_last; |
17053 |
++ e->flags = 0; |
17054 |
++ e->conn = NULL; |
17055 |
++ e->activator = NULL; |
17056 |
++ INIT_LIST_HEAD(&e->queue); |
17057 |
++ INIT_LIST_HEAD(&e->conn_entry); |
17058 |
++ hash_add(r->entries_hash, &e->hentry, hash); |
17059 |
++ memcpy(e->name, name, namelen + 1); |
17060 |
++ |
17061 |
++ return e; |
17062 |
++} |
17063 |
++ |
17064 |
++static void kdbus_name_entry_free(struct kdbus_name_entry *e) |
17065 |
++{ |
17066 |
++ if (!e) |
17067 |
++ return; |
17068 |
++ |
17069 |
++ WARN_ON(!list_empty(&e->conn_entry)); |
17070 |
++ WARN_ON(!list_empty(&e->queue)); |
17071 |
++ WARN_ON(e->activator); |
17072 |
++ WARN_ON(e->conn); |
17073 |
++ |
17074 |
++ hash_del(&e->hentry); |
17075 |
++ kfree(e); |
17076 |
++} |
17077 |
++ |
17078 |
++static void kdbus_name_entry_set_owner(struct kdbus_name_entry *e, |
17079 |
++ struct kdbus_conn *conn, u64 flags) |
17080 |
++{ |
17081 |
++ WARN_ON(e->conn); |
17082 |
++ |
17083 |
++ e->conn = kdbus_conn_ref(conn); |
17084 |
++ e->flags = flags; |
17085 |
++ atomic_inc(&conn->name_count); |
17086 |
++ list_add_tail(&e->conn_entry, &e->conn->names_list); |
17087 |
++} |
17088 |
++ |
17089 |
++static void kdbus_name_entry_remove_owner(struct kdbus_name_entry *e) |
17090 |
++{ |
17091 |
++ WARN_ON(!e->conn); |
17092 |
++ |
17093 |
++ list_del_init(&e->conn_entry); |
17094 |
++ atomic_dec(&e->conn->name_count); |
17095 |
++ e->flags = 0; |
17096 |
++ e->conn = kdbus_conn_unref(e->conn); |
17097 |
++} |
17098 |
++ |
17099 |
++static void kdbus_name_entry_replace_owner(struct kdbus_name_entry *e, |
17100 |
++ struct kdbus_conn *conn, u64 flags) |
17101 |
++{ |
17102 |
++ if (WARN_ON(!e->conn) || WARN_ON(conn == e->conn)) |
17103 |
++ return; |
17104 |
++ |
17105 |
++ kdbus_notify_name_change(conn->ep->bus, KDBUS_ITEM_NAME_CHANGE, |
17106 |
++ e->conn->id, conn->id, |
17107 |
++ e->flags, flags, e->name); |
17108 |
++ kdbus_name_entry_remove_owner(e); |
17109 |
++ kdbus_name_entry_set_owner(e, conn, flags); |
17110 |
++} |
17111 |
++ |
17112 |
++/** |
17113 |
++ * kdbus_name_is_valid() - check if a name is valid |
17114 |
++ * @p: The name to check |
17115 |
++ * @allow_wildcard: Whether or not to allow a wildcard name |
17116 |
++ * |
17117 |
++ * A name is valid if all of the following criterias are met: |
17118 |
++ * |
17119 |
++ * - The name has two or more elements separated by a period ('.') character. |
17120 |
++ * - All elements must contain at least one character. |
17121 |
++ * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-" |
17122 |
++ * and must not begin with a digit. |
17123 |
++ * - The name must not exceed KDBUS_NAME_MAX_LEN. |
17124 |
++ * - If @allow_wildcard is true, the name may end on '.*' |
17125 |
++ */ |
17126 |
++bool kdbus_name_is_valid(const char *p, bool allow_wildcard) |
17127 |
++{ |
17128 |
++ bool dot, found_dot = false; |
17129 |
++ const char *q; |
17130 |
++ |
17131 |
++ for (dot = true, q = p; *q; q++) { |
17132 |
++ if (*q == '.') { |
17133 |
++ if (dot) |
17134 |
++ return false; |
17135 |
++ |
17136 |
++ found_dot = true; |
17137 |
++ dot = true; |
17138 |
++ } else { |
17139 |
++ bool good; |
17140 |
++ |
17141 |
++ good = isalpha(*q) || (!dot && isdigit(*q)) || |
17142 |
++ *q == '_' || *q == '-' || |
17143 |
++ (allow_wildcard && dot && |
17144 |
++ *q == '*' && *(q + 1) == '\0'); |
17145 |
++ |
17146 |
++ if (!good) |
17147 |
++ return false; |
17148 |
++ |
17149 |
++ dot = false; |
17150 |
++ } |
17151 |
++ } |
17152 |
++ |
17153 |
++ if (q - p > KDBUS_NAME_MAX_LEN) |
17154 |
++ return false; |
17155 |
++ |
17156 |
++ if (dot) |
17157 |
++ return false; |
17158 |
++ |
17159 |
++ if (!found_dot) |
17160 |
++ return false; |
17161 |
++ |
17162 |
++ return true; |
17163 |
++} |
17164 |
++ |
17165 |
++/** |
17166 |
++ * kdbus_name_registry_new() - create a new name registry |
17167 |
++ * |
17168 |
++ * Return: a new kdbus_name_registry on success, ERR_PTR on failure. |
17169 |
++ */ |
17170 |
++struct kdbus_name_registry *kdbus_name_registry_new(void) |
17171 |
++{ |
17172 |
++ struct kdbus_name_registry *r; |
17173 |
++ |
17174 |
++ r = kmalloc(sizeof(*r), GFP_KERNEL); |
17175 |
++ if (!r) |
17176 |
++ return ERR_PTR(-ENOMEM); |
17177 |
++ |
17178 |
++ hash_init(r->entries_hash); |
17179 |
++ init_rwsem(&r->rwlock); |
17180 |
++ r->name_seq_last = 0; |
17181 |
++ |
17182 |
++ return r; |
17183 |
++} |
17184 |
++ |
17185 |
++/** |
17186 |
++ * kdbus_name_registry_free() - drop a name reg's reference |
17187 |
++ * @reg: The name registry, may be %NULL |
17188 |
++ * |
17189 |
++ * Cleanup the name registry's internal structures. |
17190 |
++ */ |
17191 |
++void kdbus_name_registry_free(struct kdbus_name_registry *reg) |
17192 |
++{ |
17193 |
++ if (!reg) |
17194 |
++ return; |
17195 |
++ |
17196 |
++ WARN_ON(!hash_empty(reg->entries_hash)); |
17197 |
++ kfree(reg); |
17198 |
++} |
17199 |
++ |
17200 |
++static struct kdbus_name_entry * |
17201 |
++kdbus_name_find(struct kdbus_name_registry *reg, u32 hash, const char *name) |
17202 |
++{ |
17203 |
++ struct kdbus_name_entry *e; |
17204 |
++ |
17205 |
++ lockdep_assert_held(®->rwlock); |
17206 |
++ |
17207 |
++ hash_for_each_possible(reg->entries_hash, e, hentry, hash) |
17208 |
++ if (strcmp(e->name, name) == 0) |
17209 |
++ return e; |
17210 |
++ |
17211 |
++ return NULL; |
17212 |
++} |
17213 |
++ |
17214 |
++/** |
17215 |
++ * kdbus_name_lookup_unlocked() - lookup name in registry |
17216 |
++ * @reg: name registry |
17217 |
++ * @name: name to lookup |
17218 |
++ * |
17219 |
++ * This looks up @name in the given name-registry and returns the |
17220 |
++ * kdbus_name_entry object. The caller must hold the registry-lock and must not |
17221 |
++ * access the returned object after releasing the lock. |
17222 |
++ * |
17223 |
++ * Return: Pointer to name-entry, or NULL if not found. |
17224 |
++ */ |
17225 |
++struct kdbus_name_entry * |
17226 |
++kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name) |
17227 |
++{ |
17228 |
++ return kdbus_name_find(reg, kdbus_strhash(name), name); |
17229 |
++} |
17230 |
++ |
17231 |
++/** |
17232 |
++ * kdbus_name_acquire() - acquire a name |
17233 |
++ * @reg: The name registry |
17234 |
++ * @conn: The connection to pin this entry to |
17235 |
++ * @name: The name to acquire |
17236 |
++ * @flags: Acquisition flags (KDBUS_NAME_*) |
17237 |
++ * @return_flags: Pointer to return flags for the acquired name |
17238 |
++ * (KDBUS_NAME_*), may be %NULL |
17239 |
++ * |
17240 |
++ * Callers must ensure that @conn is either a privileged bus user or has |
17241 |
++ * sufficient privileges in the policy-db to own the well-known name @name. |
17242 |
++ * |
17243 |
++ * Return: 0 success, negative error number on failure. |
17244 |
++ */ |
17245 |
++int kdbus_name_acquire(struct kdbus_name_registry *reg, |
17246 |
++ struct kdbus_conn *conn, const char *name, |
17247 |
++ u64 flags, u64 *return_flags) |
17248 |
++{ |
17249 |
++ struct kdbus_name_entry *e; |
17250 |
++ u64 rflags = 0; |
17251 |
++ int ret = 0; |
17252 |
++ u32 hash; |
17253 |
++ |
17254 |
++ kdbus_conn_assert_active(conn); |
17255 |
++ |
17256 |
++ down_write(®->rwlock); |
17257 |
++ |
17258 |
++ if (!kdbus_conn_policy_own_name(conn, current_cred(), name)) { |
17259 |
++ ret = -EPERM; |
17260 |
++ goto exit_unlock; |
17261 |
++ } |
17262 |
++ |
17263 |
++ hash = kdbus_strhash(name); |
17264 |
++ e = kdbus_name_find(reg, hash, name); |
17265 |
++ if (!e) { |
17266 |
++ /* claim new name */ |
17267 |
++ |
17268 |
++ if (conn->activator_of) { |
17269 |
++ ret = -EINVAL; |
17270 |
++ goto exit_unlock; |
17271 |
++ } |
17272 |
++ |
17273 |
++ e = kdbus_name_entry_new(reg, hash, name); |
17274 |
++ if (IS_ERR(e)) { |
17275 |
++ ret = PTR_ERR(e); |
17276 |
++ goto exit_unlock; |
17277 |
++ } |
17278 |
++ |
17279 |
++ if (kdbus_conn_is_activator(conn)) { |
17280 |
++ e->activator = kdbus_conn_ref(conn); |
17281 |
++ conn->activator_of = e; |
17282 |
++ } |
17283 |
++ |
17284 |
++ kdbus_name_entry_set_owner(e, conn, flags); |
17285 |
++ kdbus_notify_name_change(e->conn->ep->bus, KDBUS_ITEM_NAME_ADD, |
17286 |
++ 0, e->conn->id, 0, e->flags, e->name); |
17287 |
++ } else if (e->conn == conn || e == conn->activator_of) { |
17288 |
++ /* connection already owns that name */ |
17289 |
++ ret = -EALREADY; |
17290 |
++ } else if (kdbus_conn_is_activator(conn)) { |
17291 |
++ /* activator claims existing name */ |
17292 |
++ |
17293 |
++ if (conn->activator_of) { |
17294 |
++ ret = -EINVAL; /* multiple names not allowed */ |
17295 |
++ } else if (e->activator) { |
17296 |
++ ret = -EEXIST; /* only one activator per name */ |
17297 |
++ } else { |
17298 |
++ e->activator = kdbus_conn_ref(conn); |
17299 |
++ conn->activator_of = e; |
17300 |
++ } |
17301 |
++ } else if (e->flags & KDBUS_NAME_ACTIVATOR) { |
17302 |
++ /* claim name of an activator */ |
17303 |
++ |
17304 |
++ kdbus_conn_move_messages(conn, e->activator, 0); |
17305 |
++ kdbus_name_entry_replace_owner(e, conn, flags); |
17306 |
++ } else if ((flags & KDBUS_NAME_REPLACE_EXISTING) && |
17307 |
++ (e->flags & KDBUS_NAME_ALLOW_REPLACEMENT)) { |
17308 |
++ /* claim name of a previous owner */ |
17309 |
++ |
17310 |
++ if (e->flags & KDBUS_NAME_QUEUE) { |
17311 |
++ /* move owner back to queue if they asked for it */ |
17312 |
++ ret = kdbus_name_pending_new(e, e->conn, e->flags); |
17313 |
++ if (ret < 0) |
17314 |
++ goto exit_unlock; |
17315 |
++ } |
17316 |
++ |
17317 |
++ kdbus_name_entry_replace_owner(e, conn, flags); |
17318 |
++ } else if (flags & KDBUS_NAME_QUEUE) { |
17319 |
++ /* add to waiting-queue of the name */ |
17320 |
++ |
17321 |
++ ret = kdbus_name_pending_new(e, conn, flags); |
17322 |
++ if (ret >= 0) |
17323 |
++ /* tell the caller that we queued it */ |
17324 |
++ rflags |= KDBUS_NAME_IN_QUEUE; |
17325 |
++ } else { |
17326 |
++ /* the name is busy, return a failure */ |
17327 |
++ ret = -EEXIST; |
17328 |
++ } |
17329 |
++ |
17330 |
++ if (ret == 0 && return_flags) |
17331 |
++ *return_flags = rflags; |
17332 |
++ |
17333 |
++exit_unlock: |
17334 |
++ up_write(®->rwlock); |
17335 |
++ kdbus_notify_flush(conn->ep->bus); |
17336 |
++ return ret; |
17337 |
++} |
17338 |
++ |
17339 |
++static void kdbus_name_release_unlocked(struct kdbus_name_registry *reg, |
17340 |
++ struct kdbus_name_entry *e) |
17341 |
++{ |
17342 |
++ struct kdbus_name_pending *p; |
17343 |
++ |
17344 |
++ lockdep_assert_held(®->rwlock); |
17345 |
++ |
17346 |
++ p = list_first_entry_or_null(&e->queue, struct kdbus_name_pending, |
17347 |
++ name_entry); |
17348 |
++ |
17349 |
++ if (p) { |
17350 |
++ /* give it to first active waiter in the queue */ |
17351 |
++ kdbus_name_entry_replace_owner(e, p->conn, p->flags); |
17352 |
++ kdbus_name_pending_free(p); |
17353 |
++ } else if (e->activator && e->activator != e->conn) { |
17354 |
++ /* hand it back to an active activator connection */ |
17355 |
++ kdbus_conn_move_messages(e->activator, e->conn, e->name_id); |
17356 |
++ kdbus_name_entry_replace_owner(e, e->activator, |
17357 |
++ KDBUS_NAME_ACTIVATOR); |
17358 |
++ } else { |
17359 |
++ /* release the name */ |
17360 |
++ kdbus_notify_name_change(e->conn->ep->bus, |
17361 |
++ KDBUS_ITEM_NAME_REMOVE, |
17362 |
++ e->conn->id, 0, e->flags, 0, e->name); |
17363 |
++ kdbus_name_entry_remove_owner(e); |
17364 |
++ kdbus_name_entry_free(e); |
17365 |
++ } |
17366 |
++} |
17367 |
++ |
17368 |
++static int kdbus_name_release(struct kdbus_name_registry *reg, |
17369 |
++ struct kdbus_conn *conn, |
17370 |
++ const char *name) |
17371 |
++{ |
17372 |
++ struct kdbus_name_pending *p; |
17373 |
++ struct kdbus_name_entry *e; |
17374 |
++ int ret = 0; |
17375 |
++ |
17376 |
++ down_write(®->rwlock); |
17377 |
++ e = kdbus_name_find(reg, kdbus_strhash(name), name); |
17378 |
++ if (!e) { |
17379 |
++ ret = -ESRCH; |
17380 |
++ } else if (e->conn == conn) { |
17381 |
++ kdbus_name_release_unlocked(reg, e); |
17382 |
++ } else { |
17383 |
++ ret = -EADDRINUSE; |
17384 |
++ list_for_each_entry(p, &e->queue, name_entry) { |
17385 |
++ if (p->conn == conn) { |
17386 |
++ kdbus_name_pending_free(p); |
17387 |
++ ret = 0; |
17388 |
++ break; |
17389 |
++ } |
17390 |
++ } |
17391 |
++ } |
17392 |
++ up_write(®->rwlock); |
17393 |
++ |
17394 |
++ kdbus_notify_flush(conn->ep->bus); |
17395 |
++ return ret; |
17396 |
++} |
17397 |
++ |
17398 |
++/** |
17399 |
++ * kdbus_name_release_all() - remove all name entries of a given connection |
17400 |
++ * @reg: name registry |
17401 |
++ * @conn: connection |
17402 |
++ */ |
17403 |
++void kdbus_name_release_all(struct kdbus_name_registry *reg, |
17404 |
++ struct kdbus_conn *conn) |
17405 |
++{ |
17406 |
++ struct kdbus_name_pending *p; |
17407 |
++ struct kdbus_conn *activator = NULL; |
17408 |
++ struct kdbus_name_entry *e; |
17409 |
++ |
17410 |
++ down_write(®->rwlock); |
17411 |
++ |
17412 |
++ if (kdbus_conn_is_activator(conn)) { |
17413 |
++ activator = conn->activator_of->activator; |
17414 |
++ conn->activator_of->activator = NULL; |
17415 |
++ } |
17416 |
++ |
17417 |
++ while ((p = list_first_entry_or_null(&conn->names_queue_list, |
17418 |
++ struct kdbus_name_pending, |
17419 |
++ conn_entry))) |
17420 |
++ kdbus_name_pending_free(p); |
17421 |
++ while ((e = list_first_entry_or_null(&conn->names_list, |
17422 |
++ struct kdbus_name_entry, |
17423 |
++ conn_entry))) |
17424 |
++ kdbus_name_release_unlocked(reg, e); |
17425 |
++ |
17426 |
++ up_write(®->rwlock); |
17427 |
++ |
17428 |
++ kdbus_conn_unref(activator); |
17429 |
++ kdbus_notify_flush(conn->ep->bus); |
17430 |
++} |
17431 |
++ |
17432 |
++/** |
17433 |
++ * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE |
17434 |
++ * @conn: connection to operate on |
17435 |
++ * @argp: command payload |
17436 |
++ * |
17437 |
++ * Return: 0 on success, negative error code on failure. |
17438 |
++ */ |
17439 |
++int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp) |
17440 |
++{ |
17441 |
++ const char *item_name; |
17442 |
++ struct kdbus_cmd *cmd; |
17443 |
++ int ret; |
17444 |
++ |
17445 |
++ struct kdbus_arg argv[] = { |
17446 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
17447 |
++ { .type = KDBUS_ITEM_NAME, .mandatory = true }, |
17448 |
++ }; |
17449 |
++ struct kdbus_args args = { |
17450 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
17451 |
++ KDBUS_NAME_REPLACE_EXISTING | |
17452 |
++ KDBUS_NAME_ALLOW_REPLACEMENT | |
17453 |
++ KDBUS_NAME_QUEUE, |
17454 |
++ .argv = argv, |
17455 |
++ .argc = ARRAY_SIZE(argv), |
17456 |
++ }; |
17457 |
++ |
17458 |
++ if (!kdbus_conn_is_ordinary(conn)) |
17459 |
++ return -EOPNOTSUPP; |
17460 |
++ |
17461 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
17462 |
++ if (ret != 0) |
17463 |
++ return ret; |
17464 |
++ |
17465 |
++ item_name = argv[1].item->str; |
17466 |
++ if (!kdbus_name_is_valid(item_name, false)) { |
17467 |
++ ret = -EINVAL; |
17468 |
++ goto exit; |
17469 |
++ } |
17470 |
++ |
17471 |
++ /* |
17472 |
++ * Do atomic_inc_return here to reserve our slot, then decrement |
17473 |
++ * it before returning. |
17474 |
++ */ |
17475 |
++ if (atomic_inc_return(&conn->name_count) > KDBUS_CONN_MAX_NAMES) { |
17476 |
++ ret = -E2BIG; |
17477 |
++ goto exit_dec; |
17478 |
++ } |
17479 |
++ |
17480 |
++ ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name, |
17481 |
++ cmd->flags, &cmd->return_flags); |
17482 |
++ if (ret < 0) |
17483 |
++ goto exit_dec; |
17484 |
++ |
17485 |
++exit_dec: |
17486 |
++ atomic_dec(&conn->name_count); |
17487 |
++exit: |
17488 |
++ return kdbus_args_clear(&args, ret); |
17489 |
++} |
17490 |
++ |
17491 |
++/** |
17492 |
++ * kdbus_cmd_name_release() - handle KDBUS_CMD_NAME_RELEASE |
17493 |
++ * @conn: connection to operate on |
17494 |
++ * @argp: command payload |
17495 |
++ * |
17496 |
++ * Return: 0 on success, negative error code on failure. |
17497 |
++ */ |
17498 |
++int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp) |
17499 |
++{ |
17500 |
++ struct kdbus_cmd *cmd; |
17501 |
++ int ret; |
17502 |
++ |
17503 |
++ struct kdbus_arg argv[] = { |
17504 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
17505 |
++ { .type = KDBUS_ITEM_NAME, .mandatory = true }, |
17506 |
++ }; |
17507 |
++ struct kdbus_args args = { |
17508 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
17509 |
++ .argv = argv, |
17510 |
++ .argc = ARRAY_SIZE(argv), |
17511 |
++ }; |
17512 |
++ |
17513 |
++ if (!kdbus_conn_is_ordinary(conn)) |
17514 |
++ return -EOPNOTSUPP; |
17515 |
++ |
17516 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
17517 |
++ if (ret != 0) |
17518 |
++ return ret; |
17519 |
++ |
17520 |
++ ret = kdbus_name_release(conn->ep->bus->name_registry, conn, |
17521 |
++ argv[1].item->str); |
17522 |
++ return kdbus_args_clear(&args, ret); |
17523 |
++} |
17524 |
++ |
17525 |
++static int kdbus_list_write(struct kdbus_conn *conn, |
17526 |
++ struct kdbus_conn *c, |
17527 |
++ struct kdbus_pool_slice *slice, |
17528 |
++ size_t *pos, |
17529 |
++ struct kdbus_name_entry *e, |
17530 |
++ bool write) |
17531 |
++{ |
17532 |
++ struct kvec kvec[4]; |
17533 |
++ size_t cnt = 0; |
17534 |
++ int ret; |
17535 |
++ |
17536 |
++ /* info header */ |
17537 |
++ struct kdbus_info info = { |
17538 |
++ .size = 0, |
17539 |
++ .id = c->id, |
17540 |
++ .flags = c->flags, |
17541 |
++ }; |
17542 |
++ |
17543 |
++ /* fake the header of a kdbus_name item */ |
17544 |
++ struct { |
17545 |
++ u64 size; |
17546 |
++ u64 type; |
17547 |
++ u64 flags; |
17548 |
++ } h = {}; |
17549 |
++ |
17550 |
++ if (e && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(), |
17551 |
++ e->name)) |
17552 |
++ return 0; |
17553 |
++ |
17554 |
++ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size); |
17555 |
++ |
17556 |
++ /* append name */ |
17557 |
++ if (e) { |
17558 |
++ size_t slen = strlen(e->name) + 1; |
17559 |
++ |
17560 |
++ h.size = offsetof(struct kdbus_item, name.name) + slen; |
17561 |
++ h.type = KDBUS_ITEM_OWNED_NAME; |
17562 |
++ h.flags = e->flags; |
17563 |
++ |
17564 |
++ kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size); |
17565 |
++ kdbus_kvec_set(&kvec[cnt++], e->name, slen, &info.size); |
17566 |
++ cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size); |
17567 |
++ } |
17568 |
++ |
17569 |
++ if (write) { |
17570 |
++ ret = kdbus_pool_slice_copy_kvec(slice, *pos, kvec, |
17571 |
++ cnt, info.size); |
17572 |
++ if (ret < 0) |
17573 |
++ return ret; |
17574 |
++ } |
17575 |
++ |
17576 |
++ *pos += info.size; |
17577 |
++ return 0; |
17578 |
++} |
17579 |
++ |
17580 |
++static int kdbus_list_all(struct kdbus_conn *conn, u64 flags, |
17581 |
++ struct kdbus_pool_slice *slice, |
17582 |
++ size_t *pos, bool write) |
17583 |
++{ |
17584 |
++ struct kdbus_conn *c; |
17585 |
++ size_t p = *pos; |
17586 |
++ int ret, i; |
17587 |
++ |
17588 |
++ hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) { |
17589 |
++ bool added = false; |
17590 |
++ |
17591 |
++ /* skip monitors */ |
17592 |
++ if (kdbus_conn_is_monitor(c)) |
17593 |
++ continue; |
17594 |
++ |
17595 |
++ /* skip activators */ |
17596 |
++ if (!(flags & KDBUS_LIST_ACTIVATORS) && |
17597 |
++ kdbus_conn_is_activator(c)) |
17598 |
++ continue; |
17599 |
++ |
17600 |
++ /* all names the connection owns */ |
17601 |
++ if (flags & (KDBUS_LIST_NAMES | KDBUS_LIST_ACTIVATORS)) { |
17602 |
++ struct kdbus_name_entry *e; |
17603 |
++ |
17604 |
++ list_for_each_entry(e, &c->names_list, conn_entry) { |
17605 |
++ struct kdbus_conn *a = e->activator; |
17606 |
++ |
17607 |
++ if ((flags & KDBUS_LIST_ACTIVATORS) && |
17608 |
++ a && a != c) { |
17609 |
++ ret = kdbus_list_write(conn, a, slice, |
17610 |
++ &p, e, write); |
17611 |
++ if (ret < 0) { |
17612 |
++ mutex_unlock(&c->lock); |
17613 |
++ return ret; |
17614 |
++ } |
17615 |
++ |
17616 |
++ added = true; |
17617 |
++ } |
17618 |
++ |
17619 |
++ if (flags & KDBUS_LIST_NAMES || |
17620 |
++ kdbus_conn_is_activator(c)) { |
17621 |
++ ret = kdbus_list_write(conn, c, slice, |
17622 |
++ &p, e, write); |
17623 |
++ if (ret < 0) { |
17624 |
++ mutex_unlock(&c->lock); |
17625 |
++ return ret; |
17626 |
++ } |
17627 |
++ |
17628 |
++ added = true; |
17629 |
++ } |
17630 |
++ } |
17631 |
++ } |
17632 |
++ |
17633 |
++ /* queue of names the connection is currently waiting for */ |
17634 |
++ if (flags & KDBUS_LIST_QUEUED) { |
17635 |
++ struct kdbus_name_pending *q; |
17636 |
++ |
17637 |
++ list_for_each_entry(q, &c->names_queue_list, |
17638 |
++ conn_entry) { |
17639 |
++ ret = kdbus_list_write(conn, c, slice, &p, |
17640 |
++ q->name, write); |
17641 |
++ if (ret < 0) { |
17642 |
++ mutex_unlock(&c->lock); |
17643 |
++ return ret; |
17644 |
++ } |
17645 |
++ |
17646 |
++ added = true; |
17647 |
++ } |
17648 |
++ } |
17649 |
++ |
17650 |
++ /* nothing added so far, just add the unique ID */ |
17651 |
++ if (!added && flags & KDBUS_LIST_UNIQUE) { |
17652 |
++ ret = kdbus_list_write(conn, c, slice, &p, NULL, write); |
17653 |
++ if (ret < 0) |
17654 |
++ return ret; |
17655 |
++ } |
17656 |
++ } |
17657 |
++ |
17658 |
++ *pos = p; |
17659 |
++ return 0; |
17660 |
++} |
17661 |
++ |
17662 |
++/** |
17663 |
++ * kdbus_cmd_list() - handle KDBUS_CMD_LIST |
17664 |
++ * @conn: connection to operate on |
17665 |
++ * @argp: command payload |
17666 |
++ * |
17667 |
++ * Return: 0 on success, negative error code on failure. |
17668 |
++ */ |
17669 |
++int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp) |
17670 |
++{ |
17671 |
++ struct kdbus_name_registry *reg = conn->ep->bus->name_registry; |
17672 |
++ struct kdbus_pool_slice *slice = NULL; |
17673 |
++ struct kdbus_cmd_list *cmd; |
17674 |
++ size_t pos, size; |
17675 |
++ int ret; |
17676 |
++ |
17677 |
++ struct kdbus_arg argv[] = { |
17678 |
++ { .type = KDBUS_ITEM_NEGOTIATE }, |
17679 |
++ }; |
17680 |
++ struct kdbus_args args = { |
17681 |
++ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
17682 |
++ KDBUS_LIST_UNIQUE | |
17683 |
++ KDBUS_LIST_NAMES | |
17684 |
++ KDBUS_LIST_ACTIVATORS | |
17685 |
++ KDBUS_LIST_QUEUED, |
17686 |
++ .argv = argv, |
17687 |
++ .argc = ARRAY_SIZE(argv), |
17688 |
++ }; |
17689 |
++ |
17690 |
++ ret = kdbus_args_parse(&args, argp, &cmd); |
17691 |
++ if (ret != 0) |
17692 |
++ return ret; |
17693 |
++ |
17694 |
++ /* lock order: domain -> bus -> ep -> names -> conn */ |
17695 |
++ down_read(®->rwlock); |
17696 |
++ down_read(&conn->ep->bus->conn_rwlock); |
17697 |
++ down_read(&conn->ep->policy_db.entries_rwlock); |
17698 |
++ |
17699 |
++ /* size of records */ |
17700 |
++ size = 0; |
17701 |
++ ret = kdbus_list_all(conn, cmd->flags, NULL, &size, false); |
17702 |
++ if (ret < 0) |
17703 |
++ goto exit_unlock; |
17704 |
++ |
17705 |
++ if (size == 0) { |
17706 |
++ kdbus_pool_publish_empty(conn->pool, &cmd->offset, |
17707 |
++ &cmd->list_size); |
17708 |
++ } else { |
17709 |
++ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
17710 |
++ if (IS_ERR(slice)) { |
17711 |
++ ret = PTR_ERR(slice); |
17712 |
++ slice = NULL; |
17713 |
++ goto exit_unlock; |
17714 |
++ } |
17715 |
++ |
17716 |
++ /* copy the records */ |
17717 |
++ pos = 0; |
17718 |
++ ret = kdbus_list_all(conn, cmd->flags, slice, &pos, true); |
17719 |
++ if (ret < 0) |
17720 |
++ goto exit_unlock; |
17721 |
++ |
17722 |
++ WARN_ON(pos != size); |
17723 |
++ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->list_size); |
17724 |
++ } |
17725 |
++ |
17726 |
++ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
17727 |
++ kdbus_member_set_user(&cmd->list_size, argp, |
17728 |
++ typeof(*cmd), list_size)) |
17729 |
++ ret = -EFAULT; |
17730 |
++ |
17731 |
++exit_unlock: |
17732 |
++ up_read(&conn->ep->policy_db.entries_rwlock); |
17733 |
++ up_read(&conn->ep->bus->conn_rwlock); |
17734 |
++ up_read(®->rwlock); |
17735 |
++ kdbus_pool_slice_release(slice); |
17736 |
++ return kdbus_args_clear(&args, ret); |
17737 |
++} |
17738 |
+diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h |
17739 |
+new file mode 100644 |
17740 |
+index 0000000..3dd2589 |
17741 |
+--- /dev/null |
17742 |
++++ b/ipc/kdbus/names.h |
17743 |
+@@ -0,0 +1,74 @@ |
17744 |
++/* |
17745 |
++ * Copyright (C) 2013-2015 Kay Sievers |
17746 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
17747 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
17748 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
17749 |
++ * Copyright (C) 2013-2015 Linux Foundation |
17750 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
17751 |
++ * |
17752 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
17753 |
++ * the terms of the GNU Lesser General Public License as published by the |
17754 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
17755 |
++ * your option) any later version. |
17756 |
++ */ |
17757 |
++ |
17758 |
++#ifndef __KDBUS_NAMES_H |
17759 |
++#define __KDBUS_NAMES_H |
17760 |
++ |
17761 |
++#include <linux/hashtable.h> |
17762 |
++#include <linux/rwsem.h> |
17763 |
++ |
17764 |
++/** |
17765 |
++ * struct kdbus_name_registry - names registered for a bus |
17766 |
++ * @entries_hash: Map of entries |
17767 |
++ * @lock: Registry data lock |
17768 |
++ * @name_seq_last: Last used sequence number to assign to a name entry |
17769 |
++ */ |
17770 |
++struct kdbus_name_registry { |
17771 |
++ DECLARE_HASHTABLE(entries_hash, 8); |
17772 |
++ struct rw_semaphore rwlock; |
17773 |
++ u64 name_seq_last; |
17774 |
++}; |
17775 |
++ |
17776 |
++/** |
17777 |
++ * struct kdbus_name_entry - well-know name entry |
17778 |
++ * @name_id: Sequence number of name entry to be able to uniquely |
17779 |
++ * identify a name over its registration lifetime |
17780 |
++ * @flags: KDBUS_NAME_* flags |
17781 |
++ * @conn: Connection owning the name |
17782 |
++ * @activator: Connection of the activator queuing incoming messages |
17783 |
++ * @queue: List of queued connections |
17784 |
++ * @conn_entry: Entry in connection |
17785 |
++ * @hentry: Entry in registry map |
17786 |
++ * @name: The well-known name |
17787 |
++ */ |
17788 |
++struct kdbus_name_entry { |
17789 |
++ u64 name_id; |
17790 |
++ u64 flags; |
17791 |
++ struct kdbus_conn *conn; |
17792 |
++ struct kdbus_conn *activator; |
17793 |
++ struct list_head queue; |
17794 |
++ struct list_head conn_entry; |
17795 |
++ struct hlist_node hentry; |
17796 |
++ char name[]; |
17797 |
++}; |
17798 |
++ |
17799 |
++bool kdbus_name_is_valid(const char *p, bool allow_wildcard); |
17800 |
++ |
17801 |
++struct kdbus_name_registry *kdbus_name_registry_new(void); |
17802 |
++void kdbus_name_registry_free(struct kdbus_name_registry *reg); |
17803 |
++ |
17804 |
++struct kdbus_name_entry * |
17805 |
++kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name); |
17806 |
++ |
17807 |
++int kdbus_name_acquire(struct kdbus_name_registry *reg, |
17808 |
++ struct kdbus_conn *conn, const char *name, |
17809 |
++ u64 flags, u64 *return_flags); |
17810 |
++void kdbus_name_release_all(struct kdbus_name_registry *reg, |
17811 |
++ struct kdbus_conn *conn); |
17812 |
++ |
17813 |
++int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp); |
17814 |
++int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp); |
17815 |
++int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp); |
17816 |
++ |
17817 |
++#endif |
17818 |
+diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c |
17819 |
+new file mode 100644 |
17820 |
+index 0000000..520df00 |
17821 |
+--- /dev/null |
17822 |
++++ b/ipc/kdbus/node.c |
17823 |
+@@ -0,0 +1,910 @@ |
17824 |
++/* |
17825 |
++ * Copyright (C) 2013-2015 Kay Sievers |
17826 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
17827 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
17828 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
17829 |
++ * Copyright (C) 2013-2015 Linux Foundation |
17830 |
++ * |
17831 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
17832 |
++ * the terms of the GNU Lesser General Public License as published by the |
17833 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
17834 |
++ * your option) any later version. |
17835 |
++ */ |
17836 |
++ |
17837 |
++#include <linux/atomic.h> |
17838 |
++#include <linux/fs.h> |
17839 |
++#include <linux/idr.h> |
17840 |
++#include <linux/kdev_t.h> |
17841 |
++#include <linux/rbtree.h> |
17842 |
++#include <linux/rwsem.h> |
17843 |
++#include <linux/sched.h> |
17844 |
++#include <linux/slab.h> |
17845 |
++#include <linux/wait.h> |
17846 |
++ |
17847 |
++#include "bus.h" |
17848 |
++#include "domain.h" |
17849 |
++#include "endpoint.h" |
17850 |
++#include "fs.h" |
17851 |
++#include "handle.h" |
17852 |
++#include "node.h" |
17853 |
++#include "util.h" |
17854 |
++ |
17855 |
++/** |
17856 |
++ * DOC: kdbus nodes |
17857 |
++ * |
17858 |
++ * Nodes unify lifetime management across exposed kdbus objects and provide a |
17859 |
++ * hierarchy. Each kdbus object, that might be exposed to user-space, has a |
17860 |
++ * kdbus_node object embedded and is linked into the hierarchy. Each node can |
17861 |
++ * have any number (0-n) of child nodes linked. Each child retains a reference |
17862 |
++ * to its parent node. For root-nodes, the parent is NULL. |
17863 |
++ * |
17864 |
++ * Each node object goes through a bunch of states during it's lifetime: |
17865 |
++ * * NEW |
17866 |
++ * * LINKED (can be skipped by NEW->FREED transition) |
17867 |
++ * * ACTIVE (can be skipped by LINKED->INACTIVE transition) |
17868 |
++ * * INACTIVE |
17869 |
++ * * DRAINED |
17870 |
++ * * FREED |
17871 |
++ * |
17872 |
++ * Each node is allocated by the caller and initialized via kdbus_node_init(). |
17873 |
++ * This never fails and sets the object into state NEW. From now on, ref-counts |
17874 |
++ * on the node manage its lifetime. During init, the ref-count is set to 1. Once |
17875 |
++ * it drops to 0, the node goes to state FREED and the node->free_cb() callback |
17876 |
++ * is called to deallocate any memory. |
17877 |
++ * |
17878 |
++ * After initializing a node, you usually link it into the hierarchy. You need |
17879 |
++ * to provide a parent node and a name. The node will be linked as child to the |
17880 |
++ * parent and a globally unique ID is assigned to the child. The name of the |
17881 |
++ * child must be unique for all children of this parent. Otherwise, linking the |
17882 |
++ * child will fail with -EEXIST. |
17883 |
++ * Note that the child is not marked active, yet. Admittedly, it prevents any |
17884 |
++ * other node from being linked with the same name (thus, it reserves that |
17885 |
++ * name), but any child-lookup (via name or unique ID) will never return this |
17886 |
++ * child unless it has been marked active. |
17887 |
++ * |
17888 |
++ * Once successfully linked, you can use kdbus_node_activate() to activate a |
17889 |
++ * child. This will mark the child active. This state can be skipped by directly |
17890 |
++ * deactivating the child via kdbus_node_deactivate() (see below). |
17891 |
++ * By activating a child, you enable any lookups on this child to succeed from |
17892 |
++ * now on. Furthermore, any code that got its hands on a reference to the node, |
17893 |
++ * can from now on "acquire" the node. |
17894 |
++ * |
17895 |
++ * Active References (or: 'acquiring' and 'releasing' a node) |
17896 |
++ * Additionally to normal object references, nodes support something we call |
17897 |
++ * "active references". An active reference can be acquired via |
17898 |
++ * kdbus_node_acquire() and released via kdbus_node_release(). A caller |
17899 |
++ * _must_ own a normal object reference whenever calling those functions. |
17900 |
++ * Unlike object references, acquiring an active reference can fail (by |
17901 |
++ * returning 'false' from kdbus_node_acquire()). An active reference can |
17902 |
++ * only be acquired if the node is marked active. If it is not marked |
17903 |
++ * active, yet, or if it was already deactivated, no more active references |
17904 |
++ * can be acquired, ever! |
17905 |
++ * Active references are used to track tasks working on a node. Whenever a |
17906 |
++ * task enters kernel-space to perform an action on a node, it acquires an |
17907 |
++ * active reference, performs the action and releases the reference again. |
17908 |
++ * While holding an active reference, the node is guaranteed to stay active. |
17909 |
++ * If the node is deactivated in parallel, the node is marked as |
17910 |
++ * deactivated, then we wait for all active references to be dropped, before |
17911 |
++ * we finally proceed with any cleanups. That is, if you hold an active |
17912 |
++ * reference to a node, any resources that are bound to the "active" state |
17913 |
++ * are guaranteed to stay accessible until you release your reference. |
17914 |
++ * |
17915 |
++ * Active-references are very similar to rw-locks, where acquiring a node is |
17916 |
++ * equal to try-read-lock and releasing to read-unlock. Deactivating a node |
17917 |
++ * means write-lock and never releasing it again. |
17918 |
++ * Unlike rw-locks, the 'active reference' concept is more versatile and |
17919 |
++ * avoids unusual rw-lock usage (never releasing a write-lock..). |
17920 |
++ * |
17921 |
++ * It is safe to acquire multiple active-references recursively. But you |
17922 |
++ * need to check the return value of kdbus_node_acquire() on _each_ call. It |
17923 |
++ * may stop granting references at _any_ time. |
17924 |
++ * |
17925 |
++ * You're free to perform any operations you want while holding an active |
17926 |
++ * reference, except sleeping for an indefinite period. Sleeping for a fixed |
17927 |
++ * amount of time is fine, but you usually should not wait on wait-queues |
17928 |
++ * without a timeout. |
17929 |
++ * For example, if you wait for I/O to happen, you should gather all data |
17930 |
++ * and schedule the I/O operation, then release your active reference and |
17931 |
++ * wait for it to complete. Then try to acquire a new reference. If it |
17932 |
++ * fails, perform any cleanup (the node is now dead). Otherwise, you can |
17933 |
++ * finish your operation. |
17934 |
++ * |
17935 |
++ * All nodes can be deactivated via kdbus_node_deactivate() at any time. You can |
17936 |
++ * call this multiple times, even in parallel or on nodes that were never |
17937 |
++ * linked, and it will just work. The only restriction is, you must not hold an |
17938 |
++ * active reference when calling kdbus_node_deactivate(). |
17939 |
++ * By deactivating a node, it is immediately marked inactive. Then, we wait for |
17940 |
++ * all active references to be released (called 'draining' the node). This |
17941 |
++ * shouldn't take very long as we don't perform long-lasting operations while |
17942 |
++ * holding an active reference. Note that once the node is marked inactive, no |
17943 |
++ * new active references can be acquired. |
17944 |
++ * Once all active references are dropped, the node is considered 'drained'. Now |
17945 |
++ * kdbus_node_deactivate() is called on each child of the node before we |
17946 |
++ * continue deactvating our node. That is, once all children are entirely |
17947 |
++ * deactivated, we call ->release_cb() of our node. ->release_cb() can release |
17948 |
++ * any resources on that node which are bound to the "active" state of a node. |
17949 |
++ * When done, we unlink the node from its parent rb-tree, mark it as |
17950 |
++ * 'released' and return. |
17951 |
++ * If kdbus_node_deactivate() is called multiple times (even in parallel), all |
17952 |
++ * but one caller will just wait until the node is fully deactivated. That is, |
17953 |
++ * one random caller of kdbus_node_deactivate() is selected to call |
17954 |
++ * ->release_cb() and cleanup the node. Only once all this is done, all other |
17955 |
++ * callers will return from kdbus_node_deactivate(). That is, it doesn't matter |
17956 |
++ * whether you're the selected caller or not, it will only return after |
17957 |
++ * everything is fully done. |
17958 |
++ * |
17959 |
++ * When a node is activated, we acquire a normal object reference to the node. |
17960 |
++ * This reference is dropped after deactivation is fully done (and only iff the |
17961 |
++ * node really was activated). This allows callers to link+activate a child node |
17962 |
++ * and then drop all refs. The node will be deactivated together with the |
17963 |
++ * parent, and then be freed when this reference is dropped. |
17964 |
++ * |
17965 |
++ * Currently, nodes provide a bunch of resources that external code can use |
17966 |
++ * directly. This includes: |
17967 |
++ * |
17968 |
++ * * node->waitq: Each node has its own wait-queue that is used to manage |
17969 |
++ * the 'active' state. When a node is deactivated, we wait on |
17970 |
++ * this queue until all active refs are dropped. Analogously, |
17971 |
++ * when you release an active reference on a deactivated |
17972 |
++ * node, and the active ref-count drops to 0, we wake up a |
17973 |
++ * single thread on this queue. Furthermore, once the |
17974 |
++ * ->release_cb() callback finished, we wake up all waiters. |
17975 |
++ * The node-owner is free to re-use this wait-queue for other |
17976 |
++ * purposes. As node-management uses this queue only during |
17977 |
++ * deactivation, it is usually totally fine to re-use the |
17978 |
++ * queue for other, preferably low-overhead, use-cases. |
17979 |
++ * |
17980 |
++ * * node->type: This field defines the type of the owner of this node. It |
17981 |
++ * must be set during node initialization and must remain |
17982 |
++ * constant. The node management never looks at this value, |
17983 |
++ * but external users might use to gain access to the owner |
17984 |
++ * object of a node. |
17985 |
++ * It is totally up to the owner of the node to define what |
17986 |
++ * their type means. Usually it means you can access the |
17987 |
++ * parent structure via container_of(), as long as you hold an |
17988 |
++ * active reference to the node. |
17989 |
++ * |
17990 |
++ * * node->free_cb: callback after all references are dropped |
17991 |
++ * node->release_cb: callback during node deactivation |
17992 |
++ * These fields must be set by the node owner during |
17993 |
++ * node initialization. They must remain constant. If |
17994 |
++ * NULL, they're skipped. |
17995 |
++ * |
17996 |
++ * * node->mode: filesystem access modes |
17997 |
++ * node->uid: filesystem owner uid |
17998 |
++ * node->gid: filesystem owner gid |
17999 |
++ * These fields must be set by the node owner during node |
18000 |
++ * initialization. They must remain constant and may be |
18001 |
++ * accessed by other callers to properly initialize |
18002 |
++ * filesystem nodes. |
18003 |
++ * |
18004 |
++ * * node->id: This is an unsigned 32bit integer allocated by an IDR. It is |
18005 |
++ * always kept as small as possible during allocation and is |
18006 |
++ * globally unique across all nodes allocated by this module. 0 |
18007 |
++ * is reserved as "not assigned" and is the default. |
18008 |
++ * The ID is assigned during kdbus_node_link() and is kept until |
18009 |
++ * the object is freed. Thus, the ID surpasses the active |
18010 |
++ * lifetime of a node. As long as you hold an object reference |
18011 |
++ * to a node (and the node was linked once), the ID is valid and |
18012 |
++ * unique. |
18013 |
++ * |
18014 |
++ * * node->name: name of this node |
18015 |
++ * node->hash: 31bit hash-value of @name (range [2..INT_MAX-1]) |
18016 |
++ * These values follow the same lifetime rules as node->id. |
18017 |
++ * They're initialized when the node is linked and then remain |
18018 |
++ * constant until the last object reference is dropped. |
18019 |
++ * Unlike the id, the name is only unique across all siblings |
18020 |
++ * and only until the node is deactivated. Currently, the name |
18021 |
++ * is even unique if linked but not activated, yet. This might |
18022 |
++ * change in the future, though. Code should not rely on this. |
18023 |
++ * |
18024 |
++ * * node->lock: lock to protect node->children, node->rb, node->parent |
18025 |
++ * * node->parent: Reference to parent node. This is set during LINK time |
18026 |
++ * and is dropped during destruction. You must not access |
18027 |
++ * it unless you hold an active reference to the node or if |
18028 |
++ * you know the node is dead. |
18029 |
++ * * node->children: rb-tree of all linked children of this node. You must |
18030 |
++ * not access this directly, but use one of the iterator |
18031 |
++ * or lookup helpers. |
18032 |
++ */ |
18033 |
++ |
18034 |
++/* |
18035 |
++ * Bias values track states of "active references". They're all negative. If a |
18036 |
++ * node is active, its active-ref-counter is >=0 and tracks all active |
18037 |
++ * references. Once a node is deactivaed, we subtract NODE_BIAS. This means, the |
18038 |
++ * counter is now negative but still counts the active references. Once it drops |
18039 |
++ * to exactly NODE_BIAS, we know all active references were dropped. Exactly one |
18040 |
++ * thread will change it to NODE_RELEASE now, perform cleanup and then put it |
18041 |
++ * into NODE_DRAINED. Once drained, all other threads that tried deactivating |
18042 |
++ * the node will now be woken up (thus, they wait until the node is fully done). |
18043 |
++ * The initial state during node-setup is NODE_NEW. If a node is directly |
18044 |
++ * deactivated without having ever been active, it is put into |
18045 |
++ * NODE_RELEASE_DIRECT instead of NODE_BIAS. This tracks this one-bit state |
18046 |
++ * across node-deactivation. The task putting it into NODE_RELEASE now knows |
18047 |
++ * whether the node was active before or not. |
18048 |
++ * |
18049 |
++ * Some archs implement atomic_sub(v) with atomic_add(-v), so reserve INT_MIN |
18050 |
++ * to avoid overflows if multiplied by -1. |
18051 |
++ */ |
18052 |
++#define KDBUS_NODE_BIAS (INT_MIN + 5) |
18053 |
++#define KDBUS_NODE_RELEASE_DIRECT (KDBUS_NODE_BIAS - 1) |
18054 |
++#define KDBUS_NODE_RELEASE (KDBUS_NODE_BIAS - 2) |
18055 |
++#define KDBUS_NODE_DRAINED (KDBUS_NODE_BIAS - 3) |
18056 |
++#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4) |
18057 |
++ |
18058 |
++/* global unique ID mapping for kdbus nodes */ |
18059 |
++static DEFINE_IDR(kdbus_node_idr); |
18060 |
++static DECLARE_RWSEM(kdbus_node_idr_lock); |
18061 |
++ |
18062 |
++/** |
18063 |
++ * kdbus_node_name_hash() - hash a name |
18064 |
++ * @name: The string to hash |
18065 |
++ * |
18066 |
++ * This computes the hash of @name. It is guaranteed to be in the range |
18067 |
++ * [2..INT_MAX-1]. The values 1, 2 and INT_MAX are unused as they are reserved |
18068 |
++ * for the filesystem code. |
18069 |
++ * |
18070 |
++ * Return: hash value of the passed string |
18071 |
++ */ |
18072 |
++static unsigned int kdbus_node_name_hash(const char *name) |
18073 |
++{ |
18074 |
++ unsigned int hash; |
18075 |
++ |
18076 |
++ /* reserve hash numbers 0, 1 and >=INT_MAX for magic directories */ |
18077 |
++ hash = kdbus_strhash(name) & INT_MAX; |
18078 |
++ if (hash < 2) |
18079 |
++ hash += 2; |
18080 |
++ if (hash >= INT_MAX) |
18081 |
++ hash = INT_MAX - 1; |
18082 |
++ |
18083 |
++ return hash; |
18084 |
++} |
18085 |
++ |
18086 |
++/** |
18087 |
++ * kdbus_node_name_compare() - compare a name with a node's name |
18088 |
++ * @hash: hash of the string to compare the node with |
18089 |
++ * @name: name to compare the node with |
18090 |
++ * @node: node to compare the name with |
18091 |
++ * |
18092 |
++ * Return: 0 if @name and @hash exactly match the information in @node, or |
18093 |
++ * an integer less than or greater than zero if @name is found, respectively, |
18094 |
++ * to be less than or be greater than the string stored in @node. |
18095 |
++ */ |
18096 |
++static int kdbus_node_name_compare(unsigned int hash, const char *name, |
18097 |
++ const struct kdbus_node *node) |
18098 |
++{ |
18099 |
++ if (hash != node->hash) |
18100 |
++ return hash - node->hash; |
18101 |
++ |
18102 |
++ return strcmp(name, node->name); |
18103 |
++} |
18104 |
++ |
18105 |
++/** |
18106 |
++ * kdbus_node_init() - initialize a kdbus_node |
18107 |
++ * @node: Pointer to the node to initialize |
18108 |
++ * @type: The type the node will have (KDBUS_NODE_*) |
18109 |
++ * |
18110 |
++ * The caller is responsible of allocating @node and initializating it to zero. |
18111 |
++ * Once this call returns, you must use the node_ref() and node_unref() |
18112 |
++ * functions to manage this node. |
18113 |
++ */ |
18114 |
++void kdbus_node_init(struct kdbus_node *node, unsigned int type) |
18115 |
++{ |
18116 |
++ atomic_set(&node->refcnt, 1); |
18117 |
++ mutex_init(&node->lock); |
18118 |
++ node->id = 0; |
18119 |
++ node->type = type; |
18120 |
++ RB_CLEAR_NODE(&node->rb); |
18121 |
++ node->children = RB_ROOT; |
18122 |
++ init_waitqueue_head(&node->waitq); |
18123 |
++ atomic_set(&node->active, KDBUS_NODE_NEW); |
18124 |
++} |
18125 |
++ |
18126 |
++/** |
18127 |
++ * kdbus_node_link() - link a node into the nodes system |
18128 |
++ * @node: Pointer to the node to initialize |
18129 |
++ * @parent: Pointer to a parent node, may be %NULL |
18130 |
++ * @name: The name of the node (or NULL if root node) |
18131 |
++ * |
18132 |
++ * This links a node into the hierarchy. This must not be called multiple times. |
18133 |
++ * If @parent is NULL, the node becomes a new root node. |
18134 |
++ * |
18135 |
++ * This call will fail if @name is not unique across all its siblings or if no |
18136 |
++ * ID could be allocated. You must not activate a node if linking failed! It is |
18137 |
++ * safe to deactivate it, though. |
18138 |
++ * |
18139 |
++ * Once you linked a node, you must call kdbus_node_deactivate() before you drop |
18140 |
++ * the last reference (even if you never activate the node). |
18141 |
++ * |
18142 |
++ * Return: 0 on success. negative error otherwise. |
18143 |
++ */ |
18144 |
++int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, |
18145 |
++ const char *name) |
18146 |
++{ |
18147 |
++ int ret; |
18148 |
++ |
18149 |
++ if (WARN_ON(node->type != KDBUS_NODE_DOMAIN && !parent)) |
18150 |
++ return -EINVAL; |
18151 |
++ |
18152 |
++ if (WARN_ON(parent && !name)) |
18153 |
++ return -EINVAL; |
18154 |
++ |
18155 |
++ if (name) { |
18156 |
++ node->name = kstrdup(name, GFP_KERNEL); |
18157 |
++ if (!node->name) |
18158 |
++ return -ENOMEM; |
18159 |
++ |
18160 |
++ node->hash = kdbus_node_name_hash(name); |
18161 |
++ } |
18162 |
++ |
18163 |
++ down_write(&kdbus_node_idr_lock); |
18164 |
++ ret = idr_alloc(&kdbus_node_idr, node, 1, 0, GFP_KERNEL); |
18165 |
++ if (ret >= 0) |
18166 |
++ node->id = ret; |
18167 |
++ up_write(&kdbus_node_idr_lock); |
18168 |
++ |
18169 |
++ if (ret < 0) |
18170 |
++ return ret; |
18171 |
++ |
18172 |
++ ret = 0; |
18173 |
++ |
18174 |
++ if (parent) { |
18175 |
++ struct rb_node **n, *prev; |
18176 |
++ |
18177 |
++ if (!kdbus_node_acquire(parent)) |
18178 |
++ return -ESHUTDOWN; |
18179 |
++ |
18180 |
++ mutex_lock(&parent->lock); |
18181 |
++ |
18182 |
++ n = &parent->children.rb_node; |
18183 |
++ prev = NULL; |
18184 |
++ |
18185 |
++ while (*n) { |
18186 |
++ struct kdbus_node *pos; |
18187 |
++ int result; |
18188 |
++ |
18189 |
++ pos = kdbus_node_from_rb(*n); |
18190 |
++ prev = *n; |
18191 |
++ result = kdbus_node_name_compare(node->hash, |
18192 |
++ node->name, |
18193 |
++ pos); |
18194 |
++ if (result == 0) { |
18195 |
++ ret = -EEXIST; |
18196 |
++ goto exit_unlock; |
18197 |
++ } |
18198 |
++ |
18199 |
++ if (result < 0) |
18200 |
++ n = &pos->rb.rb_left; |
18201 |
++ else |
18202 |
++ n = &pos->rb.rb_right; |
18203 |
++ } |
18204 |
++ |
18205 |
++ /* add new node and rebalance the tree */ |
18206 |
++ rb_link_node(&node->rb, prev, n); |
18207 |
++ rb_insert_color(&node->rb, &parent->children); |
18208 |
++ node->parent = kdbus_node_ref(parent); |
18209 |
++ |
18210 |
++exit_unlock: |
18211 |
++ mutex_unlock(&parent->lock); |
18212 |
++ kdbus_node_release(parent); |
18213 |
++ } |
18214 |
++ |
18215 |
++ return ret; |
18216 |
++} |
18217 |
++ |
18218 |
++/** |
18219 |
++ * kdbus_node_ref() - Acquire object reference |
18220 |
++ * @node: node to acquire reference to (or NULL) |
18221 |
++ * |
18222 |
++ * This acquires a new reference to @node. You must already own a reference when |
18223 |
++ * calling this! |
18224 |
++ * If @node is NULL, this is a no-op. |
18225 |
++ * |
18226 |
++ * Return: @node is returned |
18227 |
++ */ |
18228 |
++struct kdbus_node *kdbus_node_ref(struct kdbus_node *node) |
18229 |
++{ |
18230 |
++ if (node) |
18231 |
++ atomic_inc(&node->refcnt); |
18232 |
++ return node; |
18233 |
++} |
18234 |
++ |
18235 |
++/** |
18236 |
++ * kdbus_node_unref() - Drop object reference |
18237 |
++ * @node: node to drop reference to (or NULL) |
18238 |
++ * |
18239 |
++ * This drops an object reference to @node. You must not access the node if you |
18240 |
++ * no longer own a reference. |
18241 |
++ * If the ref-count drops to 0, the object will be destroyed (->free_cb will be |
18242 |
++ * called). |
18243 |
++ * |
18244 |
++ * If you linked or activated the node, you must deactivate the node before you |
18245 |
++ * drop your last reference! If you didn't link or activate the node, you can |
18246 |
++ * drop any reference you want. |
18247 |
++ * |
18248 |
++ * Note that this calls into ->free_cb() and thus _might_ sleep. The ->free_cb() |
18249 |
++ * callbacks must not acquire any outer locks, though. So you can safely drop |
18250 |
++ * references while holding locks. |
18251 |
++ * |
18252 |
++ * If @node is NULL, this is a no-op. |
18253 |
++ * |
18254 |
++ * Return: This always returns NULL |
18255 |
++ */ |
18256 |
++struct kdbus_node *kdbus_node_unref(struct kdbus_node *node) |
18257 |
++{ |
18258 |
++ if (node && atomic_dec_and_test(&node->refcnt)) { |
18259 |
++ struct kdbus_node safe = *node; |
18260 |
++ |
18261 |
++ WARN_ON(atomic_read(&node->active) != KDBUS_NODE_DRAINED); |
18262 |
++ WARN_ON(!RB_EMPTY_NODE(&node->rb)); |
18263 |
++ |
18264 |
++ if (node->free_cb) |
18265 |
++ node->free_cb(node); |
18266 |
++ |
18267 |
++ down_write(&kdbus_node_idr_lock); |
18268 |
++ if (safe.id > 0) |
18269 |
++ idr_remove(&kdbus_node_idr, safe.id); |
18270 |
++ /* drop caches after last node to not leak memory on unload */ |
18271 |
++ if (idr_is_empty(&kdbus_node_idr)) { |
18272 |
++ idr_destroy(&kdbus_node_idr); |
18273 |
++ idr_init(&kdbus_node_idr); |
18274 |
++ } |
18275 |
++ up_write(&kdbus_node_idr_lock); |
18276 |
++ |
18277 |
++ kfree(safe.name); |
18278 |
++ |
18279 |
++ /* |
18280 |
++ * kdbusfs relies on the parent to be available even after the |
18281 |
++ * node was deactivated and unlinked. Therefore, we pin it |
18282 |
++ * until a node is destroyed. |
18283 |
++ */ |
18284 |
++ kdbus_node_unref(safe.parent); |
18285 |
++ } |
18286 |
++ |
18287 |
++ return NULL; |
18288 |
++} |
18289 |
++ |
18290 |
++/** |
18291 |
++ * kdbus_node_is_active() - test whether a node is active |
18292 |
++ * @node: node to test |
18293 |
++ * |
18294 |
++ * This checks whether @node is active. That means, @node was linked and |
18295 |
++ * activated by the node owner and hasn't been deactivated, yet. If, and only |
18296 |
++ * if, a node is active, kdbus_node_acquire() will be able to acquire active |
18297 |
++ * references. |
18298 |
++ * |
18299 |
++ * Note that this function does not give any lifetime guarantees. After this |
18300 |
++ * call returns, the node might be deactivated immediately. Normally, what you |
18301 |
++ * want is to acquire a real active reference via kdbus_node_acquire(). |
18302 |
++ * |
18303 |
++ * Return: true if @node is active, false otherwise |
18304 |
++ */ |
18305 |
++bool kdbus_node_is_active(struct kdbus_node *node) |
18306 |
++{ |
18307 |
++ return atomic_read(&node->active) >= 0; |
18308 |
++} |
18309 |
++ |
18310 |
++/** |
18311 |
++ * kdbus_node_is_deactivated() - test whether a node was already deactivated |
18312 |
++ * @node: node to test |
18313 |
++ * |
18314 |
++ * This checks whether kdbus_node_deactivate() was called on @node. Note that |
18315 |
++ * this might be true even if you never deactivated the node directly, but only |
18316 |
++ * one of its ancestors. |
18317 |
++ * |
18318 |
++ * Note that even if this returns 'false', the node might get deactivated |
18319 |
++ * immediately after the call returns. |
18320 |
++ * |
18321 |
++ * Return: true if @node was already deactivated, false if not |
18322 |
++ */ |
18323 |
++bool kdbus_node_is_deactivated(struct kdbus_node *node) |
18324 |
++{ |
18325 |
++ int v; |
18326 |
++ |
18327 |
++ v = atomic_read(&node->active); |
18328 |
++ return v != KDBUS_NODE_NEW && v < 0; |
18329 |
++} |
18330 |
++ |
18331 |
++/** |
18332 |
++ * kdbus_node_activate() - activate a node |
18333 |
++ * @node: node to activate |
18334 |
++ * |
18335 |
++ * This marks @node as active if, and only if, the node wasn't activated nor |
18336 |
++ * deactivated, yet, and the parent is still active. Any but the first call to |
18337 |
++ * kdbus_node_activate() is a no-op. |
18338 |
++ * If you called kdbus_node_deactivate() before, then even the first call to |
18339 |
++ * kdbus_node_activate() will be a no-op. |
18340 |
++ * |
18341 |
++ * This call doesn't give any lifetime guarantees. The node might get |
18342 |
++ * deactivated immediately after this call returns. Or the parent might already |
18343 |
++ * be deactivated, which will make this call a no-op. |
18344 |
++ * |
18345 |
++ * If this call successfully activated a node, it will take an object reference |
18346 |
++ * to it. This reference is dropped after the node is deactivated. Therefore, |
18347 |
++ * the object owner can safely drop their reference to @node iff they know that |
18348 |
++ * its parent node will get deactivated at some point. Once the parent node is |
18349 |
++ * deactivated, it will deactivate all its child and thus drop this reference |
18350 |
++ * again. |
18351 |
++ * |
18352 |
++ * Return: True if this call successfully activated the node, otherwise false. |
18353 |
++ * Note that this might return false, even if the node is still active |
18354 |
++ * (eg., if you called this a second time). |
18355 |
++ */ |
18356 |
++bool kdbus_node_activate(struct kdbus_node *node) |
18357 |
++{ |
18358 |
++ bool res = false; |
18359 |
++ |
18360 |
++ mutex_lock(&node->lock); |
18361 |
++ if (atomic_read(&node->active) == KDBUS_NODE_NEW) { |
18362 |
++ atomic_sub(KDBUS_NODE_NEW, &node->active); |
18363 |
++ /* activated nodes have ref +1 */ |
18364 |
++ kdbus_node_ref(node); |
18365 |
++ res = true; |
18366 |
++ } |
18367 |
++ mutex_unlock(&node->lock); |
18368 |
++ |
18369 |
++ return res; |
18370 |
++} |
18371 |
++ |
18372 |
++/** |
18373 |
++ * kdbus_node_deactivate() - deactivate a node |
18374 |
++ * @node: The node to deactivate. |
18375 |
++ * |
18376 |
++ * This function recursively deactivates this node and all its children. It |
18377 |
++ * returns only once all children and the node itself were recursively disabled |
18378 |
++ * (even if you call this function multiple times in parallel). |
18379 |
++ * |
18380 |
++ * It is safe to call this function on _any_ node that was initialized _any_ |
18381 |
++ * number of times. |
18382 |
++ * |
18383 |
++ * This call may sleep, as it waits for all active references to be dropped. |
18384 |
++ */ |
18385 |
++void kdbus_node_deactivate(struct kdbus_node *node) |
18386 |
++{ |
18387 |
++ struct kdbus_node *pos, *child; |
18388 |
++ struct rb_node *rb; |
18389 |
++ int v_pre, v_post; |
18390 |
++ |
18391 |
++ pos = node; |
18392 |
++ |
18393 |
++ /* |
18394 |
++ * To avoid recursion, we perform back-tracking while deactivating |
18395 |
++ * nodes. For each node we enter, we first mark the active-counter as |
18396 |
++ * deactivated by adding BIAS. If the node as children, we set the first |
18397 |
++ * child as current position and start over. If the node has no |
18398 |
++ * children, we drain the node by waiting for all active refs to be |
18399 |
++ * dropped and then releasing the node. |
18400 |
++ * |
18401 |
++ * After the node is released, we set its parent as current position |
18402 |
++ * and start over. If the current position was the initial node, we're |
18403 |
++ * done. |
18404 |
++ * |
18405 |
++ * Note that this function can be called in parallel by multiple |
18406 |
++ * callers. We make sure that each node is only released once, and any |
18407 |
++ * racing caller will wait until the other thread fully released that |
18408 |
++ * node. |
18409 |
++ */ |
18410 |
++ |
18411 |
++ for (;;) { |
18412 |
++ /* |
18413 |
++ * Add BIAS to node->active to mark it as inactive. If it was |
18414 |
++ * never active before, immediately mark it as RELEASE_INACTIVE |
18415 |
++ * so we remember this state. |
18416 |
++ * We cannot remember v_pre as we might iterate into the |
18417 |
++ * children, overwriting v_pre, before we can release our node. |
18418 |
++ */ |
18419 |
++ mutex_lock(&pos->lock); |
18420 |
++ v_pre = atomic_read(&pos->active); |
18421 |
++ if (v_pre >= 0) |
18422 |
++ atomic_add_return(KDBUS_NODE_BIAS, &pos->active); |
18423 |
++ else if (v_pre == KDBUS_NODE_NEW) |
18424 |
++ atomic_set(&pos->active, KDBUS_NODE_RELEASE_DIRECT); |
18425 |
++ mutex_unlock(&pos->lock); |
18426 |
++ |
18427 |
++ /* wait until all active references were dropped */ |
18428 |
++ wait_event(pos->waitq, |
18429 |
++ atomic_read(&pos->active) <= KDBUS_NODE_BIAS); |
18430 |
++ |
18431 |
++ mutex_lock(&pos->lock); |
18432 |
++ /* recurse into first child if any */ |
18433 |
++ rb = rb_first(&pos->children); |
18434 |
++ if (rb) { |
18435 |
++ child = kdbus_node_ref(kdbus_node_from_rb(rb)); |
18436 |
++ mutex_unlock(&pos->lock); |
18437 |
++ pos = child; |
18438 |
++ continue; |
18439 |
++ } |
18440 |
++ |
18441 |
++ /* mark object as RELEASE */ |
18442 |
++ v_post = atomic_read(&pos->active); |
18443 |
++ if (v_post == KDBUS_NODE_BIAS || |
18444 |
++ v_post == KDBUS_NODE_RELEASE_DIRECT) |
18445 |
++ atomic_set(&pos->active, KDBUS_NODE_RELEASE); |
18446 |
++ mutex_unlock(&pos->lock); |
18447 |
++ |
18448 |
++ /* |
18449 |
++ * If this is the thread that marked the object as RELEASE, we |
18450 |
++ * perform the actual release. Otherwise, we wait until the |
18451 |
++ * release is done and the node is marked as DRAINED. |
18452 |
++ */ |
18453 |
++ if (v_post == KDBUS_NODE_BIAS || |
18454 |
++ v_post == KDBUS_NODE_RELEASE_DIRECT) { |
18455 |
++ if (pos->release_cb) |
18456 |
++ pos->release_cb(pos, v_post == KDBUS_NODE_BIAS); |
18457 |
++ |
18458 |
++ if (pos->parent) { |
18459 |
++ mutex_lock(&pos->parent->lock); |
18460 |
++ if (!RB_EMPTY_NODE(&pos->rb)) { |
18461 |
++ rb_erase(&pos->rb, |
18462 |
++ &pos->parent->children); |
18463 |
++ RB_CLEAR_NODE(&pos->rb); |
18464 |
++ } |
18465 |
++ mutex_unlock(&pos->parent->lock); |
18466 |
++ } |
18467 |
++ |
18468 |
++ /* mark as DRAINED */ |
18469 |
++ atomic_set(&pos->active, KDBUS_NODE_DRAINED); |
18470 |
++ wake_up_all(&pos->waitq); |
18471 |
++ |
18472 |
++ /* drop VFS cache */ |
18473 |
++ kdbus_fs_flush(pos); |
18474 |
++ |
18475 |
++ /* |
18476 |
++ * If the node was activated and somone subtracted BIAS |
18477 |
++ * from it to deactivate it, we, and only us, are |
18478 |
++ * responsible to release the extra ref-count that was |
18479 |
++ * taken once in kdbus_node_activate(). |
18480 |
++ * If the node was never activated, no-one ever |
18481 |
++ * subtracted BIAS, but instead skipped that state and |
18482 |
++ * immediately went to NODE_RELEASE_DIRECT. In that case |
18483 |
++ * we must not drop the reference. |
18484 |
++ */ |
18485 |
++ if (v_post == KDBUS_NODE_BIAS) |
18486 |
++ kdbus_node_unref(pos); |
18487 |
++ } else { |
18488 |
++ /* wait until object is DRAINED */ |
18489 |
++ wait_event(pos->waitq, |
18490 |
++ atomic_read(&pos->active) == KDBUS_NODE_DRAINED); |
18491 |
++ } |
18492 |
++ |
18493 |
++ /* |
18494 |
++ * We're done with the current node. Continue on its parent |
18495 |
++ * again, which will try deactivating its next child, or itself |
18496 |
++ * if no child is left. |
18497 |
++ * If we've reached our initial node again, we are done and |
18498 |
++ * can safely return. |
18499 |
++ */ |
18500 |
++ if (pos == node) |
18501 |
++ break; |
18502 |
++ |
18503 |
++ child = pos; |
18504 |
++ pos = pos->parent; |
18505 |
++ kdbus_node_unref(child); |
18506 |
++ } |
18507 |
++} |
18508 |
++ |
18509 |
++/** |
18510 |
++ * kdbus_node_acquire() - Acquire an active ref on a node |
18511 |
++ * @node: The node |
18512 |
++ * |
18513 |
++ * This acquires an active-reference to @node. This will only succeed if the |
18514 |
++ * node is active. You must release this active reference via |
18515 |
++ * kdbus_node_release() again. |
18516 |
++ * |
18517 |
++ * See the introduction to "active references" for more details. |
18518 |
++ * |
18519 |
++ * Return: %true if @node was non-NULL and active |
18520 |
++ */ |
18521 |
++bool kdbus_node_acquire(struct kdbus_node *node) |
18522 |
++{ |
18523 |
++ return node && atomic_inc_unless_negative(&node->active); |
18524 |
++} |
18525 |
++ |
18526 |
++/** |
18527 |
++ * kdbus_node_release() - Release an active ref on a node |
18528 |
++ * @node: The node |
18529 |
++ * |
18530 |
++ * This releases an active reference that was previously acquired via |
18531 |
++ * kdbus_node_acquire(). See kdbus_node_acquire() for details. |
18532 |
++ */ |
18533 |
++void kdbus_node_release(struct kdbus_node *node) |
18534 |
++{ |
18535 |
++ if (node && atomic_dec_return(&node->active) == KDBUS_NODE_BIAS) |
18536 |
++ wake_up(&node->waitq); |
18537 |
++} |
18538 |
++ |
18539 |
++/** |
18540 |
++ * kdbus_node_find_child() - Find child by name |
18541 |
++ * @node: parent node to search through |
18542 |
++ * @name: name of child node |
18543 |
++ * |
18544 |
++ * This searches through all children of @node for a child-node with name @name. |
18545 |
++ * If not found, or if the child is deactivated, NULL is returned. Otherwise, |
18546 |
++ * the child is acquired and a new reference is returned. |
18547 |
++ * |
18548 |
++ * If you're done with the child, you need to release it and drop your |
18549 |
++ * reference. |
18550 |
++ * |
18551 |
++ * This function does not acquire the parent node. However, if the parent was |
18552 |
++ * already deactivated, then kdbus_node_deactivate() will, at some point, also |
18553 |
++ * deactivate the child. Therefore, we can rely on the explicit ordering during |
18554 |
++ * deactivation. |
18555 |
++ * |
18556 |
++ * Return: Reference to acquired child node, or NULL if not found / not active. |
18557 |
++ */ |
18558 |
++struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, |
18559 |
++ const char *name) |
18560 |
++{ |
18561 |
++ struct kdbus_node *child; |
18562 |
++ struct rb_node *rb; |
18563 |
++ unsigned int hash; |
18564 |
++ int ret; |
18565 |
++ |
18566 |
++ hash = kdbus_node_name_hash(name); |
18567 |
++ |
18568 |
++ mutex_lock(&node->lock); |
18569 |
++ rb = node->children.rb_node; |
18570 |
++ while (rb) { |
18571 |
++ child = kdbus_node_from_rb(rb); |
18572 |
++ ret = kdbus_node_name_compare(hash, name, child); |
18573 |
++ if (ret < 0) |
18574 |
++ rb = rb->rb_left; |
18575 |
++ else if (ret > 0) |
18576 |
++ rb = rb->rb_right; |
18577 |
++ else |
18578 |
++ break; |
18579 |
++ } |
18580 |
++ if (rb && kdbus_node_acquire(child)) |
18581 |
++ kdbus_node_ref(child); |
18582 |
++ else |
18583 |
++ child = NULL; |
18584 |
++ mutex_unlock(&node->lock); |
18585 |
++ |
18586 |
++ return child; |
18587 |
++} |
18588 |
++ |
18589 |
++static struct kdbus_node *node_find_closest_unlocked(struct kdbus_node *node, |
18590 |
++ unsigned int hash, |
18591 |
++ const char *name) |
18592 |
++{ |
18593 |
++ struct kdbus_node *n, *pos = NULL; |
18594 |
++ struct rb_node *rb; |
18595 |
++ int res; |
18596 |
++ |
18597 |
++ /* |
18598 |
++ * Find the closest child with ``node->hash >= hash'', or, if @name is |
18599 |
++ * valid, ``node->name >= name'' (where '>=' is the lex. order). |
18600 |
++ */ |
18601 |
++ |
18602 |
++ rb = node->children.rb_node; |
18603 |
++ while (rb) { |
18604 |
++ n = kdbus_node_from_rb(rb); |
18605 |
++ |
18606 |
++ if (name) |
18607 |
++ res = kdbus_node_name_compare(hash, name, n); |
18608 |
++ else |
18609 |
++ res = hash - n->hash; |
18610 |
++ |
18611 |
++ if (res <= 0) { |
18612 |
++ rb = rb->rb_left; |
18613 |
++ pos = n; |
18614 |
++ } else { /* ``hash > n->hash'', ``name > n->name'' */ |
18615 |
++ rb = rb->rb_right; |
18616 |
++ } |
18617 |
++ } |
18618 |
++ |
18619 |
++ return pos; |
18620 |
++} |
18621 |
++ |
18622 |
++/** |
18623 |
++ * kdbus_node_find_closest() - Find closest child-match |
18624 |
++ * @node: parent node to search through |
18625 |
++ * @hash: hash value to find closest match for |
18626 |
++ * |
18627 |
++ * Find the closest child of @node with a hash greater than or equal to @hash. |
18628 |
++ * The closest match is the left-most child of @node with this property. Which |
18629 |
++ * means, it is the first child with that hash returned by |
18630 |
++ * kdbus_node_next_child(), if you'd iterate the whole parent node. |
18631 |
++ * |
18632 |
++ * Return: Reference to acquired child, or NULL if none found. |
18633 |
++ */ |
18634 |
++struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, |
18635 |
++ unsigned int hash) |
18636 |
++{ |
18637 |
++ struct kdbus_node *child; |
18638 |
++ struct rb_node *rb; |
18639 |
++ |
18640 |
++ mutex_lock(&node->lock); |
18641 |
++ |
18642 |
++ child = node_find_closest_unlocked(node, hash, NULL); |
18643 |
++ while (child && !kdbus_node_acquire(child)) { |
18644 |
++ rb = rb_next(&child->rb); |
18645 |
++ if (rb) |
18646 |
++ child = kdbus_node_from_rb(rb); |
18647 |
++ else |
18648 |
++ child = NULL; |
18649 |
++ } |
18650 |
++ kdbus_node_ref(child); |
18651 |
++ |
18652 |
++ mutex_unlock(&node->lock); |
18653 |
++ |
18654 |
++ return child; |
18655 |
++} |
18656 |
++ |
18657 |
++/** |
18658 |
++ * kdbus_node_next_child() - Acquire next child |
18659 |
++ * @node: parent node |
18660 |
++ * @prev: previous child-node position or NULL |
18661 |
++ * |
18662 |
++ * This function returns a reference to the next active child of @node, after |
18663 |
++ * the passed position @prev. If @prev is NULL, a reference to the first active |
18664 |
++ * child is returned. If no more active children are found, NULL is returned. |
18665 |
++ * |
18666 |
++ * This function acquires the next child it returns. If you're done with the |
18667 |
++ * returned pointer, you need to release _and_ unref it. |
18668 |
++ * |
18669 |
++ * The passed in pointer @prev is not modified by this function, and it does |
18670 |
++ * *not* have to be active. If @prev was acquired via different means, or if it |
18671 |
++ * was unlinked from its parent before you pass it in, then this iterator will |
18672 |
++ * still return the next active child (it will have to search through the |
18673 |
++ * rb-tree based on the node-name, though). |
18674 |
++ * However, @prev must not be linked to a different parent than @node! |
18675 |
++ * |
18676 |
++ * Return: Reference to next acquired child, or NULL if at the end. |
18677 |
++ */ |
18678 |
++struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, |
18679 |
++ struct kdbus_node *prev) |
18680 |
++{ |
18681 |
++ struct kdbus_node *pos = NULL; |
18682 |
++ struct rb_node *rb; |
18683 |
++ |
18684 |
++ mutex_lock(&node->lock); |
18685 |
++ |
18686 |
++ if (!prev) { |
18687 |
++ /* |
18688 |
++ * New iteration; find first node in rb-tree and try to acquire |
18689 |
++ * it. If we got it, directly return it as first element. |
18690 |
++ * Otherwise, the loop below will find the next active node. |
18691 |
++ */ |
18692 |
++ rb = rb_first(&node->children); |
18693 |
++ if (!rb) |
18694 |
++ goto exit; |
18695 |
++ pos = kdbus_node_from_rb(rb); |
18696 |
++ if (kdbus_node_acquire(pos)) |
18697 |
++ goto exit; |
18698 |
++ } else if (RB_EMPTY_NODE(&prev->rb)) { |
18699 |
++ /* |
18700 |
++ * The current iterator is no longer linked to the rb-tree. Use |
18701 |
++ * its hash value and name to find the next _higher_ node and |
18702 |
++ * acquire it. If we got it, return it as next element. |
18703 |
++ * Otherwise, the loop below will find the next active node. |
18704 |
++ */ |
18705 |
++ pos = node_find_closest_unlocked(node, prev->hash, prev->name); |
18706 |
++ if (!pos) |
18707 |
++ goto exit; |
18708 |
++ if (kdbus_node_acquire(pos)) |
18709 |
++ goto exit; |
18710 |
++ } else { |
18711 |
++ /* |
18712 |
++ * The current iterator is still linked to the parent. Set it |
18713 |
++ * as current position and use the loop below to find the next |
18714 |
++ * active element. |
18715 |
++ */ |
18716 |
++ pos = prev; |
18717 |
++ } |
18718 |
++ |
18719 |
++ /* @pos was already returned or is inactive; find next active node */ |
18720 |
++ do { |
18721 |
++ rb = rb_next(&pos->rb); |
18722 |
++ if (rb) |
18723 |
++ pos = kdbus_node_from_rb(rb); |
18724 |
++ else |
18725 |
++ pos = NULL; |
18726 |
++ } while (pos && !kdbus_node_acquire(pos)); |
18727 |
++ |
18728 |
++exit: |
18729 |
++ /* @pos is NULL or acquired. Take ref if non-NULL and return it */ |
18730 |
++ kdbus_node_ref(pos); |
18731 |
++ mutex_unlock(&node->lock); |
18732 |
++ return pos; |
18733 |
++} |
18734 |
+diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h |
18735 |
+new file mode 100644 |
18736 |
+index 0000000..be125ce |
18737 |
+--- /dev/null |
18738 |
++++ b/ipc/kdbus/node.h |
18739 |
+@@ -0,0 +1,84 @@ |
18740 |
++/* |
18741 |
++ * Copyright (C) 2013-2015 Kay Sievers |
18742 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
18743 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
18744 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
18745 |
++ * Copyright (C) 2013-2015 Linux Foundation |
18746 |
++ * |
18747 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
18748 |
++ * the terms of the GNU Lesser General Public License as published by the |
18749 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
18750 |
++ * your option) any later version. |
18751 |
++ */ |
18752 |
++ |
18753 |
++#ifndef __KDBUS_NODE_H |
18754 |
++#define __KDBUS_NODE_H |
18755 |
++ |
18756 |
++#include <linux/atomic.h> |
18757 |
++#include <linux/kernel.h> |
18758 |
++#include <linux/mutex.h> |
18759 |
++#include <linux/wait.h> |
18760 |
++ |
18761 |
++struct kdbus_node; |
18762 |
++ |
18763 |
++enum kdbus_node_type { |
18764 |
++ KDBUS_NODE_DOMAIN, |
18765 |
++ KDBUS_NODE_CONTROL, |
18766 |
++ KDBUS_NODE_BUS, |
18767 |
++ KDBUS_NODE_ENDPOINT, |
18768 |
++}; |
18769 |
++ |
18770 |
++typedef void (*kdbus_node_free_t) (struct kdbus_node *node); |
18771 |
++typedef void (*kdbus_node_release_t) (struct kdbus_node *node, bool was_active); |
18772 |
++ |
18773 |
++struct kdbus_node { |
18774 |
++ atomic_t refcnt; |
18775 |
++ atomic_t active; |
18776 |
++ wait_queue_head_t waitq; |
18777 |
++ |
18778 |
++ /* static members */ |
18779 |
++ unsigned int type; |
18780 |
++ kdbus_node_free_t free_cb; |
18781 |
++ kdbus_node_release_t release_cb; |
18782 |
++ umode_t mode; |
18783 |
++ kuid_t uid; |
18784 |
++ kgid_t gid; |
18785 |
++ |
18786 |
++ /* valid once linked */ |
18787 |
++ char *name; |
18788 |
++ unsigned int hash; |
18789 |
++ unsigned int id; |
18790 |
++ struct kdbus_node *parent; /* may be NULL */ |
18791 |
++ |
18792 |
++ /* valid iff active */ |
18793 |
++ struct mutex lock; |
18794 |
++ struct rb_node rb; |
18795 |
++ struct rb_root children; |
18796 |
++}; |
18797 |
++ |
18798 |
++#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb) |
18799 |
++ |
18800 |
++void kdbus_node_init(struct kdbus_node *node, unsigned int type); |
18801 |
++ |
18802 |
++int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, |
18803 |
++ const char *name); |
18804 |
++ |
18805 |
++struct kdbus_node *kdbus_node_ref(struct kdbus_node *node); |
18806 |
++struct kdbus_node *kdbus_node_unref(struct kdbus_node *node); |
18807 |
++ |
18808 |
++bool kdbus_node_is_active(struct kdbus_node *node); |
18809 |
++bool kdbus_node_is_deactivated(struct kdbus_node *node); |
18810 |
++bool kdbus_node_activate(struct kdbus_node *node); |
18811 |
++void kdbus_node_deactivate(struct kdbus_node *node); |
18812 |
++ |
18813 |
++bool kdbus_node_acquire(struct kdbus_node *node); |
18814 |
++void kdbus_node_release(struct kdbus_node *node); |
18815 |
++ |
18816 |
++struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, |
18817 |
++ const char *name); |
18818 |
++struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, |
18819 |
++ unsigned int hash); |
18820 |
++struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, |
18821 |
++ struct kdbus_node *prev); |
18822 |
++ |
18823 |
++#endif |
18824 |
+diff --git a/ipc/kdbus/notify.c b/ipc/kdbus/notify.c |
18825 |
+new file mode 100644 |
18826 |
+index 0000000..e4a4542 |
18827 |
+--- /dev/null |
18828 |
++++ b/ipc/kdbus/notify.c |
18829 |
+@@ -0,0 +1,248 @@ |
18830 |
++/* |
18831 |
++ * Copyright (C) 2013-2015 Kay Sievers |
18832 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
18833 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
18834 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
18835 |
++ * Copyright (C) 2013-2015 Linux Foundation |
18836 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
18837 |
++ * |
18838 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
18839 |
++ * the terms of the GNU Lesser General Public License as published by the |
18840 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
18841 |
++ * your option) any later version. |
18842 |
++ */ |
18843 |
++ |
18844 |
++#include <linux/fs.h> |
18845 |
++#include <linux/init.h> |
18846 |
++#include <linux/module.h> |
18847 |
++#include <linux/mutex.h> |
18848 |
++#include <linux/spinlock.h> |
18849 |
++#include <linux/sched.h> |
18850 |
++#include <linux/slab.h> |
18851 |
++ |
18852 |
++#include "bus.h" |
18853 |
++#include "connection.h" |
18854 |
++#include "domain.h" |
18855 |
++#include "endpoint.h" |
18856 |
++#include "item.h" |
18857 |
++#include "message.h" |
18858 |
++#include "notify.h" |
18859 |
++ |
18860 |
++static inline void kdbus_notify_add_tail(struct kdbus_kmsg *kmsg, |
18861 |
++ struct kdbus_bus *bus) |
18862 |
++{ |
18863 |
++ spin_lock(&bus->notify_lock); |
18864 |
++ list_add_tail(&kmsg->notify_entry, &bus->notify_list); |
18865 |
++ spin_unlock(&bus->notify_lock); |
18866 |
++} |
18867 |
++ |
18868 |
++static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id, |
18869 |
++ u64 cookie, u64 msg_type) |
18870 |
++{ |
18871 |
++ struct kdbus_kmsg *kmsg = NULL; |
18872 |
++ |
18873 |
++ WARN_ON(id == 0); |
18874 |
++ |
18875 |
++ kmsg = kdbus_kmsg_new(bus, 0); |
18876 |
++ if (IS_ERR(kmsg)) |
18877 |
++ return PTR_ERR(kmsg); |
18878 |
++ |
18879 |
++ /* |
18880 |
++ * a kernel-generated notification can only contain one |
18881 |
++ * struct kdbus_item, so make a shortcut here for |
18882 |
++ * faster lookup in the match db. |
18883 |
++ */ |
18884 |
++ kmsg->notify_type = msg_type; |
18885 |
++ kmsg->msg.flags = KDBUS_MSG_SIGNAL; |
18886 |
++ kmsg->msg.dst_id = id; |
18887 |
++ kmsg->msg.src_id = KDBUS_SRC_ID_KERNEL; |
18888 |
++ kmsg->msg.payload_type = KDBUS_PAYLOAD_KERNEL; |
18889 |
++ kmsg->msg.cookie_reply = cookie; |
18890 |
++ kmsg->msg.items[0].type = msg_type; |
18891 |
++ |
18892 |
++ kdbus_notify_add_tail(kmsg, bus); |
18893 |
++ |
18894 |
++ return 0; |
18895 |
++} |
18896 |
++ |
18897 |
++/** |
18898 |
++ * kdbus_notify_reply_timeout() - queue a timeout reply |
18899 |
++ * @bus: Bus which queues the messages |
18900 |
++ * @id: The destination's connection ID |
18901 |
++ * @cookie: The cookie to set in the reply. |
18902 |
++ * |
18903 |
++ * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached. |
18904 |
++ * |
18905 |
++ * Return: 0 on success, negative errno on failure. |
18906 |
++ */ |
18907 |
++int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie) |
18908 |
++{ |
18909 |
++ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT); |
18910 |
++} |
18911 |
++ |
18912 |
++/** |
18913 |
++ * kdbus_notify_reply_dead() - queue a 'dead' reply |
18914 |
++ * @bus: Bus which queues the messages |
18915 |
++ * @id: The destination's connection ID |
18916 |
++ * @cookie: The cookie to set in the reply. |
18917 |
++ * |
18918 |
++ * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached. |
18919 |
++ * |
18920 |
++ * Return: 0 on success, negative errno on failure. |
18921 |
++ */ |
18922 |
++int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie) |
18923 |
++{ |
18924 |
++ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD); |
18925 |
++} |
18926 |
++ |
18927 |
++/** |
18928 |
++ * kdbus_notify_name_change() - queue a notification about a name owner change |
18929 |
++ * @bus: Bus which queues the messages |
18930 |
++ * @type: The type if the notification; KDBUS_ITEM_NAME_ADD, |
18931 |
++ * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE |
18932 |
++ * @old_id: The id of the connection that used to own the name |
18933 |
++ * @new_id: The id of the new owner connection |
18934 |
++ * @old_flags: The flags to pass in the KDBUS_ITEM flags field for |
18935 |
++ * the old owner |
18936 |
++ * @new_flags: The flags to pass in the KDBUS_ITEM flags field for |
18937 |
++ * the new owner |
18938 |
++ * @name: The name that was removed or assigned to a new owner |
18939 |
++ * |
18940 |
++ * Return: 0 on success, negative errno on failure. |
18941 |
++ */ |
18942 |
++int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, |
18943 |
++ u64 old_id, u64 new_id, |
18944 |
++ u64 old_flags, u64 new_flags, |
18945 |
++ const char *name) |
18946 |
++{ |
18947 |
++ struct kdbus_kmsg *kmsg = NULL; |
18948 |
++ size_t name_len, extra_size; |
18949 |
++ |
18950 |
++ name_len = strlen(name) + 1; |
18951 |
++ extra_size = sizeof(struct kdbus_notify_name_change) + name_len; |
18952 |
++ kmsg = kdbus_kmsg_new(bus, extra_size); |
18953 |
++ if (IS_ERR(kmsg)) |
18954 |
++ return PTR_ERR(kmsg); |
18955 |
++ |
18956 |
++ kmsg->msg.flags = KDBUS_MSG_SIGNAL; |
18957 |
++ kmsg->msg.dst_id = KDBUS_DST_ID_BROADCAST; |
18958 |
++ kmsg->msg.src_id = KDBUS_SRC_ID_KERNEL; |
18959 |
++ kmsg->msg.payload_type = KDBUS_PAYLOAD_KERNEL; |
18960 |
++ kmsg->notify_type = type; |
18961 |
++ kmsg->notify_old_id = old_id; |
18962 |
++ kmsg->notify_new_id = new_id; |
18963 |
++ kmsg->msg.items[0].type = type; |
18964 |
++ kmsg->msg.items[0].name_change.old_id.id = old_id; |
18965 |
++ kmsg->msg.items[0].name_change.old_id.flags = old_flags; |
18966 |
++ kmsg->msg.items[0].name_change.new_id.id = new_id; |
18967 |
++ kmsg->msg.items[0].name_change.new_id.flags = new_flags; |
18968 |
++ memcpy(kmsg->msg.items[0].name_change.name, name, name_len); |
18969 |
++ kmsg->notify_name = kmsg->msg.items[0].name_change.name; |
18970 |
++ |
18971 |
++ kdbus_notify_add_tail(kmsg, bus); |
18972 |
++ |
18973 |
++ return 0; |
18974 |
++} |
18975 |
++ |
18976 |
++/** |
18977 |
++ * kdbus_notify_id_change() - queue a notification about a unique ID change |
18978 |
++ * @bus: Bus which queues the messages |
18979 |
++ * @type: The type if the notification; KDBUS_ITEM_ID_ADD or |
18980 |
++ * KDBUS_ITEM_ID_REMOVE |
18981 |
++ * @id: The id of the connection that was added or removed |
18982 |
++ * @flags: The flags to pass in the KDBUS_ITEM flags field |
18983 |
++ * |
18984 |
++ * Return: 0 on success, negative errno on failure. |
18985 |
++ */ |
18986 |
++int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags) |
18987 |
++{ |
18988 |
++ struct kdbus_kmsg *kmsg = NULL; |
18989 |
++ |
18990 |
++ kmsg = kdbus_kmsg_new(bus, sizeof(struct kdbus_notify_id_change)); |
18991 |
++ if (IS_ERR(kmsg)) |
18992 |
++ return PTR_ERR(kmsg); |
18993 |
++ |
18994 |
++ kmsg->msg.flags = KDBUS_MSG_SIGNAL; |
18995 |
++ kmsg->msg.dst_id = KDBUS_DST_ID_BROADCAST; |
18996 |
++ kmsg->msg.src_id = KDBUS_SRC_ID_KERNEL; |
18997 |
++ kmsg->msg.payload_type = KDBUS_PAYLOAD_KERNEL; |
18998 |
++ kmsg->notify_type = type; |
18999 |
++ |
19000 |
++ switch (type) { |
19001 |
++ case KDBUS_ITEM_ID_ADD: |
19002 |
++ kmsg->notify_new_id = id; |
19003 |
++ break; |
19004 |
++ |
19005 |
++ case KDBUS_ITEM_ID_REMOVE: |
19006 |
++ kmsg->notify_old_id = id; |
19007 |
++ break; |
19008 |
++ |
19009 |
++ default: |
19010 |
++ BUG(); |
19011 |
++ } |
19012 |
++ |
19013 |
++ kmsg->msg.items[0].type = type; |
19014 |
++ kmsg->msg.items[0].id_change.id = id; |
19015 |
++ kmsg->msg.items[0].id_change.flags = flags; |
19016 |
++ |
19017 |
++ kdbus_notify_add_tail(kmsg, bus); |
19018 |
++ |
19019 |
++ return 0; |
19020 |
++} |
19021 |
++ |
19022 |
++/** |
19023 |
++ * kdbus_notify_flush() - send a list of collected messages |
19024 |
++ * @bus: Bus which queues the messages |
19025 |
++ * |
19026 |
++ * The list is empty after sending the messages. |
19027 |
++ */ |
19028 |
++void kdbus_notify_flush(struct kdbus_bus *bus) |
19029 |
++{ |
19030 |
++ LIST_HEAD(notify_list); |
19031 |
++ struct kdbus_kmsg *kmsg, *tmp; |
19032 |
++ |
19033 |
++ mutex_lock(&bus->notify_flush_lock); |
19034 |
++ down_read(&bus->name_registry->rwlock); |
19035 |
++ |
19036 |
++ spin_lock(&bus->notify_lock); |
19037 |
++ list_splice_init(&bus->notify_list, ¬ify_list); |
19038 |
++ spin_unlock(&bus->notify_lock); |
19039 |
++ |
19040 |
++ list_for_each_entry_safe(kmsg, tmp, ¬ify_list, notify_entry) { |
19041 |
++ kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, NULL, |
19042 |
++ KDBUS_ATTACH_TIMESTAMP); |
19043 |
++ |
19044 |
++ if (kmsg->msg.dst_id != KDBUS_DST_ID_BROADCAST) { |
19045 |
++ struct kdbus_conn *conn; |
19046 |
++ |
19047 |
++ conn = kdbus_bus_find_conn_by_id(bus, kmsg->msg.dst_id); |
19048 |
++ if (conn) { |
19049 |
++ kdbus_bus_eavesdrop(bus, NULL, kmsg); |
19050 |
++ kdbus_conn_entry_insert(NULL, conn, kmsg, NULL); |
19051 |
++ kdbus_conn_unref(conn); |
19052 |
++ } |
19053 |
++ } else { |
19054 |
++ kdbus_bus_broadcast(bus, NULL, kmsg); |
19055 |
++ } |
19056 |
++ |
19057 |
++ list_del(&kmsg->notify_entry); |
19058 |
++ kdbus_kmsg_free(kmsg); |
19059 |
++ } |
19060 |
++ |
19061 |
++ up_read(&bus->name_registry->rwlock); |
19062 |
++ mutex_unlock(&bus->notify_flush_lock); |
19063 |
++} |
19064 |
++ |
19065 |
++/** |
19066 |
++ * kdbus_notify_free() - free a list of collected messages |
19067 |
++ * @bus: Bus which queues the messages |
19068 |
++ */ |
19069 |
++void kdbus_notify_free(struct kdbus_bus *bus) |
19070 |
++{ |
19071 |
++ struct kdbus_kmsg *kmsg, *tmp; |
19072 |
++ |
19073 |
++ list_for_each_entry_safe(kmsg, tmp, &bus->notify_list, notify_entry) { |
19074 |
++ list_del(&kmsg->notify_entry); |
19075 |
++ kdbus_kmsg_free(kmsg); |
19076 |
++ } |
19077 |
++} |
19078 |
+diff --git a/ipc/kdbus/notify.h b/ipc/kdbus/notify.h |
19079 |
+new file mode 100644 |
19080 |
+index 0000000..03df464 |
19081 |
+--- /dev/null |
19082 |
++++ b/ipc/kdbus/notify.h |
19083 |
+@@ -0,0 +1,30 @@ |
19084 |
++/* |
19085 |
++ * Copyright (C) 2013-2015 Kay Sievers |
19086 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19087 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19088 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19089 |
++ * Copyright (C) 2013-2015 Linux Foundation |
19090 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
19091 |
++ * |
19092 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
19093 |
++ * the terms of the GNU Lesser General Public License as published by the |
19094 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
19095 |
++ * your option) any later version. |
19096 |
++ */ |
19097 |
++ |
19098 |
++#ifndef __KDBUS_NOTIFY_H |
19099 |
++#define __KDBUS_NOTIFY_H |
19100 |
++ |
19101 |
++struct kdbus_bus; |
19102 |
++ |
19103 |
++int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags); |
19104 |
++int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie); |
19105 |
++int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie); |
19106 |
++int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, |
19107 |
++ u64 old_id, u64 new_id, |
19108 |
++ u64 old_flags, u64 new_flags, |
19109 |
++ const char *name); |
19110 |
++void kdbus_notify_flush(struct kdbus_bus *bus); |
19111 |
++void kdbus_notify_free(struct kdbus_bus *bus); |
19112 |
++ |
19113 |
++#endif |
19114 |
+diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c |
19115 |
+new file mode 100644 |
19116 |
+index 0000000..dd7fffa |
19117 |
+--- /dev/null |
19118 |
++++ b/ipc/kdbus/policy.c |
19119 |
+@@ -0,0 +1,489 @@ |
19120 |
++/* |
19121 |
++ * Copyright (C) 2013-2015 Kay Sievers |
19122 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19123 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19124 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19125 |
++ * Copyright (C) 2013-2015 Linux Foundation |
19126 |
++ * Copyright (C) 2014-2015 Djalal Harouni |
19127 |
++ * |
19128 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
19129 |
++ * the terms of the GNU Lesser General Public License as published by the |
19130 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
19131 |
++ * your option) any later version. |
19132 |
++ */ |
19133 |
++ |
19134 |
++#include <linux/dcache.h> |
19135 |
++#include <linux/fs.h> |
19136 |
++#include <linux/init.h> |
19137 |
++#include <linux/mutex.h> |
19138 |
++#include <linux/sched.h> |
19139 |
++#include <linux/sizes.h> |
19140 |
++#include <linux/slab.h> |
19141 |
++#include <linux/uaccess.h> |
19142 |
++ |
19143 |
++#include "bus.h" |
19144 |
++#include "connection.h" |
19145 |
++#include "domain.h" |
19146 |
++#include "item.h" |
19147 |
++#include "names.h" |
19148 |
++#include "policy.h" |
19149 |
++ |
19150 |
++#define KDBUS_POLICY_HASH_SIZE 64 |
19151 |
++ |
19152 |
++/** |
19153 |
++ * struct kdbus_policy_db_entry_access - a database entry access item |
19154 |
++ * @type: One of KDBUS_POLICY_ACCESS_* types |
19155 |
++ * @access: Access to grant. One of KDBUS_POLICY_* |
19156 |
++ * @uid: For KDBUS_POLICY_ACCESS_USER, the global uid |
19157 |
++ * @gid: For KDBUS_POLICY_ACCESS_GROUP, the global gid |
19158 |
++ * @list: List entry item for the entry's list |
19159 |
++ * |
19160 |
++ * This is the internal version of struct kdbus_policy_db_access. |
19161 |
++ */ |
19162 |
++struct kdbus_policy_db_entry_access { |
19163 |
++ u8 type; /* USER, GROUP, WORLD */ |
19164 |
++ u8 access; /* OWN, TALK, SEE */ |
19165 |
++ union { |
19166 |
++ kuid_t uid; /* global uid */ |
19167 |
++ kgid_t gid; /* global gid */ |
19168 |
++ }; |
19169 |
++ struct list_head list; |
19170 |
++}; |
19171 |
++ |
19172 |
++/** |
19173 |
++ * struct kdbus_policy_db_entry - a policy database entry |
19174 |
++ * @name: The name to match the policy entry against |
19175 |
++ * @hentry: The hash entry for the database's entries_hash |
19176 |
++ * @access_list: List head for keeping tracks of the entry's |
19177 |
++ * access items. |
19178 |
++ * @owner: The owner of this entry. Can be a kdbus_conn or |
19179 |
++ * a kdbus_ep object. |
19180 |
++ * @wildcard: The name is a wildcard, such as ending on '.*' |
19181 |
++ */ |
19182 |
++struct kdbus_policy_db_entry { |
19183 |
++ char *name; |
19184 |
++ struct hlist_node hentry; |
19185 |
++ struct list_head access_list; |
19186 |
++ const void *owner; |
19187 |
++ bool wildcard:1; |
19188 |
++}; |
19189 |
++ |
19190 |
++static void kdbus_policy_entry_free(struct kdbus_policy_db_entry *e) |
19191 |
++{ |
19192 |
++ struct kdbus_policy_db_entry_access *a, *tmp; |
19193 |
++ |
19194 |
++ list_for_each_entry_safe(a, tmp, &e->access_list, list) { |
19195 |
++ list_del(&a->list); |
19196 |
++ kfree(a); |
19197 |
++ } |
19198 |
++ |
19199 |
++ kfree(e->name); |
19200 |
++ kfree(e); |
19201 |
++} |
19202 |
++ |
19203 |
++static unsigned int kdbus_strnhash(const char *str, size_t len) |
19204 |
++{ |
19205 |
++ unsigned long hash = init_name_hash(); |
19206 |
++ |
19207 |
++ while (len--) |
19208 |
++ hash = partial_name_hash(*str++, hash); |
19209 |
++ |
19210 |
++ return end_name_hash(hash); |
19211 |
++} |
19212 |
++ |
19213 |
++static const struct kdbus_policy_db_entry * |
19214 |
++kdbus_policy_lookup(struct kdbus_policy_db *db, const char *name, u32 hash) |
19215 |
++{ |
19216 |
++ struct kdbus_policy_db_entry *e; |
19217 |
++ const char *dot; |
19218 |
++ size_t len; |
19219 |
++ |
19220 |
++ /* find exact match */ |
19221 |
++ hash_for_each_possible(db->entries_hash, e, hentry, hash) |
19222 |
++ if (strcmp(e->name, name) == 0 && !e->wildcard) |
19223 |
++ return e; |
19224 |
++ |
19225 |
++ /* find wildcard match */ |
19226 |
++ |
19227 |
++ dot = strrchr(name, '.'); |
19228 |
++ if (!dot) |
19229 |
++ return NULL; |
19230 |
++ |
19231 |
++ len = dot - name; |
19232 |
++ hash = kdbus_strnhash(name, len); |
19233 |
++ |
19234 |
++ hash_for_each_possible(db->entries_hash, e, hentry, hash) |
19235 |
++ if (e->wildcard && !strncmp(e->name, name, len) && |
19236 |
++ !e->name[len]) |
19237 |
++ return e; |
19238 |
++ |
19239 |
++ return NULL; |
19240 |
++} |
19241 |
++ |
19242 |
++/** |
19243 |
++ * kdbus_policy_db_clear - release all memory from a policy db |
19244 |
++ * @db: The policy database |
19245 |
++ */ |
19246 |
++void kdbus_policy_db_clear(struct kdbus_policy_db *db) |
19247 |
++{ |
19248 |
++ struct kdbus_policy_db_entry *e; |
19249 |
++ struct hlist_node *tmp; |
19250 |
++ unsigned int i; |
19251 |
++ |
19252 |
++ /* purge entries */ |
19253 |
++ down_write(&db->entries_rwlock); |
19254 |
++ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) { |
19255 |
++ hash_del(&e->hentry); |
19256 |
++ kdbus_policy_entry_free(e); |
19257 |
++ } |
19258 |
++ up_write(&db->entries_rwlock); |
19259 |
++} |
19260 |
++ |
19261 |
++/** |
19262 |
++ * kdbus_policy_db_init() - initialize a new policy database |
19263 |
++ * @db: The location of the database |
19264 |
++ * |
19265 |
++ * This initializes a new policy-db. The underlying memory must have been |
19266 |
++ * cleared to zero by the caller. |
19267 |
++ */ |
19268 |
++void kdbus_policy_db_init(struct kdbus_policy_db *db) |
19269 |
++{ |
19270 |
++ hash_init(db->entries_hash); |
19271 |
++ init_rwsem(&db->entries_rwlock); |
19272 |
++} |
19273 |
++ |
19274 |
++/** |
19275 |
++ * kdbus_policy_query_unlocked() - Query the policy database |
19276 |
++ * @db: Policy database |
19277 |
++ * @cred: Credentials to test against |
19278 |
++ * @name: Name to query |
19279 |
++ * @hash: Hash value of @name |
19280 |
++ * |
19281 |
++ * Same as kdbus_policy_query() but requires the caller to lock the policy |
19282 |
++ * database against concurrent writes. |
19283 |
++ * |
19284 |
++ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. |
19285 |
++ */ |
19286 |
++int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, |
19287 |
++ const struct cred *cred, const char *name, |
19288 |
++ unsigned int hash) |
19289 |
++{ |
19290 |
++ struct kdbus_policy_db_entry_access *a; |
19291 |
++ const struct kdbus_policy_db_entry *e; |
19292 |
++ int i, highest = -EPERM; |
19293 |
++ |
19294 |
++ e = kdbus_policy_lookup(db, name, hash); |
19295 |
++ if (!e) |
19296 |
++ return -EPERM; |
19297 |
++ |
19298 |
++ list_for_each_entry(a, &e->access_list, list) { |
19299 |
++ if ((int)a->access <= highest) |
19300 |
++ continue; |
19301 |
++ |
19302 |
++ switch (a->type) { |
19303 |
++ case KDBUS_POLICY_ACCESS_USER: |
19304 |
++ if (uid_eq(cred->euid, a->uid)) |
19305 |
++ highest = a->access; |
19306 |
++ break; |
19307 |
++ case KDBUS_POLICY_ACCESS_GROUP: |
19308 |
++ if (gid_eq(cred->egid, a->gid)) { |
19309 |
++ highest = a->access; |
19310 |
++ break; |
19311 |
++ } |
19312 |
++ |
19313 |
++ for (i = 0; i < cred->group_info->ngroups; i++) { |
19314 |
++ kgid_t gid = GROUP_AT(cred->group_info, i); |
19315 |
++ |
19316 |
++ if (gid_eq(gid, a->gid)) { |
19317 |
++ highest = a->access; |
19318 |
++ break; |
19319 |
++ } |
19320 |
++ } |
19321 |
++ |
19322 |
++ break; |
19323 |
++ case KDBUS_POLICY_ACCESS_WORLD: |
19324 |
++ highest = a->access; |
19325 |
++ break; |
19326 |
++ } |
19327 |
++ |
19328 |
++ /* OWN is the highest possible policy */ |
19329 |
++ if (highest >= KDBUS_POLICY_OWN) |
19330 |
++ break; |
19331 |
++ } |
19332 |
++ |
19333 |
++ return highest; |
19334 |
++} |
19335 |
++ |
19336 |
++/** |
19337 |
++ * kdbus_policy_query() - Query the policy database |
19338 |
++ * @db: Policy database |
19339 |
++ * @cred: Credentials to test against |
19340 |
++ * @name: Name to query |
19341 |
++ * @hash: Hash value of @name |
19342 |
++ * |
19343 |
++ * Query the policy database @db for the access rights of @cred to the name |
19344 |
++ * @name. The access rights of @cred are returned, or -EPERM if no access is |
19345 |
++ * granted. |
19346 |
++ * |
19347 |
++ * This call effectively searches for the highest access-right granted to |
19348 |
++ * @cred. The caller should really cache those as policy lookups are rather |
19349 |
++ * expensive. |
19350 |
++ * |
19351 |
++ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. |
19352 |
++ */ |
19353 |
++int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, |
19354 |
++ const char *name, unsigned int hash) |
19355 |
++{ |
19356 |
++ int ret; |
19357 |
++ |
19358 |
++ down_read(&db->entries_rwlock); |
19359 |
++ ret = kdbus_policy_query_unlocked(db, cred, name, hash); |
19360 |
++ up_read(&db->entries_rwlock); |
19361 |
++ |
19362 |
++ return ret; |
19363 |
++} |
19364 |
++ |
19365 |
++static void __kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
19366 |
++ const void *owner) |
19367 |
++{ |
19368 |
++ struct kdbus_policy_db_entry *e; |
19369 |
++ struct hlist_node *tmp; |
19370 |
++ int i; |
19371 |
++ |
19372 |
++ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) |
19373 |
++ if (e->owner == owner) { |
19374 |
++ hash_del(&e->hentry); |
19375 |
++ kdbus_policy_entry_free(e); |
19376 |
++ } |
19377 |
++} |
19378 |
++ |
19379 |
++/** |
19380 |
++ * kdbus_policy_remove_owner() - remove all entries related to a connection |
19381 |
++ * @db: The policy database |
19382 |
++ * @owner: The connection which items to remove |
19383 |
++ */ |
19384 |
++void kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
19385 |
++ const void *owner) |
19386 |
++{ |
19387 |
++ down_write(&db->entries_rwlock); |
19388 |
++ __kdbus_policy_remove_owner(db, owner); |
19389 |
++ up_write(&db->entries_rwlock); |
19390 |
++} |
19391 |
++ |
19392 |
++/* |
19393 |
++ * Convert user provided policy access to internal kdbus policy |
19394 |
++ * access |
19395 |
++ */ |
19396 |
++static struct kdbus_policy_db_entry_access * |
19397 |
++kdbus_policy_make_access(const struct kdbus_policy_access *uaccess) |
19398 |
++{ |
19399 |
++ int ret; |
19400 |
++ struct kdbus_policy_db_entry_access *a; |
19401 |
++ |
19402 |
++ a = kzalloc(sizeof(*a), GFP_KERNEL); |
19403 |
++ if (!a) |
19404 |
++ return ERR_PTR(-ENOMEM); |
19405 |
++ |
19406 |
++ ret = -EINVAL; |
19407 |
++ switch (uaccess->access) { |
19408 |
++ case KDBUS_POLICY_SEE: |
19409 |
++ case KDBUS_POLICY_TALK: |
19410 |
++ case KDBUS_POLICY_OWN: |
19411 |
++ a->access = uaccess->access; |
19412 |
++ break; |
19413 |
++ default: |
19414 |
++ goto err; |
19415 |
++ } |
19416 |
++ |
19417 |
++ switch (uaccess->type) { |
19418 |
++ case KDBUS_POLICY_ACCESS_USER: |
19419 |
++ a->uid = make_kuid(current_user_ns(), uaccess->id); |
19420 |
++ if (!uid_valid(a->uid)) |
19421 |
++ goto err; |
19422 |
++ |
19423 |
++ break; |
19424 |
++ case KDBUS_POLICY_ACCESS_GROUP: |
19425 |
++ a->gid = make_kgid(current_user_ns(), uaccess->id); |
19426 |
++ if (!gid_valid(a->gid)) |
19427 |
++ goto err; |
19428 |
++ |
19429 |
++ break; |
19430 |
++ case KDBUS_POLICY_ACCESS_WORLD: |
19431 |
++ break; |
19432 |
++ default: |
19433 |
++ goto err; |
19434 |
++ } |
19435 |
++ |
19436 |
++ a->type = uaccess->type; |
19437 |
++ |
19438 |
++ return a; |
19439 |
++ |
19440 |
++err: |
19441 |
++ kfree(a); |
19442 |
++ return ERR_PTR(ret); |
19443 |
++} |
19444 |
++ |
19445 |
++/** |
19446 |
++ * kdbus_policy_set() - set a connection's policy rules |
19447 |
++ * @db: The policy database |
19448 |
++ * @items: A list of kdbus_item elements that contain both |
19449 |
++ * names and access rules to set. |
19450 |
++ * @items_size: The total size of the items. |
19451 |
++ * @max_policies: The maximum number of policy entries to allow. |
19452 |
++ * Pass 0 for no limit. |
19453 |
++ * @allow_wildcards: Boolean value whether wildcard entries (such |
19454 |
++ * ending on '.*') should be allowed. |
19455 |
++ * @owner: The owner of the new policy items. |
19456 |
++ * |
19457 |
++ * This function sets a new set of policies for a given owner. The names and |
19458 |
++ * access rules are gathered by walking the list of items passed in as |
19459 |
++ * argument. An item of type KDBUS_ITEM_NAME is expected before any number of |
19460 |
++ * KDBUS_ITEM_POLICY_ACCESS items. If there are more repetitions of this |
19461 |
++ * pattern than denoted in @max_policies, -EINVAL is returned. |
19462 |
++ * |
19463 |
++ * In order to allow atomic replacement of rules, the function first removes |
19464 |
++ * all entries that have been created for the given owner previously. |
19465 |
++ * |
19466 |
++ * Callers to this function must make sur that the owner is a custom |
19467 |
++ * endpoint, or if the endpoint is a default endpoint, then it must be |
19468 |
++ * either a policy holder or an activator. |
19469 |
++ * |
19470 |
++ * Return: 0 on success, negative errno on failure. |
19471 |
++ */ |
19472 |
++int kdbus_policy_set(struct kdbus_policy_db *db, |
19473 |
++ const struct kdbus_item *items, |
19474 |
++ size_t items_size, |
19475 |
++ size_t max_policies, |
19476 |
++ bool allow_wildcards, |
19477 |
++ const void *owner) |
19478 |
++{ |
19479 |
++ struct kdbus_policy_db_entry_access *a; |
19480 |
++ struct kdbus_policy_db_entry *e, *p; |
19481 |
++ const struct kdbus_item *item; |
19482 |
++ struct hlist_node *tmp; |
19483 |
++ HLIST_HEAD(entries); |
19484 |
++ HLIST_HEAD(restore); |
19485 |
++ size_t count = 0; |
19486 |
++ int i, ret = 0; |
19487 |
++ u32 hash; |
19488 |
++ |
19489 |
++ /* Walk the list of items and look for new policies */ |
19490 |
++ e = NULL; |
19491 |
++ KDBUS_ITEMS_FOREACH(item, items, items_size) { |
19492 |
++ switch (item->type) { |
19493 |
++ case KDBUS_ITEM_NAME: { |
19494 |
++ size_t len; |
19495 |
++ |
19496 |
++ if (max_policies && ++count > max_policies) { |
19497 |
++ ret = -E2BIG; |
19498 |
++ goto exit; |
19499 |
++ } |
19500 |
++ |
19501 |
++ if (!kdbus_name_is_valid(item->str, true)) { |
19502 |
++ ret = -EINVAL; |
19503 |
++ goto exit; |
19504 |
++ } |
19505 |
++ |
19506 |
++ e = kzalloc(sizeof(*e), GFP_KERNEL); |
19507 |
++ if (!e) { |
19508 |
++ ret = -ENOMEM; |
19509 |
++ goto exit; |
19510 |
++ } |
19511 |
++ |
19512 |
++ INIT_LIST_HEAD(&e->access_list); |
19513 |
++ e->owner = owner; |
19514 |
++ hlist_add_head(&e->hentry, &entries); |
19515 |
++ |
19516 |
++ e->name = kstrdup(item->str, GFP_KERNEL); |
19517 |
++ if (!e->name) { |
19518 |
++ ret = -ENOMEM; |
19519 |
++ goto exit; |
19520 |
++ } |
19521 |
++ |
19522 |
++ /* |
19523 |
++ * If a supplied name ends with an '.*', cut off that |
19524 |
++ * part, only store anything before it, and mark the |
19525 |
++ * entry as wildcard. |
19526 |
++ */ |
19527 |
++ len = strlen(e->name); |
19528 |
++ if (len > 2 && |
19529 |
++ e->name[len - 3] == '.' && |
19530 |
++ e->name[len - 2] == '*') { |
19531 |
++ if (!allow_wildcards) { |
19532 |
++ ret = -EINVAL; |
19533 |
++ goto exit; |
19534 |
++ } |
19535 |
++ |
19536 |
++ e->name[len - 3] = '\0'; |
19537 |
++ e->wildcard = true; |
19538 |
++ } |
19539 |
++ |
19540 |
++ break; |
19541 |
++ } |
19542 |
++ |
19543 |
++ case KDBUS_ITEM_POLICY_ACCESS: |
19544 |
++ if (!e) { |
19545 |
++ ret = -EINVAL; |
19546 |
++ goto exit; |
19547 |
++ } |
19548 |
++ |
19549 |
++ a = kdbus_policy_make_access(&item->policy_access); |
19550 |
++ if (IS_ERR(a)) { |
19551 |
++ ret = PTR_ERR(a); |
19552 |
++ goto exit; |
19553 |
++ } |
19554 |
++ |
19555 |
++ list_add_tail(&a->list, &e->access_list); |
19556 |
++ break; |
19557 |
++ } |
19558 |
++ } |
19559 |
++ |
19560 |
++ down_write(&db->entries_rwlock); |
19561 |
++ |
19562 |
++ /* remember previous entries to restore in case of failure */ |
19563 |
++ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) |
19564 |
++ if (e->owner == owner) { |
19565 |
++ hash_del(&e->hentry); |
19566 |
++ hlist_add_head(&e->hentry, &restore); |
19567 |
++ } |
19568 |
++ |
19569 |
++ hlist_for_each_entry_safe(e, tmp, &entries, hentry) { |
19570 |
++ /* prevent duplicates */ |
19571 |
++ hash = kdbus_strhash(e->name); |
19572 |
++ hash_for_each_possible(db->entries_hash, p, hentry, hash) |
19573 |
++ if (strcmp(e->name, p->name) == 0 && |
19574 |
++ e->wildcard == p->wildcard) { |
19575 |
++ ret = -EEXIST; |
19576 |
++ goto restore; |
19577 |
++ } |
19578 |
++ |
19579 |
++ hlist_del(&e->hentry); |
19580 |
++ hash_add(db->entries_hash, &e->hentry, hash); |
19581 |
++ } |
19582 |
++ |
19583 |
++restore: |
19584 |
++ /* if we failed, flush all entries we added so far */ |
19585 |
++ if (ret < 0) |
19586 |
++ __kdbus_policy_remove_owner(db, owner); |
19587 |
++ |
19588 |
++ /* if we failed, restore entries, otherwise release them */ |
19589 |
++ hlist_for_each_entry_safe(e, tmp, &restore, hentry) { |
19590 |
++ hlist_del(&e->hentry); |
19591 |
++ if (ret < 0) { |
19592 |
++ hash = kdbus_strhash(e->name); |
19593 |
++ hash_add(db->entries_hash, &e->hentry, hash); |
19594 |
++ } else { |
19595 |
++ kdbus_policy_entry_free(e); |
19596 |
++ } |
19597 |
++ } |
19598 |
++ |
19599 |
++ up_write(&db->entries_rwlock); |
19600 |
++ |
19601 |
++exit: |
19602 |
++ hlist_for_each_entry_safe(e, tmp, &entries, hentry) { |
19603 |
++ hlist_del(&e->hentry); |
19604 |
++ kdbus_policy_entry_free(e); |
19605 |
++ } |
19606 |
++ |
19607 |
++ return ret; |
19608 |
++} |
19609 |
+diff --git a/ipc/kdbus/policy.h b/ipc/kdbus/policy.h |
19610 |
+new file mode 100644 |
19611 |
+index 0000000..15dd7bc |
19612 |
+--- /dev/null |
19613 |
++++ b/ipc/kdbus/policy.h |
19614 |
+@@ -0,0 +1,51 @@ |
19615 |
++/* |
19616 |
++ * Copyright (C) 2013-2015 Kay Sievers |
19617 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19618 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19619 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19620 |
++ * Copyright (C) 2013-2015 Linux Foundation |
19621 |
++ * |
19622 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
19623 |
++ * the terms of the GNU Lesser General Public License as published by the |
19624 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
19625 |
++ * your option) any later version. |
19626 |
++ */ |
19627 |
++ |
19628 |
++#ifndef __KDBUS_POLICY_H |
19629 |
++#define __KDBUS_POLICY_H |
19630 |
++ |
19631 |
++#include <linux/hashtable.h> |
19632 |
++#include <linux/rwsem.h> |
19633 |
++ |
19634 |
++struct kdbus_conn; |
19635 |
++struct kdbus_item; |
19636 |
++ |
19637 |
++/** |
19638 |
++ * struct kdbus_policy_db - policy database |
19639 |
++ * @entries_hash: Hashtable of entries |
19640 |
++ * @entries_rwlock: Mutex to protect the database's access entries |
19641 |
++ */ |
19642 |
++struct kdbus_policy_db { |
19643 |
++ DECLARE_HASHTABLE(entries_hash, 6); |
19644 |
++ struct rw_semaphore entries_rwlock; |
19645 |
++}; |
19646 |
++ |
19647 |
++void kdbus_policy_db_init(struct kdbus_policy_db *db); |
19648 |
++void kdbus_policy_db_clear(struct kdbus_policy_db *db); |
19649 |
++ |
19650 |
++int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, |
19651 |
++ const struct cred *cred, const char *name, |
19652 |
++ unsigned int hash); |
19653 |
++int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, |
19654 |
++ const char *name, unsigned int hash); |
19655 |
++ |
19656 |
++void kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
19657 |
++ const void *owner); |
19658 |
++int kdbus_policy_set(struct kdbus_policy_db *db, |
19659 |
++ const struct kdbus_item *items, |
19660 |
++ size_t items_size, |
19661 |
++ size_t max_policies, |
19662 |
++ bool allow_wildcards, |
19663 |
++ const void *owner); |
19664 |
++ |
19665 |
++#endif |
19666 |
+diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c |
19667 |
+new file mode 100644 |
19668 |
+index 0000000..139bb77 |
19669 |
+--- /dev/null |
19670 |
++++ b/ipc/kdbus/pool.c |
19671 |
+@@ -0,0 +1,728 @@ |
19672 |
++/* |
19673 |
++ * Copyright (C) 2013-2015 Kay Sievers |
19674 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19675 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19676 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19677 |
++ * Copyright (C) 2013-2015 Linux Foundation |
19678 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
19679 |
++ * |
19680 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
19681 |
++ * the terms of the GNU Lesser General Public License as published by the |
19682 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
19683 |
++ * your option) any later version. |
19684 |
++ */ |
19685 |
++ |
19686 |
++#include <linux/aio.h> |
19687 |
++#include <linux/file.h> |
19688 |
++#include <linux/fs.h> |
19689 |
++#include <linux/highmem.h> |
19690 |
++#include <linux/init.h> |
19691 |
++#include <linux/mm.h> |
19692 |
++#include <linux/module.h> |
19693 |
++#include <linux/pagemap.h> |
19694 |
++#include <linux/rbtree.h> |
19695 |
++#include <linux/sched.h> |
19696 |
++#include <linux/shmem_fs.h> |
19697 |
++#include <linux/sizes.h> |
19698 |
++#include <linux/slab.h> |
19699 |
++#include <linux/uaccess.h> |
19700 |
++#include <linux/uio.h> |
19701 |
++ |
19702 |
++#include "pool.h" |
19703 |
++#include "util.h" |
19704 |
++ |
19705 |
++/** |
19706 |
++ * struct kdbus_pool - the receiver's buffer |
19707 |
++ * @f: The backing shmem file |
19708 |
++ * @size: The size of the file |
19709 |
++ * @accounted_size: Currently accounted memory in bytes |
19710 |
++ * @lock: Pool data lock |
19711 |
++ * @slices: All slices sorted by address |
19712 |
++ * @slices_busy: Tree of allocated slices |
19713 |
++ * @slices_free: Tree of free slices |
19714 |
++ * |
19715 |
++ * The receiver's buffer, managed as a pool of allocated and free |
19716 |
++ * slices containing the queued messages. |
19717 |
++ * |
19718 |
++ * Messages sent with KDBUS_CMD_SEND are copied direcly by the |
19719 |
++ * sending process into the receiver's pool. |
19720 |
++ * |
19721 |
++ * Messages received with KDBUS_CMD_RECV just return the offset |
19722 |
++ * to the data placed in the pool. |
19723 |
++ * |
19724 |
++ * The internally allocated memory needs to be returned by the receiver |
19725 |
++ * with KDBUS_CMD_FREE. |
19726 |
++ */ |
19727 |
++struct kdbus_pool { |
19728 |
++ struct file *f; |
19729 |
++ size_t size; |
19730 |
++ size_t accounted_size; |
19731 |
++ struct mutex lock; |
19732 |
++ |
19733 |
++ struct list_head slices; |
19734 |
++ struct rb_root slices_busy; |
19735 |
++ struct rb_root slices_free; |
19736 |
++}; |
19737 |
++ |
19738 |
++/** |
19739 |
++ * struct kdbus_pool_slice - allocated element in kdbus_pool |
19740 |
++ * @pool: Pool this slice belongs to |
19741 |
++ * @off: Offset of slice in the shmem file |
19742 |
++ * @size: Size of slice |
19743 |
++ * @entry: Entry in "all slices" list |
19744 |
++ * @rb_node: Entry in free or busy list |
19745 |
++ * @free: Unused slice |
19746 |
++ * @accounted: Accounted as queue slice |
19747 |
++ * @ref_kernel: Kernel holds a reference |
19748 |
++ * @ref_user: Userspace holds a reference |
19749 |
++ * |
19750 |
++ * The pool has one or more slices, always spanning the entire size of the |
19751 |
++ * pool. |
19752 |
++ * |
19753 |
++ * Every slice is an element in a list sorted by the buffer address, to |
19754 |
++ * provide access to the next neighbor slice. |
19755 |
++ * |
19756 |
++ * Every slice is member in either the busy or the free tree. The free |
19757 |
++ * tree is organized by slice size, the busy tree organized by buffer |
19758 |
++ * offset. |
19759 |
++ */ |
19760 |
++struct kdbus_pool_slice { |
19761 |
++ struct kdbus_pool *pool; |
19762 |
++ size_t off; |
19763 |
++ size_t size; |
19764 |
++ |
19765 |
++ struct list_head entry; |
19766 |
++ struct rb_node rb_node; |
19767 |
++ |
19768 |
++ bool free:1; |
19769 |
++ bool accounted:1; |
19770 |
++ bool ref_kernel:1; |
19771 |
++ bool ref_user:1; |
19772 |
++}; |
19773 |
++ |
19774 |
++static struct kdbus_pool_slice *kdbus_pool_slice_new(struct kdbus_pool *pool, |
19775 |
++ size_t off, size_t size) |
19776 |
++{ |
19777 |
++ struct kdbus_pool_slice *slice; |
19778 |
++ |
19779 |
++ slice = kzalloc(sizeof(*slice), GFP_KERNEL); |
19780 |
++ if (!slice) |
19781 |
++ return NULL; |
19782 |
++ |
19783 |
++ slice->pool = pool; |
19784 |
++ slice->off = off; |
19785 |
++ slice->size = size; |
19786 |
++ slice->free = true; |
19787 |
++ return slice; |
19788 |
++} |
19789 |
++ |
19790 |
++/* insert a slice into the free tree */ |
19791 |
++static void kdbus_pool_add_free_slice(struct kdbus_pool *pool, |
19792 |
++ struct kdbus_pool_slice *slice) |
19793 |
++{ |
19794 |
++ struct rb_node **n; |
19795 |
++ struct rb_node *pn = NULL; |
19796 |
++ |
19797 |
++ n = &pool->slices_free.rb_node; |
19798 |
++ while (*n) { |
19799 |
++ struct kdbus_pool_slice *pslice; |
19800 |
++ |
19801 |
++ pn = *n; |
19802 |
++ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node); |
19803 |
++ if (slice->size < pslice->size) |
19804 |
++ n = &pn->rb_left; |
19805 |
++ else |
19806 |
++ n = &pn->rb_right; |
19807 |
++ } |
19808 |
++ |
19809 |
++ rb_link_node(&slice->rb_node, pn, n); |
19810 |
++ rb_insert_color(&slice->rb_node, &pool->slices_free); |
19811 |
++} |
19812 |
++ |
19813 |
++/* insert a slice into the busy tree */ |
19814 |
++static void kdbus_pool_add_busy_slice(struct kdbus_pool *pool, |
19815 |
++ struct kdbus_pool_slice *slice) |
19816 |
++{ |
19817 |
++ struct rb_node **n; |
19818 |
++ struct rb_node *pn = NULL; |
19819 |
++ |
19820 |
++ n = &pool->slices_busy.rb_node; |
19821 |
++ while (*n) { |
19822 |
++ struct kdbus_pool_slice *pslice; |
19823 |
++ |
19824 |
++ pn = *n; |
19825 |
++ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node); |
19826 |
++ if (slice->off < pslice->off) |
19827 |
++ n = &pn->rb_left; |
19828 |
++ else if (slice->off > pslice->off) |
19829 |
++ n = &pn->rb_right; |
19830 |
++ else |
19831 |
++ BUG(); |
19832 |
++ } |
19833 |
++ |
19834 |
++ rb_link_node(&slice->rb_node, pn, n); |
19835 |
++ rb_insert_color(&slice->rb_node, &pool->slices_busy); |
19836 |
++} |
19837 |
++ |
19838 |
++static struct kdbus_pool_slice *kdbus_pool_find_slice(struct kdbus_pool *pool, |
19839 |
++ size_t off) |
19840 |
++{ |
19841 |
++ struct rb_node *n; |
19842 |
++ |
19843 |
++ n = pool->slices_busy.rb_node; |
19844 |
++ while (n) { |
19845 |
++ struct kdbus_pool_slice *s; |
19846 |
++ |
19847 |
++ s = rb_entry(n, struct kdbus_pool_slice, rb_node); |
19848 |
++ if (off < s->off) |
19849 |
++ n = n->rb_left; |
19850 |
++ else if (off > s->off) |
19851 |
++ n = n->rb_right; |
19852 |
++ else |
19853 |
++ return s; |
19854 |
++ } |
19855 |
++ |
19856 |
++ return NULL; |
19857 |
++} |
19858 |
++ |
19859 |
++/** |
19860 |
++ * kdbus_pool_slice_alloc() - allocate memory from a pool |
19861 |
++ * @pool: The receiver's pool |
19862 |
++ * @size: The number of bytes to allocate |
19863 |
++ * @accounted: Whether this slice should be accounted for |
19864 |
++ * |
19865 |
++ * The returned slice is used for kdbus_pool_slice_release() to |
19866 |
++ * free the allocated memory. If either @kvec or @iovec is non-NULL, the data |
19867 |
++ * will be copied from kernel or userspace memory into the new slice at |
19868 |
++ * offset 0. |
19869 |
++ * |
19870 |
++ * Return: the allocated slice on success, ERR_PTR on failure. |
19871 |
++ */ |
19872 |
++struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, |
19873 |
++ size_t size, bool accounted) |
19874 |
++{ |
19875 |
++ size_t slice_size = KDBUS_ALIGN8(size); |
19876 |
++ struct rb_node *n, *found = NULL; |
19877 |
++ struct kdbus_pool_slice *s; |
19878 |
++ int ret = 0; |
19879 |
++ |
19880 |
++ if (WARN_ON(!size)) |
19881 |
++ return ERR_PTR(-EINVAL); |
19882 |
++ |
19883 |
++ /* search a free slice with the closest matching size */ |
19884 |
++ mutex_lock(&pool->lock); |
19885 |
++ n = pool->slices_free.rb_node; |
19886 |
++ while (n) { |
19887 |
++ s = rb_entry(n, struct kdbus_pool_slice, rb_node); |
19888 |
++ if (slice_size < s->size) { |
19889 |
++ found = n; |
19890 |
++ n = n->rb_left; |
19891 |
++ } else if (slice_size > s->size) { |
19892 |
++ n = n->rb_right; |
19893 |
++ } else { |
19894 |
++ found = n; |
19895 |
++ break; |
19896 |
++ } |
19897 |
++ } |
19898 |
++ |
19899 |
++ /* no slice with the minimum size found in the pool */ |
19900 |
++ if (!found) { |
19901 |
++ ret = -EXFULL; |
19902 |
++ goto exit_unlock; |
19903 |
++ } |
19904 |
++ |
19905 |
++ /* no exact match, use the closest one */ |
19906 |
++ if (!n) { |
19907 |
++ struct kdbus_pool_slice *s_new; |
19908 |
++ |
19909 |
++ s = rb_entry(found, struct kdbus_pool_slice, rb_node); |
19910 |
++ |
19911 |
++ /* split-off the remainder of the size to its own slice */ |
19912 |
++ s_new = kdbus_pool_slice_new(pool, s->off + slice_size, |
19913 |
++ s->size - slice_size); |
19914 |
++ if (!s_new) { |
19915 |
++ ret = -ENOMEM; |
19916 |
++ goto exit_unlock; |
19917 |
++ } |
19918 |
++ |
19919 |
++ list_add(&s_new->entry, &s->entry); |
19920 |
++ kdbus_pool_add_free_slice(pool, s_new); |
19921 |
++ |
19922 |
++ /* adjust our size now that we split-off another slice */ |
19923 |
++ s->size = slice_size; |
19924 |
++ } |
19925 |
++ |
19926 |
++ /* move slice from free to the busy tree */ |
19927 |
++ rb_erase(found, &pool->slices_free); |
19928 |
++ kdbus_pool_add_busy_slice(pool, s); |
19929 |
++ |
19930 |
++ WARN_ON(s->ref_kernel || s->ref_user); |
19931 |
++ |
19932 |
++ s->ref_kernel = true; |
19933 |
++ s->free = false; |
19934 |
++ s->accounted = accounted; |
19935 |
++ if (accounted) |
19936 |
++ pool->accounted_size += s->size; |
19937 |
++ mutex_unlock(&pool->lock); |
19938 |
++ |
19939 |
++ return s; |
19940 |
++ |
19941 |
++exit_unlock: |
19942 |
++ mutex_unlock(&pool->lock); |
19943 |
++ return ERR_PTR(ret); |
19944 |
++} |
19945 |
++ |
19946 |
++static void __kdbus_pool_slice_release(struct kdbus_pool_slice *slice) |
19947 |
++{ |
19948 |
++ struct kdbus_pool *pool = slice->pool; |
19949 |
++ |
19950 |
++ /* don't free the slice if either has a reference */ |
19951 |
++ if (slice->ref_kernel || slice->ref_user) |
19952 |
++ return; |
19953 |
++ |
19954 |
++ if (WARN_ON(slice->free)) |
19955 |
++ return; |
19956 |
++ |
19957 |
++ rb_erase(&slice->rb_node, &pool->slices_busy); |
19958 |
++ |
19959 |
++ /* merge with the next free slice */ |
19960 |
++ if (!list_is_last(&slice->entry, &pool->slices)) { |
19961 |
++ struct kdbus_pool_slice *s; |
19962 |
++ |
19963 |
++ s = list_entry(slice->entry.next, |
19964 |
++ struct kdbus_pool_slice, entry); |
19965 |
++ if (s->free) { |
19966 |
++ rb_erase(&s->rb_node, &pool->slices_free); |
19967 |
++ list_del(&s->entry); |
19968 |
++ slice->size += s->size; |
19969 |
++ kfree(s); |
19970 |
++ } |
19971 |
++ } |
19972 |
++ |
19973 |
++ /* merge with previous free slice */ |
19974 |
++ if (pool->slices.next != &slice->entry) { |
19975 |
++ struct kdbus_pool_slice *s; |
19976 |
++ |
19977 |
++ s = list_entry(slice->entry.prev, |
19978 |
++ struct kdbus_pool_slice, entry); |
19979 |
++ if (s->free) { |
19980 |
++ rb_erase(&s->rb_node, &pool->slices_free); |
19981 |
++ list_del(&slice->entry); |
19982 |
++ s->size += slice->size; |
19983 |
++ kfree(slice); |
19984 |
++ slice = s; |
19985 |
++ } |
19986 |
++ } |
19987 |
++ |
19988 |
++ slice->free = true; |
19989 |
++ kdbus_pool_add_free_slice(pool, slice); |
19990 |
++} |
19991 |
++ |
19992 |
++/** |
19993 |
++ * kdbus_pool_slice_release() - drop kernel-reference on allocated slice |
19994 |
++ * @slice: Slice allocated from the pool |
19995 |
++ * |
19996 |
++ * This releases the kernel-reference on the given slice. If the |
19997 |
++ * kernel-reference and the user-reference on a slice are dropped, the slice is |
19998 |
++ * returned to the pool. |
19999 |
++ * |
20000 |
++ * So far, we do not implement full ref-counting on slices. Each, kernel and |
20001 |
++ * user-space can have exactly one reference to a slice. If both are dropped at |
20002 |
++ * the same time, the slice is released. |
20003 |
++ */ |
20004 |
++void kdbus_pool_slice_release(struct kdbus_pool_slice *slice) |
20005 |
++{ |
20006 |
++ struct kdbus_pool *pool; |
20007 |
++ |
20008 |
++ if (!slice) |
20009 |
++ return; |
20010 |
++ |
20011 |
++ /* @slice may be freed, so keep local ptr to @pool */ |
20012 |
++ pool = slice->pool; |
20013 |
++ |
20014 |
++ mutex_lock(&pool->lock); |
20015 |
++ /* kernel must own a ref to @slice to drop it */ |
20016 |
++ WARN_ON(!slice->ref_kernel); |
20017 |
++ slice->ref_kernel = false; |
20018 |
++ /* no longer kernel-owned, de-account slice */ |
20019 |
++ if (slice->accounted && !WARN_ON(pool->accounted_size < slice->size)) |
20020 |
++ pool->accounted_size -= slice->size; |
20021 |
++ __kdbus_pool_slice_release(slice); |
20022 |
++ mutex_unlock(&pool->lock); |
20023 |
++} |
20024 |
++ |
20025 |
++/** |
20026 |
++ * kdbus_pool_release_offset() - release a public offset |
20027 |
++ * @pool: pool to operate on |
20028 |
++ * @off: offset to release |
20029 |
++ * |
20030 |
++ * This should be called whenever user-space frees a slice given to them. It |
20031 |
++ * verifies the slice is available and public, and then drops it. It ensures |
20032 |
++ * correct locking and barriers against queues. |
20033 |
++ * |
20034 |
++ * Return: 0 on success, ENXIO if the offset is invalid or not public. |
20035 |
++ */ |
20036 |
++int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off) |
20037 |
++{ |
20038 |
++ struct kdbus_pool_slice *slice; |
20039 |
++ int ret = 0; |
20040 |
++ |
20041 |
++ /* 'pool->size' is used as dummy offset for empty slices */ |
20042 |
++ if (off == pool->size) |
20043 |
++ return 0; |
20044 |
++ |
20045 |
++ mutex_lock(&pool->lock); |
20046 |
++ slice = kdbus_pool_find_slice(pool, off); |
20047 |
++ if (slice && slice->ref_user) { |
20048 |
++ slice->ref_user = false; |
20049 |
++ __kdbus_pool_slice_release(slice); |
20050 |
++ } else { |
20051 |
++ ret = -ENXIO; |
20052 |
++ } |
20053 |
++ mutex_unlock(&pool->lock); |
20054 |
++ |
20055 |
++ return ret; |
20056 |
++} |
20057 |
++ |
20058 |
++/** |
20059 |
++ * kdbus_pool_publish_empty() - publish empty slice to user-space |
20060 |
++ * @pool: pool to operate on |
20061 |
++ * @off: output storage for offset, or NULL |
20062 |
++ * @size: output storage for size, or NULL |
20063 |
++ * |
20064 |
++ * This is the same as kdbus_pool_slice_publish(), but uses a dummy slice with |
20065 |
++ * size 0. The returned offset points to the end of the pool and is never |
20066 |
++ * returned on real slices. |
20067 |
++ */ |
20068 |
++void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size) |
20069 |
++{ |
20070 |
++ if (off) |
20071 |
++ *off = pool->size; |
20072 |
++ if (size) |
20073 |
++ *size = 0; |
20074 |
++} |
20075 |
++ |
20076 |
++/** |
20077 |
++ * kdbus_pool_slice_publish() - publish slice to user-space |
20078 |
++ * @slice: The slice |
20079 |
++ * @out_offset: Output storage for offset, or NULL |
20080 |
++ * @out_size: Output storage for size, or NULL |
20081 |
++ * |
20082 |
++ * This prepares a slice to be published to user-space. |
20083 |
++ * |
20084 |
++ * This call combines the following operations: |
20085 |
++ * * the memory region is flushed so the user's memory view is consistent |
20086 |
++ * * the slice is marked as referenced by user-space, so user-space has to |
20087 |
++ * call KDBUS_CMD_FREE to release it |
20088 |
++ * * the offset and size of the slice are written to the given output |
20089 |
++ * arguments, if non-NULL |
20090 |
++ */ |
20091 |
++void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, |
20092 |
++ u64 *out_offset, u64 *out_size) |
20093 |
++{ |
20094 |
++ mutex_lock(&slice->pool->lock); |
20095 |
++ /* kernel must own a ref to @slice to gain a user-space ref */ |
20096 |
++ WARN_ON(!slice->ref_kernel); |
20097 |
++ slice->ref_user = true; |
20098 |
++ mutex_unlock(&slice->pool->lock); |
20099 |
++ |
20100 |
++ if (out_offset) |
20101 |
++ *out_offset = slice->off; |
20102 |
++ if (out_size) |
20103 |
++ *out_size = slice->size; |
20104 |
++} |
20105 |
++ |
20106 |
++/** |
20107 |
++ * kdbus_pool_slice_offset() - Get a slice's offset inside the pool |
20108 |
++ * @slice: Slice to return the offset of |
20109 |
++ * |
20110 |
++ * Return: The internal offset @slice inside the pool. |
20111 |
++ */ |
20112 |
++off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice) |
20113 |
++{ |
20114 |
++ return slice->off; |
20115 |
++} |
20116 |
++ |
20117 |
++/** |
20118 |
++ * kdbus_pool_slice_size() - get size of a pool slice |
20119 |
++ * @slice: slice to query |
20120 |
++ * |
20121 |
++ * Return: size of the given slice |
20122 |
++ */ |
20123 |
++size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice) |
20124 |
++{ |
20125 |
++ return slice->size; |
20126 |
++} |
20127 |
++ |
20128 |
++/** |
20129 |
++ * kdbus_pool_new() - create a new pool |
20130 |
++ * @name: Name of the (deleted) file which shows up in |
20131 |
++ * /proc, used for debugging |
20132 |
++ * @size: Maximum size of the pool |
20133 |
++ * |
20134 |
++ * Return: a new kdbus_pool on success, ERR_PTR on failure. |
20135 |
++ */ |
20136 |
++struct kdbus_pool *kdbus_pool_new(const char *name, size_t size) |
20137 |
++{ |
20138 |
++ struct kdbus_pool_slice *s; |
20139 |
++ struct kdbus_pool *p; |
20140 |
++ struct file *f; |
20141 |
++ char *n = NULL; |
20142 |
++ int ret; |
20143 |
++ |
20144 |
++ p = kzalloc(sizeof(*p), GFP_KERNEL); |
20145 |
++ if (!p) |
20146 |
++ return ERR_PTR(-ENOMEM); |
20147 |
++ |
20148 |
++ if (name) { |
20149 |
++ n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name); |
20150 |
++ if (!n) { |
20151 |
++ ret = -ENOMEM; |
20152 |
++ goto exit_free; |
20153 |
++ } |
20154 |
++ } |
20155 |
++ |
20156 |
++ f = shmem_file_setup(n ?: KBUILD_MODNAME "-conn", size, 0); |
20157 |
++ kfree(n); |
20158 |
++ |
20159 |
++ if (IS_ERR(f)) { |
20160 |
++ ret = PTR_ERR(f); |
20161 |
++ goto exit_free; |
20162 |
++ } |
20163 |
++ |
20164 |
++ ret = get_write_access(file_inode(f)); |
20165 |
++ if (ret < 0) |
20166 |
++ goto exit_put_shmem; |
20167 |
++ |
20168 |
++ /* allocate first slice spanning the entire pool */ |
20169 |
++ s = kdbus_pool_slice_new(p, 0, size); |
20170 |
++ if (!s) { |
20171 |
++ ret = -ENOMEM; |
20172 |
++ goto exit_put_write; |
20173 |
++ } |
20174 |
++ |
20175 |
++ p->f = f; |
20176 |
++ p->size = size; |
20177 |
++ p->slices_free = RB_ROOT; |
20178 |
++ p->slices_busy = RB_ROOT; |
20179 |
++ mutex_init(&p->lock); |
20180 |
++ |
20181 |
++ INIT_LIST_HEAD(&p->slices); |
20182 |
++ list_add(&s->entry, &p->slices); |
20183 |
++ |
20184 |
++ kdbus_pool_add_free_slice(p, s); |
20185 |
++ return p; |
20186 |
++ |
20187 |
++exit_put_write: |
20188 |
++ put_write_access(file_inode(f)); |
20189 |
++exit_put_shmem: |
20190 |
++ fput(f); |
20191 |
++exit_free: |
20192 |
++ kfree(p); |
20193 |
++ return ERR_PTR(ret); |
20194 |
++} |
20195 |
++ |
20196 |
++/** |
20197 |
++ * kdbus_pool_free() - destroy pool |
20198 |
++ * @pool: The receiver's pool |
20199 |
++ */ |
20200 |
++void kdbus_pool_free(struct kdbus_pool *pool) |
20201 |
++{ |
20202 |
++ struct kdbus_pool_slice *s, *tmp; |
20203 |
++ |
20204 |
++ if (!pool) |
20205 |
++ return; |
20206 |
++ |
20207 |
++ list_for_each_entry_safe(s, tmp, &pool->slices, entry) { |
20208 |
++ list_del(&s->entry); |
20209 |
++ kfree(s); |
20210 |
++ } |
20211 |
++ |
20212 |
++ put_write_access(file_inode(pool->f)); |
20213 |
++ fput(pool->f); |
20214 |
++ kfree(pool); |
20215 |
++} |
20216 |
++ |
20217 |
++/** |
20218 |
++ * kdbus_pool_accounted() - retrieve accounting information |
20219 |
++ * @pool: pool to query |
20220 |
++ * @size: output for overall pool size |
20221 |
++ * @acc: output for currently accounted size |
20222 |
++ * |
20223 |
++ * This returns accounting information of the pool. Note that the data might |
20224 |
++ * change after the function returns, as the pool lock is dropped. You need to |
20225 |
++ * protect the data via other means, if you need reliable accounting. |
20226 |
++ */ |
20227 |
++void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc) |
20228 |
++{ |
20229 |
++ mutex_lock(&pool->lock); |
20230 |
++ if (size) |
20231 |
++ *size = pool->size; |
20232 |
++ if (acc) |
20233 |
++ *acc = pool->accounted_size; |
20234 |
++ mutex_unlock(&pool->lock); |
20235 |
++} |
20236 |
++ |
20237 |
++/** |
20238 |
++ * kdbus_pool_slice_copy_iovec() - copy user memory to a slice |
20239 |
++ * @slice: The slice to write to |
20240 |
++ * @off: Offset in the slice to write to |
20241 |
++ * @iov: iovec array, pointing to data to copy |
20242 |
++ * @iov_len: Number of elements in @iov |
20243 |
++ * @total_len: Total number of bytes described in members of @iov |
20244 |
++ * |
20245 |
++ * User memory referenced by @iov will be copied into @slice at offset @off. |
20246 |
++ * |
20247 |
++ * Return: the numbers of bytes copied, negative errno on failure. |
20248 |
++ */ |
20249 |
++ssize_t |
20250 |
++kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, loff_t off, |
20251 |
++ struct iovec *iov, size_t iov_len, size_t total_len) |
20252 |
++{ |
20253 |
++ struct iov_iter iter; |
20254 |
++ ssize_t len; |
20255 |
++ |
20256 |
++ if (WARN_ON(off + total_len > slice->size)) |
20257 |
++ return -EFAULT; |
20258 |
++ |
20259 |
++ off += slice->off; |
20260 |
++ iov_iter_init(&iter, WRITE, iov, iov_len, total_len); |
20261 |
++ len = vfs_iter_write(slice->pool->f, &iter, &off); |
20262 |
++ |
20263 |
++ return (len >= 0 && len != total_len) ? -EFAULT : len; |
20264 |
++} |
20265 |
++ |
20266 |
++/** |
20267 |
++ * kdbus_pool_slice_copy_kvec() - copy kernel memory to a slice |
20268 |
++ * @slice: The slice to write to |
20269 |
++ * @off: Offset in the slice to write to |
20270 |
++ * @kvec: kvec array, pointing to data to copy |
20271 |
++ * @kvec_len: Number of elements in @kvec |
20272 |
++ * @total_len: Total number of bytes described in members of @kvec |
20273 |
++ * |
20274 |
++ * Kernel memory referenced by @kvec will be copied into @slice at offset @off. |
20275 |
++ * |
20276 |
++ * Return: the numbers of bytes copied, negative errno on failure. |
20277 |
++ */ |
20278 |
++ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, |
20279 |
++ loff_t off, struct kvec *kvec, |
20280 |
++ size_t kvec_len, size_t total_len) |
20281 |
++{ |
20282 |
++ struct iov_iter iter; |
20283 |
++ mm_segment_t old_fs; |
20284 |
++ ssize_t len; |
20285 |
++ |
20286 |
++ if (WARN_ON(off + total_len > slice->size)) |
20287 |
++ return -EFAULT; |
20288 |
++ |
20289 |
++ off += slice->off; |
20290 |
++ iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len); |
20291 |
++ |
20292 |
++ old_fs = get_fs(); |
20293 |
++ set_fs(get_ds()); |
20294 |
++ len = vfs_iter_write(slice->pool->f, &iter, &off); |
20295 |
++ set_fs(old_fs); |
20296 |
++ |
20297 |
++ return (len >= 0 && len != total_len) ? -EFAULT : len; |
20298 |
++} |
20299 |
++ |
20300 |
++/** |
20301 |
++ * kdbus_pool_slice_copy() - copy data from one slice into another |
20302 |
++ * @slice_dst: destination slice |
20303 |
++ * @slice_src: source slice |
20304 |
++ * |
20305 |
++ * Return: 0 on success, negative error number on failure. |
20306 |
++ */ |
20307 |
++int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, |
20308 |
++ const struct kdbus_pool_slice *slice_src) |
20309 |
++{ |
20310 |
++ struct file *f_src = slice_src->pool->f; |
20311 |
++ struct file *f_dst = slice_dst->pool->f; |
20312 |
++ struct inode *i_dst = file_inode(f_dst); |
20313 |
++ struct address_space *mapping_dst = f_dst->f_mapping; |
20314 |
++ const struct address_space_operations *aops = mapping_dst->a_ops; |
20315 |
++ unsigned long len = slice_src->size; |
20316 |
++ loff_t off_src = slice_src->off; |
20317 |
++ loff_t off_dst = slice_dst->off; |
20318 |
++ mm_segment_t old_fs; |
20319 |
++ int ret = 0; |
20320 |
++ |
20321 |
++ if (WARN_ON(slice_src->size != slice_dst->size) || |
20322 |
++ WARN_ON(slice_src->free || slice_dst->free)) |
20323 |
++ return -EINVAL; |
20324 |
++ |
20325 |
++ mutex_lock(&i_dst->i_mutex); |
20326 |
++ old_fs = get_fs(); |
20327 |
++ set_fs(get_ds()); |
20328 |
++ while (len > 0) { |
20329 |
++ unsigned long page_off; |
20330 |
++ unsigned long copy_len; |
20331 |
++ char __user *kaddr; |
20332 |
++ struct page *page; |
20333 |
++ ssize_t n_read; |
20334 |
++ void *fsdata; |
20335 |
++ long status; |
20336 |
++ |
20337 |
++ page_off = off_dst & (PAGE_CACHE_SIZE - 1); |
20338 |
++ copy_len = min_t(unsigned long, |
20339 |
++ PAGE_CACHE_SIZE - page_off, len); |
20340 |
++ |
20341 |
++ status = aops->write_begin(f_dst, mapping_dst, off_dst, |
20342 |
++ copy_len, 0, &page, &fsdata); |
20343 |
++ if (unlikely(status < 0)) { |
20344 |
++ ret = status; |
20345 |
++ break; |
20346 |
++ } |
20347 |
++ |
20348 |
++ kaddr = (char __force __user *)kmap(page) + page_off; |
20349 |
++ n_read = f_src->f_op->read(f_src, kaddr, copy_len, &off_src); |
20350 |
++ kunmap(page); |
20351 |
++ mark_page_accessed(page); |
20352 |
++ flush_dcache_page(page); |
20353 |
++ |
20354 |
++ if (unlikely(n_read != copy_len)) { |
20355 |
++ ret = -EFAULT; |
20356 |
++ break; |
20357 |
++ } |
20358 |
++ |
20359 |
++ status = aops->write_end(f_dst, mapping_dst, off_dst, |
20360 |
++ copy_len, copy_len, page, fsdata); |
20361 |
++ if (unlikely(status != copy_len)) { |
20362 |
++ ret = -EFAULT; |
20363 |
++ break; |
20364 |
++ } |
20365 |
++ |
20366 |
++ off_dst += copy_len; |
20367 |
++ len -= copy_len; |
20368 |
++ } |
20369 |
++ set_fs(old_fs); |
20370 |
++ mutex_unlock(&i_dst->i_mutex); |
20371 |
++ |
20372 |
++ return ret; |
20373 |
++} |
20374 |
++ |
20375 |
++/** |
20376 |
++ * kdbus_pool_mmap() - map the pool into the process |
20377 |
++ * @pool: The receiver's pool |
20378 |
++ * @vma: passed by mmap() syscall |
20379 |
++ * |
20380 |
++ * Return: the result of the mmap() call, negative errno on failure. |
20381 |
++ */ |
20382 |
++int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma) |
20383 |
++{ |
20384 |
++ /* deny write access to the pool */ |
20385 |
++ if (vma->vm_flags & VM_WRITE) |
20386 |
++ return -EPERM; |
20387 |
++ vma->vm_flags &= ~VM_MAYWRITE; |
20388 |
++ |
20389 |
++ /* do not allow to map more than the size of the file */ |
20390 |
++ if ((vma->vm_end - vma->vm_start) > pool->size) |
20391 |
++ return -EFAULT; |
20392 |
++ |
20393 |
++ /* replace the connection file with our shmem file */ |
20394 |
++ if (vma->vm_file) |
20395 |
++ fput(vma->vm_file); |
20396 |
++ vma->vm_file = get_file(pool->f); |
20397 |
++ |
20398 |
++ return pool->f->f_op->mmap(pool->f, vma); |
20399 |
++} |
20400 |
+diff --git a/ipc/kdbus/pool.h b/ipc/kdbus/pool.h |
20401 |
+new file mode 100644 |
20402 |
+index 0000000..a903821 |
20403 |
+--- /dev/null |
20404 |
++++ b/ipc/kdbus/pool.h |
20405 |
+@@ -0,0 +1,46 @@ |
20406 |
++/* |
20407 |
++ * Copyright (C) 2013-2015 Kay Sievers |
20408 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
20409 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
20410 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
20411 |
++ * Copyright (C) 2013-2015 Linux Foundation |
20412 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
20413 |
++ * |
20414 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
20415 |
++ * the terms of the GNU Lesser General Public License as published by the |
20416 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
20417 |
++ * your option) any later version. |
20418 |
++ */ |
20419 |
++ |
20420 |
++#ifndef __KDBUS_POOL_H |
20421 |
++#define __KDBUS_POOL_H |
20422 |
++ |
20423 |
++#include <linux/uio.h> |
20424 |
++ |
20425 |
++struct kdbus_pool; |
20426 |
++struct kdbus_pool_slice; |
20427 |
++ |
20428 |
++struct kdbus_pool *kdbus_pool_new(const char *name, size_t size); |
20429 |
++void kdbus_pool_free(struct kdbus_pool *pool); |
20430 |
++void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc); |
20431 |
++int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma); |
20432 |
++int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off); |
20433 |
++void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size); |
20434 |
++ |
20435 |
++struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, |
20436 |
++ size_t size, bool accounted); |
20437 |
++void kdbus_pool_slice_release(struct kdbus_pool_slice *slice); |
20438 |
++void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, |
20439 |
++ u64 *out_offset, u64 *out_size); |
20440 |
++off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice); |
20441 |
++size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice); |
20442 |
++int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, |
20443 |
++ const struct kdbus_pool_slice *slice_src); |
20444 |
++ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, |
20445 |
++ loff_t off, struct kvec *kvec, |
20446 |
++ size_t kvec_count, size_t total_len); |
20447 |
++ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, |
20448 |
++ loff_t off, struct iovec *iov, |
20449 |
++ size_t iov_count, size_t total_len); |
20450 |
++ |
20451 |
++#endif |
20452 |
+diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c |
20453 |
+new file mode 100644 |
20454 |
+index 0000000..a449464 |
20455 |
+--- /dev/null |
20456 |
++++ b/ipc/kdbus/queue.c |
20457 |
+@@ -0,0 +1,678 @@ |
20458 |
++/* |
20459 |
++ * Copyright (C) 2013-2015 Kay Sievers |
20460 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
20461 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
20462 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
20463 |
++ * Copyright (C) 2013-2015 Linux Foundation |
20464 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
20465 |
++ * |
20466 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
20467 |
++ * the terms of the GNU Lesser General Public License as published by the |
20468 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
20469 |
++ * your option) any later version. |
20470 |
++ */ |
20471 |
++ |
20472 |
++#include <linux/audit.h> |
20473 |
++#include <linux/file.h> |
20474 |
++#include <linux/fs.h> |
20475 |
++#include <linux/hashtable.h> |
20476 |
++#include <linux/idr.h> |
20477 |
++#include <linux/init.h> |
20478 |
++#include <linux/math64.h> |
20479 |
++#include <linux/mm.h> |
20480 |
++#include <linux/module.h> |
20481 |
++#include <linux/mutex.h> |
20482 |
++#include <linux/poll.h> |
20483 |
++#include <linux/sched.h> |
20484 |
++#include <linux/sizes.h> |
20485 |
++#include <linux/slab.h> |
20486 |
++#include <linux/syscalls.h> |
20487 |
++#include <linux/uio.h> |
20488 |
++ |
20489 |
++#include "util.h" |
20490 |
++#include "domain.h" |
20491 |
++#include "connection.h" |
20492 |
++#include "item.h" |
20493 |
++#include "message.h" |
20494 |
++#include "metadata.h" |
20495 |
++#include "queue.h" |
20496 |
++#include "reply.h" |
20497 |
++ |
20498 |
++/** |
20499 |
++ * kdbus_queue_init() - initialize data structure related to a queue |
20500 |
++ * @queue: The queue to initialize |
20501 |
++ */ |
20502 |
++void kdbus_queue_init(struct kdbus_queue *queue) |
20503 |
++{ |
20504 |
++ INIT_LIST_HEAD(&queue->msg_list); |
20505 |
++ queue->msg_prio_queue = RB_ROOT; |
20506 |
++} |
20507 |
++ |
20508 |
++/** |
20509 |
++ * kdbus_queue_peek() - Retrieves an entry from a queue |
20510 |
++ * @queue: The queue |
20511 |
++ * @priority: The minimum priority of the entry to peek |
20512 |
++ * @use_priority: Boolean flag whether or not to peek by priority |
20513 |
++ * |
20514 |
++ * Look for a entry in a queue, either by priority, or the oldest one (FIFO). |
20515 |
++ * The entry is not freed, put off the queue's lists or anything else. |
20516 |
++ * |
20517 |
++ * Return: the peeked queue entry on success, NULL if no suitable msg is found |
20518 |
++ */ |
20519 |
++struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, |
20520 |
++ s64 priority, bool use_priority) |
20521 |
++{ |
20522 |
++ struct kdbus_queue_entry *e; |
20523 |
++ |
20524 |
++ if (list_empty(&queue->msg_list)) |
20525 |
++ return NULL; |
20526 |
++ |
20527 |
++ if (use_priority) { |
20528 |
++ /* get next entry with highest priority */ |
20529 |
++ e = rb_entry(queue->msg_prio_highest, |
20530 |
++ struct kdbus_queue_entry, prio_node); |
20531 |
++ |
20532 |
++ /* no entry with the requested priority */ |
20533 |
++ if (e->priority > priority) |
20534 |
++ return NULL; |
20535 |
++ } else { |
20536 |
++ /* ignore the priority, return the next entry in the entry */ |
20537 |
++ e = list_first_entry(&queue->msg_list, |
20538 |
++ struct kdbus_queue_entry, entry); |
20539 |
++ } |
20540 |
++ |
20541 |
++ return e; |
20542 |
++} |
20543 |
++ |
20544 |
++static void kdbus_queue_entry_link(struct kdbus_queue_entry *entry) |
20545 |
++{ |
20546 |
++ struct kdbus_queue *queue = &entry->conn->queue; |
20547 |
++ struct rb_node **n, *pn = NULL; |
20548 |
++ bool highest = true; |
20549 |
++ |
20550 |
++ lockdep_assert_held(&entry->conn->lock); |
20551 |
++ if (WARN_ON(!list_empty(&entry->entry))) |
20552 |
++ return; |
20553 |
++ |
20554 |
++ /* sort into priority entry tree */ |
20555 |
++ n = &queue->msg_prio_queue.rb_node; |
20556 |
++ while (*n) { |
20557 |
++ struct kdbus_queue_entry *e; |
20558 |
++ |
20559 |
++ pn = *n; |
20560 |
++ e = rb_entry(pn, struct kdbus_queue_entry, prio_node); |
20561 |
++ |
20562 |
++ /* existing node for this priority, add to its list */ |
20563 |
++ if (likely(entry->priority == e->priority)) { |
20564 |
++ list_add_tail(&entry->prio_entry, &e->prio_entry); |
20565 |
++ goto prio_done; |
20566 |
++ } |
20567 |
++ |
20568 |
++ if (entry->priority < e->priority) { |
20569 |
++ n = &pn->rb_left; |
20570 |
++ } else { |
20571 |
++ n = &pn->rb_right; |
20572 |
++ highest = false; |
20573 |
++ } |
20574 |
++ } |
20575 |
++ |
20576 |
++ /* cache highest-priority entry */ |
20577 |
++ if (highest) |
20578 |
++ queue->msg_prio_highest = &entry->prio_node; |
20579 |
++ |
20580 |
++ /* new node for this priority */ |
20581 |
++ rb_link_node(&entry->prio_node, pn, n); |
20582 |
++ rb_insert_color(&entry->prio_node, &queue->msg_prio_queue); |
20583 |
++ INIT_LIST_HEAD(&entry->prio_entry); |
20584 |
++ |
20585 |
++prio_done: |
20586 |
++ /* add to unsorted fifo list */ |
20587 |
++ list_add_tail(&entry->entry, &queue->msg_list); |
20588 |
++} |
20589 |
++ |
20590 |
++static void kdbus_queue_entry_unlink(struct kdbus_queue_entry *entry) |
20591 |
++{ |
20592 |
++ struct kdbus_queue *queue = &entry->conn->queue; |
20593 |
++ |
20594 |
++ lockdep_assert_held(&entry->conn->lock); |
20595 |
++ if (list_empty(&entry->entry)) |
20596 |
++ return; |
20597 |
++ |
20598 |
++ list_del_init(&entry->entry); |
20599 |
++ |
20600 |
++ if (list_empty(&entry->prio_entry)) { |
20601 |
++ /* |
20602 |
++ * Single entry for this priority, update cached |
20603 |
++ * highest-priority entry, remove the tree node. |
20604 |
++ */ |
20605 |
++ if (queue->msg_prio_highest == &entry->prio_node) |
20606 |
++ queue->msg_prio_highest = rb_next(&entry->prio_node); |
20607 |
++ |
20608 |
++ rb_erase(&entry->prio_node, &queue->msg_prio_queue); |
20609 |
++ } else { |
20610 |
++ struct kdbus_queue_entry *q; |
20611 |
++ |
20612 |
++ /* |
20613 |
++ * Multiple entries for this priority entry, get next one in |
20614 |
++ * the list. Update cached highest-priority entry, store the |
20615 |
++ * new one as the tree node. |
20616 |
++ */ |
20617 |
++ q = list_first_entry(&entry->prio_entry, |
20618 |
++ struct kdbus_queue_entry, prio_entry); |
20619 |
++ list_del(&entry->prio_entry); |
20620 |
++ |
20621 |
++ if (queue->msg_prio_highest == &entry->prio_node) |
20622 |
++ queue->msg_prio_highest = &q->prio_node; |
20623 |
++ |
20624 |
++ rb_replace_node(&entry->prio_node, &q->prio_node, |
20625 |
++ &queue->msg_prio_queue); |
20626 |
++ } |
20627 |
++} |
20628 |
++ |
20629 |
++/** |
20630 |
++ * kdbus_queue_entry_new() - allocate a queue entry |
20631 |
++ * @conn_dst: destination connection |
20632 |
++ * @kmsg: kmsg object the queue entry should track |
20633 |
++ * @user: user to account message on (or NULL for kernel messages) |
20634 |
++ * |
20635 |
++ * Allocates a queue entry based on a given kmsg and allocate space for |
20636 |
++ * the message payload and the requested metadata in the connection's pool. |
20637 |
++ * The entry is not actually added to the queue's lists at this point. |
20638 |
++ * |
20639 |
++ * Return: the allocated entry on success, or an ERR_PTR on failures. |
20640 |
++ */ |
20641 |
++struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *conn_dst, |
20642 |
++ const struct kdbus_kmsg *kmsg, |
20643 |
++ struct kdbus_user *user) |
20644 |
++{ |
20645 |
++ struct kdbus_msg_resources *res = kmsg->res; |
20646 |
++ const struct kdbus_msg *msg = &kmsg->msg; |
20647 |
++ struct kdbus_queue_entry *entry; |
20648 |
++ size_t memfd_cnt = 0; |
20649 |
++ struct kvec kvec[2]; |
20650 |
++ size_t meta_size; |
20651 |
++ size_t msg_size; |
20652 |
++ u64 payload_off; |
20653 |
++ u64 size = 0; |
20654 |
++ int ret = 0; |
20655 |
++ |
20656 |
++ entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
20657 |
++ if (!entry) |
20658 |
++ return ERR_PTR(-ENOMEM); |
20659 |
++ |
20660 |
++ INIT_LIST_HEAD(&entry->entry); |
20661 |
++ entry->priority = msg->priority; |
20662 |
++ entry->dst_name_id = kmsg->dst_name_id; |
20663 |
++ entry->msg_res = kdbus_msg_resources_ref(res); |
20664 |
++ entry->proc_meta = kdbus_meta_proc_ref(kmsg->proc_meta); |
20665 |
++ entry->conn_meta = kdbus_meta_conn_ref(kmsg->conn_meta); |
20666 |
++ entry->conn = kdbus_conn_ref(conn_dst); |
20667 |
++ |
20668 |
++ if (kmsg->msg.src_id == KDBUS_SRC_ID_KERNEL) |
20669 |
++ msg_size = msg->size; |
20670 |
++ else |
20671 |
++ msg_size = offsetof(struct kdbus_msg, items); |
20672 |
++ |
20673 |
++ /* sum up the size of the needed slice */ |
20674 |
++ size = msg_size; |
20675 |
++ |
20676 |
++ if (res) { |
20677 |
++ size += res->vec_count * |
20678 |
++ KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
20679 |
++ |
20680 |
++ if (res->memfd_count) { |
20681 |
++ entry->memfd_offset = |
20682 |
++ kcalloc(res->memfd_count, sizeof(size_t), |
20683 |
++ GFP_KERNEL); |
20684 |
++ if (!entry->memfd_offset) { |
20685 |
++ ret = -ENOMEM; |
20686 |
++ goto exit_free_entry; |
20687 |
++ } |
20688 |
++ |
20689 |
++ size += res->memfd_count * |
20690 |
++ KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
20691 |
++ } |
20692 |
++ |
20693 |
++ if (res->fds_count) |
20694 |
++ size += KDBUS_ITEM_SIZE(sizeof(int) * res->fds_count); |
20695 |
++ |
20696 |
++ if (res->dst_name) |
20697 |
++ size += KDBUS_ITEM_SIZE(strlen(res->dst_name) + 1); |
20698 |
++ } |
20699 |
++ |
20700 |
++ /* |
20701 |
++ * Remember the offset of the metadata part, so we can override |
20702 |
++ * this part later during kdbus_queue_entry_install(). |
20703 |
++ */ |
20704 |
++ entry->meta_offset = size; |
20705 |
++ |
20706 |
++ if (entry->proc_meta || entry->conn_meta) { |
20707 |
++ entry->attach_flags = |
20708 |
++ atomic64_read(&conn_dst->attach_flags_recv); |
20709 |
++ |
20710 |
++ ret = kdbus_meta_export_prepare(entry->proc_meta, |
20711 |
++ entry->conn_meta, |
20712 |
++ &entry->attach_flags, |
20713 |
++ &meta_size); |
20714 |
++ if (ret < 0) |
20715 |
++ goto exit_free_entry; |
20716 |
++ |
20717 |
++ size += meta_size; |
20718 |
++ } |
20719 |
++ |
20720 |
++ payload_off = size; |
20721 |
++ size += kmsg->pool_size; |
20722 |
++ size = KDBUS_ALIGN8(size); |
20723 |
++ |
20724 |
++ ret = kdbus_conn_quota_inc(conn_dst, user, size, |
20725 |
++ res ? res->fds_count : 0); |
20726 |
++ if (ret < 0) |
20727 |
++ goto exit_free_entry; |
20728 |
++ |
20729 |
++ entry->slice = kdbus_pool_slice_alloc(conn_dst->pool, size, true); |
20730 |
++ if (IS_ERR(entry->slice)) { |
20731 |
++ ret = PTR_ERR(entry->slice); |
20732 |
++ entry->slice = NULL; |
20733 |
++ kdbus_conn_quota_dec(conn_dst, user, size, |
20734 |
++ res ? res->fds_count : 0); |
20735 |
++ goto exit_free_entry; |
20736 |
++ } |
20737 |
++ |
20738 |
++ /* we accounted for exactly 'size' bytes, make sure it didn't grow */ |
20739 |
++ WARN_ON(kdbus_pool_slice_size(entry->slice) != size); |
20740 |
++ entry->user = kdbus_user_ref(user); |
20741 |
++ |
20742 |
++ /* copy message header */ |
20743 |
++ kvec[0].iov_base = (char *)msg; |
20744 |
++ kvec[0].iov_len = msg_size; |
20745 |
++ |
20746 |
++ ret = kdbus_pool_slice_copy_kvec(entry->slice, 0, kvec, 1, msg_size); |
20747 |
++ if (ret < 0) |
20748 |
++ goto exit_free_entry; |
20749 |
++ |
20750 |
++ /* 'size' will now track the write position */ |
20751 |
++ size = msg_size; |
20752 |
++ |
20753 |
++ /* create message payload items */ |
20754 |
++ if (res) { |
20755 |
++ size_t dst_name_len = 0; |
20756 |
++ unsigned int i; |
20757 |
++ size_t sz = 0; |
20758 |
++ |
20759 |
++ if (res->dst_name) { |
20760 |
++ dst_name_len = strlen(res->dst_name) + 1; |
20761 |
++ sz += KDBUS_ITEM_SIZE(dst_name_len); |
20762 |
++ } |
20763 |
++ |
20764 |
++ for (i = 0; i < res->data_count; ++i) { |
20765 |
++ struct kdbus_vec v; |
20766 |
++ struct kdbus_memfd m; |
20767 |
++ |
20768 |
++ switch (res->data[i].type) { |
20769 |
++ case KDBUS_MSG_DATA_VEC: |
20770 |
++ sz += KDBUS_ITEM_SIZE(sizeof(v)); |
20771 |
++ break; |
20772 |
++ |
20773 |
++ case KDBUS_MSG_DATA_MEMFD: |
20774 |
++ sz += KDBUS_ITEM_SIZE(sizeof(m)); |
20775 |
++ break; |
20776 |
++ } |
20777 |
++ } |
20778 |
++ |
20779 |
++ if (sz) { |
20780 |
++ struct kdbus_item *items, *item; |
20781 |
++ |
20782 |
++ items = kmalloc(sz, GFP_KERNEL); |
20783 |
++ if (!items) { |
20784 |
++ ret = -ENOMEM; |
20785 |
++ goto exit_free_entry; |
20786 |
++ } |
20787 |
++ |
20788 |
++ item = items; |
20789 |
++ |
20790 |
++ if (res->dst_name) |
20791 |
++ item = kdbus_item_set(item, KDBUS_ITEM_DST_NAME, |
20792 |
++ res->dst_name, |
20793 |
++ dst_name_len); |
20794 |
++ |
20795 |
++ for (i = 0; i < res->data_count; ++i) { |
20796 |
++ struct kdbus_msg_data *d = res->data + i; |
20797 |
++ struct kdbus_memfd m = {}; |
20798 |
++ struct kdbus_vec v = {}; |
20799 |
++ |
20800 |
++ switch (d->type) { |
20801 |
++ case KDBUS_MSG_DATA_VEC: |
20802 |
++ v.size = d->size; |
20803 |
++ v.offset = d->vec.off; |
20804 |
++ if (v.offset != ~0ULL) |
20805 |
++ v.offset += payload_off; |
20806 |
++ |
20807 |
++ item = kdbus_item_set(item, |
20808 |
++ KDBUS_ITEM_PAYLOAD_OFF, |
20809 |
++ &v, sizeof(v)); |
20810 |
++ break; |
20811 |
++ |
20812 |
++ case KDBUS_MSG_DATA_MEMFD: |
20813 |
++ /* |
20814 |
++ * Remember the location of memfds, so |
20815 |
++ * we can override the content from |
20816 |
++ * kdbus_queue_entry_install(). |
20817 |
++ */ |
20818 |
++ entry->memfd_offset[memfd_cnt++] = |
20819 |
++ msg_size + |
20820 |
++ (char *)item - (char *)items + |
20821 |
++ offsetof(struct kdbus_item, |
20822 |
++ memfd); |
20823 |
++ |
20824 |
++ item = kdbus_item_set(item, |
20825 |
++ KDBUS_ITEM_PAYLOAD_MEMFD, |
20826 |
++ &m, sizeof(m)); |
20827 |
++ break; |
20828 |
++ } |
20829 |
++ } |
20830 |
++ |
20831 |
++ kvec[0].iov_base = items; |
20832 |
++ kvec[0].iov_len = sz; |
20833 |
++ |
20834 |
++ ret = kdbus_pool_slice_copy_kvec(entry->slice, size, |
20835 |
++ kvec, 1, sz); |
20836 |
++ kfree(items); |
20837 |
++ |
20838 |
++ if (ret < 0) |
20839 |
++ goto exit_free_entry; |
20840 |
++ |
20841 |
++ size += sz; |
20842 |
++ } |
20843 |
++ |
20844 |
++ /* |
20845 |
++ * Remember the location of the FD part, so we can override the |
20846 |
++ * content in kdbus_queue_entry_install(). |
20847 |
++ */ |
20848 |
++ if (res->fds_count) { |
20849 |
++ entry->fds_offset = size; |
20850 |
++ size += KDBUS_ITEM_SIZE(sizeof(int) * res->fds_count); |
20851 |
++ } |
20852 |
++ } |
20853 |
++ |
20854 |
++ /* finally, copy over the actual message payload */ |
20855 |
++ if (kmsg->iov_count) { |
20856 |
++ ret = kdbus_pool_slice_copy_iovec(entry->slice, payload_off, |
20857 |
++ kmsg->iov, |
20858 |
++ kmsg->iov_count, |
20859 |
++ kmsg->pool_size); |
20860 |
++ if (ret < 0) |
20861 |
++ goto exit_free_entry; |
20862 |
++ } |
20863 |
++ |
20864 |
++ return entry; |
20865 |
++ |
20866 |
++exit_free_entry: |
20867 |
++ kdbus_queue_entry_free(entry); |
20868 |
++ return ERR_PTR(ret); |
20869 |
++} |
20870 |
++ |
20871 |
++/** |
20872 |
++ * kdbus_queue_entry_free() - free resources of an entry |
20873 |
++ * @entry: The entry to free |
20874 |
++ * |
20875 |
++ * Removes resources allocated by a queue entry, along with the entry itself. |
20876 |
++ * Note that the entry's slice is not freed at this point. |
20877 |
++ */ |
20878 |
++void kdbus_queue_entry_free(struct kdbus_queue_entry *entry) |
20879 |
++{ |
20880 |
++ if (!entry) |
20881 |
++ return; |
20882 |
++ |
20883 |
++ lockdep_assert_held(&entry->conn->lock); |
20884 |
++ |
20885 |
++ kdbus_queue_entry_unlink(entry); |
20886 |
++ kdbus_reply_unref(entry->reply); |
20887 |
++ |
20888 |
++ if (entry->slice) { |
20889 |
++ kdbus_conn_quota_dec(entry->conn, entry->user, |
20890 |
++ kdbus_pool_slice_size(entry->slice), |
20891 |
++ entry->msg_res ? |
20892 |
++ entry->msg_res->fds_count : 0); |
20893 |
++ kdbus_pool_slice_release(entry->slice); |
20894 |
++ kdbus_user_unref(entry->user); |
20895 |
++ } |
20896 |
++ |
20897 |
++ kdbus_msg_resources_unref(entry->msg_res); |
20898 |
++ kdbus_meta_conn_unref(entry->conn_meta); |
20899 |
++ kdbus_meta_proc_unref(entry->proc_meta); |
20900 |
++ kdbus_conn_unref(entry->conn); |
20901 |
++ kfree(entry->memfd_offset); |
20902 |
++ kfree(entry); |
20903 |
++} |
20904 |
++ |
20905 |
++/** |
20906 |
++ * kdbus_queue_entry_install() - install message components into the |
20907 |
++ * receiver's process |
20908 |
++ * @entry: The queue entry to install |
20909 |
++ * @return_flags: Pointer to store the return flags for userspace |
20910 |
++ * @install_fds: Whether or not to install associated file descriptors |
20911 |
++ * |
20912 |
++ * This function will create a slice to transport the message header, the |
20913 |
++ * metadata items and other items for information stored in @entry, and |
20914 |
++ * store it as entry->slice. |
20915 |
++ * |
20916 |
++ * If @install_fds is %true, file descriptors will as well be installed. |
20917 |
++ * This function must always be called from the task context of the receiver. |
20918 |
++ * |
20919 |
++ * Return: 0 on success. |
20920 |
++ */ |
20921 |
++int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, |
20922 |
++ u64 *return_flags, bool install_fds) |
20923 |
++{ |
20924 |
++ u64 msg_size = entry->meta_offset; |
20925 |
++ struct kdbus_conn *conn_dst = entry->conn; |
20926 |
++ struct kdbus_msg_resources *res; |
20927 |
++ bool incomplete_fds = false; |
20928 |
++ struct kvec kvec[2]; |
20929 |
++ size_t memfds = 0; |
20930 |
++ int i, ret; |
20931 |
++ |
20932 |
++ lockdep_assert_held(&conn_dst->lock); |
20933 |
++ |
20934 |
++ if (entry->proc_meta || entry->conn_meta) { |
20935 |
++ size_t meta_size; |
20936 |
++ |
20937 |
++ ret = kdbus_meta_export(entry->proc_meta, |
20938 |
++ entry->conn_meta, |
20939 |
++ entry->attach_flags, |
20940 |
++ entry->slice, |
20941 |
++ entry->meta_offset, |
20942 |
++ &meta_size); |
20943 |
++ if (ret < 0) |
20944 |
++ return ret; |
20945 |
++ |
20946 |
++ msg_size += meta_size; |
20947 |
++ } |
20948 |
++ |
20949 |
++ /* Update message size at offset 0 */ |
20950 |
++ kvec[0].iov_base = &msg_size; |
20951 |
++ kvec[0].iov_len = sizeof(msg_size); |
20952 |
++ |
20953 |
++ ret = kdbus_pool_slice_copy_kvec(entry->slice, 0, kvec, 1, |
20954 |
++ sizeof(msg_size)); |
20955 |
++ if (ret < 0) |
20956 |
++ return ret; |
20957 |
++ |
20958 |
++ res = entry->msg_res; |
20959 |
++ |
20960 |
++ if (!res) |
20961 |
++ return 0; |
20962 |
++ |
20963 |
++ if (res->fds_count) { |
20964 |
++ struct kdbus_item_header hdr; |
20965 |
++ size_t off; |
20966 |
++ int *fds; |
20967 |
++ |
20968 |
++ fds = kmalloc_array(res->fds_count, sizeof(int), GFP_KERNEL); |
20969 |
++ if (!fds) |
20970 |
++ return -ENOMEM; |
20971 |
++ |
20972 |
++ for (i = 0; i < res->fds_count; i++) { |
20973 |
++ if (install_fds) { |
20974 |
++ fds[i] = get_unused_fd_flags(O_CLOEXEC); |
20975 |
++ if (fds[i] >= 0) |
20976 |
++ fd_install(fds[i], |
20977 |
++ get_file(res->fds[i])); |
20978 |
++ else |
20979 |
++ incomplete_fds = true; |
20980 |
++ } else { |
20981 |
++ fds[i] = -1; |
20982 |
++ } |
20983 |
++ } |
20984 |
++ |
20985 |
++ off = entry->fds_offset; |
20986 |
++ |
20987 |
++ hdr.type = KDBUS_ITEM_FDS; |
20988 |
++ hdr.size = KDBUS_ITEM_HEADER_SIZE + |
20989 |
++ sizeof(int) * res->fds_count; |
20990 |
++ |
20991 |
++ kvec[0].iov_base = &hdr; |
20992 |
++ kvec[0].iov_len = sizeof(hdr); |
20993 |
++ |
20994 |
++ kvec[1].iov_base = fds; |
20995 |
++ kvec[1].iov_len = sizeof(int) * res->fds_count; |
20996 |
++ |
20997 |
++ ret = kdbus_pool_slice_copy_kvec(entry->slice, off, |
20998 |
++ kvec, 2, hdr.size); |
20999 |
++ kfree(fds); |
21000 |
++ |
21001 |
++ if (ret < 0) |
21002 |
++ return ret; |
21003 |
++ } |
21004 |
++ |
21005 |
++ for (i = 0; i < res->data_count; ++i) { |
21006 |
++ struct kdbus_msg_data *d = res->data + i; |
21007 |
++ struct kdbus_memfd m; |
21008 |
++ |
21009 |
++ if (d->type != KDBUS_MSG_DATA_MEMFD) |
21010 |
++ continue; |
21011 |
++ |
21012 |
++ m.start = d->memfd.start; |
21013 |
++ m.size = d->size; |
21014 |
++ m.fd = -1; |
21015 |
++ |
21016 |
++ if (install_fds) { |
21017 |
++ m.fd = get_unused_fd_flags(O_CLOEXEC); |
21018 |
++ if (m.fd < 0) { |
21019 |
++ m.fd = -1; |
21020 |
++ incomplete_fds = true; |
21021 |
++ } else { |
21022 |
++ fd_install(m.fd, |
21023 |
++ get_file(d->memfd.file)); |
21024 |
++ } |
21025 |
++ } |
21026 |
++ |
21027 |
++ kvec[0].iov_base = &m; |
21028 |
++ kvec[0].iov_len = sizeof(m); |
21029 |
++ |
21030 |
++ ret = kdbus_pool_slice_copy_kvec(entry->slice, |
21031 |
++ entry->memfd_offset[memfds++], |
21032 |
++ kvec, 1, sizeof(m)); |
21033 |
++ if (ret < 0) |
21034 |
++ return ret; |
21035 |
++ } |
21036 |
++ |
21037 |
++ if (incomplete_fds) |
21038 |
++ *return_flags |= KDBUS_RECV_RETURN_INCOMPLETE_FDS; |
21039 |
++ |
21040 |
++ return 0; |
21041 |
++} |
21042 |
++ |
21043 |
++/** |
21044 |
++ * kdbus_queue_entry_enqueue() - enqueue an entry |
21045 |
++ * @entry: entry to enqueue |
21046 |
++ * @reply: reply to link to this entry (or NULL if none) |
21047 |
++ * |
21048 |
++ * This enqueues an unqueued entry into the message queue of the linked |
21049 |
++ * connection. It also binds a reply object to the entry so we can remember it |
21050 |
++ * when the message is moved. |
21051 |
++ * |
21052 |
++ * Once this call returns (and the connection lock is released), this entry can |
21053 |
++ * be dequeued by the target connection. Note that the entry will not be removed |
21054 |
++ * from the queue until it is destroyed. |
21055 |
++ */ |
21056 |
++void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, |
21057 |
++ struct kdbus_reply *reply) |
21058 |
++{ |
21059 |
++ lockdep_assert_held(&entry->conn->lock); |
21060 |
++ |
21061 |
++ if (WARN_ON(entry->reply) || WARN_ON(!list_empty(&entry->entry))) |
21062 |
++ return; |
21063 |
++ |
21064 |
++ entry->reply = kdbus_reply_ref(reply); |
21065 |
++ kdbus_queue_entry_link(entry); |
21066 |
++} |
21067 |
++ |
21068 |
++/** |
21069 |
++ * kdbus_queue_entry_move() - move queue entry |
21070 |
++ * @e: queue entry to move |
21071 |
++ * @dst: destination connection to queue the entry on |
21072 |
++ * |
21073 |
++ * This moves a queue entry onto a different connection. It allocates a new |
21074 |
++ * slice on the target connection and copies the message over. If the copy |
21075 |
++ * succeeded, we move the entry from @src to @dst. |
21076 |
++ * |
21077 |
++ * On failure, the entry is left untouched. |
21078 |
++ * |
21079 |
++ * The queue entry must be queued right now, and after the call succeeds it will |
21080 |
++ * be queued on the destination, but no longer on the source. |
21081 |
++ * |
21082 |
++ * The caller must hold the connection lock of the source *and* destination. |
21083 |
++ * |
21084 |
++ * Return: 0 on success, negative error code on failure. |
21085 |
++ */ |
21086 |
++int kdbus_queue_entry_move(struct kdbus_queue_entry *e, |
21087 |
++ struct kdbus_conn *dst) |
21088 |
++{ |
21089 |
++ struct kdbus_pool_slice *slice = NULL; |
21090 |
++ struct kdbus_conn *src = e->conn; |
21091 |
++ size_t size, fds; |
21092 |
++ int ret; |
21093 |
++ |
21094 |
++ lockdep_assert_held(&src->lock); |
21095 |
++ lockdep_assert_held(&dst->lock); |
21096 |
++ |
21097 |
++ if (WARN_ON(IS_ERR(e->user)) || WARN_ON(list_empty(&e->entry))) |
21098 |
++ return -EINVAL; |
21099 |
++ if (src == dst) |
21100 |
++ return 0; |
21101 |
++ |
21102 |
++ size = kdbus_pool_slice_size(e->slice); |
21103 |
++ fds = e->msg_res ? e->msg_res->fds_count : 0; |
21104 |
++ |
21105 |
++ ret = kdbus_conn_quota_inc(dst, e->user, size, fds); |
21106 |
++ if (ret < 0) |
21107 |
++ return ret; |
21108 |
++ |
21109 |
++ slice = kdbus_pool_slice_alloc(dst->pool, size, true); |
21110 |
++ if (IS_ERR(slice)) { |
21111 |
++ ret = PTR_ERR(slice); |
21112 |
++ slice = NULL; |
21113 |
++ goto error; |
21114 |
++ } |
21115 |
++ |
21116 |
++ ret = kdbus_pool_slice_copy(slice, e->slice); |
21117 |
++ if (ret < 0) |
21118 |
++ goto error; |
21119 |
++ |
21120 |
++ kdbus_queue_entry_unlink(e); |
21121 |
++ kdbus_conn_quota_dec(src, e->user, size, fds); |
21122 |
++ kdbus_pool_slice_release(e->slice); |
21123 |
++ kdbus_conn_unref(e->conn); |
21124 |
++ |
21125 |
++ e->slice = slice; |
21126 |
++ e->conn = kdbus_conn_ref(dst); |
21127 |
++ kdbus_queue_entry_link(e); |
21128 |
++ |
21129 |
++ return 0; |
21130 |
++ |
21131 |
++error: |
21132 |
++ kdbus_pool_slice_release(slice); |
21133 |
++ kdbus_conn_quota_dec(dst, e->user, size, fds); |
21134 |
++ return ret; |
21135 |
++} |
21136 |
+diff --git a/ipc/kdbus/queue.h b/ipc/kdbus/queue.h |
21137 |
+new file mode 100644 |
21138 |
+index 0000000..7f2db96 |
21139 |
+--- /dev/null |
21140 |
++++ b/ipc/kdbus/queue.h |
21141 |
+@@ -0,0 +1,92 @@ |
21142 |
++/* |
21143 |
++ * Copyright (C) 2013-2015 Kay Sievers |
21144 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21145 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21146 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21147 |
++ * Copyright (C) 2013-2015 Linux Foundation |
21148 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21149 |
++ * |
21150 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
21151 |
++ * the terms of the GNU Lesser General Public License as published by the |
21152 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
21153 |
++ * your option) any later version. |
21154 |
++ */ |
21155 |
++ |
21156 |
++#ifndef __KDBUS_QUEUE_H |
21157 |
++#define __KDBUS_QUEUE_H |
21158 |
++ |
21159 |
++struct kdbus_user; |
21160 |
++ |
21161 |
++/** |
21162 |
++ * struct kdbus_queue - a connection's message queue |
21163 |
++ * @msg_list: List head for kdbus_queue_entry objects |
21164 |
++ * @msg_prio_queue: RB tree root for messages, sorted by priority |
21165 |
++ * @msg_prio_highest: Link to the RB node referencing the message with the |
21166 |
++ * highest priority in the tree. |
21167 |
++ */ |
21168 |
++struct kdbus_queue { |
21169 |
++ struct list_head msg_list; |
21170 |
++ struct rb_root msg_prio_queue; |
21171 |
++ struct rb_node *msg_prio_highest; |
21172 |
++}; |
21173 |
++ |
21174 |
++/** |
21175 |
++ * struct kdbus_queue_entry - messages waiting to be read |
21176 |
++ * @entry: Entry in the connection's list |
21177 |
++ * @prio_node: Entry in the priority queue tree |
21178 |
++ * @prio_entry: Queue tree node entry in the list of one priority |
21179 |
++ * @slice: Slice in the receiver's pool for the message |
21180 |
++ * @attach_flags: Attach flags used during slice allocation |
21181 |
++ * @meta_offset: Offset of first metadata item in slice |
21182 |
++ * @fds_offset: Offset of FD item in slice |
21183 |
++ * @memfd_offset: Array of slice-offsets for all memfd items |
21184 |
++ * @priority: Message priority |
21185 |
++ * @dst_name_id: The sequence number of the name this message is |
21186 |
++ * addressed to, 0 for messages sent to an ID |
21187 |
++ * @msg_res: Message resources |
21188 |
++ * @proc_meta: Process metadata, captured at message arrival |
21189 |
++ * @conn_meta: Connection metadata, captured at message arrival |
21190 |
++ * @reply: The reply block if a reply to this message is expected |
21191 |
++ * @user: User used for accounting |
21192 |
++ */ |
21193 |
++struct kdbus_queue_entry { |
21194 |
++ struct list_head entry; |
21195 |
++ struct rb_node prio_node; |
21196 |
++ struct list_head prio_entry; |
21197 |
++ |
21198 |
++ struct kdbus_pool_slice *slice; |
21199 |
++ |
21200 |
++ u64 attach_flags; |
21201 |
++ size_t meta_offset; |
21202 |
++ size_t fds_offset; |
21203 |
++ size_t *memfd_offset; |
21204 |
++ |
21205 |
++ s64 priority; |
21206 |
++ u64 dst_name_id; |
21207 |
++ |
21208 |
++ struct kdbus_msg_resources *msg_res; |
21209 |
++ struct kdbus_meta_proc *proc_meta; |
21210 |
++ struct kdbus_meta_conn *conn_meta; |
21211 |
++ struct kdbus_reply *reply; |
21212 |
++ struct kdbus_conn *conn; |
21213 |
++ struct kdbus_user *user; |
21214 |
++}; |
21215 |
++ |
21216 |
++struct kdbus_kmsg; |
21217 |
++ |
21218 |
++void kdbus_queue_init(struct kdbus_queue *queue); |
21219 |
++struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, |
21220 |
++ s64 priority, bool use_priority); |
21221 |
++ |
21222 |
++struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *conn_dst, |
21223 |
++ const struct kdbus_kmsg *kmsg, |
21224 |
++ struct kdbus_user *user); |
21225 |
++void kdbus_queue_entry_free(struct kdbus_queue_entry *entry); |
21226 |
++int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, |
21227 |
++ u64 *return_flags, bool install_fds); |
21228 |
++void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, |
21229 |
++ struct kdbus_reply *reply); |
21230 |
++int kdbus_queue_entry_move(struct kdbus_queue_entry *entry, |
21231 |
++ struct kdbus_conn *dst); |
21232 |
++ |
21233 |
++#endif /* __KDBUS_QUEUE_H */ |
21234 |
+diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c |
21235 |
+new file mode 100644 |
21236 |
+index 0000000..008dca8 |
21237 |
+--- /dev/null |
21238 |
++++ b/ipc/kdbus/reply.c |
21239 |
+@@ -0,0 +1,257 @@ |
21240 |
++#include <linux/init.h> |
21241 |
++#include <linux/mm.h> |
21242 |
++#include <linux/module.h> |
21243 |
++#include <linux/mutex.h> |
21244 |
++#include <linux/slab.h> |
21245 |
++#include <linux/uio.h> |
21246 |
++ |
21247 |
++#include "bus.h" |
21248 |
++#include "connection.h" |
21249 |
++#include "endpoint.h" |
21250 |
++#include "message.h" |
21251 |
++#include "metadata.h" |
21252 |
++#include "names.h" |
21253 |
++#include "domain.h" |
21254 |
++#include "item.h" |
21255 |
++#include "notify.h" |
21256 |
++#include "policy.h" |
21257 |
++#include "reply.h" |
21258 |
++#include "util.h" |
21259 |
++ |
21260 |
++/** |
21261 |
++ * kdbus_reply_new() - Allocate and set up a new kdbus_reply object |
21262 |
++ * @reply_src: The connection a reply is expected from |
21263 |
++ * @reply_dst: The connection this reply object belongs to |
21264 |
++ * @msg: Message associated with the reply |
21265 |
++ * @name_entry: Name entry used to send the message |
21266 |
++ * @sync: Whether or not to make this reply synchronous |
21267 |
++ * |
21268 |
++ * Allocate and fill a new kdbus_reply object. |
21269 |
++ * |
21270 |
++ * Return: New kdbus_conn object on success, ERR_PTR on error. |
21271 |
++ */ |
21272 |
++struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, |
21273 |
++ struct kdbus_conn *reply_dst, |
21274 |
++ const struct kdbus_msg *msg, |
21275 |
++ struct kdbus_name_entry *name_entry, |
21276 |
++ bool sync) |
21277 |
++{ |
21278 |
++ struct kdbus_reply *r; |
21279 |
++ int ret = 0; |
21280 |
++ |
21281 |
++ if (atomic_inc_return(&reply_dst->request_count) > |
21282 |
++ KDBUS_CONN_MAX_REQUESTS_PENDING) { |
21283 |
++ ret = -EMLINK; |
21284 |
++ goto exit_dec_request_count; |
21285 |
++ } |
21286 |
++ |
21287 |
++ r = kzalloc(sizeof(*r), GFP_KERNEL); |
21288 |
++ if (!r) { |
21289 |
++ ret = -ENOMEM; |
21290 |
++ goto exit_dec_request_count; |
21291 |
++ } |
21292 |
++ |
21293 |
++ kref_init(&r->kref); |
21294 |
++ INIT_LIST_HEAD(&r->entry); |
21295 |
++ r->reply_src = kdbus_conn_ref(reply_src); |
21296 |
++ r->reply_dst = kdbus_conn_ref(reply_dst); |
21297 |
++ r->cookie = msg->cookie; |
21298 |
++ r->name_id = name_entry ? name_entry->name_id : 0; |
21299 |
++ r->deadline_ns = msg->timeout_ns; |
21300 |
++ |
21301 |
++ if (sync) { |
21302 |
++ r->sync = true; |
21303 |
++ r->waiting = true; |
21304 |
++ } |
21305 |
++ |
21306 |
++exit_dec_request_count: |
21307 |
++ if (ret < 0) { |
21308 |
++ atomic_dec(&reply_dst->request_count); |
21309 |
++ return ERR_PTR(ret); |
21310 |
++ } |
21311 |
++ |
21312 |
++ return r; |
21313 |
++} |
21314 |
++ |
21315 |
++static void __kdbus_reply_free(struct kref *kref) |
21316 |
++{ |
21317 |
++ struct kdbus_reply *reply = |
21318 |
++ container_of(kref, struct kdbus_reply, kref); |
21319 |
++ |
21320 |
++ atomic_dec(&reply->reply_dst->request_count); |
21321 |
++ kdbus_conn_unref(reply->reply_src); |
21322 |
++ kdbus_conn_unref(reply->reply_dst); |
21323 |
++ kfree(reply); |
21324 |
++} |
21325 |
++ |
21326 |
++/** |
21327 |
++ * kdbus_reply_ref() - Increase reference on kdbus_reply |
21328 |
++ * @r: The reply, may be %NULL |
21329 |
++ * |
21330 |
++ * Return: The reply object with an extra reference |
21331 |
++ */ |
21332 |
++struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r) |
21333 |
++{ |
21334 |
++ if (r) |
21335 |
++ kref_get(&r->kref); |
21336 |
++ return r; |
21337 |
++} |
21338 |
++ |
21339 |
++/** |
21340 |
++ * kdbus_reply_unref() - Decrease reference on kdbus_reply |
21341 |
++ * @r: The reply, may be %NULL |
21342 |
++ * |
21343 |
++ * Return: NULL |
21344 |
++ */ |
21345 |
++struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r) |
21346 |
++{ |
21347 |
++ if (r) |
21348 |
++ kref_put(&r->kref, __kdbus_reply_free); |
21349 |
++ return NULL; |
21350 |
++} |
21351 |
++ |
21352 |
++/** |
21353 |
++ * kdbus_reply_link() - Link reply object into target connection |
21354 |
++ * @r: Reply to link |
21355 |
++ */ |
21356 |
++void kdbus_reply_link(struct kdbus_reply *r) |
21357 |
++{ |
21358 |
++ if (WARN_ON(!list_empty(&r->entry))) |
21359 |
++ return; |
21360 |
++ |
21361 |
++ list_add(&r->entry, &r->reply_dst->reply_list); |
21362 |
++ kdbus_reply_ref(r); |
21363 |
++} |
21364 |
++ |
21365 |
++/** |
21366 |
++ * kdbus_reply_unlink() - Unlink reply object from target connection |
21367 |
++ * @r: Reply to unlink |
21368 |
++ */ |
21369 |
++void kdbus_reply_unlink(struct kdbus_reply *r) |
21370 |
++{ |
21371 |
++ if (!list_empty(&r->entry)) { |
21372 |
++ list_del_init(&r->entry); |
21373 |
++ kdbus_reply_unref(r); |
21374 |
++ } |
21375 |
++} |
21376 |
++ |
21377 |
++/** |
21378 |
++ * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply |
21379 |
++ * @reply: The reply object |
21380 |
++ * @err: Error code to set on the remote side |
21381 |
++ * |
21382 |
++ * Remove the synchronous reply object from its connection reply_list, and |
21383 |
++ * wake up remote peer (method origin) with the appropriate synchronous reply |
21384 |
++ * code. |
21385 |
++ */ |
21386 |
++void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err) |
21387 |
++{ |
21388 |
++ if (WARN_ON(!reply->sync)) |
21389 |
++ return; |
21390 |
++ |
21391 |
++ reply->waiting = false; |
21392 |
++ reply->err = err; |
21393 |
++ wake_up_interruptible(&reply->reply_dst->wait); |
21394 |
++} |
21395 |
++ |
21396 |
++/** |
21397 |
++ * kdbus_reply_find() - Find the corresponding reply object |
21398 |
++ * @replying: The replying connection or NULL |
21399 |
++ * @reply_dst: The connection the reply will be sent to |
21400 |
++ * (method origin) |
21401 |
++ * @cookie: The cookie of the requesting message |
21402 |
++ * |
21403 |
++ * Lookup a reply object that should be sent as a reply by |
21404 |
++ * @replying to @reply_dst with the given cookie. |
21405 |
++ * |
21406 |
++ * Callers must take the @reply_dst lock. |
21407 |
++ * |
21408 |
++ * Return: the corresponding reply object or NULL if not found |
21409 |
++ */ |
21410 |
++struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, |
21411 |
++ struct kdbus_conn *reply_dst, |
21412 |
++ u64 cookie) |
21413 |
++{ |
21414 |
++ struct kdbus_reply *r, *reply = NULL; |
21415 |
++ |
21416 |
++ list_for_each_entry(r, &reply_dst->reply_list, entry) { |
21417 |
++ if (r->cookie == cookie && |
21418 |
++ (!replying || r->reply_src == replying)) { |
21419 |
++ reply = r; |
21420 |
++ break; |
21421 |
++ } |
21422 |
++ } |
21423 |
++ |
21424 |
++ return reply; |
21425 |
++} |
21426 |
++ |
21427 |
++/** |
21428 |
++ * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a |
21429 |
++ * connection for exceeded timeouts |
21430 |
++ * @work: Work struct of the connection to scan |
21431 |
++ * |
21432 |
++ * Walk the list of replies stored with a connection and look for entries |
21433 |
++ * that have exceeded their timeout. If such an entry is found, a timeout |
21434 |
++ * notification is sent to the waiting peer, and the reply is removed from |
21435 |
++ * the list. |
21436 |
++ * |
21437 |
++ * The work is rescheduled to the nearest timeout found during the list |
21438 |
++ * iteration. |
21439 |
++ */ |
21440 |
++void kdbus_reply_list_scan_work(struct work_struct *work) |
21441 |
++{ |
21442 |
++ struct kdbus_conn *conn = |
21443 |
++ container_of(work, struct kdbus_conn, work.work); |
21444 |
++ struct kdbus_reply *reply, *reply_tmp; |
21445 |
++ u64 deadline = ~0ULL; |
21446 |
++ u64 now; |
21447 |
++ |
21448 |
++ now = ktime_get_ns(); |
21449 |
++ |
21450 |
++ mutex_lock(&conn->lock); |
21451 |
++ if (!kdbus_conn_active(conn)) { |
21452 |
++ mutex_unlock(&conn->lock); |
21453 |
++ return; |
21454 |
++ } |
21455 |
++ |
21456 |
++ list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) { |
21457 |
++ /* |
21458 |
++ * If the reply block is waiting for synchronous I/O, |
21459 |
++ * the timeout is handled by wait_event_*_timeout(), |
21460 |
++ * so we don't have to care for it here. |
21461 |
++ */ |
21462 |
++ if (reply->sync && !reply->interrupted) |
21463 |
++ continue; |
21464 |
++ |
21465 |
++ WARN_ON(reply->reply_dst != conn); |
21466 |
++ |
21467 |
++ if (reply->deadline_ns > now) { |
21468 |
++ /* remember next timeout */ |
21469 |
++ if (deadline > reply->deadline_ns) |
21470 |
++ deadline = reply->deadline_ns; |
21471 |
++ |
21472 |
++ continue; |
21473 |
++ } |
21474 |
++ |
21475 |
++ /* |
21476 |
++ * A zero deadline means the connection died, was |
21477 |
++ * cleaned up already and the notification was sent. |
21478 |
++ * Don't send notifications for reply trackers that were |
21479 |
++ * left in an interrupted syscall state. |
21480 |
++ */ |
21481 |
++ if (reply->deadline_ns != 0 && !reply->interrupted) |
21482 |
++ kdbus_notify_reply_timeout(conn->ep->bus, conn->id, |
21483 |
++ reply->cookie); |
21484 |
++ |
21485 |
++ kdbus_reply_unlink(reply); |
21486 |
++ } |
21487 |
++ |
21488 |
++ /* rearm delayed work with next timeout */ |
21489 |
++ if (deadline != ~0ULL) |
21490 |
++ schedule_delayed_work(&conn->work, |
21491 |
++ nsecs_to_jiffies(deadline - now)); |
21492 |
++ |
21493 |
++ mutex_unlock(&conn->lock); |
21494 |
++ |
21495 |
++ kdbus_notify_flush(conn->ep->bus); |
21496 |
++} |
21497 |
+diff --git a/ipc/kdbus/reply.h b/ipc/kdbus/reply.h |
21498 |
+new file mode 100644 |
21499 |
+index 0000000..68d5232 |
21500 |
+--- /dev/null |
21501 |
++++ b/ipc/kdbus/reply.h |
21502 |
+@@ -0,0 +1,68 @@ |
21503 |
++/* |
21504 |
++ * Copyright (C) 2013-2015 Kay Sievers |
21505 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21506 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21507 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21508 |
++ * Copyright (C) 2013-2015 Linux Foundation |
21509 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21510 |
++ * |
21511 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
21512 |
++ * the terms of the GNU Lesser General Public License as published by the |
21513 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
21514 |
++ * your option) any later version. |
21515 |
++ */ |
21516 |
++ |
21517 |
++#ifndef __KDBUS_REPLY_H |
21518 |
++#define __KDBUS_REPLY_H |
21519 |
++ |
21520 |
++/** |
21521 |
++ * struct kdbus_reply - an entry of kdbus_conn's list of replies |
21522 |
++ * @kref: Ref-count of this object |
21523 |
++ * @entry: The entry of the connection's reply_list |
21524 |
++ * @reply_src: The connection the reply will be sent from |
21525 |
++ * @reply_dst: The connection the reply will be sent to |
21526 |
++ * @queue_entry: The queue entry item that is prepared by the replying |
21527 |
++ * connection |
21528 |
++ * @deadline_ns: The deadline of the reply, in nanoseconds |
21529 |
++ * @cookie: The cookie of the requesting message |
21530 |
++ * @name_id: ID of the well-known name the original msg was sent to |
21531 |
++ * @sync: The reply block is waiting for synchronous I/O |
21532 |
++ * @waiting: The condition to synchronously wait for |
21533 |
++ * @interrupted: The sync reply was left in an interrupted state |
21534 |
++ * @err: The error code for the synchronous reply |
21535 |
++ */ |
21536 |
++struct kdbus_reply { |
21537 |
++ struct kref kref; |
21538 |
++ struct list_head entry; |
21539 |
++ struct kdbus_conn *reply_src; |
21540 |
++ struct kdbus_conn *reply_dst; |
21541 |
++ struct kdbus_queue_entry *queue_entry; |
21542 |
++ u64 deadline_ns; |
21543 |
++ u64 cookie; |
21544 |
++ u64 name_id; |
21545 |
++ bool sync:1; |
21546 |
++ bool waiting:1; |
21547 |
++ bool interrupted:1; |
21548 |
++ int err; |
21549 |
++}; |
21550 |
++ |
21551 |
++struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, |
21552 |
++ struct kdbus_conn *reply_dst, |
21553 |
++ const struct kdbus_msg *msg, |
21554 |
++ struct kdbus_name_entry *name_entry, |
21555 |
++ bool sync); |
21556 |
++ |
21557 |
++struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r); |
21558 |
++struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r); |
21559 |
++ |
21560 |
++void kdbus_reply_link(struct kdbus_reply *r); |
21561 |
++void kdbus_reply_unlink(struct kdbus_reply *r); |
21562 |
++ |
21563 |
++struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, |
21564 |
++ struct kdbus_conn *reply_dst, |
21565 |
++ u64 cookie); |
21566 |
++ |
21567 |
++void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err); |
21568 |
++void kdbus_reply_list_scan_work(struct work_struct *work); |
21569 |
++ |
21570 |
++#endif /* __KDBUS_REPLY_H */ |
21571 |
+diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c |
21572 |
+new file mode 100644 |
21573 |
+index 0000000..eaa806a |
21574 |
+--- /dev/null |
21575 |
++++ b/ipc/kdbus/util.c |
21576 |
+@@ -0,0 +1,201 @@ |
21577 |
++/* |
21578 |
++ * Copyright (C) 2013-2015 Kay Sievers |
21579 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21580 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21581 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21582 |
++ * Copyright (C) 2013-2015 Linux Foundation |
21583 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21584 |
++ * |
21585 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
21586 |
++ * the terms of the GNU Lesser General Public License as published by the |
21587 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
21588 |
++ * your option) any later version. |
21589 |
++ */ |
21590 |
++ |
21591 |
++#include <linux/capability.h> |
21592 |
++#include <linux/cred.h> |
21593 |
++#include <linux/ctype.h> |
21594 |
++#include <linux/err.h> |
21595 |
++#include <linux/file.h> |
21596 |
++#include <linux/slab.h> |
21597 |
++#include <linux/string.h> |
21598 |
++#include <linux/uaccess.h> |
21599 |
++#include <linux/uio.h> |
21600 |
++#include <linux/user_namespace.h> |
21601 |
++ |
21602 |
++#include "limits.h" |
21603 |
++#include "util.h" |
21604 |
++ |
21605 |
++/** |
21606 |
++ * kdbus_copy_from_user() - copy aligned data from user-space |
21607 |
++ * @dest: target buffer in kernel memory |
21608 |
++ * @user_ptr: user-provided source buffer |
21609 |
++ * @size: memory size to copy from user |
21610 |
++ * |
21611 |
++ * This copies @size bytes from @user_ptr into the kernel, just like |
21612 |
++ * copy_from_user() does. But we enforce an 8-byte alignment and reject any |
21613 |
++ * unaligned user-space pointers. |
21614 |
++ * |
21615 |
++ * Return: 0 on success, negative error code on failure. |
21616 |
++ */ |
21617 |
++int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size) |
21618 |
++{ |
21619 |
++ if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr)) |
21620 |
++ return -EFAULT; |
21621 |
++ |
21622 |
++ if (copy_from_user(dest, user_ptr, size)) |
21623 |
++ return -EFAULT; |
21624 |
++ |
21625 |
++ return 0; |
21626 |
++} |
21627 |
++ |
21628 |
++/** |
21629 |
++ * kdbus_memdup_user() - copy dynamically sized object from user-space |
21630 |
++ * @user_ptr: user-provided source buffer |
21631 |
++ * @sz_min: minimum object size |
21632 |
++ * @sz_max: maximum object size |
21633 |
++ * |
21634 |
++ * This copies a dynamically sized object from user-space into kernel-space. We |
21635 |
++ * require the object to have a 64bit size field at offset 0. We read it out |
21636 |
++ * first, allocate a suitably sized buffer and then copy all data. |
21637 |
++ * |
21638 |
++ * The @sz_min and @sz_max parameters define possible min and max object sizes |
21639 |
++ * so user-space cannot trigger un-bound kernel-space allocations. |
21640 |
++ * |
21641 |
++ * The same alignment-restrictions as described in kdbus_copy_from_user() apply. |
21642 |
++ * |
21643 |
++ * Return: pointer to dynamically allocated copy, or ERR_PTR() on failure. |
21644 |
++ */ |
21645 |
++void *kdbus_memdup_user(void __user *user_ptr, size_t sz_min, size_t sz_max) |
21646 |
++{ |
21647 |
++ void *ptr; |
21648 |
++ u64 size; |
21649 |
++ int ret; |
21650 |
++ |
21651 |
++ ret = kdbus_copy_from_user(&size, user_ptr, sizeof(size)); |
21652 |
++ if (ret < 0) |
21653 |
++ return ERR_PTR(ret); |
21654 |
++ |
21655 |
++ if (size < sz_min) |
21656 |
++ return ERR_PTR(-EINVAL); |
21657 |
++ |
21658 |
++ if (size > sz_max) |
21659 |
++ return ERR_PTR(-EMSGSIZE); |
21660 |
++ |
21661 |
++ ptr = memdup_user(user_ptr, size); |
21662 |
++ if (IS_ERR(ptr)) |
21663 |
++ return ptr; |
21664 |
++ |
21665 |
++ if (*(u64 *)ptr != size) { |
21666 |
++ kfree(ptr); |
21667 |
++ return ERR_PTR(-EINVAL); |
21668 |
++ } |
21669 |
++ |
21670 |
++ return ptr; |
21671 |
++} |
21672 |
++ |
21673 |
++/** |
21674 |
++ * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name |
21675 |
++ * @name: user-supplied name to verify |
21676 |
++ * @user_ns: user-namespace to act in |
21677 |
++ * @kuid: Kernel internal uid of user |
21678 |
++ * |
21679 |
++ * This verifies that the user-supplied name @name has their UID as prefix. This |
21680 |
++ * is the default name-spacing policy we enforce on user-supplied names for |
21681 |
++ * public kdbus entities like buses and endpoints. |
21682 |
++ * |
21683 |
++ * The user must supply names prefixed with "<UID>-", whereas the UID is |
21684 |
++ * interpreted in the user-namespace of the domain. If the user fails to supply |
21685 |
++ * such a prefixed name, we reject it. |
21686 |
++ * |
21687 |
++ * Return: 0 on success, negative error code on failure |
21688 |
++ */ |
21689 |
++int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, |
21690 |
++ kuid_t kuid) |
21691 |
++{ |
21692 |
++ uid_t uid; |
21693 |
++ char prefix[16]; |
21694 |
++ |
21695 |
++ /* |
21696 |
++ * The kuid must have a mapping into the userns of the domain |
21697 |
++ * otherwise do not allow creation of buses nor endpoints. |
21698 |
++ */ |
21699 |
++ uid = from_kuid(user_ns, kuid); |
21700 |
++ if (uid == (uid_t) -1) |
21701 |
++ return -EINVAL; |
21702 |
++ |
21703 |
++ snprintf(prefix, sizeof(prefix), "%u-", uid); |
21704 |
++ if (strncmp(name, prefix, strlen(prefix)) != 0) |
21705 |
++ return -EINVAL; |
21706 |
++ |
21707 |
++ return 0; |
21708 |
++} |
21709 |
++ |
21710 |
++/** |
21711 |
++ * kdbus_sanitize_attach_flags() - Sanitize attach flags from user-space |
21712 |
++ * @flags: Attach flags provided by userspace |
21713 |
++ * @attach_flags: A pointer where to store the valid attach flags |
21714 |
++ * |
21715 |
++ * Convert attach-flags provided by user-space into a valid mask. If the mask |
21716 |
++ * is invalid, an error is returned. The sanitized attach flags are stored in |
21717 |
++ * the output parameter. |
21718 |
++ * |
21719 |
++ * Return: 0 on success, negative error on failure. |
21720 |
++ */ |
21721 |
++int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags) |
21722 |
++{ |
21723 |
++ /* 'any' degrades to 'all' for compatibility */ |
21724 |
++ if (flags == _KDBUS_ATTACH_ANY) |
21725 |
++ flags = _KDBUS_ATTACH_ALL; |
21726 |
++ |
21727 |
++ /* reject unknown attach flags */ |
21728 |
++ if (flags & ~_KDBUS_ATTACH_ALL) |
21729 |
++ return -EINVAL; |
21730 |
++ |
21731 |
++ *attach_flags = flags; |
21732 |
++ return 0; |
21733 |
++} |
21734 |
++ |
21735 |
++/** |
21736 |
++ * kdbus_kvec_set - helper utility to assemble kvec arrays |
21737 |
++ * @kvec: kvec entry to use |
21738 |
++ * @src: Source address to set in @kvec |
21739 |
++ * @len: Number of bytes in @src |
21740 |
++ * @total_len: Pointer to total length variable |
21741 |
++ * |
21742 |
++ * Set @src and @len in @kvec, and increase @total_len by @len. |
21743 |
++ */ |
21744 |
++void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len) |
21745 |
++{ |
21746 |
++ kvec->iov_base = src; |
21747 |
++ kvec->iov_len = len; |
21748 |
++ *total_len += len; |
21749 |
++} |
21750 |
++ |
21751 |
++static const char * const zeros = "\0\0\0\0\0\0\0"; |
21752 |
++ |
21753 |
++/** |
21754 |
++ * kdbus_kvec_pad - conditionally write a padding kvec |
21755 |
++ * @kvec: kvec entry to use |
21756 |
++ * @len: Total length used for kvec array |
21757 |
++ * |
21758 |
++ * Check if the current total byte length of the array in @len is aligned to |
21759 |
++ * 8 bytes. If it isn't, fill @kvec with padding information and increase @len |
21760 |
++ * by the number of bytes stored in @kvec. |
21761 |
++ * |
21762 |
++ * Return: the number of added padding bytes. |
21763 |
++ */ |
21764 |
++size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len) |
21765 |
++{ |
21766 |
++ size_t pad = KDBUS_ALIGN8(*len) - *len; |
21767 |
++ |
21768 |
++ if (!pad) |
21769 |
++ return 0; |
21770 |
++ |
21771 |
++ kvec->iov_base = (void *)zeros; |
21772 |
++ kvec->iov_len = pad; |
21773 |
++ |
21774 |
++ *len += pad; |
21775 |
++ |
21776 |
++ return pad; |
21777 |
++} |
21778 |
+diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h |
21779 |
+new file mode 100644 |
21780 |
+index 0000000..740b198 |
21781 |
+--- /dev/null |
21782 |
++++ b/ipc/kdbus/util.h |
21783 |
+@@ -0,0 +1,74 @@ |
21784 |
++/* |
21785 |
++ * Copyright (C) 2013-2015 Kay Sievers |
21786 |
++ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21787 |
++ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21788 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21789 |
++ * Copyright (C) 2013-2015 Linux Foundation |
21790 |
++ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21791 |
++ * |
21792 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
21793 |
++ * the terms of the GNU Lesser General Public License as published by the |
21794 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
21795 |
++ * your option) any later version. |
21796 |
++ */ |
21797 |
++ |
21798 |
++#ifndef __KDBUS_UTIL_H |
21799 |
++#define __KDBUS_UTIL_H |
21800 |
++ |
21801 |
++#include <linux/dcache.h> |
21802 |
++#include <linux/ioctl.h> |
21803 |
++ |
21804 |
++#include <uapi/linux/kdbus.h> |
21805 |
++ |
21806 |
++/* all exported addresses are 64 bit */ |
21807 |
++#define KDBUS_PTR(addr) ((void __user *)(uintptr_t)(addr)) |
21808 |
++ |
21809 |
++/* all exported sizes are 64 bit and data aligned to 64 bit */ |
21810 |
++#define KDBUS_ALIGN8(s) ALIGN((s), 8) |
21811 |
++#define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8)) |
21812 |
++ |
21813 |
++/** |
21814 |
++ * kdbus_member_set_user - write a structure member to user memory |
21815 |
++ * @_s: Variable to copy from |
21816 |
++ * @_b: Buffer to write to |
21817 |
++ * @_t: Structure type |
21818 |
++ * @_m: Member name in the passed structure |
21819 |
++ * |
21820 |
++ * Return: the result of copy_to_user() |
21821 |
++ */ |
21822 |
++#define kdbus_member_set_user(_s, _b, _t, _m) \ |
21823 |
++({ \ |
21824 |
++ u64 __user *_sz = \ |
21825 |
++ (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \ |
21826 |
++ copy_to_user(_sz, _s, sizeof(((_t *)0)->_m)); \ |
21827 |
++}) |
21828 |
++ |
21829 |
++/** |
21830 |
++ * kdbus_strhash - calculate a hash |
21831 |
++ * @str: String |
21832 |
++ * |
21833 |
++ * Return: hash value |
21834 |
++ */ |
21835 |
++static inline unsigned int kdbus_strhash(const char *str) |
21836 |
++{ |
21837 |
++ unsigned long hash = init_name_hash(); |
21838 |
++ |
21839 |
++ while (*str) |
21840 |
++ hash = partial_name_hash(*str++, hash); |
21841 |
++ |
21842 |
++ return end_name_hash(hash); |
21843 |
++} |
21844 |
++ |
21845 |
++int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, |
21846 |
++ kuid_t kuid); |
21847 |
++int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags); |
21848 |
++ |
21849 |
++int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size); |
21850 |
++void *kdbus_memdup_user(void __user *user_ptr, size_t sz_min, size_t sz_max); |
21851 |
++ |
21852 |
++struct kvec; |
21853 |
++ |
21854 |
++void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len); |
21855 |
++size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len); |
21856 |
++ |
21857 |
++#endif |
21858 |
+diff --git a/samples/Kconfig b/samples/Kconfig |
21859 |
+index 224ebb4..a4c6b2f 100644 |
21860 |
+--- a/samples/Kconfig |
21861 |
++++ b/samples/Kconfig |
21862 |
+@@ -55,6 +55,13 @@ config SAMPLE_KDB |
21863 |
+ Build an example of how to dynamically add the hello |
21864 |
+ command to the kdb shell. |
21865 |
+ |
21866 |
++config SAMPLE_KDBUS |
21867 |
++ bool "Build kdbus API example" |
21868 |
++ depends on KDBUS |
21869 |
++ help |
21870 |
++ Build an example of how the kdbus API can be used from |
21871 |
++ userspace. |
21872 |
++ |
21873 |
+ config SAMPLE_RPMSG_CLIENT |
21874 |
+ tristate "Build rpmsg client sample -- loadable modules only" |
21875 |
+ depends on RPMSG && m |
21876 |
+diff --git a/samples/Makefile b/samples/Makefile |
21877 |
+index f00257b..f0ad51e 100644 |
21878 |
+--- a/samples/Makefile |
21879 |
++++ b/samples/Makefile |
21880 |
+@@ -1,4 +1,5 @@ |
21881 |
+ # Makefile for Linux samples code |
21882 |
+ |
21883 |
+ obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ |
21884 |
+- hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ |
21885 |
++ hw_breakpoint/ kfifo/ kdb/ kdbus/ hidraw/ rpmsg/ \ |
21886 |
++ seccomp/ |
21887 |
+diff --git a/samples/kdbus/.gitignore b/samples/kdbus/.gitignore |
21888 |
+new file mode 100644 |
21889 |
+index 0000000..ee07d98 |
21890 |
+--- /dev/null |
21891 |
++++ b/samples/kdbus/.gitignore |
21892 |
+@@ -0,0 +1 @@ |
21893 |
++kdbus-workers |
21894 |
+diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile |
21895 |
+new file mode 100644 |
21896 |
+index 0000000..137f842 |
21897 |
+--- /dev/null |
21898 |
++++ b/samples/kdbus/Makefile |
21899 |
+@@ -0,0 +1,9 @@ |
21900 |
++# kbuild trick to avoid linker error. Can be omitted if a module is built. |
21901 |
++obj- := dummy.o |
21902 |
++ |
21903 |
++hostprogs-$(CONFIG_SAMPLE_KDBUS) += kdbus-workers |
21904 |
++ |
21905 |
++always := $(hostprogs-y) |
21906 |
++ |
21907 |
++HOSTCFLAGS_kdbus-workers.o += -I$(objtree)/usr/include |
21908 |
++HOSTLOADLIBES_kdbus-workers := -lrt |
21909 |
+diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h |
21910 |
+new file mode 100644 |
21911 |
+index 0000000..5ed5907 |
21912 |
+--- /dev/null |
21913 |
++++ b/samples/kdbus/kdbus-api.h |
21914 |
+@@ -0,0 +1,114 @@ |
21915 |
++#ifndef KDBUS_API_H |
21916 |
++#define KDBUS_API_H |
21917 |
++ |
21918 |
++#include <sys/ioctl.h> |
21919 |
++#include <linux/kdbus.h> |
21920 |
++ |
21921 |
++#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) |
21922 |
++#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
21923 |
++#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) |
21924 |
++#define KDBUS_ITEM_NEXT(item) \ |
21925 |
++ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size)) |
21926 |
++#define KDBUS_FOREACH(iter, first, _size) \ |
21927 |
++ for (iter = (first); \ |
21928 |
++ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ |
21929 |
++ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ |
21930 |
++ iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size))) |
21931 |
++ |
21932 |
++static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd) |
21933 |
++{ |
21934 |
++ int ret = ioctl(control_fd, KDBUS_CMD_BUS_MAKE, cmd); |
21935 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21936 |
++} |
21937 |
++ |
21938 |
++static inline int kdbus_cmd_endpoint_make(int bus_fd, struct kdbus_cmd *cmd) |
21939 |
++{ |
21940 |
++ int ret = ioctl(bus_fd, KDBUS_CMD_ENDPOINT_MAKE, cmd); |
21941 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21942 |
++} |
21943 |
++ |
21944 |
++static inline int kdbus_cmd_endpoint_update(int ep_fd, struct kdbus_cmd *cmd) |
21945 |
++{ |
21946 |
++ int ret = ioctl(ep_fd, KDBUS_CMD_ENDPOINT_UPDATE, cmd); |
21947 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21948 |
++} |
21949 |
++ |
21950 |
++static inline int kdbus_cmd_hello(int bus_fd, struct kdbus_cmd_hello *cmd) |
21951 |
++{ |
21952 |
++ int ret = ioctl(bus_fd, KDBUS_CMD_HELLO, cmd); |
21953 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21954 |
++} |
21955 |
++ |
21956 |
++static inline int kdbus_cmd_update(int fd, struct kdbus_cmd *cmd) |
21957 |
++{ |
21958 |
++ int ret = ioctl(fd, KDBUS_CMD_UPDATE, cmd); |
21959 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21960 |
++} |
21961 |
++ |
21962 |
++static inline int kdbus_cmd_byebye(int conn_fd, struct kdbus_cmd *cmd) |
21963 |
++{ |
21964 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_BYEBYE, cmd); |
21965 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21966 |
++} |
21967 |
++ |
21968 |
++static inline int kdbus_cmd_free(int conn_fd, struct kdbus_cmd_free *cmd) |
21969 |
++{ |
21970 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_FREE, cmd); |
21971 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21972 |
++} |
21973 |
++ |
21974 |
++static inline int kdbus_cmd_conn_info(int conn_fd, struct kdbus_cmd_info *cmd) |
21975 |
++{ |
21976 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_CONN_INFO, cmd); |
21977 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21978 |
++} |
21979 |
++ |
21980 |
++static inline int kdbus_cmd_bus_creator_info(int conn_fd, struct kdbus_cmd_info *cmd) |
21981 |
++{ |
21982 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_BUS_CREATOR_INFO, cmd); |
21983 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21984 |
++} |
21985 |
++ |
21986 |
++static inline int kdbus_cmd_list(int fd, struct kdbus_cmd_list *cmd) |
21987 |
++{ |
21988 |
++ int ret = ioctl(fd, KDBUS_CMD_LIST, cmd); |
21989 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21990 |
++} |
21991 |
++ |
21992 |
++static inline int kdbus_cmd_send(int conn_fd, struct kdbus_cmd_send *cmd) |
21993 |
++{ |
21994 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_SEND, cmd); |
21995 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
21996 |
++} |
21997 |
++ |
21998 |
++static inline int kdbus_cmd_recv(int conn_fd, struct kdbus_cmd_recv *cmd) |
21999 |
++{ |
22000 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_RECV, cmd); |
22001 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22002 |
++} |
22003 |
++ |
22004 |
++static inline int kdbus_cmd_name_acquire(int conn_fd, struct kdbus_cmd *cmd) |
22005 |
++{ |
22006 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_ACQUIRE, cmd); |
22007 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22008 |
++} |
22009 |
++ |
22010 |
++static inline int kdbus_cmd_name_release(int conn_fd, struct kdbus_cmd *cmd) |
22011 |
++{ |
22012 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_RELEASE, cmd); |
22013 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22014 |
++} |
22015 |
++ |
22016 |
++static inline int kdbus_cmd_match_add(int conn_fd, struct kdbus_cmd_match *cmd) |
22017 |
++{ |
22018 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_ADD, cmd); |
22019 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22020 |
++} |
22021 |
++ |
22022 |
++static inline int kdbus_cmd_match_remove(int conn_fd, struct kdbus_cmd_match *cmd) |
22023 |
++{ |
22024 |
++ int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_REMOVE, cmd); |
22025 |
++ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22026 |
++} |
22027 |
++ |
22028 |
++#endif /* KDBUS_API_H */ |
22029 |
+diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c |
22030 |
+new file mode 100644 |
22031 |
+index 0000000..d331e01 |
22032 |
+--- /dev/null |
22033 |
++++ b/samples/kdbus/kdbus-workers.c |
22034 |
+@@ -0,0 +1,1326 @@ |
22035 |
++/* |
22036 |
++ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
22037 |
++ * |
22038 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
22039 |
++ * the terms of the GNU Lesser General Public License as published by the |
22040 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
22041 |
++ * your option) any later version. |
22042 |
++ */ |
22043 |
++ |
22044 |
++/* |
22045 |
++ * Example: Workers |
22046 |
++ * This program computes prime-numbers based on the sieve of Eratosthenes. The |
22047 |
++ * master sets up a shared memory region and spawns workers which clear out the |
22048 |
++ * non-primes. The master reacts to keyboard input and to client-requests to |
22049 |
++ * control what each worker does. Note that this is in no way meant as efficient |
22050 |
++ * way to compute primes. It should only serve as example how a master/worker |
22051 |
++ * concept can be implemented with kdbus used as control messages. |
22052 |
++ * |
22053 |
++ * The main process is called the 'master'. It creates a new, private bus which |
22054 |
++ * will be used between the master and its workers to communicate. The master |
22055 |
++ * then spawns a fixed number of workers. Whenever a worker dies (detected via |
22056 |
++ * SIGCHLD), the master spawns a new worker. When done, the master waits for all |
22057 |
++ * workers to exit, prints a status report and exits itself. |
22058 |
++ * |
22059 |
++ * The master process does *not* keep track of its workers. Instead, this |
22060 |
++ * example implements a PULL model. That is, the master acquires a well-known |
22061 |
++ * name on the bus which each worker uses to request tasks from the master. If |
22062 |
++ * there are no more tasks, the master will return an empty task-list, which |
22063 |
++ * casues a worker to exit immediately. |
22064 |
++ * |
22065 |
++ * As tasks can be computationally expensive, we support cancellation. Whenever |
22066 |
++ * the master process is interrupted, it will drop its well-known name on the |
22067 |
++ * bus. This causes kdbus to broadcast a name-change notification. The workers |
22068 |
++ * check for broadcast messages regularly and will exit if they receive one. |
22069 |
++ * |
22070 |
++ * This example exists of 4 objects: |
22071 |
++ * * master: The master object contains the context of the master process. This |
22072 |
++ * process manages the prime-context, spawns workers and assigns |
22073 |
++ * prime-ranges to each worker to compute. |
22074 |
++ * The master itself does not do any prime-computations itself. |
22075 |
++ * * child: The child object contains the context of a worker. It inherits the |
22076 |
++ * prime context from its parent (the master) and then creates a new |
22077 |
++ * bus context to request prime-ranges to compute. |
22078 |
++ * * prime: The "prime" object is used to abstract how we compute primes. When |
22079 |
++ * allocated, it prepares a memory region to hold 1 bit for each |
22080 |
++ * natural number up to a fixed maximum ('MAX_PRIMES'). |
22081 |
++ * The memory region is backed by a memfd which we share between |
22082 |
++ * processes. Each worker now gets assigned a range of natural |
22083 |
++ * numbers which it clears multiples of off the memory region. The |
22084 |
++ * master process is responsible of distributing all natural numbers |
22085 |
++ * up to the fixed maximum to its workers. |
22086 |
++ * * bus: The bus object is an abstraction of the kdbus API. It is pretty |
22087 |
++ * straightfoward and only manages the connection-fd plus the |
22088 |
++ * memory-mapped pool in a single object. |
22089 |
++ * |
22090 |
++ * This example is in reversed order, which should make it easier to read |
22091 |
++ * top-down, but requires some forward-declarations. Just ignore those. |
22092 |
++ */ |
22093 |
++ |
22094 |
++#include <ctype.h> |
22095 |
++#include <errno.h> |
22096 |
++#include <fcntl.h> |
22097 |
++#include <linux/memfd.h> |
22098 |
++#include <signal.h> |
22099 |
++#include <stdbool.h> |
22100 |
++#include <stddef.h> |
22101 |
++#include <stdint.h> |
22102 |
++#include <stdio.h> |
22103 |
++#include <stdlib.h> |
22104 |
++#include <string.h> |
22105 |
++#include <sys/mman.h> |
22106 |
++#include <sys/poll.h> |
22107 |
++#include <sys/signalfd.h> |
22108 |
++#include <sys/syscall.h> |
22109 |
++#include <sys/time.h> |
22110 |
++#include <sys/wait.h> |
22111 |
++#include <time.h> |
22112 |
++#include <unistd.h> |
22113 |
++#include "kdbus-api.h" |
22114 |
++ |
22115 |
++/* FORWARD DECLARATIONS */ |
22116 |
++ |
22117 |
++#define POOL_SIZE (16 * 1024 * 1024) |
22118 |
++#define MAX_PRIMES (2UL << 24) |
22119 |
++#define WORKER_COUNT (16) |
22120 |
++#define PRIME_STEPS (65536 * 4) |
22121 |
++ |
22122 |
++static const char *arg_busname = "example-workers"; |
22123 |
++static const char *arg_modname = "kdbus"; |
22124 |
++static const char *arg_master = "org.freedesktop.master"; |
22125 |
++ |
22126 |
++static int err_assert(int r_errno, const char *msg, const char *func, int line, |
22127 |
++ const char *file) |
22128 |
++{ |
22129 |
++ r_errno = (r_errno != 0) ? -abs(r_errno) : -EFAULT; |
22130 |
++ if (r_errno < 0) { |
22131 |
++ errno = -r_errno; |
22132 |
++ fprintf(stderr, "ERR: %s: %m (%s:%d in %s)\n", |
22133 |
++ msg, func, line, file); |
22134 |
++ } |
22135 |
++ return r_errno; |
22136 |
++} |
22137 |
++ |
22138 |
++#define err_r(_r, _msg) err_assert((_r), (_msg), __func__, __LINE__, __FILE__) |
22139 |
++#define err(_msg) err_r(errno, (_msg)) |
22140 |
++ |
22141 |
++struct prime; |
22142 |
++struct bus; |
22143 |
++struct master; |
22144 |
++struct child; |
22145 |
++ |
22146 |
++struct prime { |
22147 |
++ int fd; |
22148 |
++ uint8_t *area; |
22149 |
++ size_t max; |
22150 |
++ size_t done; |
22151 |
++ size_t status; |
22152 |
++}; |
22153 |
++ |
22154 |
++static int prime_new(struct prime **out); |
22155 |
++static void prime_free(struct prime *p); |
22156 |
++static bool prime_done(struct prime *p); |
22157 |
++static void prime_consume(struct prime *p, size_t amount); |
22158 |
++static int prime_run(struct prime *p, struct bus *cancel, size_t number); |
22159 |
++static void prime_print(struct prime *p); |
22160 |
++ |
22161 |
++struct bus { |
22162 |
++ int fd; |
22163 |
++ uint8_t *pool; |
22164 |
++}; |
22165 |
++ |
22166 |
++static int bus_open_connection(struct bus **out, uid_t uid, const char *name, |
22167 |
++ uint64_t recv_flags); |
22168 |
++static void bus_close_connection(struct bus *b); |
22169 |
++static void bus_poool_free_slice(struct bus *b, uint64_t offset); |
22170 |
++static int bus_acquire_name(struct bus *b, const char *name); |
22171 |
++static int bus_install_name_loss_match(struct bus *b, const char *name); |
22172 |
++static int bus_poll(struct bus *b); |
22173 |
++static int bus_make(uid_t uid, const char *name); |
22174 |
++ |
22175 |
++struct master { |
22176 |
++ size_t n_workers; |
22177 |
++ size_t max_workers; |
22178 |
++ |
22179 |
++ int signal_fd; |
22180 |
++ int control_fd; |
22181 |
++ |
22182 |
++ struct prime *prime; |
22183 |
++ struct bus *bus; |
22184 |
++}; |
22185 |
++ |
22186 |
++static int master_new(struct master **out); |
22187 |
++static void master_free(struct master *m); |
22188 |
++static int master_run(struct master *m); |
22189 |
++static int master_poll(struct master *m); |
22190 |
++static int master_handle_stdin(struct master *m); |
22191 |
++static int master_handle_signal(struct master *m); |
22192 |
++static int master_handle_bus(struct master *m); |
22193 |
++static int master_reply(struct master *m, const struct kdbus_msg *msg); |
22194 |
++static int master_waitpid(struct master *m); |
22195 |
++static int master_spawn(struct master *m); |
22196 |
++ |
22197 |
++struct child { |
22198 |
++ struct bus *bus; |
22199 |
++ struct prime *prime; |
22200 |
++}; |
22201 |
++ |
22202 |
++static int child_new(struct child **out, struct prime *p); |
22203 |
++static void child_free(struct child *c); |
22204 |
++static int child_run(struct child *c); |
22205 |
++ |
22206 |
++/* END OF FORWARD DECLARATIONS */ |
22207 |
++ |
22208 |
++/* |
22209 |
++ * This is the main entrypoint of this example. It is pretty straightforward. We |
22210 |
++ * create a master object, run the computation, print a status report and then |
22211 |
++ * exit. Nothing particularly interesting here, so lets look into the master |
22212 |
++ * object... |
22213 |
++ */ |
22214 |
++int main(int argc, char **argv) |
22215 |
++{ |
22216 |
++ struct master *m = NULL; |
22217 |
++ int r; |
22218 |
++ |
22219 |
++ r = master_new(&m); |
22220 |
++ if (r < 0) |
22221 |
++ goto out; |
22222 |
++ |
22223 |
++ r = master_run(m); |
22224 |
++ if (r < 0) |
22225 |
++ goto out; |
22226 |
++ |
22227 |
++ if (0) |
22228 |
++ prime_print(m->prime); |
22229 |
++ |
22230 |
++out: |
22231 |
++ master_free(m); |
22232 |
++ if (r < 0 && r != -EINTR) |
22233 |
++ fprintf(stderr, "failed\n"); |
22234 |
++ else |
22235 |
++ fprintf(stderr, "done\n"); |
22236 |
++ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
22237 |
++} |
22238 |
++ |
22239 |
++/* |
22240 |
++ * ...this will allocate a new master context. It keeps track of the current |
22241 |
++ * number of children/workers that are running, manages a signalfd to track |
22242 |
++ * SIGCHLD, and creates a private kdbus bus. Afterwards, it opens its connection |
22243 |
++ * to the bus and acquires a well known-name (arg_master). |
22244 |
++ */ |
22245 |
++static int master_new(struct master **out) |
22246 |
++{ |
22247 |
++ struct master *m; |
22248 |
++ sigset_t smask; |
22249 |
++ int r; |
22250 |
++ |
22251 |
++ m = calloc(1, sizeof(*m)); |
22252 |
++ if (!m) |
22253 |
++ return err("cannot allocate master"); |
22254 |
++ |
22255 |
++ m->max_workers = WORKER_COUNT; |
22256 |
++ m->signal_fd = -1; |
22257 |
++ m->control_fd = -1; |
22258 |
++ |
22259 |
++ /* Block SIGINT and SIGCHLD signals */ |
22260 |
++ sigemptyset(&smask); |
22261 |
++ sigaddset(&smask, SIGINT); |
22262 |
++ sigaddset(&smask, SIGCHLD); |
22263 |
++ sigprocmask(SIG_BLOCK, &smask, NULL); |
22264 |
++ |
22265 |
++ m->signal_fd = signalfd(-1, &smask, SFD_CLOEXEC); |
22266 |
++ if (m->signal_fd < 0) { |
22267 |
++ r = err("cannot create signalfd"); |
22268 |
++ goto error; |
22269 |
++ } |
22270 |
++ |
22271 |
++ r = prime_new(&m->prime); |
22272 |
++ if (r < 0) |
22273 |
++ goto error; |
22274 |
++ |
22275 |
++ m->control_fd = bus_make(getuid(), arg_busname); |
22276 |
++ if (m->control_fd < 0) { |
22277 |
++ r = m->control_fd; |
22278 |
++ goto error; |
22279 |
++ } |
22280 |
++ |
22281 |
++ /* |
22282 |
++ * Open a bus connection for the master, and require each received |
22283 |
++ * message to have a metadata item of type KDBUS_ITEM_PIDS attached. |
22284 |
++ * The current UID is needed to compute the name of the bus node to |
22285 |
++ * connect to. |
22286 |
++ */ |
22287 |
++ r = bus_open_connection(&m->bus, getuid(), |
22288 |
++ arg_busname, KDBUS_ATTACH_PIDS); |
22289 |
++ if (r < 0) |
22290 |
++ goto error; |
22291 |
++ |
22292 |
++ /* |
22293 |
++ * Acquire a well-known name on the bus, so children can address |
22294 |
++ * messages to the master using KDBUS_DST_ID_NAME as destination-ID |
22295 |
++ * of messages. |
22296 |
++ */ |
22297 |
++ r = bus_acquire_name(m->bus, arg_master); |
22298 |
++ if (r < 0) |
22299 |
++ goto error; |
22300 |
++ |
22301 |
++ *out = m; |
22302 |
++ return 0; |
22303 |
++ |
22304 |
++error: |
22305 |
++ master_free(m); |
22306 |
++ return r; |
22307 |
++} |
22308 |
++ |
22309 |
++/* pretty straightforward destructor of a master object */ |
22310 |
++static void master_free(struct master *m) |
22311 |
++{ |
22312 |
++ if (!m) |
22313 |
++ return; |
22314 |
++ |
22315 |
++ bus_close_connection(m->bus); |
22316 |
++ if (m->control_fd >= 0) |
22317 |
++ close(m->control_fd); |
22318 |
++ prime_free(m->prime); |
22319 |
++ if (m->signal_fd >= 0) |
22320 |
++ close(m->signal_fd); |
22321 |
++ free(m); |
22322 |
++} |
22323 |
++ |
22324 |
++static int master_run(struct master *m) |
22325 |
++{ |
22326 |
++ int res, r = 0; |
22327 |
++ |
22328 |
++ while (!prime_done(m->prime)) { |
22329 |
++ while (m->n_workers < m->max_workers) { |
22330 |
++ r = master_spawn(m); |
22331 |
++ if (r < 0) |
22332 |
++ break; |
22333 |
++ } |
22334 |
++ |
22335 |
++ r = master_poll(m); |
22336 |
++ if (r < 0) |
22337 |
++ break; |
22338 |
++ } |
22339 |
++ |
22340 |
++ if (r < 0) { |
22341 |
++ bus_close_connection(m->bus); |
22342 |
++ m->bus = NULL; |
22343 |
++ } |
22344 |
++ |
22345 |
++ while (m->n_workers > 0) { |
22346 |
++ res = master_poll(m); |
22347 |
++ if (res < 0) { |
22348 |
++ if (m->bus) { |
22349 |
++ bus_close_connection(m->bus); |
22350 |
++ m->bus = NULL; |
22351 |
++ } |
22352 |
++ r = res; |
22353 |
++ } |
22354 |
++ } |
22355 |
++ |
22356 |
++ return r == -EINTR ? 0 : r; |
22357 |
++} |
22358 |
++ |
22359 |
++static int master_poll(struct master *m) |
22360 |
++{ |
22361 |
++ struct pollfd fds[3] = {}; |
22362 |
++ int r = 0, n = 0; |
22363 |
++ |
22364 |
++ /* |
22365 |
++ * Add stdin, the eventfd and the connection owner file descriptor to |
22366 |
++ * the pollfd table, and handle incoming traffic on the latter in |
22367 |
++ * master_handle_bus(). |
22368 |
++ */ |
22369 |
++ fds[n].fd = STDIN_FILENO; |
22370 |
++ fds[n++].events = POLLIN; |
22371 |
++ fds[n].fd = m->signal_fd; |
22372 |
++ fds[n++].events = POLLIN; |
22373 |
++ if (m->bus) { |
22374 |
++ fds[n].fd = m->bus->fd; |
22375 |
++ fds[n++].events = POLLIN; |
22376 |
++ } |
22377 |
++ |
22378 |
++ r = poll(fds, n, -1); |
22379 |
++ if (r < 0) |
22380 |
++ return err("poll() failed"); |
22381 |
++ |
22382 |
++ if (fds[0].revents & POLLIN) |
22383 |
++ r = master_handle_stdin(m); |
22384 |
++ else if (fds[0].revents) |
22385 |
++ r = err("ERR/HUP on stdin"); |
22386 |
++ if (r < 0) |
22387 |
++ return r; |
22388 |
++ |
22389 |
++ if (fds[1].revents & POLLIN) |
22390 |
++ r = master_handle_signal(m); |
22391 |
++ else if (fds[1].revents) |
22392 |
++ r = err("ERR/HUP on signalfd"); |
22393 |
++ if (r < 0) |
22394 |
++ return r; |
22395 |
++ |
22396 |
++ if (fds[2].revents & POLLIN) |
22397 |
++ r = master_handle_bus(m); |
22398 |
++ else if (fds[2].revents) |
22399 |
++ r = err("ERR/HUP on bus"); |
22400 |
++ |
22401 |
++ return r; |
22402 |
++} |
22403 |
++ |
22404 |
++static int master_handle_stdin(struct master *m) |
22405 |
++{ |
22406 |
++ char buf[128]; |
22407 |
++ ssize_t l; |
22408 |
++ int r = 0; |
22409 |
++ |
22410 |
++ l = read(STDIN_FILENO, buf, sizeof(buf)); |
22411 |
++ if (l < 0) |
22412 |
++ return err("cannot read stdin"); |
22413 |
++ if (l == 0) |
22414 |
++ return err_r(-EINVAL, "EOF on stdin"); |
22415 |
++ |
22416 |
++ while (l-- > 0) { |
22417 |
++ switch (buf[l]) { |
22418 |
++ case 'q': |
22419 |
++ /* quit */ |
22420 |
++ r = -EINTR; |
22421 |
++ break; |
22422 |
++ case '\n': |
22423 |
++ case ' ': |
22424 |
++ /* ignore */ |
22425 |
++ break; |
22426 |
++ default: |
22427 |
++ if (isgraph(buf[l])) |
22428 |
++ fprintf(stderr, "invalid input '%c'\n", buf[l]); |
22429 |
++ else |
22430 |
++ fprintf(stderr, "invalid input 0x%x\n", buf[l]); |
22431 |
++ break; |
22432 |
++ } |
22433 |
++ } |
22434 |
++ |
22435 |
++ return r; |
22436 |
++} |
22437 |
++ |
22438 |
++static int master_handle_signal(struct master *m) |
22439 |
++{ |
22440 |
++ struct signalfd_siginfo val; |
22441 |
++ ssize_t l; |
22442 |
++ |
22443 |
++ l = read(m->signal_fd, &val, sizeof(val)); |
22444 |
++ if (l < 0) |
22445 |
++ return err("cannot read signalfd"); |
22446 |
++ if (l != sizeof(val)) |
22447 |
++ return err_r(-EINVAL, "invalid data from signalfd"); |
22448 |
++ |
22449 |
++ switch (val.ssi_signo) { |
22450 |
++ case SIGCHLD: |
22451 |
++ return master_waitpid(m); |
22452 |
++ case SIGINT: |
22453 |
++ return err_r(-EINTR, "interrupted"); |
22454 |
++ default: |
22455 |
++ return err_r(-EINVAL, "caught invalid signal"); |
22456 |
++ } |
22457 |
++} |
22458 |
++ |
22459 |
++static int master_handle_bus(struct master *m) |
22460 |
++{ |
22461 |
++ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
22462 |
++ const struct kdbus_msg *msg = NULL; |
22463 |
++ const struct kdbus_item *item; |
22464 |
++ const struct kdbus_vec *vec = NULL; |
22465 |
++ int r = 0; |
22466 |
++ |
22467 |
++ /* |
22468 |
++ * To receive a message, the KDBUS_CMD_RECV ioctl is used. |
22469 |
++ * It takes an argument of type 'struct kdbus_cmd_recv', which |
22470 |
++ * will contain information on the received message when the call |
22471 |
++ * returns. See kdbus.message(7). |
22472 |
++ */ |
22473 |
++ r = kdbus_cmd_recv(m->bus->fd, &recv); |
22474 |
++ /* |
22475 |
++ * EAGAIN is returned when there is no message waiting on this |
22476 |
++ * connection. This is not an error - simply bail out. |
22477 |
++ */ |
22478 |
++ if (r == -EAGAIN) |
22479 |
++ return 0; |
22480 |
++ if (r < 0) |
22481 |
++ return err_r(r, "cannot receive message"); |
22482 |
++ |
22483 |
++ /* |
22484 |
++ * Messages received by a connection are stored inside the connection's |
22485 |
++ * pool, at an offset that has been returned in the 'recv' command |
22486 |
++ * struct above. The value describes the relative offset from the |
22487 |
++ * start address of the pool. A message is described with |
22488 |
++ * 'struct kdbus_msg'. See kdbus.message(7). |
22489 |
++ */ |
22490 |
++ msg = (void *)(m->bus->pool + recv.msg.offset); |
22491 |
++ |
22492 |
++ /* |
22493 |
++ * A messages describes its actual payload in an array of items. |
22494 |
++ * KDBUS_FOREACH() is a simple iterator that walks such an array. |
22495 |
++ * struct kdbus_msg has a field to denote its total size, which is |
22496 |
++ * needed to determine the number of items in the array. |
22497 |
++ */ |
22498 |
++ KDBUS_FOREACH(item, msg->items, |
22499 |
++ msg->size - offsetof(struct kdbus_msg, items)) { |
22500 |
++ /* |
22501 |
++ * An item of type PAYLOAD_OFF describes in-line memory |
22502 |
++ * stored in the pool at a described offset. That offset is |
22503 |
++ * relative to the start address of the message header. |
22504 |
++ * This example program only expects one single item of that |
22505 |
++ * type, remembers the struct kdbus_vec member of the item |
22506 |
++ * when it sees it, and bails out if there is more than one |
22507 |
++ * of them. |
22508 |
++ */ |
22509 |
++ if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { |
22510 |
++ if (vec) { |
22511 |
++ r = err_r(-EEXIST, |
22512 |
++ "message with multiple vecs"); |
22513 |
++ break; |
22514 |
++ } |
22515 |
++ vec = &item->vec; |
22516 |
++ if (vec->size != 1) { |
22517 |
++ r = err_r(-EINVAL, "invalid message size"); |
22518 |
++ break; |
22519 |
++ } |
22520 |
++ |
22521 |
++ /* |
22522 |
++ * MEMFDs are transported as items of type PAYLOAD_MEMFD. |
22523 |
++ * If such an item is attached, a new file descriptor was |
22524 |
++ * installed into the task when KDBUS_CMD_RECV was called, and |
22525 |
++ * its number is stored in item->memfd.fd. |
22526 |
++ * Implementers *must* handle this item type and close the |
22527 |
++ * file descriptor when no longer needed in order to prevent |
22528 |
++ * file descriptor exhaustion. This example program just bails |
22529 |
++ * out with an error in this case, as memfds are not expected |
22530 |
++ * in this context. |
22531 |
++ */ |
22532 |
++ } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) { |
22533 |
++ r = err_r(-EINVAL, "message with memfd"); |
22534 |
++ break; |
22535 |
++ } |
22536 |
++ } |
22537 |
++ if (r < 0) |
22538 |
++ goto exit; |
22539 |
++ if (!vec) { |
22540 |
++ r = err_r(-EINVAL, "empty message"); |
22541 |
++ goto exit; |
22542 |
++ } |
22543 |
++ |
22544 |
++ switch (*((const uint8_t *)msg + vec->offset)) { |
22545 |
++ case 'r': { |
22546 |
++ r = master_reply(m, msg); |
22547 |
++ break; |
22548 |
++ } |
22549 |
++ default: |
22550 |
++ r = err_r(-EINVAL, "invalid message type"); |
22551 |
++ break; |
22552 |
++ } |
22553 |
++ |
22554 |
++exit: |
22555 |
++ /* |
22556 |
++ * We are done with the memory slice that was given to us through |
22557 |
++ * recv.msg.offset. Tell the kernel it can use it for other content |
22558 |
++ * in the future. See kdbus.pool(7). |
22559 |
++ */ |
22560 |
++ bus_poool_free_slice(m->bus, recv.msg.offset); |
22561 |
++ return r; |
22562 |
++} |
22563 |
++ |
22564 |
++static int master_reply(struct master *m, const struct kdbus_msg *msg) |
22565 |
++{ |
22566 |
++ struct kdbus_cmd_send cmd; |
22567 |
++ struct kdbus_item *item; |
22568 |
++ struct kdbus_msg *reply; |
22569 |
++ size_t size, status, p[2]; |
22570 |
++ int r; |
22571 |
++ |
22572 |
++ /* |
22573 |
++ * This functions sends a message over kdbus. To do this, it uses the |
22574 |
++ * KDBUS_CMD_SEND ioctl, which takes a command struct argument of type |
22575 |
++ * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual |
22576 |
++ * message to send. See kdbus.message(7). |
22577 |
++ */ |
22578 |
++ p[0] = m->prime->done; |
22579 |
++ p[1] = prime_done(m->prime) ? 0 : PRIME_STEPS; |
22580 |
++ |
22581 |
++ size = sizeof(*reply); |
22582 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
22583 |
++ |
22584 |
++ /* Prepare the message to send */ |
22585 |
++ reply = alloca(size); |
22586 |
++ memset(reply, 0, size); |
22587 |
++ reply->size = size; |
22588 |
++ |
22589 |
++ /* Each message has a cookie that can be used to send replies */ |
22590 |
++ reply->cookie = 1; |
22591 |
++ |
22592 |
++ /* The payload_type is arbitrary, but it must be non-zero */ |
22593 |
++ reply->payload_type = 0xdeadbeef; |
22594 |
++ |
22595 |
++ /* |
22596 |
++ * We are sending a reply. Let the kernel know the cookie of the |
22597 |
++ * message we are replying to. |
22598 |
++ */ |
22599 |
++ reply->cookie_reply = msg->cookie; |
22600 |
++ |
22601 |
++ /* |
22602 |
++ * Messages can either be directed to a well-known name (stored as |
22603 |
++ * string) or to a unique name (stored as number). This example does |
22604 |
++ * the latter. If the message would be directed to a well-known name |
22605 |
++ * instead, the message's dst_id field would be set to |
22606 |
++ * KDBUS_DST_ID_NAME, and the name would be attaches in an item of type |
22607 |
++ * KDBUS_ITEM_DST_NAME. See below for an example, and also refer to |
22608 |
++ * kdbus.message(7). |
22609 |
++ */ |
22610 |
++ reply->dst_id = msg->src_id; |
22611 |
++ |
22612 |
++ /* Our message has exactly one item to store its payload */ |
22613 |
++ item = reply->items; |
22614 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
22615 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
22616 |
++ item->vec.address = (uintptr_t)p; |
22617 |
++ item->vec.size = sizeof(p); |
22618 |
++ |
22619 |
++ /* |
22620 |
++ * Now prepare the command struct, and reference the message we want |
22621 |
++ * to send. |
22622 |
++ */ |
22623 |
++ memset(&cmd, 0, sizeof(cmd)); |
22624 |
++ cmd.size = sizeof(cmd); |
22625 |
++ cmd.msg_address = (uintptr_t)reply; |
22626 |
++ |
22627 |
++ /* |
22628 |
++ * Finally, employ the command on the connection owner |
22629 |
++ * file descriptor. |
22630 |
++ */ |
22631 |
++ r = kdbus_cmd_send(m->bus->fd, &cmd); |
22632 |
++ if (r < 0) |
22633 |
++ return err_r(r, "cannot send reply"); |
22634 |
++ |
22635 |
++ if (p[1]) { |
22636 |
++ prime_consume(m->prime, p[1]); |
22637 |
++ status = m->prime->done * 10000 / m->prime->max; |
22638 |
++ if (status != m->prime->status) { |
22639 |
++ m->prime->status = status; |
22640 |
++ fprintf(stderr, "status: %7.3lf%%\n", |
22641 |
++ (double)status / 100); |
22642 |
++ } |
22643 |
++ } |
22644 |
++ |
22645 |
++ return 0; |
22646 |
++} |
22647 |
++ |
22648 |
++static int master_waitpid(struct master *m) |
22649 |
++{ |
22650 |
++ pid_t pid; |
22651 |
++ int r; |
22652 |
++ |
22653 |
++ while ((pid = waitpid(-1, &r, WNOHANG)) > 0) { |
22654 |
++ if (m->n_workers > 0) |
22655 |
++ --m->n_workers; |
22656 |
++ if (!WIFEXITED(r)) |
22657 |
++ r = err_r(-EINVAL, "child died unexpectedly"); |
22658 |
++ else if (WEXITSTATUS(r) != 0) |
22659 |
++ r = err_r(-WEXITSTATUS(r), "child failed"); |
22660 |
++ } |
22661 |
++ |
22662 |
++ return r; |
22663 |
++} |
22664 |
++ |
22665 |
++static int master_spawn(struct master *m) |
22666 |
++{ |
22667 |
++ struct child *c = NULL; |
22668 |
++ struct prime *p = NULL; |
22669 |
++ pid_t pid; |
22670 |
++ int r; |
22671 |
++ |
22672 |
++ /* Spawn off one child and call child_run() inside it */ |
22673 |
++ |
22674 |
++ pid = fork(); |
22675 |
++ if (pid < 0) |
22676 |
++ return err("cannot fork"); |
22677 |
++ if (pid > 0) { |
22678 |
++ /* parent */ |
22679 |
++ ++m->n_workers; |
22680 |
++ return 0; |
22681 |
++ } |
22682 |
++ |
22683 |
++ /* child */ |
22684 |
++ |
22685 |
++ p = m->prime; |
22686 |
++ m->prime = NULL; |
22687 |
++ master_free(m); |
22688 |
++ |
22689 |
++ r = child_new(&c, p); |
22690 |
++ if (r < 0) |
22691 |
++ goto exit; |
22692 |
++ |
22693 |
++ r = child_run(c); |
22694 |
++ |
22695 |
++exit: |
22696 |
++ child_free(c); |
22697 |
++ exit(abs(r)); |
22698 |
++} |
22699 |
++ |
22700 |
++static int child_new(struct child **out, struct prime *p) |
22701 |
++{ |
22702 |
++ struct child *c; |
22703 |
++ int r; |
22704 |
++ |
22705 |
++ c = calloc(1, sizeof(*c)); |
22706 |
++ if (!c) |
22707 |
++ return err("cannot allocate child"); |
22708 |
++ |
22709 |
++ c->prime = p; |
22710 |
++ |
22711 |
++ /* |
22712 |
++ * Open a connection to the bus and require each received message to |
22713 |
++ * carry a list of the well-known names the sendind connection currently |
22714 |
++ * owns. The current UID is needed in order to determine the name of the |
22715 |
++ * bus node to connect to. |
22716 |
++ */ |
22717 |
++ r = bus_open_connection(&c->bus, getuid(), |
22718 |
++ arg_busname, KDBUS_ATTACH_NAMES); |
22719 |
++ if (r < 0) |
22720 |
++ goto error; |
22721 |
++ |
22722 |
++ /* |
22723 |
++ * Install a kdbus match so the child's connection gets notified when |
22724 |
++ * the master loses its well-known name. |
22725 |
++ */ |
22726 |
++ r = bus_install_name_loss_match(c->bus, arg_master); |
22727 |
++ if (r < 0) |
22728 |
++ goto error; |
22729 |
++ |
22730 |
++ *out = c; |
22731 |
++ return 0; |
22732 |
++ |
22733 |
++error: |
22734 |
++ child_free(c); |
22735 |
++ return r; |
22736 |
++} |
22737 |
++ |
22738 |
++static void child_free(struct child *c) |
22739 |
++{ |
22740 |
++ if (!c) |
22741 |
++ return; |
22742 |
++ |
22743 |
++ bus_close_connection(c->bus); |
22744 |
++ prime_free(c->prime); |
22745 |
++ free(c); |
22746 |
++} |
22747 |
++ |
22748 |
++static int child_run(struct child *c) |
22749 |
++{ |
22750 |
++ struct kdbus_cmd_send cmd; |
22751 |
++ struct kdbus_item *item; |
22752 |
++ struct kdbus_vec *vec = NULL; |
22753 |
++ struct kdbus_msg *msg; |
22754 |
++ struct timespec spec; |
22755 |
++ size_t n, steps, size; |
22756 |
++ int r = 0; |
22757 |
++ |
22758 |
++ /* |
22759 |
++ * Let's send a message to the master and ask for work. To do this, |
22760 |
++ * we use the KDBUS_CMD_SEND ioctl, which takes an argument of type |
22761 |
++ * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual |
22762 |
++ * message to send. See kdbus.message(7). |
22763 |
++ */ |
22764 |
++ size = sizeof(*msg); |
22765 |
++ size += KDBUS_ITEM_SIZE(strlen(arg_master) + 1); |
22766 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
22767 |
++ |
22768 |
++ msg = alloca(size); |
22769 |
++ memset(msg, 0, size); |
22770 |
++ msg->size = size; |
22771 |
++ |
22772 |
++ /* |
22773 |
++ * Tell the kernel that we expect a reply to this message. This means |
22774 |
++ * that |
22775 |
++ * |
22776 |
++ * a) The remote peer will gain temporary permission to talk to us |
22777 |
++ * even if it would not be allowed to normally. |
22778 |
++ * |
22779 |
++ * b) A timeout value is required. |
22780 |
++ * |
22781 |
++ * For asynchronous send commands, if no reply is received, we will |
22782 |
++ * get a kernel notification with an item of type |
22783 |
++ * KDBUS_ITEM_REPLY_TIMEOUT attached. |
22784 |
++ * |
22785 |
++ * For synchronous send commands (which this example does), the |
22786 |
++ * ioctl will block until a reply is received or the timeout is |
22787 |
++ * exceeded. |
22788 |
++ */ |
22789 |
++ msg->flags = KDBUS_MSG_EXPECT_REPLY; |
22790 |
++ |
22791 |
++ /* Set our cookie. Replies must use this cookie to send their reply. */ |
22792 |
++ msg->cookie = 1; |
22793 |
++ |
22794 |
++ /* The payload_type is arbitrary, but it must be non-zero */ |
22795 |
++ msg->payload_type = 0xdeadbeef; |
22796 |
++ |
22797 |
++ /* |
22798 |
++ * We are sending our message to the current owner of a well-known |
22799 |
++ * name. This makes an item of type KDBUS_ITEM_DST_NAME mandatory. |
22800 |
++ */ |
22801 |
++ msg->dst_id = KDBUS_DST_ID_NAME; |
22802 |
++ |
22803 |
++ /* |
22804 |
++ * Set the reply timeout to 5 seconds. Timeouts are always set in |
22805 |
++ * absolute timestamps, based con CLOCK_MONOTONIC. See kdbus.message(7). |
22806 |
++ */ |
22807 |
++ clock_gettime(CLOCK_MONOTONIC_COARSE, &spec); |
22808 |
++ msg->timeout_ns += (5 + spec.tv_sec) * 1000ULL * 1000ULL * 1000ULL; |
22809 |
++ msg->timeout_ns += spec.tv_nsec; |
22810 |
++ |
22811 |
++ /* |
22812 |
++ * Fill the appended items. First, set the well-known name of the |
22813 |
++ * destination we want to talk to. |
22814 |
++ */ |
22815 |
++ item = msg->items; |
22816 |
++ item->type = KDBUS_ITEM_DST_NAME; |
22817 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(arg_master) + 1; |
22818 |
++ strcpy(item->str, arg_master); |
22819 |
++ |
22820 |
++ /* |
22821 |
++ * The 2nd item contains a vector to memory we want to send. It |
22822 |
++ * can be content of any type. In our case, we're sending a one-byte |
22823 |
++ * string only. The memory referenced by this item will be copied into |
22824 |
++ * the pool of the receiver connection, and does not need to be valid |
22825 |
++ * after the command is employed. |
22826 |
++ */ |
22827 |
++ item = KDBUS_ITEM_NEXT(item); |
22828 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
22829 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
22830 |
++ item->vec.address = (uintptr_t)"r"; |
22831 |
++ item->vec.size = 1; |
22832 |
++ |
22833 |
++ /* Set up the command struct and reference the message we prepared */ |
22834 |
++ memset(&cmd, 0, sizeof(cmd)); |
22835 |
++ cmd.size = sizeof(cmd); |
22836 |
++ cmd.msg_address = (uintptr_t)msg; |
22837 |
++ |
22838 |
++ /* |
22839 |
++ * The send commands knows a mode in which it will block until a |
22840 |
++ * reply to a message is received. This example uses that mode. |
22841 |
++ * The pool offset to the received reply will be stored in the command |
22842 |
++ * struct after the send command returned. See below. |
22843 |
++ */ |
22844 |
++ cmd.flags = KDBUS_SEND_SYNC_REPLY; |
22845 |
++ |
22846 |
++ /* |
22847 |
++ * Finally, employ the command on the connection owner |
22848 |
++ * file descriptor. |
22849 |
++ */ |
22850 |
++ r = kdbus_cmd_send(c->bus->fd, &cmd); |
22851 |
++ if (r == -ESRCH || r == -EPIPE || r == -ECONNRESET) |
22852 |
++ return 0; |
22853 |
++ if (r < 0) |
22854 |
++ return err_r(r, "cannot send request to master"); |
22855 |
++ |
22856 |
++ /* |
22857 |
++ * The command was sent with the KDBUS_SEND_SYNC_REPLY flag set, |
22858 |
++ * and returned successfully, which means that cmd.reply.offset now |
22859 |
++ * points to a message inside our connection's pool where the reply |
22860 |
++ * is found. This is equivalent to receiving the reply with |
22861 |
++ * KDBUS_CMD_RECV, but it doesn't require waiting for the reply with |
22862 |
++ * poll() and also saves the ioctl to receive the message. |
22863 |
++ */ |
22864 |
++ msg = (void *)(c->bus->pool + cmd.reply.offset); |
22865 |
++ |
22866 |
++ /* |
22867 |
++ * A messages describes its actual payload in an array of items. |
22868 |
++ * KDBUS_FOREACH() is a simple iterator that walks such an array. |
22869 |
++ * struct kdbus_msg has a field to denote its total size, which is |
22870 |
++ * needed to determine the number of items in the array. |
22871 |
++ */ |
22872 |
++ KDBUS_FOREACH(item, msg->items, |
22873 |
++ msg->size - offsetof(struct kdbus_msg, items)) { |
22874 |
++ /* |
22875 |
++ * An item of type PAYLOAD_OFF describes in-line memory |
22876 |
++ * stored in the pool at a described offset. That offset is |
22877 |
++ * relative to the start address of the message header. |
22878 |
++ * This example program only expects one single item of that |
22879 |
++ * type, remembers the struct kdbus_vec member of the item |
22880 |
++ * when it sees it, and bails out if there is more than one |
22881 |
++ * of them. |
22882 |
++ */ |
22883 |
++ if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { |
22884 |
++ if (vec) { |
22885 |
++ r = err_r(-EEXIST, |
22886 |
++ "message with multiple vecs"); |
22887 |
++ break; |
22888 |
++ } |
22889 |
++ vec = &item->vec; |
22890 |
++ if (vec->size != 2 * sizeof(size_t)) { |
22891 |
++ r = err_r(-EINVAL, "invalid message size"); |
22892 |
++ break; |
22893 |
++ } |
22894 |
++ /* |
22895 |
++ * MEMFDs are transported as items of type PAYLOAD_MEMFD. |
22896 |
++ * If such an item is attached, a new file descriptor was |
22897 |
++ * installed into the task when KDBUS_CMD_RECV was called, and |
22898 |
++ * its number is stored in item->memfd.fd. |
22899 |
++ * Implementers *must* handle this item type close the |
22900 |
++ * file descriptor when no longer needed in order to prevent |
22901 |
++ * file descriptor exhaustion. This example program just bails |
22902 |
++ * out with an error in this case, as memfds are not expected |
22903 |
++ * in this context. |
22904 |
++ */ |
22905 |
++ } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) { |
22906 |
++ r = err_r(-EINVAL, "message with memfd"); |
22907 |
++ break; |
22908 |
++ } |
22909 |
++ } |
22910 |
++ if (r < 0) |
22911 |
++ goto exit; |
22912 |
++ if (!vec) { |
22913 |
++ r = err_r(-EINVAL, "empty message"); |
22914 |
++ goto exit; |
22915 |
++ } |
22916 |
++ |
22917 |
++ n = ((size_t *)((const uint8_t *)msg + vec->offset))[0]; |
22918 |
++ steps = ((size_t *)((const uint8_t *)msg + vec->offset))[1]; |
22919 |
++ |
22920 |
++ while (steps-- > 0) { |
22921 |
++ ++n; |
22922 |
++ r = prime_run(c->prime, c->bus, n); |
22923 |
++ if (r < 0) |
22924 |
++ break; |
22925 |
++ r = bus_poll(c->bus); |
22926 |
++ if (r != 0) { |
22927 |
++ r = r < 0 ? r : -EINTR; |
22928 |
++ break; |
22929 |
++ } |
22930 |
++ } |
22931 |
++ |
22932 |
++exit: |
22933 |
++ /* |
22934 |
++ * We are done with the memory slice that was given to us through |
22935 |
++ * cmd.reply.offset. Tell the kernel it can use it for other content |
22936 |
++ * in the future. See kdbus.pool(7). |
22937 |
++ */ |
22938 |
++ bus_poool_free_slice(c->bus, cmd.reply.offset); |
22939 |
++ return r; |
22940 |
++} |
22941 |
++ |
22942 |
++/* |
22943 |
++ * Prime Computation |
22944 |
++ * |
22945 |
++ */ |
22946 |
++ |
22947 |
++static int prime_new(struct prime **out) |
22948 |
++{ |
22949 |
++ struct prime *p; |
22950 |
++ int r; |
22951 |
++ |
22952 |
++ p = calloc(1, sizeof(*p)); |
22953 |
++ if (!p) |
22954 |
++ return err("cannot allocate prime memory"); |
22955 |
++ |
22956 |
++ p->fd = -1; |
22957 |
++ p->area = MAP_FAILED; |
22958 |
++ p->max = MAX_PRIMES; |
22959 |
++ |
22960 |
++ /* |
22961 |
++ * Prepare and map a memfd to store the bit-fields for the number |
22962 |
++ * ranges we want to perform the prime detection on. |
22963 |
++ */ |
22964 |
++ p->fd = syscall(__NR_memfd_create, "prime-area", MFD_CLOEXEC); |
22965 |
++ if (p->fd < 0) { |
22966 |
++ r = err("cannot create memfd"); |
22967 |
++ goto error; |
22968 |
++ } |
22969 |
++ |
22970 |
++ r = ftruncate(p->fd, p->max / 8 + 1); |
22971 |
++ if (r < 0) { |
22972 |
++ r = err("cannot ftruncate area"); |
22973 |
++ goto error; |
22974 |
++ } |
22975 |
++ |
22976 |
++ p->area = mmap(NULL, p->max / 8 + 1, PROT_READ | PROT_WRITE, |
22977 |
++ MAP_SHARED, p->fd, 0); |
22978 |
++ if (p->area == MAP_FAILED) { |
22979 |
++ r = err("cannot mmap memfd"); |
22980 |
++ goto error; |
22981 |
++ } |
22982 |
++ |
22983 |
++ *out = p; |
22984 |
++ return 0; |
22985 |
++ |
22986 |
++error: |
22987 |
++ prime_free(p); |
22988 |
++ return r; |
22989 |
++} |
22990 |
++ |
22991 |
++static void prime_free(struct prime *p) |
22992 |
++{ |
22993 |
++ if (!p) |
22994 |
++ return; |
22995 |
++ |
22996 |
++ if (p->area != MAP_FAILED) |
22997 |
++ munmap(p->area, p->max / 8 + 1); |
22998 |
++ if (p->fd >= 0) |
22999 |
++ close(p->fd); |
23000 |
++ free(p); |
23001 |
++} |
23002 |
++ |
23003 |
++static bool prime_done(struct prime *p) |
23004 |
++{ |
23005 |
++ return p->done >= p->max; |
23006 |
++} |
23007 |
++ |
23008 |
++static void prime_consume(struct prime *p, size_t amount) |
23009 |
++{ |
23010 |
++ p->done += amount; |
23011 |
++} |
23012 |
++ |
23013 |
++static int prime_run(struct prime *p, struct bus *cancel, size_t number) |
23014 |
++{ |
23015 |
++ size_t i, n = 0; |
23016 |
++ int r; |
23017 |
++ |
23018 |
++ if (number < 2 || number > 65535) |
23019 |
++ return 0; |
23020 |
++ |
23021 |
++ for (i = number * number; |
23022 |
++ i < p->max && i > number; |
23023 |
++ i += number) { |
23024 |
++ p->area[i / 8] |= 1 << (i % 8); |
23025 |
++ |
23026 |
++ if (!(++n % (1 << 20))) { |
23027 |
++ r = bus_poll(cancel); |
23028 |
++ if (r != 0) |
23029 |
++ return r < 0 ? r : -EINTR; |
23030 |
++ } |
23031 |
++ } |
23032 |
++ |
23033 |
++ return 0; |
23034 |
++} |
23035 |
++ |
23036 |
++static void prime_print(struct prime *p) |
23037 |
++{ |
23038 |
++ size_t i, l = 0; |
23039 |
++ |
23040 |
++ fprintf(stderr, "PRIMES:"); |
23041 |
++ for (i = 0; i < p->max; ++i) { |
23042 |
++ if (!(p->area[i / 8] & (1 << (i % 8)))) |
23043 |
++ fprintf(stderr, "%c%7zu", !(l++ % 16) ? '\n' : ' ', i); |
23044 |
++ } |
23045 |
++ fprintf(stderr, "\nEND\n"); |
23046 |
++} |
23047 |
++ |
23048 |
++static int bus_open_connection(struct bus **out, uid_t uid, const char *name, |
23049 |
++ uint64_t recv_flags) |
23050 |
++{ |
23051 |
++ struct kdbus_cmd_hello hello; |
23052 |
++ char path[128]; |
23053 |
++ struct bus *b; |
23054 |
++ int r; |
23055 |
++ |
23056 |
++ /* |
23057 |
++ * The 'bus' object is our representation of a kdbus connection which |
23058 |
++ * stores two details: the connection owner file descriptor, and the |
23059 |
++ * mmap()ed memory of its associated pool. See kdbus.connection(7) and |
23060 |
++ * kdbus.pool(7). |
23061 |
++ */ |
23062 |
++ b = calloc(1, sizeof(*b)); |
23063 |
++ if (!b) |
23064 |
++ return err("cannot allocate bus memory"); |
23065 |
++ |
23066 |
++ b->fd = -1; |
23067 |
++ b->pool = MAP_FAILED; |
23068 |
++ |
23069 |
++ /* Compute the name of the bus node to connect to. */ |
23070 |
++ snprintf(path, sizeof(path), "/sys/fs/%s/%lu-%s/bus", |
23071 |
++ arg_modname, (unsigned long)uid, name); |
23072 |
++ b->fd = open(path, O_RDWR | O_CLOEXEC); |
23073 |
++ if (b->fd < 0) { |
23074 |
++ r = err("cannot open bus"); |
23075 |
++ goto error; |
23076 |
++ } |
23077 |
++ |
23078 |
++ /* |
23079 |
++ * To make a connection to the bus, the KDBUS_CMD_HELLO ioctl is used. |
23080 |
++ * It takes an argument of type 'struct kdbus_cmd_hello'. |
23081 |
++ */ |
23082 |
++ memset(&hello, 0, sizeof(hello)); |
23083 |
++ hello.size = sizeof(hello); |
23084 |
++ |
23085 |
++ /* |
23086 |
++ * Specify a mask of metadata attach flags, describing metadata items |
23087 |
++ * that this new connection allows to be sent. |
23088 |
++ */ |
23089 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
23090 |
++ |
23091 |
++ /* |
23092 |
++ * Specify a mask of metadata attach flags, describing metadata items |
23093 |
++ * that this new connection wants to be receive along with each message. |
23094 |
++ */ |
23095 |
++ hello.attach_flags_recv = recv_flags; |
23096 |
++ |
23097 |
++ /* |
23098 |
++ * A connection may choose the size of its pool, but the number has to |
23099 |
++ * comply with two rules: a) it must be greater than 0, and b) it must |
23100 |
++ * be a mulitple of PAGE_SIZE. See kdbus.pool(7). |
23101 |
++ */ |
23102 |
++ hello.pool_size = POOL_SIZE; |
23103 |
++ |
23104 |
++ /* |
23105 |
++ * Now employ the command on the file descriptor opened above. |
23106 |
++ * This command will turn the file descriptor into a connection-owner |
23107 |
++ * file descriptor that controls the life-time of the connection; once |
23108 |
++ * it's closed, the connection is shut down. |
23109 |
++ */ |
23110 |
++ r = kdbus_cmd_hello(b->fd, &hello); |
23111 |
++ if (r < 0) { |
23112 |
++ err_r(r, "HELLO failed"); |
23113 |
++ goto error; |
23114 |
++ } |
23115 |
++ |
23116 |
++ bus_poool_free_slice(b, hello.offset); |
23117 |
++ |
23118 |
++ /* |
23119 |
++ * Map the pool of the connection. Its size has been set in the |
23120 |
++ * command struct above. See kdbus.pool(7). |
23121 |
++ */ |
23122 |
++ b->pool = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, b->fd, 0); |
23123 |
++ if (b->pool == MAP_FAILED) { |
23124 |
++ r = err("cannot mmap pool"); |
23125 |
++ goto error; |
23126 |
++ } |
23127 |
++ |
23128 |
++ *out = b; |
23129 |
++ return 0; |
23130 |
++ |
23131 |
++error: |
23132 |
++ bus_close_connection(b); |
23133 |
++ return r; |
23134 |
++} |
23135 |
++ |
23136 |
++static void bus_close_connection(struct bus *b) |
23137 |
++{ |
23138 |
++ if (!b) |
23139 |
++ return; |
23140 |
++ |
23141 |
++ /* |
23142 |
++ * A bus connection is closed by simply calling close() on the |
23143 |
++ * connection owner file descriptor. The unique name and all owned |
23144 |
++ * well-known names of the conneciton will disappear. |
23145 |
++ * See kdbus.connection(7). |
23146 |
++ */ |
23147 |
++ if (b->pool != MAP_FAILED) |
23148 |
++ munmap(b->pool, POOL_SIZE); |
23149 |
++ if (b->fd >= 0) |
23150 |
++ close(b->fd); |
23151 |
++ free(b); |
23152 |
++} |
23153 |
++ |
23154 |
++static void bus_poool_free_slice(struct bus *b, uint64_t offset) |
23155 |
++{ |
23156 |
++ struct kdbus_cmd_free cmd = { |
23157 |
++ .size = sizeof(cmd), |
23158 |
++ .offset = offset, |
23159 |
++ }; |
23160 |
++ int r; |
23161 |
++ |
23162 |
++ /* |
23163 |
++ * Once we're done with a piece of pool memory that was returned |
23164 |
++ * by a command, we have to call the KDBUS_CMD_FREE ioctl on it so it |
23165 |
++ * can be reused. The command takes an argument of type |
23166 |
++ * 'struct kdbus_cmd_free', in which the pool offset of the slice to |
23167 |
++ * free is stored. The ioctl is employed on the connection owner |
23168 |
++ * file descriptor. See kdbus.pool(7), |
23169 |
++ */ |
23170 |
++ r = kdbus_cmd_free(b->fd, &cmd); |
23171 |
++ if (r < 0) |
23172 |
++ err_r(r, "cannot free pool slice"); |
23173 |
++} |
23174 |
++ |
23175 |
++static int bus_acquire_name(struct bus *b, const char *name) |
23176 |
++{ |
23177 |
++ struct kdbus_item *item; |
23178 |
++ struct kdbus_cmd *cmd; |
23179 |
++ size_t size; |
23180 |
++ int r; |
23181 |
++ |
23182 |
++ /* |
23183 |
++ * This function acquires a well-known name on the bus through the |
23184 |
++ * KDBUS_CMD_NAME_ACQUIRE ioctl. This ioctl takes an argument of type |
23185 |
++ * 'struct kdbus_cmd', which is assembled below. See kdbus.name(7). |
23186 |
++ */ |
23187 |
++ size = sizeof(*cmd); |
23188 |
++ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
23189 |
++ |
23190 |
++ cmd = alloca(size); |
23191 |
++ memset(cmd, 0, size); |
23192 |
++ cmd->size = size; |
23193 |
++ |
23194 |
++ /* |
23195 |
++ * The command requires an item of type KDBUS_ITEM_NAME, and its |
23196 |
++ * content must be a valid bus name. |
23197 |
++ */ |
23198 |
++ item = cmd->items; |
23199 |
++ item->type = KDBUS_ITEM_NAME; |
23200 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
23201 |
++ strcpy(item->str, name); |
23202 |
++ |
23203 |
++ /* |
23204 |
++ * Employ the command on the connection owner file descriptor. |
23205 |
++ */ |
23206 |
++ r = kdbus_cmd_name_acquire(b->fd, cmd); |
23207 |
++ if (r < 0) |
23208 |
++ return err_r(r, "cannot acquire name"); |
23209 |
++ |
23210 |
++ return 0; |
23211 |
++} |
23212 |
++ |
23213 |
++static int bus_install_name_loss_match(struct bus *b, const char *name) |
23214 |
++{ |
23215 |
++ struct kdbus_cmd_match *match; |
23216 |
++ struct kdbus_item *item; |
23217 |
++ size_t size; |
23218 |
++ int r; |
23219 |
++ |
23220 |
++ /* |
23221 |
++ * In order to install a match for signal messages, we have to |
23222 |
++ * assemble a 'struct kdbus_cmd_match' and use it along with the |
23223 |
++ * KDBUS_CMD_MATCH_ADD ioctl. See kdbus.match(7). |
23224 |
++ */ |
23225 |
++ size = sizeof(*match); |
23226 |
++ size += KDBUS_ITEM_SIZE(sizeof(item->name_change) + strlen(name) + 1); |
23227 |
++ |
23228 |
++ match = alloca(size); |
23229 |
++ memset(match, 0, size); |
23230 |
++ match->size = size; |
23231 |
++ |
23232 |
++ /* |
23233 |
++ * A match is comprised of many 'rules', each of which describes a |
23234 |
++ * mandatory detail of the message. All rules of a match must be |
23235 |
++ * satified in order to make a message pass. |
23236 |
++ */ |
23237 |
++ item = match->items; |
23238 |
++ |
23239 |
++ /* |
23240 |
++ * In this case, we're interested in notifications that inform us |
23241 |
++ * about a well-known name being removed from the bus. |
23242 |
++ */ |
23243 |
++ item->type = KDBUS_ITEM_NAME_REMOVE; |
23244 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + |
23245 |
++ sizeof(item->name_change) + strlen(name) + 1; |
23246 |
++ |
23247 |
++ /* |
23248 |
++ * We could limit the match further and require a specific unique-ID |
23249 |
++ * to be the new or the old owner of the name. In this case, however, |
23250 |
++ * we don't, and allow 'any' id. |
23251 |
++ */ |
23252 |
++ item->name_change.old_id.id = KDBUS_MATCH_ID_ANY; |
23253 |
++ item->name_change.new_id.id = KDBUS_MATCH_ID_ANY; |
23254 |
++ |
23255 |
++ /* Copy in the well-known name we're interested in */ |
23256 |
++ strcpy(item->name_change.name, name); |
23257 |
++ |
23258 |
++ /* |
23259 |
++ * Add the match through the KDBUS_CMD_MATCH_ADD ioctl, employed on |
23260 |
++ * the connection owner fd. |
23261 |
++ */ |
23262 |
++ r = kdbus_cmd_match_add(b->fd, match); |
23263 |
++ if (r < 0) |
23264 |
++ return err_r(r, "cannot add match"); |
23265 |
++ |
23266 |
++ return 0; |
23267 |
++} |
23268 |
++ |
23269 |
++static int bus_poll(struct bus *b) |
23270 |
++{ |
23271 |
++ struct pollfd fds[1] = {}; |
23272 |
++ int r; |
23273 |
++ |
23274 |
++ /* |
23275 |
++ * A connection endpoint supports poll() and will wake-up the |
23276 |
++ * task with POLLIN set once a message has arrived. |
23277 |
++ */ |
23278 |
++ fds[0].fd = b->fd; |
23279 |
++ fds[0].events = POLLIN; |
23280 |
++ r = poll(fds, sizeof(fds) / sizeof(*fds), 0); |
23281 |
++ if (r < 0) |
23282 |
++ return err("cannot poll bus"); |
23283 |
++ return !!(fds[0].revents & POLLIN); |
23284 |
++} |
23285 |
++ |
23286 |
++static int bus_make(uid_t uid, const char *name) |
23287 |
++{ |
23288 |
++ struct kdbus_item *item; |
23289 |
++ struct kdbus_cmd *make; |
23290 |
++ char path[128], busname[128]; |
23291 |
++ size_t size; |
23292 |
++ int r, fd; |
23293 |
++ |
23294 |
++ /* |
23295 |
++ * Compute the full path to the 'control' node. 'arg_modname' may be |
23296 |
++ * set to a different value than 'kdbus' for development purposes. |
23297 |
++ * The 'control' node is the primary entry point to kdbus that must be |
23298 |
++ * used in order to create a bus. See kdbus(7) and kdbus.bus(7). |
23299 |
++ */ |
23300 |
++ snprintf(path, sizeof(path), "/sys/fs/%s/control", arg_modname); |
23301 |
++ |
23302 |
++ /* |
23303 |
++ * Compute the bus name. A valid bus name must always be prefixed with |
23304 |
++ * the EUID of the currently running process in order to avoid name |
23305 |
++ * conflicts. See kdbus.bus(7). |
23306 |
++ */ |
23307 |
++ snprintf(busname, sizeof(busname), "%lu-%s", (unsigned long)uid, name); |
23308 |
++ |
23309 |
++ fd = open(path, O_RDWR | O_CLOEXEC); |
23310 |
++ if (fd < 0) |
23311 |
++ return err("cannot open control file"); |
23312 |
++ |
23313 |
++ /* |
23314 |
++ * The KDBUS_CMD_BUS_MAKE ioctl takes an argument of type |
23315 |
++ * 'struct kdbus_cmd', and expects at least two items attached to |
23316 |
++ * it: one to decribe the bloom parameters to be propagated to |
23317 |
++ * connections of the bus, and the name of the bus that was computed |
23318 |
++ * above. Assemble this struct now, and fill it with values. |
23319 |
++ */ |
23320 |
++ size = sizeof(*make); |
23321 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_parameter)); |
23322 |
++ size += KDBUS_ITEM_SIZE(strlen(busname) + 1); |
23323 |
++ |
23324 |
++ make = alloca(size); |
23325 |
++ memset(make, 0, size); |
23326 |
++ make->size = size; |
23327 |
++ |
23328 |
++ /* |
23329 |
++ * Each item has a 'type' and 'size' field, and must be stored at an |
23330 |
++ * 8-byte aligned address. The KDBUS_ITEM_NEXT macro is used to advance |
23331 |
++ * the pointer. See kdbus.item(7) for more details. |
23332 |
++ */ |
23333 |
++ item = make->items; |
23334 |
++ item->type = KDBUS_ITEM_BLOOM_PARAMETER; |
23335 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->bloom_parameter); |
23336 |
++ item->bloom_parameter.size = 8; |
23337 |
++ item->bloom_parameter.n_hash = 1; |
23338 |
++ |
23339 |
++ /* The name of the new bus is stored in the next item. */ |
23340 |
++ item = KDBUS_ITEM_NEXT(item); |
23341 |
++ item->type = KDBUS_ITEM_MAKE_NAME; |
23342 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(busname) + 1; |
23343 |
++ strcpy(item->str, busname); |
23344 |
++ |
23345 |
++ /* |
23346 |
++ * Now create the bus via the KDBUS_CMD_BUS_MAKE ioctl and return the |
23347 |
++ * fd that was used back to the caller of this function. This fd is now |
23348 |
++ * called a 'bus owner file descriptor', and it controls the life-time |
23349 |
++ * of the newly created bus; once the file descriptor is closed, the |
23350 |
++ * bus goes away, and all connections are shut down. See kdbus.bus(7). |
23351 |
++ */ |
23352 |
++ r = kdbus_cmd_bus_make(fd, make); |
23353 |
++ if (r < 0) { |
23354 |
++ err_r(r, "cannot make bus"); |
23355 |
++ close(fd); |
23356 |
++ return r; |
23357 |
++ } |
23358 |
++ |
23359 |
++ return fd; |
23360 |
++} |
23361 |
+diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile |
23362 |
+index 4e51122..7b51cce 100644 |
23363 |
+--- a/tools/testing/selftests/Makefile |
23364 |
++++ b/tools/testing/selftests/Makefile |
23365 |
+@@ -5,6 +5,7 @@ TARGETS += exec |
23366 |
+ TARGETS += firmware |
23367 |
+ TARGETS += ftrace |
23368 |
+ TARGETS += kcmp |
23369 |
++TARGETS += kdbus |
23370 |
+ TARGETS += memfd |
23371 |
+ TARGETS += memory-hotplug |
23372 |
+ TARGETS += mount |
23373 |
+diff --git a/tools/testing/selftests/kdbus/.gitignore b/tools/testing/selftests/kdbus/.gitignore |
23374 |
+new file mode 100644 |
23375 |
+index 0000000..d3ef42f |
23376 |
+--- /dev/null |
23377 |
++++ b/tools/testing/selftests/kdbus/.gitignore |
23378 |
+@@ -0,0 +1 @@ |
23379 |
++kdbus-test |
23380 |
+diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile |
23381 |
+new file mode 100644 |
23382 |
+index 0000000..de8242f |
23383 |
+--- /dev/null |
23384 |
++++ b/tools/testing/selftests/kdbus/Makefile |
23385 |
+@@ -0,0 +1,48 @@ |
23386 |
++CFLAGS += -I../../../../usr/include/ |
23387 |
++CFLAGS += -I../../../../samples/kdbus/ |
23388 |
++CFLAGS += -I../../../../include/uapi/ |
23389 |
++CFLAGS += -std=gnu99 |
23390 |
++CFLAGS += -DKBUILD_MODNAME=\"kdbus\" -D_GNU_SOURCE |
23391 |
++LDLIBS = -pthread -lcap -lm |
23392 |
++ |
23393 |
++OBJS= \ |
23394 |
++ kdbus-enum.o \ |
23395 |
++ kdbus-util.o \ |
23396 |
++ kdbus-test.o \ |
23397 |
++ kdbus-test.o \ |
23398 |
++ test-activator.o \ |
23399 |
++ test-attach-flags.o \ |
23400 |
++ test-benchmark.o \ |
23401 |
++ test-bus.o \ |
23402 |
++ test-chat.o \ |
23403 |
++ test-connection.o \ |
23404 |
++ test-daemon.o \ |
23405 |
++ test-endpoint.o \ |
23406 |
++ test-fd.o \ |
23407 |
++ test-free.o \ |
23408 |
++ test-match.o \ |
23409 |
++ test-message.o \ |
23410 |
++ test-metadata-ns.o \ |
23411 |
++ test-monitor.o \ |
23412 |
++ test-names.o \ |
23413 |
++ test-policy.o \ |
23414 |
++ test-policy-ns.o \ |
23415 |
++ test-policy-priv.o \ |
23416 |
++ test-sync.o \ |
23417 |
++ test-timeout.o |
23418 |
++ |
23419 |
++all: kdbus-test |
23420 |
++ |
23421 |
++include ../lib.mk |
23422 |
++ |
23423 |
++%.o: %.c |
23424 |
++ $(CC) $(CFLAGS) -c $< -o $@ |
23425 |
++ |
23426 |
++kdbus-test: $(OBJS) |
23427 |
++ $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@ |
23428 |
++ |
23429 |
++run_tests: |
23430 |
++ ./kdbus-test --tap |
23431 |
++ |
23432 |
++clean: |
23433 |
++ rm -f *.o kdbus-test |
23434 |
+diff --git a/tools/testing/selftests/kdbus/kdbus-enum.c b/tools/testing/selftests/kdbus/kdbus-enum.c |
23435 |
+new file mode 100644 |
23436 |
+index 0000000..4f1e579 |
23437 |
+--- /dev/null |
23438 |
++++ b/tools/testing/selftests/kdbus/kdbus-enum.c |
23439 |
+@@ -0,0 +1,94 @@ |
23440 |
++/* |
23441 |
++ * Copyright (C) 2013-2015 Kay Sievers |
23442 |
++ * |
23443 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
23444 |
++ * the terms of the GNU Lesser General Public License as published by the |
23445 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
23446 |
++ * your option) any later version. |
23447 |
++ */ |
23448 |
++ |
23449 |
++#include <stdio.h> |
23450 |
++#include <string.h> |
23451 |
++#include <fcntl.h> |
23452 |
++#include <stdlib.h> |
23453 |
++#include <stddef.h> |
23454 |
++#include <unistd.h> |
23455 |
++#include <stdint.h> |
23456 |
++#include <errno.h> |
23457 |
++ |
23458 |
++#include "kdbus-util.h" |
23459 |
++#include "kdbus-enum.h" |
23460 |
++ |
23461 |
++struct kdbus_enum_table { |
23462 |
++ long long id; |
23463 |
++ const char *name; |
23464 |
++}; |
23465 |
++ |
23466 |
++#define TABLE(what) static struct kdbus_enum_table kdbus_table_##what[] |
23467 |
++#define ENUM(_id) { .id = _id, .name = STRINGIFY(_id) } |
23468 |
++#define LOOKUP(what) \ |
23469 |
++ const char *enum_##what(long long id) \ |
23470 |
++ { \ |
23471 |
++ for (size_t i = 0; i < ELEMENTSOF(kdbus_table_##what); i++) \ |
23472 |
++ if (id == kdbus_table_##what[i].id) \ |
23473 |
++ return kdbus_table_##what[i].name; \ |
23474 |
++ return "UNKNOWN"; \ |
23475 |
++ } |
23476 |
++ |
23477 |
++TABLE(CMD) = { |
23478 |
++ ENUM(KDBUS_CMD_BUS_MAKE), |
23479 |
++ ENUM(KDBUS_CMD_ENDPOINT_MAKE), |
23480 |
++ ENUM(KDBUS_CMD_HELLO), |
23481 |
++ ENUM(KDBUS_CMD_SEND), |
23482 |
++ ENUM(KDBUS_CMD_RECV), |
23483 |
++ ENUM(KDBUS_CMD_LIST), |
23484 |
++ ENUM(KDBUS_CMD_NAME_RELEASE), |
23485 |
++ ENUM(KDBUS_CMD_CONN_INFO), |
23486 |
++ ENUM(KDBUS_CMD_MATCH_ADD), |
23487 |
++ ENUM(KDBUS_CMD_MATCH_REMOVE), |
23488 |
++}; |
23489 |
++LOOKUP(CMD); |
23490 |
++ |
23491 |
++TABLE(MSG) = { |
23492 |
++ ENUM(_KDBUS_ITEM_NULL), |
23493 |
++ ENUM(KDBUS_ITEM_PAYLOAD_VEC), |
23494 |
++ ENUM(KDBUS_ITEM_PAYLOAD_OFF), |
23495 |
++ ENUM(KDBUS_ITEM_PAYLOAD_MEMFD), |
23496 |
++ ENUM(KDBUS_ITEM_FDS), |
23497 |
++ ENUM(KDBUS_ITEM_BLOOM_PARAMETER), |
23498 |
++ ENUM(KDBUS_ITEM_BLOOM_FILTER), |
23499 |
++ ENUM(KDBUS_ITEM_DST_NAME), |
23500 |
++ ENUM(KDBUS_ITEM_MAKE_NAME), |
23501 |
++ ENUM(KDBUS_ITEM_ATTACH_FLAGS_SEND), |
23502 |
++ ENUM(KDBUS_ITEM_ATTACH_FLAGS_RECV), |
23503 |
++ ENUM(KDBUS_ITEM_ID), |
23504 |
++ ENUM(KDBUS_ITEM_NAME), |
23505 |
++ ENUM(KDBUS_ITEM_TIMESTAMP), |
23506 |
++ ENUM(KDBUS_ITEM_CREDS), |
23507 |
++ ENUM(KDBUS_ITEM_PIDS), |
23508 |
++ ENUM(KDBUS_ITEM_AUXGROUPS), |
23509 |
++ ENUM(KDBUS_ITEM_OWNED_NAME), |
23510 |
++ ENUM(KDBUS_ITEM_TID_COMM), |
23511 |
++ ENUM(KDBUS_ITEM_PID_COMM), |
23512 |
++ ENUM(KDBUS_ITEM_EXE), |
23513 |
++ ENUM(KDBUS_ITEM_CMDLINE), |
23514 |
++ ENUM(KDBUS_ITEM_CGROUP), |
23515 |
++ ENUM(KDBUS_ITEM_CAPS), |
23516 |
++ ENUM(KDBUS_ITEM_SECLABEL), |
23517 |
++ ENUM(KDBUS_ITEM_AUDIT), |
23518 |
++ ENUM(KDBUS_ITEM_CONN_DESCRIPTION), |
23519 |
++ ENUM(KDBUS_ITEM_NAME_ADD), |
23520 |
++ ENUM(KDBUS_ITEM_NAME_REMOVE), |
23521 |
++ ENUM(KDBUS_ITEM_NAME_CHANGE), |
23522 |
++ ENUM(KDBUS_ITEM_ID_ADD), |
23523 |
++ ENUM(KDBUS_ITEM_ID_REMOVE), |
23524 |
++ ENUM(KDBUS_ITEM_REPLY_TIMEOUT), |
23525 |
++ ENUM(KDBUS_ITEM_REPLY_DEAD), |
23526 |
++}; |
23527 |
++LOOKUP(MSG); |
23528 |
++ |
23529 |
++TABLE(PAYLOAD) = { |
23530 |
++ ENUM(KDBUS_PAYLOAD_KERNEL), |
23531 |
++ ENUM(KDBUS_PAYLOAD_DBUS), |
23532 |
++}; |
23533 |
++LOOKUP(PAYLOAD); |
23534 |
+diff --git a/tools/testing/selftests/kdbus/kdbus-enum.h b/tools/testing/selftests/kdbus/kdbus-enum.h |
23535 |
+new file mode 100644 |
23536 |
+index 0000000..a67cec3 |
23537 |
+--- /dev/null |
23538 |
++++ b/tools/testing/selftests/kdbus/kdbus-enum.h |
23539 |
+@@ -0,0 +1,14 @@ |
23540 |
++/* |
23541 |
++ * Copyright (C) 2013-2015 Kay Sievers |
23542 |
++ * |
23543 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
23544 |
++ * the terms of the GNU Lesser General Public License as published by the |
23545 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
23546 |
++ * your option) any later version. |
23547 |
++ */ |
23548 |
++#pragma once |
23549 |
++ |
23550 |
++const char *enum_CMD(long long id); |
23551 |
++const char *enum_MSG(long long id); |
23552 |
++const char *enum_MATCH(long long id); |
23553 |
++const char *enum_PAYLOAD(long long id); |
23554 |
+diff --git a/tools/testing/selftests/kdbus/kdbus-test.c b/tools/testing/selftests/kdbus/kdbus-test.c |
23555 |
+new file mode 100644 |
23556 |
+index 0000000..a43674c |
23557 |
+--- /dev/null |
23558 |
++++ b/tools/testing/selftests/kdbus/kdbus-test.c |
23559 |
+@@ -0,0 +1,923 @@ |
23560 |
++#include <errno.h> |
23561 |
++#include <stdio.h> |
23562 |
++#include <string.h> |
23563 |
++#include <fcntl.h> |
23564 |
++#include <stdlib.h> |
23565 |
++#include <stddef.h> |
23566 |
++#include <time.h> |
23567 |
++#include <unistd.h> |
23568 |
++#include <stdint.h> |
23569 |
++#include <assert.h> |
23570 |
++#include <getopt.h> |
23571 |
++#include <stdbool.h> |
23572 |
++#include <signal.h> |
23573 |
++#include <sys/mount.h> |
23574 |
++#include <sys/prctl.h> |
23575 |
++#include <sys/wait.h> |
23576 |
++#include <sys/syscall.h> |
23577 |
++#include <sys/eventfd.h> |
23578 |
++#include <linux/sched.h> |
23579 |
++ |
23580 |
++#include "kdbus-util.h" |
23581 |
++#include "kdbus-enum.h" |
23582 |
++#include "kdbus-test.h" |
23583 |
++ |
23584 |
++enum { |
23585 |
++ TEST_CREATE_BUS = 1 << 0, |
23586 |
++ TEST_CREATE_CONN = 1 << 1, |
23587 |
++}; |
23588 |
++ |
23589 |
++struct kdbus_test { |
23590 |
++ const char *name; |
23591 |
++ const char *desc; |
23592 |
++ int (*func)(struct kdbus_test_env *env); |
23593 |
++ unsigned int flags; |
23594 |
++}; |
23595 |
++ |
23596 |
++struct kdbus_test_args { |
23597 |
++ bool mntns; |
23598 |
++ bool pidns; |
23599 |
++ bool userns; |
23600 |
++ char *uid_map; |
23601 |
++ char *gid_map; |
23602 |
++ int loop; |
23603 |
++ int wait; |
23604 |
++ int fork; |
23605 |
++ int tap_output; |
23606 |
++ char *module; |
23607 |
++ char *root; |
23608 |
++ char *test; |
23609 |
++ char *busname; |
23610 |
++ char *mask_param_path; |
23611 |
++}; |
23612 |
++ |
23613 |
++static const struct kdbus_test tests[] = { |
23614 |
++ { |
23615 |
++ .name = "bus-make", |
23616 |
++ .desc = "bus make functions", |
23617 |
++ .func = kdbus_test_bus_make, |
23618 |
++ .flags = 0, |
23619 |
++ }, |
23620 |
++ { |
23621 |
++ .name = "hello", |
23622 |
++ .desc = "the HELLO command", |
23623 |
++ .func = kdbus_test_hello, |
23624 |
++ .flags = TEST_CREATE_BUS, |
23625 |
++ }, |
23626 |
++ { |
23627 |
++ .name = "byebye", |
23628 |
++ .desc = "the BYEBYE command", |
23629 |
++ .func = kdbus_test_byebye, |
23630 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23631 |
++ }, |
23632 |
++ { |
23633 |
++ .name = "chat", |
23634 |
++ .desc = "a chat pattern", |
23635 |
++ .func = kdbus_test_chat, |
23636 |
++ .flags = TEST_CREATE_BUS, |
23637 |
++ }, |
23638 |
++ { |
23639 |
++ .name = "daemon", |
23640 |
++ .desc = "a simple daemon", |
23641 |
++ .func = kdbus_test_daemon, |
23642 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23643 |
++ }, |
23644 |
++ { |
23645 |
++ .name = "fd-passing", |
23646 |
++ .desc = "file descriptor passing", |
23647 |
++ .func = kdbus_test_fd_passing, |
23648 |
++ .flags = TEST_CREATE_BUS, |
23649 |
++ }, |
23650 |
++ { |
23651 |
++ .name = "endpoint", |
23652 |
++ .desc = "custom endpoint", |
23653 |
++ .func = kdbus_test_custom_endpoint, |
23654 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23655 |
++ }, |
23656 |
++ { |
23657 |
++ .name = "monitor", |
23658 |
++ .desc = "monitor functionality", |
23659 |
++ .func = kdbus_test_monitor, |
23660 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23661 |
++ }, |
23662 |
++ { |
23663 |
++ .name = "name-basics", |
23664 |
++ .desc = "basic name registry functions", |
23665 |
++ .func = kdbus_test_name_basic, |
23666 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23667 |
++ }, |
23668 |
++ { |
23669 |
++ .name = "name-conflict", |
23670 |
++ .desc = "name registry conflict details", |
23671 |
++ .func = kdbus_test_name_conflict, |
23672 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23673 |
++ }, |
23674 |
++ { |
23675 |
++ .name = "name-queue", |
23676 |
++ .desc = "queuing of names", |
23677 |
++ .func = kdbus_test_name_queue, |
23678 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23679 |
++ }, |
23680 |
++ { |
23681 |
++ .name = "message-basic", |
23682 |
++ .desc = "basic message handling", |
23683 |
++ .func = kdbus_test_message_basic, |
23684 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23685 |
++ }, |
23686 |
++ { |
23687 |
++ .name = "message-prio", |
23688 |
++ .desc = "handling of messages with priority", |
23689 |
++ .func = kdbus_test_message_prio, |
23690 |
++ .flags = TEST_CREATE_BUS, |
23691 |
++ }, |
23692 |
++ { |
23693 |
++ .name = "message-quota", |
23694 |
++ .desc = "message quotas are enforced", |
23695 |
++ .func = kdbus_test_message_quota, |
23696 |
++ .flags = TEST_CREATE_BUS, |
23697 |
++ }, |
23698 |
++ { |
23699 |
++ .name = "memory-access", |
23700 |
++ .desc = "memory access", |
23701 |
++ .func = kdbus_test_memory_access, |
23702 |
++ .flags = TEST_CREATE_BUS, |
23703 |
++ }, |
23704 |
++ { |
23705 |
++ .name = "timeout", |
23706 |
++ .desc = "timeout", |
23707 |
++ .func = kdbus_test_timeout, |
23708 |
++ .flags = TEST_CREATE_BUS, |
23709 |
++ }, |
23710 |
++ { |
23711 |
++ .name = "sync-byebye", |
23712 |
++ .desc = "synchronous replies vs. BYEBYE", |
23713 |
++ .func = kdbus_test_sync_byebye, |
23714 |
++ .flags = TEST_CREATE_BUS, |
23715 |
++ }, |
23716 |
++ { |
23717 |
++ .name = "sync-reply", |
23718 |
++ .desc = "synchronous replies", |
23719 |
++ .func = kdbus_test_sync_reply, |
23720 |
++ .flags = TEST_CREATE_BUS, |
23721 |
++ }, |
23722 |
++ { |
23723 |
++ .name = "message-free", |
23724 |
++ .desc = "freeing of memory", |
23725 |
++ .func = kdbus_test_free, |
23726 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23727 |
++ }, |
23728 |
++ { |
23729 |
++ .name = "connection-info", |
23730 |
++ .desc = "retrieving connection information", |
23731 |
++ .func = kdbus_test_conn_info, |
23732 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23733 |
++ }, |
23734 |
++ { |
23735 |
++ .name = "connection-update", |
23736 |
++ .desc = "updating connection information", |
23737 |
++ .func = kdbus_test_conn_update, |
23738 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23739 |
++ }, |
23740 |
++ { |
23741 |
++ .name = "writable-pool", |
23742 |
++ .desc = "verifying pools are never writable", |
23743 |
++ .func = kdbus_test_writable_pool, |
23744 |
++ .flags = TEST_CREATE_BUS, |
23745 |
++ }, |
23746 |
++ { |
23747 |
++ .name = "policy", |
23748 |
++ .desc = "policy", |
23749 |
++ .func = kdbus_test_policy, |
23750 |
++ .flags = TEST_CREATE_BUS, |
23751 |
++ }, |
23752 |
++ { |
23753 |
++ .name = "policy-priv", |
23754 |
++ .desc = "unprivileged bus access", |
23755 |
++ .func = kdbus_test_policy_priv, |
23756 |
++ .flags = TEST_CREATE_BUS, |
23757 |
++ }, |
23758 |
++ { |
23759 |
++ .name = "policy-ns", |
23760 |
++ .desc = "policy in user namespaces", |
23761 |
++ .func = kdbus_test_policy_ns, |
23762 |
++ .flags = TEST_CREATE_BUS, |
23763 |
++ }, |
23764 |
++ { |
23765 |
++ .name = "metadata-ns", |
23766 |
++ .desc = "metadata in different namespaces", |
23767 |
++ .func = kdbus_test_metadata_ns, |
23768 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23769 |
++ }, |
23770 |
++ { |
23771 |
++ .name = "match-id-add", |
23772 |
++ .desc = "adding of matches by id", |
23773 |
++ .func = kdbus_test_match_id_add, |
23774 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23775 |
++ }, |
23776 |
++ { |
23777 |
++ .name = "match-id-remove", |
23778 |
++ .desc = "removing of matches by id", |
23779 |
++ .func = kdbus_test_match_id_remove, |
23780 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23781 |
++ }, |
23782 |
++ { |
23783 |
++ .name = "match-replace", |
23784 |
++ .desc = "replace of matches with the same cookie", |
23785 |
++ .func = kdbus_test_match_replace, |
23786 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23787 |
++ }, |
23788 |
++ { |
23789 |
++ .name = "match-name-add", |
23790 |
++ .desc = "adding of matches by name", |
23791 |
++ .func = kdbus_test_match_name_add, |
23792 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23793 |
++ }, |
23794 |
++ { |
23795 |
++ .name = "match-name-remove", |
23796 |
++ .desc = "removing of matches by name", |
23797 |
++ .func = kdbus_test_match_name_remove, |
23798 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23799 |
++ }, |
23800 |
++ { |
23801 |
++ .name = "match-name-change", |
23802 |
++ .desc = "matching for name changes", |
23803 |
++ .func = kdbus_test_match_name_change, |
23804 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23805 |
++ }, |
23806 |
++ { |
23807 |
++ .name = "match-bloom", |
23808 |
++ .desc = "matching with bloom filters", |
23809 |
++ .func = kdbus_test_match_bloom, |
23810 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23811 |
++ }, |
23812 |
++ { |
23813 |
++ .name = "activator", |
23814 |
++ .desc = "activator connections", |
23815 |
++ .func = kdbus_test_activator, |
23816 |
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23817 |
++ }, |
23818 |
++ { |
23819 |
++ .name = "benchmark", |
23820 |
++ .desc = "benchmark", |
23821 |
++ .func = kdbus_test_benchmark, |
23822 |
++ .flags = TEST_CREATE_BUS, |
23823 |
++ }, |
23824 |
++ { |
23825 |
++ .name = "benchmark-nomemfds", |
23826 |
++ .desc = "benchmark without using memfds", |
23827 |
++ .func = kdbus_test_benchmark_nomemfds, |
23828 |
++ .flags = TEST_CREATE_BUS, |
23829 |
++ }, |
23830 |
++ { |
23831 |
++ .name = "benchmark-uds", |
23832 |
++ .desc = "benchmark comparison to UDS", |
23833 |
++ .func = kdbus_test_benchmark_uds, |
23834 |
++ .flags = TEST_CREATE_BUS, |
23835 |
++ }, |
23836 |
++ { |
23837 |
++ /* Last test */ |
23838 |
++ .name = "attach-flags", |
23839 |
++ .desc = "attach flags mask", |
23840 |
++ .func = kdbus_test_attach_flags, |
23841 |
++ .flags = 0, |
23842 |
++ }, |
23843 |
++}; |
23844 |
++ |
23845 |
++#define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0]))) |
23846 |
++ |
23847 |
++static int test_prepare_env(const struct kdbus_test *t, |
23848 |
++ const struct kdbus_test_args *args, |
23849 |
++ struct kdbus_test_env *env) |
23850 |
++{ |
23851 |
++ if (t->flags & TEST_CREATE_BUS) { |
23852 |
++ char *s; |
23853 |
++ char *n = NULL; |
23854 |
++ int ret; |
23855 |
++ |
23856 |
++ asprintf(&s, "%s/control", args->root); |
23857 |
++ |
23858 |
++ env->control_fd = open(s, O_RDWR); |
23859 |
++ free(s); |
23860 |
++ ASSERT_RETURN(env->control_fd >= 0); |
23861 |
++ |
23862 |
++ if (!args->busname) { |
23863 |
++ n = unique_name("test-bus"); |
23864 |
++ ASSERT_RETURN(n); |
23865 |
++ } |
23866 |
++ |
23867 |
++ ret = kdbus_create_bus(env->control_fd, |
23868 |
++ args->busname ?: n, |
23869 |
++ _KDBUS_ATTACH_ALL, |
23870 |
++ _KDBUS_ATTACH_ALL, &s); |
23871 |
++ free(n); |
23872 |
++ ASSERT_RETURN(ret == 0); |
23873 |
++ |
23874 |
++ asprintf(&env->buspath, "%s/%s/bus", args->root, s); |
23875 |
++ free(s); |
23876 |
++ } |
23877 |
++ |
23878 |
++ if (t->flags & TEST_CREATE_CONN) { |
23879 |
++ env->conn = kdbus_hello(env->buspath, 0, NULL, 0); |
23880 |
++ ASSERT_RETURN(env->conn); |
23881 |
++ } |
23882 |
++ |
23883 |
++ env->root = args->root; |
23884 |
++ env->module = args->module; |
23885 |
++ env->mask_param_path = args->mask_param_path; |
23886 |
++ |
23887 |
++ return 0; |
23888 |
++} |
23889 |
++ |
23890 |
++void test_unprepare_env(const struct kdbus_test *t, struct kdbus_test_env *env) |
23891 |
++{ |
23892 |
++ if (env->conn) { |
23893 |
++ kdbus_conn_free(env->conn); |
23894 |
++ env->conn = NULL; |
23895 |
++ } |
23896 |
++ |
23897 |
++ if (env->control_fd >= 0) { |
23898 |
++ close(env->control_fd); |
23899 |
++ env->control_fd = -1; |
23900 |
++ } |
23901 |
++ |
23902 |
++ if (env->buspath) { |
23903 |
++ free(env->buspath); |
23904 |
++ env->buspath = NULL; |
23905 |
++ } |
23906 |
++} |
23907 |
++ |
23908 |
++static int test_run(const struct kdbus_test *t, |
23909 |
++ const struct kdbus_test_args *kdbus_args, |
23910 |
++ int wait) |
23911 |
++{ |
23912 |
++ int ret; |
23913 |
++ struct kdbus_test_env env = {}; |
23914 |
++ |
23915 |
++ ret = test_prepare_env(t, kdbus_args, &env); |
23916 |
++ if (ret != TEST_OK) |
23917 |
++ return ret; |
23918 |
++ |
23919 |
++ if (wait > 0) { |
23920 |
++ printf("Sleeping %d seconds before running test ...\n", wait); |
23921 |
++ sleep(wait); |
23922 |
++ } |
23923 |
++ |
23924 |
++ ret = t->func(&env); |
23925 |
++ test_unprepare_env(t, &env); |
23926 |
++ return ret; |
23927 |
++} |
23928 |
++ |
23929 |
++static int test_run_forked(const struct kdbus_test *t, |
23930 |
++ const struct kdbus_test_args *kdbus_args, |
23931 |
++ int wait) |
23932 |
++{ |
23933 |
++ int ret; |
23934 |
++ pid_t pid; |
23935 |
++ |
23936 |
++ pid = fork(); |
23937 |
++ if (pid < 0) { |
23938 |
++ return TEST_ERR; |
23939 |
++ } else if (pid == 0) { |
23940 |
++ ret = test_run(t, kdbus_args, wait); |
23941 |
++ _exit(ret); |
23942 |
++ } |
23943 |
++ |
23944 |
++ pid = waitpid(pid, &ret, 0); |
23945 |
++ if (pid <= 0) |
23946 |
++ return TEST_ERR; |
23947 |
++ else if (!WIFEXITED(ret)) |
23948 |
++ return TEST_ERR; |
23949 |
++ else |
23950 |
++ return WEXITSTATUS(ret); |
23951 |
++} |
23952 |
++ |
23953 |
++static void print_test_result(int ret) |
23954 |
++{ |
23955 |
++ switch (ret) { |
23956 |
++ case TEST_OK: |
23957 |
++ printf("OK"); |
23958 |
++ break; |
23959 |
++ case TEST_SKIP: |
23960 |
++ printf("SKIPPED"); |
23961 |
++ break; |
23962 |
++ case TEST_ERR: |
23963 |
++ printf("ERROR"); |
23964 |
++ break; |
23965 |
++ } |
23966 |
++} |
23967 |
++ |
23968 |
++static int start_all_tests(struct kdbus_test_args *kdbus_args) |
23969 |
++{ |
23970 |
++ int ret; |
23971 |
++ unsigned int fail_cnt = 0; |
23972 |
++ unsigned int skip_cnt = 0; |
23973 |
++ unsigned int ok_cnt = 0; |
23974 |
++ unsigned int i; |
23975 |
++ |
23976 |
++ if (kdbus_args->tap_output) { |
23977 |
++ printf("1..%d\n", N_TESTS); |
23978 |
++ fflush(stdout); |
23979 |
++ } |
23980 |
++ |
23981 |
++ kdbus_util_verbose = false; |
23982 |
++ |
23983 |
++ for (i = 0; i < N_TESTS; i++) { |
23984 |
++ const struct kdbus_test *t = tests + i; |
23985 |
++ |
23986 |
++ if (!kdbus_args->tap_output) { |
23987 |
++ unsigned int n; |
23988 |
++ |
23989 |
++ printf("Testing %s (%s) ", t->desc, t->name); |
23990 |
++ for (n = 0; n < 60 - strlen(t->desc) - strlen(t->name); n++) |
23991 |
++ printf("."); |
23992 |
++ printf(" "); |
23993 |
++ } |
23994 |
++ |
23995 |
++ ret = test_run_forked(t, kdbus_args, 0); |
23996 |
++ switch (ret) { |
23997 |
++ case TEST_OK: |
23998 |
++ ok_cnt++; |
23999 |
++ break; |
24000 |
++ case TEST_SKIP: |
24001 |
++ skip_cnt++; |
24002 |
++ break; |
24003 |
++ case TEST_ERR: |
24004 |
++ fail_cnt++; |
24005 |
++ break; |
24006 |
++ } |
24007 |
++ |
24008 |
++ if (kdbus_args->tap_output) { |
24009 |
++ printf("%sok %d - %s%s (%s)\n", |
24010 |
++ (ret == TEST_ERR) ? "not " : "", i + 1, |
24011 |
++ (ret == TEST_SKIP) ? "# SKIP " : "", |
24012 |
++ t->desc, t->name); |
24013 |
++ fflush(stdout); |
24014 |
++ } else { |
24015 |
++ print_test_result(ret); |
24016 |
++ printf("\n"); |
24017 |
++ } |
24018 |
++ } |
24019 |
++ |
24020 |
++ if (kdbus_args->tap_output) |
24021 |
++ printf("Failed %d/%d tests, %.2f%% okay\n", fail_cnt, N_TESTS, |
24022 |
++ 100.0 - (fail_cnt * 100.0) / ((float) N_TESTS)); |
24023 |
++ else |
24024 |
++ printf("\nSUMMARY: %u tests passed, %u skipped, %u failed\n", |
24025 |
++ ok_cnt, skip_cnt, fail_cnt); |
24026 |
++ |
24027 |
++ return fail_cnt > 0 ? TEST_ERR : TEST_OK; |
24028 |
++} |
24029 |
++ |
24030 |
++static int start_one_test(struct kdbus_test_args *kdbus_args) |
24031 |
++{ |
24032 |
++ int i, ret; |
24033 |
++ bool test_found = false; |
24034 |
++ |
24035 |
++ for (i = 0; i < N_TESTS; i++) { |
24036 |
++ const struct kdbus_test *t = tests + i; |
24037 |
++ |
24038 |
++ if (strcmp(t->name, kdbus_args->test)) |
24039 |
++ continue; |
24040 |
++ |
24041 |
++ do { |
24042 |
++ test_found = true; |
24043 |
++ if (kdbus_args->fork) |
24044 |
++ ret = test_run_forked(t, kdbus_args, |
24045 |
++ kdbus_args->wait); |
24046 |
++ else |
24047 |
++ ret = test_run(t, kdbus_args, |
24048 |
++ kdbus_args->wait); |
24049 |
++ |
24050 |
++ printf("Testing %s: ", t->desc); |
24051 |
++ print_test_result(ret); |
24052 |
++ printf("\n"); |
24053 |
++ |
24054 |
++ if (ret != TEST_OK) |
24055 |
++ break; |
24056 |
++ } while (kdbus_args->loop); |
24057 |
++ |
24058 |
++ return ret; |
24059 |
++ } |
24060 |
++ |
24061 |
++ if (!test_found) { |
24062 |
++ printf("Unknown test-id '%s'\n", kdbus_args->test); |
24063 |
++ return TEST_ERR; |
24064 |
++ } |
24065 |
++ |
24066 |
++ return TEST_OK; |
24067 |
++} |
24068 |
++ |
24069 |
++static void usage(const char *argv0) |
24070 |
++{ |
24071 |
++ unsigned int i, j; |
24072 |
++ |
24073 |
++ printf("Usage: %s [options]\n" |
24074 |
++ "Options:\n" |
24075 |
++ "\t-a, --tap Output test results in TAP format\n" |
24076 |
++ "\t-m, --module <module> Kdbus module name\n" |
24077 |
++ "\t-x, --loop Run in a loop\n" |
24078 |
++ "\t-f, --fork Fork before running a test\n" |
24079 |
++ "\t-h, --help Print this help\n" |
24080 |
++ "\t-r, --root <root> Toplevel of the kdbus hierarchy\n" |
24081 |
++ "\t-t, --test <test-id> Run one specific test only, in verbose mode\n" |
24082 |
++ "\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n" |
24083 |
++ "\t-w, --wait <secs> Wait <secs> before actually starting test\n" |
24084 |
++ "\t --mntns New mount namespace\n" |
24085 |
++ "\t --pidns New PID namespace\n" |
24086 |
++ "\t --userns New user namespace\n" |
24087 |
++ "\t --uidmap uid_map UID map for user namespace\n" |
24088 |
++ "\t --gidmap gid_map GID map for user namespace\n" |
24089 |
++ "\n", argv0); |
24090 |
++ |
24091 |
++ printf("By default, all test are run once, and a summary is printed.\n" |
24092 |
++ "Available tests for --test:\n\n"); |
24093 |
++ |
24094 |
++ for (i = 0; i < N_TESTS; i++) { |
24095 |
++ const struct kdbus_test *t = tests + i; |
24096 |
++ |
24097 |
++ printf("\t%s", t->name); |
24098 |
++ |
24099 |
++ for (j = 0; j < 24 - strlen(t->name); j++) |
24100 |
++ printf(" "); |
24101 |
++ |
24102 |
++ printf("Test %s\n", t->desc); |
24103 |
++ } |
24104 |
++ |
24105 |
++ printf("\n"); |
24106 |
++ printf("Note that some tests may, if run specifically by --test, " |
24107 |
++ "behave differently, and not terminate by themselves.\n"); |
24108 |
++ |
24109 |
++ exit(EXIT_FAILURE); |
24110 |
++} |
24111 |
++ |
24112 |
++void print_kdbus_test_args(struct kdbus_test_args *args) |
24113 |
++{ |
24114 |
++ if (args->userns || args->pidns || args->mntns) |
24115 |
++ printf("# Starting tests in new %s%s%s namespaces%s\n", |
24116 |
++ args->mntns ? "MOUNT " : "", |
24117 |
++ args->pidns ? "PID " : "", |
24118 |
++ args->userns ? "USER " : "", |
24119 |
++ args->mntns ? ", kdbusfs will be remounted" : ""); |
24120 |
++ else |
24121 |
++ printf("# Starting tests in the same namespaces\n"); |
24122 |
++} |
24123 |
++ |
24124 |
++void print_metadata_support(void) |
24125 |
++{ |
24126 |
++ bool no_meta_audit, no_meta_cgroups, no_meta_seclabel; |
24127 |
++ |
24128 |
++ /* |
24129 |
++ * KDBUS_ATTACH_CGROUP, KDBUS_ATTACH_AUDIT and |
24130 |
++ * KDBUS_ATTACH_SECLABEL |
24131 |
++ */ |
24132 |
++ no_meta_audit = !config_auditsyscall_is_enabled(); |
24133 |
++ no_meta_cgroups = !config_cgroups_is_enabled(); |
24134 |
++ no_meta_seclabel = !config_security_is_enabled(); |
24135 |
++ |
24136 |
++ if (no_meta_audit | no_meta_cgroups | no_meta_seclabel) |
24137 |
++ printf("# Starting tests without %s%s%s metadata support\n", |
24138 |
++ no_meta_audit ? "AUDIT " : "", |
24139 |
++ no_meta_cgroups ? "CGROUP " : "", |
24140 |
++ no_meta_seclabel ? "SECLABEL " : ""); |
24141 |
++ else |
24142 |
++ printf("# Starting tests with full metadata support\n"); |
24143 |
++} |
24144 |
++ |
24145 |
++int run_tests(struct kdbus_test_args *kdbus_args) |
24146 |
++{ |
24147 |
++ int ret; |
24148 |
++ static char control[4096]; |
24149 |
++ |
24150 |
++ snprintf(control, sizeof(control), "%s/control", kdbus_args->root); |
24151 |
++ |
24152 |
++ if (access(control, W_OK) < 0) { |
24153 |
++ printf("Unable to locate control node at '%s'.\n", |
24154 |
++ control); |
24155 |
++ return TEST_ERR; |
24156 |
++ } |
24157 |
++ |
24158 |
++ if (kdbus_args->test) { |
24159 |
++ ret = start_one_test(kdbus_args); |
24160 |
++ } else { |
24161 |
++ do { |
24162 |
++ ret = start_all_tests(kdbus_args); |
24163 |
++ if (ret != TEST_OK) |
24164 |
++ break; |
24165 |
++ } while (kdbus_args->loop); |
24166 |
++ } |
24167 |
++ |
24168 |
++ return ret; |
24169 |
++} |
24170 |
++ |
24171 |
++static void nop_handler(int sig) {} |
24172 |
++ |
24173 |
++static int test_prepare_mounts(struct kdbus_test_args *kdbus_args) |
24174 |
++{ |
24175 |
++ int ret; |
24176 |
++ char kdbusfs[64] = {'\0'}; |
24177 |
++ |
24178 |
++ snprintf(kdbusfs, sizeof(kdbusfs), "%sfs", kdbus_args->module); |
24179 |
++ |
24180 |
++ /* make current mount slave */ |
24181 |
++ ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); |
24182 |
++ if (ret < 0) { |
24183 |
++ ret = -errno; |
24184 |
++ printf("error mount() root: %d (%m)\n", ret); |
24185 |
++ return ret; |
24186 |
++ } |
24187 |
++ |
24188 |
++ /* Remount procfs since we need it in our tests */ |
24189 |
++ if (kdbus_args->pidns) { |
24190 |
++ ret = mount("proc", "/proc", "proc", |
24191 |
++ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); |
24192 |
++ if (ret < 0) { |
24193 |
++ ret = -errno; |
24194 |
++ printf("error mount() /proc : %d (%m)\n", ret); |
24195 |
++ return ret; |
24196 |
++ } |
24197 |
++ } |
24198 |
++ |
24199 |
++ /* Remount kdbusfs */ |
24200 |
++ ret = mount(kdbusfs, kdbus_args->root, kdbusfs, |
24201 |
++ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); |
24202 |
++ if (ret < 0) { |
24203 |
++ ret = -errno; |
24204 |
++ printf("error mount() %s :%d (%m)\n", kdbusfs, ret); |
24205 |
++ return ret; |
24206 |
++ } |
24207 |
++ |
24208 |
++ return 0; |
24209 |
++} |
24210 |
++ |
24211 |
++int run_tests_in_namespaces(struct kdbus_test_args *kdbus_args) |
24212 |
++{ |
24213 |
++ int ret; |
24214 |
++ int efd = -1; |
24215 |
++ int status; |
24216 |
++ pid_t pid, rpid; |
24217 |
++ struct sigaction oldsa; |
24218 |
++ struct sigaction sa = { |
24219 |
++ .sa_handler = nop_handler, |
24220 |
++ .sa_flags = SA_NOCLDSTOP, |
24221 |
++ }; |
24222 |
++ |
24223 |
++ efd = eventfd(0, EFD_CLOEXEC); |
24224 |
++ if (efd < 0) { |
24225 |
++ ret = -errno; |
24226 |
++ printf("eventfd() failed: %d (%m)\n", ret); |
24227 |
++ return TEST_ERR; |
24228 |
++ } |
24229 |
++ |
24230 |
++ ret = sigaction(SIGCHLD, &sa, &oldsa); |
24231 |
++ if (ret < 0) { |
24232 |
++ ret = -errno; |
24233 |
++ printf("sigaction() failed: %d (%m)\n", ret); |
24234 |
++ return TEST_ERR; |
24235 |
++ } |
24236 |
++ |
24237 |
++ /* setup namespaces */ |
24238 |
++ pid = syscall(__NR_clone, SIGCHLD| |
24239 |
++ (kdbus_args->userns ? CLONE_NEWUSER : 0) | |
24240 |
++ (kdbus_args->mntns ? CLONE_NEWNS : 0) | |
24241 |
++ (kdbus_args->pidns ? CLONE_NEWPID : 0), NULL); |
24242 |
++ if (pid < 0) { |
24243 |
++ printf("clone() failed: %d (%m)\n", -errno); |
24244 |
++ return TEST_ERR; |
24245 |
++ } |
24246 |
++ |
24247 |
++ if (pid == 0) { |
24248 |
++ eventfd_t event_status = 0; |
24249 |
++ |
24250 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
24251 |
++ if (ret < 0) { |
24252 |
++ ret = -errno; |
24253 |
++ printf("error prctl(): %d (%m)\n", ret); |
24254 |
++ _exit(TEST_ERR); |
24255 |
++ } |
24256 |
++ |
24257 |
++ /* reset sighandlers of childs */ |
24258 |
++ ret = sigaction(SIGCHLD, &oldsa, NULL); |
24259 |
++ if (ret < 0) { |
24260 |
++ ret = -errno; |
24261 |
++ printf("sigaction() failed: %d (%m)\n", ret); |
24262 |
++ _exit(TEST_ERR); |
24263 |
++ } |
24264 |
++ |
24265 |
++ ret = eventfd_read(efd, &event_status); |
24266 |
++ if (ret < 0 || event_status != 1) { |
24267 |
++ printf("error eventfd_read()\n"); |
24268 |
++ _exit(TEST_ERR); |
24269 |
++ } |
24270 |
++ |
24271 |
++ if (kdbus_args->mntns) { |
24272 |
++ ret = test_prepare_mounts(kdbus_args); |
24273 |
++ if (ret < 0) { |
24274 |
++ printf("error preparing mounts\n"); |
24275 |
++ _exit(TEST_ERR); |
24276 |
++ } |
24277 |
++ } |
24278 |
++ |
24279 |
++ ret = run_tests(kdbus_args); |
24280 |
++ _exit(ret); |
24281 |
++ } |
24282 |
++ |
24283 |
++ /* Setup userns mapping */ |
24284 |
++ if (kdbus_args->userns) { |
24285 |
++ ret = userns_map_uid_gid(pid, kdbus_args->uid_map, |
24286 |
++ kdbus_args->gid_map); |
24287 |
++ if (ret < 0) { |
24288 |
++ printf("error mapping uid and gid in userns\n"); |
24289 |
++ eventfd_write(efd, 2); |
24290 |
++ return TEST_ERR; |
24291 |
++ } |
24292 |
++ } |
24293 |
++ |
24294 |
++ ret = eventfd_write(efd, 1); |
24295 |
++ if (ret < 0) { |
24296 |
++ ret = -errno; |
24297 |
++ printf("error eventfd_write(): %d (%m)\n", ret); |
24298 |
++ return TEST_ERR; |
24299 |
++ } |
24300 |
++ |
24301 |
++ rpid = waitpid(pid, &status, 0); |
24302 |
++ ASSERT_RETURN_VAL(rpid == pid, TEST_ERR); |
24303 |
++ |
24304 |
++ close(efd); |
24305 |
++ |
24306 |
++ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) |
24307 |
++ return TEST_ERR; |
24308 |
++ |
24309 |
++ return TEST_OK; |
24310 |
++} |
24311 |
++ |
24312 |
++int start_tests(struct kdbus_test_args *kdbus_args) |
24313 |
++{ |
24314 |
++ int ret; |
24315 |
++ bool namespaces; |
24316 |
++ uint64_t kdbus_param_mask; |
24317 |
++ static char fspath[4096], parampath[4096]; |
24318 |
++ |
24319 |
++ namespaces = (kdbus_args->mntns || kdbus_args->pidns || |
24320 |
++ kdbus_args->userns); |
24321 |
++ |
24322 |
++ /* for pidns we need mntns set */ |
24323 |
++ if (kdbus_args->pidns && !kdbus_args->mntns) { |
24324 |
++ printf("Failed: please set both pid and mnt namesapces\n"); |
24325 |
++ return TEST_ERR; |
24326 |
++ } |
24327 |
++ |
24328 |
++ if (kdbus_args->userns) { |
24329 |
++ if (!config_user_ns_is_enabled()) { |
24330 |
++ printf("User namespace not supported\n"); |
24331 |
++ return TEST_ERR; |
24332 |
++ } |
24333 |
++ |
24334 |
++ if (!kdbus_args->uid_map || !kdbus_args->gid_map) { |
24335 |
++ printf("Failed: please specify uid or gid mapping\n"); |
24336 |
++ return TEST_ERR; |
24337 |
++ } |
24338 |
++ } |
24339 |
++ |
24340 |
++ print_kdbus_test_args(kdbus_args); |
24341 |
++ print_metadata_support(); |
24342 |
++ |
24343 |
++ /* setup kdbus paths */ |
24344 |
++ if (!kdbus_args->module) |
24345 |
++ kdbus_args->module = "kdbus"; |
24346 |
++ |
24347 |
++ if (!kdbus_args->root) { |
24348 |
++ snprintf(fspath, sizeof(fspath), "/sys/fs/%s", |
24349 |
++ kdbus_args->module); |
24350 |
++ kdbus_args->root = fspath; |
24351 |
++ } |
24352 |
++ |
24353 |
++ snprintf(parampath, sizeof(parampath), |
24354 |
++ "/sys/module/%s/parameters/attach_flags_mask", |
24355 |
++ kdbus_args->module); |
24356 |
++ kdbus_args->mask_param_path = parampath; |
24357 |
++ |
24358 |
++ ret = kdbus_sysfs_get_parameter_mask(kdbus_args->mask_param_path, |
24359 |
++ &kdbus_param_mask); |
24360 |
++ if (ret < 0) |
24361 |
++ return TEST_ERR; |
24362 |
++ |
24363 |
++ printf("# Starting tests with an attach_flags_mask=0x%llx\n", |
24364 |
++ (unsigned long long)kdbus_param_mask); |
24365 |
++ |
24366 |
++ /* Start tests */ |
24367 |
++ if (namespaces) |
24368 |
++ ret = run_tests_in_namespaces(kdbus_args); |
24369 |
++ else |
24370 |
++ ret = run_tests(kdbus_args); |
24371 |
++ |
24372 |
++ return ret; |
24373 |
++} |
24374 |
++ |
24375 |
++int main(int argc, char *argv[]) |
24376 |
++{ |
24377 |
++ int t, ret = 0; |
24378 |
++ struct kdbus_test_args *kdbus_args; |
24379 |
++ enum { |
24380 |
++ ARG_MNTNS = 0x100, |
24381 |
++ ARG_PIDNS, |
24382 |
++ ARG_USERNS, |
24383 |
++ ARG_UIDMAP, |
24384 |
++ ARG_GIDMAP, |
24385 |
++ }; |
24386 |
++ |
24387 |
++ kdbus_args = malloc(sizeof(*kdbus_args)); |
24388 |
++ if (!kdbus_args) { |
24389 |
++ printf("unable to malloc() kdbus_args\n"); |
24390 |
++ return EXIT_FAILURE; |
24391 |
++ } |
24392 |
++ |
24393 |
++ memset(kdbus_args, 0, sizeof(*kdbus_args)); |
24394 |
++ |
24395 |
++ static const struct option options[] = { |
24396 |
++ { "loop", no_argument, NULL, 'x' }, |
24397 |
++ { "help", no_argument, NULL, 'h' }, |
24398 |
++ { "root", required_argument, NULL, 'r' }, |
24399 |
++ { "test", required_argument, NULL, 't' }, |
24400 |
++ { "bus", required_argument, NULL, 'b' }, |
24401 |
++ { "wait", required_argument, NULL, 'w' }, |
24402 |
++ { "fork", no_argument, NULL, 'f' }, |
24403 |
++ { "module", required_argument, NULL, 'm' }, |
24404 |
++ { "tap", no_argument, NULL, 'a' }, |
24405 |
++ { "mntns", no_argument, NULL, ARG_MNTNS }, |
24406 |
++ { "pidns", no_argument, NULL, ARG_PIDNS }, |
24407 |
++ { "userns", no_argument, NULL, ARG_USERNS }, |
24408 |
++ { "uidmap", required_argument, NULL, ARG_UIDMAP }, |
24409 |
++ { "gidmap", required_argument, NULL, ARG_GIDMAP }, |
24410 |
++ {} |
24411 |
++ }; |
24412 |
++ |
24413 |
++ srand(time(NULL)); |
24414 |
++ |
24415 |
++ while ((t = getopt_long(argc, argv, "hxfm:r:t:b:w:a", options, NULL)) >= 0) { |
24416 |
++ switch (t) { |
24417 |
++ case 'x': |
24418 |
++ kdbus_args->loop = 1; |
24419 |
++ break; |
24420 |
++ |
24421 |
++ case 'm': |
24422 |
++ kdbus_args->module = optarg; |
24423 |
++ break; |
24424 |
++ |
24425 |
++ case 'r': |
24426 |
++ kdbus_args->root = optarg; |
24427 |
++ break; |
24428 |
++ |
24429 |
++ case 't': |
24430 |
++ kdbus_args->test = optarg; |
24431 |
++ break; |
24432 |
++ |
24433 |
++ case 'b': |
24434 |
++ kdbus_args->busname = optarg; |
24435 |
++ break; |
24436 |
++ |
24437 |
++ case 'w': |
24438 |
++ kdbus_args->wait = strtol(optarg, NULL, 10); |
24439 |
++ break; |
24440 |
++ |
24441 |
++ case 'f': |
24442 |
++ kdbus_args->fork = 1; |
24443 |
++ break; |
24444 |
++ |
24445 |
++ case 'a': |
24446 |
++ kdbus_args->tap_output = 1; |
24447 |
++ break; |
24448 |
++ |
24449 |
++ case ARG_MNTNS: |
24450 |
++ kdbus_args->mntns = true; |
24451 |
++ break; |
24452 |
++ |
24453 |
++ case ARG_PIDNS: |
24454 |
++ kdbus_args->pidns = true; |
24455 |
++ break; |
24456 |
++ |
24457 |
++ case ARG_USERNS: |
24458 |
++ kdbus_args->userns = true; |
24459 |
++ break; |
24460 |
++ |
24461 |
++ case ARG_UIDMAP: |
24462 |
++ kdbus_args->uid_map = optarg; |
24463 |
++ break; |
24464 |
++ |
24465 |
++ case ARG_GIDMAP: |
24466 |
++ kdbus_args->gid_map = optarg; |
24467 |
++ break; |
24468 |
++ |
24469 |
++ default: |
24470 |
++ case 'h': |
24471 |
++ usage(argv[0]); |
24472 |
++ } |
24473 |
++ } |
24474 |
++ |
24475 |
++ ret = start_tests(kdbus_args); |
24476 |
++ if (ret == TEST_ERR) |
24477 |
++ return EXIT_FAILURE; |
24478 |
++ |
24479 |
++ free(kdbus_args); |
24480 |
++ |
24481 |
++ return 0; |
24482 |
++} |
24483 |
+diff --git a/tools/testing/selftests/kdbus/kdbus-test.h b/tools/testing/selftests/kdbus/kdbus-test.h |
24484 |
+new file mode 100644 |
24485 |
+index 0000000..6473318 |
24486 |
+--- /dev/null |
24487 |
++++ b/tools/testing/selftests/kdbus/kdbus-test.h |
24488 |
+@@ -0,0 +1,85 @@ |
24489 |
++#ifndef _TEST_KDBUS_H_ |
24490 |
++#define _TEST_KDBUS_H_ |
24491 |
++ |
24492 |
++struct kdbus_test_env { |
24493 |
++ char *buspath; |
24494 |
++ const char *root; |
24495 |
++ const char *module; |
24496 |
++ const char *mask_param_path; |
24497 |
++ int control_fd; |
24498 |
++ struct kdbus_conn *conn; |
24499 |
++}; |
24500 |
++ |
24501 |
++enum { |
24502 |
++ TEST_OK, |
24503 |
++ TEST_SKIP, |
24504 |
++ TEST_ERR, |
24505 |
++}; |
24506 |
++ |
24507 |
++#define ASSERT_RETURN_VAL(cond, val) \ |
24508 |
++ if (!(cond)) { \ |
24509 |
++ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24510 |
++ #cond, __func__, __FILE__, __LINE__); \ |
24511 |
++ return val; \ |
24512 |
++ } |
24513 |
++ |
24514 |
++#define ASSERT_EXIT_VAL(cond, val) \ |
24515 |
++ if (!(cond)) { \ |
24516 |
++ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24517 |
++ #cond, __func__, __FILE__, __LINE__); \ |
24518 |
++ _exit(val); \ |
24519 |
++ } |
24520 |
++ |
24521 |
++#define ASSERT_BREAK(cond) \ |
24522 |
++ if (!(cond)) { \ |
24523 |
++ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24524 |
++ #cond, __func__, __FILE__, __LINE__); \ |
24525 |
++ break; \ |
24526 |
++ } |
24527 |
++ |
24528 |
++#define ASSERT_RETURN(cond) \ |
24529 |
++ ASSERT_RETURN_VAL(cond, TEST_ERR) |
24530 |
++ |
24531 |
++#define ASSERT_EXIT(cond) \ |
24532 |
++ ASSERT_EXIT_VAL(cond, EXIT_FAILURE) |
24533 |
++ |
24534 |
++int kdbus_test_activator(struct kdbus_test_env *env); |
24535 |
++int kdbus_test_attach_flags(struct kdbus_test_env *env); |
24536 |
++int kdbus_test_benchmark(struct kdbus_test_env *env); |
24537 |
++int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env); |
24538 |
++int kdbus_test_benchmark_uds(struct kdbus_test_env *env); |
24539 |
++int kdbus_test_bus_make(struct kdbus_test_env *env); |
24540 |
++int kdbus_test_byebye(struct kdbus_test_env *env); |
24541 |
++int kdbus_test_chat(struct kdbus_test_env *env); |
24542 |
++int kdbus_test_conn_info(struct kdbus_test_env *env); |
24543 |
++int kdbus_test_conn_update(struct kdbus_test_env *env); |
24544 |
++int kdbus_test_daemon(struct kdbus_test_env *env); |
24545 |
++int kdbus_test_custom_endpoint(struct kdbus_test_env *env); |
24546 |
++int kdbus_test_fd_passing(struct kdbus_test_env *env); |
24547 |
++int kdbus_test_free(struct kdbus_test_env *env); |
24548 |
++int kdbus_test_hello(struct kdbus_test_env *env); |
24549 |
++int kdbus_test_match_bloom(struct kdbus_test_env *env); |
24550 |
++int kdbus_test_match_id_add(struct kdbus_test_env *env); |
24551 |
++int kdbus_test_match_id_remove(struct kdbus_test_env *env); |
24552 |
++int kdbus_test_match_replace(struct kdbus_test_env *env); |
24553 |
++int kdbus_test_match_name_add(struct kdbus_test_env *env); |
24554 |
++int kdbus_test_match_name_change(struct kdbus_test_env *env); |
24555 |
++int kdbus_test_match_name_remove(struct kdbus_test_env *env); |
24556 |
++int kdbus_test_message_basic(struct kdbus_test_env *env); |
24557 |
++int kdbus_test_message_prio(struct kdbus_test_env *env); |
24558 |
++int kdbus_test_message_quota(struct kdbus_test_env *env); |
24559 |
++int kdbus_test_memory_access(struct kdbus_test_env *env); |
24560 |
++int kdbus_test_metadata_ns(struct kdbus_test_env *env); |
24561 |
++int kdbus_test_monitor(struct kdbus_test_env *env); |
24562 |
++int kdbus_test_name_basic(struct kdbus_test_env *env); |
24563 |
++int kdbus_test_name_conflict(struct kdbus_test_env *env); |
24564 |
++int kdbus_test_name_queue(struct kdbus_test_env *env); |
24565 |
++int kdbus_test_policy(struct kdbus_test_env *env); |
24566 |
++int kdbus_test_policy_ns(struct kdbus_test_env *env); |
24567 |
++int kdbus_test_policy_priv(struct kdbus_test_env *env); |
24568 |
++int kdbus_test_sync_byebye(struct kdbus_test_env *env); |
24569 |
++int kdbus_test_sync_reply(struct kdbus_test_env *env); |
24570 |
++int kdbus_test_timeout(struct kdbus_test_env *env); |
24571 |
++int kdbus_test_writable_pool(struct kdbus_test_env *env); |
24572 |
++ |
24573 |
++#endif /* _TEST_KDBUS_H_ */ |
24574 |
+diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c |
24575 |
+new file mode 100644 |
24576 |
+index 0000000..4b376ec |
24577 |
+--- /dev/null |
24578 |
++++ b/tools/testing/selftests/kdbus/kdbus-util.c |
24579 |
+@@ -0,0 +1,1615 @@ |
24580 |
++/* |
24581 |
++ * Copyright (C) 2013-2015 Daniel Mack |
24582 |
++ * Copyright (C) 2013-2015 Kay Sievers |
24583 |
++ * Copyright (C) 2014-2015 Djalal Harouni |
24584 |
++ * |
24585 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
24586 |
++ * the terms of the GNU Lesser General Public License as published by the |
24587 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
24588 |
++ * your option) any later version. |
24589 |
++ */ |
24590 |
++ |
24591 |
++#include <stdio.h> |
24592 |
++#include <stdarg.h> |
24593 |
++#include <string.h> |
24594 |
++#include <time.h> |
24595 |
++#include <inttypes.h> |
24596 |
++#include <fcntl.h> |
24597 |
++#include <stdlib.h> |
24598 |
++#include <stddef.h> |
24599 |
++#include <unistd.h> |
24600 |
++#include <stdint.h> |
24601 |
++#include <stdbool.h> |
24602 |
++#include <errno.h> |
24603 |
++#include <assert.h> |
24604 |
++#include <poll.h> |
24605 |
++#include <grp.h> |
24606 |
++#include <sys/capability.h> |
24607 |
++#include <sys/mman.h> |
24608 |
++#include <sys/stat.h> |
24609 |
++#include <sys/time.h> |
24610 |
++#include <linux/unistd.h> |
24611 |
++#include <linux/memfd.h> |
24612 |
++ |
24613 |
++#ifndef __NR_memfd_create |
24614 |
++ #ifdef __x86_64__ |
24615 |
++ #define __NR_memfd_create 319 |
24616 |
++ #elif defined __arm__ |
24617 |
++ #define __NR_memfd_create 385 |
24618 |
++ #else |
24619 |
++ #define __NR_memfd_create 356 |
24620 |
++ #endif |
24621 |
++#endif |
24622 |
++ |
24623 |
++#include "kdbus-api.h" |
24624 |
++#include "kdbus-util.h" |
24625 |
++#include "kdbus-enum.h" |
24626 |
++ |
24627 |
++#ifndef F_ADD_SEALS |
24628 |
++#define F_LINUX_SPECIFIC_BASE 1024 |
24629 |
++#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) |
24630 |
++#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) |
24631 |
++ |
24632 |
++#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ |
24633 |
++#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ |
24634 |
++#define F_SEAL_GROW 0x0004 /* prevent file from growing */ |
24635 |
++#define F_SEAL_WRITE 0x0008 /* prevent writes */ |
24636 |
++#endif |
24637 |
++ |
24638 |
++int kdbus_util_verbose = true; |
24639 |
++ |
24640 |
++int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask) |
24641 |
++{ |
24642 |
++ int ret; |
24643 |
++ FILE *file; |
24644 |
++ unsigned long long value; |
24645 |
++ |
24646 |
++ file = fopen(path, "r"); |
24647 |
++ if (!file) { |
24648 |
++ ret = -errno; |
24649 |
++ kdbus_printf("--- error fopen(): %d (%m)\n", ret); |
24650 |
++ return ret; |
24651 |
++ } |
24652 |
++ |
24653 |
++ ret = fscanf(file, "%llu", &value); |
24654 |
++ if (ret != 1) { |
24655 |
++ if (ferror(file)) |
24656 |
++ ret = -errno; |
24657 |
++ else |
24658 |
++ ret = -EIO; |
24659 |
++ |
24660 |
++ kdbus_printf("--- error fscanf(): %d\n", ret); |
24661 |
++ fclose(file); |
24662 |
++ return ret; |
24663 |
++ } |
24664 |
++ |
24665 |
++ *mask = (uint64_t)value; |
24666 |
++ |
24667 |
++ fclose(file); |
24668 |
++ |
24669 |
++ return 0; |
24670 |
++} |
24671 |
++ |
24672 |
++int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask) |
24673 |
++{ |
24674 |
++ int ret; |
24675 |
++ FILE *file; |
24676 |
++ |
24677 |
++ file = fopen(path, "w"); |
24678 |
++ if (!file) { |
24679 |
++ ret = -errno; |
24680 |
++ kdbus_printf("--- error open(): %d (%m)\n", ret); |
24681 |
++ return ret; |
24682 |
++ } |
24683 |
++ |
24684 |
++ ret = fprintf(file, "%llu", (unsigned long long)mask); |
24685 |
++ if (ret <= 0) { |
24686 |
++ ret = -EIO; |
24687 |
++ kdbus_printf("--- error fprintf(): %d\n", ret); |
24688 |
++ } |
24689 |
++ |
24690 |
++ fclose(file); |
24691 |
++ |
24692 |
++ return ret > 0 ? 0 : ret; |
24693 |
++} |
24694 |
++ |
24695 |
++int kdbus_create_bus(int control_fd, const char *name, |
24696 |
++ uint64_t req_meta, uint64_t owner_meta, |
24697 |
++ char **path) |
24698 |
++{ |
24699 |
++ struct { |
24700 |
++ struct kdbus_cmd cmd; |
24701 |
++ |
24702 |
++ /* bloom size item */ |
24703 |
++ struct { |
24704 |
++ uint64_t size; |
24705 |
++ uint64_t type; |
24706 |
++ struct kdbus_bloom_parameter bloom; |
24707 |
++ } bp; |
24708 |
++ |
24709 |
++ /* required and owner metadata items */ |
24710 |
++ struct { |
24711 |
++ uint64_t size; |
24712 |
++ uint64_t type; |
24713 |
++ uint64_t flags; |
24714 |
++ } attach[2]; |
24715 |
++ |
24716 |
++ /* name item */ |
24717 |
++ struct { |
24718 |
++ uint64_t size; |
24719 |
++ uint64_t type; |
24720 |
++ char str[64]; |
24721 |
++ } name; |
24722 |
++ } bus_make; |
24723 |
++ int ret; |
24724 |
++ |
24725 |
++ memset(&bus_make, 0, sizeof(bus_make)); |
24726 |
++ bus_make.bp.size = sizeof(bus_make.bp); |
24727 |
++ bus_make.bp.type = KDBUS_ITEM_BLOOM_PARAMETER; |
24728 |
++ bus_make.bp.bloom.size = 64; |
24729 |
++ bus_make.bp.bloom.n_hash = 1; |
24730 |
++ |
24731 |
++ snprintf(bus_make.name.str, sizeof(bus_make.name.str), |
24732 |
++ "%u-%s", getuid(), name); |
24733 |
++ |
24734 |
++ bus_make.attach[0].type = KDBUS_ITEM_ATTACH_FLAGS_RECV; |
24735 |
++ bus_make.attach[0].size = sizeof(bus_make.attach[0]); |
24736 |
++ bus_make.attach[0].flags = req_meta; |
24737 |
++ |
24738 |
++ bus_make.attach[1].type = KDBUS_ITEM_ATTACH_FLAGS_SEND; |
24739 |
++ bus_make.attach[1].size = sizeof(bus_make.attach[0]); |
24740 |
++ bus_make.attach[1].flags = owner_meta; |
24741 |
++ |
24742 |
++ bus_make.name.type = KDBUS_ITEM_MAKE_NAME; |
24743 |
++ bus_make.name.size = KDBUS_ITEM_HEADER_SIZE + |
24744 |
++ strlen(bus_make.name.str) + 1; |
24745 |
++ |
24746 |
++ bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD; |
24747 |
++ bus_make.cmd.size = sizeof(bus_make.cmd) + |
24748 |
++ bus_make.bp.size + |
24749 |
++ bus_make.attach[0].size + |
24750 |
++ bus_make.attach[1].size + |
24751 |
++ bus_make.name.size; |
24752 |
++ |
24753 |
++ kdbus_printf("Creating bus with name >%s< on control fd %d ...\n", |
24754 |
++ name, control_fd); |
24755 |
++ |
24756 |
++ ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd); |
24757 |
++ if (ret < 0) { |
24758 |
++ kdbus_printf("--- error when making bus: %d (%m)\n", ret); |
24759 |
++ return ret; |
24760 |
++ } |
24761 |
++ |
24762 |
++ if (ret == 0 && path) |
24763 |
++ *path = strdup(bus_make.name.str); |
24764 |
++ |
24765 |
++ return ret; |
24766 |
++} |
24767 |
++ |
24768 |
++struct kdbus_conn * |
24769 |
++kdbus_hello(const char *path, uint64_t flags, |
24770 |
++ const struct kdbus_item *item, size_t item_size) |
24771 |
++{ |
24772 |
++ struct kdbus_cmd_free cmd_free = {}; |
24773 |
++ int fd, ret; |
24774 |
++ struct { |
24775 |
++ struct kdbus_cmd_hello hello; |
24776 |
++ |
24777 |
++ struct { |
24778 |
++ uint64_t size; |
24779 |
++ uint64_t type; |
24780 |
++ char str[16]; |
24781 |
++ } conn_name; |
24782 |
++ |
24783 |
++ uint8_t extra_items[item_size]; |
24784 |
++ } h; |
24785 |
++ struct kdbus_conn *conn; |
24786 |
++ |
24787 |
++ memset(&h, 0, sizeof(h)); |
24788 |
++ |
24789 |
++ if (item_size > 0) |
24790 |
++ memcpy(h.extra_items, item, item_size); |
24791 |
++ |
24792 |
++ kdbus_printf("-- opening bus connection %s\n", path); |
24793 |
++ fd = open(path, O_RDWR|O_CLOEXEC); |
24794 |
++ if (fd < 0) { |
24795 |
++ kdbus_printf("--- error %d (%m)\n", fd); |
24796 |
++ return NULL; |
24797 |
++ } |
24798 |
++ |
24799 |
++ h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD; |
24800 |
++ h.hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
24801 |
++ h.hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
24802 |
++ h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION; |
24803 |
++ strcpy(h.conn_name.str, "this-is-my-name"); |
24804 |
++ h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1; |
24805 |
++ |
24806 |
++ h.hello.size = sizeof(h); |
24807 |
++ h.hello.pool_size = POOL_SIZE; |
24808 |
++ |
24809 |
++ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello); |
24810 |
++ if (ret < 0) { |
24811 |
++ kdbus_printf("--- error when saying hello: %d (%m)\n", ret); |
24812 |
++ return NULL; |
24813 |
++ } |
24814 |
++ 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", |
24815 |
++ path, (unsigned long long)h.hello.id, |
24816 |
++ h.hello.id128[0], h.hello.id128[1], h.hello.id128[2], |
24817 |
++ h.hello.id128[3], h.hello.id128[4], h.hello.id128[5], |
24818 |
++ h.hello.id128[6], h.hello.id128[7], h.hello.id128[8], |
24819 |
++ h.hello.id128[9], h.hello.id128[10], h.hello.id128[11], |
24820 |
++ h.hello.id128[12], h.hello.id128[13], h.hello.id128[14], |
24821 |
++ h.hello.id128[15]); |
24822 |
++ |
24823 |
++ cmd_free.size = sizeof(cmd_free); |
24824 |
++ cmd_free.offset = h.hello.offset; |
24825 |
++ kdbus_cmd_free(fd, &cmd_free); |
24826 |
++ |
24827 |
++ conn = malloc(sizeof(*conn)); |
24828 |
++ if (!conn) { |
24829 |
++ kdbus_printf("unable to malloc()!?\n"); |
24830 |
++ return NULL; |
24831 |
++ } |
24832 |
++ |
24833 |
++ conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
24834 |
++ if (conn->buf == MAP_FAILED) { |
24835 |
++ free(conn); |
24836 |
++ close(fd); |
24837 |
++ kdbus_printf("--- error mmap (%m)\n"); |
24838 |
++ return NULL; |
24839 |
++ } |
24840 |
++ |
24841 |
++ conn->fd = fd; |
24842 |
++ conn->id = h.hello.id; |
24843 |
++ return conn; |
24844 |
++} |
24845 |
++ |
24846 |
++struct kdbus_conn * |
24847 |
++kdbus_hello_registrar(const char *path, const char *name, |
24848 |
++ const struct kdbus_policy_access *access, |
24849 |
++ size_t num_access, uint64_t flags) |
24850 |
++{ |
24851 |
++ struct kdbus_item *item, *items; |
24852 |
++ size_t i, size; |
24853 |
++ |
24854 |
++ size = KDBUS_ITEM_SIZE(strlen(name) + 1) + |
24855 |
++ num_access * KDBUS_ITEM_SIZE(sizeof(*access)); |
24856 |
++ |
24857 |
++ items = alloca(size); |
24858 |
++ |
24859 |
++ item = items; |
24860 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
24861 |
++ item->type = KDBUS_ITEM_NAME; |
24862 |
++ strcpy(item->str, name); |
24863 |
++ item = KDBUS_ITEM_NEXT(item); |
24864 |
++ |
24865 |
++ for (i = 0; i < num_access; i++) { |
24866 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + |
24867 |
++ sizeof(struct kdbus_policy_access); |
24868 |
++ item->type = KDBUS_ITEM_POLICY_ACCESS; |
24869 |
++ |
24870 |
++ item->policy_access.type = access[i].type; |
24871 |
++ item->policy_access.access = access[i].access; |
24872 |
++ item->policy_access.id = access[i].id; |
24873 |
++ |
24874 |
++ item = KDBUS_ITEM_NEXT(item); |
24875 |
++ } |
24876 |
++ |
24877 |
++ return kdbus_hello(path, flags, items, size); |
24878 |
++} |
24879 |
++ |
24880 |
++struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, |
24881 |
++ const struct kdbus_policy_access *access, |
24882 |
++ size_t num_access) |
24883 |
++{ |
24884 |
++ return kdbus_hello_registrar(path, name, access, num_access, |
24885 |
++ KDBUS_HELLO_ACTIVATOR); |
24886 |
++} |
24887 |
++ |
24888 |
++bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type) |
24889 |
++{ |
24890 |
++ const struct kdbus_item *item; |
24891 |
++ |
24892 |
++ KDBUS_ITEM_FOREACH(item, msg, items) |
24893 |
++ if (item->type == type) |
24894 |
++ return true; |
24895 |
++ |
24896 |
++ return false; |
24897 |
++} |
24898 |
++ |
24899 |
++int kdbus_bus_creator_info(struct kdbus_conn *conn, |
24900 |
++ uint64_t flags, |
24901 |
++ uint64_t *offset) |
24902 |
++{ |
24903 |
++ struct kdbus_cmd_info *cmd; |
24904 |
++ size_t size = sizeof(*cmd); |
24905 |
++ int ret; |
24906 |
++ |
24907 |
++ cmd = alloca(size); |
24908 |
++ memset(cmd, 0, size); |
24909 |
++ cmd->size = size; |
24910 |
++ cmd->attach_flags = flags; |
24911 |
++ |
24912 |
++ ret = kdbus_cmd_bus_creator_info(conn->fd, cmd); |
24913 |
++ if (ret < 0) { |
24914 |
++ kdbus_printf("--- error when requesting info: %d (%m)\n", ret); |
24915 |
++ return ret; |
24916 |
++ } |
24917 |
++ |
24918 |
++ if (offset) |
24919 |
++ *offset = cmd->offset; |
24920 |
++ else |
24921 |
++ kdbus_free(conn, cmd->offset); |
24922 |
++ |
24923 |
++ return 0; |
24924 |
++} |
24925 |
++ |
24926 |
++int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, |
24927 |
++ const char *name, uint64_t flags, |
24928 |
++ uint64_t *offset) |
24929 |
++{ |
24930 |
++ struct kdbus_cmd_info *cmd; |
24931 |
++ size_t size = sizeof(*cmd); |
24932 |
++ struct kdbus_info *info; |
24933 |
++ int ret; |
24934 |
++ |
24935 |
++ if (name) |
24936 |
++ size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
24937 |
++ |
24938 |
++ cmd = alloca(size); |
24939 |
++ memset(cmd, 0, size); |
24940 |
++ cmd->size = size; |
24941 |
++ cmd->attach_flags = flags; |
24942 |
++ |
24943 |
++ if (name) { |
24944 |
++ cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
24945 |
++ cmd->items[0].type = KDBUS_ITEM_NAME; |
24946 |
++ strcpy(cmd->items[0].str, name); |
24947 |
++ } else { |
24948 |
++ cmd->id = id; |
24949 |
++ } |
24950 |
++ |
24951 |
++ ret = kdbus_cmd_conn_info(conn->fd, cmd); |
24952 |
++ if (ret < 0) { |
24953 |
++ kdbus_printf("--- error when requesting info: %d (%m)\n", ret); |
24954 |
++ return ret; |
24955 |
++ } |
24956 |
++ |
24957 |
++ info = (struct kdbus_info *) (conn->buf + cmd->offset); |
24958 |
++ if (info->size != cmd->info_size) { |
24959 |
++ kdbus_printf("%s(): size mismatch: %d != %d\n", __func__, |
24960 |
++ (int) info->size, (int) cmd->info_size); |
24961 |
++ return -EIO; |
24962 |
++ } |
24963 |
++ |
24964 |
++ if (offset) |
24965 |
++ *offset = cmd->offset; |
24966 |
++ else |
24967 |
++ kdbus_free(conn, cmd->offset); |
24968 |
++ |
24969 |
++ return 0; |
24970 |
++} |
24971 |
++ |
24972 |
++void kdbus_conn_free(struct kdbus_conn *conn) |
24973 |
++{ |
24974 |
++ if (!conn) |
24975 |
++ return; |
24976 |
++ |
24977 |
++ if (conn->buf) |
24978 |
++ munmap(conn->buf, POOL_SIZE); |
24979 |
++ |
24980 |
++ if (conn->fd >= 0) |
24981 |
++ close(conn->fd); |
24982 |
++ |
24983 |
++ free(conn); |
24984 |
++} |
24985 |
++ |
24986 |
++int sys_memfd_create(const char *name, __u64 size) |
24987 |
++{ |
24988 |
++ int ret, fd; |
24989 |
++ |
24990 |
++ ret = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING); |
24991 |
++ if (ret < 0) |
24992 |
++ return ret; |
24993 |
++ |
24994 |
++ fd = ret; |
24995 |
++ |
24996 |
++ ret = ftruncate(fd, size); |
24997 |
++ if (ret < 0) { |
24998 |
++ close(fd); |
24999 |
++ return ret; |
25000 |
++ } |
25001 |
++ |
25002 |
++ return fd; |
25003 |
++} |
25004 |
++ |
25005 |
++int sys_memfd_seal_set(int fd) |
25006 |
++{ |
25007 |
++ return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | |
25008 |
++ F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); |
25009 |
++} |
25010 |
++ |
25011 |
++off_t sys_memfd_get_size(int fd, off_t *size) |
25012 |
++{ |
25013 |
++ struct stat stat; |
25014 |
++ int ret; |
25015 |
++ |
25016 |
++ ret = fstat(fd, &stat); |
25017 |
++ if (ret < 0) { |
25018 |
++ kdbus_printf("stat() failed: %m\n"); |
25019 |
++ return ret; |
25020 |
++ } |
25021 |
++ |
25022 |
++ *size = stat.st_size; |
25023 |
++ return 0; |
25024 |
++} |
25025 |
++ |
25026 |
++static int __kdbus_msg_send(const struct kdbus_conn *conn, |
25027 |
++ const char *name, |
25028 |
++ uint64_t cookie, |
25029 |
++ uint64_t flags, |
25030 |
++ uint64_t timeout, |
25031 |
++ int64_t priority, |
25032 |
++ uint64_t dst_id, |
25033 |
++ uint64_t cmd_flags, |
25034 |
++ int cancel_fd) |
25035 |
++{ |
25036 |
++ struct kdbus_cmd_send *cmd; |
25037 |
++ struct kdbus_msg *msg; |
25038 |
++ const char ref1[1024 * 128 + 3] = "0123456789_0"; |
25039 |
++ const char ref2[] = "0123456789_1"; |
25040 |
++ struct kdbus_item *item; |
25041 |
++ struct timespec now; |
25042 |
++ uint64_t size; |
25043 |
++ int memfd = -1; |
25044 |
++ int ret; |
25045 |
++ |
25046 |
++ size = sizeof(*msg); |
25047 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25048 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25049 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25050 |
++ |
25051 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) |
25052 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
25053 |
++ else { |
25054 |
++ memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024); |
25055 |
++ if (memfd < 0) { |
25056 |
++ kdbus_printf("failed to create memfd: %m\n"); |
25057 |
++ return memfd; |
25058 |
++ } |
25059 |
++ |
25060 |
++ if (write(memfd, "kdbus memfd 1234567", 19) != 19) { |
25061 |
++ ret = -errno; |
25062 |
++ kdbus_printf("writing to memfd failed: %m\n"); |
25063 |
++ return ret; |
25064 |
++ } |
25065 |
++ |
25066 |
++ ret = sys_memfd_seal_set(memfd); |
25067 |
++ if (ret < 0) { |
25068 |
++ ret = -errno; |
25069 |
++ kdbus_printf("memfd sealing failed: %m\n"); |
25070 |
++ return ret; |
25071 |
++ } |
25072 |
++ |
25073 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
25074 |
++ } |
25075 |
++ |
25076 |
++ if (name) |
25077 |
++ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
25078 |
++ |
25079 |
++ msg = malloc(size); |
25080 |
++ if (!msg) { |
25081 |
++ ret = -errno; |
25082 |
++ kdbus_printf("unable to malloc()!?\n"); |
25083 |
++ return ret; |
25084 |
++ } |
25085 |
++ |
25086 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) |
25087 |
++ flags |= KDBUS_MSG_SIGNAL; |
25088 |
++ |
25089 |
++ memset(msg, 0, size); |
25090 |
++ msg->flags = flags; |
25091 |
++ msg->priority = priority; |
25092 |
++ msg->size = size; |
25093 |
++ msg->src_id = conn->id; |
25094 |
++ msg->dst_id = name ? 0 : dst_id; |
25095 |
++ msg->cookie = cookie; |
25096 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
25097 |
++ |
25098 |
++ if (timeout) { |
25099 |
++ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); |
25100 |
++ if (ret < 0) |
25101 |
++ return ret; |
25102 |
++ |
25103 |
++ msg->timeout_ns = now.tv_sec * 1000000000ULL + |
25104 |
++ now.tv_nsec + timeout; |
25105 |
++ } |
25106 |
++ |
25107 |
++ item = msg->items; |
25108 |
++ |
25109 |
++ if (name) { |
25110 |
++ item->type = KDBUS_ITEM_DST_NAME; |
25111 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25112 |
++ strcpy(item->str, name); |
25113 |
++ item = KDBUS_ITEM_NEXT(item); |
25114 |
++ } |
25115 |
++ |
25116 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25117 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25118 |
++ item->vec.address = (uintptr_t)&ref1; |
25119 |
++ item->vec.size = sizeof(ref1); |
25120 |
++ item = KDBUS_ITEM_NEXT(item); |
25121 |
++ |
25122 |
++ /* data padding for ref1 */ |
25123 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25124 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25125 |
++ item->vec.address = (uintptr_t)NULL; |
25126 |
++ item->vec.size = KDBUS_ALIGN8(sizeof(ref1)) - sizeof(ref1); |
25127 |
++ item = KDBUS_ITEM_NEXT(item); |
25128 |
++ |
25129 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25130 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25131 |
++ item->vec.address = (uintptr_t)&ref2; |
25132 |
++ item->vec.size = sizeof(ref2); |
25133 |
++ item = KDBUS_ITEM_NEXT(item); |
25134 |
++ |
25135 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
25136 |
++ item->type = KDBUS_ITEM_BLOOM_FILTER; |
25137 |
++ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
25138 |
++ item->bloom_filter.generation = 0; |
25139 |
++ } else { |
25140 |
++ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
25141 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd); |
25142 |
++ item->memfd.size = 16; |
25143 |
++ item->memfd.fd = memfd; |
25144 |
++ } |
25145 |
++ item = KDBUS_ITEM_NEXT(item); |
25146 |
++ |
25147 |
++ size = sizeof(*cmd); |
25148 |
++ if (cancel_fd != -1) |
25149 |
++ size += KDBUS_ITEM_SIZE(sizeof(cancel_fd)); |
25150 |
++ |
25151 |
++ cmd = malloc(size); |
25152 |
++ cmd->size = size; |
25153 |
++ cmd->flags = cmd_flags; |
25154 |
++ cmd->msg_address = (uintptr_t)msg; |
25155 |
++ |
25156 |
++ item = cmd->items; |
25157 |
++ |
25158 |
++ if (cancel_fd != -1) { |
25159 |
++ item->type = KDBUS_ITEM_CANCEL_FD; |
25160 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(cancel_fd); |
25161 |
++ item->fds[0] = cancel_fd; |
25162 |
++ item = KDBUS_ITEM_NEXT(item); |
25163 |
++ } |
25164 |
++ |
25165 |
++ ret = kdbus_cmd_send(conn->fd, cmd); |
25166 |
++ if (memfd >= 0) |
25167 |
++ close(memfd); |
25168 |
++ |
25169 |
++ if (ret < 0) { |
25170 |
++ kdbus_printf("error sending message: %d (%m)\n", ret); |
25171 |
++ return ret; |
25172 |
++ } |
25173 |
++ |
25174 |
++ if (cmd_flags & KDBUS_SEND_SYNC_REPLY) { |
25175 |
++ struct kdbus_msg *reply; |
25176 |
++ |
25177 |
++ kdbus_printf("SYNC REPLY @offset %llu:\n", cmd->reply.offset); |
25178 |
++ reply = (struct kdbus_msg *)(conn->buf + cmd->reply.offset); |
25179 |
++ kdbus_msg_dump(conn, reply); |
25180 |
++ |
25181 |
++ kdbus_msg_free(reply); |
25182 |
++ |
25183 |
++ ret = kdbus_free(conn, cmd->reply.offset); |
25184 |
++ if (ret < 0) |
25185 |
++ return ret; |
25186 |
++ } |
25187 |
++ |
25188 |
++ free(msg); |
25189 |
++ free(cmd); |
25190 |
++ |
25191 |
++ return 0; |
25192 |
++} |
25193 |
++ |
25194 |
++int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, |
25195 |
++ uint64_t cookie, uint64_t flags, uint64_t timeout, |
25196 |
++ int64_t priority, uint64_t dst_id) |
25197 |
++{ |
25198 |
++ return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority, |
25199 |
++ dst_id, 0, -1); |
25200 |
++} |
25201 |
++ |
25202 |
++int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, |
25203 |
++ uint64_t cookie, uint64_t flags, uint64_t timeout, |
25204 |
++ int64_t priority, uint64_t dst_id, int cancel_fd) |
25205 |
++{ |
25206 |
++ return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority, |
25207 |
++ dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd); |
25208 |
++} |
25209 |
++ |
25210 |
++int kdbus_msg_send_reply(const struct kdbus_conn *conn, |
25211 |
++ uint64_t reply_cookie, |
25212 |
++ uint64_t dst_id) |
25213 |
++{ |
25214 |
++ struct kdbus_cmd_send cmd = {}; |
25215 |
++ struct kdbus_msg *msg; |
25216 |
++ const char ref1[1024 * 128 + 3] = "0123456789_0"; |
25217 |
++ struct kdbus_item *item; |
25218 |
++ uint64_t size; |
25219 |
++ int ret; |
25220 |
++ |
25221 |
++ size = sizeof(struct kdbus_msg); |
25222 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25223 |
++ |
25224 |
++ msg = malloc(size); |
25225 |
++ if (!msg) { |
25226 |
++ kdbus_printf("unable to malloc()!?\n"); |
25227 |
++ return -ENOMEM; |
25228 |
++ } |
25229 |
++ |
25230 |
++ memset(msg, 0, size); |
25231 |
++ msg->size = size; |
25232 |
++ msg->src_id = conn->id; |
25233 |
++ msg->dst_id = dst_id; |
25234 |
++ msg->cookie_reply = reply_cookie; |
25235 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
25236 |
++ |
25237 |
++ item = msg->items; |
25238 |
++ |
25239 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25240 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25241 |
++ item->vec.address = (uintptr_t)&ref1; |
25242 |
++ item->vec.size = sizeof(ref1); |
25243 |
++ item = KDBUS_ITEM_NEXT(item); |
25244 |
++ |
25245 |
++ cmd.size = sizeof(cmd); |
25246 |
++ cmd.msg_address = (uintptr_t)msg; |
25247 |
++ |
25248 |
++ ret = kdbus_cmd_send(conn->fd, &cmd); |
25249 |
++ if (ret < 0) |
25250 |
++ kdbus_printf("error sending message: %d (%m)\n", ret); |
25251 |
++ |
25252 |
++ free(msg); |
25253 |
++ |
25254 |
++ return ret; |
25255 |
++} |
25256 |
++ |
25257 |
++static char *msg_id(uint64_t id, char *buf) |
25258 |
++{ |
25259 |
++ if (id == 0) |
25260 |
++ return "KERNEL"; |
25261 |
++ if (id == ~0ULL) |
25262 |
++ return "BROADCAST"; |
25263 |
++ sprintf(buf, "%llu", (unsigned long long)id); |
25264 |
++ return buf; |
25265 |
++} |
25266 |
++ |
25267 |
++int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg) |
25268 |
++{ |
25269 |
++ const struct kdbus_item *item = msg->items; |
25270 |
++ char buf_src[32]; |
25271 |
++ char buf_dst[32]; |
25272 |
++ uint64_t timeout = 0; |
25273 |
++ uint64_t cookie_reply = 0; |
25274 |
++ int ret = 0; |
25275 |
++ |
25276 |
++ if (msg->flags & KDBUS_MSG_EXPECT_REPLY) |
25277 |
++ timeout = msg->timeout_ns; |
25278 |
++ else |
25279 |
++ cookie_reply = msg->cookie_reply; |
25280 |
++ |
25281 |
++ kdbus_printf("MESSAGE: %s (%llu bytes) flags=0x%08llx, %s → %s, " |
25282 |
++ "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n", |
25283 |
++ enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size, |
25284 |
++ (unsigned long long)msg->flags, |
25285 |
++ msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst), |
25286 |
++ (unsigned long long)msg->cookie, (unsigned long long)timeout, |
25287 |
++ (unsigned long long)cookie_reply, (long long)msg->priority); |
25288 |
++ |
25289 |
++ KDBUS_ITEM_FOREACH(item, msg, items) { |
25290 |
++ if (item->size < KDBUS_ITEM_HEADER_SIZE) { |
25291 |
++ kdbus_printf(" +%s (%llu bytes) invalid data record\n", |
25292 |
++ enum_MSG(item->type), item->size); |
25293 |
++ ret = -EINVAL; |
25294 |
++ break; |
25295 |
++ } |
25296 |
++ |
25297 |
++ switch (item->type) { |
25298 |
++ case KDBUS_ITEM_PAYLOAD_OFF: { |
25299 |
++ char *s; |
25300 |
++ |
25301 |
++ if (item->vec.offset == ~0ULL) |
25302 |
++ s = "[\\0-bytes]"; |
25303 |
++ else |
25304 |
++ s = (char *)msg + item->vec.offset; |
25305 |
++ |
25306 |
++ kdbus_printf(" +%s (%llu bytes) off=%llu size=%llu '%s'\n", |
25307 |
++ enum_MSG(item->type), item->size, |
25308 |
++ (unsigned long long)item->vec.offset, |
25309 |
++ (unsigned long long)item->vec.size, s); |
25310 |
++ break; |
25311 |
++ } |
25312 |
++ |
25313 |
++ case KDBUS_ITEM_FDS: { |
25314 |
++ int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25315 |
++ sizeof(int); |
25316 |
++ |
25317 |
++ kdbus_printf(" +%s (%llu bytes, %d fds)\n", |
25318 |
++ enum_MSG(item->type), item->size, n); |
25319 |
++ |
25320 |
++ for (i = 0; i < n; i++) |
25321 |
++ kdbus_printf(" fd[%d] = %d\n", |
25322 |
++ i, item->fds[i]); |
25323 |
++ |
25324 |
++ break; |
25325 |
++ } |
25326 |
++ |
25327 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
25328 |
++ char *buf; |
25329 |
++ off_t size; |
25330 |
++ |
25331 |
++ buf = mmap(NULL, item->memfd.size, PROT_READ, |
25332 |
++ MAP_PRIVATE, item->memfd.fd, 0); |
25333 |
++ if (buf == MAP_FAILED) { |
25334 |
++ kdbus_printf("mmap() fd=%i size=%llu failed: %m\n", |
25335 |
++ item->memfd.fd, item->memfd.size); |
25336 |
++ break; |
25337 |
++ } |
25338 |
++ |
25339 |
++ if (sys_memfd_get_size(item->memfd.fd, &size) < 0) { |
25340 |
++ kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n"); |
25341 |
++ break; |
25342 |
++ } |
25343 |
++ |
25344 |
++ kdbus_printf(" +%s (%llu bytes) fd=%i size=%llu filesize=%llu '%s'\n", |
25345 |
++ enum_MSG(item->type), item->size, item->memfd.fd, |
25346 |
++ (unsigned long long)item->memfd.size, |
25347 |
++ (unsigned long long)size, buf); |
25348 |
++ munmap(buf, item->memfd.size); |
25349 |
++ break; |
25350 |
++ } |
25351 |
++ |
25352 |
++ case KDBUS_ITEM_CREDS: |
25353 |
++ kdbus_printf(" +%s (%llu bytes) uid=%lld, euid=%lld, suid=%lld, fsuid=%lld, " |
25354 |
++ "gid=%lld, egid=%lld, sgid=%lld, fsgid=%lld\n", |
25355 |
++ enum_MSG(item->type), item->size, |
25356 |
++ item->creds.uid, item->creds.euid, |
25357 |
++ item->creds.suid, item->creds.fsuid, |
25358 |
++ item->creds.gid, item->creds.egid, |
25359 |
++ item->creds.sgid, item->creds.fsgid); |
25360 |
++ break; |
25361 |
++ |
25362 |
++ case KDBUS_ITEM_PIDS: |
25363 |
++ kdbus_printf(" +%s (%llu bytes) pid=%lld, tid=%lld, ppid=%lld\n", |
25364 |
++ enum_MSG(item->type), item->size, |
25365 |
++ item->pids.pid, item->pids.tid, |
25366 |
++ item->pids.ppid); |
25367 |
++ break; |
25368 |
++ |
25369 |
++ case KDBUS_ITEM_AUXGROUPS: { |
25370 |
++ int i, n; |
25371 |
++ |
25372 |
++ kdbus_printf(" +%s (%llu bytes)\n", |
25373 |
++ enum_MSG(item->type), item->size); |
25374 |
++ n = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25375 |
++ sizeof(uint64_t); |
25376 |
++ |
25377 |
++ for (i = 0; i < n; i++) |
25378 |
++ kdbus_printf(" gid[%d] = %lld\n", |
25379 |
++ i, item->data64[i]); |
25380 |
++ break; |
25381 |
++ } |
25382 |
++ |
25383 |
++ case KDBUS_ITEM_NAME: |
25384 |
++ case KDBUS_ITEM_PID_COMM: |
25385 |
++ case KDBUS_ITEM_TID_COMM: |
25386 |
++ case KDBUS_ITEM_EXE: |
25387 |
++ case KDBUS_ITEM_CGROUP: |
25388 |
++ case KDBUS_ITEM_SECLABEL: |
25389 |
++ case KDBUS_ITEM_DST_NAME: |
25390 |
++ case KDBUS_ITEM_CONN_DESCRIPTION: |
25391 |
++ kdbus_printf(" +%s (%llu bytes) '%s' (%zu)\n", |
25392 |
++ enum_MSG(item->type), item->size, |
25393 |
++ item->str, strlen(item->str)); |
25394 |
++ break; |
25395 |
++ |
25396 |
++ case KDBUS_ITEM_OWNED_NAME: { |
25397 |
++ kdbus_printf(" +%s (%llu bytes) '%s' (%zu) flags=0x%08llx\n", |
25398 |
++ enum_MSG(item->type), item->size, |
25399 |
++ item->name.name, strlen(item->name.name), |
25400 |
++ item->name.flags); |
25401 |
++ break; |
25402 |
++ } |
25403 |
++ |
25404 |
++ case KDBUS_ITEM_CMDLINE: { |
25405 |
++ size_t size = item->size - KDBUS_ITEM_HEADER_SIZE; |
25406 |
++ const char *str = item->str; |
25407 |
++ int count = 0; |
25408 |
++ |
25409 |
++ kdbus_printf(" +%s (%llu bytes) ", |
25410 |
++ enum_MSG(item->type), item->size); |
25411 |
++ while (size) { |
25412 |
++ kdbus_printf("'%s' ", str); |
25413 |
++ size -= strlen(str) + 1; |
25414 |
++ str += strlen(str) + 1; |
25415 |
++ count++; |
25416 |
++ } |
25417 |
++ |
25418 |
++ kdbus_printf("(%d string%s)\n", |
25419 |
++ count, (count == 1) ? "" : "s"); |
25420 |
++ break; |
25421 |
++ } |
25422 |
++ |
25423 |
++ case KDBUS_ITEM_AUDIT: |
25424 |
++ kdbus_printf(" +%s (%llu bytes) loginuid=%u sessionid=%u\n", |
25425 |
++ enum_MSG(item->type), item->size, |
25426 |
++ item->audit.loginuid, item->audit.sessionid); |
25427 |
++ break; |
25428 |
++ |
25429 |
++ case KDBUS_ITEM_CAPS: { |
25430 |
++ const uint32_t *cap; |
25431 |
++ int n, i; |
25432 |
++ |
25433 |
++ kdbus_printf(" +%s (%llu bytes) len=%llu bytes, last_cap %d\n", |
25434 |
++ enum_MSG(item->type), item->size, |
25435 |
++ (unsigned long long)item->size - |
25436 |
++ KDBUS_ITEM_HEADER_SIZE, |
25437 |
++ (int) item->caps.last_cap); |
25438 |
++ |
25439 |
++ cap = item->caps.caps; |
25440 |
++ n = (item->size - offsetof(struct kdbus_item, caps.caps)) |
25441 |
++ / 4 / sizeof(uint32_t); |
25442 |
++ |
25443 |
++ kdbus_printf(" CapInh="); |
25444 |
++ for (i = 0; i < n; i++) |
25445 |
++ kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]); |
25446 |
++ |
25447 |
++ kdbus_printf(" CapPrm="); |
25448 |
++ for (i = 0; i < n; i++) |
25449 |
++ kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]); |
25450 |
++ |
25451 |
++ kdbus_printf(" CapEff="); |
25452 |
++ for (i = 0; i < n; i++) |
25453 |
++ kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]); |
25454 |
++ |
25455 |
++ kdbus_printf(" CapBnd="); |
25456 |
++ for (i = 0; i < n; i++) |
25457 |
++ kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]); |
25458 |
++ kdbus_printf("\n"); |
25459 |
++ break; |
25460 |
++ } |
25461 |
++ |
25462 |
++ case KDBUS_ITEM_TIMESTAMP: |
25463 |
++ kdbus_printf(" +%s (%llu bytes) seq=%llu realtime=%lluns monotonic=%lluns\n", |
25464 |
++ enum_MSG(item->type), item->size, |
25465 |
++ (unsigned long long)item->timestamp.seqnum, |
25466 |
++ (unsigned long long)item->timestamp.realtime_ns, |
25467 |
++ (unsigned long long)item->timestamp.monotonic_ns); |
25468 |
++ break; |
25469 |
++ |
25470 |
++ case KDBUS_ITEM_REPLY_TIMEOUT: |
25471 |
++ kdbus_printf(" +%s (%llu bytes) cookie=%llu\n", |
25472 |
++ enum_MSG(item->type), item->size, |
25473 |
++ msg->cookie_reply); |
25474 |
++ break; |
25475 |
++ |
25476 |
++ case KDBUS_ITEM_NAME_ADD: |
25477 |
++ case KDBUS_ITEM_NAME_REMOVE: |
25478 |
++ case KDBUS_ITEM_NAME_CHANGE: |
25479 |
++ kdbus_printf(" +%s (%llu bytes) '%s', old id=%lld, now id=%lld, old_flags=0x%llx new_flags=0x%llx\n", |
25480 |
++ enum_MSG(item->type), |
25481 |
++ (unsigned long long) item->size, |
25482 |
++ item->name_change.name, |
25483 |
++ item->name_change.old_id.id, |
25484 |
++ item->name_change.new_id.id, |
25485 |
++ item->name_change.old_id.flags, |
25486 |
++ item->name_change.new_id.flags); |
25487 |
++ break; |
25488 |
++ |
25489 |
++ case KDBUS_ITEM_ID_ADD: |
25490 |
++ case KDBUS_ITEM_ID_REMOVE: |
25491 |
++ kdbus_printf(" +%s (%llu bytes) id=%llu flags=%llu\n", |
25492 |
++ enum_MSG(item->type), |
25493 |
++ (unsigned long long) item->size, |
25494 |
++ (unsigned long long) item->id_change.id, |
25495 |
++ (unsigned long long) item->id_change.flags); |
25496 |
++ break; |
25497 |
++ |
25498 |
++ default: |
25499 |
++ kdbus_printf(" +%s (%llu bytes)\n", |
25500 |
++ enum_MSG(item->type), item->size); |
25501 |
++ break; |
25502 |
++ } |
25503 |
++ } |
25504 |
++ |
25505 |
++ if ((char *)item - ((char *)msg + msg->size) >= 8) { |
25506 |
++ kdbus_printf("invalid padding at end of message\n"); |
25507 |
++ ret = -EINVAL; |
25508 |
++ } |
25509 |
++ |
25510 |
++ kdbus_printf("\n"); |
25511 |
++ |
25512 |
++ return ret; |
25513 |
++} |
25514 |
++ |
25515 |
++void kdbus_msg_free(struct kdbus_msg *msg) |
25516 |
++{ |
25517 |
++ const struct kdbus_item *item; |
25518 |
++ int nfds, i; |
25519 |
++ |
25520 |
++ if (!msg) |
25521 |
++ return; |
25522 |
++ |
25523 |
++ KDBUS_ITEM_FOREACH(item, msg, items) { |
25524 |
++ switch (item->type) { |
25525 |
++ /* close all memfds */ |
25526 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: |
25527 |
++ close(item->memfd.fd); |
25528 |
++ break; |
25529 |
++ case KDBUS_ITEM_FDS: |
25530 |
++ nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25531 |
++ sizeof(int); |
25532 |
++ |
25533 |
++ for (i = 0; i < nfds; i++) |
25534 |
++ close(item->fds[i]); |
25535 |
++ |
25536 |
++ break; |
25537 |
++ } |
25538 |
++ } |
25539 |
++} |
25540 |
++ |
25541 |
++int kdbus_msg_recv(struct kdbus_conn *conn, |
25542 |
++ struct kdbus_msg **msg_out, |
25543 |
++ uint64_t *offset) |
25544 |
++{ |
25545 |
++ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
25546 |
++ struct kdbus_msg *msg; |
25547 |
++ int ret; |
25548 |
++ |
25549 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
25550 |
++ if (ret < 0) |
25551 |
++ return ret; |
25552 |
++ |
25553 |
++ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
25554 |
++ ret = kdbus_msg_dump(conn, msg); |
25555 |
++ if (ret < 0) { |
25556 |
++ kdbus_msg_free(msg); |
25557 |
++ return ret; |
25558 |
++ } |
25559 |
++ |
25560 |
++ if (msg_out) { |
25561 |
++ *msg_out = msg; |
25562 |
++ |
25563 |
++ if (offset) |
25564 |
++ *offset = recv.msg.offset; |
25565 |
++ } else { |
25566 |
++ kdbus_msg_free(msg); |
25567 |
++ |
25568 |
++ ret = kdbus_free(conn, recv.msg.offset); |
25569 |
++ if (ret < 0) |
25570 |
++ return ret; |
25571 |
++ } |
25572 |
++ |
25573 |
++ return 0; |
25574 |
++} |
25575 |
++ |
25576 |
++/* |
25577 |
++ * Returns: 0 on success, negative errno on failure. |
25578 |
++ * |
25579 |
++ * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors. |
25580 |
++ * We must return the result of kdbus_msg_recv() |
25581 |
++ */ |
25582 |
++int kdbus_msg_recv_poll(struct kdbus_conn *conn, |
25583 |
++ int timeout_ms, |
25584 |
++ struct kdbus_msg **msg_out, |
25585 |
++ uint64_t *offset) |
25586 |
++{ |
25587 |
++ int ret; |
25588 |
++ |
25589 |
++ do { |
25590 |
++ struct timeval before, after, diff; |
25591 |
++ struct pollfd fd; |
25592 |
++ |
25593 |
++ fd.fd = conn->fd; |
25594 |
++ fd.events = POLLIN | POLLPRI | POLLHUP; |
25595 |
++ fd.revents = 0; |
25596 |
++ |
25597 |
++ gettimeofday(&before, NULL); |
25598 |
++ ret = poll(&fd, 1, timeout_ms); |
25599 |
++ gettimeofday(&after, NULL); |
25600 |
++ |
25601 |
++ if (ret == 0) { |
25602 |
++ ret = -ETIMEDOUT; |
25603 |
++ break; |
25604 |
++ } |
25605 |
++ |
25606 |
++ if (ret > 0) { |
25607 |
++ if (fd.revents & POLLIN) |
25608 |
++ ret = kdbus_msg_recv(conn, msg_out, offset); |
25609 |
++ |
25610 |
++ if (fd.revents & (POLLHUP | POLLERR)) |
25611 |
++ ret = -ECONNRESET; |
25612 |
++ } |
25613 |
++ |
25614 |
++ if (ret == 0 || ret != -EAGAIN) |
25615 |
++ break; |
25616 |
++ |
25617 |
++ timersub(&after, &before, &diff); |
25618 |
++ timeout_ms -= diff.tv_sec * 1000UL + |
25619 |
++ diff.tv_usec / 1000UL; |
25620 |
++ } while (timeout_ms > 0); |
25621 |
++ |
25622 |
++ return ret; |
25623 |
++} |
25624 |
++ |
25625 |
++int kdbus_free(const struct kdbus_conn *conn, uint64_t offset) |
25626 |
++{ |
25627 |
++ struct kdbus_cmd_free cmd_free = {}; |
25628 |
++ int ret; |
25629 |
++ |
25630 |
++ cmd_free.size = sizeof(cmd_free); |
25631 |
++ cmd_free.offset = offset; |
25632 |
++ cmd_free.flags = 0; |
25633 |
++ |
25634 |
++ ret = kdbus_cmd_free(conn->fd, &cmd_free); |
25635 |
++ if (ret < 0) { |
25636 |
++ kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret); |
25637 |
++ return ret; |
25638 |
++ } |
25639 |
++ |
25640 |
++ return 0; |
25641 |
++} |
25642 |
++ |
25643 |
++int kdbus_name_acquire(struct kdbus_conn *conn, |
25644 |
++ const char *name, uint64_t *flags) |
25645 |
++{ |
25646 |
++ struct kdbus_cmd *cmd_name; |
25647 |
++ size_t name_len = strlen(name) + 1; |
25648 |
++ uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len); |
25649 |
++ struct kdbus_item *item; |
25650 |
++ int ret; |
25651 |
++ |
25652 |
++ cmd_name = alloca(size); |
25653 |
++ |
25654 |
++ memset(cmd_name, 0, size); |
25655 |
++ |
25656 |
++ item = cmd_name->items; |
25657 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + name_len; |
25658 |
++ item->type = KDBUS_ITEM_NAME; |
25659 |
++ strcpy(item->str, name); |
25660 |
++ |
25661 |
++ cmd_name->size = size; |
25662 |
++ if (flags) |
25663 |
++ cmd_name->flags = *flags; |
25664 |
++ |
25665 |
++ ret = kdbus_cmd_name_acquire(conn->fd, cmd_name); |
25666 |
++ if (ret < 0) { |
25667 |
++ kdbus_printf("error aquiring name: %s\n", strerror(-ret)); |
25668 |
++ return ret; |
25669 |
++ } |
25670 |
++ |
25671 |
++ kdbus_printf("%s(): flags after call: 0x%llx\n", __func__, |
25672 |
++ cmd_name->return_flags); |
25673 |
++ |
25674 |
++ if (flags) |
25675 |
++ *flags = cmd_name->return_flags; |
25676 |
++ |
25677 |
++ return 0; |
25678 |
++} |
25679 |
++ |
25680 |
++int kdbus_name_release(struct kdbus_conn *conn, const char *name) |
25681 |
++{ |
25682 |
++ struct kdbus_cmd *cmd_name; |
25683 |
++ size_t name_len = strlen(name) + 1; |
25684 |
++ uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len); |
25685 |
++ struct kdbus_item *item; |
25686 |
++ int ret; |
25687 |
++ |
25688 |
++ cmd_name = alloca(size); |
25689 |
++ |
25690 |
++ memset(cmd_name, 0, size); |
25691 |
++ |
25692 |
++ item = cmd_name->items; |
25693 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + name_len; |
25694 |
++ item->type = KDBUS_ITEM_NAME; |
25695 |
++ strcpy(item->str, name); |
25696 |
++ |
25697 |
++ cmd_name->size = size; |
25698 |
++ |
25699 |
++ kdbus_printf("conn %lld giving up name '%s'\n", |
25700 |
++ (unsigned long long) conn->id, name); |
25701 |
++ |
25702 |
++ ret = kdbus_cmd_name_release(conn->fd, cmd_name); |
25703 |
++ if (ret < 0) { |
25704 |
++ kdbus_printf("error releasing name: %s\n", strerror(-ret)); |
25705 |
++ return ret; |
25706 |
++ } |
25707 |
++ |
25708 |
++ return 0; |
25709 |
++} |
25710 |
++ |
25711 |
++int kdbus_list(struct kdbus_conn *conn, uint64_t flags) |
25712 |
++{ |
25713 |
++ struct kdbus_cmd_list cmd_list = {}; |
25714 |
++ struct kdbus_info *list, *name; |
25715 |
++ int ret; |
25716 |
++ |
25717 |
++ cmd_list.size = sizeof(cmd_list); |
25718 |
++ cmd_list.flags = flags; |
25719 |
++ |
25720 |
++ ret = kdbus_cmd_list(conn->fd, &cmd_list); |
25721 |
++ if (ret < 0) { |
25722 |
++ kdbus_printf("error listing names: %d (%m)\n", ret); |
25723 |
++ return ret; |
25724 |
++ } |
25725 |
++ |
25726 |
++ kdbus_printf("REGISTRY:\n"); |
25727 |
++ list = (struct kdbus_info *)(conn->buf + cmd_list.offset); |
25728 |
++ |
25729 |
++ KDBUS_FOREACH(name, list, cmd_list.list_size) { |
25730 |
++ uint64_t flags = 0; |
25731 |
++ struct kdbus_item *item; |
25732 |
++ const char *n = "MISSING-NAME"; |
25733 |
++ |
25734 |
++ if (name->size == sizeof(struct kdbus_cmd)) |
25735 |
++ continue; |
25736 |
++ |
25737 |
++ KDBUS_ITEM_FOREACH(item, name, items) |
25738 |
++ if (item->type == KDBUS_ITEM_OWNED_NAME) { |
25739 |
++ n = item->name.name; |
25740 |
++ flags = item->name.flags; |
25741 |
++ } |
25742 |
++ |
25743 |
++ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n", |
25744 |
++ name->id, (unsigned long long) flags, |
25745 |
++ name->flags, n); |
25746 |
++ } |
25747 |
++ kdbus_printf("\n"); |
25748 |
++ |
25749 |
++ ret = kdbus_free(conn, cmd_list.offset); |
25750 |
++ |
25751 |
++ return ret; |
25752 |
++} |
25753 |
++ |
25754 |
++int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, |
25755 |
++ uint64_t attach_flags_send, |
25756 |
++ uint64_t attach_flags_recv) |
25757 |
++{ |
25758 |
++ int ret; |
25759 |
++ size_t size; |
25760 |
++ struct kdbus_cmd *update; |
25761 |
++ struct kdbus_item *item; |
25762 |
++ |
25763 |
++ size = sizeof(struct kdbus_cmd); |
25764 |
++ size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2; |
25765 |
++ |
25766 |
++ update = malloc(size); |
25767 |
++ if (!update) { |
25768 |
++ kdbus_printf("error malloc: %m\n"); |
25769 |
++ return -ENOMEM; |
25770 |
++ } |
25771 |
++ |
25772 |
++ memset(update, 0, size); |
25773 |
++ update->size = size; |
25774 |
++ |
25775 |
++ item = update->items; |
25776 |
++ |
25777 |
++ item->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; |
25778 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); |
25779 |
++ item->data64[0] = attach_flags_send; |
25780 |
++ item = KDBUS_ITEM_NEXT(item); |
25781 |
++ |
25782 |
++ item->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; |
25783 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); |
25784 |
++ item->data64[0] = attach_flags_recv; |
25785 |
++ item = KDBUS_ITEM_NEXT(item); |
25786 |
++ |
25787 |
++ ret = kdbus_cmd_update(conn->fd, update); |
25788 |
++ if (ret < 0) |
25789 |
++ kdbus_printf("error conn update: %d (%m)\n", ret); |
25790 |
++ |
25791 |
++ free(update); |
25792 |
++ |
25793 |
++ return ret; |
25794 |
++} |
25795 |
++ |
25796 |
++int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, |
25797 |
++ const struct kdbus_policy_access *access, |
25798 |
++ size_t num_access) |
25799 |
++{ |
25800 |
++ struct kdbus_cmd *update; |
25801 |
++ struct kdbus_item *item; |
25802 |
++ size_t i, size; |
25803 |
++ int ret; |
25804 |
++ |
25805 |
++ size = sizeof(struct kdbus_cmd); |
25806 |
++ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
25807 |
++ size += num_access * KDBUS_ITEM_SIZE(sizeof(struct kdbus_policy_access)); |
25808 |
++ |
25809 |
++ update = malloc(size); |
25810 |
++ if (!update) { |
25811 |
++ kdbus_printf("error malloc: %m\n"); |
25812 |
++ return -ENOMEM; |
25813 |
++ } |
25814 |
++ |
25815 |
++ memset(update, 0, size); |
25816 |
++ update->size = size; |
25817 |
++ |
25818 |
++ item = update->items; |
25819 |
++ |
25820 |
++ item->type = KDBUS_ITEM_NAME; |
25821 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25822 |
++ strcpy(item->str, name); |
25823 |
++ item = KDBUS_ITEM_NEXT(item); |
25824 |
++ |
25825 |
++ for (i = 0; i < num_access; i++) { |
25826 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + |
25827 |
++ sizeof(struct kdbus_policy_access); |
25828 |
++ item->type = KDBUS_ITEM_POLICY_ACCESS; |
25829 |
++ |
25830 |
++ item->policy_access.type = access[i].type; |
25831 |
++ item->policy_access.access = access[i].access; |
25832 |
++ item->policy_access.id = access[i].id; |
25833 |
++ |
25834 |
++ item = KDBUS_ITEM_NEXT(item); |
25835 |
++ } |
25836 |
++ |
25837 |
++ ret = kdbus_cmd_update(conn->fd, update); |
25838 |
++ if (ret < 0) |
25839 |
++ kdbus_printf("error conn update: %d (%m)\n", ret); |
25840 |
++ |
25841 |
++ free(update); |
25842 |
++ |
25843 |
++ return ret; |
25844 |
++} |
25845 |
++ |
25846 |
++int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, |
25847 |
++ uint64_t type, uint64_t id) |
25848 |
++{ |
25849 |
++ struct { |
25850 |
++ struct kdbus_cmd_match cmd; |
25851 |
++ struct { |
25852 |
++ uint64_t size; |
25853 |
++ uint64_t type; |
25854 |
++ struct kdbus_notify_id_change chg; |
25855 |
++ } item; |
25856 |
++ } buf; |
25857 |
++ int ret; |
25858 |
++ |
25859 |
++ memset(&buf, 0, sizeof(buf)); |
25860 |
++ |
25861 |
++ buf.cmd.size = sizeof(buf); |
25862 |
++ buf.cmd.cookie = cookie; |
25863 |
++ buf.item.size = sizeof(buf.item); |
25864 |
++ buf.item.type = type; |
25865 |
++ buf.item.chg.id = id; |
25866 |
++ |
25867 |
++ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
25868 |
++ if (ret < 0) |
25869 |
++ kdbus_printf("--- error adding conn match: %d (%m)\n", ret); |
25870 |
++ |
25871 |
++ return ret; |
25872 |
++} |
25873 |
++ |
25874 |
++int kdbus_add_match_empty(struct kdbus_conn *conn) |
25875 |
++{ |
25876 |
++ struct { |
25877 |
++ struct kdbus_cmd_match cmd; |
25878 |
++ struct kdbus_item item; |
25879 |
++ } buf; |
25880 |
++ int ret; |
25881 |
++ |
25882 |
++ memset(&buf, 0, sizeof(buf)); |
25883 |
++ |
25884 |
++ buf.item.size = sizeof(uint64_t) * 3; |
25885 |
++ buf.item.type = KDBUS_ITEM_ID; |
25886 |
++ buf.item.id = KDBUS_MATCH_ID_ANY; |
25887 |
++ |
25888 |
++ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
25889 |
++ |
25890 |
++ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
25891 |
++ if (ret < 0) |
25892 |
++ kdbus_printf("--- error adding conn match: %d (%m)\n", ret); |
25893 |
++ |
25894 |
++ return ret; |
25895 |
++} |
25896 |
++ |
25897 |
++static int all_ids_are_mapped(const char *path) |
25898 |
++{ |
25899 |
++ int ret; |
25900 |
++ FILE *file; |
25901 |
++ uint32_t inside_id, length; |
25902 |
++ |
25903 |
++ file = fopen(path, "r"); |
25904 |
++ if (!file) { |
25905 |
++ ret = -errno; |
25906 |
++ kdbus_printf("error fopen() %s: %d (%m)\n", |
25907 |
++ path, ret); |
25908 |
++ return ret; |
25909 |
++ } |
25910 |
++ |
25911 |
++ ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length); |
25912 |
++ if (ret != 2) { |
25913 |
++ if (ferror(file)) |
25914 |
++ ret = -errno; |
25915 |
++ else |
25916 |
++ ret = -EIO; |
25917 |
++ |
25918 |
++ kdbus_printf("--- error fscanf(): %d\n", ret); |
25919 |
++ fclose(file); |
25920 |
++ return ret; |
25921 |
++ } |
25922 |
++ |
25923 |
++ fclose(file); |
25924 |
++ |
25925 |
++ /* |
25926 |
++ * If length is 4294967295 which means the invalid uid |
25927 |
++ * (uid_t) -1 then we are able to map all uid/gids |
25928 |
++ */ |
25929 |
++ if (inside_id == 0 && length == (uid_t) -1) |
25930 |
++ return 1; |
25931 |
++ |
25932 |
++ return 0; |
25933 |
++} |
25934 |
++ |
25935 |
++int all_uids_gids_are_mapped() |
25936 |
++{ |
25937 |
++ int ret; |
25938 |
++ |
25939 |
++ ret = all_ids_are_mapped("/proc/self/uid_map"); |
25940 |
++ if (ret <= 0) { |
25941 |
++ kdbus_printf("--- error not all uids are mapped\n"); |
25942 |
++ return 0; |
25943 |
++ } |
25944 |
++ |
25945 |
++ ret = all_ids_are_mapped("/proc/self/gid_map"); |
25946 |
++ if (ret <= 0) { |
25947 |
++ kdbus_printf("--- error not all gids are mapped\n"); |
25948 |
++ return 0; |
25949 |
++ } |
25950 |
++ |
25951 |
++ return 1; |
25952 |
++} |
25953 |
++ |
25954 |
++int drop_privileges(uid_t uid, gid_t gid) |
25955 |
++{ |
25956 |
++ int ret; |
25957 |
++ |
25958 |
++ ret = setgroups(0, NULL); |
25959 |
++ if (ret < 0) { |
25960 |
++ ret = -errno; |
25961 |
++ kdbus_printf("error setgroups: %d (%m)\n", ret); |
25962 |
++ return ret; |
25963 |
++ } |
25964 |
++ |
25965 |
++ ret = setresgid(gid, gid, gid); |
25966 |
++ if (ret < 0) { |
25967 |
++ ret = -errno; |
25968 |
++ kdbus_printf("error setresgid: %d (%m)\n", ret); |
25969 |
++ return ret; |
25970 |
++ } |
25971 |
++ |
25972 |
++ ret = setresuid(uid, uid, uid); |
25973 |
++ if (ret < 0) { |
25974 |
++ ret = -errno; |
25975 |
++ kdbus_printf("error setresuid: %d (%m)\n", ret); |
25976 |
++ return ret; |
25977 |
++ } |
25978 |
++ |
25979 |
++ return ret; |
25980 |
++} |
25981 |
++ |
25982 |
++uint64_t now(clockid_t clock) |
25983 |
++{ |
25984 |
++ struct timespec spec; |
25985 |
++ |
25986 |
++ clock_gettime(clock, &spec); |
25987 |
++ return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec; |
25988 |
++} |
25989 |
++ |
25990 |
++char *unique_name(const char *prefix) |
25991 |
++{ |
25992 |
++ unsigned int i; |
25993 |
++ uint64_t u_now; |
25994 |
++ char n[17]; |
25995 |
++ char *str; |
25996 |
++ int r; |
25997 |
++ |
25998 |
++ /* |
25999 |
++ * This returns a random string which is guaranteed to be |
26000 |
++ * globally unique across all calls to unique_name(). We |
26001 |
++ * compose the string as: |
26002 |
++ * <prefix>-<random>-<time> |
26003 |
++ * With: |
26004 |
++ * <prefix>: string provided by the caller |
26005 |
++ * <random>: a random alpha string of 16 characters |
26006 |
++ * <time>: the current time in micro-seconds since last boot |
26007 |
++ * |
26008 |
++ * The <random> part makes the string always look vastly different, |
26009 |
++ * the <time> part makes sure no two calls return the same string. |
26010 |
++ */ |
26011 |
++ |
26012 |
++ u_now = now(CLOCK_MONOTONIC); |
26013 |
++ |
26014 |
++ for (i = 0; i < sizeof(n) - 1; ++i) |
26015 |
++ n[i] = 'a' + (rand() % ('z' - 'a')); |
26016 |
++ n[sizeof(n) - 1] = 0; |
26017 |
++ |
26018 |
++ r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now); |
26019 |
++ if (r < 0) |
26020 |
++ return NULL; |
26021 |
++ |
26022 |
++ return str; |
26023 |
++} |
26024 |
++ |
26025 |
++static int do_userns_map_id(pid_t pid, |
26026 |
++ const char *map_file, |
26027 |
++ const char *map_id) |
26028 |
++{ |
26029 |
++ int ret; |
26030 |
++ int fd; |
26031 |
++ char *map; |
26032 |
++ unsigned int i; |
26033 |
++ |
26034 |
++ map = strndupa(map_id, strlen(map_id)); |
26035 |
++ if (!map) { |
26036 |
++ ret = -errno; |
26037 |
++ kdbus_printf("error strndupa %s: %d (%m)\n", |
26038 |
++ map_file, ret); |
26039 |
++ return ret; |
26040 |
++ } |
26041 |
++ |
26042 |
++ for (i = 0; i < strlen(map); i++) |
26043 |
++ if (map[i] == ',') |
26044 |
++ map[i] = '\n'; |
26045 |
++ |
26046 |
++ fd = open(map_file, O_RDWR); |
26047 |
++ if (fd < 0) { |
26048 |
++ ret = -errno; |
26049 |
++ kdbus_printf("error open %s: %d (%m)\n", |
26050 |
++ map_file, ret); |
26051 |
++ return ret; |
26052 |
++ } |
26053 |
++ |
26054 |
++ ret = write(fd, map, strlen(map)); |
26055 |
++ if (ret < 0) { |
26056 |
++ ret = -errno; |
26057 |
++ kdbus_printf("error write to %s: %d (%m)\n", |
26058 |
++ map_file, ret); |
26059 |
++ goto out; |
26060 |
++ } |
26061 |
++ |
26062 |
++ ret = 0; |
26063 |
++ |
26064 |
++out: |
26065 |
++ close(fd); |
26066 |
++ return ret; |
26067 |
++} |
26068 |
++ |
26069 |
++int userns_map_uid_gid(pid_t pid, |
26070 |
++ const char *map_uid, |
26071 |
++ const char *map_gid) |
26072 |
++{ |
26073 |
++ int fd, ret; |
26074 |
++ char file_id[128] = {'\0'}; |
26075 |
++ |
26076 |
++ snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map", |
26077 |
++ (long) pid); |
26078 |
++ |
26079 |
++ ret = do_userns_map_id(pid, file_id, map_uid); |
26080 |
++ if (ret < 0) |
26081 |
++ return ret; |
26082 |
++ |
26083 |
++ snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups", |
26084 |
++ (long) pid); |
26085 |
++ |
26086 |
++ fd = open(file_id, O_WRONLY); |
26087 |
++ if (fd >= 0) { |
26088 |
++ write(fd, "deny\n", 5); |
26089 |
++ close(fd); |
26090 |
++ } |
26091 |
++ |
26092 |
++ snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map", |
26093 |
++ (long) pid); |
26094 |
++ |
26095 |
++ return do_userns_map_id(pid, file_id, map_gid); |
26096 |
++} |
26097 |
++ |
26098 |
++static int do_cap_get_flag(cap_t caps, cap_value_t cap) |
26099 |
++{ |
26100 |
++ int ret; |
26101 |
++ cap_flag_value_t flag_set; |
26102 |
++ |
26103 |
++ ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set); |
26104 |
++ if (ret < 0) { |
26105 |
++ ret = -errno; |
26106 |
++ kdbus_printf("error cap_get_flag(): %d (%m)\n", ret); |
26107 |
++ return ret; |
26108 |
++ } |
26109 |
++ |
26110 |
++ return (flag_set == CAP_SET); |
26111 |
++} |
26112 |
++ |
26113 |
++/* |
26114 |
++ * Returns: |
26115 |
++ * 1 in case all the requested effective capabilities are set. |
26116 |
++ * 0 in case we do not have the requested capabilities. This value |
26117 |
++ * will be used to abort tests with TEST_SKIP |
26118 |
++ * Negative errno on failure. |
26119 |
++ * |
26120 |
++ * Terminate args with a negative value. |
26121 |
++ */ |
26122 |
++int test_is_capable(int cap, ...) |
26123 |
++{ |
26124 |
++ int ret; |
26125 |
++ va_list ap; |
26126 |
++ cap_t caps; |
26127 |
++ |
26128 |
++ caps = cap_get_proc(); |
26129 |
++ if (!cap) { |
26130 |
++ ret = -errno; |
26131 |
++ kdbus_printf("error cap_get_proc(): %d (%m)\n", ret); |
26132 |
++ return ret; |
26133 |
++ } |
26134 |
++ |
26135 |
++ ret = do_cap_get_flag(caps, (cap_value_t)cap); |
26136 |
++ if (ret <= 0) |
26137 |
++ goto out; |
26138 |
++ |
26139 |
++ va_start(ap, cap); |
26140 |
++ while ((cap = va_arg(ap, int)) > 0) { |
26141 |
++ ret = do_cap_get_flag(caps, (cap_value_t)cap); |
26142 |
++ if (ret <= 0) |
26143 |
++ break; |
26144 |
++ } |
26145 |
++ va_end(ap); |
26146 |
++ |
26147 |
++out: |
26148 |
++ cap_free(caps); |
26149 |
++ return ret; |
26150 |
++} |
26151 |
++ |
26152 |
++int config_user_ns_is_enabled(void) |
26153 |
++{ |
26154 |
++ return (access("/proc/self/uid_map", F_OK) == 0); |
26155 |
++} |
26156 |
++ |
26157 |
++int config_auditsyscall_is_enabled(void) |
26158 |
++{ |
26159 |
++ return (access("/proc/self/loginuid", F_OK) == 0); |
26160 |
++} |
26161 |
++ |
26162 |
++int config_cgroups_is_enabled(void) |
26163 |
++{ |
26164 |
++ return (access("/proc/self/cgroup", F_OK) == 0); |
26165 |
++} |
26166 |
++ |
26167 |
++int config_security_is_enabled(void) |
26168 |
++{ |
26169 |
++ int fd; |
26170 |
++ int ret; |
26171 |
++ char buf[128]; |
26172 |
++ |
26173 |
++ /* CONFIG_SECURITY is disabled */ |
26174 |
++ if (access("/proc/self/attr/current", F_OK) != 0) |
26175 |
++ return 0; |
26176 |
++ |
26177 |
++ /* |
26178 |
++ * Now only if read() fails with -EINVAL then we assume |
26179 |
++ * that SECLABEL and LSM are disabled |
26180 |
++ */ |
26181 |
++ fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC); |
26182 |
++ if (fd < 0) |
26183 |
++ return 1; |
26184 |
++ |
26185 |
++ ret = read(fd, buf, sizeof(buf)); |
26186 |
++ if (ret == -1 && errno == EINVAL) |
26187 |
++ ret = 0; |
26188 |
++ else |
26189 |
++ ret = 1; |
26190 |
++ |
26191 |
++ close(fd); |
26192 |
++ |
26193 |
++ return ret; |
26194 |
++} |
26195 |
+diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h |
26196 |
+new file mode 100644 |
26197 |
+index 0000000..50ff071 |
26198 |
+--- /dev/null |
26199 |
++++ b/tools/testing/selftests/kdbus/kdbus-util.h |
26200 |
+@@ -0,0 +1,222 @@ |
26201 |
++/* |
26202 |
++ * Copyright (C) 2013-2015 Kay Sievers |
26203 |
++ * Copyright (C) 2013-2015 Daniel Mack |
26204 |
++ * |
26205 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
26206 |
++ * the terms of the GNU Lesser General Public License as published by the |
26207 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
26208 |
++ * your option) any later version. |
26209 |
++ */ |
26210 |
++#pragma once |
26211 |
++ |
26212 |
++#define BIT(X) (1 << (X)) |
26213 |
++ |
26214 |
++#include <time.h> |
26215 |
++#include <stdbool.h> |
26216 |
++#include <linux/kdbus.h> |
26217 |
++ |
26218 |
++#define _STRINGIFY(x) #x |
26219 |
++#define STRINGIFY(x) _STRINGIFY(x) |
26220 |
++#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) |
26221 |
++ |
26222 |
++#define KDBUS_PTR(addr) ((void *)(uintptr_t)(addr)) |
26223 |
++ |
26224 |
++#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) |
26225 |
++#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
26226 |
++#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) |
26227 |
++ |
26228 |
++#define KDBUS_ITEM_NEXT(item) \ |
26229 |
++ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size)) |
26230 |
++#define KDBUS_ITEM_FOREACH(item, head, first) \ |
26231 |
++ for (item = (head)->first; \ |
26232 |
++ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ |
26233 |
++ ((uint8_t *)(item) >= (uint8_t *)(head)); \ |
26234 |
++ item = KDBUS_ITEM_NEXT(item)) |
26235 |
++#define KDBUS_FOREACH(iter, first, _size) \ |
26236 |
++ for (iter = (first); \ |
26237 |
++ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ |
26238 |
++ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ |
26239 |
++ iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size))) |
26240 |
++ |
26241 |
++ |
26242 |
++#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL)) |
26243 |
++ |
26244 |
++/* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */ |
26245 |
++#define KDBUS_ATTACH_ITEMS_TYPE_SUM \ |
26246 |
++ ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \ |
26247 |
++ ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2 ) + \ |
26248 |
++ (_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR)) |
26249 |
++ |
26250 |
++ |
26251 |
++#define POOL_SIZE (16 * 1024LU * 1024LU) |
26252 |
++ |
26253 |
++#define UNPRIV_UID 65534 |
26254 |
++#define UNPRIV_GID 65534 |
26255 |
++ |
26256 |
++/* Dump as user of process, useful for user namespace testing */ |
26257 |
++#define SUID_DUMP_USER 1 |
26258 |
++ |
26259 |
++extern int kdbus_util_verbose; |
26260 |
++ |
26261 |
++#define kdbus_printf(X...) \ |
26262 |
++ if (kdbus_util_verbose) \ |
26263 |
++ printf(X) |
26264 |
++ |
26265 |
++#define RUN_UNPRIVILEGED(child_uid, child_gid, _child_, _parent_) ({ \ |
26266 |
++ pid_t pid, rpid; \ |
26267 |
++ int ret; \ |
26268 |
++ \ |
26269 |
++ pid = fork(); \ |
26270 |
++ if (pid == 0) { \ |
26271 |
++ ret = drop_privileges(child_uid, child_gid); \ |
26272 |
++ ASSERT_EXIT_VAL(ret == 0, ret); \ |
26273 |
++ \ |
26274 |
++ _child_; \ |
26275 |
++ _exit(0); \ |
26276 |
++ } else if (pid > 0) { \ |
26277 |
++ _parent_; \ |
26278 |
++ rpid = waitpid(pid, &ret, 0); \ |
26279 |
++ ASSERT_RETURN(rpid == pid); \ |
26280 |
++ ASSERT_RETURN(WIFEXITED(ret)); \ |
26281 |
++ ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ |
26282 |
++ ret = TEST_OK; \ |
26283 |
++ } else { \ |
26284 |
++ ret = pid; \ |
26285 |
++ } \ |
26286 |
++ \ |
26287 |
++ ret; \ |
26288 |
++ }) |
26289 |
++ |
26290 |
++#define RUN_UNPRIVILEGED_CONN(_var_, _bus_, _code_) \ |
26291 |
++ RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ \ |
26292 |
++ struct kdbus_conn *_var_; \ |
26293 |
++ _var_ = kdbus_hello(_bus_, 0, NULL, 0); \ |
26294 |
++ ASSERT_EXIT(_var_); \ |
26295 |
++ _code_; \ |
26296 |
++ kdbus_conn_free(_var_); \ |
26297 |
++ }), ({ 0; })) |
26298 |
++ |
26299 |
++#define RUN_CLONE_CHILD(clone_ret, flags, _setup_, _child_body_, \ |
26300 |
++ _parent_setup_, _parent_body_) ({ \ |
26301 |
++ pid_t pid, rpid; \ |
26302 |
++ int ret; \ |
26303 |
++ int efd = -1; \ |
26304 |
++ \ |
26305 |
++ _setup_; \ |
26306 |
++ efd = eventfd(0, EFD_CLOEXEC); \ |
26307 |
++ ASSERT_RETURN(efd >= 0); \ |
26308 |
++ *clone_ret = 0; \ |
26309 |
++ pid = syscall(__NR_clone, flags, NULL); \ |
26310 |
++ if (pid == 0) { \ |
26311 |
++ eventfd_t event_status = 0; \ |
26312 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); \ |
26313 |
++ ASSERT_EXIT(ret == 0); \ |
26314 |
++ ret = eventfd_read(efd, &event_status); \ |
26315 |
++ if (ret < 0 || event_status != 1) { \ |
26316 |
++ kdbus_printf("error eventfd_read()\n"); \ |
26317 |
++ _exit(EXIT_FAILURE); \ |
26318 |
++ } \ |
26319 |
++ _child_body_; \ |
26320 |
++ _exit(0); \ |
26321 |
++ } else if (pid > 0) { \ |
26322 |
++ _parent_setup_; \ |
26323 |
++ ret = eventfd_write(efd, 1); \ |
26324 |
++ ASSERT_RETURN(ret >= 0); \ |
26325 |
++ _parent_body_; \ |
26326 |
++ rpid = waitpid(pid, &ret, 0); \ |
26327 |
++ ASSERT_RETURN(rpid == pid); \ |
26328 |
++ ASSERT_RETURN(WIFEXITED(ret)); \ |
26329 |
++ ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ |
26330 |
++ ret = TEST_OK; \ |
26331 |
++ } else { \ |
26332 |
++ ret = -errno; \ |
26333 |
++ *clone_ret = -errno; \ |
26334 |
++ } \ |
26335 |
++ close(efd); \ |
26336 |
++ ret; \ |
26337 |
++}) |
26338 |
++ |
26339 |
++/* Enums for parent if it should drop privs or not */ |
26340 |
++enum kdbus_drop_parent { |
26341 |
++ DO_NOT_DROP, |
26342 |
++ DROP_SAME_UNPRIV, |
26343 |
++ DROP_OTHER_UNPRIV, |
26344 |
++}; |
26345 |
++ |
26346 |
++struct kdbus_conn { |
26347 |
++ int fd; |
26348 |
++ uint64_t id; |
26349 |
++ unsigned char *buf; |
26350 |
++}; |
26351 |
++ |
26352 |
++int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask); |
26353 |
++int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask); |
26354 |
++ |
26355 |
++int sys_memfd_create(const char *name, __u64 size); |
26356 |
++int sys_memfd_seal_set(int fd); |
26357 |
++off_t sys_memfd_get_size(int fd, off_t *size); |
26358 |
++ |
26359 |
++int kdbus_list(struct kdbus_conn *conn, uint64_t flags); |
26360 |
++int kdbus_name_release(struct kdbus_conn *conn, const char *name); |
26361 |
++int kdbus_name_acquire(struct kdbus_conn *conn, const char *name, |
26362 |
++ uint64_t *flags); |
26363 |
++void kdbus_msg_free(struct kdbus_msg *msg); |
26364 |
++int kdbus_msg_recv(struct kdbus_conn *conn, |
26365 |
++ struct kdbus_msg **msg, uint64_t *offset); |
26366 |
++int kdbus_msg_recv_poll(struct kdbus_conn *conn, int timeout_ms, |
26367 |
++ struct kdbus_msg **msg_out, uint64_t *offset); |
26368 |
++int kdbus_free(const struct kdbus_conn *conn, uint64_t offset); |
26369 |
++int kdbus_msg_dump(const struct kdbus_conn *conn, |
26370 |
++ const struct kdbus_msg *msg); |
26371 |
++int kdbus_create_bus(int control_fd, const char *name, |
26372 |
++ uint64_t req_meta, uint64_t owner_meta, |
26373 |
++ char **path); |
26374 |
++int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, |
26375 |
++ uint64_t cookie, uint64_t flags, uint64_t timeout, |
26376 |
++ int64_t priority, uint64_t dst_id); |
26377 |
++int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, |
26378 |
++ uint64_t cookie, uint64_t flags, uint64_t timeout, |
26379 |
++ int64_t priority, uint64_t dst_id, int cancel_fd); |
26380 |
++int kdbus_msg_send_reply(const struct kdbus_conn *conn, |
26381 |
++ uint64_t reply_cookie, |
26382 |
++ uint64_t dst_id); |
26383 |
++struct kdbus_conn *kdbus_hello(const char *path, uint64_t hello_flags, |
26384 |
++ const struct kdbus_item *item, |
26385 |
++ size_t item_size); |
26386 |
++struct kdbus_conn *kdbus_hello_registrar(const char *path, const char *name, |
26387 |
++ const struct kdbus_policy_access *access, |
26388 |
++ size_t num_access, uint64_t flags); |
26389 |
++struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, |
26390 |
++ const struct kdbus_policy_access *access, |
26391 |
++ size_t num_access); |
26392 |
++bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type); |
26393 |
++int kdbus_bus_creator_info(struct kdbus_conn *conn, |
26394 |
++ uint64_t flags, |
26395 |
++ uint64_t *offset); |
26396 |
++int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, |
26397 |
++ const char *name, uint64_t flags, uint64_t *offset); |
26398 |
++void kdbus_conn_free(struct kdbus_conn *conn); |
26399 |
++int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, |
26400 |
++ uint64_t attach_flags_send, |
26401 |
++ uint64_t attach_flags_recv); |
26402 |
++int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, |
26403 |
++ const struct kdbus_policy_access *access, |
26404 |
++ size_t num_access); |
26405 |
++ |
26406 |
++int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, |
26407 |
++ uint64_t type, uint64_t id); |
26408 |
++int kdbus_add_match_empty(struct kdbus_conn *conn); |
26409 |
++ |
26410 |
++int all_uids_gids_are_mapped(); |
26411 |
++int drop_privileges(uid_t uid, gid_t gid); |
26412 |
++uint64_t now(clockid_t clock); |
26413 |
++char *unique_name(const char *prefix); |
26414 |
++ |
26415 |
++int userns_map_uid_gid(pid_t pid, |
26416 |
++ const char *map_uid, |
26417 |
++ const char *map_gid); |
26418 |
++int test_is_capable(int cap, ...); |
26419 |
++int config_user_ns_is_enabled(void); |
26420 |
++int config_auditsyscall_is_enabled(void); |
26421 |
++int config_cgroups_is_enabled(void); |
26422 |
++int config_security_is_enabled(void); |
26423 |
+diff --git a/tools/testing/selftests/kdbus/test-activator.c b/tools/testing/selftests/kdbus/test-activator.c |
26424 |
+new file mode 100644 |
26425 |
+index 0000000..3d1b763 |
26426 |
+--- /dev/null |
26427 |
++++ b/tools/testing/selftests/kdbus/test-activator.c |
26428 |
+@@ -0,0 +1,318 @@ |
26429 |
++#include <stdio.h> |
26430 |
++#include <string.h> |
26431 |
++#include <time.h> |
26432 |
++#include <fcntl.h> |
26433 |
++#include <stdlib.h> |
26434 |
++#include <stdbool.h> |
26435 |
++#include <stddef.h> |
26436 |
++#include <unistd.h> |
26437 |
++#include <stdint.h> |
26438 |
++#include <errno.h> |
26439 |
++#include <assert.h> |
26440 |
++#include <poll.h> |
26441 |
++#include <sys/capability.h> |
26442 |
++#include <sys/types.h> |
26443 |
++#include <sys/wait.h> |
26444 |
++ |
26445 |
++#include "kdbus-test.h" |
26446 |
++#include "kdbus-util.h" |
26447 |
++#include "kdbus-enum.h" |
26448 |
++ |
26449 |
++static int kdbus_starter_poll(struct kdbus_conn *conn) |
26450 |
++{ |
26451 |
++ int ret; |
26452 |
++ struct pollfd fd; |
26453 |
++ |
26454 |
++ fd.fd = conn->fd; |
26455 |
++ fd.events = POLLIN | POLLPRI | POLLHUP; |
26456 |
++ fd.revents = 0; |
26457 |
++ |
26458 |
++ ret = poll(&fd, 1, 100); |
26459 |
++ if (ret == 0) |
26460 |
++ return -ETIMEDOUT; |
26461 |
++ else if (ret > 0) { |
26462 |
++ if (fd.revents & POLLIN) |
26463 |
++ return 0; |
26464 |
++ |
26465 |
++ if (fd.revents & (POLLHUP | POLLERR)) |
26466 |
++ ret = -ECONNRESET; |
26467 |
++ } |
26468 |
++ |
26469 |
++ return ret; |
26470 |
++} |
26471 |
++ |
26472 |
++/* Ensure that kdbus activator logic is safe */ |
26473 |
++static int kdbus_priv_activator(struct kdbus_test_env *env) |
26474 |
++{ |
26475 |
++ int ret; |
26476 |
++ struct kdbus_msg *msg = NULL; |
26477 |
++ uint64_t cookie = 0xdeadbeef; |
26478 |
++ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
26479 |
++ struct kdbus_conn *activator; |
26480 |
++ struct kdbus_conn *service; |
26481 |
++ struct kdbus_conn *client; |
26482 |
++ struct kdbus_conn *holder; |
26483 |
++ struct kdbus_policy_access *access; |
26484 |
++ |
26485 |
++ access = (struct kdbus_policy_access[]){ |
26486 |
++ { |
26487 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
26488 |
++ .id = getuid(), |
26489 |
++ .access = KDBUS_POLICY_OWN, |
26490 |
++ }, |
26491 |
++ { |
26492 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
26493 |
++ .id = getuid(), |
26494 |
++ .access = KDBUS_POLICY_TALK, |
26495 |
++ }, |
26496 |
++ }; |
26497 |
++ |
26498 |
++ activator = kdbus_hello_activator(env->buspath, "foo.priv.activator", |
26499 |
++ access, 2); |
26500 |
++ ASSERT_RETURN(activator); |
26501 |
++ |
26502 |
++ service = kdbus_hello(env->buspath, 0, NULL, 0); |
26503 |
++ ASSERT_RETURN(service); |
26504 |
++ |
26505 |
++ client = kdbus_hello(env->buspath, 0, NULL, 0); |
26506 |
++ ASSERT_RETURN(client); |
26507 |
++ |
26508 |
++ /* |
26509 |
++ * Make sure that other users can't TALK to the activator |
26510 |
++ */ |
26511 |
++ |
26512 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26513 |
++ /* Try to talk using the ID */ |
26514 |
++ ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0, |
26515 |
++ 0, activator->id); |
26516 |
++ ASSERT_EXIT(ret == -ENXIO); |
26517 |
++ |
26518 |
++ /* Try to talk to the name */ |
26519 |
++ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26520 |
++ 0xdeadbeef, 0, 0, 0, |
26521 |
++ KDBUS_DST_ID_NAME); |
26522 |
++ ASSERT_EXIT(ret == -EPERM); |
26523 |
++ })); |
26524 |
++ ASSERT_RETURN(ret >= 0); |
26525 |
++ |
26526 |
++ /* |
26527 |
++ * Make sure that we did not receive anything, so the |
26528 |
++ * service will not be started automatically |
26529 |
++ */ |
26530 |
++ |
26531 |
++ ret = kdbus_starter_poll(activator); |
26532 |
++ ASSERT_RETURN(ret == -ETIMEDOUT); |
26533 |
++ |
26534 |
++ /* |
26535 |
++ * Now try to emulate the starter/service logic and |
26536 |
++ * acquire the name. |
26537 |
++ */ |
26538 |
++ |
26539 |
++ cookie++; |
26540 |
++ ret = kdbus_msg_send(service, "foo.priv.activator", cookie, |
26541 |
++ 0, 0, 0, KDBUS_DST_ID_NAME); |
26542 |
++ ASSERT_RETURN(ret == 0); |
26543 |
++ |
26544 |
++ ret = kdbus_starter_poll(activator); |
26545 |
++ ASSERT_RETURN(ret == 0); |
26546 |
++ |
26547 |
++ /* Policies are still checked, access denied */ |
26548 |
++ |
26549 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26550 |
++ ret = kdbus_name_acquire(unpriv, "foo.priv.activator", |
26551 |
++ &flags); |
26552 |
++ ASSERT_RETURN(ret == -EPERM); |
26553 |
++ })); |
26554 |
++ ASSERT_RETURN(ret >= 0); |
26555 |
++ |
26556 |
++ ret = kdbus_name_acquire(service, "foo.priv.activator", |
26557 |
++ &flags); |
26558 |
++ ASSERT_RETURN(ret == 0); |
26559 |
++ |
26560 |
++ /* We read our previous starter message */ |
26561 |
++ |
26562 |
++ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26563 |
++ ASSERT_RETURN(ret == 0); |
26564 |
++ |
26565 |
++ /* Try to talk, we still fail */ |
26566 |
++ |
26567 |
++ cookie++; |
26568 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26569 |
++ /* Try to talk to the name */ |
26570 |
++ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26571 |
++ cookie, 0, 0, 0, |
26572 |
++ KDBUS_DST_ID_NAME); |
26573 |
++ ASSERT_EXIT(ret == -EPERM); |
26574 |
++ })); |
26575 |
++ ASSERT_RETURN(ret >= 0); |
26576 |
++ |
26577 |
++ /* Still nothing to read */ |
26578 |
++ |
26579 |
++ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26580 |
++ ASSERT_RETURN(ret == -ETIMEDOUT); |
26581 |
++ |
26582 |
++ /* We receive every thing now */ |
26583 |
++ |
26584 |
++ cookie++; |
26585 |
++ ret = kdbus_msg_send(client, "foo.priv.activator", cookie, |
26586 |
++ 0, 0, 0, KDBUS_DST_ID_NAME); |
26587 |
++ ASSERT_RETURN(ret == 0); |
26588 |
++ ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); |
26589 |
++ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
26590 |
++ |
26591 |
++ kdbus_msg_free(msg); |
26592 |
++ |
26593 |
++ /* Policies default to deny TALK now */ |
26594 |
++ kdbus_conn_free(activator); |
26595 |
++ |
26596 |
++ cookie++; |
26597 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26598 |
++ /* Try to talk to the name */ |
26599 |
++ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26600 |
++ cookie, 0, 0, 0, |
26601 |
++ KDBUS_DST_ID_NAME); |
26602 |
++ ASSERT_EXIT(ret == -EPERM); |
26603 |
++ })); |
26604 |
++ ASSERT_RETURN(ret >= 0); |
26605 |
++ |
26606 |
++ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26607 |
++ ASSERT_RETURN(ret == -ETIMEDOUT); |
26608 |
++ |
26609 |
++ /* Same user is able to TALK */ |
26610 |
++ cookie++; |
26611 |
++ ret = kdbus_msg_send(client, "foo.priv.activator", cookie, |
26612 |
++ 0, 0, 0, KDBUS_DST_ID_NAME); |
26613 |
++ ASSERT_RETURN(ret == 0); |
26614 |
++ ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); |
26615 |
++ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
26616 |
++ |
26617 |
++ kdbus_msg_free(msg); |
26618 |
++ |
26619 |
++ access = (struct kdbus_policy_access []){ |
26620 |
++ { |
26621 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
26622 |
++ .id = getuid(), |
26623 |
++ .access = KDBUS_POLICY_TALK, |
26624 |
++ }, |
26625 |
++ }; |
26626 |
++ |
26627 |
++ holder = kdbus_hello_registrar(env->buspath, "foo.priv.activator", |
26628 |
++ access, 1, KDBUS_HELLO_POLICY_HOLDER); |
26629 |
++ ASSERT_RETURN(holder); |
26630 |
++ |
26631 |
++ /* Now we are able to TALK to the name */ |
26632 |
++ |
26633 |
++ cookie++; |
26634 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26635 |
++ /* Try to talk to the name */ |
26636 |
++ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26637 |
++ cookie, 0, 0, 0, |
26638 |
++ KDBUS_DST_ID_NAME); |
26639 |
++ ASSERT_EXIT(ret == 0); |
26640 |
++ })); |
26641 |
++ ASSERT_RETURN(ret >= 0); |
26642 |
++ |
26643 |
++ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26644 |
++ ASSERT_RETURN(ret == 0); |
26645 |
++ |
26646 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26647 |
++ ret = kdbus_name_acquire(unpriv, "foo.priv.activator", |
26648 |
++ &flags); |
26649 |
++ ASSERT_RETURN(ret == -EPERM); |
26650 |
++ })); |
26651 |
++ ASSERT_RETURN(ret >= 0); |
26652 |
++ |
26653 |
++ kdbus_conn_free(service); |
26654 |
++ kdbus_conn_free(client); |
26655 |
++ kdbus_conn_free(holder); |
26656 |
++ |
26657 |
++ return 0; |
26658 |
++} |
26659 |
++ |
26660 |
++int kdbus_test_activator(struct kdbus_test_env *env) |
26661 |
++{ |
26662 |
++ int ret; |
26663 |
++ struct kdbus_conn *activator; |
26664 |
++ struct pollfd fds[2]; |
26665 |
++ bool activator_done = false; |
26666 |
++ struct kdbus_policy_access access[2]; |
26667 |
++ |
26668 |
++ access[0].type = KDBUS_POLICY_ACCESS_USER; |
26669 |
++ access[0].id = getuid(); |
26670 |
++ access[0].access = KDBUS_POLICY_OWN; |
26671 |
++ |
26672 |
++ access[1].type = KDBUS_POLICY_ACCESS_WORLD; |
26673 |
++ access[1].access = KDBUS_POLICY_TALK; |
26674 |
++ |
26675 |
++ activator = kdbus_hello_activator(env->buspath, "foo.test.activator", |
26676 |
++ access, 2); |
26677 |
++ ASSERT_RETURN(activator); |
26678 |
++ |
26679 |
++ ret = kdbus_add_match_empty(env->conn); |
26680 |
++ ASSERT_RETURN(ret == 0); |
26681 |
++ |
26682 |
++ ret = kdbus_list(env->conn, KDBUS_LIST_NAMES | |
26683 |
++ KDBUS_LIST_UNIQUE | |
26684 |
++ KDBUS_LIST_ACTIVATORS | |
26685 |
++ KDBUS_LIST_QUEUED); |
26686 |
++ ASSERT_RETURN(ret == 0); |
26687 |
++ |
26688 |
++ ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef, |
26689 |
++ 0, 0, 0, KDBUS_DST_ID_NAME); |
26690 |
++ ASSERT_RETURN(ret == 0); |
26691 |
++ |
26692 |
++ fds[0].fd = activator->fd; |
26693 |
++ fds[1].fd = env->conn->fd; |
26694 |
++ |
26695 |
++ kdbus_printf("-- entering poll loop ...\n"); |
26696 |
++ |
26697 |
++ for (;;) { |
26698 |
++ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
26699 |
++ |
26700 |
++ for (i = 0; i < nfds; i++) { |
26701 |
++ fds[i].events = POLLIN | POLLPRI; |
26702 |
++ fds[i].revents = 0; |
26703 |
++ } |
26704 |
++ |
26705 |
++ ret = poll(fds, nfds, 3000); |
26706 |
++ ASSERT_RETURN(ret >= 0); |
26707 |
++ |
26708 |
++ ret = kdbus_list(env->conn, KDBUS_LIST_NAMES); |
26709 |
++ ASSERT_RETURN(ret == 0); |
26710 |
++ |
26711 |
++ if ((fds[0].revents & POLLIN) && !activator_done) { |
26712 |
++ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
26713 |
++ |
26714 |
++ kdbus_printf("Starter was called back!\n"); |
26715 |
++ |
26716 |
++ ret = kdbus_name_acquire(env->conn, |
26717 |
++ "foo.test.activator", &flags); |
26718 |
++ ASSERT_RETURN(ret == 0); |
26719 |
++ |
26720 |
++ activator_done = true; |
26721 |
++ } |
26722 |
++ |
26723 |
++ if (fds[1].revents & POLLIN) { |
26724 |
++ kdbus_msg_recv(env->conn, NULL, NULL); |
26725 |
++ break; |
26726 |
++ } |
26727 |
++ } |
26728 |
++ |
26729 |
++ /* Check if all uids/gids are mapped */ |
26730 |
++ if (!all_uids_gids_are_mapped()) |
26731 |
++ return TEST_SKIP; |
26732 |
++ |
26733 |
++ /* Check now capabilities, so we run the previous tests */ |
26734 |
++ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
26735 |
++ ASSERT_RETURN(ret >= 0); |
26736 |
++ |
26737 |
++ if (!ret) |
26738 |
++ return TEST_SKIP; |
26739 |
++ |
26740 |
++ ret = kdbus_priv_activator(env); |
26741 |
++ ASSERT_RETURN(ret == 0); |
26742 |
++ |
26743 |
++ kdbus_conn_free(activator); |
26744 |
++ |
26745 |
++ return TEST_OK; |
26746 |
++} |
26747 |
+diff --git a/tools/testing/selftests/kdbus/test-attach-flags.c b/tools/testing/selftests/kdbus/test-attach-flags.c |
26748 |
+new file mode 100644 |
26749 |
+index 0000000..deee7c3 |
26750 |
+--- /dev/null |
26751 |
++++ b/tools/testing/selftests/kdbus/test-attach-flags.c |
26752 |
+@@ -0,0 +1,750 @@ |
26753 |
++#include <stdio.h> |
26754 |
++#include <string.h> |
26755 |
++#include <stdlib.h> |
26756 |
++#include <stdbool.h> |
26757 |
++#include <stddef.h> |
26758 |
++#include <fcntl.h> |
26759 |
++#include <unistd.h> |
26760 |
++#include <stdint.h> |
26761 |
++#include <errno.h> |
26762 |
++#include <assert.h> |
26763 |
++#include <sys/capability.h> |
26764 |
++#include <sys/mman.h> |
26765 |
++#include <sys/stat.h> |
26766 |
++#include <sys/types.h> |
26767 |
++#include <linux/unistd.h> |
26768 |
++ |
26769 |
++#include "kdbus-api.h" |
26770 |
++#include "kdbus-test.h" |
26771 |
++#include "kdbus-util.h" |
26772 |
++#include "kdbus-enum.h" |
26773 |
++ |
26774 |
++/* |
26775 |
++ * Should be the sum of the currently supported and compiled-in |
26776 |
++ * KDBUS_ITEMS_* that reflect KDBUS_ATTACH_* flags. |
26777 |
++ */ |
26778 |
++static unsigned int KDBUS_TEST_ITEMS_SUM = KDBUS_ATTACH_ITEMS_TYPE_SUM; |
26779 |
++ |
26780 |
++static struct kdbus_conn *__kdbus_hello(const char *path, uint64_t flags, |
26781 |
++ uint64_t attach_flags_send, |
26782 |
++ uint64_t attach_flags_recv) |
26783 |
++{ |
26784 |
++ struct kdbus_cmd_free cmd_free = {}; |
26785 |
++ int ret, fd; |
26786 |
++ struct kdbus_conn *conn; |
26787 |
++ struct { |
26788 |
++ struct kdbus_cmd_hello hello; |
26789 |
++ |
26790 |
++ struct { |
26791 |
++ uint64_t size; |
26792 |
++ uint64_t type; |
26793 |
++ char str[16]; |
26794 |
++ } conn_name; |
26795 |
++ |
26796 |
++ uint8_t extra_items[0]; |
26797 |
++ } h; |
26798 |
++ |
26799 |
++ memset(&h, 0, sizeof(h)); |
26800 |
++ |
26801 |
++ kdbus_printf("-- opening bus connection %s\n", path); |
26802 |
++ fd = open(path, O_RDWR|O_CLOEXEC); |
26803 |
++ if (fd < 0) { |
26804 |
++ kdbus_printf("--- error %d (%m)\n", fd); |
26805 |
++ return NULL; |
26806 |
++ } |
26807 |
++ |
26808 |
++ h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD; |
26809 |
++ h.hello.attach_flags_send = attach_flags_send; |
26810 |
++ h.hello.attach_flags_recv = attach_flags_recv; |
26811 |
++ h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION; |
26812 |
++ strcpy(h.conn_name.str, "this-is-my-name"); |
26813 |
++ h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1; |
26814 |
++ |
26815 |
++ h.hello.size = sizeof(h); |
26816 |
++ h.hello.pool_size = POOL_SIZE; |
26817 |
++ |
26818 |
++ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello); |
26819 |
++ if (ret < 0) { |
26820 |
++ kdbus_printf("--- error when saying hello: %d (%m)\n", ret); |
26821 |
++ return NULL; |
26822 |
++ } |
26823 |
++ |
26824 |
++ kdbus_printf("-- New connection ID : %llu\n", |
26825 |
++ (unsigned long long)h.hello.id); |
26826 |
++ |
26827 |
++ cmd_free.size = sizeof(cmd_free); |
26828 |
++ cmd_free.offset = h.hello.offset; |
26829 |
++ ret = kdbus_cmd_free(fd, &cmd_free); |
26830 |
++ if (ret < 0) |
26831 |
++ return NULL; |
26832 |
++ |
26833 |
++ conn = malloc(sizeof(*conn)); |
26834 |
++ if (!conn) { |
26835 |
++ kdbus_printf("unable to malloc()!?\n"); |
26836 |
++ return NULL; |
26837 |
++ } |
26838 |
++ |
26839 |
++ conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
26840 |
++ if (conn->buf == MAP_FAILED) { |
26841 |
++ ret = -errno; |
26842 |
++ free(conn); |
26843 |
++ close(fd); |
26844 |
++ kdbus_printf("--- error mmap: %d (%m)\n", ret); |
26845 |
++ return NULL; |
26846 |
++ } |
26847 |
++ |
26848 |
++ conn->fd = fd; |
26849 |
++ conn->id = h.hello.id; |
26850 |
++ return conn; |
26851 |
++} |
26852 |
++ |
26853 |
++static int kdbus_test_peers_creation(struct kdbus_test_env *env) |
26854 |
++{ |
26855 |
++ int ret; |
26856 |
++ int control_fd; |
26857 |
++ char *path; |
26858 |
++ char *busname; |
26859 |
++ char buspath[2048]; |
26860 |
++ char control_path[2048]; |
26861 |
++ uint64_t attach_flags_mask; |
26862 |
++ struct kdbus_conn *conn; |
26863 |
++ |
26864 |
++ snprintf(control_path, sizeof(control_path), |
26865 |
++ "%s/control", env->root); |
26866 |
++ |
26867 |
++ /* |
26868 |
++ * Set kdbus system-wide mask to 0, this has nothing |
26869 |
++ * to do with the following tests, bus and connection |
26870 |
++ * creation nor connection update, but we do it so we are |
26871 |
++ * sure that everything work as expected |
26872 |
++ */ |
26873 |
++ |
26874 |
++ attach_flags_mask = 0; |
26875 |
++ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
26876 |
++ attach_flags_mask); |
26877 |
++ ASSERT_RETURN(ret == 0); |
26878 |
++ |
26879 |
++ |
26880 |
++ /* |
26881 |
++ * Create bus with a full set of ATTACH flags |
26882 |
++ */ |
26883 |
++ |
26884 |
++ control_fd = open(control_path, O_RDWR); |
26885 |
++ ASSERT_RETURN(control_fd >= 0); |
26886 |
++ |
26887 |
++ busname = unique_name("test-peers-creation-bus"); |
26888 |
++ ASSERT_RETURN(busname); |
26889 |
++ |
26890 |
++ ret = kdbus_create_bus(control_fd, busname, _KDBUS_ATTACH_ALL, |
26891 |
++ 0, &path); |
26892 |
++ ASSERT_RETURN(ret == 0); |
26893 |
++ |
26894 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
26895 |
++ |
26896 |
++ /* |
26897 |
++ * Create a connection with an empty send attach flags, or |
26898 |
++ * with just KDBUS_ATTACH_CREDS, this should fail |
26899 |
++ */ |
26900 |
++ conn = __kdbus_hello(buspath, 0, 0, 0); |
26901 |
++ ASSERT_RETURN(conn == NULL); |
26902 |
++ ASSERT_RETURN(errno == ECONNREFUSED); |
26903 |
++ |
26904 |
++ conn = __kdbus_hello(buspath, 0, KDBUS_ATTACH_CREDS, |
26905 |
++ _KDBUS_ATTACH_ALL); |
26906 |
++ ASSERT_RETURN(conn == NULL); |
26907 |
++ ASSERT_RETURN(errno == ECONNREFUSED); |
26908 |
++ |
26909 |
++ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0); |
26910 |
++ ASSERT_RETURN(conn); |
26911 |
++ |
26912 |
++ /* Try to cut back some send attach flags */ |
26913 |
++ ret = kdbus_conn_update_attach_flags(conn, |
26914 |
++ KDBUS_ATTACH_CREDS| |
26915 |
++ KDBUS_ATTACH_PIDS, |
26916 |
++ _KDBUS_ATTACH_ALL); |
26917 |
++ ASSERT_RETURN(ret == -EINVAL); |
26918 |
++ |
26919 |
++ ret = kdbus_conn_update_attach_flags(conn, |
26920 |
++ _KDBUS_ATTACH_ALL, 0); |
26921 |
++ ASSERT_RETURN(ret == 0); |
26922 |
++ |
26923 |
++ kdbus_conn_free(conn); |
26924 |
++ free(path); |
26925 |
++ free(busname); |
26926 |
++ close(control_fd); |
26927 |
++ |
26928 |
++ |
26929 |
++ /* Test a new bus with KDBUS_ATTACH_PIDS */ |
26930 |
++ |
26931 |
++ control_fd = open(control_path, O_RDWR); |
26932 |
++ ASSERT_RETURN(control_fd >= 0); |
26933 |
++ |
26934 |
++ busname = unique_name("test-peer-flags-bus"); |
26935 |
++ ASSERT_RETURN(busname); |
26936 |
++ |
26937 |
++ ret = kdbus_create_bus(control_fd, busname, KDBUS_ATTACH_PIDS, |
26938 |
++ 0, &path); |
26939 |
++ ASSERT_RETURN(ret == 0); |
26940 |
++ |
26941 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
26942 |
++ |
26943 |
++ /* |
26944 |
++ * Create a connection with an empty send attach flags, or |
26945 |
++ * all flags except KDBUS_ATTACH_PIDS |
26946 |
++ */ |
26947 |
++ conn = __kdbus_hello(buspath, 0, 0, 0); |
26948 |
++ ASSERT_RETURN(conn == NULL); |
26949 |
++ ASSERT_RETURN(errno == ECONNREFUSED); |
26950 |
++ |
26951 |
++ conn = __kdbus_hello(buspath, 0, |
26952 |
++ _KDBUS_ATTACH_ALL & ~KDBUS_ATTACH_PIDS, |
26953 |
++ _KDBUS_ATTACH_ALL); |
26954 |
++ ASSERT_RETURN(conn == NULL); |
26955 |
++ ASSERT_RETURN(errno == ECONNREFUSED); |
26956 |
++ |
26957 |
++ /* The following should succeed */ |
26958 |
++ conn = __kdbus_hello(buspath, 0, KDBUS_ATTACH_PIDS, 0); |
26959 |
++ ASSERT_RETURN(conn); |
26960 |
++ kdbus_conn_free(conn); |
26961 |
++ |
26962 |
++ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0); |
26963 |
++ ASSERT_RETURN(conn); |
26964 |
++ |
26965 |
++ ret = kdbus_conn_update_attach_flags(conn, |
26966 |
++ _KDBUS_ATTACH_ALL & |
26967 |
++ ~KDBUS_ATTACH_PIDS, |
26968 |
++ _KDBUS_ATTACH_ALL); |
26969 |
++ ASSERT_RETURN(ret == -EINVAL); |
26970 |
++ |
26971 |
++ ret = kdbus_conn_update_attach_flags(conn, 0, |
26972 |
++ _KDBUS_ATTACH_ALL); |
26973 |
++ ASSERT_RETURN(ret == -EINVAL); |
26974 |
++ |
26975 |
++ /* Now we want only KDBUS_ATTACH_PIDS */ |
26976 |
++ ret = kdbus_conn_update_attach_flags(conn, |
26977 |
++ KDBUS_ATTACH_PIDS, 0); |
26978 |
++ ASSERT_RETURN(ret == 0); |
26979 |
++ |
26980 |
++ kdbus_conn_free(conn); |
26981 |
++ free(path); |
26982 |
++ free(busname); |
26983 |
++ close(control_fd); |
26984 |
++ |
26985 |
++ |
26986 |
++ /* |
26987 |
++ * Create bus with 0 as ATTACH flags, the bus does not |
26988 |
++ * require any attach flags |
26989 |
++ */ |
26990 |
++ |
26991 |
++ control_fd = open(control_path, O_RDWR); |
26992 |
++ ASSERT_RETURN(control_fd >= 0); |
26993 |
++ |
26994 |
++ busname = unique_name("test-peer-flags-bus"); |
26995 |
++ ASSERT_RETURN(busname); |
26996 |
++ |
26997 |
++ ret = kdbus_create_bus(control_fd, busname, 0, 0, &path); |
26998 |
++ ASSERT_RETURN(ret == 0); |
26999 |
++ |
27000 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
27001 |
++ |
27002 |
++ /* Bus is open it does not require any send attach flags */ |
27003 |
++ conn = __kdbus_hello(buspath, 0, 0, 0); |
27004 |
++ ASSERT_RETURN(conn); |
27005 |
++ kdbus_conn_free(conn); |
27006 |
++ |
27007 |
++ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0); |
27008 |
++ ASSERT_RETURN(conn); |
27009 |
++ |
27010 |
++ ret = kdbus_conn_update_attach_flags(conn, 0, 0); |
27011 |
++ ASSERT_RETURN(ret == 0); |
27012 |
++ |
27013 |
++ ret = kdbus_conn_update_attach_flags(conn, KDBUS_ATTACH_CREDS, 0); |
27014 |
++ ASSERT_RETURN(ret == 0); |
27015 |
++ |
27016 |
++ kdbus_conn_free(conn); |
27017 |
++ free(path); |
27018 |
++ free(busname); |
27019 |
++ close(control_fd); |
27020 |
++ |
27021 |
++ return 0; |
27022 |
++} |
27023 |
++ |
27024 |
++static int kdbus_test_peers_info(struct kdbus_test_env *env) |
27025 |
++{ |
27026 |
++ int ret; |
27027 |
++ int control_fd; |
27028 |
++ char *path; |
27029 |
++ char *busname; |
27030 |
++ unsigned int i = 0; |
27031 |
++ uint64_t offset = 0; |
27032 |
++ char buspath[2048]; |
27033 |
++ char control_path[2048]; |
27034 |
++ uint64_t attach_flags_mask; |
27035 |
++ struct kdbus_item *item; |
27036 |
++ struct kdbus_info *info; |
27037 |
++ struct kdbus_conn *conn; |
27038 |
++ struct kdbus_conn *reader; |
27039 |
++ unsigned long long attach_count = 0; |
27040 |
++ |
27041 |
++ snprintf(control_path, sizeof(control_path), |
27042 |
++ "%s/control", env->root); |
27043 |
++ |
27044 |
++ attach_flags_mask = 0; |
27045 |
++ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
27046 |
++ attach_flags_mask); |
27047 |
++ ASSERT_RETURN(ret == 0); |
27048 |
++ |
27049 |
++ control_fd = open(control_path, O_RDWR); |
27050 |
++ ASSERT_RETURN(control_fd >= 0); |
27051 |
++ |
27052 |
++ busname = unique_name("test-peers-info-bus"); |
27053 |
++ ASSERT_RETURN(busname); |
27054 |
++ |
27055 |
++ ret = kdbus_create_bus(control_fd, busname, _KDBUS_ATTACH_ALL, |
27056 |
++ 0, &path); |
27057 |
++ ASSERT_RETURN(ret == 0); |
27058 |
++ |
27059 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
27060 |
++ |
27061 |
++ /* Create connections with the appropriate flags */ |
27062 |
++ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0); |
27063 |
++ ASSERT_RETURN(conn); |
27064 |
++ |
27065 |
++ reader = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0); |
27066 |
++ ASSERT_RETURN(reader); |
27067 |
++ |
27068 |
++ ret = kdbus_conn_info(reader, conn->id, NULL, |
27069 |
++ _KDBUS_ATTACH_ALL, &offset); |
27070 |
++ ASSERT_RETURN(ret == 0); |
27071 |
++ |
27072 |
++ info = (struct kdbus_info *)(reader->buf + offset); |
27073 |
++ ASSERT_RETURN(info->id == conn->id); |
27074 |
++ |
27075 |
++ /* all attach flags are masked, no metadata */ |
27076 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
27077 |
++ i++; |
27078 |
++ |
27079 |
++ ASSERT_RETURN(i == 0); |
27080 |
++ |
27081 |
++ kdbus_free(reader, offset); |
27082 |
++ |
27083 |
++ /* Set the mask to _KDBUS_ATTACH_ANY */ |
27084 |
++ attach_flags_mask = _KDBUS_ATTACH_ANY; |
27085 |
++ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
27086 |
++ attach_flags_mask); |
27087 |
++ ASSERT_RETURN(ret == 0); |
27088 |
++ |
27089 |
++ ret = kdbus_conn_info(reader, conn->id, NULL, |
27090 |
++ _KDBUS_ATTACH_ALL, &offset); |
27091 |
++ ASSERT_RETURN(ret == 0); |
27092 |
++ |
27093 |
++ info = (struct kdbus_info *)(reader->buf + offset); |
27094 |
++ ASSERT_RETURN(info->id == conn->id); |
27095 |
++ |
27096 |
++ attach_count = 0; |
27097 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
27098 |
++ attach_count += item->type; |
27099 |
++ |
27100 |
++ /* |
27101 |
++ * All flags have been returned except for: |
27102 |
++ * KDBUS_ITEM_TIMESTAMP and |
27103 |
++ * KDBUS_ITEM_OWNED_NAME we do not own any name. |
27104 |
++ */ |
27105 |
++ ASSERT_RETURN(attach_count == (KDBUS_TEST_ITEMS_SUM - |
27106 |
++ KDBUS_ITEM_OWNED_NAME - |
27107 |
++ KDBUS_ITEM_TIMESTAMP)); |
27108 |
++ |
27109 |
++ kdbus_free(reader, offset); |
27110 |
++ |
27111 |
++ /* Request only OWNED names */ |
27112 |
++ ret = kdbus_conn_info(reader, conn->id, NULL, |
27113 |
++ KDBUS_ATTACH_NAMES, &offset); |
27114 |
++ ASSERT_RETURN(ret == 0); |
27115 |
++ |
27116 |
++ info = (struct kdbus_info *)(reader->buf + offset); |
27117 |
++ ASSERT_RETURN(info->id == conn->id); |
27118 |
++ |
27119 |
++ attach_count = 0; |
27120 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
27121 |
++ attach_count += item->type; |
27122 |
++ |
27123 |
++ /* we should not get any metadata since we do not own names */ |
27124 |
++ ASSERT_RETURN(attach_count == 0); |
27125 |
++ |
27126 |
++ kdbus_free(reader, offset); |
27127 |
++ |
27128 |
++ kdbus_conn_free(conn); |
27129 |
++ kdbus_conn_free(reader); |
27130 |
++ |
27131 |
++ return 0; |
27132 |
++} |
27133 |
++ |
27134 |
++/** |
27135 |
++ * @kdbus_mask_param: kdbus module mask parameter (system-wide) |
27136 |
++ * @requested_meta: The bus owner metadata that we want |
27137 |
++ * @expected_items: The returned KDBUS_ITEMS_* sum. Used to |
27138 |
++ * validate the returned metadata items |
27139 |
++ */ |
27140 |
++static int kdbus_cmp_bus_creator_metadata(struct kdbus_test_env *env, |
27141 |
++ struct kdbus_conn *conn, |
27142 |
++ uint64_t kdbus_mask_param, |
27143 |
++ uint64_t requested_meta, |
27144 |
++ unsigned long expected_items) |
27145 |
++{ |
27146 |
++ int ret; |
27147 |
++ uint64_t offset = 0; |
27148 |
++ struct kdbus_info *info; |
27149 |
++ struct kdbus_item *item; |
27150 |
++ unsigned long attach_count = 0; |
27151 |
++ |
27152 |
++ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
27153 |
++ kdbus_mask_param); |
27154 |
++ ASSERT_RETURN(ret == 0); |
27155 |
++ |
27156 |
++ ret = kdbus_bus_creator_info(conn, requested_meta, &offset); |
27157 |
++ ASSERT_RETURN(ret == 0); |
27158 |
++ |
27159 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
27160 |
++ |
27161 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
27162 |
++ attach_count += item->type; |
27163 |
++ |
27164 |
++ ASSERT_RETURN(attach_count == expected_items); |
27165 |
++ |
27166 |
++ ret = kdbus_free(conn, offset); |
27167 |
++ ASSERT_RETURN(ret == 0); |
27168 |
++ |
27169 |
++ return 0; |
27170 |
++} |
27171 |
++ |
27172 |
++static int kdbus_test_bus_creator_info(struct kdbus_test_env *env) |
27173 |
++{ |
27174 |
++ int ret; |
27175 |
++ int control_fd; |
27176 |
++ char *path; |
27177 |
++ char *busname; |
27178 |
++ char buspath[2048]; |
27179 |
++ char control_path[2048]; |
27180 |
++ uint64_t attach_flags_mask; |
27181 |
++ struct kdbus_conn *conn; |
27182 |
++ unsigned long expected_items = 0; |
27183 |
++ |
27184 |
++ snprintf(control_path, sizeof(control_path), |
27185 |
++ "%s/control", env->root); |
27186 |
++ |
27187 |
++ control_fd = open(control_path, O_RDWR); |
27188 |
++ ASSERT_RETURN(control_fd >= 0); |
27189 |
++ |
27190 |
++ busname = unique_name("test-peers-info-bus"); |
27191 |
++ ASSERT_RETURN(busname); |
27192 |
++ |
27193 |
++ /* |
27194 |
++ * Now the bus allows us to see all its KDBUS_ATTACH_* |
27195 |
++ * items |
27196 |
++ */ |
27197 |
++ ret = kdbus_create_bus(control_fd, busname, 0, |
27198 |
++ _KDBUS_ATTACH_ALL, &path); |
27199 |
++ ASSERT_RETURN(ret == 0); |
27200 |
++ |
27201 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
27202 |
++ |
27203 |
++ conn = __kdbus_hello(buspath, 0, 0, 0); |
27204 |
++ ASSERT_RETURN(conn); |
27205 |
++ |
27206 |
++ /* |
27207 |
++ * Start with a kdbus module mask set to _KDBUS_ATTACH_ANY |
27208 |
++ */ |
27209 |
++ attach_flags_mask = _KDBUS_ATTACH_ANY; |
27210 |
++ |
27211 |
++ /* |
27212 |
++ * All flags will be returned except for: |
27213 |
++ * KDBUS_ITEM_TIMESTAMP |
27214 |
++ * KDBUS_ITEM_OWNED_NAME |
27215 |
++ * KDBUS_ITEM_CONN_DESCRIPTION |
27216 |
++ * |
27217 |
++ * An extra flags is always returned KDBUS_ITEM_MAKE_NAME |
27218 |
++ * which contains the bus name |
27219 |
++ */ |
27220 |
++ expected_items = KDBUS_TEST_ITEMS_SUM + KDBUS_ITEM_MAKE_NAME; |
27221 |
++ expected_items -= KDBUS_ITEM_TIMESTAMP + |
27222 |
++ KDBUS_ITEM_OWNED_NAME + |
27223 |
++ KDBUS_ITEM_CONN_DESCRIPTION; |
27224 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27225 |
++ attach_flags_mask, |
27226 |
++ _KDBUS_ATTACH_ALL, |
27227 |
++ expected_items); |
27228 |
++ ASSERT_RETURN(ret == 0); |
27229 |
++ |
27230 |
++ /* |
27231 |
++ * We should have: |
27232 |
++ * KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS + KDBUS_ITEM_MAKE_NAME |
27233 |
++ */ |
27234 |
++ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS + |
27235 |
++ KDBUS_ITEM_MAKE_NAME; |
27236 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27237 |
++ attach_flags_mask, |
27238 |
++ KDBUS_ATTACH_PIDS | |
27239 |
++ KDBUS_ATTACH_CREDS, |
27240 |
++ expected_items); |
27241 |
++ ASSERT_RETURN(ret == 0); |
27242 |
++ |
27243 |
++ /* KDBUS_ITEM_MAKE_NAME is always returned */ |
27244 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27245 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27246 |
++ attach_flags_mask, |
27247 |
++ 0, expected_items); |
27248 |
++ ASSERT_RETURN(ret == 0); |
27249 |
++ |
27250 |
++ /* |
27251 |
++ * Restrict kdbus system-wide mask to KDBUS_ATTACH_PIDS |
27252 |
++ */ |
27253 |
++ |
27254 |
++ attach_flags_mask = KDBUS_ATTACH_PIDS; |
27255 |
++ |
27256 |
++ /* |
27257 |
++ * We should have: |
27258 |
++ * KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME |
27259 |
++ */ |
27260 |
++ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME; |
27261 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27262 |
++ attach_flags_mask, |
27263 |
++ _KDBUS_ATTACH_ALL, |
27264 |
++ expected_items); |
27265 |
++ ASSERT_RETURN(ret == 0); |
27266 |
++ |
27267 |
++ |
27268 |
++ /* system-wide mask to 0 */ |
27269 |
++ attach_flags_mask = 0; |
27270 |
++ |
27271 |
++ /* we should only see: KDBUS_ITEM_MAKE_NAME */ |
27272 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27273 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27274 |
++ attach_flags_mask, |
27275 |
++ _KDBUS_ATTACH_ALL, |
27276 |
++ expected_items); |
27277 |
++ ASSERT_RETURN(ret == 0); |
27278 |
++ |
27279 |
++ kdbus_conn_free(conn); |
27280 |
++ free(path); |
27281 |
++ free(busname); |
27282 |
++ close(control_fd); |
27283 |
++ |
27284 |
++ |
27285 |
++ /* |
27286 |
++ * A new bus that hides all its owner metadata |
27287 |
++ */ |
27288 |
++ |
27289 |
++ control_fd = open(control_path, O_RDWR); |
27290 |
++ ASSERT_RETURN(control_fd >= 0); |
27291 |
++ |
27292 |
++ busname = unique_name("test-peers-info-bus"); |
27293 |
++ ASSERT_RETURN(busname); |
27294 |
++ |
27295 |
++ ret = kdbus_create_bus(control_fd, busname, 0, 0, &path); |
27296 |
++ ASSERT_RETURN(ret == 0); |
27297 |
++ |
27298 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
27299 |
++ |
27300 |
++ conn = __kdbus_hello(buspath, 0, 0, 0); |
27301 |
++ ASSERT_RETURN(conn); |
27302 |
++ |
27303 |
++ /* |
27304 |
++ * Start with a kdbus module mask set to _KDBUS_ATTACH_ANY |
27305 |
++ */ |
27306 |
++ attach_flags_mask = _KDBUS_ATTACH_ANY; |
27307 |
++ |
27308 |
++ /* |
27309 |
++ * We only get the KDBUS_ITEM_MAKE_NAME |
27310 |
++ */ |
27311 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27312 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27313 |
++ attach_flags_mask, |
27314 |
++ _KDBUS_ATTACH_ALL, |
27315 |
++ expected_items); |
27316 |
++ ASSERT_RETURN(ret == 0); |
27317 |
++ |
27318 |
++ /* |
27319 |
++ * We still get only kdbus_ITEM_MAKE_NAME |
27320 |
++ */ |
27321 |
++ attach_flags_mask = 0; |
27322 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27323 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27324 |
++ attach_flags_mask, |
27325 |
++ _KDBUS_ATTACH_ALL, |
27326 |
++ expected_items); |
27327 |
++ ASSERT_RETURN(ret == 0); |
27328 |
++ |
27329 |
++ kdbus_conn_free(conn); |
27330 |
++ free(path); |
27331 |
++ free(busname); |
27332 |
++ close(control_fd); |
27333 |
++ |
27334 |
++ |
27335 |
++ /* |
27336 |
++ * A new bus that shows only the PID and CREDS metadata |
27337 |
++ * of the bus owner. |
27338 |
++ */ |
27339 |
++ control_fd = open(control_path, O_RDWR); |
27340 |
++ ASSERT_RETURN(control_fd >= 0); |
27341 |
++ |
27342 |
++ busname = unique_name("test-peers-info-bus"); |
27343 |
++ ASSERT_RETURN(busname); |
27344 |
++ |
27345 |
++ ret = kdbus_create_bus(control_fd, busname, 0, |
27346 |
++ KDBUS_ATTACH_PIDS| |
27347 |
++ KDBUS_ATTACH_CREDS, &path); |
27348 |
++ ASSERT_RETURN(ret == 0); |
27349 |
++ |
27350 |
++ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path); |
27351 |
++ |
27352 |
++ conn = __kdbus_hello(buspath, 0, 0, 0); |
27353 |
++ ASSERT_RETURN(conn); |
27354 |
++ |
27355 |
++ /* |
27356 |
++ * Start with a kdbus module mask set to _KDBUS_ATTACH_ANY |
27357 |
++ */ |
27358 |
++ attach_flags_mask = _KDBUS_ATTACH_ANY; |
27359 |
++ |
27360 |
++ /* |
27361 |
++ * We should have: |
27362 |
++ * KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS + KDBUS_ITEM_MAKE_NAME |
27363 |
++ */ |
27364 |
++ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS + |
27365 |
++ KDBUS_ITEM_MAKE_NAME; |
27366 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27367 |
++ attach_flags_mask, |
27368 |
++ _KDBUS_ATTACH_ALL, |
27369 |
++ expected_items); |
27370 |
++ ASSERT_RETURN(ret == 0); |
27371 |
++ |
27372 |
++ expected_items = KDBUS_ITEM_CREDS + KDBUS_ITEM_MAKE_NAME; |
27373 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27374 |
++ attach_flags_mask, |
27375 |
++ KDBUS_ATTACH_CREDS, |
27376 |
++ expected_items); |
27377 |
++ ASSERT_RETURN(ret == 0); |
27378 |
++ |
27379 |
++ /* KDBUS_ITEM_MAKE_NAME is always returned */ |
27380 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27381 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27382 |
++ attach_flags_mask, |
27383 |
++ 0, expected_items); |
27384 |
++ ASSERT_RETURN(ret == 0); |
27385 |
++ |
27386 |
++ /* |
27387 |
++ * Restrict kdbus system-wide mask to KDBUS_ATTACH_PIDS |
27388 |
++ */ |
27389 |
++ |
27390 |
++ attach_flags_mask = KDBUS_ATTACH_PIDS; |
27391 |
++ /* |
27392 |
++ * We should have: |
27393 |
++ * KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME |
27394 |
++ */ |
27395 |
++ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME; |
27396 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27397 |
++ attach_flags_mask, |
27398 |
++ _KDBUS_ATTACH_ALL, |
27399 |
++ expected_items); |
27400 |
++ ASSERT_RETURN(ret == 0); |
27401 |
++ |
27402 |
++ /* No KDBUS_ATTACH_CREDS */ |
27403 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27404 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27405 |
++ attach_flags_mask, |
27406 |
++ KDBUS_ATTACH_CREDS, |
27407 |
++ expected_items); |
27408 |
++ ASSERT_RETURN(ret == 0); |
27409 |
++ |
27410 |
++ /* system-wide mask to 0 */ |
27411 |
++ attach_flags_mask = 0; |
27412 |
++ |
27413 |
++ /* we should only see: KDBUS_ITEM_MAKE_NAME */ |
27414 |
++ expected_items = KDBUS_ITEM_MAKE_NAME; |
27415 |
++ ret = kdbus_cmp_bus_creator_metadata(env, conn, |
27416 |
++ attach_flags_mask, |
27417 |
++ _KDBUS_ATTACH_ALL, |
27418 |
++ expected_items); |
27419 |
++ ASSERT_RETURN(ret == 0); |
27420 |
++ |
27421 |
++ |
27422 |
++ kdbus_conn_free(conn); |
27423 |
++ free(path); |
27424 |
++ free(busname); |
27425 |
++ close(control_fd); |
27426 |
++ |
27427 |
++ return 0; |
27428 |
++} |
27429 |
++ |
27430 |
++int kdbus_test_attach_flags(struct kdbus_test_env *env) |
27431 |
++{ |
27432 |
++ int ret; |
27433 |
++ uint64_t flags_mask; |
27434 |
++ uint64_t old_kdbus_flags_mask; |
27435 |
++ |
27436 |
++ /* We need CAP_DAC_OVERRIDE to overwrite the kdbus mask */ |
27437 |
++ ret = test_is_capable(CAP_DAC_OVERRIDE, -1); |
27438 |
++ ASSERT_RETURN(ret >= 0); |
27439 |
++ |
27440 |
++ /* no enough privileges, SKIP test */ |
27441 |
++ if (!ret) |
27442 |
++ return TEST_SKIP; |
27443 |
++ |
27444 |
++ /* |
27445 |
++ * We need to be able to write to |
27446 |
++ * "/sys/module/kdbus/parameters/attach_flags_mask" |
27447 |
++ * perhaps we are unprvileged/privileged in its userns |
27448 |
++ */ |
27449 |
++ ret = access(env->mask_param_path, W_OK); |
27450 |
++ if (ret < 0) { |
27451 |
++ kdbus_printf("--- access() '%s' failed: %d (%m)\n", |
27452 |
++ env->mask_param_path, -errno); |
27453 |
++ return TEST_SKIP; |
27454 |
++ } |
27455 |
++ |
27456 |
++ ret = kdbus_sysfs_get_parameter_mask(env->mask_param_path, |
27457 |
++ &old_kdbus_flags_mask); |
27458 |
++ ASSERT_RETURN(ret == 0); |
27459 |
++ |
27460 |
++ /* setup the right KDBUS_TEST_ITEMS_SUM */ |
27461 |
++ if (!config_auditsyscall_is_enabled()) |
27462 |
++ KDBUS_TEST_ITEMS_SUM -= KDBUS_ITEM_AUDIT; |
27463 |
++ |
27464 |
++ if (!config_cgroups_is_enabled()) |
27465 |
++ KDBUS_TEST_ITEMS_SUM -= KDBUS_ITEM_CGROUP; |
27466 |
++ |
27467 |
++ if (!config_security_is_enabled()) |
27468 |
++ KDBUS_TEST_ITEMS_SUM -= KDBUS_ITEM_SECLABEL; |
27469 |
++ |
27470 |
++ /* |
27471 |
++ * Test the connection creation attach flags |
27472 |
++ */ |
27473 |
++ ret = kdbus_test_peers_creation(env); |
27474 |
++ /* Restore previous kdbus mask */ |
27475 |
++ kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
27476 |
++ old_kdbus_flags_mask); |
27477 |
++ ASSERT_RETURN(ret == 0); |
27478 |
++ |
27479 |
++ /* |
27480 |
++ * Test the CONN_INFO attach flags |
27481 |
++ */ |
27482 |
++ ret = kdbus_test_peers_info(env); |
27483 |
++ /* Restore previous kdbus mask */ |
27484 |
++ kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
27485 |
++ old_kdbus_flags_mask); |
27486 |
++ ASSERT_RETURN(ret == 0); |
27487 |
++ |
27488 |
++ /* |
27489 |
++ * Test the Bus creator info and its attach flags |
27490 |
++ */ |
27491 |
++ ret = kdbus_test_bus_creator_info(env); |
27492 |
++ /* Restore previous kdbus mask */ |
27493 |
++ kdbus_sysfs_set_parameter_mask(env->mask_param_path, |
27494 |
++ old_kdbus_flags_mask); |
27495 |
++ ASSERT_RETURN(ret == 0); |
27496 |
++ |
27497 |
++ ret = kdbus_sysfs_get_parameter_mask(env->mask_param_path, |
27498 |
++ &flags_mask); |
27499 |
++ ASSERT_RETURN(ret == 0 && old_kdbus_flags_mask == flags_mask); |
27500 |
++ |
27501 |
++ return TEST_OK; |
27502 |
++} |
27503 |
+diff --git a/tools/testing/selftests/kdbus/test-benchmark.c b/tools/testing/selftests/kdbus/test-benchmark.c |
27504 |
+new file mode 100644 |
27505 |
+index 0000000..8a9744b |
27506 |
+--- /dev/null |
27507 |
++++ b/tools/testing/selftests/kdbus/test-benchmark.c |
27508 |
+@@ -0,0 +1,451 @@ |
27509 |
++#include <stdio.h> |
27510 |
++#include <string.h> |
27511 |
++#include <time.h> |
27512 |
++#include <fcntl.h> |
27513 |
++#include <locale.h> |
27514 |
++#include <stdlib.h> |
27515 |
++#include <stddef.h> |
27516 |
++#include <unistd.h> |
27517 |
++#include <stdint.h> |
27518 |
++#include <stdbool.h> |
27519 |
++#include <errno.h> |
27520 |
++#include <assert.h> |
27521 |
++#include <poll.h> |
27522 |
++#include <sys/time.h> |
27523 |
++#include <sys/mman.h> |
27524 |
++#include <sys/socket.h> |
27525 |
++#include <math.h> |
27526 |
++ |
27527 |
++#include "kdbus-api.h" |
27528 |
++#include "kdbus-test.h" |
27529 |
++#include "kdbus-util.h" |
27530 |
++#include "kdbus-enum.h" |
27531 |
++ |
27532 |
++#define SERVICE_NAME "foo.bar.echo" |
27533 |
++ |
27534 |
++/* |
27535 |
++ * To have a banchmark comparison with unix socket, set: |
27536 |
++ * user_memfd = false; |
27537 |
++ * compare_uds = true; |
27538 |
++ * attach_none = true; do not attached metadata |
27539 |
++ */ |
27540 |
++ |
27541 |
++static bool use_memfd = true; /* transmit memfd? */ |
27542 |
++static bool compare_uds = false; /* unix-socket comparison? */ |
27543 |
++static bool attach_none = false; /* clear attach-flags? */ |
27544 |
++static char stress_payload[8192]; |
27545 |
++ |
27546 |
++struct stats { |
27547 |
++ uint64_t count; |
27548 |
++ uint64_t latency_acc; |
27549 |
++ uint64_t latency_low; |
27550 |
++ uint64_t latency_high; |
27551 |
++ uint64_t latency_avg; |
27552 |
++ uint64_t latency_ssquares; |
27553 |
++}; |
27554 |
++ |
27555 |
++static struct stats stats; |
27556 |
++ |
27557 |
++static void reset_stats(void) |
27558 |
++{ |
27559 |
++ stats.count = 0; |
27560 |
++ stats.latency_acc = 0; |
27561 |
++ stats.latency_low = UINT64_MAX; |
27562 |
++ stats.latency_high = 0; |
27563 |
++ stats.latency_avg = 0; |
27564 |
++ stats.latency_ssquares = 0; |
27565 |
++} |
27566 |
++ |
27567 |
++static void dump_stats(bool is_uds) |
27568 |
++{ |
27569 |
++ if (stats.count > 0) { |
27570 |
++ kdbus_printf("stats %s: %'llu packets processed, latency (nsecs) min/max/avg/dev %'7llu // %'7llu // %'7llu // %'7.f\n", |
27571 |
++ is_uds ? " (UNIX)" : "(KDBUS)", |
27572 |
++ (unsigned long long) stats.count, |
27573 |
++ (unsigned long long) stats.latency_low, |
27574 |
++ (unsigned long long) stats.latency_high, |
27575 |
++ (unsigned long long) stats.latency_avg, |
27576 |
++ sqrt(stats.latency_ssquares / stats.count)); |
27577 |
++ } else { |
27578 |
++ kdbus_printf("*** no packets received. bus stuck?\n"); |
27579 |
++ } |
27580 |
++} |
27581 |
++ |
27582 |
++static void add_stats(uint64_t prev) |
27583 |
++{ |
27584 |
++ uint64_t diff, latency_avg_prev; |
27585 |
++ |
27586 |
++ diff = now(CLOCK_THREAD_CPUTIME_ID) - prev; |
27587 |
++ |
27588 |
++ stats.count++; |
27589 |
++ stats.latency_acc += diff; |
27590 |
++ |
27591 |
++ /* see Welford62 */ |
27592 |
++ latency_avg_prev = stats.latency_avg; |
27593 |
++ stats.latency_avg = stats.latency_acc / stats.count; |
27594 |
++ stats.latency_ssquares += (diff - latency_avg_prev) * (diff - stats.latency_avg); |
27595 |
++ |
27596 |
++ if (stats.latency_low > diff) |
27597 |
++ stats.latency_low = diff; |
27598 |
++ |
27599 |
++ if (stats.latency_high < diff) |
27600 |
++ stats.latency_high = diff; |
27601 |
++} |
27602 |
++ |
27603 |
++static int setup_simple_kdbus_msg(struct kdbus_conn *conn, |
27604 |
++ uint64_t dst_id, |
27605 |
++ struct kdbus_msg **msg_out) |
27606 |
++{ |
27607 |
++ struct kdbus_msg *msg; |
27608 |
++ struct kdbus_item *item; |
27609 |
++ uint64_t size; |
27610 |
++ |
27611 |
++ size = sizeof(struct kdbus_msg); |
27612 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
27613 |
++ |
27614 |
++ msg = malloc(size); |
27615 |
++ ASSERT_RETURN_VAL(msg, -ENOMEM); |
27616 |
++ |
27617 |
++ memset(msg, 0, size); |
27618 |
++ msg->size = size; |
27619 |
++ msg->src_id = conn->id; |
27620 |
++ msg->dst_id = dst_id; |
27621 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
27622 |
++ |
27623 |
++ item = msg->items; |
27624 |
++ |
27625 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
27626 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
27627 |
++ item->vec.address = (uintptr_t) stress_payload; |
27628 |
++ item->vec.size = sizeof(stress_payload); |
27629 |
++ item = KDBUS_ITEM_NEXT(item); |
27630 |
++ |
27631 |
++ *msg_out = msg; |
27632 |
++ |
27633 |
++ return 0; |
27634 |
++} |
27635 |
++ |
27636 |
++static int setup_memfd_kdbus_msg(struct kdbus_conn *conn, |
27637 |
++ uint64_t dst_id, |
27638 |
++ off_t *memfd_item_offset, |
27639 |
++ struct kdbus_msg **msg_out) |
27640 |
++{ |
27641 |
++ struct kdbus_msg *msg; |
27642 |
++ struct kdbus_item *item; |
27643 |
++ uint64_t size; |
27644 |
++ |
27645 |
++ size = sizeof(struct kdbus_msg); |
27646 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
27647 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
27648 |
++ |
27649 |
++ msg = malloc(size); |
27650 |
++ ASSERT_RETURN_VAL(msg, -ENOMEM); |
27651 |
++ |
27652 |
++ memset(msg, 0, size); |
27653 |
++ msg->size = size; |
27654 |
++ msg->src_id = conn->id; |
27655 |
++ msg->dst_id = dst_id; |
27656 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
27657 |
++ |
27658 |
++ item = msg->items; |
27659 |
++ |
27660 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
27661 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
27662 |
++ item->vec.address = (uintptr_t) stress_payload; |
27663 |
++ item->vec.size = sizeof(stress_payload); |
27664 |
++ item = KDBUS_ITEM_NEXT(item); |
27665 |
++ |
27666 |
++ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
27667 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd); |
27668 |
++ item->memfd.size = sizeof(uint64_t); |
27669 |
++ |
27670 |
++ *memfd_item_offset = (unsigned char *)item - (unsigned char *)msg; |
27671 |
++ *msg_out = msg; |
27672 |
++ |
27673 |
++ return 0; |
27674 |
++} |
27675 |
++ |
27676 |
++static int |
27677 |
++send_echo_request(struct kdbus_conn *conn, uint64_t dst_id, |
27678 |
++ void *kdbus_msg, off_t memfd_item_offset) |
27679 |
++{ |
27680 |
++ struct kdbus_cmd_send cmd = {}; |
27681 |
++ int memfd = -1; |
27682 |
++ int ret; |
27683 |
++ |
27684 |
++ if (use_memfd) { |
27685 |
++ uint64_t now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27686 |
++ struct kdbus_item *item = memfd_item_offset + kdbus_msg; |
27687 |
++ memfd = sys_memfd_create("memfd-name", 0); |
27688 |
++ ASSERT_RETURN_VAL(memfd >= 0, memfd); |
27689 |
++ |
27690 |
++ ret = write(memfd, &now_ns, sizeof(now_ns)); |
27691 |
++ ASSERT_RETURN_VAL(ret == sizeof(now_ns), -EAGAIN); |
27692 |
++ |
27693 |
++ ret = sys_memfd_seal_set(memfd); |
27694 |
++ ASSERT_RETURN_VAL(ret == 0, -errno); |
27695 |
++ |
27696 |
++ item->memfd.fd = memfd; |
27697 |
++ } |
27698 |
++ |
27699 |
++ cmd.size = sizeof(cmd); |
27700 |
++ cmd.msg_address = (uintptr_t)kdbus_msg; |
27701 |
++ |
27702 |
++ ret = kdbus_cmd_send(conn->fd, &cmd); |
27703 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
27704 |
++ |
27705 |
++ close(memfd); |
27706 |
++ |
27707 |
++ return 0; |
27708 |
++} |
27709 |
++ |
27710 |
++static int |
27711 |
++handle_echo_reply(struct kdbus_conn *conn, uint64_t send_ns) |
27712 |
++{ |
27713 |
++ int ret; |
27714 |
++ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
27715 |
++ struct kdbus_msg *msg; |
27716 |
++ const struct kdbus_item *item; |
27717 |
++ bool has_memfd = false; |
27718 |
++ |
27719 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
27720 |
++ if (ret == -EAGAIN) |
27721 |
++ return ret; |
27722 |
++ |
27723 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
27724 |
++ |
27725 |
++ if (!use_memfd) |
27726 |
++ goto out; |
27727 |
++ |
27728 |
++ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
27729 |
++ |
27730 |
++ KDBUS_ITEM_FOREACH(item, msg, items) { |
27731 |
++ switch (item->type) { |
27732 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
27733 |
++ char *buf; |
27734 |
++ |
27735 |
++ buf = mmap(NULL, item->memfd.size, PROT_READ, |
27736 |
++ MAP_PRIVATE, item->memfd.fd, 0); |
27737 |
++ ASSERT_RETURN_VAL(buf != MAP_FAILED, -EINVAL); |
27738 |
++ ASSERT_RETURN_VAL(item->memfd.size == sizeof(uint64_t), |
27739 |
++ -EINVAL); |
27740 |
++ |
27741 |
++ add_stats(*(uint64_t*)buf); |
27742 |
++ munmap(buf, item->memfd.size); |
27743 |
++ close(item->memfd.fd); |
27744 |
++ has_memfd = true; |
27745 |
++ break; |
27746 |
++ } |
27747 |
++ |
27748 |
++ case KDBUS_ITEM_PAYLOAD_OFF: |
27749 |
++ /* ignore */ |
27750 |
++ break; |
27751 |
++ } |
27752 |
++ } |
27753 |
++ |
27754 |
++out: |
27755 |
++ if (!has_memfd) |
27756 |
++ add_stats(send_ns); |
27757 |
++ |
27758 |
++ ret = kdbus_free(conn, recv.msg.offset); |
27759 |
++ ASSERT_RETURN_VAL(ret == 0, -errno); |
27760 |
++ |
27761 |
++ return 0; |
27762 |
++} |
27763 |
++ |
27764 |
++static int benchmark(struct kdbus_test_env *env) |
27765 |
++{ |
27766 |
++ static char buf[sizeof(stress_payload)]; |
27767 |
++ struct kdbus_msg *kdbus_msg = NULL; |
27768 |
++ off_t memfd_cached_offset = 0; |
27769 |
++ int ret; |
27770 |
++ struct kdbus_conn *conn_a, *conn_b; |
27771 |
++ struct pollfd fds[2]; |
27772 |
++ uint64_t start, send_ns, now_ns, diff; |
27773 |
++ unsigned int i; |
27774 |
++ int uds[2]; |
27775 |
++ |
27776 |
++ setlocale(LC_ALL, ""); |
27777 |
++ |
27778 |
++ for (i = 0; i < sizeof(stress_payload); i++) |
27779 |
++ stress_payload[i] = i; |
27780 |
++ |
27781 |
++ /* setup kdbus pair */ |
27782 |
++ |
27783 |
++ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
27784 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
27785 |
++ ASSERT_RETURN(conn_a && conn_b); |
27786 |
++ |
27787 |
++ ret = kdbus_add_match_empty(conn_a); |
27788 |
++ ASSERT_RETURN(ret == 0); |
27789 |
++ |
27790 |
++ ret = kdbus_add_match_empty(conn_b); |
27791 |
++ ASSERT_RETURN(ret == 0); |
27792 |
++ |
27793 |
++ ret = kdbus_name_acquire(conn_a, SERVICE_NAME, NULL); |
27794 |
++ ASSERT_RETURN(ret == 0); |
27795 |
++ |
27796 |
++ if (attach_none) { |
27797 |
++ ret = kdbus_conn_update_attach_flags(conn_a, |
27798 |
++ _KDBUS_ATTACH_ALL, |
27799 |
++ 0); |
27800 |
++ ASSERT_RETURN(ret == 0); |
27801 |
++ } |
27802 |
++ |
27803 |
++ /* setup UDS pair */ |
27804 |
++ |
27805 |
++ ret = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, uds); |
27806 |
++ ASSERT_RETURN(ret == 0); |
27807 |
++ |
27808 |
++ /* setup a kdbus msg now */ |
27809 |
++ if (use_memfd) { |
27810 |
++ ret = setup_memfd_kdbus_msg(conn_b, conn_a->id, |
27811 |
++ &memfd_cached_offset, |
27812 |
++ &kdbus_msg); |
27813 |
++ ASSERT_RETURN(ret == 0); |
27814 |
++ } else { |
27815 |
++ ret = setup_simple_kdbus_msg(conn_b, conn_a->id, &kdbus_msg); |
27816 |
++ ASSERT_RETURN(ret == 0); |
27817 |
++ } |
27818 |
++ |
27819 |
++ /* start benchmark */ |
27820 |
++ |
27821 |
++ kdbus_printf("-- entering poll loop ...\n"); |
27822 |
++ |
27823 |
++ do { |
27824 |
++ /* run kdbus benchmark */ |
27825 |
++ fds[0].fd = conn_a->fd; |
27826 |
++ fds[1].fd = conn_b->fd; |
27827 |
++ |
27828 |
++ /* cancel any pending message */ |
27829 |
++ handle_echo_reply(conn_a, 0); |
27830 |
++ |
27831 |
++ start = now(CLOCK_THREAD_CPUTIME_ID); |
27832 |
++ reset_stats(); |
27833 |
++ |
27834 |
++ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27835 |
++ ret = send_echo_request(conn_b, conn_a->id, |
27836 |
++ kdbus_msg, memfd_cached_offset); |
27837 |
++ ASSERT_RETURN(ret == 0); |
27838 |
++ |
27839 |
++ while (1) { |
27840 |
++ unsigned int nfds = sizeof(fds) / sizeof(fds[0]); |
27841 |
++ unsigned int i; |
27842 |
++ |
27843 |
++ for (i = 0; i < nfds; i++) { |
27844 |
++ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27845 |
++ fds[i].revents = 0; |
27846 |
++ } |
27847 |
++ |
27848 |
++ ret = poll(fds, nfds, 10); |
27849 |
++ if (ret < 0) |
27850 |
++ break; |
27851 |
++ |
27852 |
++ if (fds[0].revents & POLLIN) { |
27853 |
++ ret = handle_echo_reply(conn_a, send_ns); |
27854 |
++ ASSERT_RETURN(ret == 0); |
27855 |
++ |
27856 |
++ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27857 |
++ ret = send_echo_request(conn_b, conn_a->id, |
27858 |
++ kdbus_msg, |
27859 |
++ memfd_cached_offset); |
27860 |
++ ASSERT_RETURN(ret == 0); |
27861 |
++ } |
27862 |
++ |
27863 |
++ now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27864 |
++ diff = now_ns - start; |
27865 |
++ if (diff > 1000000000ULL) { |
27866 |
++ start = now_ns; |
27867 |
++ |
27868 |
++ dump_stats(false); |
27869 |
++ break; |
27870 |
++ } |
27871 |
++ } |
27872 |
++ |
27873 |
++ if (!compare_uds) |
27874 |
++ continue; |
27875 |
++ |
27876 |
++ /* run unix-socket benchmark as comparison */ |
27877 |
++ |
27878 |
++ fds[0].fd = uds[0]; |
27879 |
++ fds[1].fd = uds[1]; |
27880 |
++ |
27881 |
++ /* cancel any pendign message */ |
27882 |
++ read(uds[1], buf, sizeof(buf)); |
27883 |
++ |
27884 |
++ start = now(CLOCK_THREAD_CPUTIME_ID); |
27885 |
++ reset_stats(); |
27886 |
++ |
27887 |
++ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27888 |
++ ret = write(uds[0], stress_payload, sizeof(stress_payload)); |
27889 |
++ ASSERT_RETURN(ret == sizeof(stress_payload)); |
27890 |
++ |
27891 |
++ while (1) { |
27892 |
++ unsigned int nfds = sizeof(fds) / sizeof(fds[0]); |
27893 |
++ unsigned int i; |
27894 |
++ |
27895 |
++ for (i = 0; i < nfds; i++) { |
27896 |
++ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27897 |
++ fds[i].revents = 0; |
27898 |
++ } |
27899 |
++ |
27900 |
++ ret = poll(fds, nfds, 10); |
27901 |
++ if (ret < 0) |
27902 |
++ break; |
27903 |
++ |
27904 |
++ if (fds[1].revents & POLLIN) { |
27905 |
++ ret = read(uds[1], buf, sizeof(buf)); |
27906 |
++ ASSERT_RETURN(ret == sizeof(buf)); |
27907 |
++ |
27908 |
++ add_stats(send_ns); |
27909 |
++ |
27910 |
++ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27911 |
++ ret = write(uds[0], buf, sizeof(buf)); |
27912 |
++ ASSERT_RETURN(ret == sizeof(buf)); |
27913 |
++ } |
27914 |
++ |
27915 |
++ now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27916 |
++ diff = now_ns - start; |
27917 |
++ if (diff > 1000000000ULL) { |
27918 |
++ start = now_ns; |
27919 |
++ |
27920 |
++ dump_stats(true); |
27921 |
++ break; |
27922 |
++ } |
27923 |
++ } |
27924 |
++ |
27925 |
++ } while (kdbus_util_verbose); |
27926 |
++ |
27927 |
++ kdbus_printf("-- closing bus connections\n"); |
27928 |
++ |
27929 |
++ free(kdbus_msg); |
27930 |
++ |
27931 |
++ kdbus_conn_free(conn_a); |
27932 |
++ kdbus_conn_free(conn_b); |
27933 |
++ |
27934 |
++ return (stats.count > 1) ? TEST_OK : TEST_ERR; |
27935 |
++} |
27936 |
++ |
27937 |
++int kdbus_test_benchmark(struct kdbus_test_env *env) |
27938 |
++{ |
27939 |
++ use_memfd = true; |
27940 |
++ attach_none = false; |
27941 |
++ compare_uds = false; |
27942 |
++ return benchmark(env); |
27943 |
++} |
27944 |
++ |
27945 |
++int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env) |
27946 |
++{ |
27947 |
++ use_memfd = false; |
27948 |
++ attach_none = false; |
27949 |
++ compare_uds = false; |
27950 |
++ return benchmark(env); |
27951 |
++} |
27952 |
++ |
27953 |
++int kdbus_test_benchmark_uds(struct kdbus_test_env *env) |
27954 |
++{ |
27955 |
++ use_memfd = false; |
27956 |
++ attach_none = true; |
27957 |
++ compare_uds = true; |
27958 |
++ return benchmark(env); |
27959 |
++} |
27960 |
+diff --git a/tools/testing/selftests/kdbus/test-bus.c b/tools/testing/selftests/kdbus/test-bus.c |
27961 |
+new file mode 100644 |
27962 |
+index 0000000..762fb30 |
27963 |
+--- /dev/null |
27964 |
++++ b/tools/testing/selftests/kdbus/test-bus.c |
27965 |
+@@ -0,0 +1,175 @@ |
27966 |
++#include <stdio.h> |
27967 |
++#include <string.h> |
27968 |
++#include <fcntl.h> |
27969 |
++#include <stdlib.h> |
27970 |
++#include <stddef.h> |
27971 |
++#include <unistd.h> |
27972 |
++#include <stdint.h> |
27973 |
++#include <errno.h> |
27974 |
++#include <assert.h> |
27975 |
++#include <limits.h> |
27976 |
++#include <sys/mman.h> |
27977 |
++#include <stdbool.h> |
27978 |
++ |
27979 |
++#include "kdbus-api.h" |
27980 |
++#include "kdbus-util.h" |
27981 |
++#include "kdbus-enum.h" |
27982 |
++#include "kdbus-test.h" |
27983 |
++ |
27984 |
++static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, |
27985 |
++ uint64_t type) |
27986 |
++{ |
27987 |
++ struct kdbus_item *item; |
27988 |
++ |
27989 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
27990 |
++ if (item->type == type) |
27991 |
++ return item; |
27992 |
++ |
27993 |
++ return NULL; |
27994 |
++} |
27995 |
++ |
27996 |
++static int test_bus_creator_info(const char *bus_path) |
27997 |
++{ |
27998 |
++ int ret; |
27999 |
++ uint64_t offset; |
28000 |
++ struct kdbus_conn *conn; |
28001 |
++ struct kdbus_info *info; |
28002 |
++ struct kdbus_item *item; |
28003 |
++ char *tmp, *busname; |
28004 |
++ |
28005 |
++ /* extract the bus-name from @bus_path */ |
28006 |
++ tmp = strdup(bus_path); |
28007 |
++ ASSERT_RETURN(tmp); |
28008 |
++ busname = strrchr(tmp, '/'); |
28009 |
++ ASSERT_RETURN(busname); |
28010 |
++ *busname = 0; |
28011 |
++ busname = strrchr(tmp, '/'); |
28012 |
++ ASSERT_RETURN(busname); |
28013 |
++ ++busname; |
28014 |
++ |
28015 |
++ conn = kdbus_hello(bus_path, 0, NULL, 0); |
28016 |
++ ASSERT_RETURN(conn); |
28017 |
++ |
28018 |
++ ret = kdbus_bus_creator_info(conn, _KDBUS_ATTACH_ALL, &offset); |
28019 |
++ ASSERT_RETURN(ret == 0); |
28020 |
++ |
28021 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
28022 |
++ |
28023 |
++ item = kdbus_get_item(info, KDBUS_ITEM_MAKE_NAME); |
28024 |
++ ASSERT_RETURN(item); |
28025 |
++ ASSERT_RETURN(!strcmp(item->str, busname)); |
28026 |
++ |
28027 |
++ ret = kdbus_free(conn, offset); |
28028 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
28029 |
++ |
28030 |
++ free(tmp); |
28031 |
++ kdbus_conn_free(conn); |
28032 |
++ return 0; |
28033 |
++} |
28034 |
++ |
28035 |
++int kdbus_test_bus_make(struct kdbus_test_env *env) |
28036 |
++{ |
28037 |
++ struct { |
28038 |
++ struct kdbus_cmd cmd; |
28039 |
++ |
28040 |
++ /* bloom size item */ |
28041 |
++ struct { |
28042 |
++ uint64_t size; |
28043 |
++ uint64_t type; |
28044 |
++ struct kdbus_bloom_parameter bloom; |
28045 |
++ } bs; |
28046 |
++ |
28047 |
++ /* name item */ |
28048 |
++ uint64_t n_size; |
28049 |
++ uint64_t n_type; |
28050 |
++ char name[64]; |
28051 |
++ } bus_make; |
28052 |
++ char s[PATH_MAX], *name; |
28053 |
++ int ret, control_fd2; |
28054 |
++ uid_t uid; |
28055 |
++ |
28056 |
++ name = unique_name(""); |
28057 |
++ ASSERT_RETURN(name); |
28058 |
++ |
28059 |
++ snprintf(s, sizeof(s), "%s/control", env->root); |
28060 |
++ env->control_fd = open(s, O_RDWR|O_CLOEXEC); |
28061 |
++ ASSERT_RETURN(env->control_fd >= 0); |
28062 |
++ |
28063 |
++ control_fd2 = open(s, O_RDWR|O_CLOEXEC); |
28064 |
++ ASSERT_RETURN(control_fd2 >= 0); |
28065 |
++ |
28066 |
++ memset(&bus_make, 0, sizeof(bus_make)); |
28067 |
++ |
28068 |
++ bus_make.bs.size = sizeof(bus_make.bs); |
28069 |
++ bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER; |
28070 |
++ bus_make.bs.bloom.size = 64; |
28071 |
++ bus_make.bs.bloom.n_hash = 1; |
28072 |
++ |
28073 |
++ bus_make.n_type = KDBUS_ITEM_MAKE_NAME; |
28074 |
++ |
28075 |
++ uid = getuid(); |
28076 |
++ |
28077 |
++ /* missing uid prefix */ |
28078 |
++ snprintf(bus_make.name, sizeof(bus_make.name), "foo"); |
28079 |
++ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
28080 |
++ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
28081 |
++ sizeof(bus_make.bs) + bus_make.n_size; |
28082 |
++ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
28083 |
++ ASSERT_RETURN(ret == -EINVAL); |
28084 |
++ |
28085 |
++ /* non alphanumeric character */ |
28086 |
++ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid); |
28087 |
++ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
28088 |
++ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
28089 |
++ sizeof(bus_make.bs) + bus_make.n_size; |
28090 |
++ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
28091 |
++ ASSERT_RETURN(ret == -EINVAL); |
28092 |
++ |
28093 |
++ /* '-' at the end */ |
28094 |
++ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid); |
28095 |
++ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
28096 |
++ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
28097 |
++ sizeof(bus_make.bs) + bus_make.n_size; |
28098 |
++ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
28099 |
++ ASSERT_RETURN(ret == -EINVAL); |
28100 |
++ |
28101 |
++ /* create a new bus */ |
28102 |
++ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-1", uid, name); |
28103 |
++ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
28104 |
++ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
28105 |
++ sizeof(bus_make.bs) + bus_make.n_size; |
28106 |
++ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
28107 |
++ ASSERT_RETURN(ret == 0); |
28108 |
++ |
28109 |
++ ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); |
28110 |
++ ASSERT_RETURN(ret == -EEXIST); |
28111 |
++ |
28112 |
++ snprintf(s, sizeof(s), "%s/%u-%s-1/bus", env->root, uid, name); |
28113 |
++ ASSERT_RETURN(access(s, F_OK) == 0); |
28114 |
++ |
28115 |
++ ret = test_bus_creator_info(s); |
28116 |
++ ASSERT_RETURN(ret == 0); |
28117 |
++ |
28118 |
++ /* can't use the same fd for bus make twice, even though a different |
28119 |
++ * bus name is used |
28120 |
++ */ |
28121 |
++ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); |
28122 |
++ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
28123 |
++ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
28124 |
++ sizeof(bus_make.bs) + bus_make.n_size; |
28125 |
++ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
28126 |
++ ASSERT_RETURN(ret == -EBADFD); |
28127 |
++ |
28128 |
++ /* create a new bus, with different fd and different bus name */ |
28129 |
++ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); |
28130 |
++ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
28131 |
++ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
28132 |
++ sizeof(bus_make.bs) + bus_make.n_size; |
28133 |
++ ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); |
28134 |
++ ASSERT_RETURN(ret == 0); |
28135 |
++ |
28136 |
++ close(control_fd2); |
28137 |
++ free(name); |
28138 |
++ |
28139 |
++ return TEST_OK; |
28140 |
++} |
28141 |
+diff --git a/tools/testing/selftests/kdbus/test-chat.c b/tools/testing/selftests/kdbus/test-chat.c |
28142 |
+new file mode 100644 |
28143 |
+index 0000000..71a92d8 |
28144 |
+--- /dev/null |
28145 |
++++ b/tools/testing/selftests/kdbus/test-chat.c |
28146 |
+@@ -0,0 +1,122 @@ |
28147 |
++#include <stdio.h> |
28148 |
++#include <string.h> |
28149 |
++#include <time.h> |
28150 |
++#include <fcntl.h> |
28151 |
++#include <stdlib.h> |
28152 |
++#include <stddef.h> |
28153 |
++#include <unistd.h> |
28154 |
++#include <stdint.h> |
28155 |
++#include <errno.h> |
28156 |
++#include <assert.h> |
28157 |
++#include <poll.h> |
28158 |
++#include <stdbool.h> |
28159 |
++ |
28160 |
++#include "kdbus-test.h" |
28161 |
++#include "kdbus-util.h" |
28162 |
++#include "kdbus-enum.h" |
28163 |
++ |
28164 |
++int kdbus_test_chat(struct kdbus_test_env *env) |
28165 |
++{ |
28166 |
++ int ret, cookie; |
28167 |
++ struct kdbus_conn *conn_a, *conn_b; |
28168 |
++ struct pollfd fds[2]; |
28169 |
++ uint64_t flags; |
28170 |
++ int count; |
28171 |
++ |
28172 |
++ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
28173 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
28174 |
++ ASSERT_RETURN(conn_a && conn_b); |
28175 |
++ |
28176 |
++ flags = KDBUS_NAME_ALLOW_REPLACEMENT; |
28177 |
++ ret = kdbus_name_acquire(conn_a, "foo.bar.test", &flags); |
28178 |
++ ASSERT_RETURN(ret == 0); |
28179 |
++ |
28180 |
++ ret = kdbus_name_acquire(conn_a, "foo.bar.baz", NULL); |
28181 |
++ ASSERT_RETURN(ret == 0); |
28182 |
++ |
28183 |
++ flags = KDBUS_NAME_QUEUE; |
28184 |
++ ret = kdbus_name_acquire(conn_b, "foo.bar.baz", &flags); |
28185 |
++ ASSERT_RETURN(ret == 0); |
28186 |
++ |
28187 |
++ ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL); |
28188 |
++ ASSERT_RETURN(ret == 0); |
28189 |
++ |
28190 |
++ ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL); |
28191 |
++ ASSERT_RETURN(ret == -EALREADY); |
28192 |
++ |
28193 |
++ ret = kdbus_name_release(conn_a, "foo.bar.double"); |
28194 |
++ ASSERT_RETURN(ret == 0); |
28195 |
++ |
28196 |
++ ret = kdbus_name_release(conn_a, "foo.bar.double"); |
28197 |
++ ASSERT_RETURN(ret == -ESRCH); |
28198 |
++ |
28199 |
++ ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | |
28200 |
++ KDBUS_LIST_NAMES | |
28201 |
++ KDBUS_LIST_QUEUED | |
28202 |
++ KDBUS_LIST_ACTIVATORS); |
28203 |
++ ASSERT_RETURN(ret == 0); |
28204 |
++ |
28205 |
++ ret = kdbus_add_match_empty(conn_a); |
28206 |
++ ASSERT_RETURN(ret == 0); |
28207 |
++ |
28208 |
++ ret = kdbus_add_match_empty(conn_b); |
28209 |
++ ASSERT_RETURN(ret == 0); |
28210 |
++ |
28211 |
++ cookie = 0; |
28212 |
++ ret = kdbus_msg_send(conn_b, NULL, 0xc0000000 | cookie, 0, 0, 0, |
28213 |
++ KDBUS_DST_ID_BROADCAST); |
28214 |
++ ASSERT_RETURN(ret == 0); |
28215 |
++ |
28216 |
++ fds[0].fd = conn_a->fd; |
28217 |
++ fds[1].fd = conn_b->fd; |
28218 |
++ |
28219 |
++ kdbus_printf("-- entering poll loop ...\n"); |
28220 |
++ |
28221 |
++ for (count = 0;; count++) { |
28222 |
++ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
28223 |
++ |
28224 |
++ for (i = 0; i < nfds; i++) { |
28225 |
++ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
28226 |
++ fds[i].revents = 0; |
28227 |
++ } |
28228 |
++ |
28229 |
++ ret = poll(fds, nfds, 3000); |
28230 |
++ ASSERT_RETURN(ret >= 0); |
28231 |
++ |
28232 |
++ if (fds[0].revents & POLLIN) { |
28233 |
++ if (count > 2) |
28234 |
++ kdbus_name_release(conn_a, "foo.bar.baz"); |
28235 |
++ |
28236 |
++ ret = kdbus_msg_recv(conn_a, NULL, NULL); |
28237 |
++ ASSERT_RETURN(ret == 0); |
28238 |
++ ret = kdbus_msg_send(conn_a, NULL, |
28239 |
++ 0xc0000000 | cookie++, |
28240 |
++ 0, 0, 0, conn_b->id); |
28241 |
++ ASSERT_RETURN(ret == 0); |
28242 |
++ } |
28243 |
++ |
28244 |
++ if (fds[1].revents & POLLIN) { |
28245 |
++ ret = kdbus_msg_recv(conn_b, NULL, NULL); |
28246 |
++ ASSERT_RETURN(ret == 0); |
28247 |
++ ret = kdbus_msg_send(conn_b, NULL, |
28248 |
++ 0xc0000000 | cookie++, |
28249 |
++ 0, 0, 0, conn_a->id); |
28250 |
++ ASSERT_RETURN(ret == 0); |
28251 |
++ } |
28252 |
++ |
28253 |
++ ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | |
28254 |
++ KDBUS_LIST_NAMES | |
28255 |
++ KDBUS_LIST_QUEUED | |
28256 |
++ KDBUS_LIST_ACTIVATORS); |
28257 |
++ ASSERT_RETURN(ret == 0); |
28258 |
++ |
28259 |
++ if (count > 10) |
28260 |
++ break; |
28261 |
++ } |
28262 |
++ |
28263 |
++ kdbus_printf("-- closing bus connections\n"); |
28264 |
++ kdbus_conn_free(conn_a); |
28265 |
++ kdbus_conn_free(conn_b); |
28266 |
++ |
28267 |
++ return TEST_OK; |
28268 |
++} |
28269 |
+diff --git a/tools/testing/selftests/kdbus/test-connection.c b/tools/testing/selftests/kdbus/test-connection.c |
28270 |
+new file mode 100644 |
28271 |
+index 0000000..5c2bf35 |
28272 |
+--- /dev/null |
28273 |
++++ b/tools/testing/selftests/kdbus/test-connection.c |
28274 |
+@@ -0,0 +1,616 @@ |
28275 |
++#include <stdio.h> |
28276 |
++#include <string.h> |
28277 |
++#include <fcntl.h> |
28278 |
++#include <stdlib.h> |
28279 |
++#include <stddef.h> |
28280 |
++#include <unistd.h> |
28281 |
++#include <stdint.h> |
28282 |
++#include <errno.h> |
28283 |
++#include <assert.h> |
28284 |
++#include <limits.h> |
28285 |
++#include <sys/types.h> |
28286 |
++#include <sys/capability.h> |
28287 |
++#include <sys/mman.h> |
28288 |
++#include <sys/syscall.h> |
28289 |
++#include <sys/wait.h> |
28290 |
++#include <stdbool.h> |
28291 |
++ |
28292 |
++#include "kdbus-api.h" |
28293 |
++#include "kdbus-util.h" |
28294 |
++#include "kdbus-enum.h" |
28295 |
++#include "kdbus-test.h" |
28296 |
++ |
28297 |
++int kdbus_test_hello(struct kdbus_test_env *env) |
28298 |
++{ |
28299 |
++ struct kdbus_cmd_free cmd_free = {}; |
28300 |
++ struct kdbus_cmd_hello hello; |
28301 |
++ int fd, ret; |
28302 |
++ |
28303 |
++ memset(&hello, 0, sizeof(hello)); |
28304 |
++ |
28305 |
++ fd = open(env->buspath, O_RDWR|O_CLOEXEC); |
28306 |
++ ASSERT_RETURN(fd >= 0); |
28307 |
++ |
28308 |
++ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
28309 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28310 |
++ hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
28311 |
++ hello.size = sizeof(struct kdbus_cmd_hello); |
28312 |
++ hello.pool_size = POOL_SIZE; |
28313 |
++ |
28314 |
++ /* an unaligned hello must result in -EFAULT */ |
28315 |
++ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) ((char *) &hello + 1)); |
28316 |
++ ASSERT_RETURN(ret == -EFAULT); |
28317 |
++ |
28318 |
++ /* a size of 0 must return EMSGSIZE */ |
28319 |
++ hello.size = 1; |
28320 |
++ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
28321 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28322 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28323 |
++ ASSERT_RETURN(ret == -EINVAL); |
28324 |
++ |
28325 |
++ hello.size = sizeof(struct kdbus_cmd_hello); |
28326 |
++ |
28327 |
++ /* check faulty flags */ |
28328 |
++ hello.flags = 1ULL << 32; |
28329 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28330 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28331 |
++ ASSERT_RETURN(ret == -EINVAL); |
28332 |
++ |
28333 |
++ /* check for faulty pool sizes */ |
28334 |
++ hello.pool_size = 0; |
28335 |
++ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
28336 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28337 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28338 |
++ ASSERT_RETURN(ret == -EINVAL); |
28339 |
++ |
28340 |
++ hello.pool_size = 4097; |
28341 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28342 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28343 |
++ ASSERT_RETURN(ret == -EINVAL); |
28344 |
++ |
28345 |
++ hello.pool_size = POOL_SIZE; |
28346 |
++ |
28347 |
++ /* |
28348 |
++ * The connection created by the core requires ALL meta flags |
28349 |
++ * to be sent. An attempt to send less than that should result in |
28350 |
++ * -ECONNREFUSED. |
28351 |
++ */ |
28352 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL & ~KDBUS_ATTACH_TIMESTAMP; |
28353 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28354 |
++ ASSERT_RETURN(ret == -ECONNREFUSED); |
28355 |
++ |
28356 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28357 |
++ hello.offset = (__u64)-1; |
28358 |
++ |
28359 |
++ /* success test */ |
28360 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28361 |
++ ASSERT_RETURN(ret == 0); |
28362 |
++ |
28363 |
++ /* The kernel should have returned some items */ |
28364 |
++ ASSERT_RETURN(hello.offset != (__u64)-1); |
28365 |
++ cmd_free.size = sizeof(cmd_free); |
28366 |
++ cmd_free.offset = hello.offset; |
28367 |
++ ret = kdbus_cmd_free(fd, &cmd_free); |
28368 |
++ ASSERT_RETURN(ret >= 0); |
28369 |
++ |
28370 |
++ close(fd); |
28371 |
++ |
28372 |
++ fd = open(env->buspath, O_RDWR|O_CLOEXEC); |
28373 |
++ ASSERT_RETURN(fd >= 0); |
28374 |
++ |
28375 |
++ /* no ACTIVATOR flag without a name */ |
28376 |
++ hello.flags = KDBUS_HELLO_ACTIVATOR; |
28377 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28378 |
++ ASSERT_RETURN(ret == -EINVAL); |
28379 |
++ |
28380 |
++ close(fd); |
28381 |
++ |
28382 |
++ return TEST_OK; |
28383 |
++} |
28384 |
++ |
28385 |
++int kdbus_test_byebye(struct kdbus_test_env *env) |
28386 |
++{ |
28387 |
++ struct kdbus_conn *conn; |
28388 |
++ struct kdbus_cmd_recv cmd_recv = { .size = sizeof(cmd_recv) }; |
28389 |
++ struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; |
28390 |
++ int ret; |
28391 |
++ |
28392 |
++ /* create a 2nd connection */ |
28393 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28394 |
++ ASSERT_RETURN(conn != NULL); |
28395 |
++ |
28396 |
++ ret = kdbus_add_match_empty(conn); |
28397 |
++ ASSERT_RETURN(ret == 0); |
28398 |
++ |
28399 |
++ ret = kdbus_add_match_empty(env->conn); |
28400 |
++ ASSERT_RETURN(ret == 0); |
28401 |
++ |
28402 |
++ /* send over 1st connection */ |
28403 |
++ ret = kdbus_msg_send(env->conn, NULL, 0, 0, 0, 0, |
28404 |
++ KDBUS_DST_ID_BROADCAST); |
28405 |
++ ASSERT_RETURN(ret == 0); |
28406 |
++ |
28407 |
++ /* say byebye on the 2nd, which must fail */ |
28408 |
++ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
28409 |
++ ASSERT_RETURN(ret == -EBUSY); |
28410 |
++ |
28411 |
++ /* receive the message */ |
28412 |
++ ret = kdbus_cmd_recv(conn->fd, &cmd_recv); |
28413 |
++ ASSERT_RETURN(ret == 0); |
28414 |
++ |
28415 |
++ ret = kdbus_free(conn, cmd_recv.msg.offset); |
28416 |
++ ASSERT_RETURN(ret == 0); |
28417 |
++ |
28418 |
++ /* and try again */ |
28419 |
++ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
28420 |
++ ASSERT_RETURN(ret == 0); |
28421 |
++ |
28422 |
++ /* a 2nd try should result in -ECONNRESET */ |
28423 |
++ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
28424 |
++ ASSERT_RETURN(ret == -ECONNRESET); |
28425 |
++ |
28426 |
++ kdbus_conn_free(conn); |
28427 |
++ |
28428 |
++ return TEST_OK; |
28429 |
++} |
28430 |
++ |
28431 |
++/* Get only the first item */ |
28432 |
++static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, |
28433 |
++ uint64_t type) |
28434 |
++{ |
28435 |
++ struct kdbus_item *item; |
28436 |
++ |
28437 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
28438 |
++ if (item->type == type) |
28439 |
++ return item; |
28440 |
++ |
28441 |
++ return NULL; |
28442 |
++} |
28443 |
++ |
28444 |
++static unsigned int kdbus_count_item(struct kdbus_info *info, |
28445 |
++ uint64_t type) |
28446 |
++{ |
28447 |
++ unsigned int i = 0; |
28448 |
++ const struct kdbus_item *item; |
28449 |
++ |
28450 |
++ KDBUS_ITEM_FOREACH(item, info, items) |
28451 |
++ if (item->type == type) |
28452 |
++ i++; |
28453 |
++ |
28454 |
++ return i; |
28455 |
++} |
28456 |
++ |
28457 |
++static int kdbus_fuzz_conn_info(struct kdbus_test_env *env, int capable) |
28458 |
++{ |
28459 |
++ int ret; |
28460 |
++ unsigned int cnt = 0; |
28461 |
++ uint64_t offset = 0; |
28462 |
++ uint64_t kdbus_flags_mask; |
28463 |
++ struct kdbus_info *info; |
28464 |
++ struct kdbus_conn *conn; |
28465 |
++ struct kdbus_conn *privileged; |
28466 |
++ const struct kdbus_item *item; |
28467 |
++ uint64_t valid_flags_set; |
28468 |
++ uint64_t invalid_flags_set; |
28469 |
++ uint64_t valid_flags = KDBUS_ATTACH_NAMES | |
28470 |
++ KDBUS_ATTACH_CREDS | |
28471 |
++ KDBUS_ATTACH_PIDS | |
28472 |
++ KDBUS_ATTACH_CONN_DESCRIPTION; |
28473 |
++ |
28474 |
++ uint64_t invalid_flags = KDBUS_ATTACH_NAMES | |
28475 |
++ KDBUS_ATTACH_CREDS | |
28476 |
++ KDBUS_ATTACH_PIDS | |
28477 |
++ KDBUS_ATTACH_CAPS | |
28478 |
++ KDBUS_ATTACH_CGROUP | |
28479 |
++ KDBUS_ATTACH_CONN_DESCRIPTION; |
28480 |
++ |
28481 |
++ struct kdbus_creds cached_creds; |
28482 |
++ uid_t ruid, euid, suid; |
28483 |
++ gid_t rgid, egid, sgid; |
28484 |
++ |
28485 |
++ getresuid(&ruid, &euid, &suid); |
28486 |
++ getresgid(&rgid, &egid, &sgid); |
28487 |
++ |
28488 |
++ cached_creds.uid = ruid; |
28489 |
++ cached_creds.euid = euid; |
28490 |
++ cached_creds.suid = suid; |
28491 |
++ cached_creds.fsuid = ruid; |
28492 |
++ |
28493 |
++ cached_creds.gid = rgid; |
28494 |
++ cached_creds.egid = egid; |
28495 |
++ cached_creds.sgid = sgid; |
28496 |
++ cached_creds.fsgid = rgid; |
28497 |
++ |
28498 |
++ struct kdbus_pids cached_pids = { |
28499 |
++ .pid = getpid(), |
28500 |
++ .tid = syscall(SYS_gettid), |
28501 |
++ .ppid = getppid(), |
28502 |
++ }; |
28503 |
++ |
28504 |
++ ret = kdbus_sysfs_get_parameter_mask(env->mask_param_path, |
28505 |
++ &kdbus_flags_mask); |
28506 |
++ ASSERT_RETURN(ret == 0); |
28507 |
++ |
28508 |
++ valid_flags_set = valid_flags & kdbus_flags_mask; |
28509 |
++ invalid_flags_set = invalid_flags & kdbus_flags_mask; |
28510 |
++ |
28511 |
++ ret = kdbus_conn_info(env->conn, env->conn->id, NULL, |
28512 |
++ valid_flags, &offset); |
28513 |
++ ASSERT_RETURN(ret == 0); |
28514 |
++ |
28515 |
++ info = (struct kdbus_info *)(env->conn->buf + offset); |
28516 |
++ ASSERT_RETURN(info->id == env->conn->id); |
28517 |
++ |
28518 |
++ /* We do not have any well-known name */ |
28519 |
++ item = kdbus_get_item(info, KDBUS_ITEM_NAME); |
28520 |
++ ASSERT_RETURN(item == NULL); |
28521 |
++ |
28522 |
++ item = kdbus_get_item(info, KDBUS_ITEM_CONN_DESCRIPTION); |
28523 |
++ if (valid_flags_set & KDBUS_ATTACH_CONN_DESCRIPTION) { |
28524 |
++ ASSERT_RETURN(item); |
28525 |
++ } else { |
28526 |
++ ASSERT_RETURN(item == NULL); |
28527 |
++ } |
28528 |
++ |
28529 |
++ kdbus_free(env->conn, offset); |
28530 |
++ |
28531 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28532 |
++ ASSERT_RETURN(conn); |
28533 |
++ |
28534 |
++ privileged = kdbus_hello(env->buspath, 0, NULL, 0); |
28535 |
++ ASSERT_RETURN(privileged); |
28536 |
++ |
28537 |
++ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28538 |
++ ASSERT_RETURN(ret == 0); |
28539 |
++ |
28540 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
28541 |
++ ASSERT_RETURN(info->id == conn->id); |
28542 |
++ |
28543 |
++ /* We do not have any well-known name */ |
28544 |
++ item = kdbus_get_item(info, KDBUS_ITEM_NAME); |
28545 |
++ ASSERT_RETURN(item == NULL); |
28546 |
++ |
28547 |
++ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); |
28548 |
++ if (valid_flags_set & KDBUS_ATTACH_CREDS) { |
28549 |
++ ASSERT_RETURN(cnt == 1); |
28550 |
++ |
28551 |
++ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28552 |
++ ASSERT_RETURN(item); |
28553 |
++ |
28554 |
++ /* Compare received items with cached creds */ |
28555 |
++ ASSERT_RETURN(memcmp(&item->creds, &cached_creds, |
28556 |
++ sizeof(struct kdbus_creds)) == 0); |
28557 |
++ } else { |
28558 |
++ ASSERT_RETURN(cnt == 0); |
28559 |
++ } |
28560 |
++ |
28561 |
++ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28562 |
++ if (valid_flags_set & KDBUS_ATTACH_PIDS) { |
28563 |
++ ASSERT_RETURN(item); |
28564 |
++ |
28565 |
++ /* Compare item->pids with cached PIDs */ |
28566 |
++ ASSERT_RETURN(item->pids.pid == cached_pids.pid && |
28567 |
++ item->pids.tid == cached_pids.tid && |
28568 |
++ item->pids.ppid == cached_pids.ppid); |
28569 |
++ } else { |
28570 |
++ ASSERT_RETURN(item == NULL); |
28571 |
++ } |
28572 |
++ |
28573 |
++ /* We did not request KDBUS_ITEM_CAPS */ |
28574 |
++ item = kdbus_get_item(info, KDBUS_ITEM_CAPS); |
28575 |
++ ASSERT_RETURN(item == NULL); |
28576 |
++ |
28577 |
++ kdbus_free(conn, offset); |
28578 |
++ |
28579 |
++ ret = kdbus_name_acquire(conn, "com.example.a", NULL); |
28580 |
++ ASSERT_RETURN(ret >= 0); |
28581 |
++ |
28582 |
++ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28583 |
++ ASSERT_RETURN(ret == 0); |
28584 |
++ |
28585 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
28586 |
++ ASSERT_RETURN(info->id == conn->id); |
28587 |
++ |
28588 |
++ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); |
28589 |
++ if (valid_flags_set & KDBUS_ATTACH_NAMES) { |
28590 |
++ ASSERT_RETURN(item && !strcmp(item->name.name, "com.example.a")); |
28591 |
++ } else { |
28592 |
++ ASSERT_RETURN(item == NULL); |
28593 |
++ } |
28594 |
++ |
28595 |
++ kdbus_free(conn, offset); |
28596 |
++ |
28597 |
++ ret = kdbus_conn_info(conn, 0, "com.example.a", valid_flags, &offset); |
28598 |
++ ASSERT_RETURN(ret == 0); |
28599 |
++ |
28600 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
28601 |
++ ASSERT_RETURN(info->id == conn->id); |
28602 |
++ |
28603 |
++ kdbus_free(conn, offset); |
28604 |
++ |
28605 |
++ /* does not have the necessary caps to drop to unprivileged */ |
28606 |
++ if (!capable) |
28607 |
++ goto continue_test; |
28608 |
++ |
28609 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
28610 |
++ ret = kdbus_conn_info(conn, conn->id, NULL, |
28611 |
++ valid_flags, &offset); |
28612 |
++ ASSERT_EXIT(ret == 0); |
28613 |
++ |
28614 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
28615 |
++ ASSERT_EXIT(info->id == conn->id); |
28616 |
++ |
28617 |
++ if (valid_flags_set & KDBUS_ATTACH_NAMES) { |
28618 |
++ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); |
28619 |
++ ASSERT_EXIT(item && |
28620 |
++ strcmp(item->name.name, |
28621 |
++ "com.example.a") == 0); |
28622 |
++ } |
28623 |
++ |
28624 |
++ if (valid_flags_set & KDBUS_ATTACH_CREDS) { |
28625 |
++ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28626 |
++ ASSERT_EXIT(item); |
28627 |
++ |
28628 |
++ /* Compare received items with cached creds */ |
28629 |
++ ASSERT_EXIT(memcmp(&item->creds, &cached_creds, |
28630 |
++ sizeof(struct kdbus_creds)) == 0); |
28631 |
++ } |
28632 |
++ |
28633 |
++ if (valid_flags_set & KDBUS_ATTACH_PIDS) { |
28634 |
++ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28635 |
++ ASSERT_EXIT(item); |
28636 |
++ |
28637 |
++ /* |
28638 |
++ * Compare item->pids with cached pids of |
28639 |
++ * privileged one. |
28640 |
++ * |
28641 |
++ * cmd_info will always return cached pids. |
28642 |
++ */ |
28643 |
++ ASSERT_EXIT(item->pids.pid == cached_pids.pid && |
28644 |
++ item->pids.tid == cached_pids.tid); |
28645 |
++ } |
28646 |
++ |
28647 |
++ kdbus_free(conn, offset); |
28648 |
++ |
28649 |
++ /* |
28650 |
++ * Use invalid_flags and make sure that userspace |
28651 |
++ * do not play with us. |
28652 |
++ */ |
28653 |
++ ret = kdbus_conn_info(conn, conn->id, NULL, |
28654 |
++ invalid_flags, &offset); |
28655 |
++ ASSERT_EXIT(ret == 0); |
28656 |
++ |
28657 |
++ /* |
28658 |
++ * Make sure that we return only one creds item and |
28659 |
++ * it points to the cached creds. |
28660 |
++ */ |
28661 |
++ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); |
28662 |
++ if (invalid_flags_set & KDBUS_ATTACH_CREDS) { |
28663 |
++ ASSERT_EXIT(cnt == 1); |
28664 |
++ |
28665 |
++ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28666 |
++ ASSERT_EXIT(item); |
28667 |
++ |
28668 |
++ /* Compare received items with cached creds */ |
28669 |
++ ASSERT_EXIT(memcmp(&item->creds, &cached_creds, |
28670 |
++ sizeof(struct kdbus_creds)) == 0); |
28671 |
++ } else { |
28672 |
++ ASSERT_EXIT(cnt == 0); |
28673 |
++ } |
28674 |
++ |
28675 |
++ if (invalid_flags_set & KDBUS_ATTACH_PIDS) { |
28676 |
++ cnt = kdbus_count_item(info, KDBUS_ITEM_PIDS); |
28677 |
++ ASSERT_EXIT(cnt == 1); |
28678 |
++ |
28679 |
++ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28680 |
++ ASSERT_EXIT(item); |
28681 |
++ |
28682 |
++ /* Compare item->pids with cached pids */ |
28683 |
++ ASSERT_EXIT(item->pids.pid == cached_pids.pid && |
28684 |
++ item->pids.tid == cached_pids.tid); |
28685 |
++ } |
28686 |
++ |
28687 |
++ cnt = kdbus_count_item(info, KDBUS_ITEM_CGROUP); |
28688 |
++ if (invalid_flags_set & KDBUS_ATTACH_CGROUP) { |
28689 |
++ ASSERT_EXIT(cnt == 1); |
28690 |
++ } else { |
28691 |
++ ASSERT_EXIT(cnt == 0); |
28692 |
++ } |
28693 |
++ |
28694 |
++ cnt = kdbus_count_item(info, KDBUS_ITEM_CAPS); |
28695 |
++ if (invalid_flags_set & KDBUS_ATTACH_CAPS) { |
28696 |
++ ASSERT_EXIT(cnt == 1); |
28697 |
++ } else { |
28698 |
++ ASSERT_EXIT(cnt == 0); |
28699 |
++ } |
28700 |
++ |
28701 |
++ kdbus_free(conn, offset); |
28702 |
++ }), |
28703 |
++ ({ 0; })); |
28704 |
++ ASSERT_RETURN(ret == 0); |
28705 |
++ |
28706 |
++continue_test: |
28707 |
++ |
28708 |
++ /* A second name */ |
28709 |
++ ret = kdbus_name_acquire(conn, "com.example.b", NULL); |
28710 |
++ ASSERT_RETURN(ret >= 0); |
28711 |
++ |
28712 |
++ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28713 |
++ ASSERT_RETURN(ret == 0); |
28714 |
++ |
28715 |
++ info = (struct kdbus_info *)(conn->buf + offset); |
28716 |
++ ASSERT_RETURN(info->id == conn->id); |
28717 |
++ |
28718 |
++ cnt = kdbus_count_item(info, KDBUS_ITEM_OWNED_NAME); |
28719 |
++ if (valid_flags_set & KDBUS_ATTACH_NAMES) { |
28720 |
++ ASSERT_RETURN(cnt == 2); |
28721 |
++ } else { |
28722 |
++ ASSERT_RETURN(cnt == 0); |
28723 |
++ } |
28724 |
++ |
28725 |
++ kdbus_free(conn, offset); |
28726 |
++ |
28727 |
++ ASSERT_RETURN(ret == 0); |
28728 |
++ |
28729 |
++ return 0; |
28730 |
++} |
28731 |
++ |
28732 |
++int kdbus_test_conn_info(struct kdbus_test_env *env) |
28733 |
++{ |
28734 |
++ int ret; |
28735 |
++ int have_caps; |
28736 |
++ struct { |
28737 |
++ struct kdbus_cmd_info cmd_info; |
28738 |
++ |
28739 |
++ struct { |
28740 |
++ uint64_t size; |
28741 |
++ uint64_t type; |
28742 |
++ char str[64]; |
28743 |
++ } name; |
28744 |
++ } buf; |
28745 |
++ |
28746 |
++ buf.cmd_info.size = sizeof(struct kdbus_cmd_info); |
28747 |
++ buf.cmd_info.flags = 0; |
28748 |
++ buf.cmd_info.attach_flags = 0; |
28749 |
++ buf.cmd_info.id = env->conn->id; |
28750 |
++ |
28751 |
++ ret = kdbus_conn_info(env->conn, env->conn->id, NULL, 0, NULL); |
28752 |
++ ASSERT_RETURN(ret == 0); |
28753 |
++ |
28754 |
++ /* try to pass a name that is longer than the buffer's size */ |
28755 |
++ buf.name.size = KDBUS_ITEM_HEADER_SIZE + 1; |
28756 |
++ buf.name.type = KDBUS_ITEM_NAME; |
28757 |
++ strcpy(buf.name.str, "foo.bar.bla"); |
28758 |
++ |
28759 |
++ buf.cmd_info.id = 0; |
28760 |
++ buf.cmd_info.size = sizeof(buf.cmd_info) + buf.name.size; |
28761 |
++ ret = kdbus_cmd_conn_info(env->conn->fd, (struct kdbus_cmd_info *) &buf); |
28762 |
++ ASSERT_RETURN(ret == -EINVAL); |
28763 |
++ |
28764 |
++ /* Pass a non existent name */ |
28765 |
++ ret = kdbus_conn_info(env->conn, 0, "non.existent.name", 0, NULL); |
28766 |
++ ASSERT_RETURN(ret == -ESRCH); |
28767 |
++ |
28768 |
++ if (!all_uids_gids_are_mapped()) |
28769 |
++ return TEST_SKIP; |
28770 |
++ |
28771 |
++ /* Test for caps here, so we run the previous test */ |
28772 |
++ have_caps = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
28773 |
++ ASSERT_RETURN(have_caps >= 0); |
28774 |
++ |
28775 |
++ ret = kdbus_fuzz_conn_info(env, have_caps); |
28776 |
++ ASSERT_RETURN(ret == 0); |
28777 |
++ |
28778 |
++ /* Now if we have skipped some tests then let the user know */ |
28779 |
++ if (!have_caps) |
28780 |
++ return TEST_SKIP; |
28781 |
++ |
28782 |
++ return TEST_OK; |
28783 |
++} |
28784 |
++ |
28785 |
++int kdbus_test_conn_update(struct kdbus_test_env *env) |
28786 |
++{ |
28787 |
++ struct kdbus_conn *conn; |
28788 |
++ struct kdbus_msg *msg; |
28789 |
++ int found = 0; |
28790 |
++ int ret; |
28791 |
++ |
28792 |
++ /* |
28793 |
++ * kdbus_hello() sets all attach flags. Receive a message by this |
28794 |
++ * connection, and make sure a timestamp item (just to pick one) is |
28795 |
++ * present. |
28796 |
++ */ |
28797 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28798 |
++ ASSERT_RETURN(conn); |
28799 |
++ |
28800 |
++ ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); |
28801 |
++ ASSERT_RETURN(ret == 0); |
28802 |
++ |
28803 |
++ ret = kdbus_msg_recv(conn, &msg, NULL); |
28804 |
++ ASSERT_RETURN(ret == 0); |
28805 |
++ |
28806 |
++ found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
28807 |
++ ASSERT_RETURN(found == 1); |
28808 |
++ |
28809 |
++ kdbus_msg_free(msg); |
28810 |
++ |
28811 |
++ /* |
28812 |
++ * Now, modify the attach flags and repeat the action. The item must |
28813 |
++ * now be missing. |
28814 |
++ */ |
28815 |
++ found = 0; |
28816 |
++ |
28817 |
++ ret = kdbus_conn_update_attach_flags(conn, |
28818 |
++ _KDBUS_ATTACH_ALL, |
28819 |
++ _KDBUS_ATTACH_ALL & |
28820 |
++ ~KDBUS_ATTACH_TIMESTAMP); |
28821 |
++ ASSERT_RETURN(ret == 0); |
28822 |
++ |
28823 |
++ ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); |
28824 |
++ ASSERT_RETURN(ret == 0); |
28825 |
++ |
28826 |
++ ret = kdbus_msg_recv(conn, &msg, NULL); |
28827 |
++ ASSERT_RETURN(ret == 0); |
28828 |
++ |
28829 |
++ found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
28830 |
++ ASSERT_RETURN(found == 0); |
28831 |
++ |
28832 |
++ /* Provide a bogus attach_flags value */ |
28833 |
++ ret = kdbus_conn_update_attach_flags(conn, |
28834 |
++ _KDBUS_ATTACH_ALL + 1, |
28835 |
++ _KDBUS_ATTACH_ALL); |
28836 |
++ ASSERT_RETURN(ret == -EINVAL); |
28837 |
++ |
28838 |
++ kdbus_msg_free(msg); |
28839 |
++ |
28840 |
++ kdbus_conn_free(conn); |
28841 |
++ |
28842 |
++ return TEST_OK; |
28843 |
++} |
28844 |
++ |
28845 |
++int kdbus_test_writable_pool(struct kdbus_test_env *env) |
28846 |
++{ |
28847 |
++ struct kdbus_cmd_free cmd_free = {}; |
28848 |
++ struct kdbus_cmd_hello hello; |
28849 |
++ int fd, ret; |
28850 |
++ void *map; |
28851 |
++ |
28852 |
++ fd = open(env->buspath, O_RDWR | O_CLOEXEC); |
28853 |
++ ASSERT_RETURN(fd >= 0); |
28854 |
++ |
28855 |
++ memset(&hello, 0, sizeof(hello)); |
28856 |
++ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
28857 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28858 |
++ hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
28859 |
++ hello.size = sizeof(struct kdbus_cmd_hello); |
28860 |
++ hello.pool_size = POOL_SIZE; |
28861 |
++ hello.offset = (__u64)-1; |
28862 |
++ |
28863 |
++ /* success test */ |
28864 |
++ ret = kdbus_cmd_hello(fd, &hello); |
28865 |
++ ASSERT_RETURN(ret == 0); |
28866 |
++ |
28867 |
++ /* The kernel should have returned some items */ |
28868 |
++ ASSERT_RETURN(hello.offset != (__u64)-1); |
28869 |
++ cmd_free.size = sizeof(cmd_free); |
28870 |
++ cmd_free.offset = hello.offset; |
28871 |
++ ret = kdbus_cmd_free(fd, &cmd_free); |
28872 |
++ ASSERT_RETURN(ret >= 0); |
28873 |
++ |
28874 |
++ /* pools cannot be mapped writable */ |
28875 |
++ map = mmap(NULL, POOL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
28876 |
++ ASSERT_RETURN(map == MAP_FAILED); |
28877 |
++ |
28878 |
++ /* pools can always be mapped readable */ |
28879 |
++ map = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
28880 |
++ ASSERT_RETURN(map != MAP_FAILED); |
28881 |
++ |
28882 |
++ /* make sure we cannot change protection masks to writable */ |
28883 |
++ ret = mprotect(map, POOL_SIZE, PROT_READ | PROT_WRITE); |
28884 |
++ ASSERT_RETURN(ret < 0); |
28885 |
++ |
28886 |
++ munmap(map, POOL_SIZE); |
28887 |
++ close(fd); |
28888 |
++ |
28889 |
++ return TEST_OK; |
28890 |
++} |
28891 |
+diff --git a/tools/testing/selftests/kdbus/test-daemon.c b/tools/testing/selftests/kdbus/test-daemon.c |
28892 |
+new file mode 100644 |
28893 |
+index 0000000..8bc2386 |
28894 |
+--- /dev/null |
28895 |
++++ b/tools/testing/selftests/kdbus/test-daemon.c |
28896 |
+@@ -0,0 +1,65 @@ |
28897 |
++#include <stdio.h> |
28898 |
++#include <string.h> |
28899 |
++#include <time.h> |
28900 |
++#include <fcntl.h> |
28901 |
++#include <stdlib.h> |
28902 |
++#include <stddef.h> |
28903 |
++#include <unistd.h> |
28904 |
++#include <stdint.h> |
28905 |
++#include <errno.h> |
28906 |
++#include <assert.h> |
28907 |
++#include <poll.h> |
28908 |
++#include <stdbool.h> |
28909 |
++ |
28910 |
++#include "kdbus-test.h" |
28911 |
++#include "kdbus-util.h" |
28912 |
++#include "kdbus-enum.h" |
28913 |
++ |
28914 |
++int kdbus_test_daemon(struct kdbus_test_env *env) |
28915 |
++{ |
28916 |
++ struct pollfd fds[2]; |
28917 |
++ int count; |
28918 |
++ int ret; |
28919 |
++ |
28920 |
++ /* This test doesn't make any sense in non-interactive mode */ |
28921 |
++ if (!kdbus_util_verbose) |
28922 |
++ return TEST_OK; |
28923 |
++ |
28924 |
++ printf("Created connection %llu on bus '%s'\n", |
28925 |
++ (unsigned long long) env->conn->id, env->buspath); |
28926 |
++ |
28927 |
++ ret = kdbus_name_acquire(env->conn, "com.example.kdbus-test", NULL); |
28928 |
++ ASSERT_RETURN(ret == 0); |
28929 |
++ printf(" Aquired name: com.example.kdbus-test\n"); |
28930 |
++ |
28931 |
++ fds[0].fd = env->conn->fd; |
28932 |
++ fds[1].fd = STDIN_FILENO; |
28933 |
++ |
28934 |
++ printf("Monitoring connections:\n"); |
28935 |
++ |
28936 |
++ for (count = 0;; count++) { |
28937 |
++ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
28938 |
++ |
28939 |
++ for (i = 0; i < nfds; i++) { |
28940 |
++ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
28941 |
++ fds[i].revents = 0; |
28942 |
++ } |
28943 |
++ |
28944 |
++ ret = poll(fds, nfds, -1); |
28945 |
++ if (ret <= 0) |
28946 |
++ break; |
28947 |
++ |
28948 |
++ if (fds[0].revents & POLLIN) { |
28949 |
++ ret = kdbus_msg_recv(env->conn, NULL, NULL); |
28950 |
++ ASSERT_RETURN(ret == 0); |
28951 |
++ } |
28952 |
++ |
28953 |
++ /* stdin */ |
28954 |
++ if (fds[1].revents & POLLIN) |
28955 |
++ break; |
28956 |
++ } |
28957 |
++ |
28958 |
++ printf("Closing bus connection\n"); |
28959 |
++ |
28960 |
++ return TEST_OK; |
28961 |
++} |
28962 |
+diff --git a/tools/testing/selftests/kdbus/test-endpoint.c b/tools/testing/selftests/kdbus/test-endpoint.c |
28963 |
+new file mode 100644 |
28964 |
+index 0000000..dcc6ab9 |
28965 |
+--- /dev/null |
28966 |
++++ b/tools/testing/selftests/kdbus/test-endpoint.c |
28967 |
+@@ -0,0 +1,341 @@ |
28968 |
++#include <stdio.h> |
28969 |
++#include <string.h> |
28970 |
++#include <fcntl.h> |
28971 |
++#include <stdlib.h> |
28972 |
++#include <stddef.h> |
28973 |
++#include <unistd.h> |
28974 |
++#include <stdint.h> |
28975 |
++#include <errno.h> |
28976 |
++#include <assert.h> |
28977 |
++#include <libgen.h> |
28978 |
++#include <sys/capability.h> |
28979 |
++#include <sys/wait.h> |
28980 |
++#include <stdbool.h> |
28981 |
++ |
28982 |
++#include "kdbus-api.h" |
28983 |
++#include "kdbus-util.h" |
28984 |
++#include "kdbus-enum.h" |
28985 |
++#include "kdbus-test.h" |
28986 |
++ |
28987 |
++#define KDBUS_SYSNAME_MAX_LEN 63 |
28988 |
++ |
28989 |
++static int install_name_add_match(struct kdbus_conn *conn, const char *name) |
28990 |
++{ |
28991 |
++ struct { |
28992 |
++ struct kdbus_cmd_match cmd; |
28993 |
++ struct { |
28994 |
++ uint64_t size; |
28995 |
++ uint64_t type; |
28996 |
++ struct kdbus_notify_name_change chg; |
28997 |
++ } item; |
28998 |
++ char name[64]; |
28999 |
++ } buf; |
29000 |
++ int ret; |
29001 |
++ |
29002 |
++ /* install the match rule */ |
29003 |
++ memset(&buf, 0, sizeof(buf)); |
29004 |
++ buf.item.type = KDBUS_ITEM_NAME_ADD; |
29005 |
++ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
29006 |
++ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
29007 |
++ strncpy(buf.name, name, sizeof(buf.name) - 1); |
29008 |
++ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
29009 |
++ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
29010 |
++ |
29011 |
++ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
29012 |
++ if (ret < 0) |
29013 |
++ return ret; |
29014 |
++ |
29015 |
++ return 0; |
29016 |
++} |
29017 |
++ |
29018 |
++static int create_endpoint(const char *buspath, uid_t uid, const char *name, |
29019 |
++ uint64_t flags) |
29020 |
++{ |
29021 |
++ struct { |
29022 |
++ struct kdbus_cmd cmd; |
29023 |
++ |
29024 |
++ /* name item */ |
29025 |
++ struct { |
29026 |
++ uint64_t size; |
29027 |
++ uint64_t type; |
29028 |
++ /* max should be KDBUS_SYSNAME_MAX_LEN */ |
29029 |
++ char str[128]; |
29030 |
++ } name; |
29031 |
++ } ep_make; |
29032 |
++ int fd, ret; |
29033 |
++ |
29034 |
++ fd = open(buspath, O_RDWR); |
29035 |
++ if (fd < 0) |
29036 |
++ return fd; |
29037 |
++ |
29038 |
++ memset(&ep_make, 0, sizeof(ep_make)); |
29039 |
++ |
29040 |
++ snprintf(ep_make.name.str, |
29041 |
++ /* Use the KDBUS_SYSNAME_MAX_LEN or sizeof(str) */ |
29042 |
++ KDBUS_SYSNAME_MAX_LEN > strlen(name) ? |
29043 |
++ KDBUS_SYSNAME_MAX_LEN : sizeof(ep_make.name.str), |
29044 |
++ "%u-%s", uid, name); |
29045 |
++ |
29046 |
++ ep_make.name.type = KDBUS_ITEM_MAKE_NAME; |
29047 |
++ ep_make.name.size = KDBUS_ITEM_HEADER_SIZE + |
29048 |
++ strlen(ep_make.name.str) + 1; |
29049 |
++ |
29050 |
++ ep_make.cmd.flags = flags; |
29051 |
++ ep_make.cmd.size = sizeof(ep_make.cmd) + ep_make.name.size; |
29052 |
++ |
29053 |
++ ret = kdbus_cmd_endpoint_make(fd, &ep_make.cmd); |
29054 |
++ if (ret < 0) { |
29055 |
++ kdbus_printf("error creating endpoint: %d (%m)\n", ret); |
29056 |
++ return ret; |
29057 |
++ } |
29058 |
++ |
29059 |
++ return fd; |
29060 |
++} |
29061 |
++ |
29062 |
++static int unpriv_test_custom_ep(const char *buspath) |
29063 |
++{ |
29064 |
++ int ret, ep_fd1, ep_fd2; |
29065 |
++ char *ep1, *ep2, *tmp1, *tmp2; |
29066 |
++ |
29067 |
++ tmp1 = strdup(buspath); |
29068 |
++ tmp2 = strdup(buspath); |
29069 |
++ ASSERT_RETURN(tmp1 && tmp2); |
29070 |
++ |
29071 |
++ ret = asprintf(&ep1, "%s/%u-%s", dirname(tmp1), getuid(), "apps1"); |
29072 |
++ ASSERT_RETURN(ret >= 0); |
29073 |
++ |
29074 |
++ ret = asprintf(&ep2, "%s/%u-%s", dirname(tmp2), getuid(), "apps2"); |
29075 |
++ ASSERT_RETURN(ret >= 0); |
29076 |
++ |
29077 |
++ free(tmp1); |
29078 |
++ free(tmp2); |
29079 |
++ |
29080 |
++ /* endpoint only accessible to current uid */ |
29081 |
++ ep_fd1 = create_endpoint(buspath, getuid(), "apps1", 0); |
29082 |
++ ASSERT_RETURN(ep_fd1 >= 0); |
29083 |
++ |
29084 |
++ /* endpoint world accessible */ |
29085 |
++ ep_fd2 = create_endpoint(buspath, getuid(), "apps2", |
29086 |
++ KDBUS_MAKE_ACCESS_WORLD); |
29087 |
++ ASSERT_RETURN(ep_fd2 >= 0); |
29088 |
++ |
29089 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
29090 |
++ int ep_fd; |
29091 |
++ struct kdbus_conn *ep_conn; |
29092 |
++ |
29093 |
++ /* |
29094 |
++ * Make sure that we are not able to create custom |
29095 |
++ * endpoints |
29096 |
++ */ |
29097 |
++ ep_fd = create_endpoint(buspath, getuid(), |
29098 |
++ "unpriv_costum_ep", 0); |
29099 |
++ ASSERT_EXIT(ep_fd == -EPERM); |
29100 |
++ |
29101 |
++ /* |
29102 |
++ * Endpoint "apps1" only accessible to same users, |
29103 |
++ * that own the endpoint. Access denied by VFS |
29104 |
++ */ |
29105 |
++ ep_conn = kdbus_hello(ep1, 0, NULL, 0); |
29106 |
++ ASSERT_EXIT(!ep_conn && errno == EACCES); |
29107 |
++ |
29108 |
++ /* Endpoint "apps2" world accessible */ |
29109 |
++ ep_conn = kdbus_hello(ep2, 0, NULL, 0); |
29110 |
++ ASSERT_EXIT(ep_conn); |
29111 |
++ |
29112 |
++ kdbus_conn_free(ep_conn); |
29113 |
++ |
29114 |
++ _exit(EXIT_SUCCESS); |
29115 |
++ }), |
29116 |
++ ({ 0; })); |
29117 |
++ ASSERT_RETURN(ret == 0); |
29118 |
++ |
29119 |
++ close(ep_fd1); |
29120 |
++ close(ep_fd2); |
29121 |
++ free(ep1); |
29122 |
++ free(ep2); |
29123 |
++ |
29124 |
++ return 0; |
29125 |
++} |
29126 |
++ |
29127 |
++static int update_endpoint(int fd, const char *name) |
29128 |
++{ |
29129 |
++ int len = strlen(name) + 1; |
29130 |
++ struct { |
29131 |
++ struct kdbus_cmd cmd; |
29132 |
++ |
29133 |
++ /* name item */ |
29134 |
++ struct { |
29135 |
++ uint64_t size; |
29136 |
++ uint64_t type; |
29137 |
++ char str[KDBUS_ALIGN8(len)]; |
29138 |
++ } name; |
29139 |
++ |
29140 |
++ struct { |
29141 |
++ uint64_t size; |
29142 |
++ uint64_t type; |
29143 |
++ struct kdbus_policy_access access; |
29144 |
++ } access; |
29145 |
++ } ep_update; |
29146 |
++ int ret; |
29147 |
++ |
29148 |
++ memset(&ep_update, 0, sizeof(ep_update)); |
29149 |
++ |
29150 |
++ ep_update.name.size = KDBUS_ITEM_HEADER_SIZE + len; |
29151 |
++ ep_update.name.type = KDBUS_ITEM_NAME; |
29152 |
++ strncpy(ep_update.name.str, name, sizeof(ep_update.name.str) - 1); |
29153 |
++ |
29154 |
++ ep_update.access.size = sizeof(ep_update.access); |
29155 |
++ ep_update.access.type = KDBUS_ITEM_POLICY_ACCESS; |
29156 |
++ ep_update.access.access.type = KDBUS_POLICY_ACCESS_WORLD; |
29157 |
++ ep_update.access.access.access = KDBUS_POLICY_SEE; |
29158 |
++ |
29159 |
++ ep_update.cmd.size = sizeof(ep_update); |
29160 |
++ |
29161 |
++ ret = kdbus_cmd_endpoint_update(fd, &ep_update.cmd); |
29162 |
++ if (ret < 0) { |
29163 |
++ kdbus_printf("error updating endpoint: %d (%m)\n", ret); |
29164 |
++ return ret; |
29165 |
++ } |
29166 |
++ |
29167 |
++ return 0; |
29168 |
++} |
29169 |
++ |
29170 |
++int kdbus_test_custom_endpoint(struct kdbus_test_env *env) |
29171 |
++{ |
29172 |
++ char *ep, *tmp; |
29173 |
++ int ret, ep_fd; |
29174 |
++ struct kdbus_msg *msg; |
29175 |
++ struct kdbus_conn *ep_conn; |
29176 |
++ struct kdbus_conn *reader; |
29177 |
++ const char *name = "foo.bar.baz"; |
29178 |
++ const char *epname = "foo"; |
29179 |
++ char fake_ep[KDBUS_SYSNAME_MAX_LEN + 1] = {'\0'}; |
29180 |
++ |
29181 |
++ memset(fake_ep, 'X', sizeof(fake_ep) - 1); |
29182 |
++ |
29183 |
++ /* Try to create a custom endpoint with a long name */ |
29184 |
++ ret = create_endpoint(env->buspath, getuid(), fake_ep, 0); |
29185 |
++ ASSERT_RETURN(ret == -ENAMETOOLONG); |
29186 |
++ |
29187 |
++ /* Try to create a custom endpoint with a different uid */ |
29188 |
++ ret = create_endpoint(env->buspath, getuid() + 1, "foobar", 0); |
29189 |
++ ASSERT_RETURN(ret == -EINVAL); |
29190 |
++ |
29191 |
++ /* create a custom endpoint, and open a connection on it */ |
29192 |
++ ep_fd = create_endpoint(env->buspath, getuid(), "foo", 0); |
29193 |
++ ASSERT_RETURN(ep_fd >= 0); |
29194 |
++ |
29195 |
++ tmp = strdup(env->buspath); |
29196 |
++ ASSERT_RETURN(tmp); |
29197 |
++ |
29198 |
++ ret = asprintf(&ep, "%s/%u-%s", dirname(tmp), getuid(), epname); |
29199 |
++ free(tmp); |
29200 |
++ ASSERT_RETURN(ret >= 0); |
29201 |
++ |
29202 |
++ /* Register a connection that listen to broadcasts */ |
29203 |
++ reader = kdbus_hello(ep, 0, NULL, 0); |
29204 |
++ ASSERT_RETURN(reader); |
29205 |
++ |
29206 |
++ /* Register to kernel signals */ |
29207 |
++ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, |
29208 |
++ KDBUS_MATCH_ID_ANY); |
29209 |
++ ASSERT_RETURN(ret == 0); |
29210 |
++ |
29211 |
++ ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, |
29212 |
++ KDBUS_MATCH_ID_ANY); |
29213 |
++ ASSERT_RETURN(ret == 0); |
29214 |
++ |
29215 |
++ ret = install_name_add_match(reader, name); |
29216 |
++ ASSERT_RETURN(ret == 0); |
29217 |
++ |
29218 |
++ /* Monitor connections are not supported on custom endpoints */ |
29219 |
++ ep_conn = kdbus_hello(ep, KDBUS_HELLO_MONITOR, NULL, 0); |
29220 |
++ ASSERT_RETURN(!ep_conn && errno == EOPNOTSUPP); |
29221 |
++ |
29222 |
++ ep_conn = kdbus_hello(ep, 0, NULL, 0); |
29223 |
++ ASSERT_RETURN(ep_conn); |
29224 |
++ |
29225 |
++ /* |
29226 |
++ * Add a name add match on the endpoint connection, acquire name from |
29227 |
++ * the unfiltered connection, and make sure the filtered connection |
29228 |
++ * did not get the notification on the name owner change. Also, the |
29229 |
++ * endpoint connection may not be able to call conn_info, neither on |
29230 |
++ * the name nor on the ID. |
29231 |
++ */ |
29232 |
++ ret = install_name_add_match(ep_conn, name); |
29233 |
++ ASSERT_RETURN(ret == 0); |
29234 |
++ |
29235 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
29236 |
++ ASSERT_RETURN(ret == 0); |
29237 |
++ |
29238 |
++ ret = kdbus_msg_recv(ep_conn, NULL, NULL); |
29239 |
++ ASSERT_RETURN(ret == -EAGAIN); |
29240 |
++ |
29241 |
++ ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); |
29242 |
++ ASSERT_RETURN(ret == -ESRCH); |
29243 |
++ |
29244 |
++ ret = kdbus_conn_info(ep_conn, 0, "random.crappy.name", 0, NULL); |
29245 |
++ ASSERT_RETURN(ret == -ESRCH); |
29246 |
++ |
29247 |
++ ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); |
29248 |
++ ASSERT_RETURN(ret == -ENXIO); |
29249 |
++ |
29250 |
++ ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL); |
29251 |
++ ASSERT_RETURN(ret == -ENXIO); |
29252 |
++ |
29253 |
++ /* Check that the reader did not receive anything */ |
29254 |
++ ret = kdbus_msg_recv(reader, NULL, NULL); |
29255 |
++ ASSERT_RETURN(ret == -EAGAIN); |
29256 |
++ |
29257 |
++ /* |
29258 |
++ * Release the name again, update the custom endpoint policy, |
29259 |
++ * and try again. This time, the connection on the custom endpoint |
29260 |
++ * should have gotten it. |
29261 |
++ */ |
29262 |
++ ret = kdbus_name_release(env->conn, name); |
29263 |
++ ASSERT_RETURN(ret == 0); |
29264 |
++ |
29265 |
++ ret = update_endpoint(ep_fd, name); |
29266 |
++ ASSERT_RETURN(ret == 0); |
29267 |
++ |
29268 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
29269 |
++ ASSERT_RETURN(ret == 0); |
29270 |
++ |
29271 |
++ ret = kdbus_msg_recv(ep_conn, &msg, NULL); |
29272 |
++ ASSERT_RETURN(ret == 0); |
29273 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); |
29274 |
++ ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); |
29275 |
++ ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); |
29276 |
++ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
29277 |
++ kdbus_msg_free(msg); |
29278 |
++ |
29279 |
++ ret = kdbus_msg_recv(reader, &msg, NULL); |
29280 |
++ ASSERT_RETURN(ret == 0); |
29281 |
++ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
29282 |
++ |
29283 |
++ kdbus_msg_free(msg); |
29284 |
++ |
29285 |
++ ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); |
29286 |
++ ASSERT_RETURN(ret == 0); |
29287 |
++ |
29288 |
++ ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); |
29289 |
++ ASSERT_RETURN(ret == 0); |
29290 |
++ |
29291 |
++ /* If we have privileges test custom endpoints */ |
29292 |
++ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
29293 |
++ ASSERT_RETURN(ret >= 0); |
29294 |
++ |
29295 |
++ /* |
29296 |
++ * All uids/gids are mapped and we have the necessary caps |
29297 |
++ */ |
29298 |
++ if (ret && all_uids_gids_are_mapped()) { |
29299 |
++ ret = unpriv_test_custom_ep(env->buspath); |
29300 |
++ ASSERT_RETURN(ret == 0); |
29301 |
++ } |
29302 |
++ |
29303 |
++ kdbus_conn_free(reader); |
29304 |
++ kdbus_conn_free(ep_conn); |
29305 |
++ close(ep_fd); |
29306 |
++ |
29307 |
++ return TEST_OK; |
29308 |
++} |
29309 |
+diff --git a/tools/testing/selftests/kdbus/test-fd.c b/tools/testing/selftests/kdbus/test-fd.c |
29310 |
+new file mode 100644 |
29311 |
+index 0000000..2ae0f5a |
29312 |
+--- /dev/null |
29313 |
++++ b/tools/testing/selftests/kdbus/test-fd.c |
29314 |
+@@ -0,0 +1,789 @@ |
29315 |
++#include <stdio.h> |
29316 |
++#include <string.h> |
29317 |
++#include <time.h> |
29318 |
++#include <fcntl.h> |
29319 |
++#include <stdlib.h> |
29320 |
++#include <stdbool.h> |
29321 |
++#include <stddef.h> |
29322 |
++#include <unistd.h> |
29323 |
++#include <stdint.h> |
29324 |
++#include <errno.h> |
29325 |
++#include <assert.h> |
29326 |
++#include <sys/types.h> |
29327 |
++#include <sys/mman.h> |
29328 |
++#include <sys/socket.h> |
29329 |
++#include <sys/wait.h> |
29330 |
++ |
29331 |
++#include "kdbus-api.h" |
29332 |
++#include "kdbus-test.h" |
29333 |
++#include "kdbus-util.h" |
29334 |
++#include "kdbus-enum.h" |
29335 |
++ |
29336 |
++#define KDBUS_MSG_MAX_ITEMS 128 |
29337 |
++#define KDBUS_USER_MAX_CONN 256 |
29338 |
++ |
29339 |
++/* maximum number of inflight fds in a target queue per user */ |
29340 |
++#define KDBUS_CONN_MAX_FDS_PER_USER 16 |
29341 |
++ |
29342 |
++/* maximum number of memfd items per message */ |
29343 |
++#define KDBUS_MSG_MAX_MEMFD_ITEMS 16 |
29344 |
++ |
29345 |
++static int make_msg_payload_dbus(uint64_t src_id, uint64_t dst_id, |
29346 |
++ uint64_t msg_size, |
29347 |
++ struct kdbus_msg **msg_dbus) |
29348 |
++{ |
29349 |
++ struct kdbus_msg *msg; |
29350 |
++ |
29351 |
++ msg = malloc(msg_size); |
29352 |
++ ASSERT_RETURN_VAL(msg, -ENOMEM); |
29353 |
++ |
29354 |
++ memset(msg, 0, msg_size); |
29355 |
++ msg->size = msg_size; |
29356 |
++ msg->src_id = src_id; |
29357 |
++ msg->dst_id = dst_id; |
29358 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
29359 |
++ |
29360 |
++ *msg_dbus = msg; |
29361 |
++ |
29362 |
++ return 0; |
29363 |
++} |
29364 |
++ |
29365 |
++static void make_item_memfds(struct kdbus_item *item, |
29366 |
++ int *memfds, size_t memfd_size) |
29367 |
++{ |
29368 |
++ size_t i; |
29369 |
++ |
29370 |
++ for (i = 0; i < memfd_size; i++) { |
29371 |
++ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
29372 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + |
29373 |
++ sizeof(struct kdbus_memfd); |
29374 |
++ item->memfd.fd = memfds[i]; |
29375 |
++ item->memfd.size = sizeof(uint64_t); /* const size */ |
29376 |
++ item = KDBUS_ITEM_NEXT(item); |
29377 |
++ } |
29378 |
++} |
29379 |
++ |
29380 |
++static void make_item_fds(struct kdbus_item *item, |
29381 |
++ int *fd_array, size_t fd_size) |
29382 |
++{ |
29383 |
++ size_t i; |
29384 |
++ item->type = KDBUS_ITEM_FDS; |
29385 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + (sizeof(int) * fd_size); |
29386 |
++ |
29387 |
++ for (i = 0; i < fd_size; i++) |
29388 |
++ item->fds[i] = fd_array[i]; |
29389 |
++} |
29390 |
++ |
29391 |
++static int memfd_write(const char *name, void *buf, size_t bufsize) |
29392 |
++{ |
29393 |
++ ssize_t ret; |
29394 |
++ int memfd; |
29395 |
++ |
29396 |
++ memfd = sys_memfd_create(name, 0); |
29397 |
++ ASSERT_RETURN_VAL(memfd >= 0, memfd); |
29398 |
++ |
29399 |
++ ret = write(memfd, buf, bufsize); |
29400 |
++ ASSERT_RETURN_VAL(ret == (ssize_t)bufsize, -EAGAIN); |
29401 |
++ |
29402 |
++ ret = sys_memfd_seal_set(memfd); |
29403 |
++ ASSERT_RETURN_VAL(ret == 0, -errno); |
29404 |
++ |
29405 |
++ return memfd; |
29406 |
++} |
29407 |
++ |
29408 |
++static int send_memfds(struct kdbus_conn *conn, uint64_t dst_id, |
29409 |
++ int *memfds_array, size_t memfd_count) |
29410 |
++{ |
29411 |
++ struct kdbus_cmd_send cmd = {}; |
29412 |
++ struct kdbus_item *item; |
29413 |
++ struct kdbus_msg *msg; |
29414 |
++ uint64_t size; |
29415 |
++ int ret; |
29416 |
++ |
29417 |
++ size = sizeof(struct kdbus_msg); |
29418 |
++ size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
29419 |
++ |
29420 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) |
29421 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29422 |
++ |
29423 |
++ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29424 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
29425 |
++ |
29426 |
++ item = msg->items; |
29427 |
++ |
29428 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
29429 |
++ item->type = KDBUS_ITEM_BLOOM_FILTER; |
29430 |
++ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29431 |
++ item = KDBUS_ITEM_NEXT(item); |
29432 |
++ |
29433 |
++ msg->flags |= KDBUS_MSG_SIGNAL; |
29434 |
++ } |
29435 |
++ |
29436 |
++ make_item_memfds(item, memfds_array, memfd_count); |
29437 |
++ |
29438 |
++ cmd.size = sizeof(cmd); |
29439 |
++ cmd.msg_address = (uintptr_t)msg; |
29440 |
++ |
29441 |
++ ret = kdbus_cmd_send(conn->fd, &cmd); |
29442 |
++ if (ret < 0) { |
29443 |
++ kdbus_printf("error sending message: %d (%m)\n", ret); |
29444 |
++ return ret; |
29445 |
++ } |
29446 |
++ |
29447 |
++ free(msg); |
29448 |
++ return 0; |
29449 |
++} |
29450 |
++ |
29451 |
++static int send_fds(struct kdbus_conn *conn, uint64_t dst_id, |
29452 |
++ int *fd_array, size_t fd_count) |
29453 |
++{ |
29454 |
++ struct kdbus_cmd_send cmd = {}; |
29455 |
++ struct kdbus_item *item; |
29456 |
++ struct kdbus_msg *msg; |
29457 |
++ uint64_t size; |
29458 |
++ int ret; |
29459 |
++ |
29460 |
++ size = sizeof(struct kdbus_msg); |
29461 |
++ size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count); |
29462 |
++ |
29463 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) |
29464 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29465 |
++ |
29466 |
++ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29467 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
29468 |
++ |
29469 |
++ item = msg->items; |
29470 |
++ |
29471 |
++ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
29472 |
++ item->type = KDBUS_ITEM_BLOOM_FILTER; |
29473 |
++ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29474 |
++ item = KDBUS_ITEM_NEXT(item); |
29475 |
++ |
29476 |
++ msg->flags |= KDBUS_MSG_SIGNAL; |
29477 |
++ } |
29478 |
++ |
29479 |
++ make_item_fds(item, fd_array, fd_count); |
29480 |
++ |
29481 |
++ cmd.size = sizeof(cmd); |
29482 |
++ cmd.msg_address = (uintptr_t)msg; |
29483 |
++ |
29484 |
++ ret = kdbus_cmd_send(conn->fd, &cmd); |
29485 |
++ if (ret < 0) { |
29486 |
++ kdbus_printf("error sending message: %d (%m)\n", ret); |
29487 |
++ return ret; |
29488 |
++ } |
29489 |
++ |
29490 |
++ free(msg); |
29491 |
++ return ret; |
29492 |
++} |
29493 |
++ |
29494 |
++static int send_fds_memfds(struct kdbus_conn *conn, uint64_t dst_id, |
29495 |
++ int *fds_array, size_t fd_count, |
29496 |
++ int *memfds_array, size_t memfd_count) |
29497 |
++{ |
29498 |
++ struct kdbus_cmd_send cmd = {}; |
29499 |
++ struct kdbus_item *item; |
29500 |
++ struct kdbus_msg *msg; |
29501 |
++ uint64_t size; |
29502 |
++ int ret; |
29503 |
++ |
29504 |
++ size = sizeof(struct kdbus_msg); |
29505 |
++ size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
29506 |
++ size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count); |
29507 |
++ |
29508 |
++ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29509 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
29510 |
++ |
29511 |
++ item = msg->items; |
29512 |
++ |
29513 |
++ make_item_fds(item, fds_array, fd_count); |
29514 |
++ item = KDBUS_ITEM_NEXT(item); |
29515 |
++ make_item_memfds(item, memfds_array, memfd_count); |
29516 |
++ |
29517 |
++ cmd.size = sizeof(cmd); |
29518 |
++ cmd.msg_address = (uintptr_t)msg; |
29519 |
++ |
29520 |
++ ret = kdbus_cmd_send(conn->fd, &cmd); |
29521 |
++ if (ret < 0) { |
29522 |
++ kdbus_printf("error sending message: %d (%m)\n", ret); |
29523 |
++ return ret; |
29524 |
++ } |
29525 |
++ |
29526 |
++ free(msg); |
29527 |
++ return ret; |
29528 |
++} |
29529 |
++ |
29530 |
++/* Return the number of received fds */ |
29531 |
++static unsigned int kdbus_item_get_nfds(struct kdbus_msg *msg) |
29532 |
++{ |
29533 |
++ unsigned int fds = 0; |
29534 |
++ const struct kdbus_item *item; |
29535 |
++ |
29536 |
++ KDBUS_ITEM_FOREACH(item, msg, items) { |
29537 |
++ switch (item->type) { |
29538 |
++ case KDBUS_ITEM_FDS: { |
29539 |
++ fds += (item->size - KDBUS_ITEM_HEADER_SIZE) / |
29540 |
++ sizeof(int); |
29541 |
++ break; |
29542 |
++ } |
29543 |
++ |
29544 |
++ case KDBUS_ITEM_PAYLOAD_MEMFD: |
29545 |
++ fds++; |
29546 |
++ break; |
29547 |
++ |
29548 |
++ default: |
29549 |
++ break; |
29550 |
++ } |
29551 |
++ } |
29552 |
++ |
29553 |
++ return fds; |
29554 |
++} |
29555 |
++ |
29556 |
++static struct kdbus_msg * |
29557 |
++get_kdbus_msg_with_fd(struct kdbus_conn *conn_src, |
29558 |
++ uint64_t dst_id, uint64_t cookie, int fd) |
29559 |
++{ |
29560 |
++ int ret; |
29561 |
++ uint64_t size; |
29562 |
++ struct kdbus_item *item; |
29563 |
++ struct kdbus_msg *msg; |
29564 |
++ |
29565 |
++ size = sizeof(struct kdbus_msg); |
29566 |
++ if (fd >= 0) |
29567 |
++ size += KDBUS_ITEM_SIZE(sizeof(int)); |
29568 |
++ |
29569 |
++ ret = make_msg_payload_dbus(conn_src->id, dst_id, size, &msg); |
29570 |
++ ASSERT_RETURN_VAL(ret == 0, NULL); |
29571 |
++ |
29572 |
++ msg->cookie = cookie; |
29573 |
++ |
29574 |
++ if (fd >= 0) { |
29575 |
++ item = msg->items; |
29576 |
++ |
29577 |
++ make_item_fds(item, (int *)&fd, 1); |
29578 |
++ } |
29579 |
++ |
29580 |
++ return msg; |
29581 |
++} |
29582 |
++ |
29583 |
++static int kdbus_test_no_fds(struct kdbus_test_env *env, |
29584 |
++ int *fds, int *memfd) |
29585 |
++{ |
29586 |
++ pid_t pid; |
29587 |
++ int ret, status; |
29588 |
++ uint64_t cookie; |
29589 |
++ int connfd1, connfd2; |
29590 |
++ struct kdbus_msg *msg, *msg_sync_reply; |
29591 |
++ struct kdbus_cmd_hello hello; |
29592 |
++ struct kdbus_conn *conn_src, *conn_dst, *conn_dummy; |
29593 |
++ struct kdbus_cmd_send cmd = {}; |
29594 |
++ struct kdbus_cmd_free cmd_free = {}; |
29595 |
++ |
29596 |
++ conn_src = kdbus_hello(env->buspath, 0, NULL, 0); |
29597 |
++ ASSERT_RETURN(conn_src); |
29598 |
++ |
29599 |
++ connfd1 = open(env->buspath, O_RDWR|O_CLOEXEC); |
29600 |
++ ASSERT_RETURN(connfd1 >= 0); |
29601 |
++ |
29602 |
++ connfd2 = open(env->buspath, O_RDWR|O_CLOEXEC); |
29603 |
++ ASSERT_RETURN(connfd2 >= 0); |
29604 |
++ |
29605 |
++ /* |
29606 |
++ * Create connections without KDBUS_HELLO_ACCEPT_FD |
29607 |
++ * to test if send fd operations are blocked |
29608 |
++ */ |
29609 |
++ conn_dst = malloc(sizeof(*conn_dst)); |
29610 |
++ ASSERT_RETURN(conn_dst); |
29611 |
++ |
29612 |
++ conn_dummy = malloc(sizeof(*conn_dummy)); |
29613 |
++ ASSERT_RETURN(conn_dummy); |
29614 |
++ |
29615 |
++ memset(&hello, 0, sizeof(hello)); |
29616 |
++ hello.size = sizeof(struct kdbus_cmd_hello); |
29617 |
++ hello.pool_size = POOL_SIZE; |
29618 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
29619 |
++ |
29620 |
++ ret = kdbus_cmd_hello(connfd1, &hello); |
29621 |
++ ASSERT_RETURN(ret == 0); |
29622 |
++ |
29623 |
++ cmd_free.size = sizeof(cmd_free); |
29624 |
++ cmd_free.offset = hello.offset; |
29625 |
++ ret = kdbus_cmd_free(connfd1, &cmd_free); |
29626 |
++ ASSERT_RETURN(ret >= 0); |
29627 |
++ |
29628 |
++ conn_dst->fd = connfd1; |
29629 |
++ conn_dst->id = hello.id; |
29630 |
++ |
29631 |
++ memset(&hello, 0, sizeof(hello)); |
29632 |
++ hello.size = sizeof(struct kdbus_cmd_hello); |
29633 |
++ hello.pool_size = POOL_SIZE; |
29634 |
++ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
29635 |
++ |
29636 |
++ ret = kdbus_cmd_hello(connfd2, &hello); |
29637 |
++ ASSERT_RETURN(ret == 0); |
29638 |
++ |
29639 |
++ cmd_free.size = sizeof(cmd_free); |
29640 |
++ cmd_free.offset = hello.offset; |
29641 |
++ ret = kdbus_cmd_free(connfd2, &cmd_free); |
29642 |
++ ASSERT_RETURN(ret >= 0); |
29643 |
++ |
29644 |
++ conn_dummy->fd = connfd2; |
29645 |
++ conn_dummy->id = hello.id; |
29646 |
++ |
29647 |
++ conn_dst->buf = mmap(NULL, POOL_SIZE, PROT_READ, |
29648 |
++ MAP_SHARED, connfd1, 0); |
29649 |
++ ASSERT_RETURN(conn_dst->buf != MAP_FAILED); |
29650 |
++ |
29651 |
++ conn_dummy->buf = mmap(NULL, POOL_SIZE, PROT_READ, |
29652 |
++ MAP_SHARED, connfd2, 0); |
29653 |
++ ASSERT_RETURN(conn_dummy->buf != MAP_FAILED); |
29654 |
++ |
29655 |
++ /* |
29656 |
++ * Send fds to connection that do not accept fd passing |
29657 |
++ */ |
29658 |
++ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29659 |
++ ASSERT_RETURN(ret == -ECOMM); |
29660 |
++ |
29661 |
++ /* |
29662 |
++ * memfd are kdbus payload |
29663 |
++ */ |
29664 |
++ ret = send_memfds(conn_src, conn_dst->id, memfd, 1); |
29665 |
++ ASSERT_RETURN(ret == 0); |
29666 |
++ |
29667 |
++ ret = kdbus_msg_recv_poll(conn_dst, 100, NULL, NULL); |
29668 |
++ ASSERT_RETURN(ret == 0); |
29669 |
++ |
29670 |
++ cookie = time(NULL); |
29671 |
++ |
29672 |
++ pid = fork(); |
29673 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
29674 |
++ |
29675 |
++ if (pid == 0) { |
29676 |
++ struct timespec now; |
29677 |
++ |
29678 |
++ /* |
29679 |
++ * A sync send/reply to a connection that do not |
29680 |
++ * accept fds should fail if it contains an fd |
29681 |
++ */ |
29682 |
++ msg_sync_reply = get_kdbus_msg_with_fd(conn_dst, |
29683 |
++ conn_dummy->id, |
29684 |
++ cookie, fds[0]); |
29685 |
++ ASSERT_EXIT(msg_sync_reply); |
29686 |
++ |
29687 |
++ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); |
29688 |
++ ASSERT_EXIT(ret == 0); |
29689 |
++ |
29690 |
++ msg_sync_reply->timeout_ns = now.tv_sec * 1000000000ULL + |
29691 |
++ now.tv_nsec + 100000000ULL; |
29692 |
++ msg_sync_reply->flags = KDBUS_MSG_EXPECT_REPLY; |
29693 |
++ |
29694 |
++ memset(&cmd, 0, sizeof(cmd)); |
29695 |
++ cmd.size = sizeof(cmd); |
29696 |
++ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29697 |
++ cmd.flags = KDBUS_SEND_SYNC_REPLY; |
29698 |
++ |
29699 |
++ ret = kdbus_cmd_send(conn_dst->fd, &cmd); |
29700 |
++ ASSERT_EXIT(ret == -ECOMM); |
29701 |
++ |
29702 |
++ /* |
29703 |
++ * Now send a normal message, but the sync reply |
29704 |
++ * will fail since it contains an fd that the |
29705 |
++ * original sender do not want. |
29706 |
++ * |
29707 |
++ * The original sender will fail with -ETIMEDOUT |
29708 |
++ */ |
29709 |
++ cookie++; |
29710 |
++ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
29711 |
++ KDBUS_MSG_EXPECT_REPLY, |
29712 |
++ 5000000000ULL, 0, conn_src->id, -1); |
29713 |
++ ASSERT_EXIT(ret == -EREMOTEIO); |
29714 |
++ |
29715 |
++ cookie++; |
29716 |
++ ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); |
29717 |
++ ASSERT_EXIT(ret == 0); |
29718 |
++ ASSERT_EXIT(msg->cookie == cookie); |
29719 |
++ |
29720 |
++ free(msg_sync_reply); |
29721 |
++ kdbus_msg_free(msg); |
29722 |
++ |
29723 |
++ _exit(EXIT_SUCCESS); |
29724 |
++ } |
29725 |
++ |
29726 |
++ ret = kdbus_msg_recv_poll(conn_dummy, 100, NULL, NULL); |
29727 |
++ ASSERT_RETURN(ret == -ETIMEDOUT); |
29728 |
++ |
29729 |
++ cookie++; |
29730 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
29731 |
++ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
29732 |
++ |
29733 |
++ kdbus_msg_free(msg); |
29734 |
++ |
29735 |
++ /* |
29736 |
++ * Try to reply with a kdbus connection handle, this should |
29737 |
++ * fail with -EOPNOTSUPP |
29738 |
++ */ |
29739 |
++ msg_sync_reply = get_kdbus_msg_with_fd(conn_src, |
29740 |
++ conn_dst->id, |
29741 |
++ cookie, conn_dst->fd); |
29742 |
++ ASSERT_RETURN(msg_sync_reply); |
29743 |
++ |
29744 |
++ msg_sync_reply->cookie_reply = cookie; |
29745 |
++ |
29746 |
++ memset(&cmd, 0, sizeof(cmd)); |
29747 |
++ cmd.size = sizeof(cmd); |
29748 |
++ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29749 |
++ |
29750 |
++ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
29751 |
++ ASSERT_RETURN(ret == -EOPNOTSUPP); |
29752 |
++ |
29753 |
++ free(msg_sync_reply); |
29754 |
++ |
29755 |
++ /* |
29756 |
++ * Try to reply with a normal fd, this should fail even |
29757 |
++ * if the response is a sync reply |
29758 |
++ * |
29759 |
++ * From the sender view we fail with -ECOMM |
29760 |
++ */ |
29761 |
++ msg_sync_reply = get_kdbus_msg_with_fd(conn_src, |
29762 |
++ conn_dst->id, |
29763 |
++ cookie, fds[0]); |
29764 |
++ ASSERT_RETURN(msg_sync_reply); |
29765 |
++ |
29766 |
++ msg_sync_reply->cookie_reply = cookie; |
29767 |
++ |
29768 |
++ memset(&cmd, 0, sizeof(cmd)); |
29769 |
++ cmd.size = sizeof(cmd); |
29770 |
++ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29771 |
++ |
29772 |
++ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
29773 |
++ ASSERT_RETURN(ret == -ECOMM); |
29774 |
++ |
29775 |
++ free(msg_sync_reply); |
29776 |
++ |
29777 |
++ /* |
29778 |
++ * Resend another normal message and check if the queue |
29779 |
++ * is clear |
29780 |
++ */ |
29781 |
++ cookie++; |
29782 |
++ ret = kdbus_msg_send(conn_src, NULL, cookie, 0, 0, 0, |
29783 |
++ conn_dst->id); |
29784 |
++ ASSERT_RETURN(ret == 0); |
29785 |
++ |
29786 |
++ ret = waitpid(pid, &status, 0); |
29787 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
29788 |
++ |
29789 |
++ kdbus_conn_free(conn_dummy); |
29790 |
++ kdbus_conn_free(conn_dst); |
29791 |
++ kdbus_conn_free(conn_src); |
29792 |
++ |
29793 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
29794 |
++} |
29795 |
++ |
29796 |
++static int kdbus_send_multiple_fds(struct kdbus_conn *conn_src, |
29797 |
++ struct kdbus_conn *conn_dst) |
29798 |
++{ |
29799 |
++ int ret, i; |
29800 |
++ unsigned int nfds; |
29801 |
++ int fds[KDBUS_CONN_MAX_FDS_PER_USER + 1]; |
29802 |
++ int memfds[KDBUS_MSG_MAX_ITEMS + 1]; |
29803 |
++ struct kdbus_msg *msg; |
29804 |
++ uint64_t dummy_value; |
29805 |
++ |
29806 |
++ dummy_value = time(NULL); |
29807 |
++ |
29808 |
++ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) { |
29809 |
++ fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC); |
29810 |
++ ASSERT_RETURN_VAL(fds[i] >= 0, -errno); |
29811 |
++ } |
29812 |
++ |
29813 |
++ /* Send KDBUS_CONN_MAX_FDS_PER_USER with one more fd */ |
29814 |
++ ret = send_fds(conn_src, conn_dst->id, fds, |
29815 |
++ KDBUS_CONN_MAX_FDS_PER_USER + 1); |
29816 |
++ ASSERT_RETURN(ret == -EMFILE); |
29817 |
++ |
29818 |
++ /* Retry with the correct KDBUS_CONN_MAX_FDS_PER_USER */ |
29819 |
++ ret = send_fds(conn_src, conn_dst->id, fds, |
29820 |
++ KDBUS_CONN_MAX_FDS_PER_USER); |
29821 |
++ ASSERT_RETURN(ret == 0); |
29822 |
++ |
29823 |
++ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29824 |
++ ASSERT_RETURN(ret == 0); |
29825 |
++ |
29826 |
++ /* Check we got the right number of fds */ |
29827 |
++ nfds = kdbus_item_get_nfds(msg); |
29828 |
++ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER); |
29829 |
++ |
29830 |
++ kdbus_msg_free(msg); |
29831 |
++ |
29832 |
++ for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++, dummy_value++) { |
29833 |
++ memfds[i] = memfd_write("memfd-name", |
29834 |
++ &dummy_value, |
29835 |
++ sizeof(dummy_value)); |
29836 |
++ ASSERT_RETURN_VAL(memfds[i] >= 0, memfds[i]); |
29837 |
++ } |
29838 |
++ |
29839 |
++ /* Send KDBUS_MSG_MAX_ITEMS with one more memfd */ |
29840 |
++ ret = send_memfds(conn_src, conn_dst->id, |
29841 |
++ memfds, KDBUS_MSG_MAX_ITEMS + 1); |
29842 |
++ ASSERT_RETURN(ret == -E2BIG); |
29843 |
++ |
29844 |
++ ret = send_memfds(conn_src, conn_dst->id, |
29845 |
++ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1); |
29846 |
++ ASSERT_RETURN(ret == -E2BIG); |
29847 |
++ |
29848 |
++ /* Retry with the correct KDBUS_MSG_MAX_ITEMS */ |
29849 |
++ ret = send_memfds(conn_src, conn_dst->id, |
29850 |
++ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29851 |
++ ASSERT_RETURN(ret == 0); |
29852 |
++ |
29853 |
++ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29854 |
++ ASSERT_RETURN(ret == 0); |
29855 |
++ |
29856 |
++ /* Check we got the right number of fds */ |
29857 |
++ nfds = kdbus_item_get_nfds(msg); |
29858 |
++ ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS); |
29859 |
++ |
29860 |
++ kdbus_msg_free(msg); |
29861 |
++ |
29862 |
++ |
29863 |
++ /* |
29864 |
++ * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER+1 fds and |
29865 |
++ * 10 memfds |
29866 |
++ */ |
29867 |
++ ret = send_fds_memfds(conn_src, conn_dst->id, |
29868 |
++ fds, KDBUS_CONN_MAX_FDS_PER_USER + 1, |
29869 |
++ memfds, 10); |
29870 |
++ ASSERT_RETURN(ret == -EMFILE); |
29871 |
++ |
29872 |
++ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29873 |
++ ASSERT_RETURN(ret == -EAGAIN); |
29874 |
++ |
29875 |
++ /* |
29876 |
++ * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER fds and |
29877 |
++ * (128 - 1) + 1 memfds, all fds take one item, while each |
29878 |
++ * memfd takes one item |
29879 |
++ */ |
29880 |
++ ret = send_fds_memfds(conn_src, conn_dst->id, |
29881 |
++ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29882 |
++ memfds, (KDBUS_MSG_MAX_ITEMS - 1) + 1); |
29883 |
++ ASSERT_RETURN(ret == -E2BIG); |
29884 |
++ |
29885 |
++ ret = send_fds_memfds(conn_src, conn_dst->id, |
29886 |
++ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29887 |
++ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1); |
29888 |
++ ASSERT_RETURN(ret == -E2BIG); |
29889 |
++ |
29890 |
++ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29891 |
++ ASSERT_RETURN(ret == -EAGAIN); |
29892 |
++ |
29893 |
++ /* |
29894 |
++ * Send KDBUS_CONN_MAX_FDS_PER_USER fds + |
29895 |
++ * KDBUS_MSG_MAX_MEMFD_ITEMS memfds |
29896 |
++ */ |
29897 |
++ ret = send_fds_memfds(conn_src, conn_dst->id, |
29898 |
++ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29899 |
++ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29900 |
++ ASSERT_RETURN(ret == 0); |
29901 |
++ |
29902 |
++ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29903 |
++ ASSERT_RETURN(ret == 0); |
29904 |
++ |
29905 |
++ /* Check we got the right number of fds */ |
29906 |
++ nfds = kdbus_item_get_nfds(msg); |
29907 |
++ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER + |
29908 |
++ KDBUS_MSG_MAX_MEMFD_ITEMS); |
29909 |
++ |
29910 |
++ kdbus_msg_free(msg); |
29911 |
++ |
29912 |
++ |
29913 |
++ /* |
29914 |
++ * Re-send fds + memfds, close them, but do not receive them |
29915 |
++ * and try to queue more |
29916 |
++ */ |
29917 |
++ ret = send_fds_memfds(conn_src, conn_dst->id, |
29918 |
++ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29919 |
++ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29920 |
++ ASSERT_RETURN(ret == 0); |
29921 |
++ |
29922 |
++ /* close old references and get a new ones */ |
29923 |
++ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) { |
29924 |
++ close(fds[i]); |
29925 |
++ fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC); |
29926 |
++ ASSERT_RETURN_VAL(fds[i] >= 0, -errno); |
29927 |
++ } |
29928 |
++ |
29929 |
++ /* should fail since we have already fds in the queue */ |
29930 |
++ ret = send_fds(conn_src, conn_dst->id, fds, |
29931 |
++ KDBUS_CONN_MAX_FDS_PER_USER); |
29932 |
++ ASSERT_RETURN(ret == -EMFILE); |
29933 |
++ |
29934 |
++ /* This should succeed */ |
29935 |
++ ret = send_memfds(conn_src, conn_dst->id, |
29936 |
++ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29937 |
++ ASSERT_RETURN(ret == 0); |
29938 |
++ |
29939 |
++ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29940 |
++ ASSERT_RETURN(ret == 0); |
29941 |
++ |
29942 |
++ nfds = kdbus_item_get_nfds(msg); |
29943 |
++ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER + |
29944 |
++ KDBUS_MSG_MAX_MEMFD_ITEMS); |
29945 |
++ |
29946 |
++ kdbus_msg_free(msg); |
29947 |
++ |
29948 |
++ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29949 |
++ ASSERT_RETURN(ret == 0); |
29950 |
++ |
29951 |
++ nfds = kdbus_item_get_nfds(msg); |
29952 |
++ ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS); |
29953 |
++ |
29954 |
++ kdbus_msg_free(msg); |
29955 |
++ |
29956 |
++ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29957 |
++ ASSERT_RETURN(ret == -EAGAIN); |
29958 |
++ |
29959 |
++ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) |
29960 |
++ close(fds[i]); |
29961 |
++ |
29962 |
++ for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++) |
29963 |
++ close(memfds[i]); |
29964 |
++ |
29965 |
++ return 0; |
29966 |
++} |
29967 |
++ |
29968 |
++int kdbus_test_fd_passing(struct kdbus_test_env *env) |
29969 |
++{ |
29970 |
++ struct kdbus_conn *conn_src, *conn_dst; |
29971 |
++ const char *str = "stackenblocken"; |
29972 |
++ const struct kdbus_item *item; |
29973 |
++ struct kdbus_msg *msg; |
29974 |
++ unsigned int i; |
29975 |
++ uint64_t now; |
29976 |
++ int fds_conn[2]; |
29977 |
++ int sock_pair[2]; |
29978 |
++ int fds[2]; |
29979 |
++ int memfd; |
29980 |
++ int ret; |
29981 |
++ |
29982 |
++ now = (uint64_t) time(NULL); |
29983 |
++ |
29984 |
++ /* create two connections */ |
29985 |
++ conn_src = kdbus_hello(env->buspath, 0, NULL, 0); |
29986 |
++ conn_dst = kdbus_hello(env->buspath, 0, NULL, 0); |
29987 |
++ ASSERT_RETURN(conn_src && conn_dst); |
29988 |
++ |
29989 |
++ fds_conn[0] = conn_src->fd; |
29990 |
++ fds_conn[1] = conn_dst->fd; |
29991 |
++ |
29992 |
++ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair); |
29993 |
++ ASSERT_RETURN(ret == 0); |
29994 |
++ |
29995 |
++ /* Setup memfd */ |
29996 |
++ memfd = memfd_write("memfd-name", &now, sizeof(now)); |
29997 |
++ ASSERT_RETURN(memfd >= 0); |
29998 |
++ |
29999 |
++ /* Setup pipes */ |
30000 |
++ ret = pipe(fds); |
30001 |
++ ASSERT_RETURN(ret == 0); |
30002 |
++ |
30003 |
++ i = write(fds[1], str, strlen(str)); |
30004 |
++ ASSERT_RETURN(i == strlen(str)); |
30005 |
++ |
30006 |
++ /* |
30007 |
++ * Try to ass the handle of a connection as message payload. |
30008 |
++ * This must fail. |
30009 |
++ */ |
30010 |
++ ret = send_fds(conn_src, conn_dst->id, fds_conn, 2); |
30011 |
++ ASSERT_RETURN(ret == -ENOTSUP); |
30012 |
++ |
30013 |
++ ret = send_fds(conn_dst, conn_src->id, fds_conn, 2); |
30014 |
++ ASSERT_RETURN(ret == -ENOTSUP); |
30015 |
++ |
30016 |
++ ret = send_fds(conn_src, conn_dst->id, sock_pair, 2); |
30017 |
++ ASSERT_RETURN(ret == -ENOTSUP); |
30018 |
++ |
30019 |
++ /* |
30020 |
++ * Send fds and memfds to connection that do not accept fds |
30021 |
++ */ |
30022 |
++ ret = kdbus_test_no_fds(env, fds, (int *)&memfd); |
30023 |
++ ASSERT_RETURN(ret == 0); |
30024 |
++ |
30025 |
++ /* Try to broadcast file descriptors. This must fail. */ |
30026 |
++ ret = send_fds(conn_src, KDBUS_DST_ID_BROADCAST, fds, 1); |
30027 |
++ ASSERT_RETURN(ret == -ENOTUNIQ); |
30028 |
++ |
30029 |
++ /* Try to broadcast memfd. This must succeed. */ |
30030 |
++ ret = send_memfds(conn_src, KDBUS_DST_ID_BROADCAST, (int *)&memfd, 1); |
30031 |
++ ASSERT_RETURN(ret == 0); |
30032 |
++ |
30033 |
++ /* Open code this loop */ |
30034 |
++loop_send_fds: |
30035 |
++ |
30036 |
++ /* |
30037 |
++ * Send the read end of the pipe and close it. |
30038 |
++ */ |
30039 |
++ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
30040 |
++ ASSERT_RETURN(ret == 0); |
30041 |
++ close(fds[0]); |
30042 |
++ |
30043 |
++ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
30044 |
++ ASSERT_RETURN(ret == 0); |
30045 |
++ |
30046 |
++ KDBUS_ITEM_FOREACH(item, msg, items) { |
30047 |
++ if (item->type == KDBUS_ITEM_FDS) { |
30048 |
++ char tmp[14]; |
30049 |
++ int nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
30050 |
++ sizeof(int); |
30051 |
++ ASSERT_RETURN(nfds == 1); |
30052 |
++ |
30053 |
++ i = read(item->fds[0], tmp, sizeof(tmp)); |
30054 |
++ if (i != 0) { |
30055 |
++ ASSERT_RETURN(i == sizeof(tmp)); |
30056 |
++ ASSERT_RETURN(memcmp(tmp, str, sizeof(tmp)) == 0); |
30057 |
++ |
30058 |
++ /* Write EOF */ |
30059 |
++ close(fds[1]); |
30060 |
++ |
30061 |
++ /* |
30062 |
++ * Resend the read end of the pipe, |
30063 |
++ * the receiver still holds a reference |
30064 |
++ * to it... |
30065 |
++ */ |
30066 |
++ goto loop_send_fds; |
30067 |
++ } |
30068 |
++ |
30069 |
++ /* Got EOF */ |
30070 |
++ |
30071 |
++ /* |
30072 |
++ * Close the last reference to the read end |
30073 |
++ * of the pipe, other references are |
30074 |
++ * automatically closed just after send. |
30075 |
++ */ |
30076 |
++ close(item->fds[0]); |
30077 |
++ } |
30078 |
++ } |
30079 |
++ |
30080 |
++ /* |
30081 |
++ * Try to resend the read end of the pipe. Must fail with |
30082 |
++ * -EBADF since both the sender and receiver closed their |
30083 |
++ * references to it. We assume the above since sender and |
30084 |
++ * receiver are on the same process. |
30085 |
++ */ |
30086 |
++ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
30087 |
++ ASSERT_RETURN(ret == -EBADF); |
30088 |
++ |
30089 |
++ /* Then we clear out received any data... */ |
30090 |
++ kdbus_msg_free(msg); |
30091 |
++ |
30092 |
++ ret = kdbus_send_multiple_fds(conn_src, conn_dst); |
30093 |
++ ASSERT_RETURN(ret == 0); |
30094 |
++ |
30095 |
++ close(sock_pair[0]); |
30096 |
++ close(sock_pair[1]); |
30097 |
++ close(memfd); |
30098 |
++ |
30099 |
++ kdbus_conn_free(conn_src); |
30100 |
++ kdbus_conn_free(conn_dst); |
30101 |
++ |
30102 |
++ return TEST_OK; |
30103 |
++} |
30104 |
+diff --git a/tools/testing/selftests/kdbus/test-free.c b/tools/testing/selftests/kdbus/test-free.c |
30105 |
+new file mode 100644 |
30106 |
+index 0000000..f666da3 |
30107 |
+--- /dev/null |
30108 |
++++ b/tools/testing/selftests/kdbus/test-free.c |
30109 |
+@@ -0,0 +1,64 @@ |
30110 |
++#include <stdio.h> |
30111 |
++#include <string.h> |
30112 |
++#include <fcntl.h> |
30113 |
++#include <stdlib.h> |
30114 |
++#include <stddef.h> |
30115 |
++#include <unistd.h> |
30116 |
++#include <stdint.h> |
30117 |
++#include <errno.h> |
30118 |
++#include <assert.h> |
30119 |
++#include <stdbool.h> |
30120 |
++ |
30121 |
++#include "kdbus-api.h" |
30122 |
++#include "kdbus-util.h" |
30123 |
++#include "kdbus-enum.h" |
30124 |
++#include "kdbus-test.h" |
30125 |
++ |
30126 |
++static int sample_ioctl_call(struct kdbus_test_env *env) |
30127 |
++{ |
30128 |
++ int ret; |
30129 |
++ struct kdbus_cmd_list cmd_list = { |
30130 |
++ .flags = KDBUS_LIST_QUEUED, |
30131 |
++ .size = sizeof(cmd_list), |
30132 |
++ }; |
30133 |
++ |
30134 |
++ ret = kdbus_cmd_list(env->conn->fd, &cmd_list); |
30135 |
++ ASSERT_RETURN(ret == 0); |
30136 |
++ |
30137 |
++ /* DON'T FREE THIS SLICE OF MEMORY! */ |
30138 |
++ |
30139 |
++ return TEST_OK; |
30140 |
++} |
30141 |
++ |
30142 |
++int kdbus_test_free(struct kdbus_test_env *env) |
30143 |
++{ |
30144 |
++ int ret; |
30145 |
++ struct kdbus_cmd_free cmd_free = {}; |
30146 |
++ |
30147 |
++ /* free an unallocated buffer */ |
30148 |
++ cmd_free.size = sizeof(cmd_free); |
30149 |
++ cmd_free.flags = 0; |
30150 |
++ cmd_free.offset = 0; |
30151 |
++ ret = kdbus_cmd_free(env->conn->fd, &cmd_free); |
30152 |
++ ASSERT_RETURN(ret == -ENXIO); |
30153 |
++ |
30154 |
++ /* free a buffer out of the pool's bounds */ |
30155 |
++ cmd_free.size = sizeof(cmd_free); |
30156 |
++ cmd_free.offset = POOL_SIZE + 1; |
30157 |
++ ret = kdbus_cmd_free(env->conn->fd, &cmd_free); |
30158 |
++ ASSERT_RETURN(ret == -ENXIO); |
30159 |
++ |
30160 |
++ /* |
30161 |
++ * The user application is responsible for freeing the allocated |
30162 |
++ * memory with the KDBUS_CMD_FREE ioctl, so let's test what happens |
30163 |
++ * if we forget about it. |
30164 |
++ */ |
30165 |
++ |
30166 |
++ ret = sample_ioctl_call(env); |
30167 |
++ ASSERT_RETURN(ret == 0); |
30168 |
++ |
30169 |
++ ret = sample_ioctl_call(env); |
30170 |
++ ASSERT_RETURN(ret == 0); |
30171 |
++ |
30172 |
++ return TEST_OK; |
30173 |
++} |
30174 |
+diff --git a/tools/testing/selftests/kdbus/test-match.c b/tools/testing/selftests/kdbus/test-match.c |
30175 |
+new file mode 100644 |
30176 |
+index 0000000..2360dc1 |
30177 |
+--- /dev/null |
30178 |
++++ b/tools/testing/selftests/kdbus/test-match.c |
30179 |
+@@ -0,0 +1,441 @@ |
30180 |
++#include <stdio.h> |
30181 |
++#include <string.h> |
30182 |
++#include <fcntl.h> |
30183 |
++#include <stdlib.h> |
30184 |
++#include <stddef.h> |
30185 |
++#include <unistd.h> |
30186 |
++#include <stdint.h> |
30187 |
++#include <errno.h> |
30188 |
++#include <assert.h> |
30189 |
++#include <stdbool.h> |
30190 |
++ |
30191 |
++#include "kdbus-api.h" |
30192 |
++#include "kdbus-util.h" |
30193 |
++#include "kdbus-enum.h" |
30194 |
++#include "kdbus-test.h" |
30195 |
++ |
30196 |
++int kdbus_test_match_id_add(struct kdbus_test_env *env) |
30197 |
++{ |
30198 |
++ struct { |
30199 |
++ struct kdbus_cmd_match cmd; |
30200 |
++ struct { |
30201 |
++ uint64_t size; |
30202 |
++ uint64_t type; |
30203 |
++ struct kdbus_notify_id_change chg; |
30204 |
++ } item; |
30205 |
++ } buf; |
30206 |
++ struct kdbus_conn *conn; |
30207 |
++ struct kdbus_msg *msg; |
30208 |
++ int ret; |
30209 |
++ |
30210 |
++ memset(&buf, 0, sizeof(buf)); |
30211 |
++ |
30212 |
++ buf.cmd.size = sizeof(buf); |
30213 |
++ buf.cmd.cookie = 0xdeafbeefdeaddead; |
30214 |
++ buf.item.size = sizeof(buf.item); |
30215 |
++ buf.item.type = KDBUS_ITEM_ID_ADD; |
30216 |
++ buf.item.chg.id = KDBUS_MATCH_ID_ANY; |
30217 |
++ |
30218 |
++ /* match on id add */ |
30219 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30220 |
++ ASSERT_RETURN(ret == 0); |
30221 |
++ |
30222 |
++ /* create 2nd connection */ |
30223 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30224 |
++ ASSERT_RETURN(conn != NULL); |
30225 |
++ |
30226 |
++ /* 1st connection should have received a notification */ |
30227 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30228 |
++ ASSERT_RETURN(ret == 0); |
30229 |
++ |
30230 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD); |
30231 |
++ ASSERT_RETURN(msg->items[0].id_change.id == conn->id); |
30232 |
++ |
30233 |
++ kdbus_conn_free(conn); |
30234 |
++ |
30235 |
++ return TEST_OK; |
30236 |
++} |
30237 |
++ |
30238 |
++int kdbus_test_match_id_remove(struct kdbus_test_env *env) |
30239 |
++{ |
30240 |
++ struct { |
30241 |
++ struct kdbus_cmd_match cmd; |
30242 |
++ struct { |
30243 |
++ uint64_t size; |
30244 |
++ uint64_t type; |
30245 |
++ struct kdbus_notify_id_change chg; |
30246 |
++ } item; |
30247 |
++ } buf; |
30248 |
++ struct kdbus_conn *conn; |
30249 |
++ struct kdbus_msg *msg; |
30250 |
++ size_t id; |
30251 |
++ int ret; |
30252 |
++ |
30253 |
++ /* create 2nd connection */ |
30254 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30255 |
++ ASSERT_RETURN(conn != NULL); |
30256 |
++ id = conn->id; |
30257 |
++ |
30258 |
++ memset(&buf, 0, sizeof(buf)); |
30259 |
++ buf.cmd.size = sizeof(buf); |
30260 |
++ buf.cmd.cookie = 0xdeafbeefdeaddead; |
30261 |
++ buf.item.size = sizeof(buf.item); |
30262 |
++ buf.item.type = KDBUS_ITEM_ID_REMOVE; |
30263 |
++ buf.item.chg.id = id; |
30264 |
++ |
30265 |
++ /* register match on 2nd connection */ |
30266 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30267 |
++ ASSERT_RETURN(ret == 0); |
30268 |
++ |
30269 |
++ /* remove 2nd connection again */ |
30270 |
++ kdbus_conn_free(conn); |
30271 |
++ |
30272 |
++ /* 1st connection should have received a notification */ |
30273 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30274 |
++ ASSERT_RETURN(ret == 0); |
30275 |
++ |
30276 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE); |
30277 |
++ ASSERT_RETURN(msg->items[0].id_change.id == id); |
30278 |
++ |
30279 |
++ return TEST_OK; |
30280 |
++} |
30281 |
++ |
30282 |
++int kdbus_test_match_replace(struct kdbus_test_env *env) |
30283 |
++{ |
30284 |
++ struct { |
30285 |
++ struct kdbus_cmd_match cmd; |
30286 |
++ struct { |
30287 |
++ uint64_t size; |
30288 |
++ uint64_t type; |
30289 |
++ struct kdbus_notify_id_change chg; |
30290 |
++ } item; |
30291 |
++ } buf; |
30292 |
++ struct kdbus_conn *conn; |
30293 |
++ struct kdbus_msg *msg; |
30294 |
++ size_t id; |
30295 |
++ int ret; |
30296 |
++ |
30297 |
++ /* add a match to id_add */ |
30298 |
++ ASSERT_RETURN(kdbus_test_match_id_add(env) == TEST_OK); |
30299 |
++ |
30300 |
++ /* do a replace of the match from id_add to id_remove */ |
30301 |
++ memset(&buf, 0, sizeof(buf)); |
30302 |
++ |
30303 |
++ buf.cmd.size = sizeof(buf); |
30304 |
++ buf.cmd.cookie = 0xdeafbeefdeaddead; |
30305 |
++ buf.cmd.flags = KDBUS_MATCH_REPLACE; |
30306 |
++ buf.item.size = sizeof(buf.item); |
30307 |
++ buf.item.type = KDBUS_ITEM_ID_REMOVE; |
30308 |
++ buf.item.chg.id = KDBUS_MATCH_ID_ANY; |
30309 |
++ |
30310 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30311 |
++ |
30312 |
++ /* create 2nd connection */ |
30313 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30314 |
++ ASSERT_RETURN(conn != NULL); |
30315 |
++ id = conn->id; |
30316 |
++ |
30317 |
++ /* 1st connection should _not_ have received a notification */ |
30318 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30319 |
++ ASSERT_RETURN(ret != 0); |
30320 |
++ |
30321 |
++ /* remove 2nd connection */ |
30322 |
++ kdbus_conn_free(conn); |
30323 |
++ |
30324 |
++ /* 1st connection should _now_ have received a notification */ |
30325 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30326 |
++ ASSERT_RETURN(ret == 0); |
30327 |
++ |
30328 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE); |
30329 |
++ ASSERT_RETURN(msg->items[0].id_change.id == id); |
30330 |
++ |
30331 |
++ return TEST_OK; |
30332 |
++} |
30333 |
++ |
30334 |
++int kdbus_test_match_name_add(struct kdbus_test_env *env) |
30335 |
++{ |
30336 |
++ struct { |
30337 |
++ struct kdbus_cmd_match cmd; |
30338 |
++ struct { |
30339 |
++ uint64_t size; |
30340 |
++ uint64_t type; |
30341 |
++ struct kdbus_notify_name_change chg; |
30342 |
++ } item; |
30343 |
++ char name[64]; |
30344 |
++ } buf; |
30345 |
++ struct kdbus_msg *msg; |
30346 |
++ char *name; |
30347 |
++ int ret; |
30348 |
++ |
30349 |
++ name = "foo.bla.blaz"; |
30350 |
++ |
30351 |
++ /* install the match rule */ |
30352 |
++ memset(&buf, 0, sizeof(buf)); |
30353 |
++ buf.item.type = KDBUS_ITEM_NAME_ADD; |
30354 |
++ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
30355 |
++ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
30356 |
++ strncpy(buf.name, name, sizeof(buf.name) - 1); |
30357 |
++ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
30358 |
++ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
30359 |
++ |
30360 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30361 |
++ ASSERT_RETURN(ret == 0); |
30362 |
++ |
30363 |
++ /* acquire the name */ |
30364 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
30365 |
++ ASSERT_RETURN(ret == 0); |
30366 |
++ |
30367 |
++ /* we should have received a notification */ |
30368 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30369 |
++ ASSERT_RETURN(ret == 0); |
30370 |
++ |
30371 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); |
30372 |
++ ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); |
30373 |
++ ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); |
30374 |
++ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
30375 |
++ |
30376 |
++ return TEST_OK; |
30377 |
++} |
30378 |
++ |
30379 |
++int kdbus_test_match_name_remove(struct kdbus_test_env *env) |
30380 |
++{ |
30381 |
++ struct { |
30382 |
++ struct kdbus_cmd_match cmd; |
30383 |
++ struct { |
30384 |
++ uint64_t size; |
30385 |
++ uint64_t type; |
30386 |
++ struct kdbus_notify_name_change chg; |
30387 |
++ } item; |
30388 |
++ char name[64]; |
30389 |
++ } buf; |
30390 |
++ struct kdbus_msg *msg; |
30391 |
++ char *name; |
30392 |
++ int ret; |
30393 |
++ |
30394 |
++ name = "foo.bla.blaz"; |
30395 |
++ |
30396 |
++ /* acquire the name */ |
30397 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
30398 |
++ ASSERT_RETURN(ret == 0); |
30399 |
++ |
30400 |
++ /* install the match rule */ |
30401 |
++ memset(&buf, 0, sizeof(buf)); |
30402 |
++ buf.item.type = KDBUS_ITEM_NAME_REMOVE; |
30403 |
++ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
30404 |
++ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
30405 |
++ strncpy(buf.name, name, sizeof(buf.name) - 1); |
30406 |
++ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
30407 |
++ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
30408 |
++ |
30409 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30410 |
++ ASSERT_RETURN(ret == 0); |
30411 |
++ |
30412 |
++ /* release the name again */ |
30413 |
++ kdbus_name_release(env->conn, name); |
30414 |
++ ASSERT_RETURN(ret == 0); |
30415 |
++ |
30416 |
++ /* we should have received a notification */ |
30417 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30418 |
++ ASSERT_RETURN(ret == 0); |
30419 |
++ |
30420 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_REMOVE); |
30421 |
++ ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id); |
30422 |
++ ASSERT_RETURN(msg->items[0].name_change.new_id.id == 0); |
30423 |
++ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
30424 |
++ |
30425 |
++ return TEST_OK; |
30426 |
++} |
30427 |
++ |
30428 |
++int kdbus_test_match_name_change(struct kdbus_test_env *env) |
30429 |
++{ |
30430 |
++ struct { |
30431 |
++ struct kdbus_cmd_match cmd; |
30432 |
++ struct { |
30433 |
++ uint64_t size; |
30434 |
++ uint64_t type; |
30435 |
++ struct kdbus_notify_name_change chg; |
30436 |
++ } item; |
30437 |
++ char name[64]; |
30438 |
++ } buf; |
30439 |
++ struct kdbus_conn *conn; |
30440 |
++ struct kdbus_msg *msg; |
30441 |
++ uint64_t flags; |
30442 |
++ char *name = "foo.bla.baz"; |
30443 |
++ int ret; |
30444 |
++ |
30445 |
++ /* acquire the name */ |
30446 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
30447 |
++ ASSERT_RETURN(ret == 0); |
30448 |
++ |
30449 |
++ /* install the match rule */ |
30450 |
++ memset(&buf, 0, sizeof(buf)); |
30451 |
++ buf.item.type = KDBUS_ITEM_NAME_CHANGE; |
30452 |
++ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
30453 |
++ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
30454 |
++ strncpy(buf.name, name, sizeof(buf.name) - 1); |
30455 |
++ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
30456 |
++ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
30457 |
++ |
30458 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30459 |
++ ASSERT_RETURN(ret == 0); |
30460 |
++ |
30461 |
++ /* create a 2nd connection */ |
30462 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30463 |
++ ASSERT_RETURN(conn != NULL); |
30464 |
++ |
30465 |
++ /* allow the new connection to own the same name */ |
30466 |
++ /* queue the 2nd connection as waiting owner */ |
30467 |
++ flags = KDBUS_NAME_QUEUE; |
30468 |
++ ret = kdbus_name_acquire(conn, name, &flags); |
30469 |
++ ASSERT_RETURN(ret == 0); |
30470 |
++ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); |
30471 |
++ |
30472 |
++ /* release name from 1st connection */ |
30473 |
++ ret = kdbus_name_release(env->conn, name); |
30474 |
++ ASSERT_RETURN(ret == 0); |
30475 |
++ |
30476 |
++ /* we should have received a notification */ |
30477 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30478 |
++ ASSERT_RETURN(ret == 0); |
30479 |
++ |
30480 |
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_CHANGE); |
30481 |
++ ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id); |
30482 |
++ ASSERT_RETURN(msg->items[0].name_change.new_id.id == conn->id); |
30483 |
++ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
30484 |
++ |
30485 |
++ kdbus_conn_free(conn); |
30486 |
++ |
30487 |
++ return TEST_OK; |
30488 |
++} |
30489 |
++ |
30490 |
++static int send_bloom_filter(const struct kdbus_conn *conn, |
30491 |
++ uint64_t cookie, |
30492 |
++ const uint8_t *filter, |
30493 |
++ size_t filter_size, |
30494 |
++ uint64_t filter_generation) |
30495 |
++{ |
30496 |
++ struct kdbus_cmd_send cmd = {}; |
30497 |
++ struct kdbus_msg *msg; |
30498 |
++ struct kdbus_item *item; |
30499 |
++ uint64_t size; |
30500 |
++ int ret; |
30501 |
++ |
30502 |
++ size = sizeof(struct kdbus_msg); |
30503 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + filter_size; |
30504 |
++ |
30505 |
++ msg = alloca(size); |
30506 |
++ |
30507 |
++ memset(msg, 0, size); |
30508 |
++ msg->size = size; |
30509 |
++ msg->src_id = conn->id; |
30510 |
++ msg->dst_id = KDBUS_DST_ID_BROADCAST; |
30511 |
++ msg->flags = KDBUS_MSG_SIGNAL; |
30512 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30513 |
++ msg->cookie = cookie; |
30514 |
++ |
30515 |
++ item = msg->items; |
30516 |
++ item->type = KDBUS_ITEM_BLOOM_FILTER; |
30517 |
++ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + |
30518 |
++ filter_size; |
30519 |
++ |
30520 |
++ item->bloom_filter.generation = filter_generation; |
30521 |
++ memcpy(item->bloom_filter.data, filter, filter_size); |
30522 |
++ |
30523 |
++ cmd.size = sizeof(cmd); |
30524 |
++ cmd.msg_address = (uintptr_t)msg; |
30525 |
++ |
30526 |
++ ret = kdbus_cmd_send(conn->fd, &cmd); |
30527 |
++ if (ret < 0) { |
30528 |
++ kdbus_printf("error sending message: %d (%m)\n", ret); |
30529 |
++ return ret; |
30530 |
++ } |
30531 |
++ |
30532 |
++ return 0; |
30533 |
++} |
30534 |
++ |
30535 |
++int kdbus_test_match_bloom(struct kdbus_test_env *env) |
30536 |
++{ |
30537 |
++ struct { |
30538 |
++ struct kdbus_cmd_match cmd; |
30539 |
++ struct { |
30540 |
++ uint64_t size; |
30541 |
++ uint64_t type; |
30542 |
++ uint8_t data_gen0[64]; |
30543 |
++ uint8_t data_gen1[64]; |
30544 |
++ } item; |
30545 |
++ } buf; |
30546 |
++ struct kdbus_conn *conn; |
30547 |
++ struct kdbus_msg *msg; |
30548 |
++ uint64_t cookie = 0xf000f00f; |
30549 |
++ uint8_t filter[64]; |
30550 |
++ int ret; |
30551 |
++ |
30552 |
++ /* install the match rule */ |
30553 |
++ memset(&buf, 0, sizeof(buf)); |
30554 |
++ buf.cmd.size = sizeof(buf); |
30555 |
++ |
30556 |
++ buf.item.size = sizeof(buf.item); |
30557 |
++ buf.item.type = KDBUS_ITEM_BLOOM_MASK; |
30558 |
++ buf.item.data_gen0[0] = 0x55; |
30559 |
++ buf.item.data_gen0[63] = 0x80; |
30560 |
++ |
30561 |
++ buf.item.data_gen1[1] = 0xaa; |
30562 |
++ buf.item.data_gen1[9] = 0x02; |
30563 |
++ |
30564 |
++ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30565 |
++ ASSERT_RETURN(ret == 0); |
30566 |
++ |
30567 |
++ /* create a 2nd connection */ |
30568 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30569 |
++ ASSERT_RETURN(conn != NULL); |
30570 |
++ |
30571 |
++ /* a message with a 0'ed out filter must not reach the other peer */ |
30572 |
++ memset(filter, 0, sizeof(filter)); |
30573 |
++ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30574 |
++ ASSERT_RETURN(ret == 0); |
30575 |
++ |
30576 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30577 |
++ ASSERT_RETURN(ret == -EAGAIN); |
30578 |
++ |
30579 |
++ /* now set the filter to the connection's mask and expect success */ |
30580 |
++ filter[0] = 0x55; |
30581 |
++ filter[63] = 0x80; |
30582 |
++ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30583 |
++ ASSERT_RETURN(ret == 0); |
30584 |
++ |
30585 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30586 |
++ ASSERT_RETURN(ret == 0); |
30587 |
++ ASSERT_RETURN(msg->cookie == cookie); |
30588 |
++ |
30589 |
++ /* broaden the filter and try again. this should also succeed. */ |
30590 |
++ filter[0] = 0xff; |
30591 |
++ filter[8] = 0xff; |
30592 |
++ filter[63] = 0xff; |
30593 |
++ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30594 |
++ ASSERT_RETURN(ret == 0); |
30595 |
++ |
30596 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30597 |
++ ASSERT_RETURN(ret == 0); |
30598 |
++ ASSERT_RETURN(msg->cookie == cookie); |
30599 |
++ |
30600 |
++ /* the same filter must not match against bloom generation 1 */ |
30601 |
++ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1); |
30602 |
++ ASSERT_RETURN(ret == 0); |
30603 |
++ |
30604 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30605 |
++ ASSERT_RETURN(ret == -EAGAIN); |
30606 |
++ |
30607 |
++ /* set a different filter and try again */ |
30608 |
++ filter[1] = 0xaa; |
30609 |
++ filter[9] = 0x02; |
30610 |
++ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1); |
30611 |
++ ASSERT_RETURN(ret == 0); |
30612 |
++ |
30613 |
++ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30614 |
++ ASSERT_RETURN(ret == 0); |
30615 |
++ ASSERT_RETURN(msg->cookie == cookie); |
30616 |
++ |
30617 |
++ kdbus_conn_free(conn); |
30618 |
++ |
30619 |
++ return TEST_OK; |
30620 |
++} |
30621 |
+diff --git a/tools/testing/selftests/kdbus/test-message.c b/tools/testing/selftests/kdbus/test-message.c |
30622 |
+new file mode 100644 |
30623 |
+index 0000000..f1615da |
30624 |
+--- /dev/null |
30625 |
++++ b/tools/testing/selftests/kdbus/test-message.c |
30626 |
+@@ -0,0 +1,731 @@ |
30627 |
++#include <stdio.h> |
30628 |
++#include <string.h> |
30629 |
++#include <fcntl.h> |
30630 |
++#include <stdlib.h> |
30631 |
++#include <stddef.h> |
30632 |
++#include <unistd.h> |
30633 |
++#include <stdint.h> |
30634 |
++#include <errno.h> |
30635 |
++#include <assert.h> |
30636 |
++#include <time.h> |
30637 |
++#include <stdbool.h> |
30638 |
++#include <sys/eventfd.h> |
30639 |
++#include <sys/types.h> |
30640 |
++#include <sys/wait.h> |
30641 |
++ |
30642 |
++#include "kdbus-api.h" |
30643 |
++#include "kdbus-util.h" |
30644 |
++#include "kdbus-enum.h" |
30645 |
++#include "kdbus-test.h" |
30646 |
++ |
30647 |
++/* maximum number of queued messages from the same individual user */ |
30648 |
++#define KDBUS_CONN_MAX_MSGS 256 |
30649 |
++ |
30650 |
++/* maximum number of queued requests waiting for a reply */ |
30651 |
++#define KDBUS_CONN_MAX_REQUESTS_PENDING 128 |
30652 |
++ |
30653 |
++/* maximum message payload size */ |
30654 |
++#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE (2 * 1024UL * 1024UL) |
30655 |
++ |
30656 |
++int kdbus_test_message_basic(struct kdbus_test_env *env) |
30657 |
++{ |
30658 |
++ struct kdbus_conn *conn; |
30659 |
++ struct kdbus_conn *sender; |
30660 |
++ struct kdbus_msg *msg; |
30661 |
++ uint64_t cookie = 0x1234abcd5678eeff; |
30662 |
++ uint64_t offset; |
30663 |
++ int ret; |
30664 |
++ |
30665 |
++ sender = kdbus_hello(env->buspath, 0, NULL, 0); |
30666 |
++ ASSERT_RETURN(sender != NULL); |
30667 |
++ |
30668 |
++ /* create a 2nd connection */ |
30669 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30670 |
++ ASSERT_RETURN(conn != NULL); |
30671 |
++ |
30672 |
++ ret = kdbus_add_match_empty(conn); |
30673 |
++ ASSERT_RETURN(ret == 0); |
30674 |
++ |
30675 |
++ ret = kdbus_add_match_empty(sender); |
30676 |
++ ASSERT_RETURN(ret == 0); |
30677 |
++ |
30678 |
++ /* send over 1st connection */ |
30679 |
++ ret = kdbus_msg_send(sender, NULL, cookie, 0, 0, 0, |
30680 |
++ KDBUS_DST_ID_BROADCAST); |
30681 |
++ ASSERT_RETURN(ret == 0); |
30682 |
++ |
30683 |
++ /* Make sure that we do not get our own broadcasts */ |
30684 |
++ ret = kdbus_msg_recv(sender, NULL, NULL); |
30685 |
++ ASSERT_RETURN(ret == -EAGAIN); |
30686 |
++ |
30687 |
++ /* ... and receive on the 2nd */ |
30688 |
++ ret = kdbus_msg_recv_poll(conn, 100, &msg, &offset); |
30689 |
++ ASSERT_RETURN(ret == 0); |
30690 |
++ ASSERT_RETURN(msg->cookie == cookie); |
30691 |
++ |
30692 |
++ kdbus_msg_free(msg); |
30693 |
++ |
30694 |
++ /* Msgs that expect a reply must have timeout and cookie */ |
30695 |
++ ret = kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY, |
30696 |
++ 0, 0, conn->id); |
30697 |
++ ASSERT_RETURN(ret == -EINVAL); |
30698 |
++ |
30699 |
++ /* Faked replies with a valid reply cookie are rejected */ |
30700 |
++ ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id); |
30701 |
++ ASSERT_RETURN(ret == -EPERM); |
30702 |
++ |
30703 |
++ ret = kdbus_free(conn, offset); |
30704 |
++ ASSERT_RETURN(ret == 0); |
30705 |
++ |
30706 |
++ kdbus_conn_free(sender); |
30707 |
++ kdbus_conn_free(conn); |
30708 |
++ |
30709 |
++ return TEST_OK; |
30710 |
++} |
30711 |
++ |
30712 |
++static int msg_recv_prio(struct kdbus_conn *conn, |
30713 |
++ int64_t requested_prio, |
30714 |
++ int64_t expected_prio) |
30715 |
++{ |
30716 |
++ struct kdbus_cmd_recv recv = { |
30717 |
++ .size = sizeof(recv), |
30718 |
++ .flags = KDBUS_RECV_USE_PRIORITY, |
30719 |
++ .priority = requested_prio, |
30720 |
++ }; |
30721 |
++ struct kdbus_msg *msg; |
30722 |
++ int ret; |
30723 |
++ |
30724 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
30725 |
++ if (ret < 0) { |
30726 |
++ kdbus_printf("error receiving message: %d (%m)\n", -errno); |
30727 |
++ return ret; |
30728 |
++ } |
30729 |
++ |
30730 |
++ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
30731 |
++ kdbus_msg_dump(conn, msg); |
30732 |
++ |
30733 |
++ if (msg->priority != expected_prio) { |
30734 |
++ kdbus_printf("expected message prio %lld, got %lld\n", |
30735 |
++ (unsigned long long) expected_prio, |
30736 |
++ (unsigned long long) msg->priority); |
30737 |
++ return -EINVAL; |
30738 |
++ } |
30739 |
++ |
30740 |
++ kdbus_msg_free(msg); |
30741 |
++ ret = kdbus_free(conn, recv.msg.offset); |
30742 |
++ if (ret < 0) |
30743 |
++ return ret; |
30744 |
++ |
30745 |
++ return 0; |
30746 |
++} |
30747 |
++ |
30748 |
++int kdbus_test_message_prio(struct kdbus_test_env *env) |
30749 |
++{ |
30750 |
++ struct kdbus_conn *a, *b; |
30751 |
++ uint64_t cookie = 0; |
30752 |
++ |
30753 |
++ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30754 |
++ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30755 |
++ ASSERT_RETURN(a && b); |
30756 |
++ |
30757 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 25, a->id) == 0); |
30758 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id) == 0); |
30759 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); |
30760 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -35, a->id) == 0); |
30761 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id) == 0); |
30762 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 20, a->id) == 0); |
30763 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -15, a->id) == 0); |
30764 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); |
30765 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id) == 0); |
30766 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); |
30767 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); |
30768 |
++ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -10, a->id) == 0); |
30769 |
++ |
30770 |
++ ASSERT_RETURN(msg_recv_prio(a, -200, -800) == 0); |
30771 |
++ ASSERT_RETURN(msg_recv_prio(a, -100, -800) == 0); |
30772 |
++ ASSERT_RETURN(msg_recv_prio(a, -400, -600) == 0); |
30773 |
++ ASSERT_RETURN(msg_recv_prio(a, -400, -600) == -EAGAIN); |
30774 |
++ ASSERT_RETURN(msg_recv_prio(a, 10, -150) == 0); |
30775 |
++ ASSERT_RETURN(msg_recv_prio(a, 10, -100) == 0); |
30776 |
++ |
30777 |
++ kdbus_printf("--- get priority (all)\n"); |
30778 |
++ ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0); |
30779 |
++ |
30780 |
++ kdbus_conn_free(a); |
30781 |
++ kdbus_conn_free(b); |
30782 |
++ |
30783 |
++ return TEST_OK; |
30784 |
++} |
30785 |
++ |
30786 |
++static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env) |
30787 |
++{ |
30788 |
++ int ret; |
30789 |
++ unsigned int i; |
30790 |
++ struct kdbus_conn *conn; |
30791 |
++ struct kdbus_conn *reader; |
30792 |
++ struct kdbus_msg *msg = NULL; |
30793 |
++ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
30794 |
++ |
30795 |
++ reader = kdbus_hello(env->buspath, 0, NULL, 0); |
30796 |
++ ASSERT_RETURN(reader); |
30797 |
++ |
30798 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30799 |
++ ASSERT_RETURN(conn); |
30800 |
++ |
30801 |
++ /* Register for ID signals */ |
30802 |
++ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, |
30803 |
++ KDBUS_MATCH_ID_ANY); |
30804 |
++ ASSERT_RETURN(ret == 0); |
30805 |
++ |
30806 |
++ ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, |
30807 |
++ KDBUS_MATCH_ID_ANY); |
30808 |
++ ASSERT_RETURN(ret == 0); |
30809 |
++ |
30810 |
++ /* Each iteration two notifications: add and remove ID */ |
30811 |
++ for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) { |
30812 |
++ struct kdbus_conn *notifier; |
30813 |
++ |
30814 |
++ notifier = kdbus_hello(env->buspath, 0, NULL, 0); |
30815 |
++ ASSERT_RETURN(notifier); |
30816 |
++ |
30817 |
++ kdbus_conn_free(notifier); |
30818 |
++ } |
30819 |
++ |
30820 |
++ /* |
30821 |
++ * Now the reader queue is full with kernel notfications, |
30822 |
++ * but as a user we still have room to push our messages. |
30823 |
++ */ |
30824 |
++ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id); |
30825 |
++ ASSERT_RETURN(ret == 0); |
30826 |
++ |
30827 |
++ /* More ID kernel notifications that will be lost */ |
30828 |
++ kdbus_conn_free(conn); |
30829 |
++ |
30830 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30831 |
++ ASSERT_RETURN(conn); |
30832 |
++ |
30833 |
++ kdbus_conn_free(conn); |
30834 |
++ |
30835 |
++ /* |
30836 |
++ * We lost only 3 packets since only signal msgs are |
30837 |
++ * accounted. The connection ID add/remove notification |
30838 |
++ */ |
30839 |
++ ret = kdbus_cmd_recv(reader->fd, &recv); |
30840 |
++ ASSERT_RETURN(ret == 0); |
30841 |
++ ASSERT_RETURN(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS); |
30842 |
++ ASSERT_RETURN(recv.dropped_msgs == 3); |
30843 |
++ |
30844 |
++ msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset); |
30845 |
++ kdbus_msg_free(msg); |
30846 |
++ |
30847 |
++ /* Read our queue */ |
30848 |
++ for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) { |
30849 |
++ memset(&recv, 0, sizeof(recv)); |
30850 |
++ recv.size = sizeof(recv); |
30851 |
++ |
30852 |
++ ret = kdbus_cmd_recv(reader->fd, &recv); |
30853 |
++ ASSERT_RETURN(ret == 0); |
30854 |
++ ASSERT_RETURN(!(recv.return_flags & |
30855 |
++ KDBUS_RECV_RETURN_DROPPED_MSGS)); |
30856 |
++ |
30857 |
++ msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset); |
30858 |
++ kdbus_msg_free(msg); |
30859 |
++ } |
30860 |
++ |
30861 |
++ ret = kdbus_msg_recv(reader, NULL, NULL); |
30862 |
++ ASSERT_RETURN(ret == 0); |
30863 |
++ |
30864 |
++ ret = kdbus_msg_recv(reader, NULL, NULL); |
30865 |
++ ASSERT_RETURN(ret == -EAGAIN); |
30866 |
++ |
30867 |
++ kdbus_conn_free(reader); |
30868 |
++ |
30869 |
++ return 0; |
30870 |
++} |
30871 |
++ |
30872 |
++/* Return the number of message successfully sent */ |
30873 |
++static int kdbus_fill_conn_queue(struct kdbus_conn *conn_src, |
30874 |
++ uint64_t dst_id, |
30875 |
++ unsigned int max_msgs) |
30876 |
++{ |
30877 |
++ unsigned int i; |
30878 |
++ uint64_t cookie = 0; |
30879 |
++ size_t size; |
30880 |
++ struct kdbus_cmd_send cmd = {}; |
30881 |
++ struct kdbus_msg *msg; |
30882 |
++ int ret; |
30883 |
++ |
30884 |
++ size = sizeof(struct kdbus_msg); |
30885 |
++ msg = malloc(size); |
30886 |
++ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30887 |
++ |
30888 |
++ memset(msg, 0, size); |
30889 |
++ msg->size = size; |
30890 |
++ msg->src_id = conn_src->id; |
30891 |
++ msg->dst_id = dst_id; |
30892 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30893 |
++ |
30894 |
++ cmd.size = sizeof(cmd); |
30895 |
++ cmd.msg_address = (uintptr_t)msg; |
30896 |
++ |
30897 |
++ for (i = 0; i < max_msgs; i++) { |
30898 |
++ msg->cookie = cookie++; |
30899 |
++ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
30900 |
++ if (ret < 0) |
30901 |
++ break; |
30902 |
++ } |
30903 |
++ |
30904 |
++ free(msg); |
30905 |
++ |
30906 |
++ return i; |
30907 |
++} |
30908 |
++ |
30909 |
++static int kdbus_test_activator_quota(struct kdbus_test_env *env) |
30910 |
++{ |
30911 |
++ int ret; |
30912 |
++ unsigned int i; |
30913 |
++ unsigned int activator_msgs_count = 0; |
30914 |
++ uint64_t cookie = time(NULL); |
30915 |
++ struct kdbus_conn *conn; |
30916 |
++ struct kdbus_conn *sender; |
30917 |
++ struct kdbus_conn *activator; |
30918 |
++ struct kdbus_msg *msg; |
30919 |
++ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
30920 |
++ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
30921 |
++ struct kdbus_policy_access access = { |
30922 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
30923 |
++ .id = geteuid(), |
30924 |
++ .access = KDBUS_POLICY_OWN, |
30925 |
++ }; |
30926 |
++ |
30927 |
++ activator = kdbus_hello_activator(env->buspath, "foo.test.activator", |
30928 |
++ &access, 1); |
30929 |
++ ASSERT_RETURN(activator); |
30930 |
++ |
30931 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30932 |
++ sender = kdbus_hello(env->buspath, 0, NULL, 0); |
30933 |
++ ASSERT_RETURN(conn || sender); |
30934 |
++ |
30935 |
++ ret = kdbus_list(sender, KDBUS_LIST_NAMES | |
30936 |
++ KDBUS_LIST_UNIQUE | |
30937 |
++ KDBUS_LIST_ACTIVATORS | |
30938 |
++ KDBUS_LIST_QUEUED); |
30939 |
++ ASSERT_RETURN(ret == 0); |
30940 |
++ |
30941 |
++ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30942 |
++ ret = kdbus_msg_send(sender, "foo.test.activator", |
30943 |
++ cookie++, 0, 0, 0, |
30944 |
++ KDBUS_DST_ID_NAME); |
30945 |
++ if (ret < 0) |
30946 |
++ break; |
30947 |
++ activator_msgs_count++; |
30948 |
++ } |
30949 |
++ |
30950 |
++ /* we must have at least sent one message */ |
30951 |
++ ASSERT_RETURN_VAL(i > 0, -errno); |
30952 |
++ ASSERT_RETURN(ret == -ENOBUFS); |
30953 |
++ |
30954 |
++ /* Good, activator queue is full now */ |
30955 |
++ |
30956 |
++ /* ENXIO on direct send (activators can never be addressed by ID) */ |
30957 |
++ ret = kdbus_msg_send(conn, NULL, cookie++, 0, 0, 0, activator->id); |
30958 |
++ ASSERT_RETURN(ret == -ENXIO); |
30959 |
++ |
30960 |
++ /* can't queue more */ |
30961 |
++ ret = kdbus_msg_send(conn, "foo.test.activator", cookie++, |
30962 |
++ 0, 0, 0, KDBUS_DST_ID_NAME); |
30963 |
++ ASSERT_RETURN(ret == -ENOBUFS); |
30964 |
++ |
30965 |
++ /* no match installed, so the broadcast will not inc dropped_msgs */ |
30966 |
++ ret = kdbus_msg_send(sender, NULL, cookie++, 0, 0, 0, |
30967 |
++ KDBUS_DST_ID_BROADCAST); |
30968 |
++ ASSERT_RETURN(ret == 0); |
30969 |
++ |
30970 |
++ /* Check activator queue */ |
30971 |
++ ret = kdbus_cmd_recv(activator->fd, &recv); |
30972 |
++ ASSERT_RETURN(ret == 0); |
30973 |
++ ASSERT_RETURN(recv.dropped_msgs == 0); |
30974 |
++ |
30975 |
++ activator_msgs_count--; |
30976 |
++ |
30977 |
++ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30978 |
++ kdbus_msg_free(msg); |
30979 |
++ |
30980 |
++ |
30981 |
++ /* Stage 1) of test check the pool memory quota */ |
30982 |
++ |
30983 |
++ /* Consume the connection pool memory */ |
30984 |
++ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30985 |
++ ret = kdbus_msg_send(sender, NULL, |
30986 |
++ cookie++, 0, 0, 0, conn->id); |
30987 |
++ if (ret < 0) |
30988 |
++ break; |
30989 |
++ } |
30990 |
++ |
30991 |
++ /* consume one message, so later at least one can be moved */ |
30992 |
++ memset(&recv, 0, sizeof(recv)); |
30993 |
++ recv.size = sizeof(recv); |
30994 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
30995 |
++ ASSERT_RETURN(ret == 0); |
30996 |
++ ASSERT_RETURN(recv.dropped_msgs == 0); |
30997 |
++ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
30998 |
++ kdbus_msg_free(msg); |
30999 |
++ |
31000 |
++ /* Try to acquire the name now */ |
31001 |
++ ret = kdbus_name_acquire(conn, "foo.test.activator", &flags); |
31002 |
++ ASSERT_RETURN(ret == 0); |
31003 |
++ |
31004 |
++ /* try to read messages and see if we have lost some */ |
31005 |
++ memset(&recv, 0, sizeof(recv)); |
31006 |
++ recv.size = sizeof(recv); |
31007 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
31008 |
++ ASSERT_RETURN(ret == 0); |
31009 |
++ ASSERT_RETURN(recv.dropped_msgs != 0); |
31010 |
++ |
31011 |
++ /* number of dropped msgs < received ones (at least one was moved) */ |
31012 |
++ ASSERT_RETURN(recv.dropped_msgs < activator_msgs_count); |
31013 |
++ |
31014 |
++ /* Deduct the number of dropped msgs from the activator msgs */ |
31015 |
++ activator_msgs_count -= recv.dropped_msgs; |
31016 |
++ |
31017 |
++ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
31018 |
++ kdbus_msg_free(msg); |
31019 |
++ |
31020 |
++ /* |
31021 |
++ * Release the name and hand it back to activator, now |
31022 |
++ * we should have 'activator_msgs_count' msgs again in |
31023 |
++ * the activator queue |
31024 |
++ */ |
31025 |
++ ret = kdbus_name_release(conn, "foo.test.activator"); |
31026 |
++ ASSERT_RETURN(ret == 0); |
31027 |
++ |
31028 |
++ /* make sure that we got our previous activator msgs */ |
31029 |
++ ret = kdbus_msg_recv(activator, &msg, NULL); |
31030 |
++ ASSERT_RETURN(ret == 0); |
31031 |
++ ASSERT_RETURN(msg->src_id == sender->id); |
31032 |
++ |
31033 |
++ activator_msgs_count--; |
31034 |
++ |
31035 |
++ kdbus_msg_free(msg); |
31036 |
++ |
31037 |
++ |
31038 |
++ /* Stage 2) of test check max message quota */ |
31039 |
++ |
31040 |
++ /* Empty conn queue */ |
31041 |
++ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
31042 |
++ ret = kdbus_msg_recv(conn, NULL, NULL); |
31043 |
++ if (ret == -EAGAIN) |
31044 |
++ break; |
31045 |
++ } |
31046 |
++ |
31047 |
++ /* fill queue with max msgs quota */ |
31048 |
++ ret = kdbus_fill_conn_queue(sender, conn->id, KDBUS_CONN_MAX_MSGS); |
31049 |
++ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
31050 |
++ |
31051 |
++ /* This one is lost but it is not accounted */ |
31052 |
++ ret = kdbus_msg_send(sender, NULL, |
31053 |
++ cookie++, 0, 0, 0, conn->id); |
31054 |
++ ASSERT_RETURN(ret == -ENOBUFS); |
31055 |
++ |
31056 |
++ /* Acquire the name again */ |
31057 |
++ ret = kdbus_name_acquire(conn, "foo.test.activator", &flags); |
31058 |
++ ASSERT_RETURN(ret == 0); |
31059 |
++ |
31060 |
++ memset(&recv, 0, sizeof(recv)); |
31061 |
++ recv.size = sizeof(recv); |
31062 |
++ |
31063 |
++ /* |
31064 |
++ * Try to read messages and make sure that we have lost all |
31065 |
++ * the activator messages due to quota checks. Our queue is |
31066 |
++ * already full. |
31067 |
++ */ |
31068 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
31069 |
++ ASSERT_RETURN(ret == 0); |
31070 |
++ ASSERT_RETURN(recv.dropped_msgs == activator_msgs_count); |
31071 |
++ |
31072 |
++ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
31073 |
++ kdbus_msg_free(msg); |
31074 |
++ |
31075 |
++ kdbus_conn_free(sender); |
31076 |
++ kdbus_conn_free(conn); |
31077 |
++ kdbus_conn_free(activator); |
31078 |
++ |
31079 |
++ return 0; |
31080 |
++} |
31081 |
++ |
31082 |
++static int kdbus_test_expected_reply_quota(struct kdbus_test_env *env) |
31083 |
++{ |
31084 |
++ int ret; |
31085 |
++ unsigned int i, n; |
31086 |
++ unsigned int count; |
31087 |
++ uint64_t cookie = 0x1234abcd5678eeff; |
31088 |
++ struct kdbus_conn *conn; |
31089 |
++ struct kdbus_conn *connections[9]; |
31090 |
++ |
31091 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31092 |
++ ASSERT_RETURN(conn); |
31093 |
++ |
31094 |
++ for (i = 0; i < 9; i++) { |
31095 |
++ connections[i] = kdbus_hello(env->buspath, 0, NULL, 0); |
31096 |
++ ASSERT_RETURN(connections[i]); |
31097 |
++ } |
31098 |
++ |
31099 |
++ count = 0; |
31100 |
++ /* Send 16 messages to 8 different connections */ |
31101 |
++ for (i = 0; i < 8; i++) { |
31102 |
++ for (n = 0; n < 16; n++) { |
31103 |
++ ret = kdbus_msg_send(conn, NULL, cookie++, |
31104 |
++ KDBUS_MSG_EXPECT_REPLY, |
31105 |
++ 100000000ULL, 0, |
31106 |
++ connections[i]->id); |
31107 |
++ if (ret < 0) |
31108 |
++ break; |
31109 |
++ |
31110 |
++ count++; |
31111 |
++ } |
31112 |
++ } |
31113 |
++ |
31114 |
++ /* |
31115 |
++ * We should have queued at least |
31116 |
++ * KDBUS_CONN_MAX_REQUESTS_PENDING method call |
31117 |
++ */ |
31118 |
++ ASSERT_RETURN(count == KDBUS_CONN_MAX_REQUESTS_PENDING); |
31119 |
++ |
31120 |
++ /* |
31121 |
++ * Now try to send a message to the last connection, |
31122 |
++ * if we have reached KDBUS_CONN_MAX_REQUESTS_PENDING |
31123 |
++ * no further requests are allowed |
31124 |
++ */ |
31125 |
++ ret = kdbus_msg_send(conn, NULL, cookie++, KDBUS_MSG_EXPECT_REPLY, |
31126 |
++ 1000000000ULL, 0, connections[8]->id); |
31127 |
++ ASSERT_RETURN(ret == -EMLINK); |
31128 |
++ |
31129 |
++ for (i = 0; i < 9; i++) |
31130 |
++ kdbus_conn_free(connections[i]); |
31131 |
++ |
31132 |
++ kdbus_conn_free(conn); |
31133 |
++ |
31134 |
++ return 0; |
31135 |
++} |
31136 |
++ |
31137 |
++int kdbus_test_pool_quota(struct kdbus_test_env *env) |
31138 |
++{ |
31139 |
++ struct kdbus_conn *a, *b, *c; |
31140 |
++ struct kdbus_cmd_send cmd = {}; |
31141 |
++ struct kdbus_item *item; |
31142 |
++ struct kdbus_msg *recv_msg; |
31143 |
++ struct kdbus_msg *msg; |
31144 |
++ uint64_t cookie = time(NULL); |
31145 |
++ uint64_t size; |
31146 |
++ unsigned int i; |
31147 |
++ char *payload; |
31148 |
++ int ret; |
31149 |
++ |
31150 |
++ /* just a guard */ |
31151 |
++ if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE || |
31152 |
++ POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0) |
31153 |
++ return 0; |
31154 |
++ |
31155 |
++ payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char)); |
31156 |
++ ASSERT_RETURN_VAL(payload, -ENOMEM); |
31157 |
++ |
31158 |
++ a = kdbus_hello(env->buspath, 0, NULL, 0); |
31159 |
++ b = kdbus_hello(env->buspath, 0, NULL, 0); |
31160 |
++ c = kdbus_hello(env->buspath, 0, NULL, 0); |
31161 |
++ ASSERT_RETURN(a && b && c); |
31162 |
++ |
31163 |
++ size = sizeof(struct kdbus_msg); |
31164 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
31165 |
++ |
31166 |
++ msg = malloc(size); |
31167 |
++ ASSERT_RETURN_VAL(msg, -ENOMEM); |
31168 |
++ |
31169 |
++ memset(msg, 0, size); |
31170 |
++ msg->size = size; |
31171 |
++ msg->src_id = a->id; |
31172 |
++ msg->dst_id = c->id; |
31173 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
31174 |
++ |
31175 |
++ item = msg->items; |
31176 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
31177 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
31178 |
++ item->vec.address = (uintptr_t)payload; |
31179 |
++ item->vec.size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE; |
31180 |
++ item = KDBUS_ITEM_NEXT(item); |
31181 |
++ |
31182 |
++ cmd.size = sizeof(cmd); |
31183 |
++ cmd.msg_address = (uintptr_t)msg; |
31184 |
++ |
31185 |
++ /* |
31186 |
++ * Send 2097248 bytes, a user is only allowed to get 33% of half of |
31187 |
++ * the free space of the pool, the already used space is |
31188 |
++ * accounted as free space |
31189 |
++ */ |
31190 |
++ size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE; |
31191 |
++ for (i = size; i < (POOL_SIZE / 2 / 3); i += size) { |
31192 |
++ msg->cookie = cookie++; |
31193 |
++ |
31194 |
++ ret = kdbus_cmd_send(a->fd, &cmd); |
31195 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
31196 |
++ } |
31197 |
++ |
31198 |
++ /* Try to get more than 33% */ |
31199 |
++ msg->cookie = cookie++; |
31200 |
++ ret = kdbus_cmd_send(a->fd, &cmd); |
31201 |
++ ASSERT_RETURN(ret == -ENOBUFS); |
31202 |
++ |
31203 |
++ /* We still can pass small messages */ |
31204 |
++ ret = kdbus_msg_send(b, NULL, cookie++, 0, 0, 0, c->id); |
31205 |
++ ASSERT_RETURN(ret == 0); |
31206 |
++ |
31207 |
++ for (i = size; i < (POOL_SIZE / 2 / 3); i += size) { |
31208 |
++ ret = kdbus_msg_recv(c, &recv_msg, NULL); |
31209 |
++ ASSERT_RETURN(ret == 0); |
31210 |
++ ASSERT_RETURN(recv_msg->src_id == a->id); |
31211 |
++ |
31212 |
++ kdbus_msg_free(recv_msg); |
31213 |
++ } |
31214 |
++ |
31215 |
++ ret = kdbus_msg_recv(c, &recv_msg, NULL); |
31216 |
++ ASSERT_RETURN(ret == 0); |
31217 |
++ ASSERT_RETURN(recv_msg->src_id == b->id); |
31218 |
++ |
31219 |
++ kdbus_msg_free(recv_msg); |
31220 |
++ |
31221 |
++ ret = kdbus_msg_recv(c, NULL, NULL); |
31222 |
++ ASSERT_RETURN(ret == -EAGAIN); |
31223 |
++ |
31224 |
++ free(msg); |
31225 |
++ free(payload); |
31226 |
++ |
31227 |
++ kdbus_conn_free(c); |
31228 |
++ kdbus_conn_free(b); |
31229 |
++ kdbus_conn_free(a); |
31230 |
++ |
31231 |
++ return 0; |
31232 |
++} |
31233 |
++ |
31234 |
++int kdbus_test_message_quota(struct kdbus_test_env *env) |
31235 |
++{ |
31236 |
++ struct kdbus_conn *a, *b; |
31237 |
++ uint64_t cookie = 0; |
31238 |
++ int ret; |
31239 |
++ int i; |
31240 |
++ |
31241 |
++ ret = kdbus_test_activator_quota(env); |
31242 |
++ ASSERT_RETURN(ret == 0); |
31243 |
++ |
31244 |
++ ret = kdbus_test_notify_kernel_quota(env); |
31245 |
++ ASSERT_RETURN(ret == 0); |
31246 |
++ |
31247 |
++ ret = kdbus_test_pool_quota(env); |
31248 |
++ ASSERT_RETURN(ret == 0); |
31249 |
++ |
31250 |
++ ret = kdbus_test_expected_reply_quota(env); |
31251 |
++ ASSERT_RETURN(ret == 0); |
31252 |
++ |
31253 |
++ a = kdbus_hello(env->buspath, 0, NULL, 0); |
31254 |
++ b = kdbus_hello(env->buspath, 0, NULL, 0); |
31255 |
++ |
31256 |
++ ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS); |
31257 |
++ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
31258 |
++ |
31259 |
++ ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id); |
31260 |
++ ASSERT_RETURN(ret == -ENOBUFS); |
31261 |
++ |
31262 |
++ for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i) { |
31263 |
++ ret = kdbus_msg_recv(a, NULL, NULL); |
31264 |
++ ASSERT_RETURN(ret == 0); |
31265 |
++ } |
31266 |
++ |
31267 |
++ ret = kdbus_msg_recv(a, NULL, NULL); |
31268 |
++ ASSERT_RETURN(ret == -EAGAIN); |
31269 |
++ |
31270 |
++ ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1); |
31271 |
++ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
31272 |
++ |
31273 |
++ ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id); |
31274 |
++ ASSERT_RETURN(ret == -ENOBUFS); |
31275 |
++ |
31276 |
++ kdbus_conn_free(a); |
31277 |
++ kdbus_conn_free(b); |
31278 |
++ |
31279 |
++ return TEST_OK; |
31280 |
++} |
31281 |
++ |
31282 |
++int kdbus_test_memory_access(struct kdbus_test_env *env) |
31283 |
++{ |
31284 |
++ struct kdbus_conn *a, *b; |
31285 |
++ struct kdbus_cmd_send cmd = {}; |
31286 |
++ struct kdbus_item *item; |
31287 |
++ struct kdbus_msg *msg; |
31288 |
++ uint64_t test_addr = 0; |
31289 |
++ char line[256]; |
31290 |
++ uint64_t size; |
31291 |
++ FILE *f; |
31292 |
++ int ret; |
31293 |
++ |
31294 |
++ /* |
31295 |
++ * Search in /proc/kallsyms for the address of a kernel symbol that |
31296 |
++ * should always be there, regardless of the config. Use that address |
31297 |
++ * in a PAYLOAD_VEC item and make sure it's inaccessible. |
31298 |
++ */ |
31299 |
++ |
31300 |
++ f = fopen("/proc/kallsyms", "r"); |
31301 |
++ if (!f) |
31302 |
++ return TEST_SKIP; |
31303 |
++ |
31304 |
++ while (fgets(line, sizeof(line), f)) { |
31305 |
++ char *s = line; |
31306 |
++ |
31307 |
++ if (!strsep(&s, " ")) |
31308 |
++ continue; |
31309 |
++ |
31310 |
++ if (!strsep(&s, " ")) |
31311 |
++ continue; |
31312 |
++ |
31313 |
++ if (!strncmp(s, "mutex_lock", 10)) { |
31314 |
++ test_addr = strtoull(line, NULL, 16); |
31315 |
++ break; |
31316 |
++ } |
31317 |
++ } |
31318 |
++ |
31319 |
++ fclose(f); |
31320 |
++ |
31321 |
++ if (!test_addr) |
31322 |
++ return TEST_SKIP; |
31323 |
++ |
31324 |
++ a = kdbus_hello(env->buspath, 0, NULL, 0); |
31325 |
++ b = kdbus_hello(env->buspath, 0, NULL, 0); |
31326 |
++ ASSERT_RETURN(a && b); |
31327 |
++ |
31328 |
++ size = sizeof(struct kdbus_msg); |
31329 |
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
31330 |
++ |
31331 |
++ msg = alloca(size); |
31332 |
++ ASSERT_RETURN_VAL(msg, -ENOMEM); |
31333 |
++ |
31334 |
++ memset(msg, 0, size); |
31335 |
++ msg->size = size; |
31336 |
++ msg->src_id = a->id; |
31337 |
++ msg->dst_id = b->id; |
31338 |
++ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
31339 |
++ |
31340 |
++ item = msg->items; |
31341 |
++ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
31342 |
++ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
31343 |
++ item->vec.address = test_addr; |
31344 |
++ item->vec.size = sizeof(void*); |
31345 |
++ item = KDBUS_ITEM_NEXT(item); |
31346 |
++ |
31347 |
++ cmd.size = sizeof(cmd); |
31348 |
++ cmd.msg_address = (uintptr_t)msg; |
31349 |
++ |
31350 |
++ ret = kdbus_cmd_send(a->fd, &cmd); |
31351 |
++ ASSERT_RETURN(ret == -EFAULT); |
31352 |
++ |
31353 |
++ kdbus_conn_free(b); |
31354 |
++ kdbus_conn_free(a); |
31355 |
++ |
31356 |
++ return 0; |
31357 |
++} |
31358 |
+diff --git a/tools/testing/selftests/kdbus/test-metadata-ns.c b/tools/testing/selftests/kdbus/test-metadata-ns.c |
31359 |
+new file mode 100644 |
31360 |
+index 0000000..2cb1d4d |
31361 |
+--- /dev/null |
31362 |
++++ b/tools/testing/selftests/kdbus/test-metadata-ns.c |
31363 |
+@@ -0,0 +1,506 @@ |
31364 |
++/* |
31365 |
++ * Test metadata in new namespaces. Even if our tests can run |
31366 |
++ * in a namespaced setup, this test is necessary so we can inspect |
31367 |
++ * metadata on the same kdbusfs but between multiple namespaces |
31368 |
++ */ |
31369 |
++ |
31370 |
++#include <stdio.h> |
31371 |
++#include <string.h> |
31372 |
++#include <sched.h> |
31373 |
++#include <time.h> |
31374 |
++#include <fcntl.h> |
31375 |
++#include <stdlib.h> |
31376 |
++#include <stddef.h> |
31377 |
++#include <unistd.h> |
31378 |
++#include <stdint.h> |
31379 |
++#include <errno.h> |
31380 |
++#include <assert.h> |
31381 |
++#include <signal.h> |
31382 |
++#include <sys/wait.h> |
31383 |
++#include <sys/prctl.h> |
31384 |
++#include <sys/eventfd.h> |
31385 |
++#include <sys/syscall.h> |
31386 |
++#include <sys/capability.h> |
31387 |
++#include <linux/sched.h> |
31388 |
++ |
31389 |
++#include "kdbus-test.h" |
31390 |
++#include "kdbus-util.h" |
31391 |
++#include "kdbus-enum.h" |
31392 |
++ |
31393 |
++static const struct kdbus_creds privileged_creds = {}; |
31394 |
++ |
31395 |
++static const struct kdbus_creds unmapped_creds = { |
31396 |
++ .uid = UNPRIV_UID, |
31397 |
++ .euid = UNPRIV_UID, |
31398 |
++ .suid = UNPRIV_UID, |
31399 |
++ .fsuid = UNPRIV_UID, |
31400 |
++ .gid = UNPRIV_GID, |
31401 |
++ .egid = UNPRIV_GID, |
31402 |
++ .sgid = UNPRIV_GID, |
31403 |
++ .fsgid = UNPRIV_GID, |
31404 |
++}; |
31405 |
++ |
31406 |
++static const struct kdbus_pids unmapped_pids = {}; |
31407 |
++ |
31408 |
++/* Get only the first item */ |
31409 |
++static struct kdbus_item *kdbus_get_item(struct kdbus_msg *msg, |
31410 |
++ uint64_t type) |
31411 |
++{ |
31412 |
++ struct kdbus_item *item; |
31413 |
++ |
31414 |
++ KDBUS_ITEM_FOREACH(item, msg, items) |
31415 |
++ if (item->type == type) |
31416 |
++ return item; |
31417 |
++ |
31418 |
++ return NULL; |
31419 |
++} |
31420 |
++ |
31421 |
++static int kdbus_match_kdbus_creds(struct kdbus_msg *msg, |
31422 |
++ const struct kdbus_creds *expected_creds) |
31423 |
++{ |
31424 |
++ struct kdbus_item *item; |
31425 |
++ |
31426 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_CREDS); |
31427 |
++ ASSERT_RETURN(item); |
31428 |
++ |
31429 |
++ ASSERT_RETURN(memcmp(&item->creds, expected_creds, |
31430 |
++ sizeof(struct kdbus_creds)) == 0); |
31431 |
++ |
31432 |
++ return 0; |
31433 |
++} |
31434 |
++ |
31435 |
++static int kdbus_match_kdbus_pids(struct kdbus_msg *msg, |
31436 |
++ const struct kdbus_pids *expected_pids) |
31437 |
++{ |
31438 |
++ struct kdbus_item *item; |
31439 |
++ |
31440 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31441 |
++ ASSERT_RETURN(item); |
31442 |
++ |
31443 |
++ ASSERT_RETURN(memcmp(&item->pids, expected_pids, |
31444 |
++ sizeof(struct kdbus_pids)) == 0); |
31445 |
++ |
31446 |
++ return 0; |
31447 |
++} |
31448 |
++ |
31449 |
++static int __kdbus_clone_userns_test(const char *bus, |
31450 |
++ struct kdbus_conn *conn, |
31451 |
++ uint64_t grandpa_pid, |
31452 |
++ int signal_fd) |
31453 |
++{ |
31454 |
++ int clone_ret; |
31455 |
++ int ret; |
31456 |
++ struct kdbus_msg *msg = NULL; |
31457 |
++ const struct kdbus_item *item; |
31458 |
++ uint64_t cookie = time(NULL) ^ 0xdeadbeef; |
31459 |
++ struct kdbus_conn *unpriv_conn = NULL; |
31460 |
++ struct kdbus_pids parent_pids = { |
31461 |
++ .pid = getppid(), |
31462 |
++ .tid = getppid(), |
31463 |
++ .ppid = grandpa_pid, |
31464 |
++ }; |
31465 |
++ |
31466 |
++ ret = drop_privileges(UNPRIV_UID, UNPRIV_GID); |
31467 |
++ ASSERT_EXIT(ret == 0); |
31468 |
++ |
31469 |
++ unpriv_conn = kdbus_hello(bus, 0, NULL, 0); |
31470 |
++ ASSERT_EXIT(unpriv_conn); |
31471 |
++ |
31472 |
++ ret = kdbus_add_match_empty(unpriv_conn); |
31473 |
++ ASSERT_EXIT(ret == 0); |
31474 |
++ |
31475 |
++ /* |
31476 |
++ * ping privileged connection from this new unprivileged |
31477 |
++ * one |
31478 |
++ */ |
31479 |
++ |
31480 |
++ ret = kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0, |
31481 |
++ 0, conn->id); |
31482 |
++ ASSERT_EXIT(ret == 0); |
31483 |
++ |
31484 |
++ /* |
31485 |
++ * Since we just dropped privileges, the dumpable flag |
31486 |
++ * was just cleared which makes the /proc/$clone_child/uid_map |
31487 |
++ * to be owned by root, hence any userns uid mapping will fail |
31488 |
++ * with -EPERM since the mapping will be done by uid 65534. |
31489 |
++ * |
31490 |
++ * To avoid this set the dumpable flag again which makes |
31491 |
++ * procfs update the /proc/$clone_child/ inodes owner to 65534. |
31492 |
++ * |
31493 |
++ * Using this we will be able write to /proc/$clone_child/uid_map |
31494 |
++ * as uid 65534 and map the uid 65534 to 0 inside the user namespace. |
31495 |
++ */ |
31496 |
++ ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER); |
31497 |
++ ASSERT_EXIT(ret == 0); |
31498 |
++ |
31499 |
++ /* Make child privileged in its new userns and run tests */ |
31500 |
++ |
31501 |
++ ret = RUN_CLONE_CHILD(&clone_ret, |
31502 |
++ SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID, |
31503 |
++ ({ 0; /* Clone setup, nothing */ }), |
31504 |
++ ({ |
31505 |
++ eventfd_t event_status = 0; |
31506 |
++ struct kdbus_conn *userns_conn; |
31507 |
++ |
31508 |
++ /* ping connection from the new user namespace */ |
31509 |
++ userns_conn = kdbus_hello(bus, 0, NULL, 0); |
31510 |
++ ASSERT_EXIT(userns_conn); |
31511 |
++ |
31512 |
++ ret = kdbus_add_match_empty(userns_conn); |
31513 |
++ ASSERT_EXIT(ret == 0); |
31514 |
++ |
31515 |
++ cookie++; |
31516 |
++ ret = kdbus_msg_send(userns_conn, NULL, cookie, |
31517 |
++ 0, 0, 0, conn->id); |
31518 |
++ ASSERT_EXIT(ret == 0); |
31519 |
++ |
31520 |
++ /* Parent did send */ |
31521 |
++ ret = eventfd_read(signal_fd, &event_status); |
31522 |
++ ASSERT_RETURN(ret >= 0 && event_status == 1); |
31523 |
++ |
31524 |
++ /* |
31525 |
++ * Receive from privileged connection |
31526 |
++ */ |
31527 |
++ kdbus_printf("Privileged → unprivileged/privileged " |
31528 |
++ "in its userns " |
31529 |
++ "(different userns and pidns):\n"); |
31530 |
++ ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL); |
31531 |
++ ASSERT_EXIT(ret == 0); |
31532 |
++ ASSERT_EXIT(msg->dst_id == userns_conn->id); |
31533 |
++ |
31534 |
++ /* Different namespaces no CAPS */ |
31535 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31536 |
++ ASSERT_EXIT(item == NULL); |
31537 |
++ |
31538 |
++ /* uid/gid not mapped, so we have unpriv cached creds */ |
31539 |
++ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31540 |
++ ASSERT_EXIT(ret == 0); |
31541 |
++ |
31542 |
++ /* |
31543 |
++ * Diffent pid namepsaces. This is the child pidns |
31544 |
++ * so it should not see its parent kdbus_pids |
31545 |
++ */ |
31546 |
++ ret = kdbus_match_kdbus_pids(msg, &unmapped_pids); |
31547 |
++ ASSERT_EXIT(ret == 0); |
31548 |
++ |
31549 |
++ kdbus_msg_free(msg); |
31550 |
++ |
31551 |
++ |
31552 |
++ /* |
31553 |
++ * Receive broadcast from privileged connection |
31554 |
++ */ |
31555 |
++ kdbus_printf("Privileged → unprivileged/privileged " |
31556 |
++ "in its userns " |
31557 |
++ "(different userns and pidns):\n"); |
31558 |
++ ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL); |
31559 |
++ ASSERT_EXIT(ret == 0); |
31560 |
++ ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST); |
31561 |
++ |
31562 |
++ /* Different namespaces no CAPS */ |
31563 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31564 |
++ ASSERT_EXIT(item == NULL); |
31565 |
++ |
31566 |
++ /* uid/gid not mapped, so we have unpriv cached creds */ |
31567 |
++ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31568 |
++ ASSERT_EXIT(ret == 0); |
31569 |
++ |
31570 |
++ /* |
31571 |
++ * Diffent pid namepsaces. This is the child pidns |
31572 |
++ * so it should not see its parent kdbus_pids |
31573 |
++ */ |
31574 |
++ ret = kdbus_match_kdbus_pids(msg, &unmapped_pids); |
31575 |
++ ASSERT_EXIT(ret == 0); |
31576 |
++ |
31577 |
++ kdbus_msg_free(msg); |
31578 |
++ |
31579 |
++ kdbus_conn_free(userns_conn); |
31580 |
++ }), |
31581 |
++ ({ |
31582 |
++ /* Parent setup map child uid/gid */ |
31583 |
++ ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"); |
31584 |
++ ASSERT_EXIT(ret == 0); |
31585 |
++ }), |
31586 |
++ ({ 0; })); |
31587 |
++ /* Unprivileged was not able to create user namespace */ |
31588 |
++ if (clone_ret == -EPERM) { |
31589 |
++ kdbus_printf("-- CLONE_NEWUSER TEST Failed for " |
31590 |
++ "uid: %u\n -- Make sure that your kernel " |
31591 |
++ "do not allow CLONE_NEWUSER for " |
31592 |
++ "unprivileged users\n", UNPRIV_UID); |
31593 |
++ ret = 0; |
31594 |
++ goto out; |
31595 |
++ } |
31596 |
++ |
31597 |
++ ASSERT_EXIT(ret == 0); |
31598 |
++ |
31599 |
++ |
31600 |
++ /* |
31601 |
++ * Receive from privileged connection |
31602 |
++ */ |
31603 |
++ kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n"); |
31604 |
++ ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL); |
31605 |
++ |
31606 |
++ ASSERT_EXIT(ret == 0); |
31607 |
++ ASSERT_EXIT(msg->dst_id == unpriv_conn->id); |
31608 |
++ |
31609 |
++ /* will get the privileged creds */ |
31610 |
++ ret = kdbus_match_kdbus_creds(msg, &privileged_creds); |
31611 |
++ ASSERT_EXIT(ret == 0); |
31612 |
++ |
31613 |
++ /* Same pidns so will get the kdbus_pids */ |
31614 |
++ ret = kdbus_match_kdbus_pids(msg, &parent_pids); |
31615 |
++ ASSERT_RETURN(ret == 0); |
31616 |
++ |
31617 |
++ kdbus_msg_free(msg); |
31618 |
++ |
31619 |
++ |
31620 |
++ /* |
31621 |
++ * Receive broadcast from privileged connection |
31622 |
++ */ |
31623 |
++ kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n"); |
31624 |
++ ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL); |
31625 |
++ |
31626 |
++ ASSERT_EXIT(ret == 0); |
31627 |
++ ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST); |
31628 |
++ |
31629 |
++ /* will get the privileged creds */ |
31630 |
++ ret = kdbus_match_kdbus_creds(msg, &privileged_creds); |
31631 |
++ ASSERT_EXIT(ret == 0); |
31632 |
++ |
31633 |
++ ret = kdbus_match_kdbus_pids(msg, &parent_pids); |
31634 |
++ ASSERT_RETURN(ret == 0); |
31635 |
++ |
31636 |
++ kdbus_msg_free(msg); |
31637 |
++ |
31638 |
++out: |
31639 |
++ kdbus_conn_free(unpriv_conn); |
31640 |
++ |
31641 |
++ return ret; |
31642 |
++} |
31643 |
++ |
31644 |
++static int kdbus_clone_userns_test(const char *bus, |
31645 |
++ struct kdbus_conn *conn) |
31646 |
++{ |
31647 |
++ int ret; |
31648 |
++ int status; |
31649 |
++ int efd = -1; |
31650 |
++ pid_t pid, ppid; |
31651 |
++ uint64_t unpriv_conn_id = 0; |
31652 |
++ uint64_t userns_conn_id = 0; |
31653 |
++ struct kdbus_msg *msg; |
31654 |
++ const struct kdbus_item *item; |
31655 |
++ struct kdbus_pids expected_pids; |
31656 |
++ struct kdbus_conn *monitor = NULL; |
31657 |
++ |
31658 |
++ kdbus_printf("STARTING TEST 'metadata-ns'.\n"); |
31659 |
++ |
31660 |
++ monitor = kdbus_hello(bus, KDBUS_HELLO_MONITOR, NULL, 0); |
31661 |
++ ASSERT_EXIT(monitor); |
31662 |
++ |
31663 |
++ /* |
31664 |
++ * parent will signal to child that is in its |
31665 |
++ * userns to read its queue |
31666 |
++ */ |
31667 |
++ efd = eventfd(0, EFD_CLOEXEC); |
31668 |
++ ASSERT_RETURN_VAL(efd >= 0, efd); |
31669 |
++ |
31670 |
++ ppid = getppid(); |
31671 |
++ |
31672 |
++ pid = fork(); |
31673 |
++ ASSERT_RETURN_VAL(pid >= 0, -errno); |
31674 |
++ |
31675 |
++ if (pid == 0) { |
31676 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
31677 |
++ ASSERT_EXIT_VAL(ret == 0, -errno); |
31678 |
++ |
31679 |
++ ret = __kdbus_clone_userns_test(bus, conn, ppid, efd); |
31680 |
++ _exit(ret); |
31681 |
++ } |
31682 |
++ |
31683 |
++ |
31684 |
++ /* Phase 1) privileged receives from unprivileged */ |
31685 |
++ |
31686 |
++ /* |
31687 |
++ * Receive from the unprivileged child |
31688 |
++ */ |
31689 |
++ kdbus_printf("\nUnprivileged → privileged (same namespaces):\n"); |
31690 |
++ ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL); |
31691 |
++ ASSERT_RETURN(ret == 0); |
31692 |
++ |
31693 |
++ unpriv_conn_id = msg->src_id; |
31694 |
++ |
31695 |
++ /* Unprivileged user */ |
31696 |
++ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31697 |
++ ASSERT_RETURN(ret == 0); |
31698 |
++ |
31699 |
++ /* Set the expected creds_pids */ |
31700 |
++ expected_pids = (struct kdbus_pids) { |
31701 |
++ .pid = pid, |
31702 |
++ .tid = pid, |
31703 |
++ .ppid = getpid(), |
31704 |
++ }; |
31705 |
++ ret = kdbus_match_kdbus_pids(msg, &expected_pids); |
31706 |
++ ASSERT_RETURN(ret == 0); |
31707 |
++ |
31708 |
++ kdbus_msg_free(msg); |
31709 |
++ |
31710 |
++ |
31711 |
++ /* |
31712 |
++ * Receive from the unprivileged that is in his own |
31713 |
++ * userns and pidns |
31714 |
++ */ |
31715 |
++ |
31716 |
++ kdbus_printf("\nUnprivileged/privileged in its userns → privileged " |
31717 |
++ "(different userns and pidns)\n"); |
31718 |
++ ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL); |
31719 |
++ if (ret == -ETIMEDOUT) |
31720 |
++ /* perhaps unprivileged userns is not allowed */ |
31721 |
++ goto wait; |
31722 |
++ |
31723 |
++ ASSERT_RETURN(ret == 0); |
31724 |
++ |
31725 |
++ userns_conn_id = msg->src_id; |
31726 |
++ |
31727 |
++ /* We do not share the userns, os no KDBUS_ITEM_CAPS */ |
31728 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31729 |
++ ASSERT_RETURN(item == NULL); |
31730 |
++ |
31731 |
++ /* |
31732 |
++ * Compare received items, creds must be translated into |
31733 |
++ * the receiver user namespace, so the user is unprivileged |
31734 |
++ */ |
31735 |
++ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31736 |
++ ASSERT_RETURN(ret == 0); |
31737 |
++ |
31738 |
++ /* |
31739 |
++ * We should have the kdbus_pids since we are the parent |
31740 |
++ * pidns |
31741 |
++ */ |
31742 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31743 |
++ ASSERT_RETURN(item); |
31744 |
++ |
31745 |
++ ASSERT_RETURN(memcmp(&item->pids, &unmapped_pids, |
31746 |
++ sizeof(struct kdbus_pids)) != 0); |
31747 |
++ |
31748 |
++ /* |
31749 |
++ * Parent pid of the unprivileged/privileged in its userns |
31750 |
++ * is the unprivileged child pid that was forked here. |
31751 |
++ */ |
31752 |
++ ASSERT_RETURN((uint64_t)pid == item->pids.ppid); |
31753 |
++ |
31754 |
++ kdbus_msg_free(msg); |
31755 |
++ |
31756 |
++ |
31757 |
++ /* Phase 2) Privileged connection sends now 3 packets */ |
31758 |
++ |
31759 |
++ /* |
31760 |
++ * Sending to unprivileged connections a unicast |
31761 |
++ */ |
31762 |
++ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31763 |
++ 0, unpriv_conn_id); |
31764 |
++ ASSERT_RETURN(ret == 0); |
31765 |
++ |
31766 |
++ /* signal to child that is in its userns */ |
31767 |
++ ret = eventfd_write(efd, 1); |
31768 |
++ ASSERT_EXIT(ret == 0); |
31769 |
++ |
31770 |
++ /* |
31771 |
++ * Sending to unprivileged/privilged in its userns |
31772 |
++ * connections a unicast |
31773 |
++ */ |
31774 |
++ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31775 |
++ 0, userns_conn_id); |
31776 |
++ ASSERT_RETURN(ret == 0); |
31777 |
++ |
31778 |
++ /* |
31779 |
++ * Sending to unprivileged connections a broadcast |
31780 |
++ */ |
31781 |
++ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31782 |
++ 0, KDBUS_DST_ID_BROADCAST); |
31783 |
++ ASSERT_RETURN(ret == 0); |
31784 |
++ |
31785 |
++ |
31786 |
++wait: |
31787 |
++ ret = waitpid(pid, &status, 0); |
31788 |
++ ASSERT_RETURN(ret >= 0); |
31789 |
++ |
31790 |
++ ASSERT_RETURN(WIFEXITED(status)) |
31791 |
++ ASSERT_RETURN(!WEXITSTATUS(status)); |
31792 |
++ |
31793 |
++ /* Dump monitor queue */ |
31794 |
++ kdbus_printf("\n\nMonitor queue:\n"); |
31795 |
++ for (;;) { |
31796 |
++ ret = kdbus_msg_recv_poll(monitor, 100, &msg, NULL); |
31797 |
++ if (ret < 0) |
31798 |
++ break; |
31799 |
++ |
31800 |
++ if (msg->payload_type == KDBUS_PAYLOAD_DBUS) { |
31801 |
++ /* |
31802 |
++ * Parent pidns should see all the |
31803 |
++ * pids |
31804 |
++ */ |
31805 |
++ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31806 |
++ ASSERT_RETURN(item); |
31807 |
++ |
31808 |
++ ASSERT_RETURN(item->pids.pid != 0 && |
31809 |
++ item->pids.tid != 0 && |
31810 |
++ item->pids.ppid != 0); |
31811 |
++ } |
31812 |
++ |
31813 |
++ kdbus_msg_free(msg); |
31814 |
++ } |
31815 |
++ |
31816 |
++ kdbus_conn_free(monitor); |
31817 |
++ close(efd); |
31818 |
++ |
31819 |
++ return 0; |
31820 |
++} |
31821 |
++ |
31822 |
++int kdbus_test_metadata_ns(struct kdbus_test_env *env) |
31823 |
++{ |
31824 |
++ int ret; |
31825 |
++ struct kdbus_conn *holder, *conn; |
31826 |
++ struct kdbus_policy_access policy_access = { |
31827 |
++ /* Allow world so we can inspect metadata in namespace */ |
31828 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
31829 |
++ .id = geteuid(), |
31830 |
++ .access = KDBUS_POLICY_TALK, |
31831 |
++ }; |
31832 |
++ |
31833 |
++ /* |
31834 |
++ * We require user-namespaces and all uids/gids |
31835 |
++ * should be mapped (we can just require the necessary ones) |
31836 |
++ */ |
31837 |
++ if (!config_user_ns_is_enabled() || |
31838 |
++ !all_uids_gids_are_mapped()) |
31839 |
++ return TEST_SKIP; |
31840 |
++ |
31841 |
++ ret = test_is_capable(CAP_SETUID, CAP_SETGID, CAP_SYS_ADMIN, -1); |
31842 |
++ ASSERT_RETURN(ret >= 0); |
31843 |
++ |
31844 |
++ /* no enough privileges, SKIP test */ |
31845 |
++ if (!ret) |
31846 |
++ return TEST_SKIP; |
31847 |
++ |
31848 |
++ holder = kdbus_hello_registrar(env->buspath, "com.example.metadata", |
31849 |
++ &policy_access, 1, |
31850 |
++ KDBUS_HELLO_POLICY_HOLDER); |
31851 |
++ ASSERT_RETURN(holder); |
31852 |
++ |
31853 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31854 |
++ ASSERT_RETURN(conn); |
31855 |
++ |
31856 |
++ ret = kdbus_add_match_empty(conn); |
31857 |
++ ASSERT_RETURN(ret == 0); |
31858 |
++ |
31859 |
++ ret = kdbus_name_acquire(conn, "com.example.metadata", NULL); |
31860 |
++ ASSERT_EXIT(ret >= 0); |
31861 |
++ |
31862 |
++ ret = kdbus_clone_userns_test(env->buspath, conn); |
31863 |
++ ASSERT_RETURN(ret == 0); |
31864 |
++ |
31865 |
++ kdbus_conn_free(holder); |
31866 |
++ kdbus_conn_free(conn); |
31867 |
++ |
31868 |
++ return TEST_OK; |
31869 |
++} |
31870 |
+diff --git a/tools/testing/selftests/kdbus/test-monitor.c b/tools/testing/selftests/kdbus/test-monitor.c |
31871 |
+new file mode 100644 |
31872 |
+index 0000000..e00d738 |
31873 |
+--- /dev/null |
31874 |
++++ b/tools/testing/selftests/kdbus/test-monitor.c |
31875 |
+@@ -0,0 +1,176 @@ |
31876 |
++#include <stdio.h> |
31877 |
++#include <string.h> |
31878 |
++#include <time.h> |
31879 |
++#include <fcntl.h> |
31880 |
++#include <stdlib.h> |
31881 |
++#include <stddef.h> |
31882 |
++#include <unistd.h> |
31883 |
++#include <stdint.h> |
31884 |
++#include <stdbool.h> |
31885 |
++#include <errno.h> |
31886 |
++#include <assert.h> |
31887 |
++#include <signal.h> |
31888 |
++#include <sys/time.h> |
31889 |
++#include <sys/mman.h> |
31890 |
++#include <sys/capability.h> |
31891 |
++#include <sys/wait.h> |
31892 |
++ |
31893 |
++#include "kdbus-util.h" |
31894 |
++#include "kdbus-enum.h" |
31895 |
++ |
31896 |
++#include "kdbus-util.h" |
31897 |
++#include "kdbus-enum.h" |
31898 |
++#include "kdbus-test.h" |
31899 |
++ |
31900 |
++int kdbus_test_monitor(struct kdbus_test_env *env) |
31901 |
++{ |
31902 |
++ struct kdbus_conn *monitor, *conn; |
31903 |
++ unsigned int cookie = 0xdeadbeef; |
31904 |
++ struct kdbus_msg *msg; |
31905 |
++ uint64_t offset = 0; |
31906 |
++ int ret; |
31907 |
++ |
31908 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31909 |
++ ASSERT_RETURN(conn); |
31910 |
++ |
31911 |
++ /* add matches to make sure the monitor do not trigger an item add or |
31912 |
++ * remove on connect and disconnect, respectively. |
31913 |
++ */ |
31914 |
++ ret = kdbus_add_match_id(conn, 0x1, KDBUS_ITEM_ID_ADD, |
31915 |
++ KDBUS_MATCH_ID_ANY); |
31916 |
++ ASSERT_RETURN(ret == 0); |
31917 |
++ |
31918 |
++ ret = kdbus_add_match_id(conn, 0x2, KDBUS_ITEM_ID_REMOVE, |
31919 |
++ KDBUS_MATCH_ID_ANY); |
31920 |
++ ASSERT_RETURN(ret == 0); |
31921 |
++ |
31922 |
++ /* register a monitor */ |
31923 |
++ monitor = kdbus_hello(env->buspath, KDBUS_HELLO_MONITOR, NULL, 0); |
31924 |
++ ASSERT_RETURN(monitor); |
31925 |
++ |
31926 |
++ /* make sure we did not receive a monitor connect notification */ |
31927 |
++ ret = kdbus_msg_recv(conn, &msg, &offset); |
31928 |
++ ASSERT_RETURN(ret == -EAGAIN); |
31929 |
++ |
31930 |
++ /* check that a monitor cannot acquire a name */ |
31931 |
++ ret = kdbus_name_acquire(monitor, "foo.bar.baz", NULL); |
31932 |
++ ASSERT_RETURN(ret == -EOPNOTSUPP); |
31933 |
++ |
31934 |
++ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, conn->id); |
31935 |
++ ASSERT_RETURN(ret == 0); |
31936 |
++ |
31937 |
++ /* the recipient should have gotten the message */ |
31938 |
++ ret = kdbus_msg_recv(conn, &msg, &offset); |
31939 |
++ ASSERT_RETURN(ret == 0); |
31940 |
++ ASSERT_RETURN(msg->cookie == cookie); |
31941 |
++ kdbus_msg_free(msg); |
31942 |
++ kdbus_free(conn, offset); |
31943 |
++ |
31944 |
++ /* and so should the monitor */ |
31945 |
++ ret = kdbus_msg_recv(monitor, &msg, &offset); |
31946 |
++ ASSERT_RETURN(ret == 0); |
31947 |
++ ASSERT_RETURN(msg->cookie == cookie); |
31948 |
++ |
31949 |
++ kdbus_msg_free(msg); |
31950 |
++ kdbus_free(monitor, offset); |
31951 |
++ |
31952 |
++ /* Installing matches for monitors must fais must fail */ |
31953 |
++ ret = kdbus_add_match_empty(monitor); |
31954 |
++ ASSERT_RETURN(ret == -EOPNOTSUPP); |
31955 |
++ |
31956 |
++ cookie++; |
31957 |
++ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31958 |
++ KDBUS_DST_ID_BROADCAST); |
31959 |
++ ASSERT_RETURN(ret == 0); |
31960 |
++ |
31961 |
++ /* The monitor should get the message. */ |
31962 |
++ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31963 |
++ ASSERT_RETURN(ret == 0); |
31964 |
++ ASSERT_RETURN(msg->cookie == cookie); |
31965 |
++ |
31966 |
++ kdbus_msg_free(msg); |
31967 |
++ kdbus_free(monitor, offset); |
31968 |
++ |
31969 |
++ /* |
31970 |
++ * Since we are the only monitor, update the attach flags |
31971 |
++ * and tell we are not interessted in attach flags recv |
31972 |
++ */ |
31973 |
++ |
31974 |
++ ret = kdbus_conn_update_attach_flags(monitor, |
31975 |
++ _KDBUS_ATTACH_ALL, |
31976 |
++ 0); |
31977 |
++ ASSERT_RETURN(ret == 0); |
31978 |
++ |
31979 |
++ cookie++; |
31980 |
++ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31981 |
++ KDBUS_DST_ID_BROADCAST); |
31982 |
++ ASSERT_RETURN(ret == 0); |
31983 |
++ |
31984 |
++ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31985 |
++ ASSERT_RETURN(ret == 0); |
31986 |
++ ASSERT_RETURN(msg->cookie == cookie); |
31987 |
++ |
31988 |
++ ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
31989 |
++ ASSERT_RETURN(ret == 0); |
31990 |
++ |
31991 |
++ kdbus_msg_free(msg); |
31992 |
++ kdbus_free(monitor, offset); |
31993 |
++ |
31994 |
++ /* |
31995 |
++ * Now we are interested in KDBUS_ITEM_TIMESTAMP and |
31996 |
++ * KDBUS_ITEM_CREDS |
31997 |
++ */ |
31998 |
++ ret = kdbus_conn_update_attach_flags(monitor, |
31999 |
++ _KDBUS_ATTACH_ALL, |
32000 |
++ KDBUS_ATTACH_TIMESTAMP | |
32001 |
++ KDBUS_ATTACH_CREDS); |
32002 |
++ ASSERT_RETURN(ret == 0); |
32003 |
++ |
32004 |
++ cookie++; |
32005 |
++ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
32006 |
++ KDBUS_DST_ID_BROADCAST); |
32007 |
++ ASSERT_RETURN(ret == 0); |
32008 |
++ |
32009 |
++ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
32010 |
++ ASSERT_RETURN(ret == 0); |
32011 |
++ ASSERT_RETURN(msg->cookie == cookie); |
32012 |
++ |
32013 |
++ ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
32014 |
++ ASSERT_RETURN(ret == 1); |
32015 |
++ |
32016 |
++ ret = kdbus_item_in_message(msg, KDBUS_ITEM_CREDS); |
32017 |
++ ASSERT_RETURN(ret == 1); |
32018 |
++ |
32019 |
++ /* the KDBUS_ITEM_PID_COMM was not requested */ |
32020 |
++ ret = kdbus_item_in_message(msg, KDBUS_ITEM_PID_COMM); |
32021 |
++ ASSERT_RETURN(ret == 0); |
32022 |
++ |
32023 |
++ kdbus_msg_free(msg); |
32024 |
++ kdbus_free(monitor, offset); |
32025 |
++ |
32026 |
++ kdbus_conn_free(monitor); |
32027 |
++ /* make sure we did not receive a monitor disconnect notification */ |
32028 |
++ ret = kdbus_msg_recv(conn, &msg, &offset); |
32029 |
++ ASSERT_RETURN(ret == -EAGAIN); |
32030 |
++ |
32031 |
++ kdbus_conn_free(conn); |
32032 |
++ |
32033 |
++ /* Make sure that monitor as unprivileged is not allowed */ |
32034 |
++ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
32035 |
++ ASSERT_RETURN(ret >= 0); |
32036 |
++ |
32037 |
++ if (ret && all_uids_gids_are_mapped()) { |
32038 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
32039 |
++ monitor = kdbus_hello(env->buspath, |
32040 |
++ KDBUS_HELLO_MONITOR, |
32041 |
++ NULL, 0); |
32042 |
++ ASSERT_EXIT(!monitor && errno == EPERM); |
32043 |
++ |
32044 |
++ _exit(EXIT_SUCCESS); |
32045 |
++ }), |
32046 |
++ ({ 0; })); |
32047 |
++ ASSERT_RETURN(ret == 0); |
32048 |
++ } |
32049 |
++ |
32050 |
++ return TEST_OK; |
32051 |
++} |
32052 |
+diff --git a/tools/testing/selftests/kdbus/test-names.c b/tools/testing/selftests/kdbus/test-names.c |
32053 |
+new file mode 100644 |
32054 |
+index 0000000..66ebb47 |
32055 |
+--- /dev/null |
32056 |
++++ b/tools/testing/selftests/kdbus/test-names.c |
32057 |
+@@ -0,0 +1,194 @@ |
32058 |
++#include <stdio.h> |
32059 |
++#include <string.h> |
32060 |
++#include <time.h> |
32061 |
++#include <fcntl.h> |
32062 |
++#include <stdlib.h> |
32063 |
++#include <stddef.h> |
32064 |
++#include <unistd.h> |
32065 |
++#include <stdint.h> |
32066 |
++#include <errno.h> |
32067 |
++#include <assert.h> |
32068 |
++#include <limits.h> |
32069 |
++#include <getopt.h> |
32070 |
++#include <stdbool.h> |
32071 |
++ |
32072 |
++#include "kdbus-api.h" |
32073 |
++#include "kdbus-util.h" |
32074 |
++#include "kdbus-enum.h" |
32075 |
++#include "kdbus-test.h" |
32076 |
++ |
32077 |
++static int conn_is_name_owner(const struct kdbus_conn *conn, |
32078 |
++ const char *needle) |
32079 |
++{ |
32080 |
++ struct kdbus_cmd_list cmd_list = { .size = sizeof(cmd_list) }; |
32081 |
++ struct kdbus_info *name, *list; |
32082 |
++ bool found = false; |
32083 |
++ int ret; |
32084 |
++ |
32085 |
++ cmd_list.flags = KDBUS_LIST_NAMES; |
32086 |
++ |
32087 |
++ ret = kdbus_cmd_list(conn->fd, &cmd_list); |
32088 |
++ ASSERT_RETURN(ret == 0); |
32089 |
++ |
32090 |
++ list = (struct kdbus_info *)(conn->buf + cmd_list.offset); |
32091 |
++ KDBUS_FOREACH(name, list, cmd_list.list_size) { |
32092 |
++ struct kdbus_item *item; |
32093 |
++ const char *n = NULL; |
32094 |
++ |
32095 |
++ KDBUS_ITEM_FOREACH(item, name, items) |
32096 |
++ if (item->type == KDBUS_ITEM_OWNED_NAME) |
32097 |
++ n = item->name.name; |
32098 |
++ |
32099 |
++ if (name->id == conn->id && |
32100 |
++ n && strcmp(needle, n) == 0) { |
32101 |
++ found = true; |
32102 |
++ break; |
32103 |
++ } |
32104 |
++ } |
32105 |
++ |
32106 |
++ ret = kdbus_free(conn, cmd_list.offset); |
32107 |
++ ASSERT_RETURN(ret == 0); |
32108 |
++ |
32109 |
++ return found ? 0 : -1; |
32110 |
++} |
32111 |
++ |
32112 |
++int kdbus_test_name_basic(struct kdbus_test_env *env) |
32113 |
++{ |
32114 |
++ struct kdbus_conn *conn; |
32115 |
++ char *name, *dot_name, *invalid_name, *wildcard_name; |
32116 |
++ int ret; |
32117 |
++ |
32118 |
++ name = "foo.bla.blaz"; |
32119 |
++ dot_name = ".bla.blaz"; |
32120 |
++ invalid_name = "foo"; |
32121 |
++ wildcard_name = "foo.bla.bl.*"; |
32122 |
++ |
32123 |
++ /* create a 2nd connection */ |
32124 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
32125 |
++ ASSERT_RETURN(conn != NULL); |
32126 |
++ |
32127 |
++ /* acquire name "foo.bar.xxx" name */ |
32128 |
++ ret = kdbus_name_acquire(conn, "foo.bar.xxx", NULL); |
32129 |
++ ASSERT_RETURN(ret == 0); |
32130 |
++ |
32131 |
++ /* Name is not valid, must fail */ |
32132 |
++ ret = kdbus_name_acquire(env->conn, dot_name, NULL); |
32133 |
++ ASSERT_RETURN(ret == -EINVAL); |
32134 |
++ |
32135 |
++ ret = kdbus_name_acquire(env->conn, invalid_name, NULL); |
32136 |
++ ASSERT_RETURN(ret == -EINVAL); |
32137 |
++ |
32138 |
++ ret = kdbus_name_acquire(env->conn, wildcard_name, NULL); |
32139 |
++ ASSERT_RETURN(ret == -EINVAL); |
32140 |
++ |
32141 |
++ /* check that we can acquire a name */ |
32142 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
32143 |
++ ASSERT_RETURN(ret == 0); |
32144 |
++ |
32145 |
++ ret = conn_is_name_owner(env->conn, name); |
32146 |
++ ASSERT_RETURN(ret == 0); |
32147 |
++ |
32148 |
++ /* ... and release it again */ |
32149 |
++ ret = kdbus_name_release(env->conn, name); |
32150 |
++ ASSERT_RETURN(ret == 0); |
32151 |
++ |
32152 |
++ ret = conn_is_name_owner(env->conn, name); |
32153 |
++ ASSERT_RETURN(ret != 0); |
32154 |
++ |
32155 |
++ /* check that we can't release it again */ |
32156 |
++ ret = kdbus_name_release(env->conn, name); |
32157 |
++ ASSERT_RETURN(ret == -ESRCH); |
32158 |
++ |
32159 |
++ /* check that we can't release a name that we don't own */ |
32160 |
++ ret = kdbus_name_release(env->conn, "foo.bar.xxx"); |
32161 |
++ ASSERT_RETURN(ret == -EADDRINUSE); |
32162 |
++ |
32163 |
++ /* Name is not valid, must fail */ |
32164 |
++ ret = kdbus_name_release(env->conn, dot_name); |
32165 |
++ ASSERT_RETURN(ret == -ESRCH); |
32166 |
++ |
32167 |
++ ret = kdbus_name_release(env->conn, invalid_name); |
32168 |
++ ASSERT_RETURN(ret == -ESRCH); |
32169 |
++ |
32170 |
++ ret = kdbus_name_release(env->conn, wildcard_name); |
32171 |
++ ASSERT_RETURN(ret == -ESRCH); |
32172 |
++ |
32173 |
++ kdbus_conn_free(conn); |
32174 |
++ |
32175 |
++ return TEST_OK; |
32176 |
++} |
32177 |
++ |
32178 |
++int kdbus_test_name_conflict(struct kdbus_test_env *env) |
32179 |
++{ |
32180 |
++ struct kdbus_conn *conn; |
32181 |
++ char *name; |
32182 |
++ int ret; |
32183 |
++ |
32184 |
++ name = "foo.bla.blaz"; |
32185 |
++ |
32186 |
++ /* create a 2nd connection */ |
32187 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
32188 |
++ ASSERT_RETURN(conn != NULL); |
32189 |
++ |
32190 |
++ /* allow the new connection to own the same name */ |
32191 |
++ /* acquire name from the 1st connection */ |
32192 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
32193 |
++ ASSERT_RETURN(ret == 0); |
32194 |
++ |
32195 |
++ ret = conn_is_name_owner(env->conn, name); |
32196 |
++ ASSERT_RETURN(ret == 0); |
32197 |
++ |
32198 |
++ /* check that we can't acquire it again from the 1st connection */ |
32199 |
++ ret = kdbus_name_acquire(env->conn, name, NULL); |
32200 |
++ ASSERT_RETURN(ret == -EALREADY); |
32201 |
++ |
32202 |
++ /* check that we also can't acquire it again from the 2nd connection */ |
32203 |
++ ret = kdbus_name_acquire(conn, name, NULL); |
32204 |
++ ASSERT_RETURN(ret == -EEXIST); |
32205 |
++ |
32206 |
++ kdbus_conn_free(conn); |
32207 |
++ |
32208 |
++ return TEST_OK; |
32209 |
++} |
32210 |
++ |
32211 |
++int kdbus_test_name_queue(struct kdbus_test_env *env) |
32212 |
++{ |
32213 |
++ struct kdbus_conn *conn; |
32214 |
++ const char *name; |
32215 |
++ uint64_t flags; |
32216 |
++ int ret; |
32217 |
++ |
32218 |
++ name = "foo.bla.blaz"; |
32219 |
++ |
32220 |
++ flags = KDBUS_NAME_ALLOW_REPLACEMENT; |
32221 |
++ |
32222 |
++ /* create a 2nd connection */ |
32223 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
32224 |
++ ASSERT_RETURN(conn != NULL); |
32225 |
++ |
32226 |
++ /* allow the new connection to own the same name */ |
32227 |
++ /* acquire name from the 1st connection */ |
32228 |
++ ret = kdbus_name_acquire(env->conn, name, &flags); |
32229 |
++ ASSERT_RETURN(ret == 0); |
32230 |
++ |
32231 |
++ ret = conn_is_name_owner(env->conn, name); |
32232 |
++ ASSERT_RETURN(ret == 0); |
32233 |
++ |
32234 |
++ /* queue the 2nd connection as waiting owner */ |
32235 |
++ flags = KDBUS_NAME_QUEUE; |
32236 |
++ ret = kdbus_name_acquire(conn, name, &flags); |
32237 |
++ ASSERT_RETURN(ret == 0); |
32238 |
++ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); |
32239 |
++ |
32240 |
++ /* release name from 1st connection */ |
32241 |
++ ret = kdbus_name_release(env->conn, name); |
32242 |
++ ASSERT_RETURN(ret == 0); |
32243 |
++ |
32244 |
++ /* now the name should be owned by the 2nd connection */ |
32245 |
++ ret = conn_is_name_owner(conn, name); |
32246 |
++ ASSERT_RETURN(ret == 0); |
32247 |
++ |
32248 |
++ kdbus_conn_free(conn); |
32249 |
++ |
32250 |
++ return TEST_OK; |
32251 |
++} |
32252 |
+diff --git a/tools/testing/selftests/kdbus/test-policy-ns.c b/tools/testing/selftests/kdbus/test-policy-ns.c |
32253 |
+new file mode 100644 |
32254 |
+index 0000000..3437012 |
32255 |
+--- /dev/null |
32256 |
++++ b/tools/testing/selftests/kdbus/test-policy-ns.c |
32257 |
+@@ -0,0 +1,632 @@ |
32258 |
++/* |
32259 |
++ * Test metadata and policies in new namespaces. Even if our tests |
32260 |
++ * can run in a namespaced setup, this test is necessary so we can |
32261 |
++ * inspect policies on the same kdbusfs but between multiple |
32262 |
++ * namespaces. |
32263 |
++ * |
32264 |
++ * Copyright (C) 2014-2015 Djalal Harouni |
32265 |
++ * |
32266 |
++ * kdbus is free software; you can redistribute it and/or modify it under |
32267 |
++ * the terms of the GNU Lesser General Public License as published by the |
32268 |
++ * Free Software Foundation; either version 2.1 of the License, or (at |
32269 |
++ * your option) any later version. |
32270 |
++ */ |
32271 |
++ |
32272 |
++#include <stdio.h> |
32273 |
++#include <string.h> |
32274 |
++#include <fcntl.h> |
32275 |
++#include <pthread.h> |
32276 |
++#include <sched.h> |
32277 |
++#include <stdlib.h> |
32278 |
++#include <stddef.h> |
32279 |
++#include <stdint.h> |
32280 |
++#include <stdbool.h> |
32281 |
++#include <unistd.h> |
32282 |
++#include <errno.h> |
32283 |
++#include <signal.h> |
32284 |
++#include <sys/wait.h> |
32285 |
++#include <sys/prctl.h> |
32286 |
++#include <sys/eventfd.h> |
32287 |
++#include <sys/syscall.h> |
32288 |
++#include <sys/capability.h> |
32289 |
++#include <linux/sched.h> |
32290 |
++ |
32291 |
++#include "kdbus-test.h" |
32292 |
++#include "kdbus-util.h" |
32293 |
++#include "kdbus-enum.h" |
32294 |
++ |
32295 |
++#define MAX_CONN 64 |
32296 |
++#define POLICY_NAME "foo.test.policy-test" |
32297 |
++ |
32298 |
++#define KDBUS_CONN_MAX_MSGS_PER_USER 16 |
32299 |
++ |
32300 |
++/** |
32301 |
++ * Note: this test can be used to inspect policy_db->talk_access_hash |
32302 |
++ * |
32303 |
++ * The purpose of these tests: |
32304 |
++ * 1) Check KDBUS_POLICY_TALK |
32305 |
++ * 2) Check the cache state: kdbus_policy_db->talk_access_hash |
32306 |
++ * Should be extended |
32307 |
++ */ |
32308 |
++ |
32309 |
++/** |
32310 |
++ * Check a list of connections against conn_db[0] |
32311 |
++ * conn_db[0] will own the name "foo.test.policy-test" and the |
32312 |
++ * policy holder connection for this name will update the policy |
32313 |
++ * entries, so different use cases can be tested. |
32314 |
++ */ |
32315 |
++static struct kdbus_conn **conn_db; |
32316 |
++ |
32317 |
++static void *kdbus_recv_echo(void *ptr) |
32318 |
++{ |
32319 |
++ int ret; |
32320 |
++ struct kdbus_conn *conn = ptr; |
32321 |
++ |
32322 |
++ ret = kdbus_msg_recv_poll(conn, 200, NULL, NULL); |
32323 |
++ |
32324 |
++ return (void *)(long)ret; |
32325 |
++} |
32326 |
++ |
32327 |
++/* Trigger kdbus_policy_set() */ |
32328 |
++static int kdbus_set_policy_talk(struct kdbus_conn *conn, |
32329 |
++ const char *name, |
32330 |
++ uid_t id, unsigned int type) |
32331 |
++{ |
32332 |
++ int ret; |
32333 |
++ struct kdbus_policy_access access = { |
32334 |
++ .type = type, |
32335 |
++ .id = id, |
32336 |
++ .access = KDBUS_POLICY_TALK, |
32337 |
++ }; |
32338 |
++ |
32339 |
++ ret = kdbus_conn_update_policy(conn, name, &access, 1); |
32340 |
++ ASSERT_RETURN(ret == 0); |
32341 |
++ |
32342 |
++ return TEST_OK; |
32343 |
++} |
32344 |
++ |
32345 |
++/* return TEST_OK or TEST_ERR on failure */ |
32346 |
++static int kdbus_register_same_activator(char *bus, const char *name, |
32347 |
++ struct kdbus_conn **c) |
32348 |
++{ |
32349 |
++ int ret; |
32350 |
++ struct kdbus_conn *activator; |
32351 |
++ |
32352 |
++ activator = kdbus_hello_activator(bus, name, NULL, 0); |
32353 |
++ if (activator) { |
32354 |
++ *c = activator; |
32355 |
++ fprintf(stderr, "--- error was able to register name twice '%s'.\n", |
32356 |
++ name); |
32357 |
++ return TEST_ERR; |
32358 |
++ } |
32359 |
++ |
32360 |
++ ret = -errno; |
32361 |
++ /* -EEXIST means test succeeded */ |
32362 |
++ if (ret == -EEXIST) |
32363 |
++ return TEST_OK; |
32364 |
++ |
32365 |
++ return TEST_ERR; |
32366 |
++} |
32367 |
++ |
32368 |
++/* return TEST_OK or TEST_ERR on failure */ |
32369 |
++static int kdbus_register_policy_holder(char *bus, const char *name, |
32370 |
++ struct kdbus_conn **conn) |
32371 |
++{ |
32372 |
++ struct kdbus_conn *c; |
32373 |
++ struct kdbus_policy_access access[2]; |
32374 |
++ |
32375 |
++ access[0].type = KDBUS_POLICY_ACCESS_USER; |
32376 |
++ access[0].access = KDBUS_POLICY_OWN; |
32377 |
++ access[0].id = geteuid(); |
32378 |
++ |
32379 |
++ access[1].type = KDBUS_POLICY_ACCESS_WORLD; |
32380 |
++ access[1].access = KDBUS_POLICY_TALK; |
32381 |
++ access[1].id = geteuid(); |
32382 |
++ |
32383 |
++ c = kdbus_hello_registrar(bus, name, access, 2, |
32384 |
++ KDBUS_HELLO_POLICY_HOLDER); |
32385 |
++ ASSERT_RETURN(c); |
32386 |
++ |
32387 |
++ *conn = c; |
32388 |
++ |
32389 |
++ return TEST_OK; |
32390 |
++} |
32391 |
++ |
32392 |
++/** |
32393 |
++ * Create new threads for receiving from multiple senders, |
32394 |
++ * The 'conn_db' will be populated by newly created connections. |
32395 |
++ * Caller should free all allocated connections. |
32396 |
++ * |
32397 |
++ * return 0 on success, negative errno on failure. |
32398 |
++ */ |
32399 |
++static int kdbus_recv_in_threads(const char *bus, const char *name, |
32400 |
++ struct kdbus_conn **conn_db) |
32401 |
++{ |
32402 |
++ int ret; |
32403 |
++ bool pool_full = false; |
32404 |
++ unsigned int sent_packets = 0; |
32405 |
++ unsigned int lost_packets = 0; |
32406 |
++ unsigned int i, tid; |
32407 |
++ unsigned long dst_id; |
32408 |
++ unsigned long cookie = 1; |
32409 |
++ unsigned int thread_nr = MAX_CONN - 1; |
32410 |
++ pthread_t thread_id[MAX_CONN - 1] = {'\0'}; |
32411 |
++ |
32412 |
++ dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id; |
32413 |
++ |
32414 |
++ for (tid = 0, i = 1; tid < thread_nr; tid++, i++) { |
32415 |
++ ret = pthread_create(&thread_id[tid], NULL, |
32416 |
++ kdbus_recv_echo, (void *)conn_db[0]); |
32417 |
++ if (ret < 0) { |
32418 |
++ ret = -errno; |
32419 |
++ kdbus_printf("error pthread_create: %d (%m)\n", |
32420 |
++ ret); |
32421 |
++ break; |
32422 |
++ } |
32423 |
++ |
32424 |
++ /* just free before re-using */ |
32425 |
++ kdbus_conn_free(conn_db[i]); |
32426 |
++ conn_db[i] = NULL; |
32427 |
++ |
32428 |
++ /* We need to create connections here */ |
32429 |
++ conn_db[i] = kdbus_hello(bus, 0, NULL, 0); |
32430 |
++ if (!conn_db[i]) { |
32431 |
++ ret = -errno; |
32432 |
++ break; |
32433 |
++ } |
32434 |
++ |
32435 |
++ ret = kdbus_add_match_empty(conn_db[i]); |
32436 |
++ if (ret < 0) |
32437 |
++ break; |
32438 |
++ |
32439 |
++ ret = kdbus_msg_send(conn_db[i], name, cookie++, |
32440 |
++ 0, 0, 0, dst_id); |
32441 |
++ if (ret < 0) { |
32442 |
++ /* |
32443 |
++ * Receivers are not reading their messages, |
32444 |
++ * not scheduled ?! |
32445 |
++ * |
32446 |
++ * So set the pool full here, perhaps the |
32447 |
++ * connection pool or queue was full, later |
32448 |
++ * recheck receivers errors |
32449 |
++ */ |
32450 |
++ if (ret == -ENOBUFS || ret == -EXFULL) |
32451 |
++ pool_full = true; |
32452 |
++ break; |
32453 |
++ } |
32454 |
++ |
32455 |
++ sent_packets++; |
32456 |
++ } |
32457 |
++ |
32458 |
++ for (tid = 0; tid < thread_nr; tid++) { |
32459 |
++ int thread_ret = 0; |
32460 |
++ |
32461 |
++ if (thread_id[tid]) { |
32462 |
++ pthread_join(thread_id[tid], (void *)&thread_ret); |
32463 |
++ if (thread_ret < 0) { |
32464 |
++ /* Update only if send did not fail */ |
32465 |
++ if (ret == 0) |
32466 |
++ ret = thread_ret; |
32467 |
++ |
32468 |
++ lost_packets++; |
32469 |
++ } |
32470 |
++ } |
32471 |
++ } |
32472 |
++ |
32473 |
++ /* |
32474 |
++ * When sending if we did fail with -ENOBUFS or -EXFULL |
32475 |
++ * then we should have set lost_packet and we should at |
32476 |
++ * least have sent_packets set to KDBUS_CONN_MAX_MSGS_PER_USER |
32477 |
++ */ |
32478 |
++ if (pool_full) { |
32479 |
++ ASSERT_RETURN(lost_packets > 0); |
32480 |
++ |
32481 |
++ /* |
32482 |
++ * We should at least send KDBUS_CONN_MAX_MSGS_PER_USER |
32483 |
++ * |
32484 |
++ * For every send operation we create a thread to |
32485 |
++ * recv the packet, so we keep the queue clean |
32486 |
++ */ |
32487 |
++ ASSERT_RETURN(sent_packets >= KDBUS_CONN_MAX_MSGS_PER_USER); |
32488 |
++ |
32489 |
++ /* |
32490 |
++ * Set ret to zero since we only failed due to |
32491 |
++ * the receiving threads that have not been |
32492 |
++ * scheduled |
32493 |
++ */ |
32494 |
++ ret = 0; |
32495 |
++ } |
32496 |
++ |
32497 |
++ return ret; |
32498 |
++} |
32499 |
++ |
32500 |
++/* Return: TEST_OK or TEST_ERR on failure */ |
32501 |
++static int kdbus_normal_test(const char *bus, const char *name, |
32502 |
++ struct kdbus_conn **conn_db) |
32503 |
++{ |
32504 |
++ int ret; |
32505 |
++ |
32506 |
++ ret = kdbus_recv_in_threads(bus, name, conn_db); |
32507 |
++ ASSERT_RETURN(ret >= 0); |
32508 |
++ |
32509 |
++ return TEST_OK; |
32510 |
++} |
32511 |
++ |
32512 |
++static int kdbus_fork_test_by_id(const char *bus, |
32513 |
++ struct kdbus_conn **conn_db, |
32514 |
++ int parent_status, int child_status) |
32515 |
++{ |
32516 |
++ int ret; |
32517 |
++ pid_t pid; |
32518 |
++ uint64_t cookie = 0x9876ecba; |
32519 |
++ struct kdbus_msg *msg = NULL; |
32520 |
++ uint64_t offset = 0; |
32521 |
++ int status = 0; |
32522 |
++ |
32523 |
++ /* |
32524 |
++ * If the child_status is not EXIT_SUCCESS, then we expect |
32525 |
++ * that sending from the child will fail, thus receiving |
32526 |
++ * from parent must error with -ETIMEDOUT, and vice versa. |
32527 |
++ */ |
32528 |
++ bool parent_timedout = !!child_status; |
32529 |
++ bool child_timedout = !!parent_status; |
32530 |
++ |
32531 |
++ pid = fork(); |
32532 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
32533 |
++ |
32534 |
++ if (pid == 0) { |
32535 |
++ struct kdbus_conn *conn_src; |
32536 |
++ |
32537 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32538 |
++ ASSERT_EXIT(ret == 0); |
32539 |
++ |
32540 |
++ ret = drop_privileges(65534, 65534); |
32541 |
++ ASSERT_EXIT(ret == 0); |
32542 |
++ |
32543 |
++ conn_src = kdbus_hello(bus, 0, NULL, 0); |
32544 |
++ ASSERT_EXIT(conn_src); |
32545 |
++ |
32546 |
++ ret = kdbus_add_match_empty(conn_src); |
32547 |
++ ASSERT_EXIT(ret == 0); |
32548 |
++ |
32549 |
++ /* |
32550 |
++ * child_status is always checked against send |
32551 |
++ * operations, in case it fails always return |
32552 |
++ * EXIT_FAILURE. |
32553 |
++ */ |
32554 |
++ ret = kdbus_msg_send(conn_src, NULL, cookie, |
32555 |
++ 0, 0, 0, conn_db[0]->id); |
32556 |
++ ASSERT_EXIT(ret == child_status); |
32557 |
++ |
32558 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); |
32559 |
++ |
32560 |
++ kdbus_conn_free(conn_src); |
32561 |
++ |
32562 |
++ /* |
32563 |
++ * Child kdbus_msg_recv_poll() should timeout since |
32564 |
++ * the parent_status was set to a non EXIT_SUCCESS |
32565 |
++ * value. |
32566 |
++ */ |
32567 |
++ if (child_timedout) |
32568 |
++ _exit(ret == -ETIMEDOUT ? EXIT_SUCCESS : EXIT_FAILURE); |
32569 |
++ |
32570 |
++ _exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); |
32571 |
++ } |
32572 |
++ |
32573 |
++ ret = kdbus_msg_recv_poll(conn_db[0], 100, &msg, &offset); |
32574 |
++ /* |
32575 |
++ * If parent_timedout is set then this should fail with |
32576 |
++ * -ETIMEDOUT since the child_status was set to a non |
32577 |
++ * EXIT_SUCCESS value. Otherwise, assume |
32578 |
++ * that kdbus_msg_recv_poll() has succeeded. |
32579 |
++ */ |
32580 |
++ if (parent_timedout) { |
32581 |
++ ASSERT_RETURN_VAL(ret == -ETIMEDOUT, TEST_ERR); |
32582 |
++ |
32583 |
++ /* timedout no need to continue, we don't have the |
32584 |
++ * child connection ID, so just terminate. */ |
32585 |
++ goto out; |
32586 |
++ } else { |
32587 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
32588 |
++ } |
32589 |
++ |
32590 |
++ ret = kdbus_msg_send(conn_db[0], NULL, ++cookie, |
32591 |
++ 0, 0, 0, msg->src_id); |
32592 |
++ /* |
32593 |
++ * parent_status is checked against send operations, |
32594 |
++ * on failures always return TEST_ERR. |
32595 |
++ */ |
32596 |
++ ASSERT_RETURN_VAL(ret == parent_status, TEST_ERR); |
32597 |
++ |
32598 |
++ kdbus_msg_free(msg); |
32599 |
++ kdbus_free(conn_db[0], offset); |
32600 |
++ |
32601 |
++out: |
32602 |
++ ret = waitpid(pid, &status, 0); |
32603 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
32604 |
++ |
32605 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32606 |
++} |
32607 |
++ |
32608 |
++/* |
32609 |
++ * Return: TEST_OK, TEST_ERR or TEST_SKIP |
32610 |
++ * we return TEST_OK only if the children return with the expected |
32611 |
++ * 'expected_status' that is specified as an argument. |
32612 |
++ */ |
32613 |
++static int kdbus_fork_test(const char *bus, const char *name, |
32614 |
++ struct kdbus_conn **conn_db, int expected_status) |
32615 |
++{ |
32616 |
++ pid_t pid; |
32617 |
++ int ret = 0; |
32618 |
++ int status = 0; |
32619 |
++ |
32620 |
++ pid = fork(); |
32621 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
32622 |
++ |
32623 |
++ if (pid == 0) { |
32624 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32625 |
++ ASSERT_EXIT(ret == 0); |
32626 |
++ |
32627 |
++ ret = drop_privileges(65534, 65534); |
32628 |
++ ASSERT_EXIT(ret == 0); |
32629 |
++ |
32630 |
++ ret = kdbus_recv_in_threads(bus, name, conn_db); |
32631 |
++ _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE); |
32632 |
++ } |
32633 |
++ |
32634 |
++ ret = waitpid(pid, &status, 0); |
32635 |
++ ASSERT_RETURN(ret >= 0); |
32636 |
++ |
32637 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32638 |
++} |
32639 |
++ |
32640 |
++/* Return EXIT_SUCCESS, EXIT_FAILURE or negative errno */ |
32641 |
++static int __kdbus_clone_userns_test(const char *bus, |
32642 |
++ const char *name, |
32643 |
++ struct kdbus_conn **conn_db, |
32644 |
++ int expected_status) |
32645 |
++{ |
32646 |
++ int efd; |
32647 |
++ pid_t pid; |
32648 |
++ int ret = 0; |
32649 |
++ unsigned int uid = 65534; |
32650 |
++ int status; |
32651 |
++ |
32652 |
++ ret = drop_privileges(uid, uid); |
32653 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
32654 |
++ |
32655 |
++ /* |
32656 |
++ * Since we just dropped privileges, the dumpable flag was just |
32657 |
++ * cleared which makes the /proc/$clone_child/uid_map to be |
32658 |
++ * owned by root, hence any userns uid mapping will fail with |
32659 |
++ * -EPERM since the mapping will be done by uid 65534. |
32660 |
++ * |
32661 |
++ * To avoid this set the dumpable flag again which makes procfs |
32662 |
++ * update the /proc/$clone_child/ inodes owner to 65534. |
32663 |
++ * |
32664 |
++ * Using this we will be able write to /proc/$clone_child/uid_map |
32665 |
++ * as uid 65534 and map the uid 65534 to 0 inside the user |
32666 |
++ * namespace. |
32667 |
++ */ |
32668 |
++ ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER); |
32669 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
32670 |
++ |
32671 |
++ /* sync parent/child */ |
32672 |
++ efd = eventfd(0, EFD_CLOEXEC); |
32673 |
++ ASSERT_RETURN_VAL(efd >= 0, efd); |
32674 |
++ |
32675 |
++ pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWUSER, NULL); |
32676 |
++ if (pid < 0) { |
32677 |
++ ret = -errno; |
32678 |
++ kdbus_printf("error clone: %d (%m)\n", ret); |
32679 |
++ /* |
32680 |
++ * Normal user not allowed to create userns, |
32681 |
++ * so nothing to worry about ? |
32682 |
++ */ |
32683 |
++ if (ret == -EPERM) { |
32684 |
++ kdbus_printf("-- CLONE_NEWUSER TEST Failed for uid: %u\n" |
32685 |
++ "-- Make sure that your kernel do not allow " |
32686 |
++ "CLONE_NEWUSER for unprivileged users\n" |
32687 |
++ "-- Upstream Commit: " |
32688 |
++ "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5eaf563e\n", |
32689 |
++ uid); |
32690 |
++ ret = 0; |
32691 |
++ } |
32692 |
++ |
32693 |
++ return ret; |
32694 |
++ } |
32695 |
++ |
32696 |
++ if (pid == 0) { |
32697 |
++ struct kdbus_conn *conn_src; |
32698 |
++ eventfd_t event_status = 0; |
32699 |
++ |
32700 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32701 |
++ ASSERT_EXIT(ret == 0); |
32702 |
++ |
32703 |
++ ret = eventfd_read(efd, &event_status); |
32704 |
++ ASSERT_EXIT(ret >= 0 && event_status == 1); |
32705 |
++ |
32706 |
++ /* ping connection from the new user namespace */ |
32707 |
++ conn_src = kdbus_hello(bus, 0, NULL, 0); |
32708 |
++ ASSERT_EXIT(conn_src); |
32709 |
++ |
32710 |
++ ret = kdbus_add_match_empty(conn_src); |
32711 |
++ ASSERT_EXIT(ret == 0); |
32712 |
++ |
32713 |
++ ret = kdbus_msg_send(conn_src, name, 0xabcd1234, |
32714 |
++ 0, 0, 0, KDBUS_DST_ID_NAME); |
32715 |
++ kdbus_conn_free(conn_src); |
32716 |
++ |
32717 |
++ _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE); |
32718 |
++ } |
32719 |
++ |
32720 |
++ ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"); |
32721 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
32722 |
++ |
32723 |
++ /* Tell child we are ready */ |
32724 |
++ ret = eventfd_write(efd, 1); |
32725 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
32726 |
++ |
32727 |
++ ret = waitpid(pid, &status, 0); |
32728 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
32729 |
++ |
32730 |
++ close(efd); |
32731 |
++ |
32732 |
++ return status == EXIT_SUCCESS ? TEST_OK : TEST_ERR; |
32733 |
++} |
32734 |
++ |
32735 |
++static int kdbus_clone_userns_test(const char *bus, |
32736 |
++ const char *name, |
32737 |
++ struct kdbus_conn **conn_db, |
32738 |
++ int expected_status) |
32739 |
++{ |
32740 |
++ pid_t pid; |
32741 |
++ int ret = 0; |
32742 |
++ int status; |
32743 |
++ |
32744 |
++ pid = fork(); |
32745 |
++ ASSERT_RETURN_VAL(pid >= 0, -errno); |
32746 |
++ |
32747 |
++ if (pid == 0) { |
32748 |
++ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32749 |
++ if (ret < 0) |
32750 |
++ _exit(EXIT_FAILURE); |
32751 |
++ |
32752 |
++ ret = __kdbus_clone_userns_test(bus, name, conn_db, |
32753 |
++ expected_status); |
32754 |
++ _exit(ret); |
32755 |
++ } |
32756 |
++ |
32757 |
++ /* |
32758 |
++ * Receive in the original (root privileged) user namespace, |
32759 |
++ * must fail with -ETIMEDOUT. |
32760 |
++ */ |
32761 |
++ ret = kdbus_msg_recv_poll(conn_db[0], 100, NULL, NULL); |
32762 |
++ ASSERT_RETURN_VAL(ret == -ETIMEDOUT, ret); |
32763 |
++ |
32764 |
++ ret = waitpid(pid, &status, 0); |
32765 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
32766 |
++ |
32767 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32768 |
++} |
32769 |
++ |
32770 |
++int kdbus_test_policy_ns(struct kdbus_test_env *env) |
32771 |
++{ |
32772 |
++ int i; |
32773 |
++ int ret; |
32774 |
++ struct kdbus_conn *activator = NULL; |
32775 |
++ struct kdbus_conn *policy_holder = NULL; |
32776 |
++ char *bus = env->buspath; |
32777 |
++ |
32778 |
++ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
32779 |
++ ASSERT_RETURN(ret >= 0); |
32780 |
++ |
32781 |
++ /* no enough privileges, SKIP test */ |
32782 |
++ if (!ret) |
32783 |
++ return TEST_SKIP; |
32784 |
++ |
32785 |
++ /* we require user-namespaces */ |
32786 |
++ if (access("/proc/self/uid_map", F_OK) != 0) |
32787 |
++ return TEST_SKIP; |
32788 |
++ |
32789 |
++ /* uids/gids must be mapped */ |
32790 |
++ if (!all_uids_gids_are_mapped()) |
32791 |
++ return TEST_SKIP; |
32792 |
++ |
32793 |
++ conn_db = calloc(MAX_CONN, sizeof(struct kdbus_conn *)); |
32794 |
++ ASSERT_RETURN(conn_db); |
32795 |
++ |
32796 |
++ memset(conn_db, 0, MAX_CONN * sizeof(struct kdbus_conn *)); |
32797 |
++ |
32798 |
++ conn_db[0] = kdbus_hello(bus, 0, NULL, 0); |
32799 |
++ ASSERT_RETURN(conn_db[0]); |
32800 |
++ |
32801 |
++ ret = kdbus_add_match_empty(conn_db[0]); |
32802 |
++ ASSERT_RETURN(ret == 0); |
32803 |
++ |
32804 |
++ ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM); |
32805 |
++ ASSERT_EXIT(ret == 0); |
32806 |
++ |
32807 |
++ ret = kdbus_register_policy_holder(bus, POLICY_NAME, |
32808 |
++ &policy_holder); |
32809 |
++ ASSERT_RETURN(ret == 0); |
32810 |
++ |
32811 |
++ /* Try to register the same name with an activator */ |
32812 |
++ ret = kdbus_register_same_activator(bus, POLICY_NAME, |
32813 |
++ &activator); |
32814 |
++ ASSERT_RETURN(ret == 0); |
32815 |
++ |
32816 |
++ /* Acquire POLICY_NAME */ |
32817 |
++ ret = kdbus_name_acquire(conn_db[0], POLICY_NAME, NULL); |
32818 |
++ ASSERT_RETURN(ret == 0); |
32819 |
++ |
32820 |
++ ret = kdbus_normal_test(bus, POLICY_NAME, conn_db); |
32821 |
++ ASSERT_RETURN(ret == 0); |
32822 |
++ |
32823 |
++ ret = kdbus_list(conn_db[0], KDBUS_LIST_NAMES | |
32824 |
++ KDBUS_LIST_UNIQUE | |
32825 |
++ KDBUS_LIST_ACTIVATORS | |
32826 |
++ KDBUS_LIST_QUEUED); |
32827 |
++ ASSERT_RETURN(ret == 0); |
32828 |
++ |
32829 |
++ ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, EXIT_SUCCESS); |
32830 |
++ ASSERT_RETURN(ret == 0); |
32831 |
++ |
32832 |
++ /* |
32833 |
++ * children connections are able to talk to conn_db[0] since |
32834 |
++ * current POLICY_NAME TALK type is KDBUS_POLICY_ACCESS_WORLD, |
32835 |
++ * so expect EXIT_SUCCESS when sending from child. However, |
32836 |
++ * since the child's connection does not own any well-known |
32837 |
++ * name, The parent connection conn_db[0] should fail with |
32838 |
++ * -EPERM but since it is a privileged bus user the TALK is |
32839 |
++ * allowed. |
32840 |
++ */ |
32841 |
++ ret = kdbus_fork_test_by_id(bus, conn_db, |
32842 |
++ EXIT_SUCCESS, EXIT_SUCCESS); |
32843 |
++ ASSERT_EXIT(ret == 0); |
32844 |
++ |
32845 |
++ /* |
32846 |
++ * Connections that can talk are perhaps being destroyed now. |
32847 |
++ * Restrict the policy and purge cache entries where the |
32848 |
++ * conn_db[0] is the destination. |
32849 |
++ * |
32850 |
++ * Now only connections with uid == 0 are allowed to talk. |
32851 |
++ */ |
32852 |
++ ret = kdbus_set_policy_talk(policy_holder, POLICY_NAME, |
32853 |
++ geteuid(), KDBUS_POLICY_ACCESS_USER); |
32854 |
++ ASSERT_RETURN(ret == 0); |
32855 |
++ |
32856 |
++ /* |
32857 |
++ * Testing connections (FORK+DROP) again: |
32858 |
++ * After setting the policy re-check connections |
32859 |
++ * we expect the children to fail with -EPERM |
32860 |
++ */ |
32861 |
++ ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, -EPERM); |
32862 |
++ ASSERT_RETURN(ret == 0); |
32863 |
++ |
32864 |
++ /* |
32865 |
++ * Now expect that both parent and child to fail. |
32866 |
++ * |
32867 |
++ * Child should fail with -EPERM since we just restricted |
32868 |
++ * the POLICY_NAME TALK to uid 0 and its uid is 65534. |
32869 |
++ * |
32870 |
++ * Since the parent's connection will timeout when receiving |
32871 |
++ * from the child, we never continue. FWIW just put -EPERM. |
32872 |
++ */ |
32873 |
++ ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM); |
32874 |
++ ASSERT_EXIT(ret == 0); |
32875 |
++ |
32876 |
++ /* Check if the name can be reached in a new userns */ |
32877 |
++ ret = kdbus_clone_userns_test(bus, POLICY_NAME, conn_db, -EPERM); |
32878 |
++ ASSERT_RETURN(ret == 0); |
32879 |
++ |
32880 |
++ for (i = 0; i < MAX_CONN; i++) |
32881 |
++ kdbus_conn_free(conn_db[i]); |
32882 |
++ |
32883 |
++ kdbus_conn_free(activator); |
32884 |
++ kdbus_conn_free(policy_holder); |
32885 |
++ |
32886 |
++ free(conn_db); |
32887 |
++ |
32888 |
++ return ret; |
32889 |
++} |
32890 |
+diff --git a/tools/testing/selftests/kdbus/test-policy-priv.c b/tools/testing/selftests/kdbus/test-policy-priv.c |
32891 |
+new file mode 100644 |
32892 |
+index 0000000..a318ccc |
32893 |
+--- /dev/null |
32894 |
++++ b/tools/testing/selftests/kdbus/test-policy-priv.c |
32895 |
+@@ -0,0 +1,1269 @@ |
32896 |
++#include <errno.h> |
32897 |
++#include <stdio.h> |
32898 |
++#include <string.h> |
32899 |
++#include <fcntl.h> |
32900 |
++#include <stdlib.h> |
32901 |
++#include <stdint.h> |
32902 |
++#include <stdbool.h> |
32903 |
++#include <unistd.h> |
32904 |
++#include <time.h> |
32905 |
++#include <sys/capability.h> |
32906 |
++#include <sys/eventfd.h> |
32907 |
++#include <sys/wait.h> |
32908 |
++ |
32909 |
++#include "kdbus-test.h" |
32910 |
++#include "kdbus-util.h" |
32911 |
++#include "kdbus-enum.h" |
32912 |
++ |
32913 |
++static int test_policy_priv_by_id(const char *bus, |
32914 |
++ struct kdbus_conn *conn_dst, |
32915 |
++ bool drop_second_user, |
32916 |
++ int parent_status, |
32917 |
++ int child_status) |
32918 |
++{ |
32919 |
++ int ret = 0; |
32920 |
++ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32921 |
++ |
32922 |
++ ASSERT_RETURN(conn_dst); |
32923 |
++ |
32924 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, bus, ({ |
32925 |
++ ret = kdbus_msg_send(unpriv, NULL, |
32926 |
++ expected_cookie, 0, 0, 0, |
32927 |
++ conn_dst->id); |
32928 |
++ ASSERT_EXIT(ret == child_status); |
32929 |
++ })); |
32930 |
++ ASSERT_RETURN(ret >= 0); |
32931 |
++ |
32932 |
++ ret = kdbus_msg_recv_poll(conn_dst, 300, NULL, NULL); |
32933 |
++ ASSERT_RETURN(ret == parent_status); |
32934 |
++ |
32935 |
++ return 0; |
32936 |
++} |
32937 |
++ |
32938 |
++static int test_policy_priv_by_broadcast(const char *bus, |
32939 |
++ struct kdbus_conn *conn_dst, |
32940 |
++ int drop_second_user, |
32941 |
++ int parent_status, |
32942 |
++ int child_status) |
32943 |
++{ |
32944 |
++ int efd; |
32945 |
++ int ret = 0; |
32946 |
++ eventfd_t event_status = 0; |
32947 |
++ struct kdbus_msg *msg = NULL; |
32948 |
++ uid_t second_uid = UNPRIV_UID; |
32949 |
++ gid_t second_gid = UNPRIV_GID; |
32950 |
++ struct kdbus_conn *child_2 = conn_dst; |
32951 |
++ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32952 |
++ |
32953 |
++ /* Drop to another unprivileged user other than UNPRIV_UID */ |
32954 |
++ if (drop_second_user == DROP_OTHER_UNPRIV) { |
32955 |
++ second_uid = UNPRIV_UID - 1; |
32956 |
++ second_gid = UNPRIV_GID - 1; |
32957 |
++ } |
32958 |
++ |
32959 |
++ /* child will signal parent to send broadcast */ |
32960 |
++ efd = eventfd(0, EFD_CLOEXEC); |
32961 |
++ ASSERT_RETURN_VAL(efd >= 0, efd); |
32962 |
++ |
32963 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
32964 |
++ struct kdbus_conn *child; |
32965 |
++ |
32966 |
++ child = kdbus_hello(bus, 0, NULL, 0); |
32967 |
++ ASSERT_EXIT(child); |
32968 |
++ |
32969 |
++ ret = kdbus_add_match_empty(child); |
32970 |
++ ASSERT_EXIT(ret == 0); |
32971 |
++ |
32972 |
++ /* signal parent */ |
32973 |
++ ret = eventfd_write(efd, 1); |
32974 |
++ ASSERT_EXIT(ret == 0); |
32975 |
++ |
32976 |
++ /* Use a little bit high time */ |
32977 |
++ ret = kdbus_msg_recv_poll(child, 500, &msg, NULL); |
32978 |
++ ASSERT_EXIT(ret == child_status); |
32979 |
++ |
32980 |
++ /* |
32981 |
++ * If we expect the child to get the broadcast |
32982 |
++ * message, then check the received cookie. |
32983 |
++ */ |
32984 |
++ if (ret == 0) { |
32985 |
++ ASSERT_EXIT(expected_cookie == msg->cookie); |
32986 |
++ } |
32987 |
++ |
32988 |
++ /* Use expected_cookie since 'msg' might be NULL */ |
32989 |
++ ret = kdbus_msg_send(child, NULL, expected_cookie + 1, |
32990 |
++ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
32991 |
++ ASSERT_EXIT(ret == 0); |
32992 |
++ |
32993 |
++ kdbus_msg_free(msg); |
32994 |
++ kdbus_conn_free(child); |
32995 |
++ }), |
32996 |
++ ({ |
32997 |
++ if (drop_second_user == DO_NOT_DROP) { |
32998 |
++ ASSERT_RETURN(child_2); |
32999 |
++ |
33000 |
++ ret = eventfd_read(efd, &event_status); |
33001 |
++ ASSERT_RETURN(ret >= 0 && event_status == 1); |
33002 |
++ |
33003 |
++ ret = kdbus_msg_send(child_2, NULL, |
33004 |
++ expected_cookie, 0, 0, 0, |
33005 |
++ KDBUS_DST_ID_BROADCAST); |
33006 |
++ ASSERT_RETURN(ret == 0); |
33007 |
++ |
33008 |
++ /* Use a little bit high time */ |
33009 |
++ ret = kdbus_msg_recv_poll(child_2, 1000, |
33010 |
++ &msg, NULL); |
33011 |
++ ASSERT_RETURN(ret == parent_status); |
33012 |
++ |
33013 |
++ /* |
33014 |
++ * Check returned cookie in case we expect |
33015 |
++ * success. |
33016 |
++ */ |
33017 |
++ if (ret == 0) { |
33018 |
++ ASSERT_RETURN(msg->cookie == |
33019 |
++ expected_cookie + 1); |
33020 |
++ } |
33021 |
++ |
33022 |
++ kdbus_msg_free(msg); |
33023 |
++ } else { |
33024 |
++ /* |
33025 |
++ * Two unprivileged users will try to |
33026 |
++ * communicate using broadcast. |
33027 |
++ */ |
33028 |
++ ret = RUN_UNPRIVILEGED(second_uid, second_gid, ({ |
33029 |
++ child_2 = kdbus_hello(bus, 0, NULL, 0); |
33030 |
++ ASSERT_EXIT(child_2); |
33031 |
++ |
33032 |
++ ret = kdbus_add_match_empty(child_2); |
33033 |
++ ASSERT_EXIT(ret == 0); |
33034 |
++ |
33035 |
++ ret = eventfd_read(efd, &event_status); |
33036 |
++ ASSERT_EXIT(ret >= 0 && event_status == 1); |
33037 |
++ |
33038 |
++ ret = kdbus_msg_send(child_2, NULL, |
33039 |
++ expected_cookie, 0, 0, 0, |
33040 |
++ KDBUS_DST_ID_BROADCAST); |
33041 |
++ ASSERT_EXIT(ret == 0); |
33042 |
++ |
33043 |
++ /* Use a little bit high time */ |
33044 |
++ ret = kdbus_msg_recv_poll(child_2, 1000, |
33045 |
++ &msg, NULL); |
33046 |
++ ASSERT_EXIT(ret == parent_status); |
33047 |
++ |
33048 |
++ /* |
33049 |
++ * Check returned cookie in case we expect |
33050 |
++ * success. |
33051 |
++ */ |
33052 |
++ if (ret == 0) { |
33053 |
++ ASSERT_EXIT(msg->cookie == |
33054 |
++ expected_cookie + 1); |
33055 |
++ } |
33056 |
++ |
33057 |
++ kdbus_msg_free(msg); |
33058 |
++ kdbus_conn_free(child_2); |
33059 |
++ }), |
33060 |
++ ({ 0; })); |
33061 |
++ ASSERT_RETURN(ret == 0); |
33062 |
++ } |
33063 |
++ })); |
33064 |
++ ASSERT_RETURN(ret == 0); |
33065 |
++ |
33066 |
++ close(efd); |
33067 |
++ |
33068 |
++ return ret; |
33069 |
++} |
33070 |
++ |
33071 |
++static void nosig(int sig) |
33072 |
++{ |
33073 |
++} |
33074 |
++ |
33075 |
++static int test_priv_before_policy_upload(struct kdbus_test_env *env) |
33076 |
++{ |
33077 |
++ int ret = 0; |
33078 |
++ struct kdbus_conn *conn; |
33079 |
++ |
33080 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33081 |
++ ASSERT_RETURN(conn); |
33082 |
++ |
33083 |
++ /* |
33084 |
++ * Make sure unprivileged bus user cannot acquire names |
33085 |
++ * before registring any policy holder. |
33086 |
++ */ |
33087 |
++ |
33088 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33089 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33090 |
++ ASSERT_EXIT(ret < 0); |
33091 |
++ })); |
33092 |
++ ASSERT_RETURN(ret == 0); |
33093 |
++ |
33094 |
++ /* |
33095 |
++ * Make sure unprivileged bus users cannot talk by default |
33096 |
++ * to privileged ones, unless a policy holder that allows |
33097 |
++ * this was uploaded. |
33098 |
++ */ |
33099 |
++ |
33100 |
++ ret = test_policy_priv_by_id(env->buspath, conn, false, |
33101 |
++ -ETIMEDOUT, -EPERM); |
33102 |
++ ASSERT_RETURN(ret == 0); |
33103 |
++ |
33104 |
++ /* Activate matching for a privileged connection */ |
33105 |
++ ret = kdbus_add_match_empty(conn); |
33106 |
++ ASSERT_RETURN(ret == 0); |
33107 |
++ |
33108 |
++ /* |
33109 |
++ * First make sure that BROADCAST with msg flag |
33110 |
++ * KDBUS_MSG_EXPECT_REPLY will fail with -ENOTUNIQ |
33111 |
++ */ |
33112 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33113 |
++ ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, |
33114 |
++ KDBUS_MSG_EXPECT_REPLY, |
33115 |
++ 5000000000ULL, 0, |
33116 |
++ KDBUS_DST_ID_BROADCAST); |
33117 |
++ ASSERT_EXIT(ret == -ENOTUNIQ); |
33118 |
++ })); |
33119 |
++ ASSERT_RETURN(ret == 0); |
33120 |
++ |
33121 |
++ /* |
33122 |
++ * Test broadcast with a privileged connection. |
33123 |
++ * |
33124 |
++ * The first unprivileged receiver should not get the |
33125 |
++ * broadcast message sent by the privileged connection, |
33126 |
++ * since there is no a TALK policy that allows the |
33127 |
++ * unprivileged to TALK to the privileged connection. It |
33128 |
++ * will fail with -ETIMEDOUT |
33129 |
++ * |
33130 |
++ * Then second case: |
33131 |
++ * The privileged connection should get the broadcast |
33132 |
++ * message from the unprivileged one. Since the receiver is |
33133 |
++ * a privileged bus user and it has default TALK access to |
33134 |
++ * all connections it will receive those. |
33135 |
++ */ |
33136 |
++ |
33137 |
++ ret = test_policy_priv_by_broadcast(env->buspath, conn, |
33138 |
++ DO_NOT_DROP, |
33139 |
++ 0, -ETIMEDOUT); |
33140 |
++ ASSERT_RETURN(ret == 0); |
33141 |
++ |
33142 |
++ |
33143 |
++ /* |
33144 |
++ * Test broadcast with two unprivileged connections running |
33145 |
++ * under the same user. |
33146 |
++ * |
33147 |
++ * Both connections should succeed. |
33148 |
++ */ |
33149 |
++ |
33150 |
++ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33151 |
++ DROP_SAME_UNPRIV, 0, 0); |
33152 |
++ ASSERT_RETURN(ret == 0); |
33153 |
++ |
33154 |
++ /* |
33155 |
++ * Test broadcast with two unprivileged connections running |
33156 |
++ * under different users. |
33157 |
++ * |
33158 |
++ * Both connections will fail with -ETIMEDOUT. |
33159 |
++ */ |
33160 |
++ |
33161 |
++ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33162 |
++ DROP_OTHER_UNPRIV, |
33163 |
++ -ETIMEDOUT, -ETIMEDOUT); |
33164 |
++ ASSERT_RETURN(ret == 0); |
33165 |
++ |
33166 |
++ kdbus_conn_free(conn); |
33167 |
++ |
33168 |
++ return ret; |
33169 |
++} |
33170 |
++ |
33171 |
++static int test_broadcast_after_policy_upload(struct kdbus_test_env *env) |
33172 |
++{ |
33173 |
++ int ret; |
33174 |
++ int efd; |
33175 |
++ eventfd_t event_status = 0; |
33176 |
++ struct kdbus_msg *msg = NULL; |
33177 |
++ struct kdbus_conn *owner_a, *owner_b; |
33178 |
++ struct kdbus_conn *holder_a, *holder_b; |
33179 |
++ struct kdbus_policy_access access = {}; |
33180 |
++ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
33181 |
++ |
33182 |
++ owner_a = kdbus_hello(env->buspath, 0, NULL, 0); |
33183 |
++ ASSERT_RETURN(owner_a); |
33184 |
++ |
33185 |
++ ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL); |
33186 |
++ ASSERT_EXIT(ret >= 0); |
33187 |
++ |
33188 |
++ /* |
33189 |
++ * Make sure unprivileged bus users cannot talk by default |
33190 |
++ * to privileged ones, unless a policy holder that allows |
33191 |
++ * this was uploaded. |
33192 |
++ */ |
33193 |
++ |
33194 |
++ ++expected_cookie; |
33195 |
++ ret = test_policy_priv_by_id(env->buspath, owner_a, false, |
33196 |
++ -ETIMEDOUT, -EPERM); |
33197 |
++ ASSERT_RETURN(ret == 0); |
33198 |
++ |
33199 |
++ /* |
33200 |
++ * Make sure that privileged won't receive broadcasts unless |
33201 |
++ * it installs a match. It will fail with -ETIMEDOUT |
33202 |
++ * |
33203 |
++ * At same time check that the unprivileged connection will |
33204 |
++ * not receive the broadcast message from the privileged one |
33205 |
++ * since the privileged one owns a name with a restricted |
33206 |
++ * policy TALK (actually the TALK policy is still not |
33207 |
++ * registered so we fail by default), thus the unprivileged |
33208 |
++ * receiver is not able to TALK to that name. |
33209 |
++ */ |
33210 |
++ |
33211 |
++ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
33212 |
++ DO_NOT_DROP, |
33213 |
++ -ETIMEDOUT, -ETIMEDOUT); |
33214 |
++ ASSERT_RETURN(ret == 0); |
33215 |
++ |
33216 |
++ /* Activate matching for a privileged connection */ |
33217 |
++ ret = kdbus_add_match_empty(owner_a); |
33218 |
++ ASSERT_RETURN(ret == 0); |
33219 |
++ |
33220 |
++ /* |
33221 |
++ * Redo the previous test. The privileged conn owner_a is |
33222 |
++ * able to TALK to any connection so it will receive the |
33223 |
++ * broadcast message now. |
33224 |
++ */ |
33225 |
++ |
33226 |
++ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
33227 |
++ DO_NOT_DROP, |
33228 |
++ 0, -ETIMEDOUT); |
33229 |
++ ASSERT_RETURN(ret == 0); |
33230 |
++ |
33231 |
++ /* |
33232 |
++ * Test that broadcast between two unprivileged users running |
33233 |
++ * under the same user still succeed. |
33234 |
++ */ |
33235 |
++ |
33236 |
++ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33237 |
++ DROP_SAME_UNPRIV, 0, 0); |
33238 |
++ ASSERT_RETURN(ret == 0); |
33239 |
++ |
33240 |
++ /* |
33241 |
++ * Test broadcast with two unprivileged connections running |
33242 |
++ * under different users. |
33243 |
++ * |
33244 |
++ * Both connections will fail with -ETIMEDOUT. |
33245 |
++ */ |
33246 |
++ |
33247 |
++ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33248 |
++ DROP_OTHER_UNPRIV, |
33249 |
++ -ETIMEDOUT, -ETIMEDOUT); |
33250 |
++ ASSERT_RETURN(ret == 0); |
33251 |
++ |
33252 |
++ access = (struct kdbus_policy_access){ |
33253 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33254 |
++ .id = geteuid(), |
33255 |
++ .access = KDBUS_POLICY_OWN, |
33256 |
++ }; |
33257 |
++ |
33258 |
++ holder_a = kdbus_hello_registrar(env->buspath, |
33259 |
++ "com.example.broadcastA", |
33260 |
++ &access, 1, |
33261 |
++ KDBUS_HELLO_POLICY_HOLDER); |
33262 |
++ ASSERT_RETURN(holder_a); |
33263 |
++ |
33264 |
++ holder_b = kdbus_hello_registrar(env->buspath, |
33265 |
++ "com.example.broadcastB", |
33266 |
++ &access, 1, |
33267 |
++ KDBUS_HELLO_POLICY_HOLDER); |
33268 |
++ ASSERT_RETURN(holder_b); |
33269 |
++ |
33270 |
++ /* Free connections and their received messages and restart */ |
33271 |
++ kdbus_conn_free(owner_a); |
33272 |
++ |
33273 |
++ owner_a = kdbus_hello(env->buspath, 0, NULL, 0); |
33274 |
++ ASSERT_RETURN(owner_a); |
33275 |
++ |
33276 |
++ /* Activate matching for a privileged connection */ |
33277 |
++ ret = kdbus_add_match_empty(owner_a); |
33278 |
++ ASSERT_RETURN(ret == 0); |
33279 |
++ |
33280 |
++ ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL); |
33281 |
++ ASSERT_EXIT(ret >= 0); |
33282 |
++ |
33283 |
++ owner_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33284 |
++ ASSERT_RETURN(owner_b); |
33285 |
++ |
33286 |
++ ret = kdbus_name_acquire(owner_b, "com.example.broadcastB", NULL); |
33287 |
++ ASSERT_EXIT(ret >= 0); |
33288 |
++ |
33289 |
++ /* Activate matching for a privileged connection */ |
33290 |
++ ret = kdbus_add_match_empty(owner_b); |
33291 |
++ ASSERT_RETURN(ret == 0); |
33292 |
++ |
33293 |
++ /* |
33294 |
++ * Test that even if "com.example.broadcastA" and |
33295 |
++ * "com.example.broadcastB" do have a TALK access by default |
33296 |
++ * they are able to signal each other using broadcast due to |
33297 |
++ * the fact they are privileged connections, they receive |
33298 |
++ * all broadcasts if the match allows it. |
33299 |
++ */ |
33300 |
++ |
33301 |
++ ++expected_cookie; |
33302 |
++ ret = kdbus_msg_send(owner_a, NULL, expected_cookie, 0, |
33303 |
++ 0, 0, KDBUS_DST_ID_BROADCAST); |
33304 |
++ ASSERT_RETURN(ret == 0); |
33305 |
++ |
33306 |
++ ret = kdbus_msg_recv_poll(owner_b, 100, &msg, NULL); |
33307 |
++ ASSERT_RETURN(ret == 0); |
33308 |
++ ASSERT_RETURN(msg->cookie == expected_cookie); |
33309 |
++ |
33310 |
++ /* Check src ID */ |
33311 |
++ ASSERT_RETURN(msg->src_id == owner_a->id); |
33312 |
++ |
33313 |
++ kdbus_msg_free(msg); |
33314 |
++ |
33315 |
++ /* Release name "com.example.broadcastB" */ |
33316 |
++ |
33317 |
++ ret = kdbus_name_release(owner_b, "com.example.broadcastB"); |
33318 |
++ ASSERT_EXIT(ret >= 0); |
33319 |
++ |
33320 |
++ /* KDBUS_POLICY_OWN for unprivileged connections */ |
33321 |
++ access = (struct kdbus_policy_access){ |
33322 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
33323 |
++ .id = geteuid(), |
33324 |
++ .access = KDBUS_POLICY_OWN, |
33325 |
++ }; |
33326 |
++ |
33327 |
++ /* Update the policy so unprivileged will own the name */ |
33328 |
++ |
33329 |
++ ret = kdbus_conn_update_policy(holder_b, |
33330 |
++ "com.example.broadcastB", |
33331 |
++ &access, 1); |
33332 |
++ ASSERT_RETURN(ret == 0); |
33333 |
++ |
33334 |
++ /* |
33335 |
++ * Send broadcasts from an unprivileged connection that |
33336 |
++ * owns a name "com.example.broadcastB". |
33337 |
++ * |
33338 |
++ * We'll have four destinations here: |
33339 |
++ * |
33340 |
++ * 1) destination owner_a: privileged connection that owns |
33341 |
++ * "com.example.broadcastA". It will receive the broadcast |
33342 |
++ * since it is a privileged has default TALK access to all |
33343 |
++ * connections, and it is subscribed to the match. |
33344 |
++ * Will succeed. |
33345 |
++ * |
33346 |
++ * owner_b: privileged connection (running under a different |
33347 |
++ * uid) that do not own names, but with an empty broadcast |
33348 |
++ * match, so it will receive broadcasts since it has default |
33349 |
++ * TALK access to all connection. |
33350 |
++ * |
33351 |
++ * unpriv_a: unpriv connection that do not own any name. |
33352 |
++ * It will receive the broadcast since it is running under |
33353 |
++ * the same user of the one broadcasting and did install |
33354 |
++ * matches. It should get the message. |
33355 |
++ * |
33356 |
++ * unpriv_b: unpriv connection is not interested in broadcast |
33357 |
++ * messages, so it did not install broadcast matches. Should |
33358 |
++ * fail with -ETIMEDOUT |
33359 |
++ */ |
33360 |
++ |
33361 |
++ ++expected_cookie; |
33362 |
++ efd = eventfd(0, EFD_CLOEXEC); |
33363 |
++ ASSERT_RETURN_VAL(efd >= 0, efd); |
33364 |
++ |
33365 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
33366 |
++ struct kdbus_conn *unpriv_owner; |
33367 |
++ struct kdbus_conn *unpriv_a, *unpriv_b; |
33368 |
++ |
33369 |
++ unpriv_owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33370 |
++ ASSERT_EXIT(unpriv_owner); |
33371 |
++ |
33372 |
++ unpriv_a = kdbus_hello(env->buspath, 0, NULL, 0); |
33373 |
++ ASSERT_EXIT(unpriv_a); |
33374 |
++ |
33375 |
++ unpriv_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33376 |
++ ASSERT_EXIT(unpriv_b); |
33377 |
++ |
33378 |
++ ret = kdbus_name_acquire(unpriv_owner, |
33379 |
++ "com.example.broadcastB", |
33380 |
++ NULL); |
33381 |
++ ASSERT_EXIT(ret >= 0); |
33382 |
++ |
33383 |
++ ret = kdbus_add_match_empty(unpriv_a); |
33384 |
++ ASSERT_EXIT(ret == 0); |
33385 |
++ |
33386 |
++ /* Signal that we are doing broadcasts */ |
33387 |
++ ret = eventfd_write(efd, 1); |
33388 |
++ ASSERT_EXIT(ret == 0); |
33389 |
++ |
33390 |
++ /* |
33391 |
++ * Do broadcast from a connection that owns the |
33392 |
++ * names "com.example.broadcastB". |
33393 |
++ */ |
33394 |
++ ret = kdbus_msg_send(unpriv_owner, NULL, |
33395 |
++ expected_cookie, |
33396 |
++ 0, 0, 0, |
33397 |
++ KDBUS_DST_ID_BROADCAST); |
33398 |
++ ASSERT_EXIT(ret == 0); |
33399 |
++ |
33400 |
++ /* |
33401 |
++ * Unprivileged connection running under the same |
33402 |
++ * user. It should succeed. |
33403 |
++ */ |
33404 |
++ ret = kdbus_msg_recv_poll(unpriv_a, 300, &msg, NULL); |
33405 |
++ ASSERT_EXIT(ret == 0 && msg->cookie == expected_cookie); |
33406 |
++ |
33407 |
++ /* |
33408 |
++ * Did not install matches, not interested in |
33409 |
++ * broadcasts |
33410 |
++ */ |
33411 |
++ ret = kdbus_msg_recv_poll(unpriv_b, 300, NULL, NULL); |
33412 |
++ ASSERT_EXIT(ret == -ETIMEDOUT); |
33413 |
++ }), |
33414 |
++ ({ |
33415 |
++ ret = eventfd_read(efd, &event_status); |
33416 |
++ ASSERT_RETURN(ret >= 0 && event_status == 1); |
33417 |
++ |
33418 |
++ /* |
33419 |
++ * owner_a must fail with -ETIMEDOUT, since it owns |
33420 |
++ * name "com.example.broadcastA" and its TALK |
33421 |
++ * access is restriced. |
33422 |
++ */ |
33423 |
++ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33424 |
++ ASSERT_RETURN(ret == 0); |
33425 |
++ |
33426 |
++ /* confirm the received cookie */ |
33427 |
++ ASSERT_RETURN(msg->cookie == expected_cookie); |
33428 |
++ |
33429 |
++ kdbus_msg_free(msg); |
33430 |
++ |
33431 |
++ /* |
33432 |
++ * owner_b got the broadcast from an unprivileged |
33433 |
++ * connection. |
33434 |
++ */ |
33435 |
++ ret = kdbus_msg_recv_poll(owner_b, 300, &msg, NULL); |
33436 |
++ ASSERT_RETURN(ret == 0); |
33437 |
++ |
33438 |
++ /* confirm the received cookie */ |
33439 |
++ ASSERT_RETURN(msg->cookie == expected_cookie); |
33440 |
++ |
33441 |
++ kdbus_msg_free(msg); |
33442 |
++ |
33443 |
++ })); |
33444 |
++ ASSERT_RETURN(ret == 0); |
33445 |
++ |
33446 |
++ close(efd); |
33447 |
++ |
33448 |
++ /* |
33449 |
++ * Test broadcast with two unprivileged connections running |
33450 |
++ * under different users. |
33451 |
++ * |
33452 |
++ * Both connections will fail with -ETIMEDOUT. |
33453 |
++ */ |
33454 |
++ |
33455 |
++ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33456 |
++ DROP_OTHER_UNPRIV, |
33457 |
++ -ETIMEDOUT, -ETIMEDOUT); |
33458 |
++ ASSERT_RETURN(ret == 0); |
33459 |
++ |
33460 |
++ /* Drop received broadcasts by privileged */ |
33461 |
++ ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL); |
33462 |
++ ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL); |
33463 |
++ ASSERT_RETURN(ret == 0); |
33464 |
++ |
33465 |
++ ret = kdbus_msg_recv(owner_a, NULL, NULL); |
33466 |
++ ASSERT_RETURN(ret == -EAGAIN); |
33467 |
++ |
33468 |
++ ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL); |
33469 |
++ ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL); |
33470 |
++ ASSERT_RETURN(ret == 0); |
33471 |
++ |
33472 |
++ ret = kdbus_msg_recv(owner_b, NULL, NULL); |
33473 |
++ ASSERT_RETURN(ret == -EAGAIN); |
33474 |
++ |
33475 |
++ /* |
33476 |
++ * Perform last tests, allow others to talk to name |
33477 |
++ * "com.example.broadcastA". So now receiving broadcasts |
33478 |
++ * from it should succeed since the TALK policy allow it. |
33479 |
++ */ |
33480 |
++ |
33481 |
++ /* KDBUS_POLICY_OWN for unprivileged connections */ |
33482 |
++ access = (struct kdbus_policy_access){ |
33483 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
33484 |
++ .id = geteuid(), |
33485 |
++ .access = KDBUS_POLICY_TALK, |
33486 |
++ }; |
33487 |
++ |
33488 |
++ ret = kdbus_conn_update_policy(holder_a, |
33489 |
++ "com.example.broadcastA", |
33490 |
++ &access, 1); |
33491 |
++ ASSERT_RETURN(ret == 0); |
33492 |
++ |
33493 |
++ /* |
33494 |
++ * Unprivileged is able to TALK to "com.example.broadcastA" |
33495 |
++ * now so it will receive its broadcasts |
33496 |
++ */ |
33497 |
++ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
33498 |
++ DO_NOT_DROP, 0, 0); |
33499 |
++ ASSERT_RETURN(ret == 0); |
33500 |
++ |
33501 |
++ ++expected_cookie; |
33502 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33503 |
++ ret = kdbus_name_acquire(unpriv, "com.example.broadcastB", |
33504 |
++ NULL); |
33505 |
++ ASSERT_EXIT(ret >= 0); |
33506 |
++ ret = kdbus_msg_send(unpriv, NULL, expected_cookie, |
33507 |
++ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
33508 |
++ ASSERT_EXIT(ret == 0); |
33509 |
++ })); |
33510 |
++ ASSERT_RETURN(ret == 0); |
33511 |
++ |
33512 |
++ /* owner_a is privileged it will get the broadcast now. */ |
33513 |
++ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33514 |
++ ASSERT_RETURN(ret == 0); |
33515 |
++ |
33516 |
++ /* confirm the received cookie */ |
33517 |
++ ASSERT_RETURN(msg->cookie == expected_cookie); |
33518 |
++ |
33519 |
++ kdbus_msg_free(msg); |
33520 |
++ |
33521 |
++ /* |
33522 |
++ * owner_a released name "com.example.broadcastA". It should |
33523 |
++ * receive broadcasts since it is still privileged and has |
33524 |
++ * the right match. |
33525 |
++ * |
33526 |
++ * Unprivileged connection will own a name and will try to |
33527 |
++ * signal to the privileged connection. |
33528 |
++ */ |
33529 |
++ |
33530 |
++ ret = kdbus_name_release(owner_a, "com.example.broadcastA"); |
33531 |
++ ASSERT_EXIT(ret >= 0); |
33532 |
++ |
33533 |
++ ++expected_cookie; |
33534 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33535 |
++ ret = kdbus_name_acquire(unpriv, "com.example.broadcastB", |
33536 |
++ NULL); |
33537 |
++ ASSERT_EXIT(ret >= 0); |
33538 |
++ ret = kdbus_msg_send(unpriv, NULL, expected_cookie, |
33539 |
++ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
33540 |
++ ASSERT_EXIT(ret == 0); |
33541 |
++ })); |
33542 |
++ ASSERT_RETURN(ret == 0); |
33543 |
++ |
33544 |
++ /* owner_a will get the broadcast now. */ |
33545 |
++ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33546 |
++ ASSERT_RETURN(ret == 0); |
33547 |
++ |
33548 |
++ /* confirm the received cookie */ |
33549 |
++ ASSERT_RETURN(msg->cookie == expected_cookie); |
33550 |
++ |
33551 |
++ kdbus_msg_free(msg); |
33552 |
++ |
33553 |
++ kdbus_conn_free(owner_a); |
33554 |
++ kdbus_conn_free(owner_b); |
33555 |
++ kdbus_conn_free(holder_a); |
33556 |
++ kdbus_conn_free(holder_b); |
33557 |
++ |
33558 |
++ return 0; |
33559 |
++} |
33560 |
++ |
33561 |
++static int test_policy_priv(struct kdbus_test_env *env) |
33562 |
++{ |
33563 |
++ struct kdbus_conn *conn_a, *conn_b, *conn, *owner; |
33564 |
++ struct kdbus_policy_access access, *acc; |
33565 |
++ sigset_t sset; |
33566 |
++ size_t num; |
33567 |
++ int ret; |
33568 |
++ |
33569 |
++ /* |
33570 |
++ * Make sure we have CAP_SETUID/SETGID so we can drop privileges |
33571 |
++ */ |
33572 |
++ |
33573 |
++ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
33574 |
++ ASSERT_RETURN(ret >= 0); |
33575 |
++ |
33576 |
++ if (!ret) |
33577 |
++ return TEST_SKIP; |
33578 |
++ |
33579 |
++ /* make sure that uids and gids are mapped */ |
33580 |
++ if (!all_uids_gids_are_mapped()) |
33581 |
++ return TEST_SKIP; |
33582 |
++ |
33583 |
++ /* |
33584 |
++ * Setup: |
33585 |
++ * conn_a: policy holder for com.example.a |
33586 |
++ * conn_b: name holder of com.example.b |
33587 |
++ */ |
33588 |
++ |
33589 |
++ signal(SIGUSR1, nosig); |
33590 |
++ sigemptyset(&sset); |
33591 |
++ sigaddset(&sset, SIGUSR1); |
33592 |
++ sigprocmask(SIG_BLOCK, &sset, NULL); |
33593 |
++ |
33594 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33595 |
++ ASSERT_RETURN(conn); |
33596 |
++ |
33597 |
++ /* |
33598 |
++ * Before registering any policy holder, make sure that the |
33599 |
++ * bus is secure by default. This test is necessary, it catches |
33600 |
++ * several cases where old D-Bus was vulnerable. |
33601 |
++ */ |
33602 |
++ |
33603 |
++ ret = test_priv_before_policy_upload(env); |
33604 |
++ ASSERT_RETURN(ret == 0); |
33605 |
++ |
33606 |
++ /* |
33607 |
++ * Make sure unprivileged are not able to register policy |
33608 |
++ * holders |
33609 |
++ */ |
33610 |
++ |
33611 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
33612 |
++ struct kdbus_conn *holder; |
33613 |
++ |
33614 |
++ holder = kdbus_hello_registrar(env->buspath, |
33615 |
++ "com.example.a", NULL, 0, |
33616 |
++ KDBUS_HELLO_POLICY_HOLDER); |
33617 |
++ ASSERT_EXIT(holder == NULL && errno == EPERM); |
33618 |
++ }), |
33619 |
++ ({ 0; })); |
33620 |
++ ASSERT_RETURN(ret == 0); |
33621 |
++ |
33622 |
++ |
33623 |
++ /* Register policy holder */ |
33624 |
++ |
33625 |
++ conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", |
33626 |
++ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33627 |
++ ASSERT_RETURN(conn_a); |
33628 |
++ |
33629 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33630 |
++ ASSERT_RETURN(conn_b); |
33631 |
++ |
33632 |
++ ret = kdbus_name_acquire(conn_b, "com.example.b", NULL); |
33633 |
++ ASSERT_EXIT(ret >= 0); |
33634 |
++ |
33635 |
++ /* |
33636 |
++ * Make sure bus-owners can always acquire names. |
33637 |
++ */ |
33638 |
++ ret = kdbus_name_acquire(conn, "com.example.a", NULL); |
33639 |
++ ASSERT_EXIT(ret >= 0); |
33640 |
++ |
33641 |
++ kdbus_conn_free(conn); |
33642 |
++ |
33643 |
++ /* |
33644 |
++ * Make sure unprivileged users cannot acquire names with default |
33645 |
++ * policy assigned. |
33646 |
++ */ |
33647 |
++ |
33648 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33649 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33650 |
++ ASSERT_EXIT(ret < 0); |
33651 |
++ })); |
33652 |
++ ASSERT_RETURN(ret >= 0); |
33653 |
++ |
33654 |
++ /* |
33655 |
++ * Make sure unprivileged users can acquire names if we make them |
33656 |
++ * world-accessible. |
33657 |
++ */ |
33658 |
++ |
33659 |
++ access = (struct kdbus_policy_access){ |
33660 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
33661 |
++ .id = 0, |
33662 |
++ .access = KDBUS_POLICY_OWN, |
33663 |
++ }; |
33664 |
++ |
33665 |
++ /* |
33666 |
++ * Make sure unprivileged/normal connections are not able |
33667 |
++ * to update policies |
33668 |
++ */ |
33669 |
++ |
33670 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33671 |
++ ret = kdbus_conn_update_policy(unpriv, "com.example.a", |
33672 |
++ &access, 1); |
33673 |
++ ASSERT_EXIT(ret == -EOPNOTSUPP); |
33674 |
++ })); |
33675 |
++ ASSERT_RETURN(ret == 0); |
33676 |
++ |
33677 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33678 |
++ ASSERT_RETURN(ret == 0); |
33679 |
++ |
33680 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33681 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33682 |
++ ASSERT_EXIT(ret >= 0); |
33683 |
++ })); |
33684 |
++ ASSERT_RETURN(ret >= 0); |
33685 |
++ |
33686 |
++ /* |
33687 |
++ * Make sure unprivileged users can acquire names if we make them |
33688 |
++ * gid-accessible. But only if the gid matches. |
33689 |
++ */ |
33690 |
++ |
33691 |
++ access = (struct kdbus_policy_access){ |
33692 |
++ .type = KDBUS_POLICY_ACCESS_GROUP, |
33693 |
++ .id = UNPRIV_GID, |
33694 |
++ .access = KDBUS_POLICY_OWN, |
33695 |
++ }; |
33696 |
++ |
33697 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33698 |
++ ASSERT_RETURN(ret == 0); |
33699 |
++ |
33700 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33701 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33702 |
++ ASSERT_EXIT(ret >= 0); |
33703 |
++ })); |
33704 |
++ ASSERT_RETURN(ret >= 0); |
33705 |
++ |
33706 |
++ access = (struct kdbus_policy_access){ |
33707 |
++ .type = KDBUS_POLICY_ACCESS_GROUP, |
33708 |
++ .id = 1, |
33709 |
++ .access = KDBUS_POLICY_OWN, |
33710 |
++ }; |
33711 |
++ |
33712 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33713 |
++ ASSERT_RETURN(ret == 0); |
33714 |
++ |
33715 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33716 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33717 |
++ ASSERT_EXIT(ret < 0); |
33718 |
++ })); |
33719 |
++ ASSERT_RETURN(ret >= 0); |
33720 |
++ |
33721 |
++ /* |
33722 |
++ * Make sure unprivileged users can acquire names if we make them |
33723 |
++ * uid-accessible. But only if the uid matches. |
33724 |
++ */ |
33725 |
++ |
33726 |
++ access = (struct kdbus_policy_access){ |
33727 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33728 |
++ .id = UNPRIV_UID, |
33729 |
++ .access = KDBUS_POLICY_OWN, |
33730 |
++ }; |
33731 |
++ |
33732 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33733 |
++ ASSERT_RETURN(ret == 0); |
33734 |
++ |
33735 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33736 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33737 |
++ ASSERT_EXIT(ret >= 0); |
33738 |
++ })); |
33739 |
++ ASSERT_RETURN(ret >= 0); |
33740 |
++ |
33741 |
++ access = (struct kdbus_policy_access){ |
33742 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33743 |
++ .id = 1, |
33744 |
++ .access = KDBUS_POLICY_OWN, |
33745 |
++ }; |
33746 |
++ |
33747 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33748 |
++ ASSERT_RETURN(ret == 0); |
33749 |
++ |
33750 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33751 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33752 |
++ ASSERT_EXIT(ret < 0); |
33753 |
++ })); |
33754 |
++ ASSERT_RETURN(ret >= 0); |
33755 |
++ |
33756 |
++ /* |
33757 |
++ * Make sure unprivileged users cannot acquire names if no owner-policy |
33758 |
++ * matches, even if SEE/TALK policies match. |
33759 |
++ */ |
33760 |
++ |
33761 |
++ num = 4; |
33762 |
++ acc = (struct kdbus_policy_access[]){ |
33763 |
++ { |
33764 |
++ .type = KDBUS_POLICY_ACCESS_GROUP, |
33765 |
++ .id = UNPRIV_GID, |
33766 |
++ .access = KDBUS_POLICY_SEE, |
33767 |
++ }, |
33768 |
++ { |
33769 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33770 |
++ .id = UNPRIV_UID, |
33771 |
++ .access = KDBUS_POLICY_TALK, |
33772 |
++ }, |
33773 |
++ { |
33774 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
33775 |
++ .id = 0, |
33776 |
++ .access = KDBUS_POLICY_TALK, |
33777 |
++ }, |
33778 |
++ { |
33779 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
33780 |
++ .id = 0, |
33781 |
++ .access = KDBUS_POLICY_SEE, |
33782 |
++ }, |
33783 |
++ }; |
33784 |
++ |
33785 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num); |
33786 |
++ ASSERT_RETURN(ret == 0); |
33787 |
++ |
33788 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33789 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33790 |
++ ASSERT_EXIT(ret < 0); |
33791 |
++ })); |
33792 |
++ ASSERT_RETURN(ret >= 0); |
33793 |
++ |
33794 |
++ /* |
33795 |
++ * Make sure unprivileged users can acquire names if the only matching |
33796 |
++ * policy is somewhere in the middle. |
33797 |
++ */ |
33798 |
++ |
33799 |
++ num = 5; |
33800 |
++ acc = (struct kdbus_policy_access[]){ |
33801 |
++ { |
33802 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33803 |
++ .id = 1, |
33804 |
++ .access = KDBUS_POLICY_OWN, |
33805 |
++ }, |
33806 |
++ { |
33807 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33808 |
++ .id = 2, |
33809 |
++ .access = KDBUS_POLICY_OWN, |
33810 |
++ }, |
33811 |
++ { |
33812 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33813 |
++ .id = UNPRIV_UID, |
33814 |
++ .access = KDBUS_POLICY_OWN, |
33815 |
++ }, |
33816 |
++ { |
33817 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33818 |
++ .id = 3, |
33819 |
++ .access = KDBUS_POLICY_OWN, |
33820 |
++ }, |
33821 |
++ { |
33822 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33823 |
++ .id = 4, |
33824 |
++ .access = KDBUS_POLICY_OWN, |
33825 |
++ }, |
33826 |
++ }; |
33827 |
++ |
33828 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num); |
33829 |
++ ASSERT_RETURN(ret == 0); |
33830 |
++ |
33831 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33832 |
++ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33833 |
++ ASSERT_EXIT(ret >= 0); |
33834 |
++ })); |
33835 |
++ ASSERT_RETURN(ret >= 0); |
33836 |
++ |
33837 |
++ /* |
33838 |
++ * Clear policies |
33839 |
++ */ |
33840 |
++ |
33841 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", NULL, 0); |
33842 |
++ ASSERT_RETURN(ret == 0); |
33843 |
++ |
33844 |
++ /* |
33845 |
++ * Make sure privileged bus users can _always_ talk to others. |
33846 |
++ */ |
33847 |
++ |
33848 |
++ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33849 |
++ ASSERT_RETURN(conn); |
33850 |
++ |
33851 |
++ ret = kdbus_msg_send(conn, "com.example.b", 0xdeadbeef, 0, 0, 0, 0); |
33852 |
++ ASSERT_EXIT(ret >= 0); |
33853 |
++ |
33854 |
++ ret = kdbus_msg_recv_poll(conn_b, 300, NULL, NULL); |
33855 |
++ ASSERT_EXIT(ret >= 0); |
33856 |
++ |
33857 |
++ kdbus_conn_free(conn); |
33858 |
++ |
33859 |
++ /* |
33860 |
++ * Make sure unprivileged bus users cannot talk by default. |
33861 |
++ */ |
33862 |
++ |
33863 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33864 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33865 |
++ 0, 0); |
33866 |
++ ASSERT_EXIT(ret == -EPERM); |
33867 |
++ })); |
33868 |
++ ASSERT_RETURN(ret >= 0); |
33869 |
++ |
33870 |
++ /* |
33871 |
++ * Make sure unprivileged bus users can talk to equals, even without |
33872 |
++ * policy. |
33873 |
++ */ |
33874 |
++ |
33875 |
++ access = (struct kdbus_policy_access){ |
33876 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33877 |
++ .id = UNPRIV_UID, |
33878 |
++ .access = KDBUS_POLICY_OWN, |
33879 |
++ }; |
33880 |
++ |
33881 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.c", &access, 1); |
33882 |
++ ASSERT_RETURN(ret == 0); |
33883 |
++ |
33884 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33885 |
++ struct kdbus_conn *owner; |
33886 |
++ |
33887 |
++ owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33888 |
++ ASSERT_RETURN(owner); |
33889 |
++ |
33890 |
++ ret = kdbus_name_acquire(owner, "com.example.c", NULL); |
33891 |
++ ASSERT_EXIT(ret >= 0); |
33892 |
++ |
33893 |
++ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33894 |
++ 0, 0); |
33895 |
++ ASSERT_EXIT(ret >= 0); |
33896 |
++ ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL); |
33897 |
++ ASSERT_EXIT(ret >= 0); |
33898 |
++ |
33899 |
++ kdbus_conn_free(owner); |
33900 |
++ })); |
33901 |
++ ASSERT_RETURN(ret >= 0); |
33902 |
++ |
33903 |
++ /* |
33904 |
++ * Make sure unprivileged bus users can talk to privileged users if a |
33905 |
++ * suitable UID policy is set. |
33906 |
++ */ |
33907 |
++ |
33908 |
++ access = (struct kdbus_policy_access){ |
33909 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33910 |
++ .id = UNPRIV_UID, |
33911 |
++ .access = KDBUS_POLICY_TALK, |
33912 |
++ }; |
33913 |
++ |
33914 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33915 |
++ ASSERT_RETURN(ret == 0); |
33916 |
++ |
33917 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33918 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33919 |
++ 0, 0); |
33920 |
++ ASSERT_EXIT(ret >= 0); |
33921 |
++ })); |
33922 |
++ ASSERT_RETURN(ret >= 0); |
33923 |
++ |
33924 |
++ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33925 |
++ ASSERT_EXIT(ret >= 0); |
33926 |
++ |
33927 |
++ /* |
33928 |
++ * Make sure unprivileged bus users can talk to privileged users if a |
33929 |
++ * suitable GID policy is set. |
33930 |
++ */ |
33931 |
++ |
33932 |
++ access = (struct kdbus_policy_access){ |
33933 |
++ .type = KDBUS_POLICY_ACCESS_GROUP, |
33934 |
++ .id = UNPRIV_GID, |
33935 |
++ .access = KDBUS_POLICY_TALK, |
33936 |
++ }; |
33937 |
++ |
33938 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33939 |
++ ASSERT_RETURN(ret == 0); |
33940 |
++ |
33941 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33942 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33943 |
++ 0, 0); |
33944 |
++ ASSERT_EXIT(ret >= 0); |
33945 |
++ })); |
33946 |
++ ASSERT_RETURN(ret >= 0); |
33947 |
++ |
33948 |
++ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33949 |
++ ASSERT_EXIT(ret >= 0); |
33950 |
++ |
33951 |
++ /* |
33952 |
++ * Make sure unprivileged bus users can talk to privileged users if a |
33953 |
++ * suitable WORLD policy is set. |
33954 |
++ */ |
33955 |
++ |
33956 |
++ access = (struct kdbus_policy_access){ |
33957 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
33958 |
++ .id = 0, |
33959 |
++ .access = KDBUS_POLICY_TALK, |
33960 |
++ }; |
33961 |
++ |
33962 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33963 |
++ ASSERT_RETURN(ret == 0); |
33964 |
++ |
33965 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33966 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33967 |
++ 0, 0); |
33968 |
++ ASSERT_EXIT(ret >= 0); |
33969 |
++ })); |
33970 |
++ ASSERT_RETURN(ret >= 0); |
33971 |
++ |
33972 |
++ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33973 |
++ ASSERT_EXIT(ret >= 0); |
33974 |
++ |
33975 |
++ /* |
33976 |
++ * Make sure unprivileged bus users cannot talk to privileged users if |
33977 |
++ * no suitable policy is set. |
33978 |
++ */ |
33979 |
++ |
33980 |
++ num = 5; |
33981 |
++ acc = (struct kdbus_policy_access[]){ |
33982 |
++ { |
33983 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33984 |
++ .id = 0, |
33985 |
++ .access = KDBUS_POLICY_OWN, |
33986 |
++ }, |
33987 |
++ { |
33988 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33989 |
++ .id = 1, |
33990 |
++ .access = KDBUS_POLICY_TALK, |
33991 |
++ }, |
33992 |
++ { |
33993 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33994 |
++ .id = UNPRIV_UID, |
33995 |
++ .access = KDBUS_POLICY_SEE, |
33996 |
++ }, |
33997 |
++ { |
33998 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
33999 |
++ .id = 3, |
34000 |
++ .access = KDBUS_POLICY_TALK, |
34001 |
++ }, |
34002 |
++ { |
34003 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
34004 |
++ .id = 4, |
34005 |
++ .access = KDBUS_POLICY_TALK, |
34006 |
++ }, |
34007 |
++ }; |
34008 |
++ |
34009 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", acc, num); |
34010 |
++ ASSERT_RETURN(ret == 0); |
34011 |
++ |
34012 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
34013 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
34014 |
++ 0, 0); |
34015 |
++ ASSERT_EXIT(ret == -EPERM); |
34016 |
++ })); |
34017 |
++ ASSERT_RETURN(ret >= 0); |
34018 |
++ |
34019 |
++ /* |
34020 |
++ * Make sure unprivileged bus users can talk to privileged users if a |
34021 |
++ * suitable OWN privilege overwrites TALK. |
34022 |
++ */ |
34023 |
++ |
34024 |
++ access = (struct kdbus_policy_access){ |
34025 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
34026 |
++ .id = 0, |
34027 |
++ .access = KDBUS_POLICY_OWN, |
34028 |
++ }; |
34029 |
++ |
34030 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
34031 |
++ ASSERT_RETURN(ret == 0); |
34032 |
++ |
34033 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
34034 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
34035 |
++ 0, 0); |
34036 |
++ ASSERT_EXIT(ret >= 0); |
34037 |
++ })); |
34038 |
++ ASSERT_RETURN(ret >= 0); |
34039 |
++ |
34040 |
++ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
34041 |
++ ASSERT_EXIT(ret >= 0); |
34042 |
++ |
34043 |
++ /* |
34044 |
++ * Make sure the TALK cache is reset correctly when policies are |
34045 |
++ * updated. |
34046 |
++ */ |
34047 |
++ |
34048 |
++ access = (struct kdbus_policy_access){ |
34049 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
34050 |
++ .id = 0, |
34051 |
++ .access = KDBUS_POLICY_TALK, |
34052 |
++ }; |
34053 |
++ |
34054 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
34055 |
++ ASSERT_RETURN(ret == 0); |
34056 |
++ |
34057 |
++ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
34058 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
34059 |
++ 0, 0); |
34060 |
++ ASSERT_EXIT(ret >= 0); |
34061 |
++ |
34062 |
++ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
34063 |
++ ASSERT_EXIT(ret >= 0); |
34064 |
++ |
34065 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.b", |
34066 |
++ NULL, 0); |
34067 |
++ ASSERT_RETURN(ret == 0); |
34068 |
++ |
34069 |
++ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
34070 |
++ 0, 0); |
34071 |
++ ASSERT_EXIT(ret == -EPERM); |
34072 |
++ })); |
34073 |
++ ASSERT_RETURN(ret >= 0); |
34074 |
++ |
34075 |
++ /* |
34076 |
++ * Make sure the TALK cache is reset correctly when policy holders |
34077 |
++ * disconnect. |
34078 |
++ */ |
34079 |
++ |
34080 |
++ access = (struct kdbus_policy_access){ |
34081 |
++ .type = KDBUS_POLICY_ACCESS_WORLD, |
34082 |
++ .id = 0, |
34083 |
++ .access = KDBUS_POLICY_OWN, |
34084 |
++ }; |
34085 |
++ |
34086 |
++ conn = kdbus_hello_registrar(env->buspath, "com.example.c", |
34087 |
++ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
34088 |
++ ASSERT_RETURN(conn); |
34089 |
++ |
34090 |
++ ret = kdbus_conn_update_policy(conn, "com.example.c", &access, 1); |
34091 |
++ ASSERT_RETURN(ret == 0); |
34092 |
++ |
34093 |
++ owner = kdbus_hello(env->buspath, 0, NULL, 0); |
34094 |
++ ASSERT_RETURN(owner); |
34095 |
++ |
34096 |
++ ret = kdbus_name_acquire(owner, "com.example.c", NULL); |
34097 |
++ ASSERT_RETURN(ret >= 0); |
34098 |
++ |
34099 |
++ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
34100 |
++ struct kdbus_conn *unpriv; |
34101 |
++ |
34102 |
++ /* wait for parent to be finished */ |
34103 |
++ sigemptyset(&sset); |
34104 |
++ ret = sigsuspend(&sset); |
34105 |
++ ASSERT_RETURN(ret == -1 && errno == EINTR); |
34106 |
++ |
34107 |
++ unpriv = kdbus_hello(env->buspath, 0, NULL, 0); |
34108 |
++ ASSERT_RETURN(unpriv); |
34109 |
++ |
34110 |
++ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
34111 |
++ 0, 0); |
34112 |
++ ASSERT_EXIT(ret >= 0); |
34113 |
++ |
34114 |
++ ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL); |
34115 |
++ ASSERT_EXIT(ret >= 0); |
34116 |
++ |
34117 |
++ /* free policy holder */ |
34118 |
++ kdbus_conn_free(conn); |
34119 |
++ |
34120 |
++ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
34121 |
++ 0, 0); |
34122 |
++ ASSERT_EXIT(ret == -EPERM); |
34123 |
++ |
34124 |
++ kdbus_conn_free(unpriv); |
34125 |
++ }), ({ |
34126 |
++ /* make sure policy holder is only valid in child */ |
34127 |
++ kdbus_conn_free(conn); |
34128 |
++ kill(pid, SIGUSR1); |
34129 |
++ })); |
34130 |
++ ASSERT_RETURN(ret >= 0); |
34131 |
++ |
34132 |
++ |
34133 |
++ /* |
34134 |
++ * The following tests are necessary. |
34135 |
++ */ |
34136 |
++ |
34137 |
++ ret = test_broadcast_after_policy_upload(env); |
34138 |
++ ASSERT_RETURN(ret == 0); |
34139 |
++ |
34140 |
++ kdbus_conn_free(owner); |
34141 |
++ |
34142 |
++ /* |
34143 |
++ * cleanup resources |
34144 |
++ */ |
34145 |
++ |
34146 |
++ kdbus_conn_free(conn_b); |
34147 |
++ kdbus_conn_free(conn_a); |
34148 |
++ |
34149 |
++ return TEST_OK; |
34150 |
++} |
34151 |
++ |
34152 |
++int kdbus_test_policy_priv(struct kdbus_test_env *env) |
34153 |
++{ |
34154 |
++ pid_t pid; |
34155 |
++ int ret; |
34156 |
++ |
34157 |
++ /* make sure to exit() if a child returns from fork() */ |
34158 |
++ pid = getpid(); |
34159 |
++ ret = test_policy_priv(env); |
34160 |
++ if (pid != getpid()) |
34161 |
++ exit(1); |
34162 |
++ |
34163 |
++ return ret; |
34164 |
++} |
34165 |
+diff --git a/tools/testing/selftests/kdbus/test-policy.c b/tools/testing/selftests/kdbus/test-policy.c |
34166 |
+new file mode 100644 |
34167 |
+index 0000000..96d20d5 |
34168 |
+--- /dev/null |
34169 |
++++ b/tools/testing/selftests/kdbus/test-policy.c |
34170 |
+@@ -0,0 +1,80 @@ |
34171 |
++#include <errno.h> |
34172 |
++#include <stdio.h> |
34173 |
++#include <string.h> |
34174 |
++#include <fcntl.h> |
34175 |
++#include <stdlib.h> |
34176 |
++#include <stdint.h> |
34177 |
++#include <stdbool.h> |
34178 |
++#include <unistd.h> |
34179 |
++ |
34180 |
++#include "kdbus-test.h" |
34181 |
++#include "kdbus-util.h" |
34182 |
++#include "kdbus-enum.h" |
34183 |
++ |
34184 |
++int kdbus_test_policy(struct kdbus_test_env *env) |
34185 |
++{ |
34186 |
++ struct kdbus_conn *conn_a, *conn_b; |
34187 |
++ struct kdbus_policy_access access; |
34188 |
++ int ret; |
34189 |
++ |
34190 |
++ /* Invalid name */ |
34191 |
++ conn_a = kdbus_hello_registrar(env->buspath, ".example.a", |
34192 |
++ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
34193 |
++ ASSERT_RETURN(conn_a == NULL); |
34194 |
++ |
34195 |
++ conn_a = kdbus_hello_registrar(env->buspath, "example", |
34196 |
++ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
34197 |
++ ASSERT_RETURN(conn_a == NULL); |
34198 |
++ |
34199 |
++ conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", |
34200 |
++ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
34201 |
++ ASSERT_RETURN(conn_a); |
34202 |
++ |
34203 |
++ conn_b = kdbus_hello_registrar(env->buspath, "com.example.b", |
34204 |
++ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
34205 |
++ ASSERT_RETURN(conn_b); |
34206 |
++ |
34207 |
++ /* |
34208 |
++ * Verify there cannot be any duplicate entries, except for specific vs. |
34209 |
++ * wildcard entries. |
34210 |
++ */ |
34211 |
++ |
34212 |
++ access = (struct kdbus_policy_access){ |
34213 |
++ .type = KDBUS_POLICY_ACCESS_USER, |
34214 |
++ .id = geteuid(), |
34215 |
++ .access = KDBUS_POLICY_SEE, |
34216 |
++ }; |
34217 |
++ |
34218 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
34219 |
++ ASSERT_RETURN(ret == 0); |
34220 |
++ |
34221 |
++ ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); |
34222 |
++ ASSERT_RETURN(ret == -EEXIST); |
34223 |
++ |
34224 |
++ ret = kdbus_conn_update_policy(conn_b, "com.example.a.*", &access, 1); |
34225 |
++ ASSERT_RETURN(ret == 0); |
34226 |
++ |
34227 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.a.*", &access, 1); |
34228 |
++ ASSERT_RETURN(ret == -EEXIST); |
34229 |
++ |
34230 |
++ ret = kdbus_conn_update_policy(conn_a, "com.example.*", &access, 1); |
34231 |
++ ASSERT_RETURN(ret == 0); |
34232 |
++ |
34233 |
++ ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); |
34234 |
++ ASSERT_RETURN(ret == 0); |
34235 |
++ |
34236 |
++ ret = kdbus_conn_update_policy(conn_b, "com.example.*", &access, 1); |
34237 |
++ ASSERT_RETURN(ret == -EEXIST); |
34238 |
++ |
34239 |
++ /* Invalid name */ |
34240 |
++ ret = kdbus_conn_update_policy(conn_b, ".example.*", &access, 1); |
34241 |
++ ASSERT_RETURN(ret == -EINVAL); |
34242 |
++ |
34243 |
++ ret = kdbus_conn_update_policy(conn_b, "example", &access, 1); |
34244 |
++ ASSERT_RETURN(ret == -EINVAL); |
34245 |
++ |
34246 |
++ kdbus_conn_free(conn_b); |
34247 |
++ kdbus_conn_free(conn_a); |
34248 |
++ |
34249 |
++ return TEST_OK; |
34250 |
++} |
34251 |
+diff --git a/tools/testing/selftests/kdbus/test-sync.c b/tools/testing/selftests/kdbus/test-sync.c |
34252 |
+new file mode 100644 |
34253 |
+index 0000000..e2be910 |
34254 |
+--- /dev/null |
34255 |
++++ b/tools/testing/selftests/kdbus/test-sync.c |
34256 |
+@@ -0,0 +1,369 @@ |
34257 |
++#include <stdio.h> |
34258 |
++#include <string.h> |
34259 |
++#include <time.h> |
34260 |
++#include <fcntl.h> |
34261 |
++#include <stdlib.h> |
34262 |
++#include <stddef.h> |
34263 |
++#include <unistd.h> |
34264 |
++#include <stdint.h> |
34265 |
++#include <errno.h> |
34266 |
++#include <assert.h> |
34267 |
++#include <pthread.h> |
34268 |
++#include <stdbool.h> |
34269 |
++#include <signal.h> |
34270 |
++#include <sys/wait.h> |
34271 |
++#include <sys/eventfd.h> |
34272 |
++ |
34273 |
++#include "kdbus-api.h" |
34274 |
++#include "kdbus-test.h" |
34275 |
++#include "kdbus-util.h" |
34276 |
++#include "kdbus-enum.h" |
34277 |
++ |
34278 |
++static struct kdbus_conn *conn_a, *conn_b; |
34279 |
++static unsigned int cookie = 0xdeadbeef; |
34280 |
++ |
34281 |
++static void nop_handler(int sig) {} |
34282 |
++ |
34283 |
++static int interrupt_sync(struct kdbus_conn *conn_src, |
34284 |
++ struct kdbus_conn *conn_dst) |
34285 |
++{ |
34286 |
++ pid_t pid; |
34287 |
++ int ret, status; |
34288 |
++ struct kdbus_msg *msg = NULL; |
34289 |
++ struct sigaction sa = { |
34290 |
++ .sa_handler = nop_handler, |
34291 |
++ .sa_flags = SA_NOCLDSTOP|SA_RESTART, |
34292 |
++ }; |
34293 |
++ |
34294 |
++ cookie++; |
34295 |
++ pid = fork(); |
34296 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
34297 |
++ |
34298 |
++ if (pid == 0) { |
34299 |
++ ret = sigaction(SIGINT, &sa, NULL); |
34300 |
++ ASSERT_EXIT(ret == 0); |
34301 |
++ |
34302 |
++ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34303 |
++ KDBUS_MSG_EXPECT_REPLY, |
34304 |
++ 100000000ULL, 0, conn_src->id, -1); |
34305 |
++ ASSERT_EXIT(ret == -ETIMEDOUT); |
34306 |
++ |
34307 |
++ _exit(EXIT_SUCCESS); |
34308 |
++ } |
34309 |
++ |
34310 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34311 |
++ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34312 |
++ |
34313 |
++ kdbus_msg_free(msg); |
34314 |
++ |
34315 |
++ ret = kill(pid, SIGINT); |
34316 |
++ ASSERT_RETURN_VAL(ret == 0, ret); |
34317 |
++ |
34318 |
++ ret = waitpid(pid, &status, 0); |
34319 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
34320 |
++ |
34321 |
++ if (WIFSIGNALED(status)) |
34322 |
++ return TEST_ERR; |
34323 |
++ |
34324 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); |
34325 |
++ ASSERT_RETURN(ret == -ETIMEDOUT); |
34326 |
++ |
34327 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34328 |
++} |
34329 |
++ |
34330 |
++static int close_epipe_sync(const char *bus) |
34331 |
++{ |
34332 |
++ pid_t pid; |
34333 |
++ int ret, status; |
34334 |
++ struct kdbus_conn *conn_src; |
34335 |
++ struct kdbus_conn *conn_dst; |
34336 |
++ struct kdbus_msg *msg = NULL; |
34337 |
++ |
34338 |
++ conn_src = kdbus_hello(bus, 0, NULL, 0); |
34339 |
++ ASSERT_RETURN(conn_src); |
34340 |
++ |
34341 |
++ ret = kdbus_add_match_empty(conn_src); |
34342 |
++ ASSERT_RETURN(ret == 0); |
34343 |
++ |
34344 |
++ conn_dst = kdbus_hello(bus, 0, NULL, 0); |
34345 |
++ ASSERT_RETURN(conn_dst); |
34346 |
++ |
34347 |
++ cookie++; |
34348 |
++ pid = fork(); |
34349 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
34350 |
++ |
34351 |
++ if (pid == 0) { |
34352 |
++ uint64_t dst_id; |
34353 |
++ |
34354 |
++ /* close our reference */ |
34355 |
++ dst_id = conn_dst->id; |
34356 |
++ kdbus_conn_free(conn_dst); |
34357 |
++ |
34358 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34359 |
++ ASSERT_EXIT(ret == 0 && msg->cookie == cookie); |
34360 |
++ ASSERT_EXIT(msg->src_id == dst_id); |
34361 |
++ |
34362 |
++ cookie++; |
34363 |
++ ret = kdbus_msg_send_sync(conn_src, NULL, cookie, |
34364 |
++ KDBUS_MSG_EXPECT_REPLY, |
34365 |
++ 100000000ULL, 0, dst_id, -1); |
34366 |
++ ASSERT_EXIT(ret == -EPIPE); |
34367 |
++ |
34368 |
++ _exit(EXIT_SUCCESS); |
34369 |
++ } |
34370 |
++ |
34371 |
++ ret = kdbus_msg_send(conn_dst, NULL, cookie, 0, 0, 0, |
34372 |
++ KDBUS_DST_ID_BROADCAST); |
34373 |
++ ASSERT_RETURN(ret == 0); |
34374 |
++ |
34375 |
++ cookie++; |
34376 |
++ ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); |
34377 |
++ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34378 |
++ |
34379 |
++ kdbus_msg_free(msg); |
34380 |
++ |
34381 |
++ /* destroy connection */ |
34382 |
++ kdbus_conn_free(conn_dst); |
34383 |
++ kdbus_conn_free(conn_src); |
34384 |
++ |
34385 |
++ ret = waitpid(pid, &status, 0); |
34386 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
34387 |
++ |
34388 |
++ if (!WIFEXITED(status)) |
34389 |
++ return TEST_ERR; |
34390 |
++ |
34391 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34392 |
++} |
34393 |
++ |
34394 |
++static int cancel_fd_sync(struct kdbus_conn *conn_src, |
34395 |
++ struct kdbus_conn *conn_dst) |
34396 |
++{ |
34397 |
++ pid_t pid; |
34398 |
++ int cancel_fd; |
34399 |
++ int ret, status; |
34400 |
++ uint64_t counter = 1; |
34401 |
++ struct kdbus_msg *msg = NULL; |
34402 |
++ |
34403 |
++ cancel_fd = eventfd(0, 0); |
34404 |
++ ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); |
34405 |
++ |
34406 |
++ cookie++; |
34407 |
++ pid = fork(); |
34408 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
34409 |
++ |
34410 |
++ if (pid == 0) { |
34411 |
++ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34412 |
++ KDBUS_MSG_EXPECT_REPLY, |
34413 |
++ 100000000ULL, 0, conn_src->id, |
34414 |
++ cancel_fd); |
34415 |
++ ASSERT_EXIT(ret == -ECANCELED); |
34416 |
++ |
34417 |
++ _exit(EXIT_SUCCESS); |
34418 |
++ } |
34419 |
++ |
34420 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34421 |
++ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34422 |
++ |
34423 |
++ kdbus_msg_free(msg); |
34424 |
++ |
34425 |
++ ret = write(cancel_fd, &counter, sizeof(counter)); |
34426 |
++ ASSERT_RETURN(ret == sizeof(counter)); |
34427 |
++ |
34428 |
++ ret = waitpid(pid, &status, 0); |
34429 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
34430 |
++ |
34431 |
++ if (WIFSIGNALED(status)) |
34432 |
++ return TEST_ERR; |
34433 |
++ |
34434 |
++ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34435 |
++} |
34436 |
++ |
34437 |
++static int no_cancel_sync(struct kdbus_conn *conn_src, |
34438 |
++ struct kdbus_conn *conn_dst) |
34439 |
++{ |
34440 |
++ pid_t pid; |
34441 |
++ int cancel_fd; |
34442 |
++ int ret, status; |
34443 |
++ struct kdbus_msg *msg = NULL; |
34444 |
++ |
34445 |
++ /* pass eventfd, but never signal it so it shouldn't have any effect */ |
34446 |
++ |
34447 |
++ cancel_fd = eventfd(0, 0); |
34448 |
++ ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); |
34449 |
++ |
34450 |
++ cookie++; |
34451 |
++ pid = fork(); |
34452 |
++ ASSERT_RETURN_VAL(pid >= 0, pid); |
34453 |
++ |
34454 |
++ if (pid == 0) { |
34455 |
++ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34456 |
++ KDBUS_MSG_EXPECT_REPLY, |
34457 |
++ 100000000ULL, 0, conn_src->id, |
34458 |
++ cancel_fd); |
34459 |
++ ASSERT_EXIT(ret == 0); |
34460 |
++ |
34461 |
++ _exit(EXIT_SUCCESS); |
34462 |
++ } |
34463 |
++ |
34464 |
++ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34465 |
++ ASSERT_RETURN_VAL(ret == 0 && msg->cookie == cookie, -1); |
34466 |
++ |
34467 |
++ kdbus_msg_free(msg); |
34468 |
++ |
34469 |
++ ret = kdbus_msg_send_reply(conn_src, cookie, conn_dst->id); |
34470 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
34471 |
++ |
34472 |
++ ret = waitpid(pid, &status, 0); |
34473 |
++ ASSERT_RETURN_VAL(ret >= 0, ret); |
34474 |
++ |
34475 |
++ if (WIFSIGNALED(status)) |
34476 |
++ return -1; |
34477 |
++ |
34478 |
++ return (status == EXIT_SUCCESS) ? 0 : -1; |
34479 |
++} |
34480 |
++ |
34481 |
++static void *run_thread_reply(void *data) |
34482 |
++{ |
34483 |
++ int ret; |
34484 |
++ unsigned long status = TEST_OK; |
34485 |
++ |
34486 |
++ ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); |
34487 |
++ if (ret < 0) |
34488 |
++ goto exit_thread; |
34489 |
++ |
34490 |
++ kdbus_printf("Thread received message, sending reply ...\n"); |
34491 |
++ |
34492 |
++ /* using an unknown cookie must fail */ |
34493 |
++ ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id); |
34494 |
++ if (ret != -EPERM) { |
34495 |
++ status = TEST_ERR; |
34496 |
++ goto exit_thread; |
34497 |
++ } |
34498 |
++ |
34499 |
++ ret = kdbus_msg_send_reply(conn_a, cookie, conn_b->id); |
34500 |
++ if (ret != 0) { |
34501 |
++ status = TEST_ERR; |
34502 |
++ goto exit_thread; |
34503 |
++ } |
34504 |
++ |
34505 |
++exit_thread: |
34506 |
++ pthread_exit(NULL); |
34507 |
++ return (void *) status; |
34508 |
++} |
34509 |
++ |
34510 |
++int kdbus_test_sync_reply(struct kdbus_test_env *env) |
34511 |
++{ |
34512 |
++ unsigned long status; |
34513 |
++ pthread_t thread; |
34514 |
++ int ret; |
34515 |
++ |
34516 |
++ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34517 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34518 |
++ ASSERT_RETURN(conn_a && conn_b); |
34519 |
++ |
34520 |
++ pthread_create(&thread, NULL, run_thread_reply, NULL); |
34521 |
++ |
34522 |
++ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34523 |
++ KDBUS_MSG_EXPECT_REPLY, |
34524 |
++ 5000000000ULL, 0, conn_a->id, -1); |
34525 |
++ |
34526 |
++ pthread_join(thread, (void *) &status); |
34527 |
++ ASSERT_RETURN(status == 0); |
34528 |
++ ASSERT_RETURN(ret == 0); |
34529 |
++ |
34530 |
++ ret = interrupt_sync(conn_a, conn_b); |
34531 |
++ ASSERT_RETURN(ret == 0); |
34532 |
++ |
34533 |
++ ret = close_epipe_sync(env->buspath); |
34534 |
++ ASSERT_RETURN(ret == 0); |
34535 |
++ |
34536 |
++ ret = cancel_fd_sync(conn_a, conn_b); |
34537 |
++ ASSERT_RETURN(ret == 0); |
34538 |
++ |
34539 |
++ ret = no_cancel_sync(conn_a, conn_b); |
34540 |
++ ASSERT_RETURN(ret == 0); |
34541 |
++ |
34542 |
++ kdbus_printf("-- closing bus connections\n"); |
34543 |
++ |
34544 |
++ kdbus_conn_free(conn_a); |
34545 |
++ kdbus_conn_free(conn_b); |
34546 |
++ |
34547 |
++ return TEST_OK; |
34548 |
++} |
34549 |
++ |
34550 |
++#define BYEBYE_ME ((void*)0L) |
34551 |
++#define BYEBYE_THEM ((void*)1L) |
34552 |
++ |
34553 |
++static void *run_thread_byebye(void *data) |
34554 |
++{ |
34555 |
++ struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; |
34556 |
++ int ret; |
34557 |
++ |
34558 |
++ ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); |
34559 |
++ if (ret == 0) { |
34560 |
++ kdbus_printf("Thread received message, invoking BYEBYE ...\n"); |
34561 |
++ kdbus_msg_recv(conn_a, NULL, NULL); |
34562 |
++ if (data == BYEBYE_ME) |
34563 |
++ kdbus_cmd_byebye(conn_b->fd, &cmd_byebye); |
34564 |
++ else if (data == BYEBYE_THEM) |
34565 |
++ kdbus_cmd_byebye(conn_a->fd, &cmd_byebye); |
34566 |
++ } |
34567 |
++ |
34568 |
++ pthread_exit(NULL); |
34569 |
++ return NULL; |
34570 |
++} |
34571 |
++ |
34572 |
++int kdbus_test_sync_byebye(struct kdbus_test_env *env) |
34573 |
++{ |
34574 |
++ pthread_t thread; |
34575 |
++ int ret; |
34576 |
++ |
34577 |
++ /* |
34578 |
++ * This sends a synchronous message to a thread, which waits until it |
34579 |
++ * received the message and then invokes BYEBYE on the *ORIGINAL* |
34580 |
++ * connection. That is, on the same connection that synchronously waits |
34581 |
++ * for an reply. |
34582 |
++ * This should properly wake the connection up and cause ECONNRESET as |
34583 |
++ * the connection is disconnected now. |
34584 |
++ * |
34585 |
++ * The second time, we do the same but invoke BYEBYE on the *TARGET* |
34586 |
++ * connection. This should also wake up the synchronous sender as the |
34587 |
++ * reply cannot be sent by a disconnected target. |
34588 |
++ */ |
34589 |
++ |
34590 |
++ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34591 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34592 |
++ ASSERT_RETURN(conn_a && conn_b); |
34593 |
++ |
34594 |
++ pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_ME); |
34595 |
++ |
34596 |
++ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34597 |
++ KDBUS_MSG_EXPECT_REPLY, |
34598 |
++ 5000000000ULL, 0, conn_a->id, -1); |
34599 |
++ |
34600 |
++ ASSERT_RETURN(ret == -ECONNRESET); |
34601 |
++ |
34602 |
++ pthread_join(thread, NULL); |
34603 |
++ |
34604 |
++ kdbus_conn_free(conn_a); |
34605 |
++ kdbus_conn_free(conn_b); |
34606 |
++ |
34607 |
++ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34608 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34609 |
++ ASSERT_RETURN(conn_a && conn_b); |
34610 |
++ |
34611 |
++ pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_THEM); |
34612 |
++ |
34613 |
++ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34614 |
++ KDBUS_MSG_EXPECT_REPLY, |
34615 |
++ 5000000000ULL, 0, conn_a->id, -1); |
34616 |
++ |
34617 |
++ ASSERT_RETURN(ret == -EPIPE); |
34618 |
++ |
34619 |
++ pthread_join(thread, NULL); |
34620 |
++ |
34621 |
++ kdbus_conn_free(conn_a); |
34622 |
++ kdbus_conn_free(conn_b); |
34623 |
++ |
34624 |
++ return TEST_OK; |
34625 |
++} |
34626 |
+diff --git a/tools/testing/selftests/kdbus/test-timeout.c b/tools/testing/selftests/kdbus/test-timeout.c |
34627 |
+new file mode 100644 |
34628 |
+index 0000000..cfd1930 |
34629 |
+--- /dev/null |
34630 |
++++ b/tools/testing/selftests/kdbus/test-timeout.c |
34631 |
+@@ -0,0 +1,99 @@ |
34632 |
++#include <stdio.h> |
34633 |
++#include <string.h> |
34634 |
++#include <time.h> |
34635 |
++#include <fcntl.h> |
34636 |
++#include <stdlib.h> |
34637 |
++#include <stddef.h> |
34638 |
++#include <unistd.h> |
34639 |
++#include <stdint.h> |
34640 |
++#include <errno.h> |
34641 |
++#include <assert.h> |
34642 |
++#include <poll.h> |
34643 |
++#include <stdbool.h> |
34644 |
++ |
34645 |
++#include "kdbus-api.h" |
34646 |
++#include "kdbus-test.h" |
34647 |
++#include "kdbus-util.h" |
34648 |
++#include "kdbus-enum.h" |
34649 |
++ |
34650 |
++int timeout_msg_recv(struct kdbus_conn *conn, uint64_t *expected) |
34651 |
++{ |
34652 |
++ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
34653 |
++ struct kdbus_msg *msg; |
34654 |
++ int ret; |
34655 |
++ |
34656 |
++ ret = kdbus_cmd_recv(conn->fd, &recv); |
34657 |
++ if (ret < 0) { |
34658 |
++ kdbus_printf("error receiving message: %d (%m)\n", ret); |
34659 |
++ return ret; |
34660 |
++ } |
34661 |
++ |
34662 |
++ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
34663 |
++ |
34664 |
++ ASSERT_RETURN_VAL(msg->payload_type == KDBUS_PAYLOAD_KERNEL, -EINVAL); |
34665 |
++ ASSERT_RETURN_VAL(msg->src_id == KDBUS_SRC_ID_KERNEL, -EINVAL); |
34666 |
++ ASSERT_RETURN_VAL(msg->dst_id == conn->id, -EINVAL); |
34667 |
++ |
34668 |
++ *expected &= ~(1ULL << msg->cookie_reply); |
34669 |
++ kdbus_printf("Got message timeout for cookie %llu\n", |
34670 |
++ msg->cookie_reply); |
34671 |
++ |
34672 |
++ ret = kdbus_free(conn, recv.msg.offset); |
34673 |
++ if (ret < 0) |
34674 |
++ return ret; |
34675 |
++ |
34676 |
++ return 0; |
34677 |
++} |
34678 |
++ |
34679 |
++int kdbus_test_timeout(struct kdbus_test_env *env) |
34680 |
++{ |
34681 |
++ struct kdbus_conn *conn_a, *conn_b; |
34682 |
++ struct pollfd fd; |
34683 |
++ int ret, i, n_msgs = 4; |
34684 |
++ uint64_t expected = 0; |
34685 |
++ uint64_t cookie = 0xdeadbeef; |
34686 |
++ |
34687 |
++ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34688 |
++ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34689 |
++ ASSERT_RETURN(conn_a && conn_b); |
34690 |
++ |
34691 |
++ fd.fd = conn_b->fd; |
34692 |
++ |
34693 |
++ /* |
34694 |
++ * send messages that expect a reply (within 100 msec), |
34695 |
++ * but never answer it. |
34696 |
++ */ |
34697 |
++ for (i = 0; i < n_msgs; i++, cookie++) { |
34698 |
++ kdbus_printf("Sending message with cookie %llu ...\n", |
34699 |
++ (unsigned long long)cookie); |
34700 |
++ ASSERT_RETURN(kdbus_msg_send(conn_b, NULL, cookie, |
34701 |
++ KDBUS_MSG_EXPECT_REPLY, |
34702 |
++ (i + 1) * 100ULL * 1000000ULL, 0, |
34703 |
++ conn_a->id) == 0); |
34704 |
++ expected |= 1ULL << cookie; |
34705 |
++ } |
34706 |
++ |
34707 |
++ for (;;) { |
34708 |
++ fd.events = POLLIN | POLLPRI | POLLHUP; |
34709 |
++ fd.revents = 0; |
34710 |
++ |
34711 |
++ ret = poll(&fd, 1, (n_msgs + 1) * 100); |
34712 |
++ if (ret == 0) |
34713 |
++ kdbus_printf("--- timeout\n"); |
34714 |
++ if (ret <= 0) |
34715 |
++ break; |
34716 |
++ |
34717 |
++ if (fd.revents & POLLIN) |
34718 |
++ ASSERT_RETURN(!timeout_msg_recv(conn_b, &expected)); |
34719 |
++ |
34720 |
++ if (expected == 0) |
34721 |
++ break; |
34722 |
++ } |
34723 |
++ |
34724 |
++ ASSERT_RETURN(expected == 0); |
34725 |
++ |
34726 |
++ kdbus_conn_free(conn_a); |
34727 |
++ kdbus_conn_free(conn_b); |
34728 |
++ |
34729 |
++ return TEST_OK; |
34730 |
++} |