1 |
commit: 3a0e597bb6b80d0db9567050a1fb2c397c1e3594 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Nov 5 23:30:34 2015 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Nov 5 23:30:34 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=3a0e597b |
7 |
|
8 |
Removing kdbus as per upstream developers. See http://lwn.net/Articles/663062/ |
9 |
|
10 |
0000_README | 4 - |
11 |
5015_kdbus-8-12-2015.patch | 34349 ------------------------------------------- |
12 |
2 files changed, 34353 deletions(-) |
13 |
|
14 |
diff --git a/0000_README b/0000_README |
15 |
index d40ecf2..cf9d964 100644 |
16 |
--- a/0000_README |
17 |
+++ b/0000_README |
18 |
@@ -110,7 +110,3 @@ Desc: BFQ v7r8 patch 3 for 4.2: Early Queue Merge (EQM) |
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-8-12-2015.patch |
24 |
-From: https://lkml.org |
25 |
-Desc: Kernel-level IPC implementation |
26 |
|
27 |
diff --git a/5015_kdbus-8-12-2015.patch b/5015_kdbus-8-12-2015.patch |
28 |
deleted file mode 100644 |
29 |
index 4e018f2..0000000 |
30 |
--- a/5015_kdbus-8-12-2015.patch |
31 |
+++ /dev/null |
32 |
@@ -1,34349 +0,0 @@ |
33 |
-diff --git a/Documentation/Makefile b/Documentation/Makefile |
34 |
-index bc05482..e2127a7 100644 |
35 |
---- a/Documentation/Makefile |
36 |
-+++ b/Documentation/Makefile |
37 |
-@@ -1,4 +1,4 @@ |
38 |
- subdir-y := accounting 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 51f4221..ec7c81b 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..8caffe5 |
66 |
---- /dev/null |
67 |
-+++ b/Documentation/kdbus/Makefile |
68 |
-@@ -0,0 +1,44 @@ |
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 |
-+ |
110 |
-+# we don't support other %docs targets right now |
111 |
-+%docs: |
112 |
-+ @true |
113 |
-diff --git a/Documentation/kdbus/kdbus.bus.xml b/Documentation/kdbus/kdbus.bus.xml |
114 |
-new file mode 100644 |
115 |
-index 0000000..83f1198 |
116 |
---- /dev/null |
117 |
-+++ b/Documentation/kdbus/kdbus.bus.xml |
118 |
-@@ -0,0 +1,344 @@ |
119 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
120 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
121 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
122 |
-+ |
123 |
-+<refentry id="kdbus.bus"> |
124 |
-+ |
125 |
-+ <refentryinfo> |
126 |
-+ <title>kdbus.bus</title> |
127 |
-+ <productname>kdbus.bus</productname> |
128 |
-+ </refentryinfo> |
129 |
-+ |
130 |
-+ <refmeta> |
131 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
132 |
-+ <manvolnum>7</manvolnum> |
133 |
-+ </refmeta> |
134 |
-+ |
135 |
-+ <refnamediv> |
136 |
-+ <refname>kdbus.bus</refname> |
137 |
-+ <refpurpose>kdbus bus</refpurpose> |
138 |
-+ </refnamediv> |
139 |
-+ |
140 |
-+ <refsect1> |
141 |
-+ <title>Description</title> |
142 |
-+ |
143 |
-+ <para> |
144 |
-+ A bus is a resource that is shared between connections in order to |
145 |
-+ transmit messages (see |
146 |
-+ <citerefentry> |
147 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
148 |
-+ <manvolnum>7</manvolnum> |
149 |
-+ </citerefentry>). |
150 |
-+ Each bus is independent, and operations on the bus will not have any |
151 |
-+ effect on other buses. A bus is a management entity that controls the |
152 |
-+ addresses of its connections, their policies and message transactions |
153 |
-+ performed via this bus. |
154 |
-+ </para> |
155 |
-+ <para> |
156 |
-+ Each bus is bound to the mount instance it was created on. It has a |
157 |
-+ custom name that is unique across all buses of a domain. In |
158 |
-+ <citerefentry> |
159 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
160 |
-+ <manvolnum>7</manvolnum> |
161 |
-+ </citerefentry> |
162 |
-+ a bus is presented as a directory. No operations can be performed on |
163 |
-+ the bus itself; instead you need to perform the operations on an endpoint |
164 |
-+ associated with the bus. Endpoints are accessible as files underneath the |
165 |
-+ bus directory. A default endpoint called <constant>bus</constant> is |
166 |
-+ provided on each bus. |
167 |
-+ </para> |
168 |
-+ <para> |
169 |
-+ Bus names may be chosen freely except for one restriction: the name must |
170 |
-+ be prefixed with the numeric effective UID of the creator and a dash. This |
171 |
-+ is required to avoid namespace clashes between different users. When |
172 |
-+ creating a bus, the name that is passed in must be properly formatted, or |
173 |
-+ the kernel will refuse creation of the bus. Example: |
174 |
-+ <literal>1047-foobar</literal> is an acceptable name for a bus |
175 |
-+ registered by a user with UID 1047. However, |
176 |
-+ <literal>1024-foobar</literal> is not, and neither is |
177 |
-+ <literal>foobar</literal>. The UID must be provided in the |
178 |
-+ user-namespace of the bus owner. |
179 |
-+ </para> |
180 |
-+ <para> |
181 |
-+ To create a new bus, you need to open the control file of a domain and |
182 |
-+ employ the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. The control |
183 |
-+ file descriptor that was used to issue |
184 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> must not previously have been |
185 |
-+ used for any other control-ioctl and must be kept open for the entire |
186 |
-+ life-time of the created bus. Closing it will immediately cleanup the |
187 |
-+ entire bus and all its associated resources and endpoints. Every control |
188 |
-+ file descriptor can only be used to create a single new bus; from that |
189 |
-+ point on, it is not used for any further communication until the final |
190 |
-+ <citerefentry> |
191 |
-+ <refentrytitle>close</refentrytitle> |
192 |
-+ <manvolnum>2</manvolnum> |
193 |
-+ </citerefentry> |
194 |
-+ . |
195 |
-+ </para> |
196 |
-+ <para> |
197 |
-+ Each bus will generate a random, 128-bit UUID upon creation. This UUID |
198 |
-+ will be returned to creators of connections through |
199 |
-+ <varname>kdbus_cmd_hello.id128</varname> and can be used to uniquely |
200 |
-+ identify buses, even across different machines or containers. The UUID |
201 |
-+ will have its variant bits set to <literal>DCE</literal>, and denote |
202 |
-+ version 4 (random). For more details on UUIDs, see <ulink |
203 |
-+ url="https://en.wikipedia.org/wiki/Universally_unique_identifier"> |
204 |
-+ the Wikipedia article on UUIDs</ulink>. |
205 |
-+ </para> |
206 |
-+ |
207 |
-+ </refsect1> |
208 |
-+ |
209 |
-+ <refsect1> |
210 |
-+ <title>Creating buses</title> |
211 |
-+ <para> |
212 |
-+ To create a new bus, the <constant>KDBUS_CMD_BUS_MAKE</constant> |
213 |
-+ command is used. It takes a <type>struct kdbus_cmd</type> argument. |
214 |
-+ </para> |
215 |
-+ <programlisting> |
216 |
-+struct kdbus_cmd { |
217 |
-+ __u64 size; |
218 |
-+ __u64 flags; |
219 |
-+ __u64 return_flags; |
220 |
-+ struct kdbus_item items[0]; |
221 |
-+}; |
222 |
-+ </programlisting> |
223 |
-+ |
224 |
-+ <para>The fields in this struct are described below.</para> |
225 |
-+ |
226 |
-+ <variablelist> |
227 |
-+ <varlistentry> |
228 |
-+ <term><varname>size</varname></term> |
229 |
-+ <listitem><para> |
230 |
-+ The overall size of the struct, including its items. |
231 |
-+ </para></listitem> |
232 |
-+ </varlistentry> |
233 |
-+ |
234 |
-+ <varlistentry> |
235 |
-+ <term><varname>flags</varname></term> |
236 |
-+ <listitem><para>The flags for creation.</para> |
237 |
-+ <variablelist> |
238 |
-+ <varlistentry> |
239 |
-+ <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term> |
240 |
-+ <listitem> |
241 |
-+ <para>Make the bus file group-accessible.</para> |
242 |
-+ </listitem> |
243 |
-+ </varlistentry> |
244 |
-+ |
245 |
-+ <varlistentry> |
246 |
-+ <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term> |
247 |
-+ <listitem> |
248 |
-+ <para>Make the bus file world-accessible.</para> |
249 |
-+ </listitem> |
250 |
-+ </varlistentry> |
251 |
-+ |
252 |
-+ <varlistentry> |
253 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
254 |
-+ <listitem> |
255 |
-+ <para> |
256 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
257 |
-+ set, no action is taken; the ioctl will return |
258 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
259 |
-+ field will have all bits set that are valid for this command. |
260 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
261 |
-+ cleared by the operation. |
262 |
-+ </para> |
263 |
-+ </listitem> |
264 |
-+ </varlistentry> |
265 |
-+ </variablelist> |
266 |
-+ </listitem> |
267 |
-+ </varlistentry> |
268 |
-+ |
269 |
-+ <varlistentry> |
270 |
-+ <term><varname>return_flags</varname></term> |
271 |
-+ <listitem><para> |
272 |
-+ Flags returned by the kernel. Currently unused and always set to |
273 |
-+ <constant>0</constant> by the kernel. |
274 |
-+ </para></listitem> |
275 |
-+ </varlistentry> |
276 |
-+ |
277 |
-+ <varlistentry> |
278 |
-+ <term><varname>items</varname></term> |
279 |
-+ <listitem> |
280 |
-+ <para> |
281 |
-+ The following items (see |
282 |
-+ <citerefentry> |
283 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
284 |
-+ <manvolnum>7</manvolnum> |
285 |
-+ </citerefentry>) |
286 |
-+ are expected for <constant>KDBUS_CMD_BUS_MAKE</constant>. |
287 |
-+ </para> |
288 |
-+ <variablelist> |
289 |
-+ <varlistentry> |
290 |
-+ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
291 |
-+ <listitem> |
292 |
-+ <para> |
293 |
-+ Contains a null-terminated string that identifies the |
294 |
-+ bus. The name must be unique across the kdbus domain and |
295 |
-+ must start with the effective UID of the caller, followed by |
296 |
-+ a '<literal>-</literal>' (dash). This item is mandatory. |
297 |
-+ </para> |
298 |
-+ </listitem> |
299 |
-+ </varlistentry> |
300 |
-+ |
301 |
-+ <varlistentry> |
302 |
-+ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
303 |
-+ <listitem> |
304 |
-+ <para> |
305 |
-+ Bus-wide bloom parameters passed in a |
306 |
-+ <type>struct kdbus_bloom_parameter</type>. These settings are |
307 |
-+ copied back to new connections verbatim. This item is |
308 |
-+ mandatory. See |
309 |
-+ <citerefentry> |
310 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
311 |
-+ <manvolnum>7</manvolnum> |
312 |
-+ </citerefentry> |
313 |
-+ for a more detailed description of this item. |
314 |
-+ </para> |
315 |
-+ </listitem> |
316 |
-+ </varlistentry> |
317 |
-+ |
318 |
-+ <varlistentry> |
319 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
320 |
-+ <listitem> |
321 |
-+ <para> |
322 |
-+ An optional item that contains a set of attach flags that are |
323 |
-+ returned to connections when they query the bus creator |
324 |
-+ metadata. If not set, no metadata is returned. |
325 |
-+ </para> |
326 |
-+ </listitem> |
327 |
-+ </varlistentry> |
328 |
-+ |
329 |
-+ <varlistentry> |
330 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
331 |
-+ <listitem><para> |
332 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
333 |
-+ kernel for known item types. See |
334 |
-+ <citerefentry> |
335 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
336 |
-+ <manvolnum>7</manvolnum> |
337 |
-+ </citerefentry> |
338 |
-+ for more details. |
339 |
-+ </para></listitem> |
340 |
-+ </varlistentry> |
341 |
-+ </variablelist> |
342 |
-+ </listitem> |
343 |
-+ </varlistentry> |
344 |
-+ </variablelist> |
345 |
-+ |
346 |
-+ <para> |
347 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
348 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
349 |
-+ </para> |
350 |
-+ </refsect1> |
351 |
-+ |
352 |
-+ <refsect1> |
353 |
-+ <title>Return value</title> |
354 |
-+ <para> |
355 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
356 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
357 |
-+ <varname>errno</varname> is set to indicate the error. |
358 |
-+ If the issued ioctl is illegal for the file descriptor used, |
359 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
360 |
-+ </para> |
361 |
-+ |
362 |
-+ <refsect2> |
363 |
-+ <title> |
364 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> may fail with the following |
365 |
-+ errors |
366 |
-+ </title> |
367 |
-+ |
368 |
-+ <variablelist> |
369 |
-+ <varlistentry> |
370 |
-+ <term><constant>EBADMSG</constant></term> |
371 |
-+ <listitem><para> |
372 |
-+ A mandatory item is missing. |
373 |
-+ </para></listitem> |
374 |
-+ </varlistentry> |
375 |
-+ |
376 |
-+ <varlistentry> |
377 |
-+ <term><constant>EINVAL</constant></term> |
378 |
-+ <listitem><para> |
379 |
-+ The flags supplied in the <constant>struct kdbus_cmd</constant> |
380 |
-+ are invalid or the supplied name does not start with the current |
381 |
-+ UID and a '<literal>-</literal>' (dash). |
382 |
-+ </para></listitem> |
383 |
-+ </varlistentry> |
384 |
-+ |
385 |
-+ <varlistentry> |
386 |
-+ <term><constant>EEXIST</constant></term> |
387 |
-+ <listitem><para> |
388 |
-+ A bus of that name already exists. |
389 |
-+ </para></listitem> |
390 |
-+ </varlistentry> |
391 |
-+ |
392 |
-+ <varlistentry> |
393 |
-+ <term><constant>ESHUTDOWN</constant></term> |
394 |
-+ <listitem><para> |
395 |
-+ The kdbus mount instance for the bus was already shut down. |
396 |
-+ </para></listitem> |
397 |
-+ </varlistentry> |
398 |
-+ |
399 |
-+ <varlistentry> |
400 |
-+ <term><constant>EMFILE</constant></term> |
401 |
-+ <listitem><para> |
402 |
-+ The maximum number of buses for the current user is exhausted. |
403 |
-+ </para></listitem> |
404 |
-+ </varlistentry> |
405 |
-+ </variablelist> |
406 |
-+ </refsect2> |
407 |
-+ </refsect1> |
408 |
-+ |
409 |
-+ <refsect1> |
410 |
-+ <title>See Also</title> |
411 |
-+ <simplelist type="inline"> |
412 |
-+ <member> |
413 |
-+ <citerefentry> |
414 |
-+ <refentrytitle>kdbus</refentrytitle> |
415 |
-+ <manvolnum>7</manvolnum> |
416 |
-+ </citerefentry> |
417 |
-+ </member> |
418 |
-+ <member> |
419 |
-+ <citerefentry> |
420 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
421 |
-+ <manvolnum>7</manvolnum> |
422 |
-+ </citerefentry> |
423 |
-+ </member> |
424 |
-+ <member> |
425 |
-+ <citerefentry> |
426 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
427 |
-+ <manvolnum>7</manvolnum> |
428 |
-+ </citerefentry> |
429 |
-+ </member> |
430 |
-+ <member> |
431 |
-+ <citerefentry> |
432 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
433 |
-+ <manvolnum>7</manvolnum> |
434 |
-+ </citerefentry> |
435 |
-+ </member> |
436 |
-+ <member> |
437 |
-+ <citerefentry> |
438 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
439 |
-+ <manvolnum>7</manvolnum> |
440 |
-+ </citerefentry> |
441 |
-+ </member> |
442 |
-+ <member> |
443 |
-+ <citerefentry> |
444 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
445 |
-+ <manvolnum>7</manvolnum> |
446 |
-+ </citerefentry> |
447 |
-+ </member> |
448 |
-+ <member> |
449 |
-+ <citerefentry> |
450 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
451 |
-+ <manvolnum>7</manvolnum> |
452 |
-+ </citerefentry> |
453 |
-+ </member> |
454 |
-+ <member> |
455 |
-+ <citerefentry> |
456 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
457 |
-+ <manvolnum>7</manvolnum> |
458 |
-+ </citerefentry> |
459 |
-+ </member> |
460 |
-+ </simplelist> |
461 |
-+ </refsect1> |
462 |
-+</refentry> |
463 |
-diff --git a/Documentation/kdbus/kdbus.connection.xml b/Documentation/kdbus/kdbus.connection.xml |
464 |
-new file mode 100644 |
465 |
-index 0000000..4bb5f30 |
466 |
---- /dev/null |
467 |
-+++ b/Documentation/kdbus/kdbus.connection.xml |
468 |
-@@ -0,0 +1,1244 @@ |
469 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
470 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
471 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
472 |
-+ |
473 |
-+<refentry id="kdbus.connection"> |
474 |
-+ |
475 |
-+ <refentryinfo> |
476 |
-+ <title>kdbus.connection</title> |
477 |
-+ <productname>kdbus.connection</productname> |
478 |
-+ </refentryinfo> |
479 |
-+ |
480 |
-+ <refmeta> |
481 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
482 |
-+ <manvolnum>7</manvolnum> |
483 |
-+ </refmeta> |
484 |
-+ |
485 |
-+ <refnamediv> |
486 |
-+ <refname>kdbus.connection</refname> |
487 |
-+ <refpurpose>kdbus connection</refpurpose> |
488 |
-+ </refnamediv> |
489 |
-+ |
490 |
-+ <refsect1> |
491 |
-+ <title>Description</title> |
492 |
-+ |
493 |
-+ <para> |
494 |
-+ Connections are identified by their <emphasis>connection ID</emphasis>, |
495 |
-+ internally implemented as a <type>uint64_t</type> counter. |
496 |
-+ The IDs of every newly created bus start at <constant>1</constant>, and |
497 |
-+ every new connection will increment the counter by <constant>1</constant>. |
498 |
-+ The IDs are not reused. |
499 |
-+ </para> |
500 |
-+ <para> |
501 |
-+ In higher level tools, the user visible representation of a connection is |
502 |
-+ defined by the D-Bus protocol specification as |
503 |
-+ <constant>":1.<ID>"</constant>. |
504 |
-+ </para> |
505 |
-+ <para> |
506 |
-+ Messages with a specific <type>uint64_t</type> destination ID are |
507 |
-+ directly delivered to the connection with the corresponding ID. Signal |
508 |
-+ messages (see |
509 |
-+ <citerefentry> |
510 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
511 |
-+ <manvolnum>7</manvolnum> |
512 |
-+ </citerefentry>) |
513 |
-+ may be addressed to the special destination ID |
514 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> (~0ULL) and will then |
515 |
-+ potentially be delivered to all currently active connections on the bus. |
516 |
-+ However, in order to receive any signal messages, clients must subscribe |
517 |
-+ to them by installing a match (see |
518 |
-+ <citerefentry> |
519 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
520 |
-+ <manvolnum>7</manvolnum> |
521 |
-+ </citerefentry>). |
522 |
-+ </para> |
523 |
-+ <para> |
524 |
-+ Messages synthesized and sent directly by the kernel will carry the |
525 |
-+ special source ID <constant>KDBUS_SRC_ID_KERNEL</constant> (0). |
526 |
-+ </para> |
527 |
-+ <para> |
528 |
-+ In addition to the unique <type>uint64_t</type> connection ID, |
529 |
-+ established connections can request the ownership of |
530 |
-+ <emphasis>well-known names</emphasis>, under which they can be found and |
531 |
-+ addressed by other bus clients. A well-known name is associated with one |
532 |
-+ and only one connection at a time. See |
533 |
-+ <citerefentry> |
534 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
535 |
-+ <manvolnum>7</manvolnum> |
536 |
-+ </citerefentry> |
537 |
-+ on name acquisition, the name registry, and the validity of names. |
538 |
-+ </para> |
539 |
-+ <para> |
540 |
-+ Messages can specify the special destination ID |
541 |
-+ <constant>KDBUS_DST_ID_NAME</constant> (0) and carry a well-known name |
542 |
-+ in the message data. Such a message is delivered to the destination |
543 |
-+ connection which owns that well-known name. |
544 |
-+ </para> |
545 |
-+ |
546 |
-+ <programlisting><![CDATA[ |
547 |
-+ +-------------------------------------------------------------------------+ |
548 |
-+ | +---------------+ +---------------------------+ | |
549 |
-+ | | Connection | | Message | -----------------+ | |
550 |
-+ | | :1.22 | --> | src: 22 | | | |
551 |
-+ | | | | dst: 25 | | | |
552 |
-+ | | | | | | | |
553 |
-+ | | | | | | | |
554 |
-+ | | | +---------------------------+ | | |
555 |
-+ | | | | | |
556 |
-+ | | | <--------------------------------------+ | | |
557 |
-+ | +---------------+ | | | |
558 |
-+ | | | | |
559 |
-+ | +---------------+ +---------------------------+ | | | |
560 |
-+ | | Connection | | Message | -----+ | | |
561 |
-+ | | :1.25 | --> | src: 25 | | | |
562 |
-+ | | | | dst: 0xffffffffffffffff | -------------+ | | |
563 |
-+ | | | | (KDBUS_DST_ID_BROADCAST) | | | | |
564 |
-+ | | | | | ---------+ | | | |
565 |
-+ | | | +---------------------------+ | | | | |
566 |
-+ | | | | | | | |
567 |
-+ | | | <--------------------------------------------------+ | |
568 |
-+ | +---------------+ | | | |
569 |
-+ | | | | |
570 |
-+ | +---------------+ +---------------------------+ | | | |
571 |
-+ | | Connection | | Message | --+ | | | |
572 |
-+ | | :1.55 | --> | src: 55 | | | | | |
573 |
-+ | | | | dst: 0 / org.foo.bar | | | | | |
574 |
-+ | | | | | | | | | |
575 |
-+ | | | | | | | | | |
576 |
-+ | | | +---------------------------+ | | | | |
577 |
-+ | | | | | | | |
578 |
-+ | | | <------------------------------------------+ | | |
579 |
-+ | +---------------+ | | | |
580 |
-+ | | | | |
581 |
-+ | +---------------+ | | | |
582 |
-+ | | Connection | | | | |
583 |
-+ | | :1.81 | | | | |
584 |
-+ | | org.foo.bar | | | | |
585 |
-+ | | | | | | |
586 |
-+ | | | | | | |
587 |
-+ | | | <-----------------------------------+ | | |
588 |
-+ | | | | | |
589 |
-+ | | | <----------------------------------------------+ | |
590 |
-+ | +---------------+ | |
591 |
-+ +-------------------------------------------------------------------------+ |
592 |
-+ ]]></programlisting> |
593 |
-+ </refsect1> |
594 |
-+ |
595 |
-+ <refsect1> |
596 |
-+ <title>Privileged connections</title> |
597 |
-+ <para> |
598 |
-+ A connection is considered <emphasis>privileged</emphasis> if the user |
599 |
-+ it was created by is the same that created the bus, or if the creating |
600 |
-+ task had <constant>CAP_IPC_OWNER</constant> set when it called |
601 |
-+ <constant>KDBUS_CMD_HELLO</constant> (see below). |
602 |
-+ </para> |
603 |
-+ <para> |
604 |
-+ Privileged connections have permission to employ certain restricted |
605 |
-+ functions and commands, which are explained below and in other kdbus |
606 |
-+ man-pages. |
607 |
-+ </para> |
608 |
-+ </refsect1> |
609 |
-+ |
610 |
-+ <refsect1> |
611 |
-+ <title>Activator and policy holder connection</title> |
612 |
-+ <para> |
613 |
-+ An <emphasis>activator</emphasis> connection is a placeholder for a |
614 |
-+ <emphasis>well-known name</emphasis>. Messages sent to such a connection |
615 |
-+ can be used to start an implementer connection, which will then get all |
616 |
-+ the messages from the activator copied over. An activator connection |
617 |
-+ cannot be used to send any message. |
618 |
-+ </para> |
619 |
-+ <para> |
620 |
-+ A <emphasis>policy holder</emphasis> connection only installs a policy |
621 |
-+ for one or more names. These policy entries are kept active as long as |
622 |
-+ the connection is alive, and are removed once it terminates. Such a |
623 |
-+ policy connection type can be used to deploy restrictions for names that |
624 |
-+ are not yet active on the bus. A policy holder connection cannot be used |
625 |
-+ to send any message. |
626 |
-+ </para> |
627 |
-+ <para> |
628 |
-+ The creation of activator or policy holder connections is restricted to |
629 |
-+ privileged users on the bus (see above). |
630 |
-+ </para> |
631 |
-+ </refsect1> |
632 |
-+ |
633 |
-+ <refsect1> |
634 |
-+ <title>Monitor connections</title> |
635 |
-+ <para> |
636 |
-+ Monitors are eavesdropping connections that receive all the traffic on the |
637 |
-+ bus, but is invisible to other connections. Such connections have all |
638 |
-+ properties of any other, regular connection, except for the following |
639 |
-+ details: |
640 |
-+ </para> |
641 |
-+ |
642 |
-+ <itemizedlist> |
643 |
-+ <listitem><para> |
644 |
-+ They will get every message sent over the bus, both unicasts and |
645 |
-+ broadcasts. |
646 |
-+ </para></listitem> |
647 |
-+ |
648 |
-+ <listitem><para> |
649 |
-+ Installing matches for signal messages is neither necessary |
650 |
-+ nor allowed. |
651 |
-+ </para></listitem> |
652 |
-+ |
653 |
-+ <listitem><para> |
654 |
-+ They cannot send messages or be directly addressed as receiver. |
655 |
-+ </para></listitem> |
656 |
-+ |
657 |
-+ <listitem><para> |
658 |
-+ They cannot own well-known names. Therefore, they also can't operate as |
659 |
-+ activators. |
660 |
-+ </para></listitem> |
661 |
-+ |
662 |
-+ <listitem><para> |
663 |
-+ Their creation and destruction will not cause |
664 |
-+ <constant>KDBUS_ITEM_ID_{ADD,REMOVE}</constant> (see |
665 |
-+ <citerefentry> |
666 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
667 |
-+ <manvolnum>7</manvolnum> |
668 |
-+ </citerefentry>). |
669 |
-+ </para></listitem> |
670 |
-+ |
671 |
-+ <listitem><para> |
672 |
-+ They are not listed with their unique name in name registry dumps |
673 |
-+ (see <constant>KDBUS_CMD_NAME_LIST</constant> in |
674 |
-+ <citerefentry> |
675 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
676 |
-+ <manvolnum>7</manvolnum> |
677 |
-+ </citerefentry>), so other connections cannot detect the presence of |
678 |
-+ a monitor. |
679 |
-+ </para></listitem> |
680 |
-+ </itemizedlist> |
681 |
-+ <para> |
682 |
-+ The creation of monitor connections is restricted to privileged users on |
683 |
-+ the bus (see above). |
684 |
-+ </para> |
685 |
-+ </refsect1> |
686 |
-+ |
687 |
-+ <refsect1> |
688 |
-+ <title>Creating connections</title> |
689 |
-+ <para> |
690 |
-+ A connection to a bus is created by opening an endpoint file (see |
691 |
-+ <citerefentry> |
692 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
693 |
-+ <manvolnum>7</manvolnum> |
694 |
-+ </citerefentry>) |
695 |
-+ of a bus and becoming an active client with the |
696 |
-+ <constant>KDBUS_CMD_HELLO</constant> ioctl. Every connection has a unique |
697 |
-+ identifier on the bus and can address messages to every other connection |
698 |
-+ on the same bus by using the peer's connection ID as the destination. |
699 |
-+ </para> |
700 |
-+ <para> |
701 |
-+ The <constant>KDBUS_CMD_HELLO</constant> ioctl takes a <type>struct |
702 |
-+ kdbus_cmd_hello</type> as argument. |
703 |
-+ </para> |
704 |
-+ |
705 |
-+ <programlisting> |
706 |
-+struct kdbus_cmd_hello { |
707 |
-+ __u64 size; |
708 |
-+ __u64 flags; |
709 |
-+ __u64 return_flags; |
710 |
-+ __u64 attach_flags_send; |
711 |
-+ __u64 attach_flags_recv; |
712 |
-+ __u64 bus_flags; |
713 |
-+ __u64 id; |
714 |
-+ __u64 pool_size; |
715 |
-+ __u64 offset; |
716 |
-+ __u8 id128[16]; |
717 |
-+ struct kdbus_item items[0]; |
718 |
-+}; |
719 |
-+ </programlisting> |
720 |
-+ |
721 |
-+ <para>The fields in this struct are described below.</para> |
722 |
-+ |
723 |
-+ <variablelist> |
724 |
-+ <varlistentry> |
725 |
-+ <term><varname>size</varname></term> |
726 |
-+ <listitem><para> |
727 |
-+ The overall size of the struct, including its items. |
728 |
-+ </para></listitem> |
729 |
-+ </varlistentry> |
730 |
-+ |
731 |
-+ <varlistentry> |
732 |
-+ <term><varname>flags</varname></term> |
733 |
-+ <listitem> |
734 |
-+ <para>Flags to apply to this connection</para> |
735 |
-+ <variablelist> |
736 |
-+ <varlistentry> |
737 |
-+ <term><constant>KDBUS_HELLO_ACCEPT_FD</constant></term> |
738 |
-+ <listitem> |
739 |
-+ <para> |
740 |
-+ When this flag is set, the connection can be sent file |
741 |
-+ descriptors as message payload of unicast messages. If it's |
742 |
-+ not set, an attempt to send file descriptors will result in |
743 |
-+ <constant>-ECOMM</constant> on the sender's side. |
744 |
-+ </para> |
745 |
-+ </listitem> |
746 |
-+ </varlistentry> |
747 |
-+ |
748 |
-+ <varlistentry> |
749 |
-+ <term><constant>KDBUS_HELLO_ACTIVATOR</constant></term> |
750 |
-+ <listitem> |
751 |
-+ <para> |
752 |
-+ Make this connection an activator (see above). With this bit |
753 |
-+ set, an item of type <constant>KDBUS_ITEM_NAME</constant> has |
754 |
-+ to be attached. This item describes the well-known name this |
755 |
-+ connection should be an activator for. |
756 |
-+ A connection can not be an activator and a policy holder at |
757 |
-+ the same time time, so this bit is not allowed together with |
758 |
-+ <constant>KDBUS_HELLO_POLICY_HOLDER</constant>. |
759 |
-+ </para> |
760 |
-+ </listitem> |
761 |
-+ </varlistentry> |
762 |
-+ |
763 |
-+ <varlistentry> |
764 |
-+ <term><constant>KDBUS_HELLO_POLICY_HOLDER</constant></term> |
765 |
-+ <listitem> |
766 |
-+ <para> |
767 |
-+ Make this connection a policy holder (see above). With this |
768 |
-+ bit set, an item of type <constant>KDBUS_ITEM_NAME</constant> |
769 |
-+ has to be attached. This item describes the well-known name |
770 |
-+ this connection should hold a policy for. |
771 |
-+ A connection can not be an activator and a policy holder at |
772 |
-+ the same time time, so this bit is not allowed together with |
773 |
-+ <constant>KDBUS_HELLO_ACTIVATOR</constant>. |
774 |
-+ </para> |
775 |
-+ </listitem> |
776 |
-+ </varlistentry> |
777 |
-+ |
778 |
-+ <varlistentry> |
779 |
-+ <term><constant>KDBUS_HELLO_MONITOR</constant></term> |
780 |
-+ <listitem> |
781 |
-+ <para> |
782 |
-+ Make this connection a monitor connection (see above). |
783 |
-+ </para> |
784 |
-+ <para> |
785 |
-+ This flag can only be set by privileged bus connections. See |
786 |
-+ below for more information. |
787 |
-+ A connection can not be monitor and an activator or a policy |
788 |
-+ holder at the same time time, so this bit is not allowed |
789 |
-+ together with <constant>KDBUS_HELLO_ACTIVATOR</constant> or |
790 |
-+ <constant>KDBUS_HELLO_POLICY_HOLDER</constant>. |
791 |
-+ </para> |
792 |
-+ </listitem> |
793 |
-+ </varlistentry> |
794 |
-+ |
795 |
-+ <varlistentry> |
796 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
797 |
-+ <listitem> |
798 |
-+ <para> |
799 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
800 |
-+ set, no action is taken; the ioctl will return |
801 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
802 |
-+ field will have all bits set that are valid for this command. |
803 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
804 |
-+ cleared by the operation. |
805 |
-+ </para> |
806 |
-+ </listitem> |
807 |
-+ </varlistentry> |
808 |
-+ </variablelist> |
809 |
-+ </listitem> |
810 |
-+ </varlistentry> |
811 |
-+ |
812 |
-+ <varlistentry> |
813 |
-+ <term><varname>return_flags</varname></term> |
814 |
-+ <listitem><para> |
815 |
-+ Flags returned by the kernel. Currently unused and always set to |
816 |
-+ <constant>0</constant> by the kernel. |
817 |
-+ </para></listitem> |
818 |
-+ </varlistentry> |
819 |
-+ |
820 |
-+ <varlistentry> |
821 |
-+ <term><varname>attach_flags_send</varname></term> |
822 |
-+ <listitem><para> |
823 |
-+ Set the bits for metadata this connection permits to be sent to the |
824 |
-+ receiving peer. Only metadata items that are both allowed to be sent |
825 |
-+ by the sender and that are requested by the receiver will be attached |
826 |
-+ to the message. |
827 |
-+ </para></listitem> |
828 |
-+ </varlistentry> |
829 |
-+ |
830 |
-+ <varlistentry> |
831 |
-+ <term><varname>attach_flags_recv</varname></term> |
832 |
-+ <listitem><para> |
833 |
-+ Request the attachment of metadata for each message received by this |
834 |
-+ connection. See |
835 |
-+ <citerefentry> |
836 |
-+ <refentrytitle>kdbus</refentrytitle> |
837 |
-+ <manvolnum>7</manvolnum> |
838 |
-+ </citerefentry> |
839 |
-+ for information about metadata, and |
840 |
-+ <citerefentry> |
841 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
842 |
-+ <manvolnum>7</manvolnum> |
843 |
-+ </citerefentry> |
844 |
-+ regarding items in general. |
845 |
-+ </para></listitem> |
846 |
-+ </varlistentry> |
847 |
-+ |
848 |
-+ <varlistentry> |
849 |
-+ <term><varname>bus_flags</varname></term> |
850 |
-+ <listitem><para> |
851 |
-+ Upon successful completion of the ioctl, this member will contain the |
852 |
-+ flags of the bus it connected to. |
853 |
-+ </para></listitem> |
854 |
-+ </varlistentry> |
855 |
-+ |
856 |
-+ <varlistentry> |
857 |
-+ <term><varname>id</varname></term> |
858 |
-+ <listitem><para> |
859 |
-+ Upon successful completion of the command, this member will contain |
860 |
-+ the numerical ID of the new connection. |
861 |
-+ </para></listitem> |
862 |
-+ </varlistentry> |
863 |
-+ |
864 |
-+ <varlistentry> |
865 |
-+ <term><varname>pool_size</varname></term> |
866 |
-+ <listitem><para> |
867 |
-+ The size of the communication pool, in bytes. The pool can be |
868 |
-+ accessed by calling |
869 |
-+ <citerefentry> |
870 |
-+ <refentrytitle>mmap</refentrytitle> |
871 |
-+ <manvolnum>2</manvolnum> |
872 |
-+ </citerefentry> |
873 |
-+ on the file descriptor that was used to issue the |
874 |
-+ <constant>KDBUS_CMD_HELLO</constant> ioctl. |
875 |
-+ The pool size of a connection must be greater than |
876 |
-+ <constant>0</constant> and a multiple of |
877 |
-+ <constant>PAGE_SIZE</constant>. See |
878 |
-+ <citerefentry> |
879 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
880 |
-+ <manvolnum>7</manvolnum> |
881 |
-+ </citerefentry> |
882 |
-+ for more information. |
883 |
-+ </para></listitem> |
884 |
-+ </varlistentry> |
885 |
-+ |
886 |
-+ <varlistentry> |
887 |
-+ <term><varname>offset</varname></term> |
888 |
-+ <listitem><para> |
889 |
-+ The kernel will return the offset in the pool where returned details |
890 |
-+ will be stored. See below. |
891 |
-+ </para></listitem> |
892 |
-+ </varlistentry> |
893 |
-+ |
894 |
-+ <varlistentry> |
895 |
-+ <term><varname>id128</varname></term> |
896 |
-+ <listitem><para> |
897 |
-+ Upon successful completion of the ioctl, this member will contain the |
898 |
-+ <emphasis>128-bit UUID</emphasis> of the connected bus. |
899 |
-+ </para></listitem> |
900 |
-+ </varlistentry> |
901 |
-+ |
902 |
-+ <varlistentry> |
903 |
-+ <term><varname>items</varname></term> |
904 |
-+ <listitem> |
905 |
-+ <para> |
906 |
-+ Variable list of items containing optional additional information. |
907 |
-+ The following items are currently expected/valid: |
908 |
-+ </para> |
909 |
-+ <variablelist> |
910 |
-+ <varlistentry> |
911 |
-+ <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term> |
912 |
-+ <listitem> |
913 |
-+ <para> |
914 |
-+ Contains a string that describes this connection, so it can |
915 |
-+ be identified later. |
916 |
-+ </para> |
917 |
-+ </listitem> |
918 |
-+ </varlistentry> |
919 |
-+ |
920 |
-+ <varlistentry> |
921 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
922 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
923 |
-+ <listitem> |
924 |
-+ <para> |
925 |
-+ For activators and policy holders only, combinations of |
926 |
-+ these two items describe policy access entries. See |
927 |
-+ <citerefentry> |
928 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
929 |
-+ <manvolnum>7</manvolnum> |
930 |
-+ </citerefentry> |
931 |
-+ for further details. |
932 |
-+ </para> |
933 |
-+ </listitem> |
934 |
-+ </varlistentry> |
935 |
-+ |
936 |
-+ <varlistentry> |
937 |
-+ <term><constant>KDBUS_ITEM_CREDS</constant></term> |
938 |
-+ <term><constant>KDBUS_ITEM_PIDS</constant></term> |
939 |
-+ <term><constant>KDBUS_ITEM_SECLABEL</constant></term> |
940 |
-+ <listitem> |
941 |
-+ <para> |
942 |
-+ Privileged bus users may submit these types in order to |
943 |
-+ create connections with faked credentials. This information |
944 |
-+ will be returned when peer information is queried by |
945 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant>. See below for more |
946 |
-+ information on retrieving information on connections. |
947 |
-+ </para> |
948 |
-+ </listitem> |
949 |
-+ </varlistentry> |
950 |
-+ |
951 |
-+ <varlistentry> |
952 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
953 |
-+ <listitem><para> |
954 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
955 |
-+ kernel for known item types. See |
956 |
-+ <citerefentry> |
957 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
958 |
-+ <manvolnum>7</manvolnum> |
959 |
-+ </citerefentry> |
960 |
-+ for more details. |
961 |
-+ </para></listitem> |
962 |
-+ </varlistentry> |
963 |
-+ </variablelist> |
964 |
-+ |
965 |
-+ <para> |
966 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
967 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
968 |
-+ </para> |
969 |
-+ </listitem> |
970 |
-+ </varlistentry> |
971 |
-+ </variablelist> |
972 |
-+ |
973 |
-+ <para> |
974 |
-+ At the offset returned in the <varname>offset</varname> field of |
975 |
-+ <type>struct kdbus_cmd_hello</type>, the kernel will store items |
976 |
-+ of the following types: |
977 |
-+ </para> |
978 |
-+ |
979 |
-+ <variablelist> |
980 |
-+ <varlistentry> |
981 |
-+ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
982 |
-+ <listitem> |
983 |
-+ <para> |
984 |
-+ Bloom filter parameter as defined by the bus creator. |
985 |
-+ </para> |
986 |
-+ </listitem> |
987 |
-+ </varlistentry> |
988 |
-+ </variablelist> |
989 |
-+ |
990 |
-+ <para> |
991 |
-+ The offset in the pool has to be freed with the |
992 |
-+ <constant>KDBUS_CMD_FREE</constant> ioctl. See |
993 |
-+ <citerefentry> |
994 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
995 |
-+ <manvolnum>7</manvolnum> |
996 |
-+ </citerefentry> |
997 |
-+ for further information. |
998 |
-+ </para> |
999 |
-+ </refsect1> |
1000 |
-+ |
1001 |
-+ <refsect1> |
1002 |
-+ <title>Retrieving information on a connection</title> |
1003 |
-+ <para> |
1004 |
-+ The <constant>KDBUS_CMD_CONN_INFO</constant> ioctl can be used to |
1005 |
-+ retrieve credentials and properties of the initial creator of a |
1006 |
-+ connection. This ioctl uses the following struct. |
1007 |
-+ </para> |
1008 |
-+ |
1009 |
-+ <programlisting> |
1010 |
-+struct kdbus_cmd_info { |
1011 |
-+ __u64 size; |
1012 |
-+ __u64 flags; |
1013 |
-+ __u64 return_flags; |
1014 |
-+ __u64 id; |
1015 |
-+ __u64 attach_flags; |
1016 |
-+ __u64 offset; |
1017 |
-+ __u64 info_size; |
1018 |
-+ struct kdbus_item items[0]; |
1019 |
-+}; |
1020 |
-+ </programlisting> |
1021 |
-+ |
1022 |
-+ <variablelist> |
1023 |
-+ <varlistentry> |
1024 |
-+ <term><varname>size</varname></term> |
1025 |
-+ <listitem><para> |
1026 |
-+ The overall size of the struct, including its items. |
1027 |
-+ </para></listitem> |
1028 |
-+ </varlistentry> |
1029 |
-+ |
1030 |
-+ <varlistentry> |
1031 |
-+ <term><varname>flags</varname></term> |
1032 |
-+ <listitem><para> |
1033 |
-+ Currently, no flags are supported. |
1034 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1035 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1036 |
-+ and the <varname>flags</varname> field is set to |
1037 |
-+ <constant>0</constant>. |
1038 |
-+ </para></listitem> |
1039 |
-+ </varlistentry> |
1040 |
-+ |
1041 |
-+ <varlistentry> |
1042 |
-+ <term><varname>return_flags</varname></term> |
1043 |
-+ <listitem><para> |
1044 |
-+ Flags returned by the kernel. Currently unused and always set to |
1045 |
-+ <constant>0</constant> by the kernel. |
1046 |
-+ </para></listitem> |
1047 |
-+ </varlistentry> |
1048 |
-+ |
1049 |
-+ <varlistentry> |
1050 |
-+ <term><varname>id</varname></term> |
1051 |
-+ <listitem><para> |
1052 |
-+ The numerical ID of the connection for which information is to be |
1053 |
-+ retrieved. If set to a non-zero value, the |
1054 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant> item is ignored. |
1055 |
-+ </para></listitem> |
1056 |
-+ </varlistentry> |
1057 |
-+ |
1058 |
-+ <varlistentry> |
1059 |
-+ <term><varname>attach_flags</varname></term> |
1060 |
-+ <listitem><para> |
1061 |
-+ Specifies which metadata items should be attached to the answer. See |
1062 |
-+ <citerefentry> |
1063 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
1064 |
-+ <manvolnum>7</manvolnum> |
1065 |
-+ </citerefentry>. |
1066 |
-+ </para></listitem> |
1067 |
-+ </varlistentry> |
1068 |
-+ |
1069 |
-+ <varlistentry> |
1070 |
-+ <term><varname>offset</varname></term> |
1071 |
-+ <listitem><para> |
1072 |
-+ When the ioctl returns, this field will contain the offset of the |
1073 |
-+ connection information inside the caller's pool. See |
1074 |
-+ <citerefentry> |
1075 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1076 |
-+ <manvolnum>7</manvolnum> |
1077 |
-+ </citerefentry> |
1078 |
-+ for further information. |
1079 |
-+ </para></listitem> |
1080 |
-+ </varlistentry> |
1081 |
-+ |
1082 |
-+ <varlistentry> |
1083 |
-+ <term><varname>info_size</varname></term> |
1084 |
-+ <listitem><para> |
1085 |
-+ The kernel will return the size of the returned information, so |
1086 |
-+ applications can optionally |
1087 |
-+ <citerefentry> |
1088 |
-+ <refentrytitle>mmap</refentrytitle> |
1089 |
-+ <manvolnum>2</manvolnum> |
1090 |
-+ </citerefentry> |
1091 |
-+ specific parts of the pool. See |
1092 |
-+ <citerefentry> |
1093 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1094 |
-+ <manvolnum>7</manvolnum> |
1095 |
-+ </citerefentry> |
1096 |
-+ for further information. |
1097 |
-+ </para></listitem> |
1098 |
-+ </varlistentry> |
1099 |
-+ |
1100 |
-+ <varlistentry> |
1101 |
-+ <term><varname>items</varname></term> |
1102 |
-+ <listitem> |
1103 |
-+ <para> |
1104 |
-+ The following items are expected for |
1105 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant>. |
1106 |
-+ </para> |
1107 |
-+ <variablelist> |
1108 |
-+ <varlistentry> |
1109 |
-+ <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term> |
1110 |
-+ <listitem> |
1111 |
-+ <para> |
1112 |
-+ Contains the well-known name of the connection to look up as. |
1113 |
-+ This item is mandatory if the <varname>id</varname> field is |
1114 |
-+ set to 0. |
1115 |
-+ </para> |
1116 |
-+ </listitem> |
1117 |
-+ </varlistentry> |
1118 |
-+ |
1119 |
-+ <varlistentry> |
1120 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1121 |
-+ <listitem><para> |
1122 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1123 |
-+ kernel for known item types. See |
1124 |
-+ <citerefentry> |
1125 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1126 |
-+ <manvolnum>7</manvolnum> |
1127 |
-+ </citerefentry> |
1128 |
-+ for more details. |
1129 |
-+ </para></listitem> |
1130 |
-+ </varlistentry> |
1131 |
-+ </variablelist> |
1132 |
-+ <para> |
1133 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1134 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1135 |
-+ </para> |
1136 |
-+ </listitem> |
1137 |
-+ </varlistentry> |
1138 |
-+ </variablelist> |
1139 |
-+ |
1140 |
-+ <para> |
1141 |
-+ When the ioctl returns, the following struct will be stored in the |
1142 |
-+ caller's pool at <varname>offset</varname>. The fields in this struct |
1143 |
-+ are described below. |
1144 |
-+ </para> |
1145 |
-+ |
1146 |
-+ <programlisting> |
1147 |
-+struct kdbus_info { |
1148 |
-+ __u64 size; |
1149 |
-+ __u64 id; |
1150 |
-+ __u64 flags; |
1151 |
-+ struct kdbus_item items[0]; |
1152 |
-+}; |
1153 |
-+ </programlisting> |
1154 |
-+ |
1155 |
-+ <variablelist> |
1156 |
-+ <varlistentry> |
1157 |
-+ <term><varname>size</varname></term> |
1158 |
-+ <listitem><para> |
1159 |
-+ The overall size of the struct, including its items. |
1160 |
-+ </para></listitem> |
1161 |
-+ </varlistentry> |
1162 |
-+ |
1163 |
-+ <varlistentry> |
1164 |
-+ <term><varname>id</varname></term> |
1165 |
-+ <listitem><para> |
1166 |
-+ The connection's unique ID. |
1167 |
-+ </para></listitem> |
1168 |
-+ </varlistentry> |
1169 |
-+ |
1170 |
-+ <varlistentry> |
1171 |
-+ <term><varname>flags</varname></term> |
1172 |
-+ <listitem><para> |
1173 |
-+ The connection's flags as specified when it was created. |
1174 |
-+ </para></listitem> |
1175 |
-+ </varlistentry> |
1176 |
-+ |
1177 |
-+ <varlistentry> |
1178 |
-+ <term><varname>items</varname></term> |
1179 |
-+ <listitem> |
1180 |
-+ <para> |
1181 |
-+ Depending on the <varname>flags</varname> field in |
1182 |
-+ <type>struct kdbus_cmd_info</type>, items of types |
1183 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant> and |
1184 |
-+ <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant> may follow here. |
1185 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> is also allowed. |
1186 |
-+ </para> |
1187 |
-+ </listitem> |
1188 |
-+ </varlistentry> |
1189 |
-+ </variablelist> |
1190 |
-+ |
1191 |
-+ <para> |
1192 |
-+ Once the caller is finished with parsing the return buffer, it needs to |
1193 |
-+ employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in |
1194 |
-+ order to free the buffer part. See |
1195 |
-+ <citerefentry> |
1196 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1197 |
-+ <manvolnum>7</manvolnum> |
1198 |
-+ </citerefentry> |
1199 |
-+ for further information. |
1200 |
-+ </para> |
1201 |
-+ </refsect1> |
1202 |
-+ |
1203 |
-+ <refsect1> |
1204 |
-+ <title>Getting information about a connection's bus creator</title> |
1205 |
-+ <para> |
1206 |
-+ The <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> ioctl takes the same |
1207 |
-+ struct as <constant>KDBUS_CMD_CONN_INFO</constant>, but is used to |
1208 |
-+ retrieve information about the creator of the bus the connection is |
1209 |
-+ attached to. The metadata returned by this call is collected during the |
1210 |
-+ creation of the bus and is never altered afterwards, so it provides |
1211 |
-+ pristine information on the task that created the bus, at the moment when |
1212 |
-+ it did so. |
1213 |
-+ </para> |
1214 |
-+ <para> |
1215 |
-+ In response to this call, a slice in the connection's pool is allocated |
1216 |
-+ and filled with an object of type <type>struct kdbus_info</type>, |
1217 |
-+ pointed to by the ioctl's <varname>offset</varname> field. |
1218 |
-+ </para> |
1219 |
-+ |
1220 |
-+ <programlisting> |
1221 |
-+struct kdbus_info { |
1222 |
-+ __u64 size; |
1223 |
-+ __u64 id; |
1224 |
-+ __u64 flags; |
1225 |
-+ struct kdbus_item items[0]; |
1226 |
-+}; |
1227 |
-+ </programlisting> |
1228 |
-+ |
1229 |
-+ <variablelist> |
1230 |
-+ <varlistentry> |
1231 |
-+ <term><varname>size</varname></term> |
1232 |
-+ <listitem><para> |
1233 |
-+ The overall size of the struct, including its items. |
1234 |
-+ </para></listitem> |
1235 |
-+ </varlistentry> |
1236 |
-+ |
1237 |
-+ <varlistentry> |
1238 |
-+ <term><varname>id</varname></term> |
1239 |
-+ <listitem><para> |
1240 |
-+ The bus ID. |
1241 |
-+ </para></listitem> |
1242 |
-+ </varlistentry> |
1243 |
-+ |
1244 |
-+ <varlistentry> |
1245 |
-+ <term><varname>flags</varname></term> |
1246 |
-+ <listitem><para> |
1247 |
-+ The bus flags as specified when it was created. |
1248 |
-+ </para></listitem> |
1249 |
-+ </varlistentry> |
1250 |
-+ |
1251 |
-+ <varlistentry> |
1252 |
-+ <term><varname>items</varname></term> |
1253 |
-+ <listitem> |
1254 |
-+ <para> |
1255 |
-+ Metadata information is stored in items here. The item list |
1256 |
-+ contains a <constant>KDBUS_ITEM_MAKE_NAME</constant> item that |
1257 |
-+ indicates the bus name of the calling connection. |
1258 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed to probe |
1259 |
-+ for known item types. |
1260 |
-+ </para> |
1261 |
-+ </listitem> |
1262 |
-+ </varlistentry> |
1263 |
-+ </variablelist> |
1264 |
-+ |
1265 |
-+ <para> |
1266 |
-+ Once the caller is finished with parsing the return buffer, it needs to |
1267 |
-+ employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in |
1268 |
-+ order to free the buffer part. See |
1269 |
-+ <citerefentry> |
1270 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1271 |
-+ <manvolnum>7</manvolnum> |
1272 |
-+ </citerefentry> |
1273 |
-+ for further information. |
1274 |
-+ </para> |
1275 |
-+ </refsect1> |
1276 |
-+ |
1277 |
-+ <refsect1> |
1278 |
-+ <title>Updating connection details</title> |
1279 |
-+ <para> |
1280 |
-+ Some of a connection's details can be updated with the |
1281 |
-+ <constant>KDBUS_CMD_CONN_UPDATE</constant> ioctl, using the file |
1282 |
-+ descriptor that was used to create the connection. The update command |
1283 |
-+ uses the following struct. |
1284 |
-+ </para> |
1285 |
-+ |
1286 |
-+ <programlisting> |
1287 |
-+struct kdbus_cmd { |
1288 |
-+ __u64 size; |
1289 |
-+ __u64 flags; |
1290 |
-+ __u64 return_flags; |
1291 |
-+ struct kdbus_item items[0]; |
1292 |
-+}; |
1293 |
-+ </programlisting> |
1294 |
-+ |
1295 |
-+ <variablelist> |
1296 |
-+ <varlistentry> |
1297 |
-+ <term><varname>size</varname></term> |
1298 |
-+ <listitem><para> |
1299 |
-+ The overall size of the struct, including its items. |
1300 |
-+ </para></listitem> |
1301 |
-+ </varlistentry> |
1302 |
-+ |
1303 |
-+ <varlistentry> |
1304 |
-+ <term><varname>flags</varname></term> |
1305 |
-+ <listitem><para> |
1306 |
-+ Currently, no flags are supported. |
1307 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1308 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1309 |
-+ and the <varname>flags</varname> field is set to |
1310 |
-+ <constant>0</constant>. |
1311 |
-+ </para></listitem> |
1312 |
-+ </varlistentry> |
1313 |
-+ |
1314 |
-+ <varlistentry> |
1315 |
-+ <term><varname>return_flags</varname></term> |
1316 |
-+ <listitem><para> |
1317 |
-+ Flags returned by the kernel. Currently unused and always set to |
1318 |
-+ <constant>0</constant> by the kernel. |
1319 |
-+ </para></listitem> |
1320 |
-+ </varlistentry> |
1321 |
-+ |
1322 |
-+ <varlistentry> |
1323 |
-+ <term><varname>items</varname></term> |
1324 |
-+ <listitem> |
1325 |
-+ <para> |
1326 |
-+ Items to describe the connection details to be updated. The |
1327 |
-+ following item types are supported. |
1328 |
-+ </para> |
1329 |
-+ <variablelist> |
1330 |
-+ <varlistentry> |
1331 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
1332 |
-+ <listitem> |
1333 |
-+ <para> |
1334 |
-+ Supply a new set of metadata items that this connection |
1335 |
-+ permits to be sent along with messages. |
1336 |
-+ </para> |
1337 |
-+ </listitem> |
1338 |
-+ </varlistentry> |
1339 |
-+ |
1340 |
-+ <varlistentry> |
1341 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
1342 |
-+ <listitem> |
1343 |
-+ <para> |
1344 |
-+ Supply a new set of metadata items that this connection |
1345 |
-+ requests to be attached to each message. |
1346 |
-+ </para> |
1347 |
-+ </listitem> |
1348 |
-+ </varlistentry> |
1349 |
-+ |
1350 |
-+ <varlistentry> |
1351 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1352 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1353 |
-+ <listitem> |
1354 |
-+ <para> |
1355 |
-+ Policy holder connections may supply a new set of policy |
1356 |
-+ information with these items. For other connection types, |
1357 |
-+ <constant>EOPNOTSUPP</constant> is returned in |
1358 |
-+ <varname>errno</varname>. |
1359 |
-+ </para> |
1360 |
-+ </listitem> |
1361 |
-+ </varlistentry> |
1362 |
-+ |
1363 |
-+ <varlistentry> |
1364 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1365 |
-+ <listitem><para> |
1366 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1367 |
-+ kernel for known item types. See |
1368 |
-+ <citerefentry> |
1369 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1370 |
-+ <manvolnum>7</manvolnum> |
1371 |
-+ </citerefentry> |
1372 |
-+ for more details. |
1373 |
-+ </para></listitem> |
1374 |
-+ </varlistentry> |
1375 |
-+ </variablelist> |
1376 |
-+ |
1377 |
-+ <para> |
1378 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1379 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1380 |
-+ </para> |
1381 |
-+ </listitem> |
1382 |
-+ </varlistentry> |
1383 |
-+ </variablelist> |
1384 |
-+ </refsect1> |
1385 |
-+ |
1386 |
-+ <refsect1> |
1387 |
-+ <title>Termination of connections</title> |
1388 |
-+ <para> |
1389 |
-+ A connection can be terminated by simply calling |
1390 |
-+ <citerefentry> |
1391 |
-+ <refentrytitle>close</refentrytitle> |
1392 |
-+ <manvolnum>2</manvolnum> |
1393 |
-+ </citerefentry> |
1394 |
-+ on its file descriptor. All pending incoming messages will be discarded, |
1395 |
-+ and the memory allocated by the pool will be freed. |
1396 |
-+ </para> |
1397 |
-+ |
1398 |
-+ <para> |
1399 |
-+ An alternative way of closing down a connection is via the |
1400 |
-+ <constant>KDBUS_CMD_BYEBYE</constant> ioctl. This ioctl will succeed only |
1401 |
-+ if the message queue of the connection is empty at the time of closing; |
1402 |
-+ otherwise, the ioctl will fail with <varname>errno</varname> set to |
1403 |
-+ <constant>EBUSY</constant>. When this ioctl returns |
1404 |
-+ successfully, the connection has been terminated and won't accept any new |
1405 |
-+ messages from remote peers. This way, a connection can be terminated |
1406 |
-+ race-free, without losing any messages. The ioctl takes an argument of |
1407 |
-+ type <type>struct kdbus_cmd</type>. |
1408 |
-+ </para> |
1409 |
-+ |
1410 |
-+ <programlisting> |
1411 |
-+struct kdbus_cmd { |
1412 |
-+ __u64 size; |
1413 |
-+ __u64 flags; |
1414 |
-+ __u64 return_flags; |
1415 |
-+ struct kdbus_item items[0]; |
1416 |
-+}; |
1417 |
-+ </programlisting> |
1418 |
-+ |
1419 |
-+ <variablelist> |
1420 |
-+ <varlistentry> |
1421 |
-+ <term><varname>size</varname></term> |
1422 |
-+ <listitem><para> |
1423 |
-+ The overall size of the struct, including its items. |
1424 |
-+ </para></listitem> |
1425 |
-+ </varlistentry> |
1426 |
-+ |
1427 |
-+ <varlistentry> |
1428 |
-+ <term><varname>flags</varname></term> |
1429 |
-+ <listitem><para> |
1430 |
-+ Currently, no flags are supported. |
1431 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1432 |
-+ valid flags. If set, the ioctl will fail with |
1433 |
-+ <varname>errno</varname> set to <constant>EPROTO</constant>, and |
1434 |
-+ the <varname>flags</varname> field is set to <constant>0</constant>. |
1435 |
-+ </para></listitem> |
1436 |
-+ </varlistentry> |
1437 |
-+ |
1438 |
-+ <varlistentry> |
1439 |
-+ <term><varname>return_flags</varname></term> |
1440 |
-+ <listitem><para> |
1441 |
-+ Flags returned by the kernel. Currently unused and always set to |
1442 |
-+ <constant>0</constant> by the kernel. |
1443 |
-+ </para></listitem> |
1444 |
-+ </varlistentry> |
1445 |
-+ |
1446 |
-+ <varlistentry> |
1447 |
-+ <term><varname>items</varname></term> |
1448 |
-+ <listitem> |
1449 |
-+ <para> |
1450 |
-+ The following item types are supported. |
1451 |
-+ </para> |
1452 |
-+ <variablelist> |
1453 |
-+ <varlistentry> |
1454 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1455 |
-+ <listitem><para> |
1456 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1457 |
-+ kernel for known item types. See |
1458 |
-+ <citerefentry> |
1459 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1460 |
-+ <manvolnum>7</manvolnum> |
1461 |
-+ </citerefentry> |
1462 |
-+ for more details. |
1463 |
-+ </para></listitem> |
1464 |
-+ </varlistentry> |
1465 |
-+ </variablelist> |
1466 |
-+ |
1467 |
-+ <para> |
1468 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1469 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
1470 |
-+ </para> |
1471 |
-+ </listitem> |
1472 |
-+ </varlistentry> |
1473 |
-+ </variablelist> |
1474 |
-+ </refsect1> |
1475 |
-+ |
1476 |
-+ <refsect1> |
1477 |
-+ <title>Return value</title> |
1478 |
-+ <para> |
1479 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
1480 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
1481 |
-+ <varname>errno</varname> is set to indicate the error. |
1482 |
-+ If the issued ioctl is illegal for the file descriptor used, |
1483 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
1484 |
-+ </para> |
1485 |
-+ |
1486 |
-+ <refsect2> |
1487 |
-+ <title> |
1488 |
-+ <constant>KDBUS_CMD_HELLO</constant> may fail with the following |
1489 |
-+ errors |
1490 |
-+ </title> |
1491 |
-+ |
1492 |
-+ <variablelist> |
1493 |
-+ <varlistentry> |
1494 |
-+ <term><constant>EFAULT</constant></term> |
1495 |
-+ <listitem><para> |
1496 |
-+ The supplied pool size was 0 or not a multiple of the page size. |
1497 |
-+ </para></listitem> |
1498 |
-+ </varlistentry> |
1499 |
-+ |
1500 |
-+ <varlistentry> |
1501 |
-+ <term><constant>EINVAL</constant></term> |
1502 |
-+ <listitem><para> |
1503 |
-+ The flags supplied in <type>struct kdbus_cmd_hello</type> |
1504 |
-+ are invalid. |
1505 |
-+ </para></listitem> |
1506 |
-+ </varlistentry> |
1507 |
-+ |
1508 |
-+ <varlistentry> |
1509 |
-+ <term><constant>EINVAL</constant></term> |
1510 |
-+ <listitem><para> |
1511 |
-+ An illegal combination of |
1512 |
-+ <constant>KDBUS_HELLO_MONITOR</constant>, |
1513 |
-+ <constant>KDBUS_HELLO_ACTIVATOR</constant> and |
1514 |
-+ <constant>KDBUS_HELLO_POLICY_HOLDER</constant> was passed in |
1515 |
-+ <varname>flags</varname>. |
1516 |
-+ </para></listitem> |
1517 |
-+ </varlistentry> |
1518 |
-+ |
1519 |
-+ <varlistentry> |
1520 |
-+ <term><constant>EINVAL</constant></term> |
1521 |
-+ <listitem><para> |
1522 |
-+ An invalid set of items was supplied. |
1523 |
-+ </para></listitem> |
1524 |
-+ </varlistentry> |
1525 |
-+ |
1526 |
-+ <varlistentry> |
1527 |
-+ <term><constant>ECONNREFUSED</constant></term> |
1528 |
-+ <listitem><para> |
1529 |
-+ The attach_flags_send field did not satisfy the requirements of |
1530 |
-+ the bus. |
1531 |
-+ </para></listitem> |
1532 |
-+ </varlistentry> |
1533 |
-+ |
1534 |
-+ <varlistentry> |
1535 |
-+ <term><constant>EPERM</constant></term> |
1536 |
-+ <listitem><para> |
1537 |
-+ A <constant>KDBUS_ITEM_CREDS</constant> items was supplied, but the |
1538 |
-+ current user is not privileged. |
1539 |
-+ </para></listitem> |
1540 |
-+ </varlistentry> |
1541 |
-+ |
1542 |
-+ <varlistentry> |
1543 |
-+ <term><constant>ESHUTDOWN</constant></term> |
1544 |
-+ <listitem><para> |
1545 |
-+ The bus you were trying to connect to has already been shut down. |
1546 |
-+ </para></listitem> |
1547 |
-+ </varlistentry> |
1548 |
-+ |
1549 |
-+ <varlistentry> |
1550 |
-+ <term><constant>EMFILE</constant></term> |
1551 |
-+ <listitem><para> |
1552 |
-+ The maximum number of connections on the bus has been reached. |
1553 |
-+ </para></listitem> |
1554 |
-+ </varlistentry> |
1555 |
-+ |
1556 |
-+ <varlistentry> |
1557 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
1558 |
-+ <listitem><para> |
1559 |
-+ The endpoint does not support the connection flags supplied in |
1560 |
-+ <type>struct kdbus_cmd_hello</type>. |
1561 |
-+ </para></listitem> |
1562 |
-+ </varlistentry> |
1563 |
-+ </variablelist> |
1564 |
-+ </refsect2> |
1565 |
-+ |
1566 |
-+ <refsect2> |
1567 |
-+ <title> |
1568 |
-+ <constant>KDBUS_CMD_BYEBYE</constant> may fail with the following |
1569 |
-+ errors |
1570 |
-+ </title> |
1571 |
-+ |
1572 |
-+ <variablelist> |
1573 |
-+ <varlistentry> |
1574 |
-+ <term><constant>EALREADY</constant></term> |
1575 |
-+ <listitem><para> |
1576 |
-+ The connection has already been shut down. |
1577 |
-+ </para></listitem> |
1578 |
-+ </varlistentry> |
1579 |
-+ |
1580 |
-+ <varlistentry> |
1581 |
-+ <term><constant>EBUSY</constant></term> |
1582 |
-+ <listitem><para> |
1583 |
-+ There are still messages queued up in the connection's pool. |
1584 |
-+ </para></listitem> |
1585 |
-+ </varlistentry> |
1586 |
-+ </variablelist> |
1587 |
-+ </refsect2> |
1588 |
-+ |
1589 |
-+ <refsect2> |
1590 |
-+ <title> |
1591 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant> may fail with the following |
1592 |
-+ errors |
1593 |
-+ </title> |
1594 |
-+ |
1595 |
-+ <variablelist> |
1596 |
-+ <varlistentry> |
1597 |
-+ <term><constant>EINVAL</constant></term> |
1598 |
-+ <listitem><para> |
1599 |
-+ Invalid flags, or neither an ID nor a name was provided, or the |
1600 |
-+ name is invalid. |
1601 |
-+ </para></listitem> |
1602 |
-+ </varlistentry> |
1603 |
-+ |
1604 |
-+ <varlistentry> |
1605 |
-+ <term><constant>ESRCH</constant></term> |
1606 |
-+ <listitem><para> |
1607 |
-+ Connection lookup by name failed. |
1608 |
-+ </para></listitem> |
1609 |
-+ </varlistentry> |
1610 |
-+ |
1611 |
-+ <varlistentry> |
1612 |
-+ <term><constant>ENXIO</constant></term> |
1613 |
-+ <listitem><para> |
1614 |
-+ No connection with the provided connection ID found. |
1615 |
-+ </para></listitem> |
1616 |
-+ </varlistentry> |
1617 |
-+ </variablelist> |
1618 |
-+ </refsect2> |
1619 |
-+ |
1620 |
-+ <refsect2> |
1621 |
-+ <title> |
1622 |
-+ <constant>KDBUS_CMD_CONN_UPDATE</constant> may fail with the following |
1623 |
-+ errors |
1624 |
-+ </title> |
1625 |
-+ |
1626 |
-+ <variablelist> |
1627 |
-+ <varlistentry> |
1628 |
-+ <term><constant>EINVAL</constant></term> |
1629 |
-+ <listitem><para> |
1630 |
-+ Illegal flags or items. |
1631 |
-+ </para></listitem> |
1632 |
-+ </varlistentry> |
1633 |
-+ |
1634 |
-+ <varlistentry> |
1635 |
-+ <term><constant>EINVAL</constant></term> |
1636 |
-+ <listitem><para> |
1637 |
-+ Wildcards submitted in policy entries, or illegal sequence |
1638 |
-+ of policy items. |
1639 |
-+ </para></listitem> |
1640 |
-+ </varlistentry> |
1641 |
-+ |
1642 |
-+ <varlistentry> |
1643 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
1644 |
-+ <listitem><para> |
1645 |
-+ Operation not supported by connection. |
1646 |
-+ </para></listitem> |
1647 |
-+ </varlistentry> |
1648 |
-+ |
1649 |
-+ <varlistentry> |
1650 |
-+ <term><constant>E2BIG</constant></term> |
1651 |
-+ <listitem><para> |
1652 |
-+ Too many policy items attached. |
1653 |
-+ </para></listitem> |
1654 |
-+ </varlistentry> |
1655 |
-+ </variablelist> |
1656 |
-+ </refsect2> |
1657 |
-+ </refsect1> |
1658 |
-+ |
1659 |
-+ <refsect1> |
1660 |
-+ <title>See Also</title> |
1661 |
-+ <simplelist type="inline"> |
1662 |
-+ <member> |
1663 |
-+ <citerefentry> |
1664 |
-+ <refentrytitle>kdbus</refentrytitle> |
1665 |
-+ <manvolnum>7</manvolnum> |
1666 |
-+ </citerefentry> |
1667 |
-+ </member> |
1668 |
-+ <member> |
1669 |
-+ <citerefentry> |
1670 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
1671 |
-+ <manvolnum>7</manvolnum> |
1672 |
-+ </citerefentry> |
1673 |
-+ </member> |
1674 |
-+ <member> |
1675 |
-+ <citerefentry> |
1676 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
1677 |
-+ <manvolnum>7</manvolnum> |
1678 |
-+ </citerefentry> |
1679 |
-+ </member> |
1680 |
-+ <member> |
1681 |
-+ <citerefentry> |
1682 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
1683 |
-+ <manvolnum>7</manvolnum> |
1684 |
-+ </citerefentry> |
1685 |
-+ </member> |
1686 |
-+ <member> |
1687 |
-+ <citerefentry> |
1688 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
1689 |
-+ <manvolnum>7</manvolnum> |
1690 |
-+ </citerefentry> |
1691 |
-+ </member> |
1692 |
-+ <member> |
1693 |
-+ <citerefentry> |
1694 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1695 |
-+ <manvolnum>7</manvolnum> |
1696 |
-+ </citerefentry> |
1697 |
-+ </member> |
1698 |
-+ <member> |
1699 |
-+ <citerefentry> |
1700 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
1701 |
-+ <manvolnum>7</manvolnum> |
1702 |
-+ </citerefentry> |
1703 |
-+ </member> |
1704 |
-+ <member> |
1705 |
-+ <citerefentry> |
1706 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1707 |
-+ <manvolnum>7</manvolnum> |
1708 |
-+ </citerefentry> |
1709 |
-+ </member> |
1710 |
-+ </simplelist> |
1711 |
-+ </refsect1> |
1712 |
-+</refentry> |
1713 |
-diff --git a/Documentation/kdbus/kdbus.endpoint.xml b/Documentation/kdbus/kdbus.endpoint.xml |
1714 |
-new file mode 100644 |
1715 |
-index 0000000..6632485 |
1716 |
---- /dev/null |
1717 |
-+++ b/Documentation/kdbus/kdbus.endpoint.xml |
1718 |
-@@ -0,0 +1,429 @@ |
1719 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
1720 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
1721 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
1722 |
-+ |
1723 |
-+<refentry id="kdbus.endpoint"> |
1724 |
-+ |
1725 |
-+ <refentryinfo> |
1726 |
-+ <title>kdbus.endpoint</title> |
1727 |
-+ <productname>kdbus.endpoint</productname> |
1728 |
-+ </refentryinfo> |
1729 |
-+ |
1730 |
-+ <refmeta> |
1731 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
1732 |
-+ <manvolnum>7</manvolnum> |
1733 |
-+ </refmeta> |
1734 |
-+ |
1735 |
-+ <refnamediv> |
1736 |
-+ <refname>kdbus.endpoint</refname> |
1737 |
-+ <refpurpose>kdbus endpoint</refpurpose> |
1738 |
-+ </refnamediv> |
1739 |
-+ |
1740 |
-+ <refsect1> |
1741 |
-+ <title>Description</title> |
1742 |
-+ |
1743 |
-+ <para> |
1744 |
-+ Endpoints are entry points to a bus (see |
1745 |
-+ <citerefentry> |
1746 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
1747 |
-+ <manvolnum>7</manvolnum> |
1748 |
-+ </citerefentry>). |
1749 |
-+ By default, each bus has a default |
1750 |
-+ endpoint called 'bus'. The bus owner has the ability to create custom |
1751 |
-+ endpoints with specific names, permissions, and policy databases |
1752 |
-+ (see below). An endpoint is presented as file underneath the directory |
1753 |
-+ of the parent bus. |
1754 |
-+ </para> |
1755 |
-+ <para> |
1756 |
-+ To create a custom endpoint, open the default endpoint |
1757 |
-+ (<literal>bus</literal>) and use the |
1758 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> ioctl with |
1759 |
-+ <type>struct kdbus_cmd</type>. Custom endpoints always have a policy |
1760 |
-+ database that, by default, forbids any operation. You have to explicitly |
1761 |
-+ install policy entries to allow any operation on this endpoint. |
1762 |
-+ </para> |
1763 |
-+ <para> |
1764 |
-+ Once <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> succeeded, the new |
1765 |
-+ endpoint will appear in the filesystem |
1766 |
-+ (<citerefentry> |
1767 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
1768 |
-+ <manvolnum>7</manvolnum> |
1769 |
-+ </citerefentry>), and the used file descriptor will manage the |
1770 |
-+ newly created endpoint resource. It cannot be used to manage further |
1771 |
-+ resources and must be kept open as long as the endpoint is needed. The |
1772 |
-+ endpoint will be terminated as soon as the file descriptor is closed. |
1773 |
-+ </para> |
1774 |
-+ <para> |
1775 |
-+ Endpoint names may be chosen freely except for one restriction: the name |
1776 |
-+ must be prefixed with the numeric effective UID of the creator and a dash. |
1777 |
-+ This is required to avoid namespace clashes between different users. When |
1778 |
-+ creating an endpoint, the name that is passed in must be properly |
1779 |
-+ formatted or the kernel will refuse creation of the endpoint. Example: |
1780 |
-+ <literal>1047-my-endpoint</literal> is an acceptable name for an |
1781 |
-+ endpoint registered by a user with UID 1047. However, |
1782 |
-+ <literal>1024-my-endpoint</literal> is not, and neither is |
1783 |
-+ <literal>my-endpoint</literal>. The UID must be provided in the |
1784 |
-+ user-namespace of the bus. |
1785 |
-+ </para> |
1786 |
-+ <para> |
1787 |
-+ To create connections to a bus, use <constant>KDBUS_CMD_HELLO</constant> |
1788 |
-+ on a file descriptor returned by <function>open()</function> on an |
1789 |
-+ endpoint node. See |
1790 |
-+ <citerefentry> |
1791 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
1792 |
-+ <manvolnum>7</manvolnum> |
1793 |
-+ </citerefentry> |
1794 |
-+ for further details. |
1795 |
-+ </para> |
1796 |
-+ </refsect1> |
1797 |
-+ |
1798 |
-+ <refsect1> |
1799 |
-+ <title>Creating custom endpoints</title> |
1800 |
-+ <para> |
1801 |
-+ To create a new endpoint, the |
1802 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> command is used. Along with |
1803 |
-+ the endpoint's name, which will be used to expose the endpoint in the |
1804 |
-+ <citerefentry> |
1805 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
1806 |
-+ <manvolnum>7</manvolnum> |
1807 |
-+ </citerefentry>, |
1808 |
-+ the command also optionally takes items to set up the endpoint's |
1809 |
-+ <citerefentry> |
1810 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1811 |
-+ <manvolnum>7</manvolnum> |
1812 |
-+ </citerefentry>. |
1813 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> takes a |
1814 |
-+ <type>struct kdbus_cmd</type> argument. |
1815 |
-+ </para> |
1816 |
-+ <programlisting> |
1817 |
-+struct kdbus_cmd { |
1818 |
-+ __u64 size; |
1819 |
-+ __u64 flags; |
1820 |
-+ __u64 return_flags; |
1821 |
-+ struct kdbus_item items[0]; |
1822 |
-+}; |
1823 |
-+ </programlisting> |
1824 |
-+ |
1825 |
-+ <para>The fields in this struct are described below.</para> |
1826 |
-+ |
1827 |
-+ <variablelist> |
1828 |
-+ <varlistentry> |
1829 |
-+ <term><varname>size</varname></term> |
1830 |
-+ <listitem><para> |
1831 |
-+ The overall size of the struct, including its items. |
1832 |
-+ </para></listitem> |
1833 |
-+ </varlistentry> |
1834 |
-+ |
1835 |
-+ <varlistentry> |
1836 |
-+ <term><varname>flags</varname></term> |
1837 |
-+ <listitem><para>The flags for creation.</para> |
1838 |
-+ <variablelist> |
1839 |
-+ <varlistentry> |
1840 |
-+ <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term> |
1841 |
-+ <listitem> |
1842 |
-+ <para>Make the endpoint file group-accessible.</para> |
1843 |
-+ </listitem> |
1844 |
-+ </varlistentry> |
1845 |
-+ |
1846 |
-+ <varlistentry> |
1847 |
-+ <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term> |
1848 |
-+ <listitem> |
1849 |
-+ <para>Make the endpoint file world-accessible.</para> |
1850 |
-+ </listitem> |
1851 |
-+ </varlistentry> |
1852 |
-+ |
1853 |
-+ <varlistentry> |
1854 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
1855 |
-+ <listitem> |
1856 |
-+ <para> |
1857 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
1858 |
-+ set, no action is taken; the ioctl will return |
1859 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
1860 |
-+ field will have all bits set that are valid for this command. |
1861 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
1862 |
-+ cleared by the operation. |
1863 |
-+ </para> |
1864 |
-+ </listitem> |
1865 |
-+ </varlistentry> |
1866 |
-+ </variablelist> |
1867 |
-+ </listitem> |
1868 |
-+ </varlistentry> |
1869 |
-+ |
1870 |
-+ <varlistentry> |
1871 |
-+ <term><varname>return_flags</varname></term> |
1872 |
-+ <listitem><para> |
1873 |
-+ Flags returned by the kernel. Currently unused and always set to |
1874 |
-+ <constant>0</constant> by the kernel. |
1875 |
-+ </para></listitem> |
1876 |
-+ </varlistentry> |
1877 |
-+ |
1878 |
-+ <varlistentry> |
1879 |
-+ <term><varname>items</varname></term> |
1880 |
-+ <listitem> |
1881 |
-+ <para> |
1882 |
-+ The following items are expected for |
1883 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. |
1884 |
-+ </para> |
1885 |
-+ <variablelist> |
1886 |
-+ <varlistentry> |
1887 |
-+ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
1888 |
-+ <listitem> |
1889 |
-+ <para>Contains a string to identify the endpoint name.</para> |
1890 |
-+ </listitem> |
1891 |
-+ </varlistentry> |
1892 |
-+ |
1893 |
-+ <varlistentry> |
1894 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1895 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1896 |
-+ <listitem> |
1897 |
-+ <para> |
1898 |
-+ These items are used to set the policy attached to the |
1899 |
-+ endpoint. For more details on bus and endpoint policies, see |
1900 |
-+ <citerefentry> |
1901 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1902 |
-+ <manvolnum>7</manvolnum> |
1903 |
-+ </citerefentry>. |
1904 |
-+ </para> |
1905 |
-+ </listitem> |
1906 |
-+ </varlistentry> |
1907 |
-+ </variablelist> |
1908 |
-+ <para> |
1909 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
1910 |
-+ <varname>errno</varname> set to <varname>EINVAL</varname>. |
1911 |
-+ </para> |
1912 |
-+ </listitem> |
1913 |
-+ </varlistentry> |
1914 |
-+ </variablelist> |
1915 |
-+ </refsect1> |
1916 |
-+ |
1917 |
-+ <refsect1> |
1918 |
-+ <title>Updating endpoints</title> |
1919 |
-+ <para> |
1920 |
-+ To update an existing endpoint, the |
1921 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> command is used on the file |
1922 |
-+ descriptor that was used to create the endpoint, using |
1923 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. The only relevant detail of |
1924 |
-+ the endpoint that can be updated is the policy. When the command is |
1925 |
-+ employed, the policy of the endpoint is <emphasis>replaced</emphasis> |
1926 |
-+ atomically with the new set of rules. |
1927 |
-+ The command takes a <type>struct kdbus_cmd</type> argument. |
1928 |
-+ </para> |
1929 |
-+ <programlisting> |
1930 |
-+struct kdbus_cmd { |
1931 |
-+ __u64 size; |
1932 |
-+ __u64 flags; |
1933 |
-+ __u64 return_flags; |
1934 |
-+ struct kdbus_item items[0]; |
1935 |
-+}; |
1936 |
-+ </programlisting> |
1937 |
-+ |
1938 |
-+ <para>The fields in this struct are described below.</para> |
1939 |
-+ |
1940 |
-+ <variablelist> |
1941 |
-+ <varlistentry> |
1942 |
-+ <term><varname>size</varname></term> |
1943 |
-+ <listitem><para> |
1944 |
-+ The overall size of the struct, including its items. |
1945 |
-+ </para></listitem> |
1946 |
-+ </varlistentry> |
1947 |
-+ |
1948 |
-+ <varlistentry> |
1949 |
-+ <term><varname>flags</varname></term> |
1950 |
-+ <listitem><para> |
1951 |
-+ Unused for this command. |
1952 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
1953 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
1954 |
-+ and the <varname>flags</varname> field is set to |
1955 |
-+ <constant>0</constant>. |
1956 |
-+ </para></listitem> |
1957 |
-+ </varlistentry> |
1958 |
-+ |
1959 |
-+ <varlistentry> |
1960 |
-+ <term><varname>return_flags</varname></term> |
1961 |
-+ <listitem><para> |
1962 |
-+ Flags returned by the kernel. Currently unused and always set to |
1963 |
-+ <constant>0</constant> by the kernel. |
1964 |
-+ </para></listitem> |
1965 |
-+ </varlistentry> |
1966 |
-+ |
1967 |
-+ <varlistentry> |
1968 |
-+ <term><varname>items</varname></term> |
1969 |
-+ <listitem> |
1970 |
-+ <para> |
1971 |
-+ The following items are expected for |
1972 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant>. |
1973 |
-+ </para> |
1974 |
-+ <variablelist> |
1975 |
-+ <varlistentry> |
1976 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
1977 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
1978 |
-+ <listitem> |
1979 |
-+ <para> |
1980 |
-+ These items are used to set the policy attached to the |
1981 |
-+ endpoint. For more details on bus and endpoint policies, see |
1982 |
-+ <citerefentry> |
1983 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
1984 |
-+ <manvolnum>7</manvolnum> |
1985 |
-+ </citerefentry>. |
1986 |
-+ Existing policy is atomically replaced with the new rules |
1987 |
-+ provided. |
1988 |
-+ </para> |
1989 |
-+ </listitem> |
1990 |
-+ </varlistentry> |
1991 |
-+ |
1992 |
-+ <varlistentry> |
1993 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
1994 |
-+ <listitem><para> |
1995 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
1996 |
-+ kernel for known item types. See |
1997 |
-+ <citerefentry> |
1998 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
1999 |
-+ <manvolnum>7</manvolnum> |
2000 |
-+ </citerefentry> |
2001 |
-+ for more details. |
2002 |
-+ </para></listitem> |
2003 |
-+ </varlistentry> |
2004 |
-+ </variablelist> |
2005 |
-+ <para> |
2006 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
2007 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
2008 |
-+ </para> |
2009 |
-+ </listitem> |
2010 |
-+ </varlistentry> |
2011 |
-+ </variablelist> |
2012 |
-+ </refsect1> |
2013 |
-+ |
2014 |
-+ <refsect1> |
2015 |
-+ <title>Return value</title> |
2016 |
-+ <para> |
2017 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
2018 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
2019 |
-+ <varname>errno</varname> is set to indicate the error. |
2020 |
-+ If the issued ioctl is illegal for the file descriptor used, |
2021 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
2022 |
-+ </para> |
2023 |
-+ |
2024 |
-+ <refsect2> |
2025 |
-+ <title> |
2026 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> may fail with the |
2027 |
-+ following errors |
2028 |
-+ </title> |
2029 |
-+ |
2030 |
-+ <variablelist> |
2031 |
-+ <varlistentry> |
2032 |
-+ <term><constant>EINVAL</constant></term> |
2033 |
-+ <listitem><para> |
2034 |
-+ The flags supplied in the <type>struct kdbus_cmd</type> |
2035 |
-+ are invalid. |
2036 |
-+ </para></listitem> |
2037 |
-+ </varlistentry> |
2038 |
-+ |
2039 |
-+ <varlistentry> |
2040 |
-+ <term><constant>EINVAL</constant></term> |
2041 |
-+ <listitem><para> |
2042 |
-+ Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and |
2043 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided. |
2044 |
-+ </para></listitem> |
2045 |
-+ </varlistentry> |
2046 |
-+ |
2047 |
-+ <varlistentry> |
2048 |
-+ <term><constant>EEXIST</constant></term> |
2049 |
-+ <listitem><para> |
2050 |
-+ An endpoint of that name already exists. |
2051 |
-+ </para></listitem> |
2052 |
-+ </varlistentry> |
2053 |
-+ |
2054 |
-+ <varlistentry> |
2055 |
-+ <term><constant>EPERM</constant></term> |
2056 |
-+ <listitem><para> |
2057 |
-+ The calling user is not privileged. See |
2058 |
-+ <citerefentry> |
2059 |
-+ <refentrytitle>kdbus</refentrytitle> |
2060 |
-+ <manvolnum>7</manvolnum> |
2061 |
-+ </citerefentry> |
2062 |
-+ for information about privileged users. |
2063 |
-+ </para></listitem> |
2064 |
-+ </varlistentry> |
2065 |
-+ </variablelist> |
2066 |
-+ </refsect2> |
2067 |
-+ |
2068 |
-+ <refsect2> |
2069 |
-+ <title> |
2070 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> may fail with the |
2071 |
-+ following errors |
2072 |
-+ </title> |
2073 |
-+ |
2074 |
-+ <variablelist> |
2075 |
-+ <varlistentry> |
2076 |
-+ <term><constant>EINVAL</constant></term> |
2077 |
-+ <listitem><para> |
2078 |
-+ The flags supplied in <type>struct kdbus_cmd</type> |
2079 |
-+ are invalid. |
2080 |
-+ </para></listitem> |
2081 |
-+ </varlistentry> |
2082 |
-+ |
2083 |
-+ <varlistentry> |
2084 |
-+ <term><constant>EINVAL</constant></term> |
2085 |
-+ <listitem><para> |
2086 |
-+ Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and |
2087 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided. |
2088 |
-+ </para></listitem> |
2089 |
-+ </varlistentry> |
2090 |
-+ </variablelist> |
2091 |
-+ </refsect2> |
2092 |
-+ </refsect1> |
2093 |
-+ |
2094 |
-+ <refsect1> |
2095 |
-+ <title>See Also</title> |
2096 |
-+ <simplelist type="inline"> |
2097 |
-+ <member> |
2098 |
-+ <citerefentry> |
2099 |
-+ <refentrytitle>kdbus</refentrytitle> |
2100 |
-+ <manvolnum>7</manvolnum> |
2101 |
-+ </citerefentry> |
2102 |
-+ </member> |
2103 |
-+ <member> |
2104 |
-+ <citerefentry> |
2105 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2106 |
-+ <manvolnum>7</manvolnum> |
2107 |
-+ </citerefentry> |
2108 |
-+ </member> |
2109 |
-+ <member> |
2110 |
-+ <citerefentry> |
2111 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2112 |
-+ <manvolnum>7</manvolnum> |
2113 |
-+ </citerefentry> |
2114 |
-+ </member> |
2115 |
-+ <member> |
2116 |
-+ <citerefentry> |
2117 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
2118 |
-+ <manvolnum>7</manvolnum> |
2119 |
-+ </citerefentry> |
2120 |
-+ </member> |
2121 |
-+ <member> |
2122 |
-+ <citerefentry> |
2123 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
2124 |
-+ <manvolnum>7</manvolnum> |
2125 |
-+ </citerefentry> |
2126 |
-+ </member> |
2127 |
-+ <member> |
2128 |
-+ <citerefentry> |
2129 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2130 |
-+ <manvolnum>7</manvolnum> |
2131 |
-+ </citerefentry> |
2132 |
-+ </member> |
2133 |
-+ <member> |
2134 |
-+ <citerefentry> |
2135 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
2136 |
-+ <manvolnum>7</manvolnum> |
2137 |
-+ </citerefentry> |
2138 |
-+ </member> |
2139 |
-+ <member> |
2140 |
-+ <citerefentry> |
2141 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
2142 |
-+ <manvolnum>7</manvolnum> |
2143 |
-+ </citerefentry> |
2144 |
-+ </member> |
2145 |
-+ </simplelist> |
2146 |
-+ </refsect1> |
2147 |
-+</refentry> |
2148 |
-diff --git a/Documentation/kdbus/kdbus.fs.xml b/Documentation/kdbus/kdbus.fs.xml |
2149 |
-new file mode 100644 |
2150 |
-index 0000000..8c2a90e |
2151 |
---- /dev/null |
2152 |
-+++ b/Documentation/kdbus/kdbus.fs.xml |
2153 |
-@@ -0,0 +1,124 @@ |
2154 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
2155 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
2156 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
2157 |
-+ |
2158 |
-+<refentry id="kdbus_fs"> |
2159 |
-+ |
2160 |
-+ <refentryinfo> |
2161 |
-+ <title>kdbus.fs</title> |
2162 |
-+ <productname>kdbus.fs</productname> |
2163 |
-+ </refentryinfo> |
2164 |
-+ |
2165 |
-+ <refmeta> |
2166 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
2167 |
-+ <manvolnum>7</manvolnum> |
2168 |
-+ </refmeta> |
2169 |
-+ |
2170 |
-+ <refnamediv> |
2171 |
-+ <refname>kdbus.fs</refname> |
2172 |
-+ <refpurpose>kdbus file system</refpurpose> |
2173 |
-+ </refnamediv> |
2174 |
-+ |
2175 |
-+ <refsect1> |
2176 |
-+ <title>File-system Layout</title> |
2177 |
-+ |
2178 |
-+ <para> |
2179 |
-+ The <emphasis>kdbusfs</emphasis> pseudo filesystem provides access to |
2180 |
-+ kdbus entities, such as <emphasis>buses</emphasis> and |
2181 |
-+ <emphasis>endpoints</emphasis>. Each time the filesystem is mounted, |
2182 |
-+ a new, isolated kdbus instance is created, which is independent from the |
2183 |
-+ other instances. |
2184 |
-+ </para> |
2185 |
-+ <para> |
2186 |
-+ The system-wide standard mount point for <emphasis>kdbusfs</emphasis> is |
2187 |
-+ <constant>/sys/fs/kdbus</constant>. |
2188 |
-+ </para> |
2189 |
-+ |
2190 |
-+ <para> |
2191 |
-+ Buses are represented as directories in the file system layout, whereas |
2192 |
-+ endpoints are exposed as files inside these directories. At the top-level, |
2193 |
-+ a <emphasis>control</emphasis> node is present, which can be opened to |
2194 |
-+ create new buses via the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. |
2195 |
-+ Each <emphasis>bus</emphasis> shows a default endpoint called |
2196 |
-+ <varname>bus</varname>, which can be opened to either create a connection |
2197 |
-+ with the <constant>KDBUS_CMD_HELLO</constant> ioctl, or to create new |
2198 |
-+ custom endpoints for the bus with |
2199 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. See |
2200 |
-+ <citerefentry> |
2201 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2202 |
-+ <manvolnum>7</manvolnum> |
2203 |
-+ </citerefentry>, |
2204 |
-+ <citerefentry> |
2205 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
2206 |
-+ <manvolnum>7</manvolnum> |
2207 |
-+ </citerefentry> and |
2208 |
-+ <citerefentry> |
2209 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2210 |
-+ <manvolnum>7</manvolnum> |
2211 |
-+ </citerefentry> |
2212 |
-+ for more details. |
2213 |
-+ </para> |
2214 |
-+ |
2215 |
-+ <para>Following, you can see an example layout of the |
2216 |
-+ <emphasis>kdbusfs</emphasis> filesystem:</para> |
2217 |
-+ |
2218 |
-+<programlisting> |
2219 |
-+ /sys/fs/kdbus/ ; mount-point |
2220 |
-+ |-- 0-system ; bus directory |
2221 |
-+ | |-- bus ; default endpoint |
2222 |
-+ | `-- 1017-custom ; custom endpoint |
2223 |
-+ |-- 1000-user ; bus directory |
2224 |
-+ | |-- bus ; default endpoint |
2225 |
-+ | |-- 1000-service-A ; custom endpoint |
2226 |
-+ | `-- 1000-service-B ; custom endpoint |
2227 |
-+ `-- control ; control file |
2228 |
-+</programlisting> |
2229 |
-+ </refsect1> |
2230 |
-+ |
2231 |
-+ <refsect1> |
2232 |
-+ <title>Mounting instances</title> |
2233 |
-+ <para> |
2234 |
-+ In order to get a new and separate kdbus environment, a new instance |
2235 |
-+ of <emphasis>kdbusfs</emphasis> can be mounted like this: |
2236 |
-+ </para> |
2237 |
-+<programlisting> |
2238 |
-+ # mount -t kdbusfs kdbusfs /tmp/new_kdbus/ |
2239 |
-+</programlisting> |
2240 |
-+ </refsect1> |
2241 |
-+ |
2242 |
-+ <refsect1> |
2243 |
-+ <title>See Also</title> |
2244 |
-+ <simplelist type="inline"> |
2245 |
-+ <member> |
2246 |
-+ <citerefentry> |
2247 |
-+ <refentrytitle>kdbus</refentrytitle> |
2248 |
-+ <manvolnum>7</manvolnum> |
2249 |
-+ </citerefentry> |
2250 |
-+ </member> |
2251 |
-+ <member> |
2252 |
-+ <citerefentry> |
2253 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2254 |
-+ <manvolnum>7</manvolnum> |
2255 |
-+ </citerefentry> |
2256 |
-+ </member> |
2257 |
-+ <member> |
2258 |
-+ <citerefentry> |
2259 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
2260 |
-+ <manvolnum>7</manvolnum> |
2261 |
-+ </citerefentry> |
2262 |
-+ </member> |
2263 |
-+ <member> |
2264 |
-+ <citerefentry> |
2265 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2266 |
-+ <manvolnum>7</manvolnum> |
2267 |
-+ </citerefentry> |
2268 |
-+ </member> |
2269 |
-+ <member> |
2270 |
-+ <citerefentry> |
2271 |
-+ <refentrytitle>mount</refentrytitle> |
2272 |
-+ <manvolnum>8</manvolnum> |
2273 |
-+ </citerefentry> |
2274 |
-+ </member> |
2275 |
-+ </simplelist> |
2276 |
-+ </refsect1> |
2277 |
-+</refentry> |
2278 |
-diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml |
2279 |
-new file mode 100644 |
2280 |
-index 0000000..ee09dfa |
2281 |
---- /dev/null |
2282 |
-+++ b/Documentation/kdbus/kdbus.item.xml |
2283 |
-@@ -0,0 +1,839 @@ |
2284 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
2285 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
2286 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
2287 |
-+ |
2288 |
-+<refentry id="kdbus"> |
2289 |
-+ |
2290 |
-+ <refentryinfo> |
2291 |
-+ <title>kdbus.item</title> |
2292 |
-+ <productname>kdbus item</productname> |
2293 |
-+ </refentryinfo> |
2294 |
-+ |
2295 |
-+ <refmeta> |
2296 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
2297 |
-+ <manvolnum>7</manvolnum> |
2298 |
-+ </refmeta> |
2299 |
-+ |
2300 |
-+ <refnamediv> |
2301 |
-+ <refname>kdbus.item</refname> |
2302 |
-+ <refpurpose>kdbus item structure, layout and usage</refpurpose> |
2303 |
-+ </refnamediv> |
2304 |
-+ |
2305 |
-+ <refsect1> |
2306 |
-+ <title>Description</title> |
2307 |
-+ |
2308 |
-+ <para> |
2309 |
-+ To flexibly augment transport structures, data blobs of type |
2310 |
-+ <type>struct kdbus_item</type> can be attached to the structs passed |
2311 |
-+ into the ioctls. Some ioctls make items of certain types mandatory, |
2312 |
-+ others are optional. Items that are unsupported by ioctls they are |
2313 |
-+ attached to will cause the ioctl to fail with <varname>errno</varname> |
2314 |
-+ set to <constant>EINVAL</constant>. |
2315 |
-+ Items are also used for information stored in a connection's |
2316 |
-+ <emphasis>pool</emphasis>, such as received messages, name lists or |
2317 |
-+ requested connection or bus owner information. Depending on the type of |
2318 |
-+ an item, its total size is either fixed or variable. |
2319 |
-+ </para> |
2320 |
-+ |
2321 |
-+ <refsect2> |
2322 |
-+ <title>Chaining items</title> |
2323 |
-+ <para> |
2324 |
-+ Whenever items are used as part of the kdbus kernel API, they are |
2325 |
-+ embedded in structs that are embedded inside structs that themselves |
2326 |
-+ include a size field containing the overall size of the structure. |
2327 |
-+ This allows multiple items to be chained up, and an item iterator |
2328 |
-+ (see below) is capable of detecting the end of an item chain. |
2329 |
-+ </para> |
2330 |
-+ </refsect2> |
2331 |
-+ |
2332 |
-+ <refsect2> |
2333 |
-+ <title>Alignment</title> |
2334 |
-+ <para> |
2335 |
-+ The kernel expects all items to be aligned to 8-byte boundaries. |
2336 |
-+ Unaligned items will cause the ioctl they are used with to fail |
2337 |
-+ with <varname>errno</varname> set to <constant>EINVAL</constant>. |
2338 |
-+ An item that has an unaligned size itself hence needs to be padded |
2339 |
-+ if it is followed by another item. |
2340 |
-+ </para> |
2341 |
-+ </refsect2> |
2342 |
-+ |
2343 |
-+ <refsect2> |
2344 |
-+ <title>Iterating items</title> |
2345 |
-+ <para> |
2346 |
-+ A simple iterator would iterate over the items until the items have |
2347 |
-+ reached the embedding structure's overall size. An example |
2348 |
-+ implementation is shown below. |
2349 |
-+ </para> |
2350 |
-+ |
2351 |
-+ <programlisting><![CDATA[ |
2352 |
-+#define KDBUS_ALIGN8(val) (((val) + 7) & ~7) |
2353 |
-+ |
2354 |
-+#define KDBUS_ITEM_NEXT(item) \ |
2355 |
-+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) |
2356 |
-+ |
2357 |
-+#define KDBUS_ITEM_FOREACH(item, head, first) \ |
2358 |
-+ for ((item) = (head)->first; \ |
2359 |
-+ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ |
2360 |
-+ ((uint8_t *)(item) >= (uint8_t *)(head)); \ |
2361 |
-+ (item) = KDBUS_ITEM_NEXT(item)) |
2362 |
-+ ]]></programlisting> |
2363 |
-+ </refsect2> |
2364 |
-+ </refsect1> |
2365 |
-+ |
2366 |
-+ <refsect1> |
2367 |
-+ <title>Item layout</title> |
2368 |
-+ <para> |
2369 |
-+ A <type>struct kdbus_item</type> consists of a |
2370 |
-+ <varname>size</varname> field, describing its overall size, and a |
2371 |
-+ <varname>type</varname> field, both 64 bit wide. They are followed by |
2372 |
-+ a union to store information that is specific to the item's type. |
2373 |
-+ The struct layout is shown below. |
2374 |
-+ </para> |
2375 |
-+ |
2376 |
-+ <programlisting> |
2377 |
-+struct kdbus_item { |
2378 |
-+ __u64 size; |
2379 |
-+ __u64 type; |
2380 |
-+ /* item payload - see below */ |
2381 |
-+ union { |
2382 |
-+ __u8 data[0]; |
2383 |
-+ __u32 data32[0]; |
2384 |
-+ __u64 data64[0]; |
2385 |
-+ char str[0]; |
2386 |
-+ |
2387 |
-+ __u64 id; |
2388 |
-+ struct kdbus_vec vec; |
2389 |
-+ struct kdbus_creds creds; |
2390 |
-+ struct kdbus_pids pids; |
2391 |
-+ struct kdbus_audit audit; |
2392 |
-+ struct kdbus_caps caps; |
2393 |
-+ struct kdbus_timestamp timestamp; |
2394 |
-+ struct kdbus_name name; |
2395 |
-+ struct kdbus_bloom_parameter bloom_parameter; |
2396 |
-+ struct kdbus_bloom_filter bloom_filter; |
2397 |
-+ struct kdbus_memfd memfd; |
2398 |
-+ int fds[0]; |
2399 |
-+ struct kdbus_notify_name_change name_change; |
2400 |
-+ struct kdbus_notify_id_change id_change; |
2401 |
-+ struct kdbus_policy_access policy_access; |
2402 |
-+ }; |
2403 |
-+}; |
2404 |
-+ </programlisting> |
2405 |
-+ |
2406 |
-+ <para> |
2407 |
-+ <type>struct kdbus_item</type> should never be used to allocate |
2408 |
-+ an item instance, as its size may grow in future releases of the API. |
2409 |
-+ Instead, it should be manually assembled by storing the |
2410 |
-+ <varname>size</varname>, <varname>type</varname> and payload to a |
2411 |
-+ struct of its own. |
2412 |
-+ </para> |
2413 |
-+ </refsect1> |
2414 |
-+ |
2415 |
-+ <refsect1> |
2416 |
-+ <title>Item types</title> |
2417 |
-+ |
2418 |
-+ <refsect2> |
2419 |
-+ <title>Negotiation item</title> |
2420 |
-+ <variablelist> |
2421 |
-+ <varlistentry> |
2422 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
2423 |
-+ <listitem><para> |
2424 |
-+ With this item is attached to any ioctl, programs can |
2425 |
-+ <emphasis>probe</emphasis> the kernel for known item types. |
2426 |
-+ The item carries an array of <type>uint64_t</type> values in |
2427 |
-+ <varname>item.data64</varname>, each set to an item type to |
2428 |
-+ probe. The kernel will reset each member of this array that is |
2429 |
-+ not recognized as valid item type to <constant>0</constant>. |
2430 |
-+ This way, users can negotiate kernel features at start-up to |
2431 |
-+ keep newer userspace compatible with older kernels. This item |
2432 |
-+ is never attached by the kernel in response to any command. |
2433 |
-+ </para></listitem> |
2434 |
-+ </varlistentry> |
2435 |
-+ </variablelist> |
2436 |
-+ </refsect2> |
2437 |
-+ |
2438 |
-+ <refsect2> |
2439 |
-+ <title>Command specific items</title> |
2440 |
-+ <variablelist> |
2441 |
-+ <varlistentry> |
2442 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
2443 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term> |
2444 |
-+ <listitem><para> |
2445 |
-+ Messages are directly copied by the sending process into the |
2446 |
-+ receiver's |
2447 |
-+ <citerefentry> |
2448 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
2449 |
-+ <manvolnum>7</manvolnum> |
2450 |
-+ </citerefentry>. |
2451 |
-+ This way, two peers can exchange data by effectively doing a |
2452 |
-+ single-copy from one process to another; the kernel will not buffer |
2453 |
-+ the data anywhere else. <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> |
2454 |
-+ is used when <emphasis>sending</emphasis> message. The item |
2455 |
-+ references a memory address when the payload data can be found. |
2456 |
-+ <constant>KDBUS_ITEM_PAYLOAD_OFF</constant> is used when messages |
2457 |
-+ are <emphasis>received</emphasis>, and the |
2458 |
-+ <constant>offset</constant> value describes the offset inside the |
2459 |
-+ receiving connection's |
2460 |
-+ <citerefentry> |
2461 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
2462 |
-+ <manvolnum>7</manvolnum> |
2463 |
-+ </citerefentry> |
2464 |
-+ where the message payload can be found. See |
2465 |
-+ <citerefentry> |
2466 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2467 |
-+ <manvolnum>7</manvolnum> |
2468 |
-+ </citerefentry> |
2469 |
-+ for more information on passing of payload data along with a |
2470 |
-+ message. |
2471 |
-+ <programlisting> |
2472 |
-+struct kdbus_vec { |
2473 |
-+ __u64 size; |
2474 |
-+ union { |
2475 |
-+ __u64 address; |
2476 |
-+ __u64 offset; |
2477 |
-+ }; |
2478 |
-+}; |
2479 |
-+ </programlisting> |
2480 |
-+ </para></listitem> |
2481 |
-+ </varlistentry> |
2482 |
-+ |
2483 |
-+ <varlistentry> |
2484 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
2485 |
-+ <listitem><para> |
2486 |
-+ Transports a file descriptor of a <emphasis>memfd</emphasis> in |
2487 |
-+ <type>struct kdbus_memfd</type> in <varname>item.memfd</varname>. |
2488 |
-+ The <varname>size</varname> field has to match the actual size of |
2489 |
-+ the memfd that was specified when it was created. The |
2490 |
-+ <varname>start</varname> parameter denotes the offset inside the |
2491 |
-+ memfd at which the referenced payload starts. See |
2492 |
-+ <citerefentry> |
2493 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2494 |
-+ <manvolnum>7</manvolnum> |
2495 |
-+ </citerefentry> |
2496 |
-+ for more information on passing of payload data along with a |
2497 |
-+ message. |
2498 |
-+ <programlisting> |
2499 |
-+struct kdbus_memfd { |
2500 |
-+ __u64 start; |
2501 |
-+ __u64 size; |
2502 |
-+ int fd; |
2503 |
-+ __u32 __pad; |
2504 |
-+}; |
2505 |
-+ </programlisting> |
2506 |
-+ </para></listitem> |
2507 |
-+ </varlistentry> |
2508 |
-+ |
2509 |
-+ <varlistentry> |
2510 |
-+ <term><constant>KDBUS_ITEM_FDS</constant></term> |
2511 |
-+ <listitem><para> |
2512 |
-+ Contains an array of <emphasis>file descriptors</emphasis>. |
2513 |
-+ When used with <constant>KDBUS_CMD_SEND</constant>, the values of |
2514 |
-+ this array must be filled with valid file descriptor numbers. |
2515 |
-+ When received as item attached to a message, the array will |
2516 |
-+ contain the numbers of the installed file descriptors, or |
2517 |
-+ <constant>-1</constant> in case an error occurred. |
2518 |
-+ In either case, the number of entries in the array is derived from |
2519 |
-+ the item's total size. See |
2520 |
-+ <citerefentry> |
2521 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2522 |
-+ <manvolnum>7</manvolnum> |
2523 |
-+ </citerefentry> |
2524 |
-+ for more information. |
2525 |
-+ </para></listitem> |
2526 |
-+ </varlistentry> |
2527 |
-+ </variablelist> |
2528 |
-+ </refsect2> |
2529 |
-+ |
2530 |
-+ <refsect2> |
2531 |
-+ <title>Items specific to some commands</title> |
2532 |
-+ <variablelist> |
2533 |
-+ <varlistentry> |
2534 |
-+ <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term> |
2535 |
-+ <listitem><para> |
2536 |
-+ Transports a file descriptor that can be used to cancel a |
2537 |
-+ synchronous <constant>KDBUS_CMD_SEND</constant> operation by |
2538 |
-+ writing to it. The file descriptor is stored in |
2539 |
-+ <varname>item.fd[0]</varname>. The item may only contain one |
2540 |
-+ file descriptor. See |
2541 |
-+ <citerefentry> |
2542 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2543 |
-+ <manvolnum>7</manvolnum> |
2544 |
-+ </citerefentry> |
2545 |
-+ for more information on this item and how to use it. |
2546 |
-+ </para></listitem> |
2547 |
-+ </varlistentry> |
2548 |
-+ |
2549 |
-+ <varlistentry> |
2550 |
-+ <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term> |
2551 |
-+ <listitem><para> |
2552 |
-+ Contains a set of <emphasis>bloom parameters</emphasis> as |
2553 |
-+ <type>struct kdbus_bloom_parameter</type> in |
2554 |
-+ <varname>item.bloom_parameter</varname>. |
2555 |
-+ The item is passed from userspace to kernel during the |
2556 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl, and returned |
2557 |
-+ verbatim when <constant>KDBUS_CMD_HELLO</constant> is called. |
2558 |
-+ The kernel does not use the bloom parameters, but they need to |
2559 |
-+ be known by each connection on the bus in order to define the |
2560 |
-+ bloom filter hash details. See |
2561 |
-+ <citerefentry> |
2562 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2563 |
-+ <manvolnum>7</manvolnum> |
2564 |
-+ </citerefentry> |
2565 |
-+ for more information on matching and bloom filters. |
2566 |
-+ <programlisting> |
2567 |
-+struct kdbus_bloom_parameter { |
2568 |
-+ __u64 size; |
2569 |
-+ __u64 n_hash; |
2570 |
-+}; |
2571 |
-+ </programlisting> |
2572 |
-+ </para></listitem> |
2573 |
-+ </varlistentry> |
2574 |
-+ |
2575 |
-+ <varlistentry> |
2576 |
-+ <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term> |
2577 |
-+ <listitem><para> |
2578 |
-+ Carries a <emphasis>bloom filter</emphasis> as |
2579 |
-+ <type>struct kdbus_bloom_filter</type> in |
2580 |
-+ <varname>item.bloom_filter</varname>. It is mandatory to send this |
2581 |
-+ item attached to a <type>struct kdbus_msg</type>, in case the |
2582 |
-+ message is a signal. This item is never transported from kernel to |
2583 |
-+ userspace. See |
2584 |
-+ <citerefentry> |
2585 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2586 |
-+ <manvolnum>7</manvolnum> |
2587 |
-+ </citerefentry> |
2588 |
-+ for more information on matching and bloom filters. |
2589 |
-+ <programlisting> |
2590 |
-+struct kdbus_bloom_filter { |
2591 |
-+ __u64 generation; |
2592 |
-+ __u64 data[0]; |
2593 |
-+}; |
2594 |
-+ </programlisting> |
2595 |
-+ </para></listitem> |
2596 |
-+ </varlistentry> |
2597 |
-+ |
2598 |
-+ <varlistentry> |
2599 |
-+ <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term> |
2600 |
-+ <listitem><para> |
2601 |
-+ Transports a <emphasis>bloom mask</emphasis> as binary data blob |
2602 |
-+ stored in <varname>item.data</varname>. This item is used to |
2603 |
-+ describe a match into a connection's match database. See |
2604 |
-+ <citerefentry> |
2605 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2606 |
-+ <manvolnum>7</manvolnum> |
2607 |
-+ </citerefentry> |
2608 |
-+ for more information on matching and bloom filters. |
2609 |
-+ </para></listitem> |
2610 |
-+ </varlistentry> |
2611 |
-+ |
2612 |
-+ <varlistentry> |
2613 |
-+ <term><constant>KDBUS_ITEM_DST_NAME</constant></term> |
2614 |
-+ <listitem><para> |
2615 |
-+ Contains a <emphasis>well-known name</emphasis> to send a |
2616 |
-+ message to, as null-terminated string in |
2617 |
-+ <varname>item.str</varname>. This item is used with |
2618 |
-+ <constant>KDBUS_CMD_SEND</constant>. See |
2619 |
-+ <citerefentry> |
2620 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2621 |
-+ <manvolnum>7</manvolnum> |
2622 |
-+ </citerefentry> |
2623 |
-+ for more information on how to send a message. |
2624 |
-+ </para></listitem> |
2625 |
-+ </varlistentry> |
2626 |
-+ |
2627 |
-+ <varlistentry> |
2628 |
-+ <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term> |
2629 |
-+ <listitem><para> |
2630 |
-+ Contains a <emphasis>bus name</emphasis> or |
2631 |
-+ <emphasis>endpoint name</emphasis>, stored as null-terminated |
2632 |
-+ string in <varname>item.str</varname>. This item is sent from |
2633 |
-+ userspace to kernel when buses or endpoints are created, and |
2634 |
-+ returned back to userspace when the bus creator information is |
2635 |
-+ queried. See |
2636 |
-+ <citerefentry> |
2637 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2638 |
-+ <manvolnum>7</manvolnum> |
2639 |
-+ </citerefentry> |
2640 |
-+ and |
2641 |
-+ <citerefentry> |
2642 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2643 |
-+ <manvolnum>7</manvolnum> |
2644 |
-+ </citerefentry>. |
2645 |
-+ </para></listitem> |
2646 |
-+ </varlistentry> |
2647 |
-+ |
2648 |
-+ <varlistentry> |
2649 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term> |
2650 |
-+ <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term> |
2651 |
-+ <listitem><para> |
2652 |
-+ Contains a set of <emphasis>attach flags</emphasis> at |
2653 |
-+ <emphasis>send</emphasis> or <emphasis>receive</emphasis> time. See |
2654 |
-+ <citerefentry> |
2655 |
-+ <refentrytitle>kdbus</refentrytitle> |
2656 |
-+ <manvolnum>7</manvolnum> |
2657 |
-+ </citerefentry>, |
2658 |
-+ <citerefentry> |
2659 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2660 |
-+ <manvolnum>7</manvolnum> |
2661 |
-+ </citerefentry> and |
2662 |
-+ <citerefentry> |
2663 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
2664 |
-+ <manvolnum>7</manvolnum> |
2665 |
-+ </citerefentry> |
2666 |
-+ for more information on attach flags. |
2667 |
-+ </para></listitem> |
2668 |
-+ </varlistentry> |
2669 |
-+ |
2670 |
-+ <varlistentry> |
2671 |
-+ <term><constant>KDBUS_ITEM_ID</constant></term> |
2672 |
-+ <listitem><para> |
2673 |
-+ Transports a connection's <emphasis>numerical ID</emphasis> of |
2674 |
-+ a connection as <type>uint64_t</type> value in |
2675 |
-+ <varname>item.id</varname>. |
2676 |
-+ </para></listitem> |
2677 |
-+ </varlistentry> |
2678 |
-+ |
2679 |
-+ <varlistentry> |
2680 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
2681 |
-+ <listitem><para> |
2682 |
-+ Transports a name associated with the |
2683 |
-+ <emphasis>name registry</emphasis> as null-terminated string as |
2684 |
-+ <type>struct kdbus_name</type> in |
2685 |
-+ <varname>item.name</varname>. The <varname>flags</varname> |
2686 |
-+ contains the flags of the name. See |
2687 |
-+ <citerefentry> |
2688 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
2689 |
-+ <manvolnum>7</manvolnum> |
2690 |
-+ </citerefentry> |
2691 |
-+ for more information on how to access the name registry of a bus. |
2692 |
-+ <programlisting> |
2693 |
-+struct kdbus_name { |
2694 |
-+ __u64 flags; |
2695 |
-+ char name[0]; |
2696 |
-+}; |
2697 |
-+ </programlisting> |
2698 |
-+ </para></listitem> |
2699 |
-+ </varlistentry> |
2700 |
-+ </variablelist> |
2701 |
-+ </refsect2> |
2702 |
-+ |
2703 |
-+ <refsect2> |
2704 |
-+ <title>Items attached by the kernel as metadata</title> |
2705 |
-+ |
2706 |
-+ <variablelist> |
2707 |
-+ <varlistentry> |
2708 |
-+ <term><constant>KDBUS_ITEM_TIMESTAMP</constant></term> |
2709 |
-+ <listitem><para> |
2710 |
-+ Contains both the <emphasis>monotonic</emphasis> and the |
2711 |
-+ <emphasis>realtime</emphasis> timestamp, taken when the message |
2712 |
-+ was processed on the kernel side. |
2713 |
-+ Stored as <type>struct kdbus_timestamp</type> in |
2714 |
-+ <varname>item.timestamp</varname>. |
2715 |
-+ <programlisting> |
2716 |
-+struct kdbus_timestamp { |
2717 |
-+ __u64 seqnum; |
2718 |
-+ __u64 monotonic_ns; |
2719 |
-+ __u64 realtime_ns; |
2720 |
-+}; |
2721 |
-+ </programlisting> |
2722 |
-+ </para></listitem> |
2723 |
-+ </varlistentry> |
2724 |
-+ |
2725 |
-+ <varlistentry> |
2726 |
-+ <term><constant>KDBUS_ITEM_CREDS</constant></term> |
2727 |
-+ <listitem><para> |
2728 |
-+ Contains a set of <emphasis>user</emphasis> and |
2729 |
-+ <emphasis>group</emphasis> information as 32-bit values, in the |
2730 |
-+ usual four flavors: real, effective, saved and filesystem related. |
2731 |
-+ Stored as <type>struct kdbus_creds</type> in |
2732 |
-+ <varname>item.creds</varname>. |
2733 |
-+ <programlisting> |
2734 |
-+struct kdbus_creds { |
2735 |
-+ __u32 uid; |
2736 |
-+ __u32 euid; |
2737 |
-+ __u32 suid; |
2738 |
-+ __u32 fsuid; |
2739 |
-+ __u32 gid; |
2740 |
-+ __u32 egid; |
2741 |
-+ __u32 sgid; |
2742 |
-+ __u32 fsgid; |
2743 |
-+}; |
2744 |
-+ </programlisting> |
2745 |
-+ </para></listitem> |
2746 |
-+ </varlistentry> |
2747 |
-+ |
2748 |
-+ <varlistentry> |
2749 |
-+ <term><constant>KDBUS_ITEM_PIDS</constant></term> |
2750 |
-+ <listitem><para> |
2751 |
-+ Contains the <emphasis>PID</emphasis>, <emphasis>TID</emphasis> |
2752 |
-+ and <emphasis>parent PID (PPID)</emphasis> of a remote peer. |
2753 |
-+ Stored as <type>struct kdbus_pids</type> in |
2754 |
-+ <varname>item.pids</varname>. |
2755 |
-+ <programlisting> |
2756 |
-+struct kdbus_pids { |
2757 |
-+ __u64 pid; |
2758 |
-+ __u64 tid; |
2759 |
-+ __u64 ppid; |
2760 |
-+}; |
2761 |
-+ </programlisting> |
2762 |
-+ </para></listitem> |
2763 |
-+ </varlistentry> |
2764 |
-+ |
2765 |
-+ <varlistentry> |
2766 |
-+ <term><constant>KDBUS_ITEM_AUXGROUPS</constant></term> |
2767 |
-+ <listitem><para> |
2768 |
-+ Contains the <emphasis>auxiliary (supplementary) groups</emphasis> |
2769 |
-+ a remote peer is a member of, stored as array of |
2770 |
-+ <type>uint32_t</type> values in <varname>item.data32</varname>. |
2771 |
-+ The array length can be determined by looking at the item's total |
2772 |
-+ size, subtracting the size of the header and dividing the |
2773 |
-+ remainder by <constant>sizeof(uint32_t)</constant>. |
2774 |
-+ </para></listitem> |
2775 |
-+ </varlistentry> |
2776 |
-+ |
2777 |
-+ <varlistentry> |
2778 |
-+ <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term> |
2779 |
-+ <listitem><para> |
2780 |
-+ Contains a <emphasis>well-known name</emphasis> currently owned |
2781 |
-+ by a connection. The name is stored as null-terminated string in |
2782 |
-+ <varname>item.str</varname>. Its length can also be derived from |
2783 |
-+ the item's total size. |
2784 |
-+ </para></listitem> |
2785 |
-+ </varlistentry> |
2786 |
-+ |
2787 |
-+ <varlistentry> |
2788 |
-+ <term><constant>KDBUS_ITEM_TID_COMM</constant> [*]</term> |
2789 |
-+ <listitem><para> |
2790 |
-+ Contains the <emphasis>comm</emphasis> string of a task's |
2791 |
-+ <emphasis>TID</emphasis> (thread ID), stored as null-terminated |
2792 |
-+ string in <varname>item.str</varname>. Its length can also be |
2793 |
-+ derived from the item's total size. Receivers of this item should |
2794 |
-+ not use its contents for any kind of security measures. See below. |
2795 |
-+ </para></listitem> |
2796 |
-+ </varlistentry> |
2797 |
-+ |
2798 |
-+ <varlistentry> |
2799 |
-+ <term><constant>KDBUS_ITEM_PID_COMM</constant> [*]</term> |
2800 |
-+ <listitem><para> |
2801 |
-+ Contains the <emphasis>comm</emphasis> string of a task's |
2802 |
-+ <emphasis>PID</emphasis> (process ID), stored as null-terminated |
2803 |
-+ string in <varname>item.str</varname>. Its length can also be |
2804 |
-+ derived from the item's total size. Receivers of this item should |
2805 |
-+ not use its contents for any kind of security measures. See below. |
2806 |
-+ </para></listitem> |
2807 |
-+ </varlistentry> |
2808 |
-+ |
2809 |
-+ <varlistentry> |
2810 |
-+ <term><constant>KDBUS_ITEM_EXE</constant> [*]</term> |
2811 |
-+ <listitem><para> |
2812 |
-+ Contains the <emphasis>path to the executable</emphasis> of a task, |
2813 |
-+ stored as null-terminated string in <varname>item.str</varname>. Its |
2814 |
-+ length can also be derived from the item's total size. Receivers of |
2815 |
-+ this item should not use its contents for any kind of security |
2816 |
-+ measures. See below. |
2817 |
-+ </para></listitem> |
2818 |
-+ </varlistentry> |
2819 |
-+ |
2820 |
-+ <varlistentry> |
2821 |
-+ <term><constant>KDBUS_ITEM_CMDLINE</constant> [*]</term> |
2822 |
-+ <listitem><para> |
2823 |
-+ Contains the <emphasis>command line arguments</emphasis> of a |
2824 |
-+ task, stored as an <emphasis>array</emphasis> of null-terminated |
2825 |
-+ strings in <varname>item.str</varname>. The total length of all |
2826 |
-+ strings in the array can be derived from the item's total size. |
2827 |
-+ Receivers of this item should not use its contents for any kind |
2828 |
-+ of security measures. See below. |
2829 |
-+ </para></listitem> |
2830 |
-+ </varlistentry> |
2831 |
-+ |
2832 |
-+ <varlistentry> |
2833 |
-+ <term><constant>KDBUS_ITEM_CGROUP</constant></term> |
2834 |
-+ <listitem><para> |
2835 |
-+ Contains the <emphasis>cgroup path</emphasis> of a task, stored |
2836 |
-+ as null-terminated string in <varname>item.str</varname>. Its |
2837 |
-+ length can also be derived from the item's total size. |
2838 |
-+ </para></listitem> |
2839 |
-+ </varlistentry> |
2840 |
-+ |
2841 |
-+ <varlistentry> |
2842 |
-+ <term><constant>KDBUS_ITEM_CAPS</constant></term> |
2843 |
-+ <listitem><para> |
2844 |
-+ Contains sets of <emphasis>capabilities</emphasis>, stored as |
2845 |
-+ <type>struct kdbus_caps</type> in <varname>item.caps</varname>. |
2846 |
-+ As the item size may increase in the future, programs should be |
2847 |
-+ written in a way that it takes |
2848 |
-+ <varname>item.caps.last_cap</varname> into account, and derive |
2849 |
-+ the number of sets and rows from the item size and the reported |
2850 |
-+ number of valid capability bits. |
2851 |
-+ <programlisting> |
2852 |
-+struct kdbus_caps { |
2853 |
-+ __u32 last_cap; |
2854 |
-+ __u32 caps[0]; |
2855 |
-+}; |
2856 |
-+ </programlisting> |
2857 |
-+ </para></listitem> |
2858 |
-+ </varlistentry> |
2859 |
-+ |
2860 |
-+ <varlistentry> |
2861 |
-+ <term><constant>KDBUS_ITEM_SECLABEL</constant></term> |
2862 |
-+ <listitem><para> |
2863 |
-+ Contains the <emphasis>LSM label</emphasis> of a task, stored as |
2864 |
-+ null-terminated string in <varname>item.str</varname>. Its length |
2865 |
-+ can also be derived from the item's total size. |
2866 |
-+ </para></listitem> |
2867 |
-+ </varlistentry> |
2868 |
-+ |
2869 |
-+ <varlistentry> |
2870 |
-+ <term><constant>KDBUS_ITEM_AUDIT</constant></term> |
2871 |
-+ <listitem><para> |
2872 |
-+ Contains the audit <emphasis>sessionid</emphasis> and |
2873 |
-+ <emphasis>loginuid</emphasis> of a task, stored as |
2874 |
-+ <type>struct kdbus_audit</type> in |
2875 |
-+ <varname>item.audit</varname>. |
2876 |
-+ <programlisting> |
2877 |
-+struct kdbus_audit { |
2878 |
-+ __u32 sessionid; |
2879 |
-+ __u32 loginuid; |
2880 |
-+}; |
2881 |
-+ </programlisting> |
2882 |
-+ </para></listitem> |
2883 |
-+ </varlistentry> |
2884 |
-+ |
2885 |
-+ <varlistentry> |
2886 |
-+ <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term> |
2887 |
-+ <listitem><para> |
2888 |
-+ Contains the <emphasis>connection description</emphasis>, as set |
2889 |
-+ by <constant>KDBUS_CMD_HELLO</constant> or |
2890 |
-+ <constant>KDBUS_CMD_CONN_UPDATE</constant>, stored as |
2891 |
-+ null-terminated string in <varname>item.str</varname>. Its length |
2892 |
-+ can also be derived from the item's total size. |
2893 |
-+ </para></listitem> |
2894 |
-+ </varlistentry> |
2895 |
-+ </variablelist> |
2896 |
-+ |
2897 |
-+ <para> |
2898 |
-+ All metadata is automatically translated into the |
2899 |
-+ <emphasis>namespaces</emphasis> of the task that receives them. See |
2900 |
-+ <citerefentry> |
2901 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2902 |
-+ <manvolnum>7</manvolnum> |
2903 |
-+ </citerefentry> |
2904 |
-+ for more information. |
2905 |
-+ </para> |
2906 |
-+ |
2907 |
-+ <para> |
2908 |
-+ [*] Note that the content stored in metadata items of type |
2909 |
-+ <constant>KDBUS_ITEM_TID_COMM</constant>, |
2910 |
-+ <constant>KDBUS_ITEM_PID_COMM</constant>, |
2911 |
-+ <constant>KDBUS_ITEM_EXE</constant> and |
2912 |
-+ <constant>KDBUS_ITEM_CMDLINE</constant> |
2913 |
-+ can easily be tampered by the sending tasks. Therefore, they should |
2914 |
-+ <emphasis>not</emphasis> be used for any sort of security relevant |
2915 |
-+ assumptions. The only reason they are transmitted is to let |
2916 |
-+ receivers know about details that were set when metadata was |
2917 |
-+ collected, even though the task they were collected from is not |
2918 |
-+ active any longer when the items are received. |
2919 |
-+ </para> |
2920 |
-+ </refsect2> |
2921 |
-+ |
2922 |
-+ <refsect2> |
2923 |
-+ <title>Items used for policy entries, matches and notifications</title> |
2924 |
-+ |
2925 |
-+ <variablelist> |
2926 |
-+ <varlistentry> |
2927 |
-+ <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term> |
2928 |
-+ <listitem><para> |
2929 |
-+ This item describes a <emphasis>policy access</emphasis> entry to |
2930 |
-+ access the policy database of a |
2931 |
-+ <citerefentry> |
2932 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
2933 |
-+ <manvolnum>7</manvolnum> |
2934 |
-+ </citerefentry> or |
2935 |
-+ <citerefentry> |
2936 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
2937 |
-+ <manvolnum>7</manvolnum> |
2938 |
-+ </citerefentry>. |
2939 |
-+ Please refer to |
2940 |
-+ <citerefentry> |
2941 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
2942 |
-+ <manvolnum>7</manvolnum> |
2943 |
-+ </citerefentry> |
2944 |
-+ for more information on the policy database and how to access it. |
2945 |
-+ <programlisting> |
2946 |
-+struct kdbus_policy_access { |
2947 |
-+ __u64 type; |
2948 |
-+ __u64 access; |
2949 |
-+ __u64 id; |
2950 |
-+}; |
2951 |
-+ </programlisting> |
2952 |
-+ </para></listitem> |
2953 |
-+ </varlistentry> |
2954 |
-+ |
2955 |
-+ <varlistentry> |
2956 |
-+ <term><constant>KDBUS_ITEM_ID_ADD</constant></term> |
2957 |
-+ <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term> |
2958 |
-+ <listitem><para> |
2959 |
-+ This item is sent as attachment to a |
2960 |
-+ <emphasis>kernel notification</emphasis> and indicates that a |
2961 |
-+ new connection was created on the bus, or that a connection was |
2962 |
-+ disconnected, respectively. It stores a |
2963 |
-+ <type>struct kdbus_notify_id_change</type> in |
2964 |
-+ <varname>item.id_change</varname>. |
2965 |
-+ The <varname>id</varname> field contains the numeric ID of the |
2966 |
-+ connection that was added or removed, and <varname>flags</varname> |
2967 |
-+ is set to the connection flags, as passed by |
2968 |
-+ <constant>KDBUS_CMD_HELLO</constant>. See |
2969 |
-+ <citerefentry> |
2970 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
2971 |
-+ <manvolnum>7</manvolnum> |
2972 |
-+ </citerefentry> |
2973 |
-+ and |
2974 |
-+ <citerefentry> |
2975 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
2976 |
-+ <manvolnum>7</manvolnum> |
2977 |
-+ </citerefentry> |
2978 |
-+ for more information on matches and notification messages. |
2979 |
-+ <programlisting> |
2980 |
-+struct kdbus_notify_id_change { |
2981 |
-+ __u64 id; |
2982 |
-+ __u64 flags; |
2983 |
-+}; |
2984 |
-+ </programlisting> |
2985 |
-+ </para></listitem> |
2986 |
-+ </varlistentry> |
2987 |
-+ |
2988 |
-+ <varlistentry> |
2989 |
-+ <term><constant>KDBUS_ITEM_NAME_ADD</constant></term> |
2990 |
-+ <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term> |
2991 |
-+ <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term> |
2992 |
-+ <listitem><para> |
2993 |
-+ This item is sent as attachment to a |
2994 |
-+ <emphasis>kernel notification</emphasis> and indicates that a |
2995 |
-+ <emphasis>well-known name</emphasis> appeared, disappeared or |
2996 |
-+ transferred to another owner on the bus. It stores a |
2997 |
-+ <type>struct kdbus_notify_name_change</type> in |
2998 |
-+ <varname>item.name_change</varname>. |
2999 |
-+ <varname>old_id</varname> describes the former owner of the name |
3000 |
-+ and is set to <constant>0</constant> values in case of |
3001 |
-+ <constant>KDBUS_ITEM_NAME_ADD</constant>. |
3002 |
-+ <varname>new_id</varname> describes the new owner of the name and |
3003 |
-+ is set to <constant>0</constant> values in case of |
3004 |
-+ <constant>KDBUS_ITEM_NAME_REMOVE</constant>. |
3005 |
-+ The <varname>name</varname> field contains the well-known name the |
3006 |
-+ notification is about, as null-terminated string. See |
3007 |
-+ <citerefentry> |
3008 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
3009 |
-+ <manvolnum>7</manvolnum> |
3010 |
-+ </citerefentry> |
3011 |
-+ and |
3012 |
-+ <citerefentry> |
3013 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3014 |
-+ <manvolnum>7</manvolnum> |
3015 |
-+ </citerefentry> |
3016 |
-+ for more information on matches and notification messages. |
3017 |
-+ <programlisting> |
3018 |
-+struct kdbus_notify_name_change { |
3019 |
-+ struct kdbus_notify_id_change old_id; |
3020 |
-+ struct kdbus_notify_id_change new_id; |
3021 |
-+ char name[0]; |
3022 |
-+}; |
3023 |
-+ </programlisting> |
3024 |
-+ </para></listitem> |
3025 |
-+ </varlistentry> |
3026 |
-+ |
3027 |
-+ <varlistentry> |
3028 |
-+ <term><constant>KDBUS_ITEM_REPLY_TIMEOUT</constant></term> |
3029 |
-+ <listitem><para> |
3030 |
-+ This item is sent as attachment to a |
3031 |
-+ <emphasis>kernel notification</emphasis>. It informs the receiver |
3032 |
-+ that an expected reply to a message was not received in time. |
3033 |
-+ The remote peer ID and the message cookie are stored in the message |
3034 |
-+ header. See |
3035 |
-+ <citerefentry> |
3036 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3037 |
-+ <manvolnum>7</manvolnum> |
3038 |
-+ </citerefentry> |
3039 |
-+ for more information about messages, timeouts and notifications. |
3040 |
-+ </para></listitem> |
3041 |
-+ </varlistentry> |
3042 |
-+ |
3043 |
-+ <varlistentry> |
3044 |
-+ <term><constant>KDBUS_ITEM_REPLY_DEAD</constant></term> |
3045 |
-+ <listitem><para> |
3046 |
-+ This item is sent as attachment to a |
3047 |
-+ <emphasis>kernel notification</emphasis>. It informs the receiver |
3048 |
-+ that a remote connection a reply is expected from was disconnected |
3049 |
-+ before that reply was sent. The remote peer ID and the message |
3050 |
-+ cookie are stored in the message header. See |
3051 |
-+ <citerefentry> |
3052 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3053 |
-+ <manvolnum>7</manvolnum> |
3054 |
-+ </citerefentry> |
3055 |
-+ for more information about messages, timeouts and notifications. |
3056 |
-+ </para></listitem> |
3057 |
-+ </varlistentry> |
3058 |
-+ </variablelist> |
3059 |
-+ </refsect2> |
3060 |
-+ </refsect1> |
3061 |
-+ |
3062 |
-+ <refsect1> |
3063 |
-+ <title>See Also</title> |
3064 |
-+ <simplelist type="inline"> |
3065 |
-+ <member> |
3066 |
-+ <citerefentry> |
3067 |
-+ <refentrytitle>kdbus</refentrytitle> |
3068 |
-+ <manvolnum>7</manvolnum> |
3069 |
-+ </citerefentry> |
3070 |
-+ </member> |
3071 |
-+ <member> |
3072 |
-+ <citerefentry> |
3073 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
3074 |
-+ <manvolnum>7</manvolnum> |
3075 |
-+ </citerefentry> |
3076 |
-+ </member> |
3077 |
-+ <member> |
3078 |
-+ <citerefentry> |
3079 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
3080 |
-+ <manvolnum>7</manvolnum> |
3081 |
-+ </citerefentry> |
3082 |
-+ </member> |
3083 |
-+ <member> |
3084 |
-+ <citerefentry> |
3085 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
3086 |
-+ <manvolnum>7</manvolnum> |
3087 |
-+ </citerefentry> |
3088 |
-+ </member> |
3089 |
-+ <member> |
3090 |
-+ <citerefentry> |
3091 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
3092 |
-+ <manvolnum>7</manvolnum> |
3093 |
-+ </citerefentry> |
3094 |
-+ </member> |
3095 |
-+ <member> |
3096 |
-+ <citerefentry> |
3097 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3098 |
-+ <manvolnum>7</manvolnum> |
3099 |
-+ </citerefentry> |
3100 |
-+ </member> |
3101 |
-+ <member> |
3102 |
-+ <citerefentry> |
3103 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
3104 |
-+ <manvolnum>7</manvolnum> |
3105 |
-+ </citerefentry> |
3106 |
-+ </member> |
3107 |
-+ <member> |
3108 |
-+ <citerefentry> |
3109 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
3110 |
-+ <manvolnum>7</manvolnum> |
3111 |
-+ </citerefentry> |
3112 |
-+ </member> |
3113 |
-+ <member> |
3114 |
-+ <citerefentry> |
3115 |
-+ <refentrytitle>memfd_create</refentrytitle> |
3116 |
-+ <manvolnum>2</manvolnum> |
3117 |
-+ </citerefentry> |
3118 |
-+ </member> |
3119 |
-+ </simplelist> |
3120 |
-+ </refsect1> |
3121 |
-+ |
3122 |
-+</refentry> |
3123 |
-diff --git a/Documentation/kdbus/kdbus.match.xml b/Documentation/kdbus/kdbus.match.xml |
3124 |
-new file mode 100644 |
3125 |
-index 0000000..ae38e04 |
3126 |
---- /dev/null |
3127 |
-+++ b/Documentation/kdbus/kdbus.match.xml |
3128 |
-@@ -0,0 +1,555 @@ |
3129 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
3130 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
3131 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
3132 |
-+ |
3133 |
-+<refentry id="kdbus.match"> |
3134 |
-+ |
3135 |
-+ <refentryinfo> |
3136 |
-+ <title>kdbus.match</title> |
3137 |
-+ <productname>kdbus.match</productname> |
3138 |
-+ </refentryinfo> |
3139 |
-+ |
3140 |
-+ <refmeta> |
3141 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
3142 |
-+ <manvolnum>7</manvolnum> |
3143 |
-+ </refmeta> |
3144 |
-+ |
3145 |
-+ <refnamediv> |
3146 |
-+ <refname>kdbus.match</refname> |
3147 |
-+ <refpurpose>kdbus match</refpurpose> |
3148 |
-+ </refnamediv> |
3149 |
-+ |
3150 |
-+ <refsect1> |
3151 |
-+ <title>Description</title> |
3152 |
-+ |
3153 |
-+ <para> |
3154 |
-+ kdbus connections can install matches in order to subscribe to signal |
3155 |
-+ messages sent on the bus. Such signal messages can be either directed |
3156 |
-+ to a single connection (by setting a specific connection ID in |
3157 |
-+ <varname>struct kdbus_msg.dst_id</varname> or by sending it to a |
3158 |
-+ well-known name), or to potentially <emphasis>all</emphasis> currently |
3159 |
-+ active connections on the bus (by setting |
3160 |
-+ <varname>struct kdbus_msg.dst_id</varname> to |
3161 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant>). |
3162 |
-+ A signal message always has the <constant>KDBUS_MSG_SIGNAL</constant> |
3163 |
-+ bit set in the <varname>flags</varname> bitfield. |
3164 |
-+ Also, signal messages can originate from either the kernel (called |
3165 |
-+ <emphasis>notifications</emphasis>), or from other bus connections. |
3166 |
-+ In either case, a bus connection needs to have a suitable |
3167 |
-+ <emphasis>match</emphasis> installed in order to receive any signal |
3168 |
-+ message. Without any rules installed in the connection, no signal message |
3169 |
-+ will be received. |
3170 |
-+ </para> |
3171 |
-+ </refsect1> |
3172 |
-+ |
3173 |
-+ <refsect1> |
3174 |
-+ <title>Matches for signal messages from other connections</title> |
3175 |
-+ <para> |
3176 |
-+ Matches for messages from other connections (not kernel notifications) |
3177 |
-+ are implemented as bloom filters (see below). The sender adds certain |
3178 |
-+ properties of the message as elements to a bloom filter bit field, and |
3179 |
-+ sends that along with the signal message. |
3180 |
-+ |
3181 |
-+ The receiving connection adds the message properties it is interested in |
3182 |
-+ as elements to a bloom mask bit field, and uploads the mask as match rule, |
3183 |
-+ possibly along with some other rules to further limit the match. |
3184 |
-+ |
3185 |
-+ The kernel will match the signal message's bloom filter against the |
3186 |
-+ connection's bloom mask (simply by &-ing it), and will decide whether |
3187 |
-+ the message should be delivered to a connection. |
3188 |
-+ </para> |
3189 |
-+ <para> |
3190 |
-+ The kernel has no notion of any specific properties of the signal message, |
3191 |
-+ all it sees are the bit fields of the bloom filter and the mask to match |
3192 |
-+ against. The use of bloom filters allows simple and efficient matching, |
3193 |
-+ without exposing any message properties or internals to the kernel side. |
3194 |
-+ Clients need to deal with the fact that they might receive signal messages |
3195 |
-+ which they did not subscribe to, as the bloom filter might allow |
3196 |
-+ false-positives to pass the filter. |
3197 |
-+ |
3198 |
-+ To allow the future extension of the set of elements in the bloom filter, |
3199 |
-+ the filter specifies a <emphasis>generation</emphasis> number. A later |
3200 |
-+ generation must always contain all elements of the set of the previous |
3201 |
-+ generation, but can add new elements to the set. The match rules mask can |
3202 |
-+ carry an array with all previous generations of masks individually stored. |
3203 |
-+ When the filter and mask are matched by the kernel, the mask with the |
3204 |
-+ closest matching generation is selected as the index into the mask array. |
3205 |
-+ </para> |
3206 |
-+ </refsect1> |
3207 |
-+ |
3208 |
-+ <refsect1> |
3209 |
-+ <title>Bloom filters</title> |
3210 |
-+ <para> |
3211 |
-+ Bloom filters allow checking whether a given word is present in a |
3212 |
-+ dictionary. This allows connections to set up a mask for information it |
3213 |
-+ is interested in, and will be delivered signal messages that have a |
3214 |
-+ matching filter. |
3215 |
-+ |
3216 |
-+ For general information, see |
3217 |
-+ <ulink url="https://en.wikipedia.org/wiki/Bloom_filter">the Wikipedia |
3218 |
-+ article on bloom filters</ulink>. |
3219 |
-+ </para> |
3220 |
-+ <para> |
3221 |
-+ The size of the bloom filter is defined per bus when it is created, in |
3222 |
-+ <varname>kdbus_bloom_parameter.size</varname>. All bloom filters attached |
3223 |
-+ to signal messages on the bus must match this size, and all bloom filter |
3224 |
-+ matches uploaded by connections must also match the size, or a multiple |
3225 |
-+ thereof (see below). |
3226 |
-+ |
3227 |
-+ The calculation of the mask has to be done in userspace applications. The |
3228 |
-+ kernel just checks the bitmasks to decide whether or not to let the |
3229 |
-+ message pass. All bits in the mask must match the filter in and bit-wise |
3230 |
-+ <emphasis>AND</emphasis> logic, but the mask may have more bits set than |
3231 |
-+ the filter. Consequently, false positive matches are expected to happen, |
3232 |
-+ and programs must deal with that fact by checking the contents of the |
3233 |
-+ payload again at receive time. |
3234 |
-+ </para> |
3235 |
-+ <para> |
3236 |
-+ Masks are entities that are always passed to the kernel as part of a |
3237 |
-+ match (with an item of type <constant>KDBUS_ITEM_BLOOM_MASK</constant>), |
3238 |
-+ and filters can be attached to signals, with an item of type |
3239 |
-+ <constant>KDBUS_ITEM_BLOOM_FILTER</constant>. For a filter to match, all |
3240 |
-+ its bits have to be set in the match mask as well. |
3241 |
-+ </para> |
3242 |
-+ <para> |
3243 |
-+ For example, consider a bus that has a bloom size of 8 bytes, and the |
3244 |
-+ following mask/filter combinations: |
3245 |
-+ </para> |
3246 |
-+ <programlisting><![CDATA[ |
3247 |
-+ filter 0x0101010101010101 |
3248 |
-+ mask 0x0101010101010101 |
3249 |
-+ -> matches |
3250 |
-+ |
3251 |
-+ filter 0x0303030303030303 |
3252 |
-+ mask 0x0101010101010101 |
3253 |
-+ -> doesn't match |
3254 |
-+ |
3255 |
-+ filter 0x0101010101010101 |
3256 |
-+ mask 0x0303030303030303 |
3257 |
-+ -> matches |
3258 |
-+ ]]></programlisting> |
3259 |
-+ |
3260 |
-+ <para> |
3261 |
-+ Hence, in order to catch all messages, a mask filled with |
3262 |
-+ <constant>0xff</constant> bytes can be installed as a wildcard match rule. |
3263 |
-+ </para> |
3264 |
-+ |
3265 |
-+ <refsect2> |
3266 |
-+ <title>Generations</title> |
3267 |
-+ |
3268 |
-+ <para> |
3269 |
-+ Uploaded matches may contain multiple masks, which have to be as large |
3270 |
-+ as the bloom filter size defined by the bus. Each block of a mask is |
3271 |
-+ called a <emphasis>generation</emphasis>, starting at index 0. |
3272 |
-+ |
3273 |
-+ At match time, when a signal is about to be delivered, a bloom mask |
3274 |
-+ generation is passed, which denotes which of the bloom masks the filter |
3275 |
-+ should be matched against. This allows programs to provide backward |
3276 |
-+ compatible masks at upload time, while older clients can still match |
3277 |
-+ against older versions of filters. |
3278 |
-+ </para> |
3279 |
-+ </refsect2> |
3280 |
-+ </refsect1> |
3281 |
-+ |
3282 |
-+ <refsect1> |
3283 |
-+ <title>Matches for kernel notifications</title> |
3284 |
-+ <para> |
3285 |
-+ To receive kernel generated notifications (see |
3286 |
-+ <citerefentry> |
3287 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3288 |
-+ <manvolnum>7</manvolnum> |
3289 |
-+ </citerefentry>), |
3290 |
-+ a connection must install match rules that are different from |
3291 |
-+ the bloom filter matches described in the section above. They can be |
3292 |
-+ filtered by the connection ID that caused the notification to be sent, by |
3293 |
-+ one of the names it currently owns, or by the type of the notification |
3294 |
-+ (ID/name add/remove/change). |
3295 |
-+ </para> |
3296 |
-+ </refsect1> |
3297 |
-+ |
3298 |
-+ <refsect1> |
3299 |
-+ <title>Adding a match</title> |
3300 |
-+ <para> |
3301 |
-+ To add a match, the <constant>KDBUS_CMD_MATCH_ADD</constant> ioctl is |
3302 |
-+ used, which takes a <type>struct kdbus_cmd_match</type> as an argument |
3303 |
-+ described below. |
3304 |
-+ |
3305 |
-+ Note that each of the items attached to this command will internally |
3306 |
-+ create one match <emphasis>rule</emphasis>, and the collection of them, |
3307 |
-+ which is submitted as one block via the ioctl, is called a |
3308 |
-+ <emphasis>match</emphasis>. To allow a message to pass, all rules of a |
3309 |
-+ match have to be satisfied. Hence, adding more items to the command will |
3310 |
-+ only narrow the possibility of a match to effectively let the message |
3311 |
-+ pass, and will decrease the chance that the connection's process will be |
3312 |
-+ woken up needlessly. |
3313 |
-+ |
3314 |
-+ Multiple matches can be installed per connection. As long as one of it has |
3315 |
-+ a set of rules which allows the message to pass, this one will be |
3316 |
-+ decisive. |
3317 |
-+ </para> |
3318 |
-+ |
3319 |
-+ <programlisting> |
3320 |
-+struct kdbus_cmd_match { |
3321 |
-+ __u64 size; |
3322 |
-+ __u64 flags; |
3323 |
-+ __u64 return_flags; |
3324 |
-+ __u64 cookie; |
3325 |
-+ struct kdbus_item items[0]; |
3326 |
-+}; |
3327 |
-+ </programlisting> |
3328 |
-+ |
3329 |
-+ <para>The fields in this struct are described below.</para> |
3330 |
-+ |
3331 |
-+ <variablelist> |
3332 |
-+ <varlistentry> |
3333 |
-+ <term><varname>size</varname></term> |
3334 |
-+ <listitem><para> |
3335 |
-+ The overall size of the struct, including its items. |
3336 |
-+ </para></listitem> |
3337 |
-+ </varlistentry> |
3338 |
-+ |
3339 |
-+ <varlistentry> |
3340 |
-+ <term><varname>flags</varname></term> |
3341 |
-+ <listitem><para>Flags to control the behavior of the ioctl.</para> |
3342 |
-+ <variablelist> |
3343 |
-+ <varlistentry> |
3344 |
-+ <term><constant>KDBUS_MATCH_REPLACE</constant></term> |
3345 |
-+ <listitem> |
3346 |
-+ <para>Make the endpoint file group-accessible</para> |
3347 |
-+ </listitem> |
3348 |
-+ </varlistentry> |
3349 |
-+ |
3350 |
-+ <varlistentry> |
3351 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
3352 |
-+ <listitem> |
3353 |
-+ <para> |
3354 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
3355 |
-+ set, no action is taken; the ioctl will return |
3356 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
3357 |
-+ field will have all bits set that are valid for this command. |
3358 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
3359 |
-+ cleared by the operation. |
3360 |
-+ </para> |
3361 |
-+ </listitem> |
3362 |
-+ </varlistentry> |
3363 |
-+ </variablelist> |
3364 |
-+ </listitem> |
3365 |
-+ </varlistentry> |
3366 |
-+ |
3367 |
-+ <varlistentry> |
3368 |
-+ <term><varname>return_flags</varname></term> |
3369 |
-+ <listitem><para> |
3370 |
-+ Flags returned by the kernel. Currently unused and always set to |
3371 |
-+ <constant>0</constant> by the kernel. |
3372 |
-+ </para></listitem> |
3373 |
-+ </varlistentry> |
3374 |
-+ |
3375 |
-+ <varlistentry> |
3376 |
-+ <term><varname>cookie</varname></term> |
3377 |
-+ <listitem><para> |
3378 |
-+ A cookie which identifies the match, so it can be referred to when |
3379 |
-+ removing it. |
3380 |
-+ </para></listitem> |
3381 |
-+ </varlistentry> |
3382 |
-+ |
3383 |
-+ <varlistentry> |
3384 |
-+ <term><varname>items</varname></term> |
3385 |
-+ <listitem> |
3386 |
-+ <para> |
3387 |
-+ Items to define the actual rules of the matches. The following item |
3388 |
-+ types are expected. Each item will create one new match rule. |
3389 |
-+ </para> |
3390 |
-+ <variablelist> |
3391 |
-+ <varlistentry> |
3392 |
-+ <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term> |
3393 |
-+ <listitem> |
3394 |
-+ <para> |
3395 |
-+ An item that carries the bloom filter mask to match against |
3396 |
-+ in its data field. The payload size must match the bloom |
3397 |
-+ filter size that was specified when the bus was created. |
3398 |
-+ See the "Bloom filters" section above for more information on |
3399 |
-+ bloom filters. |
3400 |
-+ </para> |
3401 |
-+ </listitem> |
3402 |
-+ </varlistentry> |
3403 |
-+ |
3404 |
-+ <varlistentry> |
3405 |
-+ <term><constant>KDBUS_ITEM_NAME</constant></term> |
3406 |
-+ <listitem> |
3407 |
-+ <para> |
3408 |
-+ When used as part of kernel notifications, this item specifies |
3409 |
-+ a name that is acquired, lost or that changed its owner (see |
3410 |
-+ below). When used as part of a match for user-generated signal |
3411 |
-+ messages, it specifies a name that the sending connection must |
3412 |
-+ own at the time of sending the signal. |
3413 |
-+ </para> |
3414 |
-+ </listitem> |
3415 |
-+ </varlistentry> |
3416 |
-+ |
3417 |
-+ <varlistentry> |
3418 |
-+ <term><constant>KDBUS_ITEM_ID</constant></term> |
3419 |
-+ <listitem> |
3420 |
-+ <para> |
3421 |
-+ Specify a sender connection's ID that will match this rule. |
3422 |
-+ For kernel notifications, this specifies the ID of a |
3423 |
-+ connection that was added to or removed from the bus. |
3424 |
-+ For used-generated signals, it specifies the ID of the |
3425 |
-+ connection that sent the signal message. |
3426 |
-+ </para> |
3427 |
-+ </listitem> |
3428 |
-+ </varlistentry> |
3429 |
-+ |
3430 |
-+ <varlistentry> |
3431 |
-+ <term><constant>KDBUS_ITEM_NAME_ADD</constant></term> |
3432 |
-+ <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term> |
3433 |
-+ <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term> |
3434 |
-+ <listitem> |
3435 |
-+ <para> |
3436 |
-+ These items request delivery of kernel notifications that |
3437 |
-+ describe a name acquisition, loss, or change. The details |
3438 |
-+ are stored in the item's |
3439 |
-+ <varname>kdbus_notify_name_change</varname> member. |
3440 |
-+ All information specified must be matched in order to make |
3441 |
-+ the message pass. Use |
3442 |
-+ <constant>KDBUS_MATCH_ID_ANY</constant> to |
3443 |
-+ match against any unique connection ID. |
3444 |
-+ </para> |
3445 |
-+ </listitem> |
3446 |
-+ </varlistentry> |
3447 |
-+ |
3448 |
-+ <varlistentry> |
3449 |
-+ <term><constant>KDBUS_ITEM_ID_ADD</constant></term> |
3450 |
-+ <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term> |
3451 |
-+ <listitem> |
3452 |
-+ <para> |
3453 |
-+ These items request delivery of kernel notifications that are |
3454 |
-+ generated when a connection is created or terminated. |
3455 |
-+ <type>struct kdbus_notify_id_change</type> is used to |
3456 |
-+ store the actual match information. This item can be used to |
3457 |
-+ monitor one particular connection ID, or, when the ID field |
3458 |
-+ is set to <constant>KDBUS_MATCH_ID_ANY</constant>, |
3459 |
-+ all of them. |
3460 |
-+ </para> |
3461 |
-+ </listitem> |
3462 |
-+ </varlistentry> |
3463 |
-+ |
3464 |
-+ <varlistentry> |
3465 |
-+ <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term> |
3466 |
-+ <listitem><para> |
3467 |
-+ With this item, programs can <emphasis>probe</emphasis> the |
3468 |
-+ kernel for known item types. See |
3469 |
-+ <citerefentry> |
3470 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
3471 |
-+ <manvolnum>7</manvolnum> |
3472 |
-+ </citerefentry> |
3473 |
-+ for more details. |
3474 |
-+ </para></listitem> |
3475 |
-+ </varlistentry> |
3476 |
-+ </variablelist> |
3477 |
-+ |
3478 |
-+ <para> |
3479 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
3480 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
3481 |
-+ </para> |
3482 |
-+ </listitem> |
3483 |
-+ </varlistentry> |
3484 |
-+ </variablelist> |
3485 |
-+ |
3486 |
-+ <para> |
3487 |
-+ Refer to |
3488 |
-+ <citerefentry> |
3489 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3490 |
-+ <manvolnum>7</manvolnum> |
3491 |
-+ </citerefentry> |
3492 |
-+ for more information on message types. |
3493 |
-+ </para> |
3494 |
-+ </refsect1> |
3495 |
-+ |
3496 |
-+ <refsect1> |
3497 |
-+ <title>Removing a match</title> |
3498 |
-+ <para> |
3499 |
-+ Matches can be removed with the |
3500 |
-+ <constant>KDBUS_CMD_MATCH_REMOVE</constant> ioctl, which takes |
3501 |
-+ <type>struct kdbus_cmd_match</type> as argument, but its fields |
3502 |
-+ usage slightly differs compared to that of |
3503 |
-+ <constant>KDBUS_CMD_MATCH_ADD</constant>. |
3504 |
-+ </para> |
3505 |
-+ |
3506 |
-+ <programlisting> |
3507 |
-+struct kdbus_cmd_match { |
3508 |
-+ __u64 size; |
3509 |
-+ __u64 cookie; |
3510 |
-+ __u64 flags; |
3511 |
-+ __u64 return_flags; |
3512 |
-+ struct kdbus_item items[0]; |
3513 |
-+}; |
3514 |
-+ </programlisting> |
3515 |
-+ |
3516 |
-+ <para>The fields in this struct are described below.</para> |
3517 |
-+ |
3518 |
-+ <variablelist> |
3519 |
-+ <varlistentry> |
3520 |
-+ <term><varname>size</varname></term> |
3521 |
-+ <listitem><para> |
3522 |
-+ The overall size of the struct, including its items. |
3523 |
-+ </para></listitem> |
3524 |
-+ </varlistentry> |
3525 |
-+ |
3526 |
-+ <varlistentry> |
3527 |
-+ <term><varname>cookie</varname></term> |
3528 |
-+ <listitem><para> |
3529 |
-+ The cookie of the match, as it was passed when the match was added. |
3530 |
-+ All matches that have this cookie will be removed. |
3531 |
-+ </para></listitem> |
3532 |
-+ </varlistentry> |
3533 |
-+ |
3534 |
-+ <varlistentry> |
3535 |
-+ <term><varname>flags</varname></term> |
3536 |
-+ <listitem><para> |
3537 |
-+ No flags are supported for this use case. |
3538 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
3539 |
-+ valid flags. If set, the ioctl will fail with |
3540 |
-+ <errorcode>-1</errorcode>, <varname>errno</varname> is set to |
3541 |
-+ <constant>EPROTO</constant>, and the <varname>flags</varname> field |
3542 |
-+ is set to <constant>0</constant>. |
3543 |
-+ </para></listitem> |
3544 |
-+ </varlistentry> |
3545 |
-+ |
3546 |
-+ <varlistentry> |
3547 |
-+ <term><varname>return_flags</varname></term> |
3548 |
-+ <listitem><para> |
3549 |
-+ Flags returned by the kernel. Currently unused and always set to |
3550 |
-+ <constant>0</constant> by the kernel. |
3551 |
-+ </para></listitem> |
3552 |
-+ </varlistentry> |
3553 |
-+ |
3554 |
-+ <varlistentry> |
3555 |
-+ <term><varname>items</varname></term> |
3556 |
-+ <listitem> |
3557 |
-+ <para> |
3558 |
-+ No items are supported for this use case, but |
3559 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed nevertheless. |
3560 |
-+ </para> |
3561 |
-+ </listitem> |
3562 |
-+ </varlistentry> |
3563 |
-+ </variablelist> |
3564 |
-+ </refsect1> |
3565 |
-+ |
3566 |
-+ <refsect1> |
3567 |
-+ <title>Return value</title> |
3568 |
-+ <para> |
3569 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
3570 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
3571 |
-+ <varname>errno</varname> is set to indicate the error. |
3572 |
-+ If the issued ioctl is illegal for the file descriptor used, |
3573 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
3574 |
-+ </para> |
3575 |
-+ |
3576 |
-+ <refsect2> |
3577 |
-+ <title> |
3578 |
-+ <constant>KDBUS_CMD_MATCH_ADD</constant> may fail with the following |
3579 |
-+ errors |
3580 |
-+ </title> |
3581 |
-+ |
3582 |
-+ <variablelist> |
3583 |
-+ <varlistentry> |
3584 |
-+ <term><constant>EINVAL</constant></term> |
3585 |
-+ <listitem><para> |
3586 |
-+ Illegal flags or items. |
3587 |
-+ </para></listitem> |
3588 |
-+ </varlistentry> |
3589 |
-+ |
3590 |
-+ <varlistentry> |
3591 |
-+ <term><constant>EDOM</constant></term> |
3592 |
-+ <listitem><para> |
3593 |
-+ Illegal bloom filter size. |
3594 |
-+ </para></listitem> |
3595 |
-+ </varlistentry> |
3596 |
-+ |
3597 |
-+ <varlistentry> |
3598 |
-+ <term><constant>EMFILE</constant></term> |
3599 |
-+ <listitem><para> |
3600 |
-+ Too many matches for this connection. |
3601 |
-+ </para></listitem> |
3602 |
-+ </varlistentry> |
3603 |
-+ </variablelist> |
3604 |
-+ </refsect2> |
3605 |
-+ |
3606 |
-+ <refsect2> |
3607 |
-+ <title> |
3608 |
-+ <constant>KDBUS_CMD_MATCH_REMOVE</constant> may fail with the following |
3609 |
-+ errors |
3610 |
-+ </title> |
3611 |
-+ |
3612 |
-+ <variablelist> |
3613 |
-+ <varlistentry> |
3614 |
-+ <term><constant>EINVAL</constant></term> |
3615 |
-+ <listitem><para> |
3616 |
-+ Illegal flags. |
3617 |
-+ </para></listitem> |
3618 |
-+ </varlistentry> |
3619 |
-+ |
3620 |
-+ <varlistentry> |
3621 |
-+ <term><constant>EBADSLT</constant></term> |
3622 |
-+ <listitem><para> |
3623 |
-+ A match entry with the given cookie could not be found. |
3624 |
-+ </para></listitem> |
3625 |
-+ </varlistentry> |
3626 |
-+ </variablelist> |
3627 |
-+ </refsect2> |
3628 |
-+ </refsect1> |
3629 |
-+ |
3630 |
-+ <refsect1> |
3631 |
-+ <title>See Also</title> |
3632 |
-+ <simplelist type="inline"> |
3633 |
-+ <member> |
3634 |
-+ <citerefentry> |
3635 |
-+ <refentrytitle>kdbus</refentrytitle> |
3636 |
-+ <manvolnum>7</manvolnum> |
3637 |
-+ </citerefentry> |
3638 |
-+ </member> |
3639 |
-+ <member> |
3640 |
-+ <citerefentry> |
3641 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
3642 |
-+ <manvolnum>7</manvolnum> |
3643 |
-+ </citerefentry> |
3644 |
-+ </member> |
3645 |
-+ <member> |
3646 |
-+ <citerefentry> |
3647 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
3648 |
-+ <manvolnum>7</manvolnum> |
3649 |
-+ </citerefentry> |
3650 |
-+ </member> |
3651 |
-+ <member> |
3652 |
-+ <citerefentry> |
3653 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
3654 |
-+ <manvolnum>7</manvolnum> |
3655 |
-+ </citerefentry> |
3656 |
-+ </member> |
3657 |
-+ <member> |
3658 |
-+ <citerefentry> |
3659 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
3660 |
-+ <manvolnum>7</manvolnum> |
3661 |
-+ </citerefentry> |
3662 |
-+ </member> |
3663 |
-+ <member> |
3664 |
-+ <citerefentry> |
3665 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3666 |
-+ <manvolnum>7</manvolnum> |
3667 |
-+ </citerefentry> |
3668 |
-+ </member> |
3669 |
-+ <member> |
3670 |
-+ <citerefentry> |
3671 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
3672 |
-+ <manvolnum>7</manvolnum> |
3673 |
-+ </citerefentry> |
3674 |
-+ </member> |
3675 |
-+ <member> |
3676 |
-+ <citerefentry> |
3677 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
3678 |
-+ <manvolnum>7</manvolnum> |
3679 |
-+ </citerefentry> |
3680 |
-+ </member> |
3681 |
-+ </simplelist> |
3682 |
-+ </refsect1> |
3683 |
-+</refentry> |
3684 |
-diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml |
3685 |
-new file mode 100644 |
3686 |
-index 0000000..0115d9d |
3687 |
---- /dev/null |
3688 |
-+++ b/Documentation/kdbus/kdbus.message.xml |
3689 |
-@@ -0,0 +1,1276 @@ |
3690 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
3691 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
3692 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
3693 |
-+ |
3694 |
-+<refentry id="kdbus.message"> |
3695 |
-+ |
3696 |
-+ <refentryinfo> |
3697 |
-+ <title>kdbus.message</title> |
3698 |
-+ <productname>kdbus.message</productname> |
3699 |
-+ </refentryinfo> |
3700 |
-+ |
3701 |
-+ <refmeta> |
3702 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
3703 |
-+ <manvolnum>7</manvolnum> |
3704 |
-+ </refmeta> |
3705 |
-+ |
3706 |
-+ <refnamediv> |
3707 |
-+ <refname>kdbus.message</refname> |
3708 |
-+ <refpurpose>kdbus message</refpurpose> |
3709 |
-+ </refnamediv> |
3710 |
-+ |
3711 |
-+ <refsect1> |
3712 |
-+ <title>Description</title> |
3713 |
-+ |
3714 |
-+ <para> |
3715 |
-+ A kdbus message is used to exchange information between two connections |
3716 |
-+ on a bus, or to transport notifications from the kernel to one or many |
3717 |
-+ connections. This document describes the layout of messages, how payload |
3718 |
-+ is added to them and how they are sent and received. |
3719 |
-+ </para> |
3720 |
-+ </refsect1> |
3721 |
-+ |
3722 |
-+ <refsect1> |
3723 |
-+ <title>Message layout</title> |
3724 |
-+ |
3725 |
-+ <para>The layout of a message is shown below.</para> |
3726 |
-+ |
3727 |
-+ <programlisting> |
3728 |
-+ +-------------------------------------------------------------------------+ |
3729 |
-+ | Message | |
3730 |
-+ | +---------------------------------------------------------------------+ | |
3731 |
-+ | | Header | | |
3732 |
-+ | | size: overall message size, including the data records | | |
3733 |
-+ | | destination: connection ID of the receiver | | |
3734 |
-+ | | source: connection ID of the sender (set by kernel) | | |
3735 |
-+ | | payload_type: "DBusDBus" textual identifier stored as uint64_t | | |
3736 |
-+ | +---------------------------------------------------------------------+ | |
3737 |
-+ | +---------------------------------------------------------------------+ | |
3738 |
-+ | | Data Record | | |
3739 |
-+ | | size: overall record size (without padding) | | |
3740 |
-+ | | type: type of data | | |
3741 |
-+ | | data: reference to data (address or file descriptor) | | |
3742 |
-+ | +---------------------------------------------------------------------+ | |
3743 |
-+ | +---------------------------------------------------------------------+ | |
3744 |
-+ | | padding bytes to the next 8 byte alignment | | |
3745 |
-+ | +---------------------------------------------------------------------+ | |
3746 |
-+ | +---------------------------------------------------------------------+ | |
3747 |
-+ | | Data Record | | |
3748 |
-+ | | size: overall record size (without padding) | | |
3749 |
-+ | | ... | | |
3750 |
-+ | +---------------------------------------------------------------------+ | |
3751 |
-+ | +---------------------------------------------------------------------+ | |
3752 |
-+ | | padding bytes to the next 8 byte alignment | | |
3753 |
-+ | +---------------------------------------------------------------------+ | |
3754 |
-+ | +---------------------------------------------------------------------+ | |
3755 |
-+ | | Data Record | | |
3756 |
-+ | | size: overall record size | | |
3757 |
-+ | | ... | | |
3758 |
-+ | +---------------------------------------------------------------------+ | |
3759 |
-+ | ... further data records ... | |
3760 |
-+ +-------------------------------------------------------------------------+ |
3761 |
-+ </programlisting> |
3762 |
-+ </refsect1> |
3763 |
-+ |
3764 |
-+ <refsect1> |
3765 |
-+ <title>Message payload</title> |
3766 |
-+ |
3767 |
-+ <para> |
3768 |
-+ When connecting to the bus, receivers request a memory pool of a given |
3769 |
-+ size, large enough to carry all backlog of data enqueued for the |
3770 |
-+ connection. The pool is internally backed by a shared memory file which |
3771 |
-+ can be <function>mmap()</function>ed by the receiver. See |
3772 |
-+ <citerefentry> |
3773 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
3774 |
-+ <manvolnum>7</manvolnum> |
3775 |
-+ </citerefentry> |
3776 |
-+ for more information. |
3777 |
-+ </para> |
3778 |
-+ |
3779 |
-+ <para> |
3780 |
-+ Message payload must be described in items attached to a message when |
3781 |
-+ it is sent. A receiver can access the payload by looking at the items |
3782 |
-+ that are attached to a message in its pool. The following items are used. |
3783 |
-+ </para> |
3784 |
-+ |
3785 |
-+ <variablelist> |
3786 |
-+ <varlistentry> |
3787 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
3788 |
-+ <listitem> |
3789 |
-+ <para> |
3790 |
-+ This item references a piece of memory on the sender side which is |
3791 |
-+ directly copied into the receiver's pool. This way, two peers can |
3792 |
-+ exchange data by effectively doing a single-copy from one process |
3793 |
-+ to another; the kernel will not buffer the data anywhere else. |
3794 |
-+ This item is never found in a message received by a connection. |
3795 |
-+ </para> |
3796 |
-+ </listitem> |
3797 |
-+ </varlistentry> |
3798 |
-+ |
3799 |
-+ <varlistentry> |
3800 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term> |
3801 |
-+ <listitem> |
3802 |
-+ <para> |
3803 |
-+ This item is attached to messages on the receiving side and points |
3804 |
-+ to a memory area inside the receiver's pool. The |
3805 |
-+ <varname>offset</varname> variable in the item denotes the memory |
3806 |
-+ location relative to the message itself. |
3807 |
-+ </para> |
3808 |
-+ </listitem> |
3809 |
-+ </varlistentry> |
3810 |
-+ |
3811 |
-+ <varlistentry> |
3812 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
3813 |
-+ <listitem> |
3814 |
-+ <para> |
3815 |
-+ Messages can reference <emphasis>memfd</emphasis> files which |
3816 |
-+ contain the data. memfd files are tmpfs-backed files that allow |
3817 |
-+ sealing of the content of the file, which prevents all writable |
3818 |
-+ access to the file content. |
3819 |
-+ </para> |
3820 |
-+ <para> |
3821 |
-+ Only memfds that have |
3822 |
-+ <constant>(F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_SEAL) |
3823 |
-+ </constant> |
3824 |
-+ set are accepted as payload data, which enforces reliable passing of |
3825 |
-+ data. The receiver can assume that neither the sender nor anyone |
3826 |
-+ else can alter the content after the message is sent. If those |
3827 |
-+ seals are not set on the memfd, the ioctl will fail with |
3828 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> will be |
3829 |
-+ set to <constant>ETXTBUSY</constant>. |
3830 |
-+ </para> |
3831 |
-+ </listitem> |
3832 |
-+ </varlistentry> |
3833 |
-+ |
3834 |
-+ <varlistentry> |
3835 |
-+ <term><constant>KDBUS_ITEM_FDS</constant></term> |
3836 |
-+ <listitem> |
3837 |
-+ <para> |
3838 |
-+ Messages can transport regular file descriptors via |
3839 |
-+ <constant>KDBUS_ITEM_FDS</constant>. This item carries an array |
3840 |
-+ of <type>int</type> values in <varname>item.fd</varname>. The |
3841 |
-+ maximum number of file descriptors in the item is |
3842 |
-+ <constant>253</constant>, and only one item of this type is |
3843 |
-+ accepted per message. All passed values must be valid file |
3844 |
-+ descriptors; the open count of each file descriptors is increased |
3845 |
-+ by installing it to the receiver's task. This item can only be |
3846 |
-+ used for directed messages, not for broadcasts, and only to |
3847 |
-+ remote peers that have opted-in for receiving file descriptors |
3848 |
-+ at connection time (<constant>KDBUS_HELLO_ACCEPT_FD</constant>). |
3849 |
-+ </para> |
3850 |
-+ </listitem> |
3851 |
-+ </varlistentry> |
3852 |
-+ </variablelist> |
3853 |
-+ |
3854 |
-+ <para> |
3855 |
-+ The sender must not make any assumptions on the type in which data is |
3856 |
-+ received by the remote peer. The kernel is free to re-pack multiple |
3857 |
-+ <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> and |
3858 |
-+ <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> payloads. For instance, the |
3859 |
-+ kernel may decide to merge multiple <constant>VECs</constant> into a |
3860 |
-+ single <constant>VEC</constant>, inline <constant>MEMFD</constant> |
3861 |
-+ payloads into memory, or merge all passed <constant>VECs</constant> into a |
3862 |
-+ single <constant>MEMFD</constant>. However, the kernel preserves the order |
3863 |
-+ of passed data. This means that the order of all <constant>VEC</constant> |
3864 |
-+ and <constant>MEMFD</constant> items is not changed in respect to each |
3865 |
-+ other. In other words: All passed <constant>VEC</constant> and |
3866 |
-+ <constant>MEMFD</constant> data payloads are treated as a single stream |
3867 |
-+ of data that may be received by the remote peer in a different set of |
3868 |
-+ chunks than it was sent as. |
3869 |
-+ </para> |
3870 |
-+ </refsect1> |
3871 |
-+ |
3872 |
-+ <refsect1> |
3873 |
-+ <title>Sending messages</title> |
3874 |
-+ |
3875 |
-+ <para> |
3876 |
-+ Messages are passed to the kernel with the |
3877 |
-+ <constant>KDBUS_CMD_SEND</constant> ioctl. Depending on the destination |
3878 |
-+ address of the message, the kernel delivers the message to the specific |
3879 |
-+ destination connection, or to some subset of all connections on the same |
3880 |
-+ bus. Sending messages across buses is not possible. Messages are always |
3881 |
-+ queued in the memory pool of the destination connection (see above). |
3882 |
-+ </para> |
3883 |
-+ |
3884 |
-+ <para> |
3885 |
-+ The <constant>KDBUS_CMD_SEND</constant> ioctl uses a |
3886 |
-+ <type>struct kdbus_cmd_send</type> to describe the message |
3887 |
-+ transfer. |
3888 |
-+ </para> |
3889 |
-+ <programlisting> |
3890 |
-+struct kdbus_cmd_send { |
3891 |
-+ __u64 size; |
3892 |
-+ __u64 flags; |
3893 |
-+ __u64 return_flags; |
3894 |
-+ __u64 msg_address; |
3895 |
-+ struct kdbus_msg_info reply; |
3896 |
-+ struct kdbus_item items[0]; |
3897 |
-+}; |
3898 |
-+ </programlisting> |
3899 |
-+ |
3900 |
-+ <para>The fields in this struct are described below.</para> |
3901 |
-+ |
3902 |
-+ <variablelist> |
3903 |
-+ <varlistentry> |
3904 |
-+ <term><varname>size</varname></term> |
3905 |
-+ <listitem><para> |
3906 |
-+ The overall size of the struct, including its items. |
3907 |
-+ </para></listitem> |
3908 |
-+ </varlistentry> |
3909 |
-+ |
3910 |
-+ <varlistentry> |
3911 |
-+ <term><varname>flags</varname></term> |
3912 |
-+ <listitem><para>Flags for message delivery</para> |
3913 |
-+ <variablelist> |
3914 |
-+ <varlistentry> |
3915 |
-+ <term><constant>KDBUS_SEND_SYNC_REPLY</constant></term> |
3916 |
-+ <listitem> |
3917 |
-+ <para> |
3918 |
-+ By default, all calls to kdbus are considered asynchronous, |
3919 |
-+ non-blocking. However, as there are many use cases that need |
3920 |
-+ to wait for a remote peer to answer a method call, there's a |
3921 |
-+ way to send a message and wait for a reply in a synchronous |
3922 |
-+ fashion. This is what the |
3923 |
-+ <constant>KDBUS_SEND_SYNC_REPLY</constant> controls. The |
3924 |
-+ <constant>KDBUS_CMD_SEND</constant> ioctl will block until the |
3925 |
-+ reply has arrived, the timeout limit is reached, in case the |
3926 |
-+ remote connection was shut down, or if interrupted by a signal |
3927 |
-+ before any reply; see |
3928 |
-+ <citerefentry> |
3929 |
-+ <refentrytitle>signal</refentrytitle> |
3930 |
-+ <manvolnum>7</manvolnum> |
3931 |
-+ </citerefentry>. |
3932 |
-+ |
3933 |
-+ The offset of the reply message in the sender's pool is stored |
3934 |
-+ in <varname>reply</varname> when the ioctl has returned without |
3935 |
-+ error. Hence, there is no need for another |
3936 |
-+ <constant>KDBUS_CMD_RECV</constant> ioctl or anything else to |
3937 |
-+ receive the reply. |
3938 |
-+ </para> |
3939 |
-+ </listitem> |
3940 |
-+ </varlistentry> |
3941 |
-+ |
3942 |
-+ <varlistentry> |
3943 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
3944 |
-+ <listitem> |
3945 |
-+ <para> |
3946 |
-+ Request a set of valid flags for this ioctl. When this bit is |
3947 |
-+ set, no action is taken; the ioctl will fail with |
3948 |
-+ <errorcode>-1</errorcode>, <varname>errno</varname> |
3949 |
-+ is set to <constant>EPROTO</constant>. |
3950 |
-+ Once the ioctl returned, the <varname>flags</varname> |
3951 |
-+ field will have all bits set that the kernel recognizes as |
3952 |
-+ valid for this command. |
3953 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
3954 |
-+ cleared by the operation. |
3955 |
-+ </para> |
3956 |
-+ </listitem> |
3957 |
-+ </varlistentry> |
3958 |
-+ </variablelist> |
3959 |
-+ </listitem> |
3960 |
-+ </varlistentry> |
3961 |
-+ |
3962 |
-+ <varlistentry> |
3963 |
-+ <term><varname>return_flags</varname></term> |
3964 |
-+ <listitem><para> |
3965 |
-+ Flags returned by the kernel. Currently unused and always set to |
3966 |
-+ <constant>0</constant> by the kernel. |
3967 |
-+ </para></listitem> |
3968 |
-+ </varlistentry> |
3969 |
-+ |
3970 |
-+ <varlistentry> |
3971 |
-+ <term><varname>msg_address</varname></term> |
3972 |
-+ <listitem><para> |
3973 |
-+ In this field, users have to provide a pointer to a message |
3974 |
-+ (<type>struct kdbus_msg</type>) to send. See below for a |
3975 |
-+ detailed description. |
3976 |
-+ </para></listitem> |
3977 |
-+ </varlistentry> |
3978 |
-+ |
3979 |
-+ <varlistentry> |
3980 |
-+ <term><varname>reply</varname></term> |
3981 |
-+ <listitem><para> |
3982 |
-+ Only used for synchronous replies. See description of |
3983 |
-+ <type>struct kdbus_cmd_recv</type> for more details. |
3984 |
-+ </para></listitem> |
3985 |
-+ </varlistentry> |
3986 |
-+ |
3987 |
-+ <varlistentry> |
3988 |
-+ <term><varname>items</varname></term> |
3989 |
-+ <listitem> |
3990 |
-+ <para> |
3991 |
-+ The following items are currently recognized. |
3992 |
-+ </para> |
3993 |
-+ <variablelist> |
3994 |
-+ <varlistentry> |
3995 |
-+ <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term> |
3996 |
-+ <listitem> |
3997 |
-+ <para> |
3998 |
-+ When this optional item is passed in, and the call is |
3999 |
-+ executed as SYNC call, the passed in file descriptor can be |
4000 |
-+ used as alternative cancellation point. The kernel will call |
4001 |
-+ <citerefentry> |
4002 |
-+ <refentrytitle>poll</refentrytitle> |
4003 |
-+ <manvolnum>2</manvolnum> |
4004 |
-+ </citerefentry> |
4005 |
-+ on this file descriptor, and once it reports any incoming |
4006 |
-+ bytes, the blocking send operation will be canceled; the |
4007 |
-+ blocking, synchronous ioctl call will return |
4008 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> will |
4009 |
-+ be set to <errorname>ECANCELED</errorname>. |
4010 |
-+ Any type of file descriptor on which |
4011 |
-+ <citerefentry> |
4012 |
-+ <refentrytitle>poll</refentrytitle> |
4013 |
-+ <manvolnum>2</manvolnum> |
4014 |
-+ </citerefentry> |
4015 |
-+ can be called on can be used as payload to this item; for |
4016 |
-+ example, an eventfd can be used for this purpose, see |
4017 |
-+ <citerefentry> |
4018 |
-+ <refentrytitle>eventfd</refentrytitle> |
4019 |
-+ <manvolnum>2</manvolnum> |
4020 |
-+ </citerefentry>. |
4021 |
-+ For asynchronous message sending, this item is allowed but |
4022 |
-+ ignored. |
4023 |
-+ </para> |
4024 |
-+ </listitem> |
4025 |
-+ </varlistentry> |
4026 |
-+ </variablelist> |
4027 |
-+ <para> |
4028 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
4029 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
4030 |
-+ </para> |
4031 |
-+ </listitem> |
4032 |
-+ </varlistentry> |
4033 |
-+ </variablelist> |
4034 |
-+ |
4035 |
-+ <para> |
4036 |
-+ The message referenced by the <varname>msg_address</varname> above has |
4037 |
-+ the following layout. |
4038 |
-+ </para> |
4039 |
-+ |
4040 |
-+ <programlisting> |
4041 |
-+struct kdbus_msg { |
4042 |
-+ __u64 size; |
4043 |
-+ __u64 flags; |
4044 |
-+ __s64 priority; |
4045 |
-+ __u64 dst_id; |
4046 |
-+ __u64 src_id; |
4047 |
-+ __u64 payload_type; |
4048 |
-+ __u64 cookie; |
4049 |
-+ __u64 timeout_ns; |
4050 |
-+ __u64 cookie_reply; |
4051 |
-+ struct kdbus_item items[0]; |
4052 |
-+}; |
4053 |
-+ </programlisting> |
4054 |
-+ |
4055 |
-+ <para>The fields in this struct are described below.</para> |
4056 |
-+ |
4057 |
-+ <variablelist> |
4058 |
-+ <varlistentry> |
4059 |
-+ <term><varname>size</varname></term> |
4060 |
-+ <listitem><para> |
4061 |
-+ The overall size of the struct, including its items. |
4062 |
-+ </para></listitem> |
4063 |
-+ </varlistentry> |
4064 |
-+ |
4065 |
-+ <varlistentry> |
4066 |
-+ <term><varname>flags</varname></term> |
4067 |
-+ <listitem><para>Flags to describe message details.</para> |
4068 |
-+ <variablelist> |
4069 |
-+ <varlistentry> |
4070 |
-+ <term><constant>KDBUS_MSG_EXPECT_REPLY</constant></term> |
4071 |
-+ <listitem> |
4072 |
-+ <para> |
4073 |
-+ Expect a reply to this message from the remote peer. With |
4074 |
-+ this bit set, the timeout_ns field must be set to a non-zero |
4075 |
-+ number of nanoseconds in which the receiving peer is expected |
4076 |
-+ to reply. If such a reply is not received in time, the sender |
4077 |
-+ will be notified with a timeout message (see below). The |
4078 |
-+ value must be an absolute value, in nanoseconds and based on |
4079 |
-+ <constant>CLOCK_MONOTONIC</constant>. |
4080 |
-+ </para><para> |
4081 |
-+ For a message to be accepted as reply, it must be a direct |
4082 |
-+ message to the original sender (not a broadcast and not a |
4083 |
-+ signal message), and its |
4084 |
-+ <varname>kdbus_msg.cookie_reply</varname> must match the |
4085 |
-+ previous message's <varname>kdbus_msg.cookie</varname>. |
4086 |
-+ </para><para> |
4087 |
-+ Expected replies also temporarily open the policy of the |
4088 |
-+ sending connection, so the other peer is allowed to respond |
4089 |
-+ within the given time window. |
4090 |
-+ </para> |
4091 |
-+ </listitem> |
4092 |
-+ </varlistentry> |
4093 |
-+ |
4094 |
-+ <varlistentry> |
4095 |
-+ <term><constant>KDBUS_MSG_NO_AUTO_START</constant></term> |
4096 |
-+ <listitem> |
4097 |
-+ <para> |
4098 |
-+ By default, when a message is sent to an activator |
4099 |
-+ connection, the activator is notified and will start an |
4100 |
-+ implementer. This flag inhibits that behavior. With this bit |
4101 |
-+ set, and the remote being an activator, the ioctl will fail |
4102 |
-+ with <varname>errno</varname> set to |
4103 |
-+ <constant>EADDRNOTAVAIL</constant>. |
4104 |
-+ </para> |
4105 |
-+ </listitem> |
4106 |
-+ </varlistentry> |
4107 |
-+ |
4108 |
-+ <varlistentry> |
4109 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
4110 |
-+ <listitem> |
4111 |
-+ <para> |
4112 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
4113 |
-+ set, no action is taken; the ioctl will return |
4114 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
4115 |
-+ field will have all bits set that are valid for this command. |
4116 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
4117 |
-+ cleared by the operation. |
4118 |
-+ </para> |
4119 |
-+ </listitem> |
4120 |
-+ </varlistentry> |
4121 |
-+ </variablelist> |
4122 |
-+ </listitem> |
4123 |
-+ </varlistentry> |
4124 |
-+ |
4125 |
-+ <varlistentry> |
4126 |
-+ <term><varname>priority</varname></term> |
4127 |
-+ <listitem><para> |
4128 |
-+ The priority of this message. Receiving messages (see below) may |
4129 |
-+ optionally be constrained to messages of a minimal priority. This |
4130 |
-+ allows for use cases where timing critical data is interleaved with |
4131 |
-+ control data on the same connection. If unused, the priority field |
4132 |
-+ should be set to <constant>0</constant>. |
4133 |
-+ </para></listitem> |
4134 |
-+ </varlistentry> |
4135 |
-+ |
4136 |
-+ <varlistentry> |
4137 |
-+ <term><varname>dst_id</varname></term> |
4138 |
-+ <listitem><para> |
4139 |
-+ The numeric ID of the destination connection, or |
4140 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> |
4141 |
-+ (~0ULL) to address every peer on the bus, or |
4142 |
-+ <constant>KDBUS_DST_ID_NAME</constant> (0) to look |
4143 |
-+ it up dynamically from the bus' name registry. |
4144 |
-+ In the latter case, an item of type |
4145 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> is mandatory. |
4146 |
-+ Also see |
4147 |
-+ <citerefentry> |
4148 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
4149 |
-+ <manvolnum>7</manvolnum> |
4150 |
-+ </citerefentry> |
4151 |
-+ . |
4152 |
-+ </para></listitem> |
4153 |
-+ </varlistentry> |
4154 |
-+ |
4155 |
-+ <varlistentry> |
4156 |
-+ <term><varname>src_id</varname></term> |
4157 |
-+ <listitem><para> |
4158 |
-+ Upon return of the ioctl, this member will contain the sending |
4159 |
-+ connection's numerical ID. Should be 0 at send time. |
4160 |
-+ </para></listitem> |
4161 |
-+ </varlistentry> |
4162 |
-+ |
4163 |
-+ <varlistentry> |
4164 |
-+ <term><varname>payload_type</varname></term> |
4165 |
-+ <listitem><para> |
4166 |
-+ Type of the payload in the actual data records. Currently, only |
4167 |
-+ <constant>KDBUS_PAYLOAD_DBUS</constant> is accepted as input value |
4168 |
-+ of this field. When receiving messages that are generated by the |
4169 |
-+ kernel (notifications), this field will contain |
4170 |
-+ <constant>KDBUS_PAYLOAD_KERNEL</constant>. |
4171 |
-+ </para></listitem> |
4172 |
-+ </varlistentry> |
4173 |
-+ |
4174 |
-+ <varlistentry> |
4175 |
-+ <term><varname>cookie</varname></term> |
4176 |
-+ <listitem><para> |
4177 |
-+ Cookie of this message, for later recognition. Also, when replying |
4178 |
-+ to a message (see above), the <varname>cookie_reply</varname> |
4179 |
-+ field must match this value. |
4180 |
-+ </para></listitem> |
4181 |
-+ </varlistentry> |
4182 |
-+ |
4183 |
-+ <varlistentry> |
4184 |
-+ <term><varname>timeout_ns</varname></term> |
4185 |
-+ <listitem><para> |
4186 |
-+ If the message sent requires a reply from the remote peer (see above), |
4187 |
-+ this field contains the timeout in absolute nanoseconds based on |
4188 |
-+ <constant>CLOCK_MONOTONIC</constant>. Also see |
4189 |
-+ <citerefentry> |
4190 |
-+ <refentrytitle>clock_gettime</refentrytitle> |
4191 |
-+ <manvolnum>2</manvolnum> |
4192 |
-+ </citerefentry>. |
4193 |
-+ </para></listitem> |
4194 |
-+ </varlistentry> |
4195 |
-+ |
4196 |
-+ <varlistentry> |
4197 |
-+ <term><varname>cookie_reply</varname></term> |
4198 |
-+ <listitem><para> |
4199 |
-+ If the message sent is a reply to another message, this field must |
4200 |
-+ match the cookie of the formerly received message. |
4201 |
-+ </para></listitem> |
4202 |
-+ </varlistentry> |
4203 |
-+ |
4204 |
-+ <varlistentry> |
4205 |
-+ <term><varname>items</varname></term> |
4206 |
-+ <listitem> |
4207 |
-+ <para> |
4208 |
-+ A dynamically sized list of items to contain additional information. |
4209 |
-+ The following items are expected/valid: |
4210 |
-+ </para> |
4211 |
-+ <variablelist> |
4212 |
-+ <varlistentry> |
4213 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term> |
4214 |
-+ <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term> |
4215 |
-+ <term><constant>KDBUS_ITEM_FDS</constant></term> |
4216 |
-+ <listitem> |
4217 |
-+ <para> |
4218 |
-+ Actual data records containing the payload. See section |
4219 |
-+ "Message payload". |
4220 |
-+ </para> |
4221 |
-+ </listitem> |
4222 |
-+ </varlistentry> |
4223 |
-+ |
4224 |
-+ <varlistentry> |
4225 |
-+ <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term> |
4226 |
-+ <listitem> |
4227 |
-+ <para> |
4228 |
-+ Bloom filter for matches (see below). |
4229 |
-+ </para> |
4230 |
-+ </listitem> |
4231 |
-+ </varlistentry> |
4232 |
-+ |
4233 |
-+ <varlistentry> |
4234 |
-+ <term><constant>KDBUS_ITEM_DST_NAME</constant></term> |
4235 |
-+ <listitem> |
4236 |
-+ <para> |
4237 |
-+ Well-known name to send this message to. Required if |
4238 |
-+ <varname>dst_id</varname> is set to |
4239 |
-+ <constant>KDBUS_DST_ID_NAME</constant>. |
4240 |
-+ If a connection holding the given name can't be found, |
4241 |
-+ the ioctl will fail with <varname>errno</varname> set to |
4242 |
-+ <constant>ESRCH</constant> is returned. |
4243 |
-+ </para> |
4244 |
-+ <para> |
4245 |
-+ For messages to a unique name (ID), this item is optional. If |
4246 |
-+ present, the kernel will make sure the name owner matches the |
4247 |
-+ given unique name. This allows programs to tie the message |
4248 |
-+ sending to the condition that a name is currently owned by a |
4249 |
-+ certain unique name. |
4250 |
-+ </para> |
4251 |
-+ </listitem> |
4252 |
-+ </varlistentry> |
4253 |
-+ </variablelist> |
4254 |
-+ </listitem> |
4255 |
-+ </varlistentry> |
4256 |
-+ </variablelist> |
4257 |
-+ |
4258 |
-+ <para> |
4259 |
-+ The message will be augmented by the requested metadata items when |
4260 |
-+ queued into the receiver's pool. See |
4261 |
-+ <citerefentry> |
4262 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
4263 |
-+ <manvolnum>7</manvolnum> |
4264 |
-+ </citerefentry> |
4265 |
-+ and |
4266 |
-+ <citerefentry> |
4267 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
4268 |
-+ <manvolnum>7</manvolnum> |
4269 |
-+ </citerefentry> |
4270 |
-+ for more information on metadata. |
4271 |
-+ </para> |
4272 |
-+ </refsect1> |
4273 |
-+ |
4274 |
-+ <refsect1> |
4275 |
-+ <title>Receiving messages</title> |
4276 |
-+ |
4277 |
-+ <para> |
4278 |
-+ Messages are received by the client with the |
4279 |
-+ <constant>KDBUS_CMD_RECV</constant> ioctl. The endpoint file of the bus |
4280 |
-+ supports <function>poll()/epoll()/select()</function>; when new messages |
4281 |
-+ are available on the connection's file descriptor, |
4282 |
-+ <constant>POLLIN</constant> is reported. For compatibility reasons, |
4283 |
-+ <constant>POLLOUT</constant> is always reported as well. Note, however, |
4284 |
-+ that the latter does not guarantee that a message can in fact be sent, as |
4285 |
-+ this depends on how many pending messages the receiver has in its pool. |
4286 |
-+ </para> |
4287 |
-+ |
4288 |
-+ <para> |
4289 |
-+ With the <constant>KDBUS_CMD_RECV</constant> ioctl, a |
4290 |
-+ <type>struct kdbus_cmd_recv</type> is used. |
4291 |
-+ </para> |
4292 |
-+ |
4293 |
-+ <programlisting> |
4294 |
-+struct kdbus_cmd_recv { |
4295 |
-+ __u64 size; |
4296 |
-+ __u64 flags; |
4297 |
-+ __u64 return_flags; |
4298 |
-+ __s64 priority; |
4299 |
-+ __u64 dropped_msgs; |
4300 |
-+ struct kdbus_msg_info msg; |
4301 |
-+ struct kdbus_item items[0]; |
4302 |
-+}; |
4303 |
-+ </programlisting> |
4304 |
-+ |
4305 |
-+ <para>The fields in this struct are described below.</para> |
4306 |
-+ |
4307 |
-+ <variablelist> |
4308 |
-+ <varlistentry> |
4309 |
-+ <term><varname>size</varname></term> |
4310 |
-+ <listitem><para> |
4311 |
-+ The overall size of the struct, including its items. |
4312 |
-+ </para></listitem> |
4313 |
-+ </varlistentry> |
4314 |
-+ |
4315 |
-+ <varlistentry> |
4316 |
-+ <term><varname>flags</varname></term> |
4317 |
-+ <listitem><para>Flags to control the receive command.</para> |
4318 |
-+ <variablelist> |
4319 |
-+ <varlistentry> |
4320 |
-+ <term><constant>KDBUS_RECV_PEEK</constant></term> |
4321 |
-+ <listitem> |
4322 |
-+ <para> |
4323 |
-+ Just return the location of the next message. Do not install |
4324 |
-+ file descriptors or anything else. This is usually used to |
4325 |
-+ determine the sender of the next queued message. |
4326 |
-+ </para> |
4327 |
-+ </listitem> |
4328 |
-+ </varlistentry> |
4329 |
-+ |
4330 |
-+ <varlistentry> |
4331 |
-+ <term><constant>KDBUS_RECV_DROP</constant></term> |
4332 |
-+ <listitem> |
4333 |
-+ <para> |
4334 |
-+ Drop the next message without doing anything else with it, |
4335 |
-+ and free the pool slice. This a short-cut for |
4336 |
-+ <constant>KDBUS_RECV_PEEK</constant> and |
4337 |
-+ <constant>KDBUS_CMD_FREE</constant>. |
4338 |
-+ </para> |
4339 |
-+ </listitem> |
4340 |
-+ </varlistentry> |
4341 |
-+ |
4342 |
-+ <varlistentry> |
4343 |
-+ <term><constant>KDBUS_RECV_USE_PRIORITY</constant></term> |
4344 |
-+ <listitem> |
4345 |
-+ <para> |
4346 |
-+ Dequeue the messages ordered by their priority, and filtering |
4347 |
-+ them with the priority field (see below). |
4348 |
-+ </para> |
4349 |
-+ </listitem> |
4350 |
-+ </varlistentry> |
4351 |
-+ |
4352 |
-+ <varlistentry> |
4353 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
4354 |
-+ <listitem> |
4355 |
-+ <para> |
4356 |
-+ Request a set of valid flags for this ioctl. When this bit is |
4357 |
-+ set, no action is taken; the ioctl will fail with |
4358 |
-+ <errorcode>-1</errorcode>, <varname>errno</varname> |
4359 |
-+ is set to <constant>EPROTO</constant>. |
4360 |
-+ Once the ioctl returned, the <varname>flags</varname> |
4361 |
-+ field will have all bits set that the kernel recognizes as |
4362 |
-+ valid for this command. |
4363 |
-+ </para> |
4364 |
-+ </listitem> |
4365 |
-+ </varlistentry> |
4366 |
-+ </variablelist> |
4367 |
-+ </listitem> |
4368 |
-+ </varlistentry> |
4369 |
-+ |
4370 |
-+ <varlistentry> |
4371 |
-+ <term><varname>return_flags</varname></term> |
4372 |
-+ <listitem><para> |
4373 |
-+ Flags returned by the kernel. If the <varname>dropped_msgs</varname> |
4374 |
-+ field is non-zero, <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> |
4375 |
-+ is set. If a file descriptor could not be installed, the |
4376 |
-+ <constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant> flag is set. |
4377 |
-+ </para></listitem> |
4378 |
-+ </varlistentry> |
4379 |
-+ |
4380 |
-+ <varlistentry> |
4381 |
-+ <term><varname>priority</varname></term> |
4382 |
-+ <listitem><para> |
4383 |
-+ With <constant>KDBUS_RECV_USE_PRIORITY</constant> set in |
4384 |
-+ <varname>flags</varname>, messages will be dequeued ordered by their |
4385 |
-+ priority, starting with the highest value. Also, messages will be |
4386 |
-+ filtered by the value given in this field, so the returned message |
4387 |
-+ will at least have the requested priority. If no such message is |
4388 |
-+ waiting in the queue, the ioctl will fail, and |
4389 |
-+ <varname>errno</varname> will be set to <constant>EAGAIN</constant>. |
4390 |
-+ </para></listitem> |
4391 |
-+ </varlistentry> |
4392 |
-+ |
4393 |
-+ <varlistentry> |
4394 |
-+ <term><varname>dropped_msgs</varname></term> |
4395 |
-+ <listitem><para> |
4396 |
-+ Whenever a message with <constant>KDBUS_MSG_SIGNAL</constant> is sent |
4397 |
-+ but cannot be queued on a peer (e.g., as it contains FDs but the peer |
4398 |
-+ does not support FDs, or there is no space left in the peer's pool) |
4399 |
-+ the 'dropped_msgs' counter of the peer is incremented. On the next |
4400 |
-+ RECV ioctl, the 'dropped_msgs' field is copied into the ioctl struct |
4401 |
-+ and cleared on the peer. If it was non-zero, the |
4402 |
-+ <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> flag will be set |
4403 |
-+ in <varname>return_flags</varname>. Note that this will only happen |
4404 |
-+ if the ioctl succeeded or failed with <constant>EAGAIN</constant>. In |
4405 |
-+ other error cases, the 'dropped_msgs' field of the peer is left |
4406 |
-+ untouched. |
4407 |
-+ </para></listitem> |
4408 |
-+ </varlistentry> |
4409 |
-+ |
4410 |
-+ <varlistentry> |
4411 |
-+ <term><varname>msg</varname></term> |
4412 |
-+ <listitem><para> |
4413 |
-+ Embedded struct containing information on the received message when |
4414 |
-+ this command succeeded (see below). |
4415 |
-+ </para></listitem> |
4416 |
-+ </varlistentry> |
4417 |
-+ |
4418 |
-+ <varlistentry> |
4419 |
-+ <term><varname>items</varname></term> |
4420 |
-+ <listitem><para> |
4421 |
-+ Items to specify further details for the receive command. |
4422 |
-+ Currently unused, and all items will be rejected with |
4423 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
4424 |
-+ </para></listitem> |
4425 |
-+ </varlistentry> |
4426 |
-+ </variablelist> |
4427 |
-+ |
4428 |
-+ <para> |
4429 |
-+ Both <type>struct kdbus_cmd_recv</type> and |
4430 |
-+ <type>struct kdbus_cmd_send</type> embed |
4431 |
-+ <type>struct kdbus_msg_info</type>. |
4432 |
-+ For the <constant>KDBUS_CMD_SEND</constant> ioctl, it is used to catch |
4433 |
-+ synchronous replies, if one was requested, and is unused otherwise. |
4434 |
-+ </para> |
4435 |
-+ |
4436 |
-+ <programlisting> |
4437 |
-+struct kdbus_msg_info { |
4438 |
-+ __u64 offset; |
4439 |
-+ __u64 msg_size; |
4440 |
-+ __u64 return_flags; |
4441 |
-+}; |
4442 |
-+ </programlisting> |
4443 |
-+ |
4444 |
-+ <para>The fields in this struct are described below.</para> |
4445 |
-+ |
4446 |
-+ <variablelist> |
4447 |
-+ <varlistentry> |
4448 |
-+ <term><varname>offset</varname></term> |
4449 |
-+ <listitem><para> |
4450 |
-+ Upon return of the ioctl, this field contains the offset in the |
4451 |
-+ receiver's memory pool. The memory must be freed with |
4452 |
-+ <constant>KDBUS_CMD_FREE</constant>. See |
4453 |
-+ <citerefentry> |
4454 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
4455 |
-+ <manvolnum>7</manvolnum> |
4456 |
-+ </citerefentry> |
4457 |
-+ for further details. |
4458 |
-+ </para></listitem> |
4459 |
-+ </varlistentry> |
4460 |
-+ |
4461 |
-+ <varlistentry> |
4462 |
-+ <term><varname>msg_size</varname></term> |
4463 |
-+ <listitem><para> |
4464 |
-+ Upon successful return of the ioctl, this field contains the size of |
4465 |
-+ the allocated slice at offset <varname>offset</varname>. |
4466 |
-+ It is the combination of the size of the stored |
4467 |
-+ <type>struct kdbus_msg</type> object plus all appended VECs. |
4468 |
-+ You can use it in combination with <varname>offset</varname> to map |
4469 |
-+ a single message, instead of mapping the entire pool. 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>return_flags</varname></term> |
4480 |
-+ <listitem> |
4481 |
-+ <para> |
4482 |
-+ Kernel-provided return flags. Currently, the following flags are |
4483 |
-+ defined. |
4484 |
-+ </para> |
4485 |
-+ <variablelist> |
4486 |
-+ <varlistentry> |
4487 |
-+ <term><constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant></term> |
4488 |
-+ <listitem> |
4489 |
-+ <para> |
4490 |
-+ The message contained memfds or file descriptors, and the |
4491 |
-+ kernel failed to install one or more of them at receive time. |
4492 |
-+ Most probably that happened because the maximum number of |
4493 |
-+ file descriptors for the receiver's task were exceeded. |
4494 |
-+ In such cases, the message is still delivered, so this is not |
4495 |
-+ a fatal condition. File descriptors numbers inside the |
4496 |
-+ <constant>KDBUS_ITEM_FDS</constant> item or memfd files |
4497 |
-+ referenced by <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> |
4498 |
-+ items which could not be installed will be set to |
4499 |
-+ <constant>-1</constant>. |
4500 |
-+ </para> |
4501 |
-+ </listitem> |
4502 |
-+ </varlistentry> |
4503 |
-+ </variablelist> |
4504 |
-+ </listitem> |
4505 |
-+ </varlistentry> |
4506 |
-+ </variablelist> |
4507 |
-+ |
4508 |
-+ <para> |
4509 |
-+ Unless <constant>KDBUS_RECV_DROP</constant> was passed, the |
4510 |
-+ <varname>offset</varname> field contains the location of the new message |
4511 |
-+ inside the receiver's pool after the <constant>KDBUS_CMD_RECV</constant> |
4512 |
-+ ioctl was employed. The message is stored as <type>struct kdbus_msg</type> |
4513 |
-+ at this offset, and can be interpreted with the semantics described above. |
4514 |
-+ </para> |
4515 |
-+ <para> |
4516 |
-+ Also, if the connection allowed for file descriptor to be passed |
4517 |
-+ (<constant>KDBUS_HELLO_ACCEPT_FD</constant>), and if the message contained |
4518 |
-+ any, they will be installed into the receiving process when the |
4519 |
-+ <constant>KDBUS_CMD_RECV</constant> ioctl is called. |
4520 |
-+ <emphasis>memfds</emphasis> may always be part of the message payload. |
4521 |
-+ The receiving task is obliged to close all file descriptors appropriately |
4522 |
-+ once no longer needed. If <constant>KDBUS_RECV_PEEK</constant> is set, no |
4523 |
-+ file descriptors are installed. This allows for peeking at a message, |
4524 |
-+ looking at its metadata only and dropping it via |
4525 |
-+ <constant>KDBUS_RECV_DROP</constant>, without installing any of the file |
4526 |
-+ descriptors into the receiving process. |
4527 |
-+ </para> |
4528 |
-+ <para> |
4529 |
-+ The caller is obliged to call the <constant>KDBUS_CMD_FREE</constant> |
4530 |
-+ ioctl with the returned offset when the memory is no longer needed. |
4531 |
-+ </para> |
4532 |
-+ </refsect1> |
4533 |
-+ |
4534 |
-+ <refsect1> |
4535 |
-+ <title>Notifications</title> |
4536 |
-+ <para> |
4537 |
-+ A kernel notification is a regular kdbus message with the following |
4538 |
-+ details. |
4539 |
-+ </para> |
4540 |
-+ |
4541 |
-+ <itemizedlist> |
4542 |
-+ <listitem><para> |
4543 |
-+ kdbus_msg.src_id == <constant>KDBUS_SRC_ID_KERNEL</constant> |
4544 |
-+ </para></listitem> |
4545 |
-+ <listitem><para> |
4546 |
-+ kdbus_msg.dst_id == <constant>KDBUS_DST_ID_BROADCAST</constant> |
4547 |
-+ </para></listitem> |
4548 |
-+ <listitem><para> |
4549 |
-+ kdbus_msg.payload_type == <constant>KDBUS_PAYLOAD_KERNEL</constant> |
4550 |
-+ </para></listitem> |
4551 |
-+ <listitem><para> |
4552 |
-+ Has exactly one of the items attached that are described below. |
4553 |
-+ </para></listitem> |
4554 |
-+ <listitem><para> |
4555 |
-+ Always has a timestamp item (<constant>KDBUS_ITEM_TIMESTAMP</constant>) |
4556 |
-+ attached. |
4557 |
-+ </para></listitem> |
4558 |
-+ </itemizedlist> |
4559 |
-+ |
4560 |
-+ <para> |
4561 |
-+ The kernel will notify its users of the following events. |
4562 |
-+ </para> |
4563 |
-+ |
4564 |
-+ <itemizedlist> |
4565 |
-+ <listitem><para> |
4566 |
-+ When connection <emphasis>A</emphasis> is terminated while connection |
4567 |
-+ <emphasis>B</emphasis> is waiting for a reply from it, connection |
4568 |
-+ <emphasis>B</emphasis> is notified with a message with an item of |
4569 |
-+ type <constant>KDBUS_ITEM_REPLY_DEAD</constant>. |
4570 |
-+ </para></listitem> |
4571 |
-+ |
4572 |
-+ <listitem><para> |
4573 |
-+ When connection <emphasis>A</emphasis> does not receive a reply from |
4574 |
-+ connection <emphasis>B</emphasis> within the specified timeout window, |
4575 |
-+ connection <emphasis>A</emphasis> will receive a message with an |
4576 |
-+ item of type <constant>KDBUS_ITEM_REPLY_TIMEOUT</constant>. |
4577 |
-+ </para></listitem> |
4578 |
-+ |
4579 |
-+ <listitem><para> |
4580 |
-+ When an ordinary connection (not a monitor) is created on or removed |
4581 |
-+ from a bus, messages with an item of type |
4582 |
-+ <constant>KDBUS_ITEM_ID_ADD</constant> or |
4583 |
-+ <constant>KDBUS_ITEM_ID_REMOVE</constant>, respectively, are delivered |
4584 |
-+ to all bus members that match these messages through their match |
4585 |
-+ database. Eavesdroppers (monitor connections) do not cause such |
4586 |
-+ notifications to be sent. They are invisible on the bus. |
4587 |
-+ </para></listitem> |
4588 |
-+ |
4589 |
-+ <listitem><para> |
4590 |
-+ When a connection gains or loses ownership of a name, messages with an |
4591 |
-+ item of type <constant>KDBUS_ITEM_NAME_ADD</constant>, |
4592 |
-+ <constant>KDBUS_ITEM_NAME_REMOVE</constant> or |
4593 |
-+ <constant>KDBUS_ITEM_NAME_CHANGE</constant> are delivered to all bus |
4594 |
-+ members that match these messages through their match database. |
4595 |
-+ </para></listitem> |
4596 |
-+ </itemizedlist> |
4597 |
-+ </refsect1> |
4598 |
-+ |
4599 |
-+ <refsect1> |
4600 |
-+ <title>Return value</title> |
4601 |
-+ <para> |
4602 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
4603 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
4604 |
-+ <varname>errno</varname> is set to indicate the error. |
4605 |
-+ If the issued ioctl is illegal for the file descriptor used, |
4606 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
4607 |
-+ </para> |
4608 |
-+ |
4609 |
-+ <refsect2> |
4610 |
-+ <title> |
4611 |
-+ <constant>KDBUS_CMD_SEND</constant> may fail with the following |
4612 |
-+ errors |
4613 |
-+ </title> |
4614 |
-+ |
4615 |
-+ <variablelist> |
4616 |
-+ <varlistentry> |
4617 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
4618 |
-+ <listitem><para> |
4619 |
-+ The connection is not an ordinary connection, or the passed |
4620 |
-+ file descriptors in <constant>KDBUS_ITEM_FDS</constant> item are |
4621 |
-+ either kdbus handles or unix domain sockets. Both are currently |
4622 |
-+ unsupported. |
4623 |
-+ </para></listitem> |
4624 |
-+ </varlistentry> |
4625 |
-+ |
4626 |
-+ <varlistentry> |
4627 |
-+ <term><constant>EINVAL</constant></term> |
4628 |
-+ <listitem><para> |
4629 |
-+ The submitted payload type is |
4630 |
-+ <constant>KDBUS_PAYLOAD_KERNEL</constant>, |
4631 |
-+ <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set without timeout |
4632 |
-+ or cookie values, <constant>KDBUS_SEND_SYNC_REPLY</constant> was |
4633 |
-+ set without <constant>KDBUS_MSG_EXPECT_REPLY</constant>, an invalid |
4634 |
-+ item was supplied, <constant>src_id</constant> was non-zero and was |
4635 |
-+ different from the current connection's ID, a supplied memfd had a |
4636 |
-+ size of 0, or a string was not properly null-terminated. |
4637 |
-+ </para></listitem> |
4638 |
-+ </varlistentry> |
4639 |
-+ |
4640 |
-+ <varlistentry> |
4641 |
-+ <term><constant>ENOTUNIQ</constant></term> |
4642 |
-+ <listitem><para> |
4643 |
-+ The supplied destination is |
4644 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> and either |
4645 |
-+ file descriptors were passed, or |
4646 |
-+ <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set, |
4647 |
-+ or a timeout was given. |
4648 |
-+ </para></listitem> |
4649 |
-+ </varlistentry> |
4650 |
-+ |
4651 |
-+ <varlistentry> |
4652 |
-+ <term><constant>E2BIG</constant></term> |
4653 |
-+ <listitem><para> |
4654 |
-+ Too many items. |
4655 |
-+ </para></listitem> |
4656 |
-+ </varlistentry> |
4657 |
-+ |
4658 |
-+ <varlistentry> |
4659 |
-+ <term><constant>EMSGSIZE</constant></term> |
4660 |
-+ <listitem><para> |
4661 |
-+ The size of the message header and items or the payload vector |
4662 |
-+ is excessive. |
4663 |
-+ </para></listitem> |
4664 |
-+ </varlistentry> |
4665 |
-+ |
4666 |
-+ <varlistentry> |
4667 |
-+ <term><constant>EEXIST</constant></term> |
4668 |
-+ <listitem><para> |
4669 |
-+ Multiple <constant>KDBUS_ITEM_FDS</constant>, |
4670 |
-+ <constant>KDBUS_ITEM_BLOOM_FILTER</constant> or |
4671 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> items were supplied. |
4672 |
-+ </para></listitem> |
4673 |
-+ </varlistentry> |
4674 |
-+ |
4675 |
-+ <varlistentry> |
4676 |
-+ <term><constant>EBADF</constant></term> |
4677 |
-+ <listitem><para> |
4678 |
-+ The supplied <constant>KDBUS_ITEM_FDS</constant> or |
4679 |
-+ <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> items |
4680 |
-+ contained an illegal file descriptor. |
4681 |
-+ </para></listitem> |
4682 |
-+ </varlistentry> |
4683 |
-+ |
4684 |
-+ <varlistentry> |
4685 |
-+ <term><constant>EMEDIUMTYPE</constant></term> |
4686 |
-+ <listitem><para> |
4687 |
-+ The supplied memfd is not a sealed kdbus memfd. |
4688 |
-+ </para></listitem> |
4689 |
-+ </varlistentry> |
4690 |
-+ |
4691 |
-+ <varlistentry> |
4692 |
-+ <term><constant>EMFILE</constant></term> |
4693 |
-+ <listitem><para> |
4694 |
-+ Too many file descriptors inside a |
4695 |
-+ <constant>KDBUS_ITEM_FDS</constant>. |
4696 |
-+ </para></listitem> |
4697 |
-+ </varlistentry> |
4698 |
-+ |
4699 |
-+ <varlistentry> |
4700 |
-+ <term><constant>EBADMSG</constant></term> |
4701 |
-+ <listitem><para> |
4702 |
-+ An item had illegal size, both a <constant>dst_id</constant> and a |
4703 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> was given, or both a name |
4704 |
-+ and a bloom filter was given. |
4705 |
-+ </para></listitem> |
4706 |
-+ </varlistentry> |
4707 |
-+ |
4708 |
-+ <varlistentry> |
4709 |
-+ <term><constant>ETXTBSY</constant></term> |
4710 |
-+ <listitem><para> |
4711 |
-+ The supplied kdbus memfd file cannot be sealed or the seal |
4712 |
-+ was removed, because it is shared with other processes or |
4713 |
-+ still mapped with |
4714 |
-+ <citerefentry> |
4715 |
-+ <refentrytitle>mmap</refentrytitle> |
4716 |
-+ <manvolnum>2</manvolnum> |
4717 |
-+ </citerefentry>. |
4718 |
-+ </para></listitem> |
4719 |
-+ </varlistentry> |
4720 |
-+ |
4721 |
-+ <varlistentry> |
4722 |
-+ <term><constant>ECOMM</constant></term> |
4723 |
-+ <listitem><para> |
4724 |
-+ A peer does not accept the file descriptors addressed to it. |
4725 |
-+ </para></listitem> |
4726 |
-+ </varlistentry> |
4727 |
-+ |
4728 |
-+ <varlistentry> |
4729 |
-+ <term><constant>EFAULT</constant></term> |
4730 |
-+ <listitem><para> |
4731 |
-+ The supplied bloom filter size was not 64-bit aligned, or supplied |
4732 |
-+ memory could not be accessed by the kernel. |
4733 |
-+ </para></listitem> |
4734 |
-+ </varlistentry> |
4735 |
-+ |
4736 |
-+ <varlistentry> |
4737 |
-+ <term><constant>EDOM</constant></term> |
4738 |
-+ <listitem><para> |
4739 |
-+ The supplied bloom filter size did not match the bloom filter |
4740 |
-+ size of the bus. |
4741 |
-+ </para></listitem> |
4742 |
-+ </varlistentry> |
4743 |
-+ |
4744 |
-+ <varlistentry> |
4745 |
-+ <term><constant>EDESTADDRREQ</constant></term> |
4746 |
-+ <listitem><para> |
4747 |
-+ <constant>dst_id</constant> was set to |
4748 |
-+ <constant>KDBUS_DST_ID_NAME</constant>, but no |
4749 |
-+ <constant>KDBUS_ITEM_DST_NAME</constant> was attached. |
4750 |
-+ </para></listitem> |
4751 |
-+ </varlistentry> |
4752 |
-+ |
4753 |
-+ <varlistentry> |
4754 |
-+ <term><constant>ESRCH</constant></term> |
4755 |
-+ <listitem><para> |
4756 |
-+ The name to look up was not found in the name registry. |
4757 |
-+ </para></listitem> |
4758 |
-+ </varlistentry> |
4759 |
-+ |
4760 |
-+ <varlistentry> |
4761 |
-+ <term><constant>EADDRNOTAVAIL</constant></term> |
4762 |
-+ <listitem><para> |
4763 |
-+ <constant>KDBUS_MSG_NO_AUTO_START</constant> was given but the |
4764 |
-+ destination connection is an activator. |
4765 |
-+ </para></listitem> |
4766 |
-+ </varlistentry> |
4767 |
-+ |
4768 |
-+ <varlistentry> |
4769 |
-+ <term><constant>ENXIO</constant></term> |
4770 |
-+ <listitem><para> |
4771 |
-+ The passed numeric destination connection ID couldn't be found, |
4772 |
-+ or is not connected. |
4773 |
-+ </para></listitem> |
4774 |
-+ </varlistentry> |
4775 |
-+ |
4776 |
-+ <varlistentry> |
4777 |
-+ <term><constant>ECONNRESET</constant></term> |
4778 |
-+ <listitem><para> |
4779 |
-+ The destination connection is no longer active. |
4780 |
-+ </para></listitem> |
4781 |
-+ </varlistentry> |
4782 |
-+ |
4783 |
-+ <varlistentry> |
4784 |
-+ <term><constant>ETIMEDOUT</constant></term> |
4785 |
-+ <listitem><para> |
4786 |
-+ Timeout while synchronously waiting for a reply. |
4787 |
-+ </para></listitem> |
4788 |
-+ </varlistentry> |
4789 |
-+ |
4790 |
-+ <varlistentry> |
4791 |
-+ <term><constant>EINTR</constant></term> |
4792 |
-+ <listitem><para> |
4793 |
-+ Interrupted system call while synchronously waiting for a reply. |
4794 |
-+ </para></listitem> |
4795 |
-+ </varlistentry> |
4796 |
-+ |
4797 |
-+ <varlistentry> |
4798 |
-+ <term><constant>EPIPE</constant></term> |
4799 |
-+ <listitem><para> |
4800 |
-+ When sending a message, a synchronous reply from the receiving |
4801 |
-+ connection was expected but the connection died before answering. |
4802 |
-+ </para></listitem> |
4803 |
-+ </varlistentry> |
4804 |
-+ |
4805 |
-+ <varlistentry> |
4806 |
-+ <term><constant>ENOBUFS</constant></term> |
4807 |
-+ <listitem><para> |
4808 |
-+ Too many pending messages on the receiver side. |
4809 |
-+ </para></listitem> |
4810 |
-+ </varlistentry> |
4811 |
-+ |
4812 |
-+ <varlistentry> |
4813 |
-+ <term><constant>EREMCHG</constant></term> |
4814 |
-+ <listitem><para> |
4815 |
-+ Both a well-known name and a unique name (ID) was given, but |
4816 |
-+ the name is not currently owned by that connection. |
4817 |
-+ </para></listitem> |
4818 |
-+ </varlistentry> |
4819 |
-+ |
4820 |
-+ <varlistentry> |
4821 |
-+ <term><constant>EXFULL</constant></term> |
4822 |
-+ <listitem><para> |
4823 |
-+ The memory pool of the receiver is full. |
4824 |
-+ </para></listitem> |
4825 |
-+ </varlistentry> |
4826 |
-+ |
4827 |
-+ <varlistentry> |
4828 |
-+ <term><constant>EREMOTEIO</constant></term> |
4829 |
-+ <listitem><para> |
4830 |
-+ While synchronously waiting for a reply, the remote peer |
4831 |
-+ failed with an I/O error. |
4832 |
-+ </para></listitem> |
4833 |
-+ </varlistentry> |
4834 |
-+ </variablelist> |
4835 |
-+ </refsect2> |
4836 |
-+ |
4837 |
-+ <refsect2> |
4838 |
-+ <title> |
4839 |
-+ <constant>KDBUS_CMD_RECV</constant> may fail with the following |
4840 |
-+ errors |
4841 |
-+ </title> |
4842 |
-+ |
4843 |
-+ <variablelist> |
4844 |
-+ <varlistentry> |
4845 |
-+ <term><constant>EOPNOTSUPP</constant></term> |
4846 |
-+ <listitem><para> |
4847 |
-+ The connection is not an ordinary connection, or the passed |
4848 |
-+ file descriptors are either kdbus handles or unix domain |
4849 |
-+ sockets. Both are currently unsupported. |
4850 |
-+ </para></listitem> |
4851 |
-+ </varlistentry> |
4852 |
-+ |
4853 |
-+ <varlistentry> |
4854 |
-+ <term><constant>EINVAL</constant></term> |
4855 |
-+ <listitem><para> |
4856 |
-+ Invalid flags or offset. |
4857 |
-+ </para></listitem> |
4858 |
-+ </varlistentry> |
4859 |
-+ |
4860 |
-+ <varlistentry> |
4861 |
-+ <term><constant>EAGAIN</constant></term> |
4862 |
-+ <listitem><para> |
4863 |
-+ No message found in the queue. |
4864 |
-+ </para></listitem> |
4865 |
-+ </varlistentry> |
4866 |
-+ </variablelist> |
4867 |
-+ </refsect2> |
4868 |
-+ </refsect1> |
4869 |
-+ |
4870 |
-+ <refsect1> |
4871 |
-+ <title>See Also</title> |
4872 |
-+ <simplelist type="inline"> |
4873 |
-+ <member> |
4874 |
-+ <citerefentry> |
4875 |
-+ <refentrytitle>kdbus</refentrytitle> |
4876 |
-+ <manvolnum>7</manvolnum> |
4877 |
-+ </citerefentry> |
4878 |
-+ </member> |
4879 |
-+ <member> |
4880 |
-+ <citerefentry> |
4881 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
4882 |
-+ <manvolnum>7</manvolnum> |
4883 |
-+ </citerefentry> |
4884 |
-+ </member> |
4885 |
-+ <member> |
4886 |
-+ <citerefentry> |
4887 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
4888 |
-+ <manvolnum>7</manvolnum> |
4889 |
-+ </citerefentry> |
4890 |
-+ </member> |
4891 |
-+ <member> |
4892 |
-+ <citerefentry> |
4893 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
4894 |
-+ <manvolnum>7</manvolnum> |
4895 |
-+ </citerefentry> |
4896 |
-+ </member> |
4897 |
-+ <member> |
4898 |
-+ <citerefentry> |
4899 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
4900 |
-+ <manvolnum>7</manvolnum> |
4901 |
-+ </citerefentry> |
4902 |
-+ </member> |
4903 |
-+ <member> |
4904 |
-+ <citerefentry> |
4905 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
4906 |
-+ <manvolnum>7</manvolnum> |
4907 |
-+ </citerefentry> |
4908 |
-+ </member> |
4909 |
-+ <member> |
4910 |
-+ <citerefentry> |
4911 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
4912 |
-+ <manvolnum>7</manvolnum> |
4913 |
-+ </citerefentry> |
4914 |
-+ </member> |
4915 |
-+ <member> |
4916 |
-+ <citerefentry> |
4917 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
4918 |
-+ <manvolnum>7</manvolnum> |
4919 |
-+ </citerefentry> |
4920 |
-+ </member> |
4921 |
-+ <member> |
4922 |
-+ <citerefentry> |
4923 |
-+ <refentrytitle>clock_gettime</refentrytitle> |
4924 |
-+ <manvolnum>2</manvolnum> |
4925 |
-+ </citerefentry> |
4926 |
-+ </member> |
4927 |
-+ <member> |
4928 |
-+ <citerefentry> |
4929 |
-+ <refentrytitle>ioctl</refentrytitle> |
4930 |
-+ <manvolnum>2</manvolnum> |
4931 |
-+ </citerefentry> |
4932 |
-+ </member> |
4933 |
-+ <member> |
4934 |
-+ <citerefentry> |
4935 |
-+ <refentrytitle>poll</refentrytitle> |
4936 |
-+ <manvolnum>2</manvolnum> |
4937 |
-+ </citerefentry> |
4938 |
-+ </member> |
4939 |
-+ <member> |
4940 |
-+ <citerefentry> |
4941 |
-+ <refentrytitle>select</refentrytitle> |
4942 |
-+ <manvolnum>2</manvolnum> |
4943 |
-+ </citerefentry> |
4944 |
-+ </member> |
4945 |
-+ <member> |
4946 |
-+ <citerefentry> |
4947 |
-+ <refentrytitle>epoll</refentrytitle> |
4948 |
-+ <manvolnum>7</manvolnum> |
4949 |
-+ </citerefentry> |
4950 |
-+ </member> |
4951 |
-+ <member> |
4952 |
-+ <citerefentry> |
4953 |
-+ <refentrytitle>eventfd</refentrytitle> |
4954 |
-+ <manvolnum>2</manvolnum> |
4955 |
-+ </citerefentry> |
4956 |
-+ </member> |
4957 |
-+ <member> |
4958 |
-+ <citerefentry> |
4959 |
-+ <refentrytitle>memfd_create</refentrytitle> |
4960 |
-+ <manvolnum>2</manvolnum> |
4961 |
-+ </citerefentry> |
4962 |
-+ </member> |
4963 |
-+ </simplelist> |
4964 |
-+ </refsect1> |
4965 |
-+</refentry> |
4966 |
-diff --git a/Documentation/kdbus/kdbus.name.xml b/Documentation/kdbus/kdbus.name.xml |
4967 |
-new file mode 100644 |
4968 |
-index 0000000..3f5f6a6 |
4969 |
---- /dev/null |
4970 |
-+++ b/Documentation/kdbus/kdbus.name.xml |
4971 |
-@@ -0,0 +1,711 @@ |
4972 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
4973 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
4974 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
4975 |
-+ |
4976 |
-+<refentry id="kdbus.name"> |
4977 |
-+ |
4978 |
-+ <refentryinfo> |
4979 |
-+ <title>kdbus.name</title> |
4980 |
-+ <productname>kdbus.name</productname> |
4981 |
-+ </refentryinfo> |
4982 |
-+ |
4983 |
-+ <refmeta> |
4984 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
4985 |
-+ <manvolnum>7</manvolnum> |
4986 |
-+ </refmeta> |
4987 |
-+ |
4988 |
-+ <refnamediv> |
4989 |
-+ <refname>kdbus.name</refname> |
4990 |
-+ <refpurpose>kdbus.name</refpurpose> |
4991 |
-+ </refnamediv> |
4992 |
-+ |
4993 |
-+ <refsect1> |
4994 |
-+ <title>Description</title> |
4995 |
-+ <para> |
4996 |
-+ Each |
4997 |
-+ <citerefentry> |
4998 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
4999 |
-+ <manvolnum>7</manvolnum> |
5000 |
-+ </citerefentry> |
5001 |
-+ instantiates a name registry to resolve well-known names into unique |
5002 |
-+ connection IDs for message delivery. The registry will be queried when a |
5003 |
-+ message is sent with <varname>kdbus_msg.dst_id</varname> set to |
5004 |
-+ <constant>KDBUS_DST_ID_NAME</constant>, or when a registry dump is |
5005 |
-+ requested with <constant>KDBUS_CMD_NAME_LIST</constant>. |
5006 |
-+ </para> |
5007 |
-+ |
5008 |
-+ <para> |
5009 |
-+ All of the below is subject to policy rules for <emphasis>SEE</emphasis> |
5010 |
-+ and <emphasis>OWN</emphasis> permissions. See |
5011 |
-+ <citerefentry> |
5012 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
5013 |
-+ <manvolnum>7</manvolnum> |
5014 |
-+ </citerefentry> |
5015 |
-+ for more information. |
5016 |
-+ </para> |
5017 |
-+ </refsect1> |
5018 |
-+ |
5019 |
-+ <refsect1> |
5020 |
-+ <title>Name validity</title> |
5021 |
-+ <para> |
5022 |
-+ A name has to comply with the following rules in order to be considered |
5023 |
-+ valid. |
5024 |
-+ </para> |
5025 |
-+ |
5026 |
-+ <itemizedlist> |
5027 |
-+ <listitem> |
5028 |
-+ <para> |
5029 |
-+ The name has two or more elements separated by a |
5030 |
-+ '<literal>.</literal>' (period) character. |
5031 |
-+ </para> |
5032 |
-+ </listitem> |
5033 |
-+ <listitem> |
5034 |
-+ <para> |
5035 |
-+ All elements must contain at least one character. |
5036 |
-+ </para> |
5037 |
-+ </listitem> |
5038 |
-+ <listitem> |
5039 |
-+ <para> |
5040 |
-+ Each element must only contain the ASCII characters |
5041 |
-+ <literal>[A-Z][a-z][0-9]_</literal> and must not begin with a |
5042 |
-+ digit. |
5043 |
-+ </para> |
5044 |
-+ </listitem> |
5045 |
-+ <listitem> |
5046 |
-+ <para> |
5047 |
-+ The name must contain at least one '<literal>.</literal>' (period) |
5048 |
-+ character (and thus at least two elements). |
5049 |
-+ </para> |
5050 |
-+ </listitem> |
5051 |
-+ <listitem> |
5052 |
-+ <para> |
5053 |
-+ The name must not begin with a '<literal>.</literal>' (period) |
5054 |
-+ character. |
5055 |
-+ </para> |
5056 |
-+ </listitem> |
5057 |
-+ <listitem> |
5058 |
-+ <para> |
5059 |
-+ The name must not exceed <constant>255</constant> characters in |
5060 |
-+ length. |
5061 |
-+ </para> |
5062 |
-+ </listitem> |
5063 |
-+ </itemizedlist> |
5064 |
-+ </refsect1> |
5065 |
-+ |
5066 |
-+ <refsect1> |
5067 |
-+ <title>Acquiring a name</title> |
5068 |
-+ <para> |
5069 |
-+ To acquire a name, a client uses the |
5070 |
-+ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> ioctl with |
5071 |
-+ <type>struct kdbus_cmd</type> as argument. |
5072 |
-+ </para> |
5073 |
-+ |
5074 |
-+ <programlisting> |
5075 |
-+struct kdbus_cmd { |
5076 |
-+ __u64 size; |
5077 |
-+ __u64 flags; |
5078 |
-+ __u64 return_flags; |
5079 |
-+ struct kdbus_item items[0]; |
5080 |
-+}; |
5081 |
-+ </programlisting> |
5082 |
-+ |
5083 |
-+ <para>The fields in this struct are described below.</para> |
5084 |
-+ |
5085 |
-+ <variablelist> |
5086 |
-+ <varlistentry> |
5087 |
-+ <term><varname>size</varname></term> |
5088 |
-+ <listitem><para> |
5089 |
-+ The overall size of the struct, including its items. |
5090 |
-+ </para></listitem> |
5091 |
-+ </varlistentry> |
5092 |
-+ |
5093 |
-+ <varlistentry> |
5094 |
-+ <term><varname>flags</varname></term> |
5095 |
-+ <listitem><para>Flags to control details in the name acquisition.</para> |
5096 |
-+ <variablelist> |
5097 |
-+ <varlistentry> |
5098 |
-+ <term><constant>KDBUS_NAME_REPLACE_EXISTING</constant></term> |
5099 |
-+ <listitem> |
5100 |
-+ <para> |
5101 |
-+ Acquiring a name that is already present usually fails, |
5102 |
-+ unless this flag is set in the call, and |
5103 |
-+ <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> (see below) |
5104 |
-+ was set when the current owner of the name acquired it, or |
5105 |
-+ if the current owner is an activator connection (see |
5106 |
-+ <citerefentry> |
5107 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5108 |
-+ <manvolnum>7</manvolnum> |
5109 |
-+ </citerefentry>). |
5110 |
-+ </para> |
5111 |
-+ </listitem> |
5112 |
-+ </varlistentry> |
5113 |
-+ |
5114 |
-+ <varlistentry> |
5115 |
-+ <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term> |
5116 |
-+ <listitem> |
5117 |
-+ <para> |
5118 |
-+ Allow other connections to take over this name. When this |
5119 |
-+ happens, the former owner of the connection will be notified |
5120 |
-+ of the name loss. |
5121 |
-+ </para> |
5122 |
-+ </listitem> |
5123 |
-+ </varlistentry> |
5124 |
-+ |
5125 |
-+ <varlistentry> |
5126 |
-+ <term><constant>KDBUS_NAME_QUEUE</constant></term> |
5127 |
-+ <listitem> |
5128 |
-+ <para> |
5129 |
-+ A name that is already acquired by a connection can not be |
5130 |
-+ acquired again (unless the |
5131 |
-+ <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> flag was |
5132 |
-+ set during acquisition; see above). |
5133 |
-+ However, a connection can put itself in a queue of |
5134 |
-+ connections waiting for the name to be released. Once that |
5135 |
-+ happens, the first connection in that queue becomes the new |
5136 |
-+ owner and is notified accordingly. |
5137 |
-+ </para> |
5138 |
-+ </listitem> |
5139 |
-+ </varlistentry> |
5140 |
-+ |
5141 |
-+ <varlistentry> |
5142 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5143 |
-+ <listitem> |
5144 |
-+ <para> |
5145 |
-+ Request a set of valid flags for this ioctl. When this bit is |
5146 |
-+ set, no action is taken; the ioctl will fail with |
5147 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> |
5148 |
-+ is set to <constant>EPROTO</constant>. |
5149 |
-+ Once the ioctl returned, the <varname>flags</varname> |
5150 |
-+ field will have all bits set that the kernel recognizes as |
5151 |
-+ valid for this command. |
5152 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5153 |
-+ cleared by the operation. |
5154 |
-+ </para> |
5155 |
-+ </listitem> |
5156 |
-+ </varlistentry> |
5157 |
-+ </variablelist> |
5158 |
-+ </listitem> |
5159 |
-+ </varlistentry> |
5160 |
-+ |
5161 |
-+ <varlistentry> |
5162 |
-+ <term><varname>return_flags</varname></term> |
5163 |
-+ <listitem> |
5164 |
-+ <para> |
5165 |
-+ Flags returned by the kernel. Currently, the following may be |
5166 |
-+ returned by the kernel. |
5167 |
-+ </para> |
5168 |
-+ <variablelist> |
5169 |
-+ <varlistentry> |
5170 |
-+ <term><constant>KDBUS_NAME_IN_QUEUE</constant></term> |
5171 |
-+ <listitem> |
5172 |
-+ <para> |
5173 |
-+ The name was not acquired yet, but the connection was |
5174 |
-+ placed in the queue of peers waiting for the name. |
5175 |
-+ This can only happen if <constant>KDBUS_NAME_QUEUE</constant> |
5176 |
-+ was set in the <varname>flags</varname> member (see above). |
5177 |
-+ The connection will receive a name owner change notification |
5178 |
-+ once the current owner has given up the name and its |
5179 |
-+ ownership was transferred. |
5180 |
-+ </para> |
5181 |
-+ </listitem> |
5182 |
-+ </varlistentry> |
5183 |
-+ </variablelist> |
5184 |
-+ </listitem> |
5185 |
-+ </varlistentry> |
5186 |
-+ |
5187 |
-+ <varlistentry> |
5188 |
-+ <term><varname>items</varname></term> |
5189 |
-+ <listitem> |
5190 |
-+ <para> |
5191 |
-+ Items to submit the name. Currently, one item of type |
5192 |
-+ <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and |
5193 |
-+ the contained string must be a valid bus name. |
5194 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for |
5195 |
-+ valid item types. See |
5196 |
-+ <citerefentry> |
5197 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5198 |
-+ <manvolnum>7</manvolnum> |
5199 |
-+ </citerefentry> |
5200 |
-+ for a detailed description of how this item is used. |
5201 |
-+ </para> |
5202 |
-+ <para> |
5203 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
5204 |
-+ <varname>errno</varname> set to <errorname>>EINVAL</errorname>. |
5205 |
-+ </para> |
5206 |
-+ </listitem> |
5207 |
-+ </varlistentry> |
5208 |
-+ </variablelist> |
5209 |
-+ </refsect1> |
5210 |
-+ |
5211 |
-+ <refsect1> |
5212 |
-+ <title>Releasing a name</title> |
5213 |
-+ <para> |
5214 |
-+ A connection may release a name explicitly with the |
5215 |
-+ <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl. If the connection was |
5216 |
-+ an implementer of an activatable name, its pending messages are moved |
5217 |
-+ back to the activator. If there are any connections queued up as waiters |
5218 |
-+ for the name, the first one in the queue (the oldest entry) will become |
5219 |
-+ the new owner. The same happens implicitly for all names once a |
5220 |
-+ connection terminates. See |
5221 |
-+ <citerefentry> |
5222 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5223 |
-+ <manvolnum>7</manvolnum> |
5224 |
-+ </citerefentry> |
5225 |
-+ for more information on connections. |
5226 |
-+ </para> |
5227 |
-+ <para> |
5228 |
-+ The <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl uses the same data |
5229 |
-+ structure as the acquisition call |
5230 |
-+ (<constant>KDBUS_CMD_NAME_ACQUIRE</constant>), |
5231 |
-+ but with slightly different field usage. |
5232 |
-+ </para> |
5233 |
-+ |
5234 |
-+ <programlisting> |
5235 |
-+struct kdbus_cmd { |
5236 |
-+ __u64 size; |
5237 |
-+ __u64 flags; |
5238 |
-+ __u64 return_flags; |
5239 |
-+ struct kdbus_item items[0]; |
5240 |
-+}; |
5241 |
-+ </programlisting> |
5242 |
-+ |
5243 |
-+ <para>The fields in this struct are described below.</para> |
5244 |
-+ |
5245 |
-+ <variablelist> |
5246 |
-+ <varlistentry> |
5247 |
-+ <term><varname>size</varname></term> |
5248 |
-+ <listitem><para> |
5249 |
-+ The overall size of the struct, including its items. |
5250 |
-+ </para></listitem> |
5251 |
-+ </varlistentry> |
5252 |
-+ |
5253 |
-+ <varlistentry> |
5254 |
-+ <term><varname>flags</varname></term> |
5255 |
-+ <listitem><para> |
5256 |
-+ Flags to the command. Currently unused. |
5257 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
5258 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
5259 |
-+ and the <varname>flags</varname> field is set to |
5260 |
-+ <constant>0</constant>. |
5261 |
-+ </para></listitem> |
5262 |
-+ </varlistentry> |
5263 |
-+ |
5264 |
-+ <varlistentry> |
5265 |
-+ <term><varname>return_flags</varname></term> |
5266 |
-+ <listitem><para> |
5267 |
-+ Flags returned by the kernel. Currently unused and always set to |
5268 |
-+ <constant>0</constant> by the kernel. |
5269 |
-+ </para></listitem> |
5270 |
-+ </varlistentry> |
5271 |
-+ |
5272 |
-+ <varlistentry> |
5273 |
-+ <term><varname>items</varname></term> |
5274 |
-+ <listitem> |
5275 |
-+ <para> |
5276 |
-+ Items to submit the name. Currently, one item of type |
5277 |
-+ <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and |
5278 |
-+ the contained string must be a valid bus name. |
5279 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for |
5280 |
-+ valid item types. See |
5281 |
-+ <citerefentry> |
5282 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5283 |
-+ <manvolnum>7</manvolnum> |
5284 |
-+ </citerefentry> |
5285 |
-+ for a detailed description of how this item is used. |
5286 |
-+ </para> |
5287 |
-+ <para> |
5288 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
5289 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
5290 |
-+ </para> |
5291 |
-+ </listitem> |
5292 |
-+ </varlistentry> |
5293 |
-+ </variablelist> |
5294 |
-+ </refsect1> |
5295 |
-+ |
5296 |
-+ <refsect1> |
5297 |
-+ <title>Dumping the name registry</title> |
5298 |
-+ <para> |
5299 |
-+ A connection may request a complete or filtered dump of currently active |
5300 |
-+ bus names with the <constant>KDBUS_CMD_LIST</constant> ioctl, which |
5301 |
-+ takes a <type>struct kdbus_cmd_list</type> as argument. |
5302 |
-+ </para> |
5303 |
-+ |
5304 |
-+ <programlisting> |
5305 |
-+struct kdbus_cmd_list { |
5306 |
-+ __u64 flags; |
5307 |
-+ __u64 return_flags; |
5308 |
-+ __u64 offset; |
5309 |
-+}; |
5310 |
-+ </programlisting> |
5311 |
-+ |
5312 |
-+ <para>The fields in this struct are described below.</para> |
5313 |
-+ |
5314 |
-+ <variablelist> |
5315 |
-+ <varlistentry> |
5316 |
-+ <term><varname>flags</varname></term> |
5317 |
-+ <listitem> |
5318 |
-+ <para> |
5319 |
-+ Any combination of flags to specify which names should be dumped. |
5320 |
-+ </para> |
5321 |
-+ <variablelist> |
5322 |
-+ <varlistentry> |
5323 |
-+ <term><constant>KDBUS_LIST_UNIQUE</constant></term> |
5324 |
-+ <listitem> |
5325 |
-+ <para> |
5326 |
-+ List the unique (numeric) IDs of the connection, whether it |
5327 |
-+ owns a name or not. |
5328 |
-+ </para> |
5329 |
-+ </listitem> |
5330 |
-+ </varlistentry> |
5331 |
-+ |
5332 |
-+ <varlistentry> |
5333 |
-+ <term><constant>KDBUS_LIST_NAMES</constant></term> |
5334 |
-+ <listitem> |
5335 |
-+ <para> |
5336 |
-+ List well-known names stored in the database which are |
5337 |
-+ actively owned by a real connection (not an activator). |
5338 |
-+ </para> |
5339 |
-+ </listitem> |
5340 |
-+ </varlistentry> |
5341 |
-+ |
5342 |
-+ <varlistentry> |
5343 |
-+ <term><constant>KDBUS_LIST_ACTIVATORS</constant></term> |
5344 |
-+ <listitem> |
5345 |
-+ <para> |
5346 |
-+ List names that are owned by an activator. |
5347 |
-+ </para> |
5348 |
-+ </listitem> |
5349 |
-+ </varlistentry> |
5350 |
-+ |
5351 |
-+ <varlistentry> |
5352 |
-+ <term><constant>KDBUS_LIST_QUEUED</constant></term> |
5353 |
-+ <listitem> |
5354 |
-+ <para> |
5355 |
-+ List connections that are not yet owning a name but are |
5356 |
-+ waiting for it to become available. |
5357 |
-+ </para> |
5358 |
-+ </listitem> |
5359 |
-+ </varlistentry> |
5360 |
-+ |
5361 |
-+ <varlistentry> |
5362 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5363 |
-+ <listitem> |
5364 |
-+ <para> |
5365 |
-+ Request a set of valid flags for this ioctl. When this bit is |
5366 |
-+ set, no action is taken; the ioctl will fail with |
5367 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> |
5368 |
-+ is set to <constant>EPROTO</constant>. |
5369 |
-+ Once the ioctl returned, the <varname>flags</varname> |
5370 |
-+ field will have all bits set that the kernel recognizes as |
5371 |
-+ valid for this command. |
5372 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5373 |
-+ cleared by the operation. |
5374 |
-+ </para> |
5375 |
-+ </listitem> |
5376 |
-+ </varlistentry> |
5377 |
-+ </variablelist> |
5378 |
-+ </listitem> |
5379 |
-+ </varlistentry> |
5380 |
-+ |
5381 |
-+ <varlistentry> |
5382 |
-+ <term><varname>return_flags</varname></term> |
5383 |
-+ <listitem><para> |
5384 |
-+ Flags returned by the kernel. Currently unused and always set to |
5385 |
-+ <constant>0</constant> by the kernel. |
5386 |
-+ </para></listitem> |
5387 |
-+ </varlistentry> |
5388 |
-+ |
5389 |
-+ <varlistentry> |
5390 |
-+ <term><varname>offset</varname></term> |
5391 |
-+ <listitem><para> |
5392 |
-+ When the ioctl returns successfully, the offset to the name registry |
5393 |
-+ dump inside the connection's pool will be stored in this field. |
5394 |
-+ </para></listitem> |
5395 |
-+ </varlistentry> |
5396 |
-+ </variablelist> |
5397 |
-+ |
5398 |
-+ <para> |
5399 |
-+ The returned list of names is stored in a <type>struct kdbus_list</type> |
5400 |
-+ that in turn contains an array of type <type>struct kdbus_info</type>, |
5401 |
-+ The array-size in bytes is given as <varname>list_size</varname>. |
5402 |
-+ The fields inside <type>struct kdbus_info</type> is described next. |
5403 |
-+ </para> |
5404 |
-+ |
5405 |
-+ <programlisting> |
5406 |
-+struct kdbus_info { |
5407 |
-+ __u64 size; |
5408 |
-+ __u64 id; |
5409 |
-+ __u64 flags; |
5410 |
-+ struct kdbus_item items[0]; |
5411 |
-+}; |
5412 |
-+ </programlisting> |
5413 |
-+ |
5414 |
-+ <para>The fields in this struct are described below.</para> |
5415 |
-+ |
5416 |
-+ <variablelist> |
5417 |
-+ <varlistentry> |
5418 |
-+ <term><varname>size</varname></term> |
5419 |
-+ <listitem><para> |
5420 |
-+ The overall size of the struct, including its items. |
5421 |
-+ </para></listitem> |
5422 |
-+ </varlistentry> |
5423 |
-+ |
5424 |
-+ <varlistentry> |
5425 |
-+ <term><varname>id</varname></term> |
5426 |
-+ <listitem><para> |
5427 |
-+ The owning connection's unique ID. |
5428 |
-+ </para></listitem> |
5429 |
-+ </varlistentry> |
5430 |
-+ |
5431 |
-+ <varlistentry> |
5432 |
-+ <term><varname>flags</varname></term> |
5433 |
-+ <listitem><para> |
5434 |
-+ The flags of the owning connection. |
5435 |
-+ </para></listitem> |
5436 |
-+ </varlistentry> |
5437 |
-+ |
5438 |
-+ <varlistentry> |
5439 |
-+ <term><varname>items</varname></term> |
5440 |
-+ <listitem> |
5441 |
-+ <para> |
5442 |
-+ Items containing the actual name. Currently, one item of type |
5443 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant> will be attached, |
5444 |
-+ including the name's flags. In that item, the flags field of the |
5445 |
-+ name may carry the following bits: |
5446 |
-+ </para> |
5447 |
-+ <variablelist> |
5448 |
-+ <varlistentry> |
5449 |
-+ <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term> |
5450 |
-+ <listitem> |
5451 |
-+ <para> |
5452 |
-+ Other connections are allowed to take over this name from the |
5453 |
-+ connection that owns it. |
5454 |
-+ </para> |
5455 |
-+ </listitem> |
5456 |
-+ </varlistentry> |
5457 |
-+ |
5458 |
-+ <varlistentry> |
5459 |
-+ <term><constant>KDBUS_NAME_IN_QUEUE</constant></term> |
5460 |
-+ <listitem> |
5461 |
-+ <para> |
5462 |
-+ When retrieving a list of currently acquired names in the |
5463 |
-+ registry, this flag indicates whether the connection |
5464 |
-+ actually owns the name or is currently waiting for it to |
5465 |
-+ become available. |
5466 |
-+ </para> |
5467 |
-+ </listitem> |
5468 |
-+ </varlistentry> |
5469 |
-+ |
5470 |
-+ <varlistentry> |
5471 |
-+ <term><constant>KDBUS_NAME_ACTIVATOR</constant></term> |
5472 |
-+ <listitem> |
5473 |
-+ <para> |
5474 |
-+ An activator connection owns a name as a placeholder for an |
5475 |
-+ implementer, which is started on demand by programs as soon |
5476 |
-+ as the first message arrives. There's some more information |
5477 |
-+ on this topic in |
5478 |
-+ <citerefentry> |
5479 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5480 |
-+ <manvolnum>7</manvolnum> |
5481 |
-+ </citerefentry> |
5482 |
-+ . |
5483 |
-+ </para> |
5484 |
-+ <para> |
5485 |
-+ In contrast to |
5486 |
-+ <constant>KDBUS_NAME_REPLACE_EXISTING</constant>, |
5487 |
-+ when a name is taken over from an activator connection, all |
5488 |
-+ the messages that have been queued in the activator |
5489 |
-+ connection will be moved over to the new owner. The activator |
5490 |
-+ connection will still be tracked for the name and will take |
5491 |
-+ control again if the implementer connection terminates. |
5492 |
-+ </para> |
5493 |
-+ <para> |
5494 |
-+ This flag can not be used when acquiring a name, but is |
5495 |
-+ implicitly set through <constant>KDBUS_CMD_HELLO</constant> |
5496 |
-+ with <constant>KDBUS_HELLO_ACTIVATOR</constant> set in |
5497 |
-+ <varname>kdbus_cmd_hello.conn_flags</varname>. |
5498 |
-+ </para> |
5499 |
-+ </listitem> |
5500 |
-+ </varlistentry> |
5501 |
-+ |
5502 |
-+ <varlistentry> |
5503 |
-+ <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term> |
5504 |
-+ <listitem> |
5505 |
-+ <para> |
5506 |
-+ Requests a set of valid flags for this ioctl. When this bit is |
5507 |
-+ set, no action is taken; the ioctl will return |
5508 |
-+ <errorcode>0</errorcode>, and the <varname>flags</varname> |
5509 |
-+ field will have all bits set that are valid for this command. |
5510 |
-+ The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be |
5511 |
-+ cleared by the operation. |
5512 |
-+ </para> |
5513 |
-+ </listitem> |
5514 |
-+ </varlistentry> |
5515 |
-+ </variablelist> |
5516 |
-+ </listitem> |
5517 |
-+ </varlistentry> |
5518 |
-+ </variablelist> |
5519 |
-+ |
5520 |
-+ <para> |
5521 |
-+ The returned buffer must be freed with the |
5522 |
-+ <constant>KDBUS_CMD_FREE</constant> ioctl when the user is finished with |
5523 |
-+ it. See |
5524 |
-+ <citerefentry> |
5525 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
5526 |
-+ <manvolnum>7</manvolnum> |
5527 |
-+ </citerefentry> |
5528 |
-+ for more information. |
5529 |
-+ </para> |
5530 |
-+ </refsect1> |
5531 |
-+ |
5532 |
-+ <refsect1> |
5533 |
-+ <title>Return value</title> |
5534 |
-+ <para> |
5535 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
5536 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
5537 |
-+ <varname>errno</varname> is set to indicate the error. |
5538 |
-+ If the issued ioctl is illegal for the file descriptor used, |
5539 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
5540 |
-+ </para> |
5541 |
-+ |
5542 |
-+ <refsect2> |
5543 |
-+ <title> |
5544 |
-+ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> may fail with the following |
5545 |
-+ errors |
5546 |
-+ </title> |
5547 |
-+ |
5548 |
-+ <variablelist> |
5549 |
-+ <varlistentry> |
5550 |
-+ <term><constant>EINVAL</constant></term> |
5551 |
-+ <listitem><para> |
5552 |
-+ Illegal command flags, illegal name provided, or an activator |
5553 |
-+ tried to acquire a second name. |
5554 |
-+ </para></listitem> |
5555 |
-+ </varlistentry> |
5556 |
-+ |
5557 |
-+ <varlistentry> |
5558 |
-+ <term><constant>EPERM</constant></term> |
5559 |
-+ <listitem><para> |
5560 |
-+ Policy prohibited name ownership. |
5561 |
-+ </para></listitem> |
5562 |
-+ </varlistentry> |
5563 |
-+ |
5564 |
-+ <varlistentry> |
5565 |
-+ <term><constant>EALREADY</constant></term> |
5566 |
-+ <listitem><para> |
5567 |
-+ Connection already owns that name. |
5568 |
-+ </para></listitem> |
5569 |
-+ </varlistentry> |
5570 |
-+ |
5571 |
-+ <varlistentry> |
5572 |
-+ <term><constant>EEXIST</constant></term> |
5573 |
-+ <listitem><para> |
5574 |
-+ The name already exists and can not be taken over. |
5575 |
-+ </para></listitem> |
5576 |
-+ </varlistentry> |
5577 |
-+ |
5578 |
-+ <varlistentry> |
5579 |
-+ <term><constant>E2BIG</constant></term> |
5580 |
-+ <listitem><para> |
5581 |
-+ The maximum number of well-known names per connection is exhausted. |
5582 |
-+ </para></listitem> |
5583 |
-+ </varlistentry> |
5584 |
-+ </variablelist> |
5585 |
-+ </refsect2> |
5586 |
-+ |
5587 |
-+ <refsect2> |
5588 |
-+ <title> |
5589 |
-+ <constant>KDBUS_CMD_NAME_RELEASE</constant> |
5590 |
-+ may fail with the following errors |
5591 |
-+ </title> |
5592 |
-+ |
5593 |
-+ <variablelist> |
5594 |
-+ <varlistentry> |
5595 |
-+ <term><constant>EINVAL</constant></term> |
5596 |
-+ <listitem><para> |
5597 |
-+ Invalid command flags, or invalid name provided. |
5598 |
-+ </para></listitem> |
5599 |
-+ </varlistentry> |
5600 |
-+ |
5601 |
-+ <varlistentry> |
5602 |
-+ <term><constant>ESRCH</constant></term> |
5603 |
-+ <listitem><para> |
5604 |
-+ Name is not found in the registry. |
5605 |
-+ </para></listitem> |
5606 |
-+ </varlistentry> |
5607 |
-+ |
5608 |
-+ <varlistentry> |
5609 |
-+ <term><constant>EADDRINUSE</constant></term> |
5610 |
-+ <listitem><para> |
5611 |
-+ Name is owned by a different connection and can't be released. |
5612 |
-+ </para></listitem> |
5613 |
-+ </varlistentry> |
5614 |
-+ </variablelist> |
5615 |
-+ </refsect2> |
5616 |
-+ |
5617 |
-+ <refsect2> |
5618 |
-+ <title> |
5619 |
-+ <constant>KDBUS_CMD_LIST</constant> may fail with the following |
5620 |
-+ errors |
5621 |
-+ </title> |
5622 |
-+ |
5623 |
-+ <variablelist> |
5624 |
-+ <varlistentry> |
5625 |
-+ <term><constant>EINVAL</constant></term> |
5626 |
-+ <listitem><para> |
5627 |
-+ Invalid command flags |
5628 |
-+ </para></listitem> |
5629 |
-+ </varlistentry> |
5630 |
-+ |
5631 |
-+ <varlistentry> |
5632 |
-+ <term><constant>ENOBUFS</constant></term> |
5633 |
-+ <listitem><para> |
5634 |
-+ No available memory in the connection's pool. |
5635 |
-+ </para></listitem> |
5636 |
-+ </varlistentry> |
5637 |
-+ </variablelist> |
5638 |
-+ </refsect2> |
5639 |
-+ </refsect1> |
5640 |
-+ |
5641 |
-+ <refsect1> |
5642 |
-+ <title>See Also</title> |
5643 |
-+ <simplelist type="inline"> |
5644 |
-+ <member> |
5645 |
-+ <citerefentry> |
5646 |
-+ <refentrytitle>kdbus</refentrytitle> |
5647 |
-+ <manvolnum>7</manvolnum> |
5648 |
-+ </citerefentry> |
5649 |
-+ </member> |
5650 |
-+ <member> |
5651 |
-+ <citerefentry> |
5652 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
5653 |
-+ <manvolnum>7</manvolnum> |
5654 |
-+ </citerefentry> |
5655 |
-+ </member> |
5656 |
-+ <member> |
5657 |
-+ <citerefentry> |
5658 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5659 |
-+ <manvolnum>7</manvolnum> |
5660 |
-+ </citerefentry> |
5661 |
-+ </member> |
5662 |
-+ <member> |
5663 |
-+ <citerefentry> |
5664 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5665 |
-+ <manvolnum>7</manvolnum> |
5666 |
-+ </citerefentry> |
5667 |
-+ </member> |
5668 |
-+ <member> |
5669 |
-+ <citerefentry> |
5670 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
5671 |
-+ <manvolnum>7</manvolnum> |
5672 |
-+ </citerefentry> |
5673 |
-+ </member> |
5674 |
-+ <member> |
5675 |
-+ <citerefentry> |
5676 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
5677 |
-+ <manvolnum>7</manvolnum> |
5678 |
-+ </citerefentry> |
5679 |
-+ </member> |
5680 |
-+ </simplelist> |
5681 |
-+ </refsect1> |
5682 |
-+</refentry> |
5683 |
-diff --git a/Documentation/kdbus/kdbus.policy.xml b/Documentation/kdbus/kdbus.policy.xml |
5684 |
-new file mode 100644 |
5685 |
-index 0000000..6732416 |
5686 |
---- /dev/null |
5687 |
-+++ b/Documentation/kdbus/kdbus.policy.xml |
5688 |
-@@ -0,0 +1,406 @@ |
5689 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
5690 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
5691 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
5692 |
-+ |
5693 |
-+<refentry id="kdbus.policy"> |
5694 |
-+ |
5695 |
-+ <refentryinfo> |
5696 |
-+ <title>kdbus.policy</title> |
5697 |
-+ <productname>kdbus.policy</productname> |
5698 |
-+ </refentryinfo> |
5699 |
-+ |
5700 |
-+ <refmeta> |
5701 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
5702 |
-+ <manvolnum>7</manvolnum> |
5703 |
-+ </refmeta> |
5704 |
-+ |
5705 |
-+ <refnamediv> |
5706 |
-+ <refname>kdbus.policy</refname> |
5707 |
-+ <refpurpose>kdbus policy</refpurpose> |
5708 |
-+ </refnamediv> |
5709 |
-+ |
5710 |
-+ <refsect1> |
5711 |
-+ <title>Description</title> |
5712 |
-+ |
5713 |
-+ <para> |
5714 |
-+ A kdbus policy restricts the possibilities of connections to own, see and |
5715 |
-+ talk to well-known names. A policy can be associated with a bus (through a |
5716 |
-+ policy holder connection) or a custom endpoint. kdbus stores its policy |
5717 |
-+ information in a database that can be accessed through the following |
5718 |
-+ ioctl commands: |
5719 |
-+ </para> |
5720 |
-+ |
5721 |
-+ <variablelist> |
5722 |
-+ <varlistentry> |
5723 |
-+ <term><constant>KDBUS_CMD_HELLO</constant></term> |
5724 |
-+ <listitem><para> |
5725 |
-+ When creating, or updating, a policy holder connection. See |
5726 |
-+ <citerefentry> |
5727 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5728 |
-+ <manvolnum>7</manvolnum> |
5729 |
-+ </citerefentry>. |
5730 |
-+ </para></listitem> |
5731 |
-+ </varlistentry> |
5732 |
-+ |
5733 |
-+ <varlistentry> |
5734 |
-+ <term><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></term> |
5735 |
-+ <term><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></term> |
5736 |
-+ <listitem><para> |
5737 |
-+ When creating, or updating, a bus custom endpoint. See |
5738 |
-+ <citerefentry> |
5739 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
5740 |
-+ <manvolnum>7</manvolnum> |
5741 |
-+ </citerefentry>. |
5742 |
-+ </para></listitem> |
5743 |
-+ </varlistentry> |
5744 |
-+ </variablelist> |
5745 |
-+ |
5746 |
-+ <para> |
5747 |
-+ In all cases, the name and policy access information is stored in items |
5748 |
-+ of type <constant>KDBUS_ITEM_NAME</constant> and |
5749 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant>. For this transport, the |
5750 |
-+ following rules apply. |
5751 |
-+ </para> |
5752 |
-+ |
5753 |
-+ <itemizedlist> |
5754 |
-+ <listitem> |
5755 |
-+ <para> |
5756 |
-+ An item of type <constant>KDBUS_ITEM_NAME</constant> must be followed |
5757 |
-+ by at least one <constant>KDBUS_ITEM_POLICY_ACCESS</constant> item. |
5758 |
-+ </para> |
5759 |
-+ </listitem> |
5760 |
-+ |
5761 |
-+ <listitem> |
5762 |
-+ <para> |
5763 |
-+ An item of type <constant>KDBUS_ITEM_NAME</constant> can be followed |
5764 |
-+ by an arbitrary number of |
5765 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> items. |
5766 |
-+ </para> |
5767 |
-+ </listitem> |
5768 |
-+ |
5769 |
-+ <listitem> |
5770 |
-+ <para> |
5771 |
-+ An arbitrary number of groups of names and access levels can be given. |
5772 |
-+ </para> |
5773 |
-+ </listitem> |
5774 |
-+ </itemizedlist> |
5775 |
-+ |
5776 |
-+ <para> |
5777 |
-+ Names passed in items of type <constant>KDBUS_ITEM_NAME</constant> must |
5778 |
-+ comply to the rules of valid kdbus.name. See |
5779 |
-+ <citerefentry> |
5780 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
5781 |
-+ <manvolnum>7</manvolnum> |
5782 |
-+ </citerefentry> |
5783 |
-+ for more information. |
5784 |
-+ |
5785 |
-+ The payload of an item of type |
5786 |
-+ <constant>KDBUS_ITEM_POLICY_ACCESS</constant> is defined by the following |
5787 |
-+ struct. For more information on the layout of items, please refer to |
5788 |
-+ <citerefentry> |
5789 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
5790 |
-+ <manvolnum>7</manvolnum> |
5791 |
-+ </citerefentry>. |
5792 |
-+ </para> |
5793 |
-+ |
5794 |
-+ <programlisting> |
5795 |
-+struct kdbus_policy_access { |
5796 |
-+ __u64 type; |
5797 |
-+ __u64 access; |
5798 |
-+ __u64 id; |
5799 |
-+}; |
5800 |
-+ </programlisting> |
5801 |
-+ |
5802 |
-+ <para>The fields in this struct are described below.</para> |
5803 |
-+ |
5804 |
-+ <variablelist> |
5805 |
-+ <varlistentry> |
5806 |
-+ <term><varname>type</varname></term> |
5807 |
-+ <listitem> |
5808 |
-+ <para> |
5809 |
-+ One of the following. |
5810 |
-+ </para> |
5811 |
-+ |
5812 |
-+ <variablelist> |
5813 |
-+ <varlistentry> |
5814 |
-+ <term><constant>KDBUS_POLICY_ACCESS_USER</constant></term> |
5815 |
-+ <listitem><para> |
5816 |
-+ Grant access to a user with the UID stored in the |
5817 |
-+ <varname>id</varname> field. |
5818 |
-+ </para></listitem> |
5819 |
-+ </varlistentry> |
5820 |
-+ |
5821 |
-+ <varlistentry> |
5822 |
-+ <term><constant>KDBUS_POLICY_ACCESS_GROUP</constant></term> |
5823 |
-+ <listitem><para> |
5824 |
-+ Grant access to a user with the GID stored in the |
5825 |
-+ <varname>id</varname> field. |
5826 |
-+ </para></listitem> |
5827 |
-+ </varlistentry> |
5828 |
-+ |
5829 |
-+ <varlistentry> |
5830 |
-+ <term><constant>KDBUS_POLICY_ACCESS_WORLD</constant></term> |
5831 |
-+ <listitem><para> |
5832 |
-+ Grant access to everyone. The <varname>id</varname> field |
5833 |
-+ is ignored. |
5834 |
-+ </para></listitem> |
5835 |
-+ </varlistentry> |
5836 |
-+ </variablelist> |
5837 |
-+ </listitem> |
5838 |
-+ </varlistentry> |
5839 |
-+ |
5840 |
-+ <varlistentry> |
5841 |
-+ <term><varname>access</varname></term> |
5842 |
-+ <listitem> |
5843 |
-+ <para> |
5844 |
-+ The access to grant. One of the following. |
5845 |
-+ </para> |
5846 |
-+ |
5847 |
-+ <variablelist> |
5848 |
-+ <varlistentry> |
5849 |
-+ <term><constant>KDBUS_POLICY_SEE</constant></term> |
5850 |
-+ <listitem><para> |
5851 |
-+ Allow the name to be seen. |
5852 |
-+ </para></listitem> |
5853 |
-+ </varlistentry> |
5854 |
-+ |
5855 |
-+ <varlistentry> |
5856 |
-+ <term><constant>KDBUS_POLICY_TALK</constant></term> |
5857 |
-+ <listitem><para> |
5858 |
-+ Allow the name to be talked to. |
5859 |
-+ </para></listitem> |
5860 |
-+ </varlistentry> |
5861 |
-+ |
5862 |
-+ <varlistentry> |
5863 |
-+ <term><constant>KDBUS_POLICY_OWN</constant></term> |
5864 |
-+ <listitem><para> |
5865 |
-+ Allow the name to be owned. |
5866 |
-+ </para></listitem> |
5867 |
-+ </varlistentry> |
5868 |
-+ </variablelist> |
5869 |
-+ </listitem> |
5870 |
-+ </varlistentry> |
5871 |
-+ |
5872 |
-+ <varlistentry> |
5873 |
-+ <term><varname>id</varname></term> |
5874 |
-+ <listitem><para> |
5875 |
-+ For <constant>KDBUS_POLICY_ACCESS_USER</constant>, stores the UID. |
5876 |
-+ For <constant>KDBUS_POLICY_ACCESS_GROUP</constant>, stores the GID. |
5877 |
-+ </para></listitem> |
5878 |
-+ </varlistentry> |
5879 |
-+ |
5880 |
-+ </variablelist> |
5881 |
-+ |
5882 |
-+ <para> |
5883 |
-+ All endpoints of buses have an empty policy database by default. |
5884 |
-+ Therefore, unless policy rules are added, all operations will also be |
5885 |
-+ denied by default. Also see |
5886 |
-+ <citerefentry> |
5887 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
5888 |
-+ <manvolnum>7</manvolnum> |
5889 |
-+ </citerefentry>. |
5890 |
-+ </para> |
5891 |
-+ </refsect1> |
5892 |
-+ |
5893 |
-+ <refsect1> |
5894 |
-+ <title>Wildcard names</title> |
5895 |
-+ <para> |
5896 |
-+ Policy holder connections may upload names that contain the wildcard |
5897 |
-+ suffix (<literal>".*"</literal>). Such a policy entry is effective for |
5898 |
-+ every well-known name that extends the provided name by exactly one more |
5899 |
-+ level. |
5900 |
-+ |
5901 |
-+ For example, the name <literal>foo.bar.*</literal> matches both |
5902 |
-+ <literal>"foo.bar.baz"</literal> and |
5903 |
-+ <literal>"foo.bar.bazbaz"</literal> are, but not |
5904 |
-+ <literal>"foo.bar.baz.baz"</literal>. |
5905 |
-+ |
5906 |
-+ This allows connections to take control over multiple names that the |
5907 |
-+ policy holder doesn't need to know about when uploading the policy. |
5908 |
-+ |
5909 |
-+ Such wildcard entries are not allowed for custom endpoints. |
5910 |
-+ </para> |
5911 |
-+ </refsect1> |
5912 |
-+ |
5913 |
-+ <refsect1> |
5914 |
-+ <title>Privileged connections</title> |
5915 |
-+ <para> |
5916 |
-+ The policy database is overruled when action is taken by a privileged |
5917 |
-+ connection. Please refer to |
5918 |
-+ <citerefentry> |
5919 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
5920 |
-+ <manvolnum>7</manvolnum> |
5921 |
-+ </citerefentry> |
5922 |
-+ for more information on what makes a connection privileged. |
5923 |
-+ </para> |
5924 |
-+ </refsect1> |
5925 |
-+ |
5926 |
-+ <refsect1> |
5927 |
-+ <title>Examples</title> |
5928 |
-+ <para> |
5929 |
-+ For instance, a set of policy rules may look like this: |
5930 |
-+ </para> |
5931 |
-+ |
5932 |
-+ <programlisting> |
5933 |
-+KDBUS_ITEM_NAME: str='org.foo.bar' |
5934 |
-+KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=1000 |
5935 |
-+KDBUS_ITEM_POLICY_ACCESS: type=USER, access=TALK, ID=1001 |
5936 |
-+KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=SEE |
5937 |
-+ |
5938 |
-+KDBUS_ITEM_NAME: str='org.blah.baz' |
5939 |
-+KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=0 |
5940 |
-+KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=TALK |
5941 |
-+ </programlisting> |
5942 |
-+ |
5943 |
-+ <para> |
5944 |
-+ That means that 'org.foo.bar' may only be owned by UID 1000, but every |
5945 |
-+ user on the bus is allowed to see the name. However, only UID 1001 may |
5946 |
-+ actually send a message to the connection and receive a reply from it. |
5947 |
-+ |
5948 |
-+ The second rule allows 'org.blah.baz' to be owned by UID 0 only, but |
5949 |
-+ every user may talk to it. |
5950 |
-+ </para> |
5951 |
-+ </refsect1> |
5952 |
-+ |
5953 |
-+ <refsect1> |
5954 |
-+ <title>TALK access and multiple well-known names per connection</title> |
5955 |
-+ <para> |
5956 |
-+ Note that TALK access is checked against all names of a connection. For |
5957 |
-+ example, if a connection owns both <constant>'org.foo.bar'</constant> and |
5958 |
-+ <constant>'org.blah.baz'</constant>, and the policy database allows |
5959 |
-+ <constant>'org.blah.baz'</constant> to be talked to by WORLD, then this |
5960 |
-+ permission is also granted to <constant>'org.foo.bar'</constant>. That |
5961 |
-+ might sound illogical, but after all, we allow messages to be directed to |
5962 |
-+ either the ID or a well-known name, and policy is applied to the |
5963 |
-+ connection, not the name. In other words, the effective TALK policy for a |
5964 |
-+ connection is the most permissive of all names the connection owns. |
5965 |
-+ |
5966 |
-+ For broadcast messages, the receiver needs TALK permissions to the sender |
5967 |
-+ to receive the broadcast. |
5968 |
-+ </para> |
5969 |
-+ <para> |
5970 |
-+ Both the endpoint and the bus policy databases are consulted to allow |
5971 |
-+ name registry listing, owning a well-known name and message delivery. |
5972 |
-+ If either one fails, the operation is failed with |
5973 |
-+ <varname>errno</varname> set to <constant>EPERM</constant>. |
5974 |
-+ |
5975 |
-+ For best practices, connections that own names with a restricted TALK |
5976 |
-+ access should not install matches. This avoids cases where the sent |
5977 |
-+ message may pass the bloom filter due to false-positives and may also |
5978 |
-+ satisfy the policy rules. |
5979 |
-+ |
5980 |
-+ Also see |
5981 |
-+ <citerefentry> |
5982 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
5983 |
-+ <manvolnum>7</manvolnum> |
5984 |
-+ </citerefentry>. |
5985 |
-+ </para> |
5986 |
-+ </refsect1> |
5987 |
-+ |
5988 |
-+ <refsect1> |
5989 |
-+ <title>Implicit policies</title> |
5990 |
-+ <para> |
5991 |
-+ Depending on the type of the endpoint, a set of implicit rules that |
5992 |
-+ override installed policies might be enforced. |
5993 |
-+ |
5994 |
-+ On default endpoints, the following set is enforced and checked before |
5995 |
-+ any user-supplied policy is checked. |
5996 |
-+ </para> |
5997 |
-+ |
5998 |
-+ <itemizedlist> |
5999 |
-+ <listitem> |
6000 |
-+ <para> |
6001 |
-+ Privileged connections always override any installed policy. Those |
6002 |
-+ connections could easily install their own policies, so there is no |
6003 |
-+ reason to enforce installed policies. |
6004 |
-+ </para> |
6005 |
-+ </listitem> |
6006 |
-+ <listitem> |
6007 |
-+ <para> |
6008 |
-+ Connections can always talk to connections of the same user. This |
6009 |
-+ includes broadcast messages. |
6010 |
-+ </para> |
6011 |
-+ </listitem> |
6012 |
-+ </itemizedlist> |
6013 |
-+ |
6014 |
-+ <para> |
6015 |
-+ Custom endpoints have stricter policies. The following rules apply: |
6016 |
-+ </para> |
6017 |
-+ |
6018 |
-+ <itemizedlist> |
6019 |
-+ <listitem> |
6020 |
-+ <para> |
6021 |
-+ Policy rules are always enforced, even if the connection is a |
6022 |
-+ privileged connection. |
6023 |
-+ </para> |
6024 |
-+ </listitem> |
6025 |
-+ <listitem> |
6026 |
-+ <para> |
6027 |
-+ Policy rules are always enforced for <constant>TALK</constant> access, |
6028 |
-+ even if both ends are running under the same user. This includes |
6029 |
-+ broadcast messages. |
6030 |
-+ </para> |
6031 |
-+ </listitem> |
6032 |
-+ <listitem> |
6033 |
-+ <para> |
6034 |
-+ To restrict the set of names that can be seen, endpoint policies can |
6035 |
-+ install <constant>SEE</constant> policies. |
6036 |
-+ </para> |
6037 |
-+ </listitem> |
6038 |
-+ </itemizedlist> |
6039 |
-+ </refsect1> |
6040 |
-+ |
6041 |
-+ <refsect1> |
6042 |
-+ <title>See Also</title> |
6043 |
-+ <simplelist type="inline"> |
6044 |
-+ <member> |
6045 |
-+ <citerefentry> |
6046 |
-+ <refentrytitle>kdbus</refentrytitle> |
6047 |
-+ <manvolnum>7</manvolnum> |
6048 |
-+ </citerefentry> |
6049 |
-+ </member> |
6050 |
-+ <member> |
6051 |
-+ <citerefentry> |
6052 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
6053 |
-+ <manvolnum>7</manvolnum> |
6054 |
-+ </citerefentry> |
6055 |
-+ </member> |
6056 |
-+ <member> |
6057 |
-+ <citerefentry> |
6058 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
6059 |
-+ <manvolnum>7</manvolnum> |
6060 |
-+ </citerefentry> |
6061 |
-+ </member> |
6062 |
-+ <member> |
6063 |
-+ <citerefentry> |
6064 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
6065 |
-+ <manvolnum>7</manvolnum> |
6066 |
-+ </citerefentry> |
6067 |
-+ </member> |
6068 |
-+ <member> |
6069 |
-+ <citerefentry> |
6070 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
6071 |
-+ <manvolnum>7</manvolnum> |
6072 |
-+ </citerefentry> |
6073 |
-+ </member> |
6074 |
-+ <member> |
6075 |
-+ <citerefentry> |
6076 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
6077 |
-+ <manvolnum>7</manvolnum> |
6078 |
-+ </citerefentry> |
6079 |
-+ </member> |
6080 |
-+ <member> |
6081 |
-+ <citerefentry> |
6082 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6083 |
-+ <manvolnum>7</manvolnum> |
6084 |
-+ </citerefentry> |
6085 |
-+ </member> |
6086 |
-+ <member> |
6087 |
-+ <citerefentry> |
6088 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
6089 |
-+ <manvolnum>7</manvolnum> |
6090 |
-+ </citerefentry> |
6091 |
-+ </member> |
6092 |
-+ </simplelist> |
6093 |
-+ </refsect1> |
6094 |
-+</refentry> |
6095 |
-diff --git a/Documentation/kdbus/kdbus.pool.xml b/Documentation/kdbus/kdbus.pool.xml |
6096 |
-new file mode 100644 |
6097 |
-index 0000000..a9e16f1 |
6098 |
---- /dev/null |
6099 |
-+++ b/Documentation/kdbus/kdbus.pool.xml |
6100 |
-@@ -0,0 +1,326 @@ |
6101 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
6102 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
6103 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
6104 |
-+ |
6105 |
-+<refentry id="kdbus.pool"> |
6106 |
-+ |
6107 |
-+ <refentryinfo> |
6108 |
-+ <title>kdbus.pool</title> |
6109 |
-+ <productname>kdbus.pool</productname> |
6110 |
-+ </refentryinfo> |
6111 |
-+ |
6112 |
-+ <refmeta> |
6113 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
6114 |
-+ <manvolnum>7</manvolnum> |
6115 |
-+ </refmeta> |
6116 |
-+ |
6117 |
-+ <refnamediv> |
6118 |
-+ <refname>kdbus.pool</refname> |
6119 |
-+ <refpurpose>kdbus pool</refpurpose> |
6120 |
-+ </refnamediv> |
6121 |
-+ |
6122 |
-+ <refsect1> |
6123 |
-+ <title>Description</title> |
6124 |
-+ <para> |
6125 |
-+ A pool for data received from the kernel is installed for every |
6126 |
-+ <emphasis>connection</emphasis> of the <emphasis>bus</emphasis>, and |
6127 |
-+ is sized according to the information stored in the |
6128 |
-+ <varname>pool_size</varname> member of <type>struct kdbus_cmd_hello</type> |
6129 |
-+ when <constant>KDBUS_CMD_HELLO</constant> is employed. Internally, the |
6130 |
-+ pool is segmented into <emphasis>slices</emphasis>, each referenced by its |
6131 |
-+ <emphasis>offset</emphasis> in the pool, expressed in <type>bytes</type>. |
6132 |
-+ See |
6133 |
-+ <citerefentry> |
6134 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6135 |
-+ <manvolnum>7</manvolnum> |
6136 |
-+ </citerefentry> |
6137 |
-+ for more information about <constant>KDBUS_CMD_HELLO</constant>. |
6138 |
-+ </para> |
6139 |
-+ |
6140 |
-+ <para> |
6141 |
-+ The pool is written to by the kernel when one of the following |
6142 |
-+ <emphasis>ioctls</emphasis> is issued: |
6143 |
-+ |
6144 |
-+ <variablelist> |
6145 |
-+ <varlistentry> |
6146 |
-+ <term><constant>KDBUS_CMD_HELLO</constant></term> |
6147 |
-+ <listitem><para> |
6148 |
-+ ... to receive details about the bus the connection was made to |
6149 |
-+ </para></listitem> |
6150 |
-+ </varlistentry> |
6151 |
-+ <varlistentry> |
6152 |
-+ <term><constant>KDBUS_CMD_RECV</constant></term> |
6153 |
-+ <listitem><para> |
6154 |
-+ ... to receive a message |
6155 |
-+ </para></listitem> |
6156 |
-+ </varlistentry> |
6157 |
-+ <varlistentry> |
6158 |
-+ <term><constant>KDBUS_CMD_LIST</constant></term> |
6159 |
-+ <listitem><para> |
6160 |
-+ ... to dump the name registry |
6161 |
-+ </para></listitem> |
6162 |
-+ </varlistentry> |
6163 |
-+ <varlistentry> |
6164 |
-+ <term><constant>KDBUS_CMD_CONN_INFO</constant></term> |
6165 |
-+ <listitem><para> |
6166 |
-+ ... to retrieve information on a connection |
6167 |
-+ </para></listitem> |
6168 |
-+ </varlistentry> |
6169 |
-+ <varlistentry> |
6170 |
-+ <term><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></term> |
6171 |
-+ <listitem><para> |
6172 |
-+ ... to retrieve information about a connection's bus creator |
6173 |
-+ </para></listitem> |
6174 |
-+ </varlistentry> |
6175 |
-+ </variablelist> |
6176 |
-+ |
6177 |
-+ </para> |
6178 |
-+ <para> |
6179 |
-+ The <varname>offset</varname> fields returned by either one of the |
6180 |
-+ aforementioned ioctls describe offsets inside the pool. In order to make |
6181 |
-+ the slice available for subsequent calls, |
6182 |
-+ <constant>KDBUS_CMD_FREE</constant> has to be called on that offset |
6183 |
-+ (see below). Otherwise, the pool will fill up, and the connection won't |
6184 |
-+ be able to receive any more information through its pool. |
6185 |
-+ </para> |
6186 |
-+ </refsect1> |
6187 |
-+ |
6188 |
-+ <refsect1> |
6189 |
-+ <title>Pool slice allocation</title> |
6190 |
-+ <para> |
6191 |
-+ Pool slices are allocated by the kernel in order to report information |
6192 |
-+ back to a task, such as messages, returned name list etc. |
6193 |
-+ Allocation of pool slices cannot be initiated by userspace. See |
6194 |
-+ <citerefentry> |
6195 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6196 |
-+ <manvolnum>7</manvolnum> |
6197 |
-+ </citerefentry> |
6198 |
-+ and |
6199 |
-+ <citerefentry> |
6200 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6201 |
-+ <manvolnum>7</manvolnum> |
6202 |
-+ </citerefentry> |
6203 |
-+ for examples of commands that use the <emphasis>pool</emphasis> to |
6204 |
-+ return data. |
6205 |
-+ </para> |
6206 |
-+ </refsect1> |
6207 |
-+ |
6208 |
-+ <refsect1> |
6209 |
-+ <title>Accessing the pool memory</title> |
6210 |
-+ <para> |
6211 |
-+ Memory in the pool is read-only for userspace and may only be written |
6212 |
-+ to by the kernel. To read from the pool memory, the caller is expected to |
6213 |
-+ <citerefentry> |
6214 |
-+ <refentrytitle>mmap</refentrytitle> |
6215 |
-+ <manvolnum>2</manvolnum> |
6216 |
-+ </citerefentry> |
6217 |
-+ the buffer into its task, like this: |
6218 |
-+ </para> |
6219 |
-+ <programlisting> |
6220 |
-+uint8_t *buf = mmap(NULL, size, PROT_READ, MAP_SHARED, conn_fd, 0); |
6221 |
-+ </programlisting> |
6222 |
-+ |
6223 |
-+ <para> |
6224 |
-+ In order to map the entire pool, the <varname>size</varname> parameter in |
6225 |
-+ the example above should be set to the value of the |
6226 |
-+ <varname>pool_size</varname> member of |
6227 |
-+ <type>struct kdbus_cmd_hello</type> when |
6228 |
-+ <constant>KDBUS_CMD_HELLO</constant> was employed to create the |
6229 |
-+ connection (see above). |
6230 |
-+ </para> |
6231 |
-+ |
6232 |
-+ <para> |
6233 |
-+ The <emphasis>file descriptor</emphasis> used to map the memory must be |
6234 |
-+ the one that was used to create the <emphasis>connection</emphasis>. |
6235 |
-+ In other words, the one that was used to call |
6236 |
-+ <constant>KDBUS_CMD_HELLO</constant>. See |
6237 |
-+ <citerefentry> |
6238 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6239 |
-+ <manvolnum>7</manvolnum> |
6240 |
-+ </citerefentry> |
6241 |
-+ for more details. |
6242 |
-+ </para> |
6243 |
-+ |
6244 |
-+ <para> |
6245 |
-+ Alternatively, instead of mapping the entire pool buffer, only parts |
6246 |
-+ of it can be mapped. Every kdbus command that returns an |
6247 |
-+ <emphasis>offset</emphasis> (see above) also reports a |
6248 |
-+ <emphasis>size</emphasis> along with it, so programs can be written |
6249 |
-+ in a way that it only maps portions of the pool to access a specific |
6250 |
-+ <emphasis>slice</emphasis>. |
6251 |
-+ </para> |
6252 |
-+ |
6253 |
-+ <para> |
6254 |
-+ When access to the pool memory is no longer needed, programs should |
6255 |
-+ call <function>munmap()</function> on the pointer returned by |
6256 |
-+ <function>mmap()</function>. |
6257 |
-+ </para> |
6258 |
-+ </refsect1> |
6259 |
-+ |
6260 |
-+ <refsect1> |
6261 |
-+ <title>Freeing pool slices</title> |
6262 |
-+ <para> |
6263 |
-+ The <constant>KDBUS_CMD_FREE</constant> ioctl is used to free a slice |
6264 |
-+ inside the pool, describing an offset that was returned in an |
6265 |
-+ <varname>offset</varname> field of another ioctl struct. |
6266 |
-+ The <constant>KDBUS_CMD_FREE</constant> command takes a |
6267 |
-+ <type>struct kdbus_cmd_free</type> as argument. |
6268 |
-+ </para> |
6269 |
-+ |
6270 |
-+<programlisting> |
6271 |
-+struct kdbus_cmd_free { |
6272 |
-+ __u64 size; |
6273 |
-+ __u64 flags; |
6274 |
-+ __u64 return_flags; |
6275 |
-+ __u64 offset; |
6276 |
-+ struct kdbus_item items[0]; |
6277 |
-+}; |
6278 |
-+</programlisting> |
6279 |
-+ |
6280 |
-+ <para>The fields in this struct are described below.</para> |
6281 |
-+ |
6282 |
-+ <variablelist> |
6283 |
-+ <varlistentry> |
6284 |
-+ <term><varname>size</varname></term> |
6285 |
-+ <listitem><para> |
6286 |
-+ The overall size of the struct, including its items. |
6287 |
-+ </para></listitem> |
6288 |
-+ </varlistentry> |
6289 |
-+ |
6290 |
-+ <varlistentry> |
6291 |
-+ <term><varname>flags</varname></term> |
6292 |
-+ <listitem><para> |
6293 |
-+ Currently unused. |
6294 |
-+ <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for |
6295 |
-+ valid flags. If set, the ioctl will return <errorcode>0</errorcode>, |
6296 |
-+ and the <varname>flags</varname> field is set to |
6297 |
-+ <constant>0</constant>. |
6298 |
-+ </para></listitem> |
6299 |
-+ </varlistentry> |
6300 |
-+ |
6301 |
-+ <varlistentry> |
6302 |
-+ <term><varname>return_flags</varname></term> |
6303 |
-+ <listitem><para> |
6304 |
-+ Flags returned by the kernel. Currently unused and always set to |
6305 |
-+ <constant>0</constant> by the kernel. |
6306 |
-+ </para></listitem> |
6307 |
-+ </varlistentry> |
6308 |
-+ |
6309 |
-+ <varlistentry> |
6310 |
-+ <term><varname>offset</varname></term> |
6311 |
-+ <listitem><para> |
6312 |
-+ The offset to free, as returned by other ioctls that allocated |
6313 |
-+ memory for returned information. |
6314 |
-+ </para></listitem> |
6315 |
-+ </varlistentry> |
6316 |
-+ |
6317 |
-+ <varlistentry> |
6318 |
-+ <term><varname>items</varname></term> |
6319 |
-+ <listitem><para> |
6320 |
-+ Items to specify further details for the receive command. |
6321 |
-+ Currently unused. |
6322 |
-+ Unrecognized items are rejected, and the ioctl will fail with |
6323 |
-+ <varname>errno</varname> set to <constant>EINVAL</constant>. |
6324 |
-+ All items except for |
6325 |
-+ <constant>KDBUS_ITEM_NEGOTIATE</constant> (see |
6326 |
-+ <citerefentry> |
6327 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
6328 |
-+ <manvolnum>7</manvolnum> |
6329 |
-+ </citerefentry> |
6330 |
-+ ) will be rejected. |
6331 |
-+ </para></listitem> |
6332 |
-+ </varlistentry> |
6333 |
-+ </variablelist> |
6334 |
-+ </refsect1> |
6335 |
-+ |
6336 |
-+ <refsect1> |
6337 |
-+ <title>Return value</title> |
6338 |
-+ <para> |
6339 |
-+ On success, all mentioned ioctl commands return <errorcode>0</errorcode>; |
6340 |
-+ on error, <errorcode>-1</errorcode> is returned, and |
6341 |
-+ <varname>errno</varname> is set to indicate the error. |
6342 |
-+ If the issued ioctl is illegal for the file descriptor used, |
6343 |
-+ <varname>errno</varname> will be set to <constant>ENOTTY</constant>. |
6344 |
-+ </para> |
6345 |
-+ |
6346 |
-+ <refsect2> |
6347 |
-+ <title> |
6348 |
-+ <constant>KDBUS_CMD_FREE</constant> may fail with the following |
6349 |
-+ errors |
6350 |
-+ </title> |
6351 |
-+ |
6352 |
-+ <variablelist> |
6353 |
-+ <varlistentry> |
6354 |
-+ <term><constant>ENXIO</constant></term> |
6355 |
-+ <listitem><para> |
6356 |
-+ No pool slice found at given offset. |
6357 |
-+ </para></listitem> |
6358 |
-+ </varlistentry> |
6359 |
-+ |
6360 |
-+ <varlistentry> |
6361 |
-+ <term><constant>EINVAL</constant></term> |
6362 |
-+ <listitem><para> |
6363 |
-+ Invalid flags provided. |
6364 |
-+ </para></listitem> |
6365 |
-+ </varlistentry> |
6366 |
-+ |
6367 |
-+ <varlistentry> |
6368 |
-+ <term><constant>EINVAL</constant></term> |
6369 |
-+ <listitem><para> |
6370 |
-+ The offset is valid, but the user is not allowed to free the slice. |
6371 |
-+ This happens, for example, if the offset was retrieved with |
6372 |
-+ <constant>KDBUS_RECV_PEEK</constant>. |
6373 |
-+ </para></listitem> |
6374 |
-+ </varlistentry> |
6375 |
-+ </variablelist> |
6376 |
-+ </refsect2> |
6377 |
-+ </refsect1> |
6378 |
-+ |
6379 |
-+ <refsect1> |
6380 |
-+ <title>See Also</title> |
6381 |
-+ <simplelist type="inline"> |
6382 |
-+ <member> |
6383 |
-+ <citerefentry> |
6384 |
-+ <refentrytitle>kdbus</refentrytitle> |
6385 |
-+ <manvolnum>7</manvolnum> |
6386 |
-+ </citerefentry> |
6387 |
-+ </member> |
6388 |
-+ <member> |
6389 |
-+ <citerefentry> |
6390 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
6391 |
-+ <manvolnum>7</manvolnum> |
6392 |
-+ </citerefentry> |
6393 |
-+ </member> |
6394 |
-+ <member> |
6395 |
-+ <citerefentry> |
6396 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6397 |
-+ <manvolnum>7</manvolnum> |
6398 |
-+ </citerefentry> |
6399 |
-+ </member> |
6400 |
-+ <member> |
6401 |
-+ <citerefentry> |
6402 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
6403 |
-+ <manvolnum>7</manvolnum> |
6404 |
-+ </citerefentry> |
6405 |
-+ </member> |
6406 |
-+ <member> |
6407 |
-+ <citerefentry> |
6408 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6409 |
-+ <manvolnum>7</manvolnum> |
6410 |
-+ </citerefentry> |
6411 |
-+ </member> |
6412 |
-+ <member> |
6413 |
-+ <citerefentry> |
6414 |
-+ <refentrytitle>mmap</refentrytitle> |
6415 |
-+ <manvolnum>2</manvolnum> |
6416 |
-+ </citerefentry> |
6417 |
-+ </member> |
6418 |
-+ <member> |
6419 |
-+ <citerefentry> |
6420 |
-+ <refentrytitle>munmap</refentrytitle> |
6421 |
-+ <manvolnum>2</manvolnum> |
6422 |
-+ </citerefentry> |
6423 |
-+ </member> |
6424 |
-+ </simplelist> |
6425 |
-+ </refsect1> |
6426 |
-+</refentry> |
6427 |
-diff --git a/Documentation/kdbus/kdbus.xml b/Documentation/kdbus/kdbus.xml |
6428 |
-new file mode 100644 |
6429 |
-index 0000000..d8e7400 |
6430 |
---- /dev/null |
6431 |
-+++ b/Documentation/kdbus/kdbus.xml |
6432 |
-@@ -0,0 +1,1012 @@ |
6433 |
-+<?xml version='1.0'?> <!--*-nxml-*--> |
6434 |
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" |
6435 |
-+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> |
6436 |
-+ |
6437 |
-+<refentry id="kdbus"> |
6438 |
-+ |
6439 |
-+ <refentryinfo> |
6440 |
-+ <title>kdbus</title> |
6441 |
-+ <productname>kdbus</productname> |
6442 |
-+ </refentryinfo> |
6443 |
-+ |
6444 |
-+ <refmeta> |
6445 |
-+ <refentrytitle>kdbus</refentrytitle> |
6446 |
-+ <manvolnum>7</manvolnum> |
6447 |
-+ </refmeta> |
6448 |
-+ |
6449 |
-+ <refnamediv> |
6450 |
-+ <refname>kdbus</refname> |
6451 |
-+ <refpurpose>Kernel Message Bus</refpurpose> |
6452 |
-+ </refnamediv> |
6453 |
-+ |
6454 |
-+ <refsect1> |
6455 |
-+ <title>Synopsis</title> |
6456 |
-+ <para> |
6457 |
-+ kdbus is an inter-process communication bus system controlled by the |
6458 |
-+ kernel. It provides user-space with an API to create buses and send |
6459 |
-+ unicast and multicast messages to one, or many, peers connected to the |
6460 |
-+ same bus. It does not enforce any layout on the transmitted data, but |
6461 |
-+ only provides the transport layer used for message interchange between |
6462 |
-+ peers. |
6463 |
-+ </para> |
6464 |
-+ <para> |
6465 |
-+ This set of man-pages gives a comprehensive overview of the kernel-level |
6466 |
-+ API, with all ioctl commands, associated structs and bit masks. However, |
6467 |
-+ most people will not use this API level directly, but rather let one of |
6468 |
-+ the high-level abstraction libraries help them integrate D-Bus |
6469 |
-+ functionality into their applications. |
6470 |
-+ </para> |
6471 |
-+ </refsect1> |
6472 |
-+ |
6473 |
-+ <refsect1> |
6474 |
-+ <title>Description</title> |
6475 |
-+ <para> |
6476 |
-+ kdbus provides a pseudo filesystem called <emphasis>kdbusfs</emphasis>, |
6477 |
-+ which is usually mounted on <filename>/sys/fs/kdbus</filename>. Bus |
6478 |
-+ primitives can be accessed as files and sub-directories underneath this |
6479 |
-+ mount-point. Any advanced operations are done via |
6480 |
-+ <function>ioctl()</function> on files created by |
6481 |
-+ <emphasis>kdbusfs</emphasis>. Multiple mount-points of |
6482 |
-+ <emphasis>kdbusfs</emphasis> are independent of each other. This allows |
6483 |
-+ namespacing of kdbus by mounting a new instance of |
6484 |
-+ <emphasis>kdbusfs</emphasis> in a new mount-namespace. kdbus calls these |
6485 |
-+ mount instances domains and each bus belongs to exactly one domain. |
6486 |
-+ </para> |
6487 |
-+ |
6488 |
-+ <para> |
6489 |
-+ kdbus was designed as a transport layer for D-Bus, but is in no way |
6490 |
-+ limited, nor controlled by the D-Bus protocol specification. The D-Bus |
6491 |
-+ protocol is one possible application layer on top of kdbus. |
6492 |
-+ </para> |
6493 |
-+ |
6494 |
-+ <para> |
6495 |
-+ For the general D-Bus protocol specification, its payload format, its |
6496 |
-+ marshaling, and its communication semantics, please refer to the |
6497 |
-+ <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html"> |
6498 |
-+ D-Bus specification</ulink>. |
6499 |
-+ </para> |
6500 |
-+ |
6501 |
-+ </refsect1> |
6502 |
-+ |
6503 |
-+ <refsect1> |
6504 |
-+ <title>Terminology</title> |
6505 |
-+ |
6506 |
-+ <refsect2> |
6507 |
-+ <title>Domain</title> |
6508 |
-+ <para> |
6509 |
-+ A domain is a <emphasis>kdbusfs</emphasis> mount-point containing all |
6510 |
-+ the bus primitives. Each domain is independent, and separate domains |
6511 |
-+ do not affect each other. |
6512 |
-+ </para> |
6513 |
-+ </refsect2> |
6514 |
-+ |
6515 |
-+ <refsect2> |
6516 |
-+ <title>Bus</title> |
6517 |
-+ <para> |
6518 |
-+ A bus is a named object inside a domain. Clients exchange messages |
6519 |
-+ over a bus. Multiple buses themselves have no connection to each other; |
6520 |
-+ messages can only be exchanged on the same bus. The default endpoint of |
6521 |
-+ a bus, to which clients establish connections, is the "bus" file |
6522 |
-+ /sys/fs/kdbus/<bus name>/bus. |
6523 |
-+ Common operating system setups create one "system bus" per system, |
6524 |
-+ and one "user bus" for every logged-in user. Applications or services |
6525 |
-+ may create their own private buses. The kernel driver does not |
6526 |
-+ distinguish between different bus types, they are all handled the same |
6527 |
-+ way. See |
6528 |
-+ <citerefentry> |
6529 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
6530 |
-+ <manvolnum>7</manvolnum> |
6531 |
-+ </citerefentry> |
6532 |
-+ for more details. |
6533 |
-+ </para> |
6534 |
-+ </refsect2> |
6535 |
-+ |
6536 |
-+ <refsect2> |
6537 |
-+ <title>Endpoint</title> |
6538 |
-+ <para> |
6539 |
-+ An endpoint provides a file to talk to a bus. Opening an endpoint |
6540 |
-+ creates a new connection to the bus to which the endpoint belongs. All |
6541 |
-+ endpoints have unique names and are accessible as files underneath the |
6542 |
-+ directory of a bus, e.g., /sys/fs/kdbus/<bus>/<endpoint> |
6543 |
-+ Every bus has a default endpoint called "bus". |
6544 |
-+ A bus can optionally offer additional endpoints with custom names |
6545 |
-+ to provide restricted access to the bus. Custom endpoints carry |
6546 |
-+ additional policy which can be used to create sandboxes with |
6547 |
-+ locked-down, limited, filtered access to a bus. See |
6548 |
-+ <citerefentry> |
6549 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
6550 |
-+ <manvolnum>7</manvolnum> |
6551 |
-+ </citerefentry> |
6552 |
-+ for more details. |
6553 |
-+ </para> |
6554 |
-+ </refsect2> |
6555 |
-+ |
6556 |
-+ <refsect2> |
6557 |
-+ <title>Connection</title> |
6558 |
-+ <para> |
6559 |
-+ A connection to a bus is created by opening an endpoint file of a |
6560 |
-+ bus. Every ordinary client connection has a unique identifier on the |
6561 |
-+ bus and can address messages to every other connection on the same |
6562 |
-+ bus by using the peer's connection ID as the destination. See |
6563 |
-+ <citerefentry> |
6564 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6565 |
-+ <manvolnum>7</manvolnum> |
6566 |
-+ </citerefentry> |
6567 |
-+ for more details. |
6568 |
-+ </para> |
6569 |
-+ </refsect2> |
6570 |
-+ |
6571 |
-+ <refsect2> |
6572 |
-+ <title>Pool</title> |
6573 |
-+ <para> |
6574 |
-+ Each connection allocates a piece of shmem-backed memory that is |
6575 |
-+ used to receive messages and answers to ioctl commands from the kernel. |
6576 |
-+ It is never used to send anything to the kernel. In order to access that |
6577 |
-+ memory, an application must mmap() it into its address space. See |
6578 |
-+ <citerefentry> |
6579 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
6580 |
-+ <manvolnum>7</manvolnum> |
6581 |
-+ </citerefentry> |
6582 |
-+ for more details. |
6583 |
-+ </para> |
6584 |
-+ </refsect2> |
6585 |
-+ |
6586 |
-+ <refsect2> |
6587 |
-+ <title>Well-known Name</title> |
6588 |
-+ <para> |
6589 |
-+ A connection can, in addition to its implicit unique connection ID, |
6590 |
-+ request the ownership of a textual well-known name. Well-known names are |
6591 |
-+ noted in reverse-domain notation, such as com.example.service1. A |
6592 |
-+ connection that offers a service on a bus is usually reached by its |
6593 |
-+ well-known name. An analogy of connection ID and well-known name is an |
6594 |
-+ IP address and a DNS name associated with that address. See |
6595 |
-+ <citerefentry> |
6596 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
6597 |
-+ <manvolnum>7</manvolnum> |
6598 |
-+ </citerefentry> |
6599 |
-+ for more details. |
6600 |
-+ </para> |
6601 |
-+ </refsect2> |
6602 |
-+ |
6603 |
-+ <refsect2> |
6604 |
-+ <title>Message</title> |
6605 |
-+ <para> |
6606 |
-+ Connections can exchange messages with other connections by addressing |
6607 |
-+ the peers with their connection ID or well-known name. A message |
6608 |
-+ consists of a message header with information on how to route the |
6609 |
-+ message, and the message payload, which is a logical byte stream of |
6610 |
-+ arbitrary size. Messages can carry additional file descriptors to be |
6611 |
-+ passed from one connection to another, just like passing file |
6612 |
-+ descriptors over UNIX domain sockets. Every connection can specify which |
6613 |
-+ set of metadata the kernel should attach to the message when it is |
6614 |
-+ delivered to the receiving connection. Metadata contains information |
6615 |
-+ like: system time stamps, UID, GID, TID, proc-starttime, well-known |
6616 |
-+ names, process comm, process exe, process argv, cgroup, capabilities, |
6617 |
-+ seclabel, audit session, loginuid and the connection's human-readable |
6618 |
-+ name. See |
6619 |
-+ <citerefentry> |
6620 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
6621 |
-+ <manvolnum>7</manvolnum> |
6622 |
-+ </citerefentry> |
6623 |
-+ for more details. |
6624 |
-+ </para> |
6625 |
-+ </refsect2> |
6626 |
-+ |
6627 |
-+ <refsect2> |
6628 |
-+ <title>Item</title> |
6629 |
-+ <para> |
6630 |
-+ The API of kdbus implements the notion of items, submitted through and |
6631 |
-+ returned by most ioctls, and stored inside data structures in the |
6632 |
-+ connection's pool. See |
6633 |
-+ <citerefentry> |
6634 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
6635 |
-+ <manvolnum>7</manvolnum> |
6636 |
-+ </citerefentry> |
6637 |
-+ for more details. |
6638 |
-+ </para> |
6639 |
-+ </refsect2> |
6640 |
-+ |
6641 |
-+ <refsect2> |
6642 |
-+ <title>Broadcast, signal, filter, match</title> |
6643 |
-+ <para> |
6644 |
-+ Signals are messages that a receiver opts in for by installing a blob of |
6645 |
-+ bytes, called a 'match'. Signal messages must always carry a |
6646 |
-+ counter-part blob, called a 'filter', and signals are only delivered to |
6647 |
-+ peers which have a match that white-lists the message's filter. Senders |
6648 |
-+ of signal messages can use either a single connection ID as receiver, |
6649 |
-+ or the special connection ID |
6650 |
-+ <constant>KDBUS_DST_ID_BROADCAST</constant> to potentially send it to |
6651 |
-+ all connections of a bus, following the logic described above. See |
6652 |
-+ <citerefentry> |
6653 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
6654 |
-+ <manvolnum>7</manvolnum> |
6655 |
-+ </citerefentry> |
6656 |
-+ and |
6657 |
-+ <citerefentry> |
6658 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
6659 |
-+ <manvolnum>7</manvolnum> |
6660 |
-+ </citerefentry> |
6661 |
-+ for more details. |
6662 |
-+ </para> |
6663 |
-+ </refsect2> |
6664 |
-+ |
6665 |
-+ <refsect2> |
6666 |
-+ <title>Policy</title> |
6667 |
-+ <para> |
6668 |
-+ A policy is a set of rules that define which connections can see, talk |
6669 |
-+ to, or register a well-known name on the bus. A policy is attached to |
6670 |
-+ buses and custom endpoints, and modified by policy holder connections or |
6671 |
-+ owners of custom endpoints. See |
6672 |
-+ <citerefentry> |
6673 |
-+ <refentrytitle>kdbus.policy</refentrytitle> |
6674 |
-+ <manvolnum>7</manvolnum> |
6675 |
-+ </citerefentry> |
6676 |
-+ for more details. |
6677 |
-+ </para> |
6678 |
-+ </refsect2> |
6679 |
-+ |
6680 |
-+ <refsect2> |
6681 |
-+ <title>Privileged bus users</title> |
6682 |
-+ <para> |
6683 |
-+ A user connecting to the bus is considered privileged if it is either |
6684 |
-+ the creator of the bus, or if it has the CAP_IPC_OWNER capability flag |
6685 |
-+ set. See |
6686 |
-+ <citerefentry> |
6687 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6688 |
-+ <manvolnum>7</manvolnum> |
6689 |
-+ </citerefentry> |
6690 |
-+ for more details. |
6691 |
-+ </para> |
6692 |
-+ </refsect2> |
6693 |
-+ </refsect1> |
6694 |
-+ |
6695 |
-+ <refsect1> |
6696 |
-+ <title>Bus Layout</title> |
6697 |
-+ |
6698 |
-+ <para> |
6699 |
-+ A <emphasis>bus</emphasis> provides and defines an environment that peers |
6700 |
-+ can connect to for message interchange. A bus is created via the kdbus |
6701 |
-+ control interface and can be modified by the bus creator. It applies the |
6702 |
-+ policy that control all bus operations. The bus creator itself does not |
6703 |
-+ participate as a peer. To establish a peer |
6704 |
-+ <emphasis>connection</emphasis>, you have to open one of the |
6705 |
-+ <emphasis>endpoints</emphasis> of a bus. Each bus provides a default |
6706 |
-+ endpoint, but further endpoints can be created on-demand. Endpoints are |
6707 |
-+ used to apply additional policies for all connections on this endpoint. |
6708 |
-+ Thus, they provide additional filters to further restrict access of |
6709 |
-+ specific connections to the bus. |
6710 |
-+ </para> |
6711 |
-+ |
6712 |
-+ <para> |
6713 |
-+ Following, you can see an example bus layout: |
6714 |
-+ </para> |
6715 |
-+ |
6716 |
-+ <programlisting><![CDATA[ |
6717 |
-+ Bus Creator |
6718 |
-+ | |
6719 |
-+ | |
6720 |
-+ +-----+ |
6721 |
-+ | Bus | |
6722 |
-+ +-----+ |
6723 |
-+ | |
6724 |
-+ __________________/ \__________________ |
6725 |
-+ / \ |
6726 |
-+ | | |
6727 |
-+ +----------+ +----------+ |
6728 |
-+ | Endpoint | | Endpoint | |
6729 |
-+ +----------+ +----------+ |
6730 |
-+ _________/|\_________ _________/|\_________ |
6731 |
-+ / | \ / | \ |
6732 |
-+ | | | | | | |
6733 |
-+ | | | | | | |
6734 |
-+ Connection Connection Connection Connection Connection Connection |
6735 |
-+ ]]></programlisting> |
6736 |
-+ |
6737 |
-+ </refsect1> |
6738 |
-+ |
6739 |
-+ <refsect1> |
6740 |
-+ <title>Data structures and interconnections</title> |
6741 |
-+ <programlisting><![CDATA[ |
6742 |
-+ +--------------------------------------------------------------------------+ |
6743 |
-+ | Domain (Mount Point) | |
6744 |
-+ | /sys/fs/kdbus/control | |
6745 |
-+ | +----------------------------------------------------------------------+ | |
6746 |
-+ | | Bus (System Bus) | | |
6747 |
-+ | | /sys/fs/kdbus/0-system/ | | |
6748 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6749 |
-+ | | | Endpoint | | Endpoint | | | |
6750 |
-+ | | | /sys/fs/kdbus/0-system/bus | | /sys/fs/kdbus/0-system/ep.app | | | |
6751 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6752 |
-+ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6753 |
-+ | | | Connection | | Connection | | Connection | | Connection | | | |
6754 |
-+ | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | | |
6755 |
-+ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6756 |
-+ | +----------------------------------------------------------------------+ | |
6757 |
-+ | | |
6758 |
-+ | +----------------------------------------------------------------------+ | |
6759 |
-+ | | Bus (User Bus for UID 2702) | | |
6760 |
-+ | | /sys/fs/kdbus/2702-user/ | | |
6761 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6762 |
-+ | | | Endpoint | | Endpoint | | | |
6763 |
-+ | | | /sys/fs/kdbus/2702-user/bus | | /sys/fs/kdbus/2702-user/ep.app | | | |
6764 |
-+ | | +-------------------------------+ +--------------------------------+ | | |
6765 |
-+ | | +--------------+ +--------------+ +--------------+ +---------------+ | | |
6766 |
-+ | | | Connection | | Connection | | Connection | | Connection | | | |
6767 |
-+ | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | | |
6768 |
-+ | | +--------------+ +--------------+ +--------------------------------+ | | |
6769 |
-+ | +----------------------------------------------------------------------+ | |
6770 |
-+ +--------------------------------------------------------------------------+ |
6771 |
-+ ]]></programlisting> |
6772 |
-+ </refsect1> |
6773 |
-+ |
6774 |
-+ <refsect1> |
6775 |
-+ <title>Metadata</title> |
6776 |
-+ |
6777 |
-+ <refsect2> |
6778 |
-+ <title>When metadata is collected</title> |
6779 |
-+ <para> |
6780 |
-+ kdbus records data about the system in certain situations. Such metadata |
6781 |
-+ can refer to the currently active process (creds, PIDs, current user |
6782 |
-+ groups, process names and its executable path, cgroup membership, |
6783 |
-+ capabilities, security label and audit information), connection |
6784 |
-+ information (description string, currently owned names) and time stamps. |
6785 |
-+ </para> |
6786 |
-+ <para> |
6787 |
-+ Metadata is collected at the following times. |
6788 |
-+ </para> |
6789 |
-+ |
6790 |
-+ <itemizedlist> |
6791 |
-+ <listitem><para> |
6792 |
-+ When a bus is created (<constant>KDBUS_CMD_MAKE</constant>), |
6793 |
-+ information about the calling task is collected. This data is returned |
6794 |
-+ by the kernel via the <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> |
6795 |
-+ call. |
6796 |
-+ </para></listitem> |
6797 |
-+ |
6798 |
-+ <listitem> |
6799 |
-+ <para> |
6800 |
-+ When a connection is created (<constant>KDBUS_CMD_HELLO</constant>), |
6801 |
-+ information about the calling task is collected. Alternatively, a |
6802 |
-+ privileged connection may provide 'faked' information about |
6803 |
-+ credentials, PIDs and security labels which will be stored instead. |
6804 |
-+ This data is returned by the kernel as information on a connection |
6805 |
-+ (<constant>KDBUS_CMD_CONN_INFO</constant>). Only metadata that a |
6806 |
-+ connection allowed to be sent (by setting its bit in |
6807 |
-+ <varname>attach_flags_send</varname>) will be exported in this way. |
6808 |
-+ </para> |
6809 |
-+ </listitem> |
6810 |
-+ |
6811 |
-+ <listitem> |
6812 |
-+ <para> |
6813 |
-+ When a message is sent (<constant>KDBUS_CMD_SEND</constant>), |
6814 |
-+ information about the sending task and the sending connection is |
6815 |
-+ collected. This metadata will be attached to the message when it |
6816 |
-+ arrives in the receiver's pool. If the connection sending the |
6817 |
-+ message installed faked credentials (see |
6818 |
-+ <citerefentry> |
6819 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
6820 |
-+ <manvolnum>7</manvolnum> |
6821 |
-+ </citerefentry>), |
6822 |
-+ the message will not be augmented by any information about the |
6823 |
-+ currently sending task. Note that only metadata that was requested |
6824 |
-+ by the receiving connection will be collected and attached to |
6825 |
-+ messages. |
6826 |
-+ </para> |
6827 |
-+ </listitem> |
6828 |
-+ </itemizedlist> |
6829 |
-+ |
6830 |
-+ <para> |
6831 |
-+ Which metadata items are actually delivered depends on the following |
6832 |
-+ sets and masks: |
6833 |
-+ </para> |
6834 |
-+ |
6835 |
-+ <itemizedlist> |
6836 |
-+ <listitem><para> |
6837 |
-+ (a) the system-wide kmod creds mask |
6838 |
-+ (module parameter <varname>attach_flags_mask</varname>) |
6839 |
-+ </para></listitem> |
6840 |
-+ |
6841 |
-+ <listitem><para> |
6842 |
-+ (b) the per-connection send creds mask, set by the connecting client |
6843 |
-+ </para></listitem> |
6844 |
-+ |
6845 |
-+ <listitem><para> |
6846 |
-+ (c) the per-connection receive creds mask, set by the connecting |
6847 |
-+ client |
6848 |
-+ </para></listitem> |
6849 |
-+ |
6850 |
-+ <listitem><para> |
6851 |
-+ (d) the per-bus minimal creds mask, set by the bus creator |
6852 |
-+ </para></listitem> |
6853 |
-+ |
6854 |
-+ <listitem><para> |
6855 |
-+ (e) the per-bus owner creds mask, set by the bus creator |
6856 |
-+ </para></listitem> |
6857 |
-+ |
6858 |
-+ <listitem><para> |
6859 |
-+ (f) the mask specified when querying creds of a bus peer |
6860 |
-+ </para></listitem> |
6861 |
-+ |
6862 |
-+ <listitem><para> |
6863 |
-+ (g) the mask specified when querying creds of a bus owner |
6864 |
-+ </para></listitem> |
6865 |
-+ </itemizedlist> |
6866 |
-+ |
6867 |
-+ <para> |
6868 |
-+ With the following rules: |
6869 |
-+ </para> |
6870 |
-+ |
6871 |
-+ <itemizedlist> |
6872 |
-+ <listitem> |
6873 |
-+ <para> |
6874 |
-+ [1] The creds attached to messages are determined as |
6875 |
-+ <constant>a & b & c</constant>. |
6876 |
-+ </para> |
6877 |
-+ </listitem> |
6878 |
-+ |
6879 |
-+ <listitem> |
6880 |
-+ <para> |
6881 |
-+ [2] When connecting to a bus (<constant>KDBUS_CMD_HELLO</constant>), |
6882 |
-+ and <constant>~b & d != 0</constant>, the call will fail with, |
6883 |
-+ <errorcode>-1</errorcode>, and <varname>errno</varname> is set to |
6884 |
-+ <constant>ECONNREFUSED</constant>. |
6885 |
-+ </para> |
6886 |
-+ </listitem> |
6887 |
-+ |
6888 |
-+ <listitem> |
6889 |
-+ <para> |
6890 |
-+ [3] When querying creds of a bus peer, the creds returned are |
6891 |
-+ <constant>a & b & f</constant>. |
6892 |
-+ </para> |
6893 |
-+ </listitem> |
6894 |
-+ |
6895 |
-+ <listitem> |
6896 |
-+ <para> |
6897 |
-+ [4] When querying creds of a bus owner, the creds returned are |
6898 |
-+ <constant>a & e & g</constant>. |
6899 |
-+ </para> |
6900 |
-+ </listitem> |
6901 |
-+ </itemizedlist> |
6902 |
-+ |
6903 |
-+ <para> |
6904 |
-+ Hence, programs might not always get all requested metadata items that |
6905 |
-+ it requested. Code must be written so that it can cope with this fact. |
6906 |
-+ </para> |
6907 |
-+ </refsect2> |
6908 |
-+ |
6909 |
-+ <refsect2> |
6910 |
-+ <title>Benefits and heads-up</title> |
6911 |
-+ <para> |
6912 |
-+ Attaching metadata to messages has two major benefits. |
6913 |
-+ |
6914 |
-+ <itemizedlist> |
6915 |
-+ <listitem> |
6916 |
-+ <para> |
6917 |
-+ Metadata attached to messages is gathered at the moment when the |
6918 |
-+ other side calls <constant>KDBUS_CMD_SEND</constant>, or, |
6919 |
-+ respectively, then the kernel notification is generated. There is |
6920 |
-+ no need for the receiving peer to retrieve information about the |
6921 |
-+ task in a second step. This closes a race gap that would otherwise |
6922 |
-+ be inherent. |
6923 |
-+ </para> |
6924 |
-+ </listitem> |
6925 |
-+ <listitem> |
6926 |
-+ <para> |
6927 |
-+ As metadata is delivered along with messages in the same data |
6928 |
-+ blob, no extra calls to kernel functions etc. are needed to gather |
6929 |
-+ them. |
6930 |
-+ </para> |
6931 |
-+ </listitem> |
6932 |
-+ </itemizedlist> |
6933 |
-+ |
6934 |
-+ Note, however, that collecting metadata does come at a price for |
6935 |
-+ performance, so developers should carefully assess which metadata to |
6936 |
-+ really opt-in for. For best practice, data that is not needed as part |
6937 |
-+ of a message should not be requested by the connection in the first |
6938 |
-+ place (see <varname>attach_flags_recv</varname> in |
6939 |
-+ <constant>KDBUS_CMD_HELLO</constant>). |
6940 |
-+ </para> |
6941 |
-+ </refsect2> |
6942 |
-+ |
6943 |
-+ <refsect2> |
6944 |
-+ <title>Attach flags for metadata items</title> |
6945 |
-+ <para> |
6946 |
-+ To let the kernel know which metadata information to attach as items |
6947 |
-+ to the aforementioned commands, it uses a bitmask. In those, the |
6948 |
-+ following <emphasis>attach flags</emphasis> are currently supported. |
6949 |
-+ Both the <varname>attach_flags_recv</varname> and |
6950 |
-+ <varname>attach_flags_send</varname> fields of |
6951 |
-+ <type>struct kdbus_cmd_hello</type>, as well as the payload of the |
6952 |
-+ <constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant> and |
6953 |
-+ <constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant> items follow this |
6954 |
-+ scheme. |
6955 |
-+ </para> |
6956 |
-+ |
6957 |
-+ <variablelist> |
6958 |
-+ <varlistentry> |
6959 |
-+ <term><constant>KDBUS_ATTACH_TIMESTAMP</constant></term> |
6960 |
-+ <listitem><para> |
6961 |
-+ Requests the attachment of an item of type |
6962 |
-+ <constant>KDBUS_ITEM_TIMESTAMP</constant>. |
6963 |
-+ </para></listitem> |
6964 |
-+ </varlistentry> |
6965 |
-+ |
6966 |
-+ <varlistentry> |
6967 |
-+ <term><constant>KDBUS_ATTACH_CREDS</constant></term> |
6968 |
-+ <listitem><para> |
6969 |
-+ Requests the attachment of an item of type |
6970 |
-+ <constant>KDBUS_ITEM_CREDS</constant>. |
6971 |
-+ </para></listitem> |
6972 |
-+ </varlistentry> |
6973 |
-+ |
6974 |
-+ <varlistentry> |
6975 |
-+ <term><constant>KDBUS_ATTACH_PIDS</constant></term> |
6976 |
-+ <listitem><para> |
6977 |
-+ Requests the attachment of an item of type |
6978 |
-+ <constant>KDBUS_ITEM_PIDS</constant>. |
6979 |
-+ </para></listitem> |
6980 |
-+ </varlistentry> |
6981 |
-+ |
6982 |
-+ <varlistentry> |
6983 |
-+ <term><constant>KDBUS_ATTACH_AUXGROUPS</constant></term> |
6984 |
-+ <listitem><para> |
6985 |
-+ Requests the attachment of an item of type |
6986 |
-+ <constant>KDBUS_ITEM_AUXGROUPS</constant>. |
6987 |
-+ </para></listitem> |
6988 |
-+ </varlistentry> |
6989 |
-+ |
6990 |
-+ <varlistentry> |
6991 |
-+ <term><constant>KDBUS_ATTACH_NAMES</constant></term> |
6992 |
-+ <listitem><para> |
6993 |
-+ Requests the attachment of an item of type |
6994 |
-+ <constant>KDBUS_ITEM_OWNED_NAME</constant>. |
6995 |
-+ </para></listitem> |
6996 |
-+ </varlistentry> |
6997 |
-+ |
6998 |
-+ <varlistentry> |
6999 |
-+ <term><constant>KDBUS_ATTACH_TID_COMM</constant></term> |
7000 |
-+ <listitem><para> |
7001 |
-+ Requests the attachment of an item of type |
7002 |
-+ <constant>KDBUS_ITEM_TID_COMM</constant>. |
7003 |
-+ </para></listitem> |
7004 |
-+ </varlistentry> |
7005 |
-+ |
7006 |
-+ <varlistentry> |
7007 |
-+ <term><constant>KDBUS_ATTACH_PID_COMM</constant></term> |
7008 |
-+ <listitem><para> |
7009 |
-+ Requests the attachment of an item of type |
7010 |
-+ <constant>KDBUS_ITEM_PID_COMM</constant>. |
7011 |
-+ </para></listitem> |
7012 |
-+ </varlistentry> |
7013 |
-+ |
7014 |
-+ <varlistentry> |
7015 |
-+ <term><constant>KDBUS_ATTACH_EXE</constant></term> |
7016 |
-+ <listitem><para> |
7017 |
-+ Requests the attachment of an item of type |
7018 |
-+ <constant>KDBUS_ITEM_EXE</constant>. |
7019 |
-+ </para></listitem> |
7020 |
-+ </varlistentry> |
7021 |
-+ |
7022 |
-+ <varlistentry> |
7023 |
-+ <term><constant>KDBUS_ATTACH_CMDLINE</constant></term> |
7024 |
-+ <listitem><para> |
7025 |
-+ Requests the attachment of an item of type |
7026 |
-+ <constant>KDBUS_ITEM_CMDLINE</constant>. |
7027 |
-+ </para></listitem> |
7028 |
-+ </varlistentry> |
7029 |
-+ |
7030 |
-+ <varlistentry> |
7031 |
-+ <term><constant>KDBUS_ATTACH_CGROUP</constant></term> |
7032 |
-+ <listitem><para> |
7033 |
-+ Requests the attachment of an item of type |
7034 |
-+ <constant>KDBUS_ITEM_CGROUP</constant>. |
7035 |
-+ </para></listitem> |
7036 |
-+ </varlistentry> |
7037 |
-+ |
7038 |
-+ <varlistentry> |
7039 |
-+ <term><constant>KDBUS_ATTACH_CAPS</constant></term> |
7040 |
-+ <listitem><para> |
7041 |
-+ Requests the attachment of an item of type |
7042 |
-+ <constant>KDBUS_ITEM_CAPS</constant>. |
7043 |
-+ </para></listitem> |
7044 |
-+ </varlistentry> |
7045 |
-+ |
7046 |
-+ <varlistentry> |
7047 |
-+ <term><constant>KDBUS_ATTACH_SECLABEL</constant></term> |
7048 |
-+ <listitem><para> |
7049 |
-+ Requests the attachment of an item of type |
7050 |
-+ <constant>KDBUS_ITEM_SECLABEL</constant>. |
7051 |
-+ </para></listitem> |
7052 |
-+ </varlistentry> |
7053 |
-+ |
7054 |
-+ <varlistentry> |
7055 |
-+ <term><constant>KDBUS_ATTACH_AUDIT</constant></term> |
7056 |
-+ <listitem><para> |
7057 |
-+ Requests the attachment of an item of type |
7058 |
-+ <constant>KDBUS_ITEM_AUDIT</constant>. |
7059 |
-+ </para></listitem> |
7060 |
-+ </varlistentry> |
7061 |
-+ |
7062 |
-+ <varlistentry> |
7063 |
-+ <term><constant>KDBUS_ATTACH_CONN_DESCRIPTION</constant></term> |
7064 |
-+ <listitem><para> |
7065 |
-+ Requests the attachment of an item of type |
7066 |
-+ <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant>. |
7067 |
-+ </para></listitem> |
7068 |
-+ </varlistentry> |
7069 |
-+ </variablelist> |
7070 |
-+ |
7071 |
-+ <para> |
7072 |
-+ Please refer to |
7073 |
-+ <citerefentry> |
7074 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
7075 |
-+ <manvolnum>7</manvolnum> |
7076 |
-+ </citerefentry> |
7077 |
-+ for detailed information about the layout and payload of items and |
7078 |
-+ what metadata should be used to. |
7079 |
-+ </para> |
7080 |
-+ </refsect2> |
7081 |
-+ </refsect1> |
7082 |
-+ |
7083 |
-+ <refsect1> |
7084 |
-+ <title>The ioctl interface</title> |
7085 |
-+ |
7086 |
-+ <para> |
7087 |
-+ As stated in the 'synopsis' section above, application developers are |
7088 |
-+ strongly encouraged to use kdbus through one of the high-level D-Bus |
7089 |
-+ abstraction libraries, rather than using the low-level API directly. |
7090 |
-+ </para> |
7091 |
-+ |
7092 |
-+ <para> |
7093 |
-+ kdbus on the kernel level exposes its functions exclusively through |
7094 |
-+ <citerefentry> |
7095 |
-+ <refentrytitle>ioctl</refentrytitle> |
7096 |
-+ <manvolnum>2</manvolnum> |
7097 |
-+ </citerefentry>, |
7098 |
-+ employed on file descriptors returned by |
7099 |
-+ <citerefentry> |
7100 |
-+ <refentrytitle>open</refentrytitle> |
7101 |
-+ <manvolnum>2</manvolnum> |
7102 |
-+ </citerefentry> |
7103 |
-+ on pseudo files exposed by |
7104 |
-+ <citerefentry> |
7105 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
7106 |
-+ <manvolnum>7</manvolnum> |
7107 |
-+ </citerefentry>. |
7108 |
-+ </para> |
7109 |
-+ <para> |
7110 |
-+ Following is a list of all the ioctls, along with the command structs |
7111 |
-+ they must be used with. |
7112 |
-+ </para> |
7113 |
-+ |
7114 |
-+ <informaltable frame="none"> |
7115 |
-+ <tgroup cols="3" colsep="1"> |
7116 |
-+ <thead> |
7117 |
-+ <row> |
7118 |
-+ <entry>ioctl signature</entry> |
7119 |
-+ <entry>command</entry> |
7120 |
-+ <entry>transported struct</entry> |
7121 |
-+ </row> |
7122 |
-+ </thead> |
7123 |
-+ <tbody> |
7124 |
-+ <row> |
7125 |
-+ <entry><constant>0x40189500</constant></entry> |
7126 |
-+ <entry><constant>KDBUS_CMD_BUS_MAKE</constant></entry> |
7127 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7128 |
-+ </row><row> |
7129 |
-+ <entry><constant>0x40189510</constant></entry> |
7130 |
-+ <entry><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></entry> |
7131 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7132 |
-+ </row><row> |
7133 |
-+ <entry><constant>0xc0609580</constant></entry> |
7134 |
-+ <entry><constant>KDBUS_CMD_HELLO</constant></entry> |
7135 |
-+ <entry><type>struct kdbus_cmd_hello *</type></entry> |
7136 |
-+ </row><row> |
7137 |
-+ <entry><constant>0x40189582</constant></entry> |
7138 |
-+ <entry><constant>KDBUS_CMD_BYEBYE</constant></entry> |
7139 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7140 |
-+ </row><row> |
7141 |
-+ <entry><constant>0x40389590</constant></entry> |
7142 |
-+ <entry><constant>KDBUS_CMD_SEND</constant></entry> |
7143 |
-+ <entry><type>struct kdbus_cmd_send *</type></entry> |
7144 |
-+ </row><row> |
7145 |
-+ <entry><constant>0x80409591</constant></entry> |
7146 |
-+ <entry><constant>KDBUS_CMD_RECV</constant></entry> |
7147 |
-+ <entry><type>struct kdbus_cmd_recv *</type></entry> |
7148 |
-+ </row><row> |
7149 |
-+ <entry><constant>0x40209583</constant></entry> |
7150 |
-+ <entry><constant>KDBUS_CMD_FREE</constant></entry> |
7151 |
-+ <entry><type>struct kdbus_cmd_free *</type></entry> |
7152 |
-+ </row><row> |
7153 |
-+ <entry><constant>0x401895a0</constant></entry> |
7154 |
-+ <entry><constant>KDBUS_CMD_NAME_ACQUIRE</constant></entry> |
7155 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7156 |
-+ </row><row> |
7157 |
-+ <entry><constant>0x401895a1</constant></entry> |
7158 |
-+ <entry><constant>KDBUS_CMD_NAME_RELEASE</constant></entry> |
7159 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7160 |
-+ </row><row> |
7161 |
-+ <entry><constant>0x80289586</constant></entry> |
7162 |
-+ <entry><constant>KDBUS_CMD_LIST</constant></entry> |
7163 |
-+ <entry><type>struct kdbus_cmd_list *</type></entry> |
7164 |
-+ </row><row> |
7165 |
-+ <entry><constant>0x80309584</constant></entry> |
7166 |
-+ <entry><constant>KDBUS_CMD_CONN_INFO</constant></entry> |
7167 |
-+ <entry><type>struct kdbus_cmd_info *</type></entry> |
7168 |
-+ </row><row> |
7169 |
-+ <entry><constant>0x40209551</constant></entry> |
7170 |
-+ <entry><constant>KDBUS_CMD_UPDATE</constant></entry> |
7171 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7172 |
-+ </row><row> |
7173 |
-+ <entry><constant>0x80309585</constant></entry> |
7174 |
-+ <entry><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></entry> |
7175 |
-+ <entry><type>struct kdbus_cmd_info *</type></entry> |
7176 |
-+ </row><row> |
7177 |
-+ <entry><constant>0x40189511</constant></entry> |
7178 |
-+ <entry><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></entry> |
7179 |
-+ <entry><type>struct kdbus_cmd *</type></entry> |
7180 |
-+ </row><row> |
7181 |
-+ <entry><constant>0x402095b0</constant></entry> |
7182 |
-+ <entry><constant>KDBUS_CMD_MATCH_ADD</constant></entry> |
7183 |
-+ <entry><type>struct kdbus_cmd_match *</type></entry> |
7184 |
-+ </row><row> |
7185 |
-+ <entry><constant>0x402095b1</constant></entry> |
7186 |
-+ <entry><constant>KDBUS_CMD_MATCH_REMOVE</constant></entry> |
7187 |
-+ <entry><type>struct kdbus_cmd_match *</type></entry> |
7188 |
-+ </row> |
7189 |
-+ </tbody> |
7190 |
-+ </tgroup> |
7191 |
-+ </informaltable> |
7192 |
-+ |
7193 |
-+ <para> |
7194 |
-+ Depending on the type of <emphasis>kdbusfs</emphasis> node that was |
7195 |
-+ opened and what ioctls have been executed on a file descriptor before, |
7196 |
-+ a different sub-set of ioctl commands is allowed. |
7197 |
-+ </para> |
7198 |
-+ |
7199 |
-+ <itemizedlist> |
7200 |
-+ <listitem> |
7201 |
-+ <para> |
7202 |
-+ On a file descriptor resulting from opening a |
7203 |
-+ <emphasis>control node</emphasis>, only the |
7204 |
-+ <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl may be executed. |
7205 |
-+ </para> |
7206 |
-+ </listitem> |
7207 |
-+ <listitem> |
7208 |
-+ <para> |
7209 |
-+ On a file descriptor resulting from opening a |
7210 |
-+ <emphasis>bus endpoint node</emphasis>, only the |
7211 |
-+ <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> and |
7212 |
-+ <constant>KDBUS_CMD_HELLO</constant> ioctls may be executed. |
7213 |
-+ </para> |
7214 |
-+ </listitem> |
7215 |
-+ <listitem> |
7216 |
-+ <para> |
7217 |
-+ A file descriptor that was used to create a bus |
7218 |
-+ (via <constant>KDBUS_CMD_BUS_MAKE</constant>) is called a |
7219 |
-+ <emphasis>bus owner</emphasis> file descriptor. The bus will be |
7220 |
-+ active as long as the file descriptor is kept open. |
7221 |
-+ A bus owner file descriptor can not be used to |
7222 |
-+ employ any further ioctls. As soon as |
7223 |
-+ <citerefentry> |
7224 |
-+ <refentrytitle>close</refentrytitle> |
7225 |
-+ <manvolnum>2</manvolnum> |
7226 |
-+ </citerefentry> |
7227 |
-+ is called on it, the bus will be shut down, along will all associated |
7228 |
-+ endpoints and connections. See |
7229 |
-+ <citerefentry> |
7230 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
7231 |
-+ <manvolnum>7</manvolnum> |
7232 |
-+ </citerefentry> |
7233 |
-+ for more details. |
7234 |
-+ </para> |
7235 |
-+ </listitem> |
7236 |
-+ <listitem> |
7237 |
-+ <para> |
7238 |
-+ A file descriptor that was used to create an endpoint |
7239 |
-+ (via <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>) is called an |
7240 |
-+ <emphasis>endpoint owner</emphasis> file descriptor. The endpoint |
7241 |
-+ will be active as long as the file descriptor is kept open. |
7242 |
-+ An endpoint owner file descriptor can only be used |
7243 |
-+ to update details of an endpoint through the |
7244 |
-+ <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> ioctl. As soon as |
7245 |
-+ <citerefentry> |
7246 |
-+ <refentrytitle>close</refentrytitle> |
7247 |
-+ <manvolnum>2</manvolnum> |
7248 |
-+ </citerefentry> |
7249 |
-+ is called on it, the endpoint will be removed from the bus, and all |
7250 |
-+ connections that are connected to the bus through it are shut down. |
7251 |
-+ See |
7252 |
-+ <citerefentry> |
7253 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
7254 |
-+ <manvolnum>7</manvolnum> |
7255 |
-+ </citerefentry> |
7256 |
-+ for more details. |
7257 |
-+ </para> |
7258 |
-+ </listitem> |
7259 |
-+ <listitem> |
7260 |
-+ <para> |
7261 |
-+ A file descriptor that was used to create a connection |
7262 |
-+ (via <constant>KDBUS_CMD_HELLO</constant>) is called a |
7263 |
-+ <emphasis>connection owner</emphasis> file descriptor. The connection |
7264 |
-+ will be active as long as the file descriptor is kept open. |
7265 |
-+ A connection owner file descriptor may be used to |
7266 |
-+ issue any of the following ioctls. |
7267 |
-+ </para> |
7268 |
-+ |
7269 |
-+ <itemizedlist> |
7270 |
-+ <listitem><para> |
7271 |
-+ <constant>KDBUS_CMD_UPDATE</constant> to tweak details of the |
7272 |
-+ connection. See |
7273 |
-+ <citerefentry> |
7274 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7275 |
-+ <manvolnum>7</manvolnum> |
7276 |
-+ </citerefentry>. |
7277 |
-+ </para></listitem> |
7278 |
-+ |
7279 |
-+ <listitem><para> |
7280 |
-+ <constant>KDBUS_CMD_BYEBYE</constant> to shut down a connection |
7281 |
-+ without losing messages. See |
7282 |
-+ <citerefentry> |
7283 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7284 |
-+ <manvolnum>7</manvolnum> |
7285 |
-+ </citerefentry>. |
7286 |
-+ </para></listitem> |
7287 |
-+ |
7288 |
-+ <listitem><para> |
7289 |
-+ <constant>KDBUS_CMD_FREE</constant> to free a slice of memory in |
7290 |
-+ the pool. See |
7291 |
-+ <citerefentry> |
7292 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
7293 |
-+ <manvolnum>7</manvolnum> |
7294 |
-+ </citerefentry>. |
7295 |
-+ </para></listitem> |
7296 |
-+ |
7297 |
-+ <listitem><para> |
7298 |
-+ <constant>KDBUS_CMD_CONN_INFO</constant> to retrieve information |
7299 |
-+ on other connections on the bus. See |
7300 |
-+ <citerefentry> |
7301 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7302 |
-+ <manvolnum>7</manvolnum> |
7303 |
-+ </citerefentry>. |
7304 |
-+ </para></listitem> |
7305 |
-+ |
7306 |
-+ <listitem><para> |
7307 |
-+ <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> to retrieve |
7308 |
-+ information on the bus creator. See |
7309 |
-+ <citerefentry> |
7310 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7311 |
-+ <manvolnum>7</manvolnum> |
7312 |
-+ </citerefentry>. |
7313 |
-+ </para></listitem> |
7314 |
-+ |
7315 |
-+ <listitem><para> |
7316 |
-+ <constant>KDBUS_CMD_LIST</constant> to retrieve a list of |
7317 |
-+ currently active well-known names and unique IDs on the bus. See |
7318 |
-+ <citerefentry> |
7319 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
7320 |
-+ <manvolnum>7</manvolnum> |
7321 |
-+ </citerefentry>. |
7322 |
-+ </para></listitem> |
7323 |
-+ |
7324 |
-+ <listitem><para> |
7325 |
-+ <constant>KDBUS_CMD_SEND</constant> and |
7326 |
-+ <constant>KDBUS_CMD_RECV</constant> to send or receive a message. |
7327 |
-+ See |
7328 |
-+ <citerefentry> |
7329 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
7330 |
-+ <manvolnum>7</manvolnum> |
7331 |
-+ </citerefentry>. |
7332 |
-+ </para></listitem> |
7333 |
-+ |
7334 |
-+ <listitem><para> |
7335 |
-+ <constant>KDBUS_CMD_NAME_ACQUIRE</constant> and |
7336 |
-+ <constant>KDBUS_CMD_NAME_RELEASE</constant> to acquire or release |
7337 |
-+ a well-known name on the bus. See |
7338 |
-+ <citerefentry> |
7339 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
7340 |
-+ <manvolnum>7</manvolnum> |
7341 |
-+ </citerefentry>. |
7342 |
-+ </para></listitem> |
7343 |
-+ |
7344 |
-+ <listitem><para> |
7345 |
-+ <constant>KDBUS_CMD_MATCH_ADD</constant> and |
7346 |
-+ <constant>KDBUS_CMD_MATCH_REMOVE</constant> to add or remove |
7347 |
-+ a match for signal messages. See |
7348 |
-+ <citerefentry> |
7349 |
-+ <refentrytitle>kdbus.match</refentrytitle> |
7350 |
-+ <manvolnum>7</manvolnum> |
7351 |
-+ </citerefentry>. |
7352 |
-+ </para></listitem> |
7353 |
-+ </itemizedlist> |
7354 |
-+ </listitem> |
7355 |
-+ </itemizedlist> |
7356 |
-+ |
7357 |
-+ <para> |
7358 |
-+ These ioctls, along with the structs they transport, are explained in |
7359 |
-+ detail in the other documents linked to in the "See Also" section below. |
7360 |
-+ </para> |
7361 |
-+ </refsect1> |
7362 |
-+ |
7363 |
-+ <refsect1> |
7364 |
-+ <title>See Also</title> |
7365 |
-+ <simplelist type="inline"> |
7366 |
-+ <member> |
7367 |
-+ <citerefentry> |
7368 |
-+ <refentrytitle>kdbus.bus</refentrytitle> |
7369 |
-+ <manvolnum>7</manvolnum> |
7370 |
-+ </citerefentry> |
7371 |
-+ </member> |
7372 |
-+ <member> |
7373 |
-+ <citerefentry> |
7374 |
-+ <refentrytitle>kdbus.connection</refentrytitle> |
7375 |
-+ <manvolnum>7</manvolnum> |
7376 |
-+ </citerefentry> |
7377 |
-+ </member> |
7378 |
-+ <member> |
7379 |
-+ <citerefentry> |
7380 |
-+ <refentrytitle>kdbus.endpoint</refentrytitle> |
7381 |
-+ <manvolnum>7</manvolnum> |
7382 |
-+ </citerefentry> |
7383 |
-+ </member> |
7384 |
-+ <member> |
7385 |
-+ <citerefentry> |
7386 |
-+ <refentrytitle>kdbus.fs</refentrytitle> |
7387 |
-+ <manvolnum>7</manvolnum> |
7388 |
-+ </citerefentry> |
7389 |
-+ </member> |
7390 |
-+ <member> |
7391 |
-+ <citerefentry> |
7392 |
-+ <refentrytitle>kdbus.item</refentrytitle> |
7393 |
-+ <manvolnum>7</manvolnum> |
7394 |
-+ </citerefentry> |
7395 |
-+ </member> |
7396 |
-+ <member> |
7397 |
-+ <citerefentry> |
7398 |
-+ <refentrytitle>kdbus.message</refentrytitle> |
7399 |
-+ <manvolnum>7</manvolnum> |
7400 |
-+ </citerefentry> |
7401 |
-+ </member> |
7402 |
-+ <member> |
7403 |
-+ <citerefentry> |
7404 |
-+ <refentrytitle>kdbus.name</refentrytitle> |
7405 |
-+ <manvolnum>7</manvolnum> |
7406 |
-+ </citerefentry> |
7407 |
-+ </member> |
7408 |
-+ <member> |
7409 |
-+ <citerefentry> |
7410 |
-+ <refentrytitle>kdbus.pool</refentrytitle> |
7411 |
-+ <manvolnum>7</manvolnum> |
7412 |
-+ </citerefentry> |
7413 |
-+ </member> |
7414 |
-+ <member> |
7415 |
-+ <citerefentry> |
7416 |
-+ <refentrytitle>ioctl</refentrytitle> |
7417 |
-+ <manvolnum>2</manvolnum> |
7418 |
-+ </citerefentry> |
7419 |
-+ </member> |
7420 |
-+ <member> |
7421 |
-+ <citerefentry> |
7422 |
-+ <refentrytitle>mmap</refentrytitle> |
7423 |
-+ <manvolnum>2</manvolnum> |
7424 |
-+ </citerefentry> |
7425 |
-+ </member> |
7426 |
-+ <member> |
7427 |
-+ <citerefentry> |
7428 |
-+ <refentrytitle>open</refentrytitle> |
7429 |
-+ <manvolnum>2</manvolnum> |
7430 |
-+ </citerefentry> |
7431 |
-+ </member> |
7432 |
-+ <member> |
7433 |
-+ <citerefentry> |
7434 |
-+ <refentrytitle>close</refentrytitle> |
7435 |
-+ <manvolnum>2</manvolnum> |
7436 |
-+ </citerefentry> |
7437 |
-+ </member> |
7438 |
-+ <member> |
7439 |
-+ <ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink> |
7440 |
-+ </member> |
7441 |
-+ </simplelist> |
7442 |
-+ </refsect1> |
7443 |
-+ |
7444 |
-+</refentry> |
7445 |
-diff --git a/Documentation/kdbus/stylesheet.xsl b/Documentation/kdbus/stylesheet.xsl |
7446 |
-new file mode 100644 |
7447 |
-index 0000000..52565ea |
7448 |
---- /dev/null |
7449 |
-+++ b/Documentation/kdbus/stylesheet.xsl |
7450 |
-@@ -0,0 +1,16 @@ |
7451 |
-+<?xml version="1.0" encoding="UTF-8"?> |
7452 |
-+<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"> |
7453 |
-+ <param name="chunk.quietly">1</param> |
7454 |
-+ <param name="funcsynopsis.style">ansi</param> |
7455 |
-+ <param name="funcsynopsis.tabular.threshold">80</param> |
7456 |
-+ <param name="callout.graphics">0</param> |
7457 |
-+ <param name="paper.type">A4</param> |
7458 |
-+ <param name="generate.section.toc.level">2</param> |
7459 |
-+ <param name="use.id.as.filename">1</param> |
7460 |
-+ <param name="citerefentry.link">1</param> |
7461 |
-+ <strip-space elements="*"/> |
7462 |
-+ <template name="generate.citerefentry.link"> |
7463 |
-+ <value-of select="refentrytitle"/> |
7464 |
-+ <text>.html</text> |
7465 |
-+ </template> |
7466 |
-+</stylesheet> |
7467 |
-diff --git a/MAINTAINERS b/MAINTAINERS |
7468 |
-index d8afd29..02f7668 100644 |
7469 |
---- a/MAINTAINERS |
7470 |
-+++ b/MAINTAINERS |
7471 |
-@@ -5585,6 +5585,19 @@ S: Maintained |
7472 |
- F: Documentation/kbuild/kconfig-language.txt |
7473 |
- F: scripts/kconfig/ |
7474 |
- |
7475 |
-+KDBUS |
7476 |
-+M: Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
7477 |
-+M: Daniel Mack <daniel@××××××.org> |
7478 |
-+M: David Herrmann <dh.herrmann@××××××××××.com> |
7479 |
-+M: Djalal Harouni <tixxdz@××××××.org> |
7480 |
-+L: linux-kernel@×××××××××××.org |
7481 |
-+S: Maintained |
7482 |
-+F: ipc/kdbus/* |
7483 |
-+F: samples/kdbus/* |
7484 |
-+F: Documentation/kdbus/* |
7485 |
-+F: include/uapi/linux/kdbus.h |
7486 |
-+F: tools/testing/selftests/kdbus/ |
7487 |
-+ |
7488 |
- KDUMP |
7489 |
- M: Vivek Goyal <vgoyal@××××××.com> |
7490 |
- M: Haren Myneni <hbabu@××××××.com> |
7491 |
-diff --git a/Makefile b/Makefile |
7492 |
-index f5c8983..a1c8d57 100644 |
7493 |
---- a/Makefile |
7494 |
-+++ b/Makefile |
7495 |
-@@ -1343,6 +1343,7 @@ $(help-board-dirs): help-%: |
7496 |
- %docs: scripts_basic FORCE |
7497 |
- $(Q)$(MAKE) $(build)=scripts build_docproc |
7498 |
- $(Q)$(MAKE) $(build)=Documentation/DocBook $@ |
7499 |
-+ $(Q)$(MAKE) $(build)=Documentation/kdbus $@ |
7500 |
- |
7501 |
- else # KBUILD_EXTMOD |
7502 |
- |
7503 |
-diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild |
7504 |
-index 1a0006a..4842a98 100644 |
7505 |
---- a/include/uapi/linux/Kbuild |
7506 |
-+++ b/include/uapi/linux/Kbuild |
7507 |
-@@ -215,6 +215,7 @@ header-y += ixjuser.h |
7508 |
- header-y += jffs2.h |
7509 |
- header-y += joystick.h |
7510 |
- header-y += kcmp.h |
7511 |
-+header-y += kdbus.h |
7512 |
- header-y += kdev_t.h |
7513 |
- header-y += kd.h |
7514 |
- header-y += kernelcapi.h |
7515 |
-diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h |
7516 |
-new file mode 100644 |
7517 |
-index 0000000..4fc44cb |
7518 |
---- /dev/null |
7519 |
-+++ b/include/uapi/linux/kdbus.h |
7520 |
-@@ -0,0 +1,984 @@ |
7521 |
-+/* |
7522 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
7523 |
-+ * the terms of the GNU Lesser General Public License as published by the |
7524 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
7525 |
-+ * your option) any later version. |
7526 |
-+ */ |
7527 |
-+ |
7528 |
-+#ifndef _UAPI_KDBUS_H_ |
7529 |
-+#define _UAPI_KDBUS_H_ |
7530 |
-+ |
7531 |
-+#include <linux/ioctl.h> |
7532 |
-+#include <linux/types.h> |
7533 |
-+ |
7534 |
-+#define KDBUS_IOCTL_MAGIC 0x95 |
7535 |
-+#define KDBUS_SRC_ID_KERNEL (0) |
7536 |
-+#define KDBUS_DST_ID_NAME (0) |
7537 |
-+#define KDBUS_MATCH_ID_ANY (~0ULL) |
7538 |
-+#define KDBUS_DST_ID_BROADCAST (~0ULL) |
7539 |
-+#define KDBUS_FLAG_NEGOTIATE (1ULL << 63) |
7540 |
-+ |
7541 |
-+/** |
7542 |
-+ * struct kdbus_notify_id_change - name registry change message |
7543 |
-+ * @id: New or former owner of the name |
7544 |
-+ * @flags: flags field from KDBUS_HELLO_* |
7545 |
-+ * |
7546 |
-+ * Sent from kernel to userspace when the owner or activator of |
7547 |
-+ * a well-known name changes. |
7548 |
-+ * |
7549 |
-+ * Attached to: |
7550 |
-+ * KDBUS_ITEM_ID_ADD |
7551 |
-+ * KDBUS_ITEM_ID_REMOVE |
7552 |
-+ */ |
7553 |
-+struct kdbus_notify_id_change { |
7554 |
-+ __u64 id; |
7555 |
-+ __u64 flags; |
7556 |
-+} __attribute__((__aligned__(8))); |
7557 |
-+ |
7558 |
-+/** |
7559 |
-+ * struct kdbus_notify_name_change - name registry change message |
7560 |
-+ * @old_id: ID and flags of former owner of a name |
7561 |
-+ * @new_id: ID and flags of new owner of a name |
7562 |
-+ * @name: Well-known name |
7563 |
-+ * |
7564 |
-+ * Sent from kernel to userspace when the owner or activator of |
7565 |
-+ * a well-known name changes. |
7566 |
-+ * |
7567 |
-+ * Attached to: |
7568 |
-+ * KDBUS_ITEM_NAME_ADD |
7569 |
-+ * KDBUS_ITEM_NAME_REMOVE |
7570 |
-+ * KDBUS_ITEM_NAME_CHANGE |
7571 |
-+ */ |
7572 |
-+struct kdbus_notify_name_change { |
7573 |
-+ struct kdbus_notify_id_change old_id; |
7574 |
-+ struct kdbus_notify_id_change new_id; |
7575 |
-+ char name[0]; |
7576 |
-+} __attribute__((__aligned__(8))); |
7577 |
-+ |
7578 |
-+/** |
7579 |
-+ * struct kdbus_creds - process credentials |
7580 |
-+ * @uid: User ID |
7581 |
-+ * @euid: Effective UID |
7582 |
-+ * @suid: Saved UID |
7583 |
-+ * @fsuid: Filesystem UID |
7584 |
-+ * @gid: Group ID |
7585 |
-+ * @egid: Effective GID |
7586 |
-+ * @sgid: Saved GID |
7587 |
-+ * @fsgid: Filesystem GID |
7588 |
-+ * |
7589 |
-+ * Attached to: |
7590 |
-+ * KDBUS_ITEM_CREDS |
7591 |
-+ */ |
7592 |
-+struct kdbus_creds { |
7593 |
-+ __u64 uid; |
7594 |
-+ __u64 euid; |
7595 |
-+ __u64 suid; |
7596 |
-+ __u64 fsuid; |
7597 |
-+ __u64 gid; |
7598 |
-+ __u64 egid; |
7599 |
-+ __u64 sgid; |
7600 |
-+ __u64 fsgid; |
7601 |
-+} __attribute__((__aligned__(8))); |
7602 |
-+ |
7603 |
-+/** |
7604 |
-+ * struct kdbus_pids - process identifiers |
7605 |
-+ * @pid: Process ID |
7606 |
-+ * @tid: Thread ID |
7607 |
-+ * @ppid: Parent process ID |
7608 |
-+ * |
7609 |
-+ * The PID and TID of a process. |
7610 |
-+ * |
7611 |
-+ * Attached to: |
7612 |
-+ * KDBUS_ITEM_PIDS |
7613 |
-+ */ |
7614 |
-+struct kdbus_pids { |
7615 |
-+ __u64 pid; |
7616 |
-+ __u64 tid; |
7617 |
-+ __u64 ppid; |
7618 |
-+} __attribute__((__aligned__(8))); |
7619 |
-+ |
7620 |
-+/** |
7621 |
-+ * struct kdbus_caps - process capabilities |
7622 |
-+ * @last_cap: Highest currently known capability bit |
7623 |
-+ * @caps: Variable number of 32-bit capabilities flags |
7624 |
-+ * |
7625 |
-+ * Contains a variable number of 32-bit capabilities flags. |
7626 |
-+ * |
7627 |
-+ * Attached to: |
7628 |
-+ * KDBUS_ITEM_CAPS |
7629 |
-+ */ |
7630 |
-+struct kdbus_caps { |
7631 |
-+ __u32 last_cap; |
7632 |
-+ __u32 caps[0]; |
7633 |
-+} __attribute__((__aligned__(8))); |
7634 |
-+ |
7635 |
-+/** |
7636 |
-+ * struct kdbus_audit - audit information |
7637 |
-+ * @sessionid: The audit session ID |
7638 |
-+ * @loginuid: The audit login uid |
7639 |
-+ * |
7640 |
-+ * Attached to: |
7641 |
-+ * KDBUS_ITEM_AUDIT |
7642 |
-+ */ |
7643 |
-+struct kdbus_audit { |
7644 |
-+ __u32 sessionid; |
7645 |
-+ __u32 loginuid; |
7646 |
-+} __attribute__((__aligned__(8))); |
7647 |
-+ |
7648 |
-+/** |
7649 |
-+ * struct kdbus_timestamp |
7650 |
-+ * @seqnum: Global per-domain message sequence number |
7651 |
-+ * @monotonic_ns: Monotonic timestamp, in nanoseconds |
7652 |
-+ * @realtime_ns: Realtime timestamp, in nanoseconds |
7653 |
-+ * |
7654 |
-+ * Attached to: |
7655 |
-+ * KDBUS_ITEM_TIMESTAMP |
7656 |
-+ */ |
7657 |
-+struct kdbus_timestamp { |
7658 |
-+ __u64 seqnum; |
7659 |
-+ __u64 monotonic_ns; |
7660 |
-+ __u64 realtime_ns; |
7661 |
-+} __attribute__((__aligned__(8))); |
7662 |
-+ |
7663 |
-+/** |
7664 |
-+ * struct kdbus_vec - I/O vector for kdbus payload items |
7665 |
-+ * @size: The size of the vector |
7666 |
-+ * @address: Memory address of data buffer |
7667 |
-+ * @offset: Offset in the in-message payload memory, |
7668 |
-+ * relative to the message head |
7669 |
-+ * |
7670 |
-+ * Attached to: |
7671 |
-+ * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF |
7672 |
-+ */ |
7673 |
-+struct kdbus_vec { |
7674 |
-+ __u64 size; |
7675 |
-+ union { |
7676 |
-+ __u64 address; |
7677 |
-+ __u64 offset; |
7678 |
-+ }; |
7679 |
-+} __attribute__((__aligned__(8))); |
7680 |
-+ |
7681 |
-+/** |
7682 |
-+ * struct kdbus_bloom_parameter - bus-wide bloom parameters |
7683 |
-+ * @size: Size of the bit field in bytes (m / 8) |
7684 |
-+ * @n_hash: Number of hash functions used (k) |
7685 |
-+ */ |
7686 |
-+struct kdbus_bloom_parameter { |
7687 |
-+ __u64 size; |
7688 |
-+ __u64 n_hash; |
7689 |
-+} __attribute__((__aligned__(8))); |
7690 |
-+ |
7691 |
-+/** |
7692 |
-+ * struct kdbus_bloom_filter - bloom filter containing n elements |
7693 |
-+ * @generation: Generation of the element set in the filter |
7694 |
-+ * @data: Bit field, multiple of 8 bytes |
7695 |
-+ */ |
7696 |
-+struct kdbus_bloom_filter { |
7697 |
-+ __u64 generation; |
7698 |
-+ __u64 data[0]; |
7699 |
-+} __attribute__((__aligned__(8))); |
7700 |
-+ |
7701 |
-+/** |
7702 |
-+ * struct kdbus_memfd - a kdbus memfd |
7703 |
-+ * @start: The offset into the memfd where the segment starts |
7704 |
-+ * @size: The size of the memfd segment |
7705 |
-+ * @fd: The file descriptor number |
7706 |
-+ * @__pad: Padding to ensure proper alignment and size |
7707 |
-+ * |
7708 |
-+ * Attached to: |
7709 |
-+ * KDBUS_ITEM_PAYLOAD_MEMFD |
7710 |
-+ */ |
7711 |
-+struct kdbus_memfd { |
7712 |
-+ __u64 start; |
7713 |
-+ __u64 size; |
7714 |
-+ int fd; |
7715 |
-+ __u32 __pad; |
7716 |
-+} __attribute__((__aligned__(8))); |
7717 |
-+ |
7718 |
-+/** |
7719 |
-+ * struct kdbus_name - a registered well-known name with its flags |
7720 |
-+ * @flags: Flags from KDBUS_NAME_* |
7721 |
-+ * @name: Well-known name |
7722 |
-+ * |
7723 |
-+ * Attached to: |
7724 |
-+ * KDBUS_ITEM_OWNED_NAME |
7725 |
-+ */ |
7726 |
-+struct kdbus_name { |
7727 |
-+ __u64 flags; |
7728 |
-+ char name[0]; |
7729 |
-+} __attribute__((__aligned__(8))); |
7730 |
-+ |
7731 |
-+/** |
7732 |
-+ * enum kdbus_policy_access_type - permissions of a policy record |
7733 |
-+ * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid |
7734 |
-+ * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid |
7735 |
-+ * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid |
7736 |
-+ * @KDBUS_POLICY_ACCESS_WORLD: World-accessible |
7737 |
-+ */ |
7738 |
-+enum kdbus_policy_access_type { |
7739 |
-+ _KDBUS_POLICY_ACCESS_NULL, |
7740 |
-+ KDBUS_POLICY_ACCESS_USER, |
7741 |
-+ KDBUS_POLICY_ACCESS_GROUP, |
7742 |
-+ KDBUS_POLICY_ACCESS_WORLD, |
7743 |
-+}; |
7744 |
-+ |
7745 |
-+/** |
7746 |
-+ * enum kdbus_policy_access_flags - mode flags |
7747 |
-+ * @KDBUS_POLICY_OWN: Allow to own a well-known name |
7748 |
-+ * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE |
7749 |
-+ * @KDBUS_POLICY_TALK: Allow communication to a well-known name |
7750 |
-+ * Implies KDBUS_POLICY_SEE |
7751 |
-+ * @KDBUS_POLICY_SEE: Allow to see a well-known name |
7752 |
-+ */ |
7753 |
-+enum kdbus_policy_type { |
7754 |
-+ KDBUS_POLICY_SEE = 0, |
7755 |
-+ KDBUS_POLICY_TALK, |
7756 |
-+ KDBUS_POLICY_OWN, |
7757 |
-+}; |
7758 |
-+ |
7759 |
-+/** |
7760 |
-+ * struct kdbus_policy_access - policy access item |
7761 |
-+ * @type: One of KDBUS_POLICY_ACCESS_* types |
7762 |
-+ * @access: Access to grant |
7763 |
-+ * @id: For KDBUS_POLICY_ACCESS_USER, the uid |
7764 |
-+ * For KDBUS_POLICY_ACCESS_GROUP, the gid |
7765 |
-+ */ |
7766 |
-+struct kdbus_policy_access { |
7767 |
-+ __u64 type; /* USER, GROUP, WORLD */ |
7768 |
-+ __u64 access; /* OWN, TALK, SEE */ |
7769 |
-+ __u64 id; /* uid, gid, 0 */ |
7770 |
-+} __attribute__((__aligned__(8))); |
7771 |
-+ |
7772 |
-+/** |
7773 |
-+ * enum kdbus_attach_flags - flags for metadata attachments |
7774 |
-+ * @KDBUS_ATTACH_TIMESTAMP: Timestamp |
7775 |
-+ * @KDBUS_ATTACH_CREDS: Credentials |
7776 |
-+ * @KDBUS_ATTACH_PIDS: PIDs |
7777 |
-+ * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups |
7778 |
-+ * @KDBUS_ATTACH_NAMES: Well-known names |
7779 |
-+ * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID |
7780 |
-+ * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID |
7781 |
-+ * @KDBUS_ATTACH_EXE: The path of the executable |
7782 |
-+ * @KDBUS_ATTACH_CMDLINE: The process command line |
7783 |
-+ * @KDBUS_ATTACH_CGROUP: The croup membership |
7784 |
-+ * @KDBUS_ATTACH_CAPS: The process capabilities |
7785 |
-+ * @KDBUS_ATTACH_SECLABEL: The security label |
7786 |
-+ * @KDBUS_ATTACH_AUDIT: The audit IDs |
7787 |
-+ * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name |
7788 |
-+ * @_KDBUS_ATTACH_ALL: All of the above |
7789 |
-+ * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of |
7790 |
-+ * metatdata. |
7791 |
-+ */ |
7792 |
-+enum kdbus_attach_flags { |
7793 |
-+ KDBUS_ATTACH_TIMESTAMP = 1ULL << 0, |
7794 |
-+ KDBUS_ATTACH_CREDS = 1ULL << 1, |
7795 |
-+ KDBUS_ATTACH_PIDS = 1ULL << 2, |
7796 |
-+ KDBUS_ATTACH_AUXGROUPS = 1ULL << 3, |
7797 |
-+ KDBUS_ATTACH_NAMES = 1ULL << 4, |
7798 |
-+ KDBUS_ATTACH_TID_COMM = 1ULL << 5, |
7799 |
-+ KDBUS_ATTACH_PID_COMM = 1ULL << 6, |
7800 |
-+ KDBUS_ATTACH_EXE = 1ULL << 7, |
7801 |
-+ KDBUS_ATTACH_CMDLINE = 1ULL << 8, |
7802 |
-+ KDBUS_ATTACH_CGROUP = 1ULL << 9, |
7803 |
-+ KDBUS_ATTACH_CAPS = 1ULL << 10, |
7804 |
-+ KDBUS_ATTACH_SECLABEL = 1ULL << 11, |
7805 |
-+ KDBUS_ATTACH_AUDIT = 1ULL << 12, |
7806 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13, |
7807 |
-+ _KDBUS_ATTACH_ALL = (1ULL << 14) - 1, |
7808 |
-+ _KDBUS_ATTACH_ANY = ~0ULL |
7809 |
-+}; |
7810 |
-+ |
7811 |
-+/** |
7812 |
-+ * enum kdbus_item_type - item types to chain data in a list |
7813 |
-+ * @_KDBUS_ITEM_NULL: Uninitialized/invalid |
7814 |
-+ * @_KDBUS_ITEM_USER_BASE: Start of user items |
7815 |
-+ * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items |
7816 |
-+ * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data |
7817 |
-+ * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head |
7818 |
-+ * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd |
7819 |
-+ * @KDBUS_ITEM_FDS: Attached file descriptors |
7820 |
-+ * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous |
7821 |
-+ * operation by writing to it from |
7822 |
-+ * userspace |
7823 |
-+ * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with |
7824 |
-+ * KDBUS_CMD_BUS_MAKE, carries a |
7825 |
-+ * struct kdbus_bloom_parameter |
7826 |
-+ * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message, |
7827 |
-+ * used to match against a bloom mask of a |
7828 |
-+ * connection, carries a struct |
7829 |
-+ * kdbus_bloom_filter |
7830 |
-+ * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a |
7831 |
-+ * message'sbloom filter |
7832 |
-+ * @KDBUS_ITEM_DST_NAME: Destination's well-known name |
7833 |
-+ * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint |
7834 |
-+ * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which |
7835 |
-+ * metadata a connection opts in to send |
7836 |
-+ * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which |
7837 |
-+ * metadata a connection requests to |
7838 |
-+ * receive for each reeceived message |
7839 |
-+ * @KDBUS_ITEM_ID: Connection ID |
7840 |
-+ * @KDBUS_ITEM_NAME: Well-know name with flags |
7841 |
-+ * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items |
7842 |
-+ * @KDBUS_ITEM_TIMESTAMP: Timestamp |
7843 |
-+ * @KDBUS_ITEM_CREDS: Process credentials |
7844 |
-+ * @KDBUS_ITEM_PIDS: Process identifiers |
7845 |
-+ * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups |
7846 |
-+ * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated |
7847 |
-+ * connection |
7848 |
-+ * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier |
7849 |
-+ * (Don't trust this, see below.) |
7850 |
-+ * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier |
7851 |
-+ * (Don't trust this, see below.) |
7852 |
-+ * @KDBUS_ITEM_EXE: The path of the executable |
7853 |
-+ * (Don't trust this, see below.) |
7854 |
-+ * @KDBUS_ITEM_CMDLINE: The process command line |
7855 |
-+ * (Don't trust this, see below.) |
7856 |
-+ * @KDBUS_ITEM_CGROUP: The croup membership |
7857 |
-+ * @KDBUS_ITEM_CAPS: The process capabilities |
7858 |
-+ * @KDBUS_ITEM_SECLABEL: The security label |
7859 |
-+ * @KDBUS_ITEM_AUDIT: The audit IDs |
7860 |
-+ * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name |
7861 |
-+ * (debugging) |
7862 |
-+ * @_KDBUS_ITEM_POLICY_BASE: Start of policy items |
7863 |
-+ * @KDBUS_ITEM_POLICY_ACCESS: Policy access block |
7864 |
-+ * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items |
7865 |
-+ * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change |
7866 |
-+ * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change |
7867 |
-+ * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change |
7868 |
-+ * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change |
7869 |
-+ * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change |
7870 |
-+ * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached |
7871 |
-+ * @KDBUS_ITEM_REPLY_DEAD: Destination died |
7872 |
-+ * |
7873 |
-+ * N.B: The process and thread COMM fields, as well as the CMDLINE and |
7874 |
-+ * EXE fields may be altered by unprivileged processes und should |
7875 |
-+ * hence *not* used for security decisions. Peers should make use of |
7876 |
-+ * these items only for informational purposes, such as generating log |
7877 |
-+ * records. |
7878 |
-+ */ |
7879 |
-+enum kdbus_item_type { |
7880 |
-+ _KDBUS_ITEM_NULL, |
7881 |
-+ _KDBUS_ITEM_USER_BASE, |
7882 |
-+ KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE, |
7883 |
-+ KDBUS_ITEM_PAYLOAD_VEC, |
7884 |
-+ KDBUS_ITEM_PAYLOAD_OFF, |
7885 |
-+ KDBUS_ITEM_PAYLOAD_MEMFD, |
7886 |
-+ KDBUS_ITEM_FDS, |
7887 |
-+ KDBUS_ITEM_CANCEL_FD, |
7888 |
-+ KDBUS_ITEM_BLOOM_PARAMETER, |
7889 |
-+ KDBUS_ITEM_BLOOM_FILTER, |
7890 |
-+ KDBUS_ITEM_BLOOM_MASK, |
7891 |
-+ KDBUS_ITEM_DST_NAME, |
7892 |
-+ KDBUS_ITEM_MAKE_NAME, |
7893 |
-+ KDBUS_ITEM_ATTACH_FLAGS_SEND, |
7894 |
-+ KDBUS_ITEM_ATTACH_FLAGS_RECV, |
7895 |
-+ KDBUS_ITEM_ID, |
7896 |
-+ KDBUS_ITEM_NAME, |
7897 |
-+ KDBUS_ITEM_DST_ID, |
7898 |
-+ |
7899 |
-+ /* keep these item types in sync with KDBUS_ATTACH_* flags */ |
7900 |
-+ _KDBUS_ITEM_ATTACH_BASE = 0x1000, |
7901 |
-+ KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE, |
7902 |
-+ KDBUS_ITEM_CREDS, |
7903 |
-+ KDBUS_ITEM_PIDS, |
7904 |
-+ KDBUS_ITEM_AUXGROUPS, |
7905 |
-+ KDBUS_ITEM_OWNED_NAME, |
7906 |
-+ KDBUS_ITEM_TID_COMM, |
7907 |
-+ KDBUS_ITEM_PID_COMM, |
7908 |
-+ KDBUS_ITEM_EXE, |
7909 |
-+ KDBUS_ITEM_CMDLINE, |
7910 |
-+ KDBUS_ITEM_CGROUP, |
7911 |
-+ KDBUS_ITEM_CAPS, |
7912 |
-+ KDBUS_ITEM_SECLABEL, |
7913 |
-+ KDBUS_ITEM_AUDIT, |
7914 |
-+ KDBUS_ITEM_CONN_DESCRIPTION, |
7915 |
-+ |
7916 |
-+ _KDBUS_ITEM_POLICY_BASE = 0x2000, |
7917 |
-+ KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE, |
7918 |
-+ |
7919 |
-+ _KDBUS_ITEM_KERNEL_BASE = 0x8000, |
7920 |
-+ KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE, |
7921 |
-+ KDBUS_ITEM_NAME_REMOVE, |
7922 |
-+ KDBUS_ITEM_NAME_CHANGE, |
7923 |
-+ KDBUS_ITEM_ID_ADD, |
7924 |
-+ KDBUS_ITEM_ID_REMOVE, |
7925 |
-+ KDBUS_ITEM_REPLY_TIMEOUT, |
7926 |
-+ KDBUS_ITEM_REPLY_DEAD, |
7927 |
-+}; |
7928 |
-+ |
7929 |
-+/** |
7930 |
-+ * struct kdbus_item - chain of data blocks |
7931 |
-+ * @size: Overall data record size |
7932 |
-+ * @type: Kdbus_item type of data |
7933 |
-+ * @data: Generic bytes |
7934 |
-+ * @data32: Generic 32 bit array |
7935 |
-+ * @data64: Generic 64 bit array |
7936 |
-+ * @str: Generic string |
7937 |
-+ * @id: Connection ID |
7938 |
-+ * @vec: KDBUS_ITEM_PAYLOAD_VEC |
7939 |
-+ * @creds: KDBUS_ITEM_CREDS |
7940 |
-+ * @audit: KDBUS_ITEM_AUDIT |
7941 |
-+ * @timestamp: KDBUS_ITEM_TIMESTAMP |
7942 |
-+ * @name: KDBUS_ITEM_NAME |
7943 |
-+ * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER |
7944 |
-+ * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER |
7945 |
-+ * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD |
7946 |
-+ * @name_change: KDBUS_ITEM_NAME_ADD |
7947 |
-+ * KDBUS_ITEM_NAME_REMOVE |
7948 |
-+ * KDBUS_ITEM_NAME_CHANGE |
7949 |
-+ * @id_change: KDBUS_ITEM_ID_ADD |
7950 |
-+ * KDBUS_ITEM_ID_REMOVE |
7951 |
-+ * @policy: KDBUS_ITEM_POLICY_ACCESS |
7952 |
-+ */ |
7953 |
-+struct kdbus_item { |
7954 |
-+ __u64 size; |
7955 |
-+ __u64 type; |
7956 |
-+ union { |
7957 |
-+ __u8 data[0]; |
7958 |
-+ __u32 data32[0]; |
7959 |
-+ __u64 data64[0]; |
7960 |
-+ char str[0]; |
7961 |
-+ |
7962 |
-+ __u64 id; |
7963 |
-+ struct kdbus_vec vec; |
7964 |
-+ struct kdbus_creds creds; |
7965 |
-+ struct kdbus_pids pids; |
7966 |
-+ struct kdbus_audit audit; |
7967 |
-+ struct kdbus_caps caps; |
7968 |
-+ struct kdbus_timestamp timestamp; |
7969 |
-+ struct kdbus_name name; |
7970 |
-+ struct kdbus_bloom_parameter bloom_parameter; |
7971 |
-+ struct kdbus_bloom_filter bloom_filter; |
7972 |
-+ struct kdbus_memfd memfd; |
7973 |
-+ int fds[0]; |
7974 |
-+ struct kdbus_notify_name_change name_change; |
7975 |
-+ struct kdbus_notify_id_change id_change; |
7976 |
-+ struct kdbus_policy_access policy_access; |
7977 |
-+ }; |
7978 |
-+} __attribute__((__aligned__(8))); |
7979 |
-+ |
7980 |
-+/** |
7981 |
-+ * enum kdbus_msg_flags - type of message |
7982 |
-+ * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for |
7983 |
-+ * method calls. The userspace-supplied |
7984 |
-+ * cookie identifies the message and the |
7985 |
-+ * respective reply carries the cookie |
7986 |
-+ * in cookie_reply |
7987 |
-+ * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed |
7988 |
-+ * name is not currently active. This flag is |
7989 |
-+ * not looked at by the kernel but only |
7990 |
-+ * serves as hint for userspace implementations. |
7991 |
-+ * @KDBUS_MSG_SIGNAL: Treat this message as signal |
7992 |
-+ */ |
7993 |
-+enum kdbus_msg_flags { |
7994 |
-+ KDBUS_MSG_EXPECT_REPLY = 1ULL << 0, |
7995 |
-+ KDBUS_MSG_NO_AUTO_START = 1ULL << 1, |
7996 |
-+ KDBUS_MSG_SIGNAL = 1ULL << 2, |
7997 |
-+}; |
7998 |
-+ |
7999 |
-+/** |
8000 |
-+ * enum kdbus_payload_type - type of payload carried by message |
8001 |
-+ * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message |
8002 |
-+ * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus" |
8003 |
-+ * |
8004 |
-+ * Any payload-type is accepted. Common types will get added here once |
8005 |
-+ * established. |
8006 |
-+ */ |
8007 |
-+enum kdbus_payload_type { |
8008 |
-+ KDBUS_PAYLOAD_KERNEL, |
8009 |
-+ KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL, |
8010 |
-+}; |
8011 |
-+ |
8012 |
-+/** |
8013 |
-+ * struct kdbus_msg - the representation of a kdbus message |
8014 |
-+ * @size: Total size of the message |
8015 |
-+ * @flags: Message flags (KDBUS_MSG_*), userspace → kernel |
8016 |
-+ * @priority: Message queue priority value |
8017 |
-+ * @dst_id: 64-bit ID of the destination connection |
8018 |
-+ * @src_id: 64-bit ID of the source connection |
8019 |
-+ * @payload_type: Payload type (KDBUS_PAYLOAD_*) |
8020 |
-+ * @cookie: Userspace-supplied cookie, for the connection |
8021 |
-+ * to identify its messages |
8022 |
-+ * @timeout_ns: The time to wait for a message reply from the peer. |
8023 |
-+ * If there is no reply, and the send command is |
8024 |
-+ * executed asynchronously, a kernel-generated message |
8025 |
-+ * with an attached KDBUS_ITEM_REPLY_TIMEOUT item |
8026 |
-+ * is sent to @src_id. For synchronously executed send |
8027 |
-+ * command, the value denotes the maximum time the call |
8028 |
-+ * blocks to wait for a reply. The timeout is expected in |
8029 |
-+ * nanoseconds and as absolute CLOCK_MONOTONIC value. |
8030 |
-+ * @cookie_reply: A reply to the requesting message with the same |
8031 |
-+ * cookie. The requesting connection can match its |
8032 |
-+ * request and the reply with this value |
8033 |
-+ * @items: A list of kdbus_items containing the message payload |
8034 |
-+ */ |
8035 |
-+struct kdbus_msg { |
8036 |
-+ __u64 size; |
8037 |
-+ __u64 flags; |
8038 |
-+ __s64 priority; |
8039 |
-+ __u64 dst_id; |
8040 |
-+ __u64 src_id; |
8041 |
-+ __u64 payload_type; |
8042 |
-+ __u64 cookie; |
8043 |
-+ union { |
8044 |
-+ __u64 timeout_ns; |
8045 |
-+ __u64 cookie_reply; |
8046 |
-+ }; |
8047 |
-+ struct kdbus_item items[0]; |
8048 |
-+} __attribute__((__aligned__(8))); |
8049 |
-+ |
8050 |
-+/** |
8051 |
-+ * struct kdbus_msg_info - returned message container |
8052 |
-+ * @offset: Offset of kdbus_msg slice in pool |
8053 |
-+ * @msg_size: Copy of the kdbus_msg.size field |
8054 |
-+ * @return_flags: Command return flags, kernel → userspace |
8055 |
-+ */ |
8056 |
-+struct kdbus_msg_info { |
8057 |
-+ __u64 offset; |
8058 |
-+ __u64 msg_size; |
8059 |
-+ __u64 return_flags; |
8060 |
-+} __attribute__((__aligned__(8))); |
8061 |
-+ |
8062 |
-+/** |
8063 |
-+ * enum kdbus_send_flags - flags for sending messages |
8064 |
-+ * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to |
8065 |
-+ * reply to this message. The |
8066 |
-+ * KDBUS_CMD_SEND ioctl() will block |
8067 |
-+ * until the reply is received, and |
8068 |
-+ * reply in struct kdbus_cmd_send will |
8069 |
-+ * yield the offset in the sender's pool |
8070 |
-+ * where the reply can be found. |
8071 |
-+ * This flag is only valid if |
8072 |
-+ * @KDBUS_MSG_EXPECT_REPLY is set as well. |
8073 |
-+ */ |
8074 |
-+enum kdbus_send_flags { |
8075 |
-+ KDBUS_SEND_SYNC_REPLY = 1ULL << 0, |
8076 |
-+}; |
8077 |
-+ |
8078 |
-+/** |
8079 |
-+ * struct kdbus_cmd_send - send message |
8080 |
-+ * @size: Overall size of this structure |
8081 |
-+ * @flags: Flags to change send behavior (KDBUS_SEND_*) |
8082 |
-+ * @return_flags: Command return flags, kernel → userspace |
8083 |
-+ * @msg_address: Storage address of the kdbus_msg to send |
8084 |
-+ * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY |
8085 |
-+ * was given |
8086 |
-+ * @items: Additional items for this command |
8087 |
-+ */ |
8088 |
-+struct kdbus_cmd_send { |
8089 |
-+ __u64 size; |
8090 |
-+ __u64 flags; |
8091 |
-+ __u64 return_flags; |
8092 |
-+ __u64 msg_address; |
8093 |
-+ struct kdbus_msg_info reply; |
8094 |
-+ struct kdbus_item items[0]; |
8095 |
-+} __attribute__((__aligned__(8))); |
8096 |
-+ |
8097 |
-+/** |
8098 |
-+ * enum kdbus_recv_flags - flags for de-queuing messages |
8099 |
-+ * @KDBUS_RECV_PEEK: Return the next queued message without |
8100 |
-+ * actually de-queuing it, and without installing |
8101 |
-+ * any file descriptors or other resources. It is |
8102 |
-+ * usually used to determine the activating |
8103 |
-+ * connection of a bus name. |
8104 |
-+ * @KDBUS_RECV_DROP: Drop and free the next queued message and all |
8105 |
-+ * its resources without actually receiving it. |
8106 |
-+ * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or |
8107 |
-+ * higher priority (lowest values); if not set, |
8108 |
-+ * the priority value is ignored. |
8109 |
-+ */ |
8110 |
-+enum kdbus_recv_flags { |
8111 |
-+ KDBUS_RECV_PEEK = 1ULL << 0, |
8112 |
-+ KDBUS_RECV_DROP = 1ULL << 1, |
8113 |
-+ KDBUS_RECV_USE_PRIORITY = 1ULL << 2, |
8114 |
-+}; |
8115 |
-+ |
8116 |
-+/** |
8117 |
-+ * enum kdbus_recv_return_flags - return flags for message receive commands |
8118 |
-+ * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not |
8119 |
-+ * be installed. These descriptors in |
8120 |
-+ * KDBUS_ITEM_FDS will carry the value -1. |
8121 |
-+ * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since |
8122 |
-+ * the last time a message was received. |
8123 |
-+ * The 'dropped_msgs' counter contains the |
8124 |
-+ * number of messages dropped pool |
8125 |
-+ * overflows or other missed broadcasts. |
8126 |
-+ */ |
8127 |
-+enum kdbus_recv_return_flags { |
8128 |
-+ KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0, |
8129 |
-+ KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1, |
8130 |
-+}; |
8131 |
-+ |
8132 |
-+/** |
8133 |
-+ * struct kdbus_cmd_recv - struct to de-queue a buffered message |
8134 |
-+ * @size: Overall size of this object |
8135 |
-+ * @flags: KDBUS_RECV_* flags, userspace → kernel |
8136 |
-+ * @return_flags: Command return flags, kernel → userspace |
8137 |
-+ * @priority: Minimum priority of the messages to de-queue. Lowest |
8138 |
-+ * values have the highest priority. |
8139 |
-+ * @dropped_msgs: In case there were any dropped messages since the last |
8140 |
-+ * time a message was received, this will be set to the |
8141 |
-+ * number of lost messages and |
8142 |
-+ * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in |
8143 |
-+ * 'return_flags'. This can only happen if the ioctl |
8144 |
-+ * returns 0 or EAGAIN. |
8145 |
-+ * @msg: Return storage for received message. |
8146 |
-+ * @items: Additional items for this command. |
8147 |
-+ * |
8148 |
-+ * This struct is used with the KDBUS_CMD_RECV ioctl. |
8149 |
-+ */ |
8150 |
-+struct kdbus_cmd_recv { |
8151 |
-+ __u64 size; |
8152 |
-+ __u64 flags; |
8153 |
-+ __u64 return_flags; |
8154 |
-+ __s64 priority; |
8155 |
-+ __u64 dropped_msgs; |
8156 |
-+ struct kdbus_msg_info msg; |
8157 |
-+ struct kdbus_item items[0]; |
8158 |
-+} __attribute__((__aligned__(8))); |
8159 |
-+ |
8160 |
-+/** |
8161 |
-+ * struct kdbus_cmd_free - struct to free a slice of memory in the pool |
8162 |
-+ * @size: Overall size of this structure |
8163 |
-+ * @flags: Flags for the free command, userspace → kernel |
8164 |
-+ * @return_flags: Command return flags, kernel → userspace |
8165 |
-+ * @offset: The offset of the memory slice, as returned by other |
8166 |
-+ * ioctls |
8167 |
-+ * @items: Additional items to modify the behavior |
8168 |
-+ * |
8169 |
-+ * This struct is used with the KDBUS_CMD_FREE ioctl. |
8170 |
-+ */ |
8171 |
-+struct kdbus_cmd_free { |
8172 |
-+ __u64 size; |
8173 |
-+ __u64 flags; |
8174 |
-+ __u64 return_flags; |
8175 |
-+ __u64 offset; |
8176 |
-+ struct kdbus_item items[0]; |
8177 |
-+} __attribute__((__aligned__(8))); |
8178 |
-+ |
8179 |
-+/** |
8180 |
-+ * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello |
8181 |
-+ * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of |
8182 |
-+ * any passed file descriptors |
8183 |
-+ * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers |
8184 |
-+ * a well-know name for a process to be started |
8185 |
-+ * when traffic arrives |
8186 |
-+ * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers |
8187 |
-+ * policy entries for a name. The provided name |
8188 |
-+ * is not activated and not registered with the |
8189 |
-+ * name database, it only allows unprivileged |
8190 |
-+ * connections to acquire a name, talk or discover |
8191 |
-+ * a service |
8192 |
-+ * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor |
8193 |
-+ * bus traffic |
8194 |
-+ */ |
8195 |
-+enum kdbus_hello_flags { |
8196 |
-+ KDBUS_HELLO_ACCEPT_FD = 1ULL << 0, |
8197 |
-+ KDBUS_HELLO_ACTIVATOR = 1ULL << 1, |
8198 |
-+ KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2, |
8199 |
-+ KDBUS_HELLO_MONITOR = 1ULL << 3, |
8200 |
-+}; |
8201 |
-+ |
8202 |
-+/** |
8203 |
-+ * struct kdbus_cmd_hello - struct to say hello to kdbus |
8204 |
-+ * @size: The total size of the structure |
8205 |
-+ * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel |
8206 |
-+ * @return_flags: Command return flags, kernel → userspace |
8207 |
-+ * @attach_flags_send: Mask of metadata to attach to each message sent |
8208 |
-+ * off by this connection (KDBUS_ATTACH_*) |
8209 |
-+ * @attach_flags_recv: Mask of metadata to attach to each message receieved |
8210 |
-+ * by the new connection (KDBUS_ATTACH_*) |
8211 |
-+ * @bus_flags: The flags field copied verbatim from the original |
8212 |
-+ * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful |
8213 |
-+ * to do negotiation of features of the payload that is |
8214 |
-+ * transferred (kernel → userspace) |
8215 |
-+ * @id: The ID of this connection (kernel → userspace) |
8216 |
-+ * @pool_size: Size of the connection's buffer where the received |
8217 |
-+ * messages are placed |
8218 |
-+ * @offset: Pool offset where items are returned to report |
8219 |
-+ * additional information about the bus and the newly |
8220 |
-+ * created connection. |
8221 |
-+ * @items_size: Size of buffer returned in the pool slice at @offset. |
8222 |
-+ * @id128: Unique 128-bit ID of the bus (kernel → userspace) |
8223 |
-+ * @items: A list of items |
8224 |
-+ * |
8225 |
-+ * This struct is used with the KDBUS_CMD_HELLO ioctl. |
8226 |
-+ */ |
8227 |
-+struct kdbus_cmd_hello { |
8228 |
-+ __u64 size; |
8229 |
-+ __u64 flags; |
8230 |
-+ __u64 return_flags; |
8231 |
-+ __u64 attach_flags_send; |
8232 |
-+ __u64 attach_flags_recv; |
8233 |
-+ __u64 bus_flags; |
8234 |
-+ __u64 id; |
8235 |
-+ __u64 pool_size; |
8236 |
-+ __u64 offset; |
8237 |
-+ __u64 items_size; |
8238 |
-+ __u8 id128[16]; |
8239 |
-+ struct kdbus_item items[0]; |
8240 |
-+} __attribute__((__aligned__(8))); |
8241 |
-+ |
8242 |
-+/** |
8243 |
-+ * struct kdbus_info - connection information |
8244 |
-+ * @size: total size of the struct |
8245 |
-+ * @id: 64bit object ID |
8246 |
-+ * @flags: object creation flags |
8247 |
-+ * @items: list of items |
8248 |
-+ * |
8249 |
-+ * Note that the user is responsible for freeing the allocated memory with |
8250 |
-+ * the KDBUS_CMD_FREE ioctl. |
8251 |
-+ */ |
8252 |
-+struct kdbus_info { |
8253 |
-+ __u64 size; |
8254 |
-+ __u64 id; |
8255 |
-+ __u64 flags; |
8256 |
-+ struct kdbus_item items[0]; |
8257 |
-+} __attribute__((__aligned__(8))); |
8258 |
-+ |
8259 |
-+/** |
8260 |
-+ * enum kdbus_list_flags - what to include into the returned list |
8261 |
-+ * @KDBUS_LIST_UNIQUE: active connections |
8262 |
-+ * @KDBUS_LIST_ACTIVATORS: activator connections |
8263 |
-+ * @KDBUS_LIST_NAMES: known well-known names |
8264 |
-+ * @KDBUS_LIST_QUEUED: queued-up names |
8265 |
-+ */ |
8266 |
-+enum kdbus_list_flags { |
8267 |
-+ KDBUS_LIST_UNIQUE = 1ULL << 0, |
8268 |
-+ KDBUS_LIST_NAMES = 1ULL << 1, |
8269 |
-+ KDBUS_LIST_ACTIVATORS = 1ULL << 2, |
8270 |
-+ KDBUS_LIST_QUEUED = 1ULL << 3, |
8271 |
-+}; |
8272 |
-+ |
8273 |
-+/** |
8274 |
-+ * struct kdbus_cmd_list - list connections |
8275 |
-+ * @size: overall size of this object |
8276 |
-+ * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel |
8277 |
-+ * @return_flags: command return flags, kernel → userspace |
8278 |
-+ * @offset: Offset in the caller's pool buffer where an array of |
8279 |
-+ * kdbus_info objects is stored. |
8280 |
-+ * The user must use KDBUS_CMD_FREE to free the |
8281 |
-+ * allocated memory. |
8282 |
-+ * @list_size: size of returned list in bytes |
8283 |
-+ * @items: Items for the command. Reserved for future use. |
8284 |
-+ * |
8285 |
-+ * This structure is used with the KDBUS_CMD_LIST ioctl. |
8286 |
-+ */ |
8287 |
-+struct kdbus_cmd_list { |
8288 |
-+ __u64 size; |
8289 |
-+ __u64 flags; |
8290 |
-+ __u64 return_flags; |
8291 |
-+ __u64 offset; |
8292 |
-+ __u64 list_size; |
8293 |
-+ struct kdbus_item items[0]; |
8294 |
-+} __attribute__((__aligned__(8))); |
8295 |
-+ |
8296 |
-+/** |
8297 |
-+ * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl |
8298 |
-+ * @size: The total size of the struct |
8299 |
-+ * @flags: Flags for this ioctl, userspace → kernel |
8300 |
-+ * @return_flags: Command return flags, kernel → userspace |
8301 |
-+ * @id: The 64-bit ID of the connection. If set to zero, passing |
8302 |
-+ * @name is required. kdbus will look up the name to |
8303 |
-+ * determine the ID in this case. |
8304 |
-+ * @attach_flags: Set of attach flags to specify the set of information |
8305 |
-+ * to receive, userspace → kernel |
8306 |
-+ * @offset: Returned offset in the caller's pool buffer where the |
8307 |
-+ * kdbus_info struct result is stored. The user must |
8308 |
-+ * use KDBUS_CMD_FREE to free the allocated memory. |
8309 |
-+ * @info_size: Output buffer to report size of data at @offset. |
8310 |
-+ * @items: The optional item list, containing the |
8311 |
-+ * well-known name to look up as a KDBUS_ITEM_NAME. |
8312 |
-+ * Only needed in case @id is zero. |
8313 |
-+ * |
8314 |
-+ * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will |
8315 |
-+ * tell the user the offset in the connection pool buffer at which to find the |
8316 |
-+ * result in a struct kdbus_info. |
8317 |
-+ */ |
8318 |
-+struct kdbus_cmd_info { |
8319 |
-+ __u64 size; |
8320 |
-+ __u64 flags; |
8321 |
-+ __u64 return_flags; |
8322 |
-+ __u64 id; |
8323 |
-+ __u64 attach_flags; |
8324 |
-+ __u64 offset; |
8325 |
-+ __u64 info_size; |
8326 |
-+ struct kdbus_item items[0]; |
8327 |
-+} __attribute__((__aligned__(8))); |
8328 |
-+ |
8329 |
-+/** |
8330 |
-+ * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl |
8331 |
-+ * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already |
8332 |
-+ * exists, remove them before installing the new |
8333 |
-+ * matches. |
8334 |
-+ */ |
8335 |
-+enum kdbus_cmd_match_flags { |
8336 |
-+ KDBUS_MATCH_REPLACE = 1ULL << 0, |
8337 |
-+}; |
8338 |
-+ |
8339 |
-+/** |
8340 |
-+ * struct kdbus_cmd_match - struct to add or remove matches |
8341 |
-+ * @size: The total size of the struct |
8342 |
-+ * @flags: Flags for match command (KDBUS_MATCH_*), |
8343 |
-+ * userspace → kernel |
8344 |
-+ * @return_flags: Command return flags, kernel → userspace |
8345 |
-+ * @cookie: Userspace supplied cookie. When removing, the cookie |
8346 |
-+ * identifies the match to remove |
8347 |
-+ * @items: A list of items for additional information |
8348 |
-+ * |
8349 |
-+ * This structure is used with the KDBUS_CMD_MATCH_ADD and |
8350 |
-+ * KDBUS_CMD_MATCH_REMOVE ioctl. |
8351 |
-+ */ |
8352 |
-+struct kdbus_cmd_match { |
8353 |
-+ __u64 size; |
8354 |
-+ __u64 flags; |
8355 |
-+ __u64 return_flags; |
8356 |
-+ __u64 cookie; |
8357 |
-+ struct kdbus_item items[0]; |
8358 |
-+} __attribute__((__aligned__(8))); |
8359 |
-+ |
8360 |
-+/** |
8361 |
-+ * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE |
8362 |
-+ * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible |
8363 |
-+ * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible |
8364 |
-+ */ |
8365 |
-+enum kdbus_make_flags { |
8366 |
-+ KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0, |
8367 |
-+ KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1, |
8368 |
-+}; |
8369 |
-+ |
8370 |
-+/** |
8371 |
-+ * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE |
8372 |
-+ * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections |
8373 |
-+ * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name |
8374 |
-+ * @KDBUS_NAME_QUEUE: Name should be queued if busy |
8375 |
-+ * @KDBUS_NAME_IN_QUEUE: Name is queued |
8376 |
-+ * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection |
8377 |
-+ * @KDBUS_NAME_PRIMARY: Primary owner of the name |
8378 |
-+ * @KDBUS_NAME_ACQUIRED: Name was acquired/queued _now_ |
8379 |
-+ */ |
8380 |
-+enum kdbus_name_flags { |
8381 |
-+ KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0, |
8382 |
-+ KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1, |
8383 |
-+ KDBUS_NAME_QUEUE = 1ULL << 2, |
8384 |
-+ KDBUS_NAME_IN_QUEUE = 1ULL << 3, |
8385 |
-+ KDBUS_NAME_ACTIVATOR = 1ULL << 4, |
8386 |
-+ KDBUS_NAME_PRIMARY = 1ULL << 5, |
8387 |
-+ KDBUS_NAME_ACQUIRED = 1ULL << 6, |
8388 |
-+}; |
8389 |
-+ |
8390 |
-+/** |
8391 |
-+ * struct kdbus_cmd - generic ioctl payload |
8392 |
-+ * @size: Overall size of this structure |
8393 |
-+ * @flags: Flags for this ioctl, userspace → kernel |
8394 |
-+ * @return_flags: Ioctl return flags, kernel → userspace |
8395 |
-+ * @items: Additional items to modify the behavior |
8396 |
-+ * |
8397 |
-+ * This is a generic ioctl payload object. It's used by all ioctls that only |
8398 |
-+ * take flags and items as input. |
8399 |
-+ */ |
8400 |
-+struct kdbus_cmd { |
8401 |
-+ __u64 size; |
8402 |
-+ __u64 flags; |
8403 |
-+ __u64 return_flags; |
8404 |
-+ struct kdbus_item items[0]; |
8405 |
-+} __attribute__((__aligned__(8))); |
8406 |
-+ |
8407 |
-+/** |
8408 |
-+ * Ioctl API |
8409 |
-+ * |
8410 |
-+ * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command |
8411 |
-+ * creates a new bus with the specified |
8412 |
-+ * name. The bus is immediately shut down and |
8413 |
-+ * cleaned up when the opened file descriptor is |
8414 |
-+ * closed. |
8415 |
-+ * |
8416 |
-+ * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to |
8417 |
-+ * the bus. Such endpoints usually carry a more |
8418 |
-+ * restrictive policy and grant restricted access |
8419 |
-+ * to specific applications. |
8420 |
-+ * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used |
8421 |
-+ * to update the policy. |
8422 |
-+ * |
8423 |
-+ * KDBUS_CMD_HELLO: By opening the bus node, a connection is |
8424 |
-+ * created. After a HELLO the opened connection |
8425 |
-+ * becomes an active peer on the bus. |
8426 |
-+ * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to |
8427 |
-+ * update the metadata subscription mask and |
8428 |
-+ * policy. |
8429 |
-+ * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no |
8430 |
-+ * messages queued up in the connection's pool, |
8431 |
-+ * the call succeeds, and the handle is rendered |
8432 |
-+ * unusable. Otherwise, -EBUSY is returned without |
8433 |
-+ * any further side-effects. |
8434 |
-+ * KDBUS_CMD_FREE: Release the allocated memory in the receiver's |
8435 |
-+ * pool. |
8436 |
-+ * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the |
8437 |
-+ * initial creator of the connection. The data was |
8438 |
-+ * stored at registration time and does not |
8439 |
-+ * necessarily represent the connected process or |
8440 |
-+ * the actual state of the process. |
8441 |
-+ * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus |
8442 |
-+ * a connection is attached to. |
8443 |
-+ * |
8444 |
-+ * KDBUS_CMD_SEND: Send a message and pass data from userspace to |
8445 |
-+ * the kernel. |
8446 |
-+ * KDBUS_CMD_RECV: Receive a message from the kernel which is |
8447 |
-+ * placed in the receiver's pool. |
8448 |
-+ * |
8449 |
-+ * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with |
8450 |
-+ * the connection. Well-known names are used to |
8451 |
-+ * address a peer on the bus. |
8452 |
-+ * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection |
8453 |
-+ * currently owns. |
8454 |
-+ * KDBUS_CMD_LIST: Retrieve the list of all currently registered |
8455 |
-+ * well-known and unique names. |
8456 |
-+ * |
8457 |
-+ * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should |
8458 |
-+ * be delivered to the connection. |
8459 |
-+ * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages. |
8460 |
-+ */ |
8461 |
-+enum kdbus_ioctl_type { |
8462 |
-+ /* bus owner (00-0f) */ |
8463 |
-+ KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00, |
8464 |
-+ struct kdbus_cmd), |
8465 |
-+ |
8466 |
-+ /* endpoint owner (10-1f) */ |
8467 |
-+ KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10, |
8468 |
-+ struct kdbus_cmd), |
8469 |
-+ KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11, |
8470 |
-+ struct kdbus_cmd), |
8471 |
-+ |
8472 |
-+ /* connection owner (80-ff) */ |
8473 |
-+ KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80, |
8474 |
-+ struct kdbus_cmd_hello), |
8475 |
-+ KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81, |
8476 |
-+ struct kdbus_cmd), |
8477 |
-+ KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82, |
8478 |
-+ struct kdbus_cmd), |
8479 |
-+ KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83, |
8480 |
-+ struct kdbus_cmd_free), |
8481 |
-+ KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84, |
8482 |
-+ struct kdbus_cmd_info), |
8483 |
-+ KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85, |
8484 |
-+ struct kdbus_cmd_info), |
8485 |
-+ KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86, |
8486 |
-+ struct kdbus_cmd_list), |
8487 |
-+ |
8488 |
-+ KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90, |
8489 |
-+ struct kdbus_cmd_send), |
8490 |
-+ KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91, |
8491 |
-+ struct kdbus_cmd_recv), |
8492 |
-+ |
8493 |
-+ KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0, |
8494 |
-+ struct kdbus_cmd), |
8495 |
-+ KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1, |
8496 |
-+ struct kdbus_cmd), |
8497 |
-+ |
8498 |
-+ KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0, |
8499 |
-+ struct kdbus_cmd_match), |
8500 |
-+ KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1, |
8501 |
-+ struct kdbus_cmd_match), |
8502 |
-+}; |
8503 |
-+ |
8504 |
-+#endif /* _UAPI_KDBUS_H_ */ |
8505 |
-diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h |
8506 |
-index 7b1425a..ce2ac5a 100644 |
8507 |
---- a/include/uapi/linux/magic.h |
8508 |
-+++ b/include/uapi/linux/magic.h |
8509 |
-@@ -76,4 +76,6 @@ |
8510 |
- #define BTRFS_TEST_MAGIC 0x73727279 |
8511 |
- #define NSFS_MAGIC 0x6e736673 |
8512 |
- |
8513 |
-+#define KDBUS_SUPER_MAGIC 0x44427573 |
8514 |
-+ |
8515 |
- #endif /* __LINUX_MAGIC_H__ */ |
8516 |
-diff --git a/init/Kconfig b/init/Kconfig |
8517 |
-index dc24dec..9388071 100644 |
8518 |
---- a/init/Kconfig |
8519 |
-+++ b/init/Kconfig |
8520 |
-@@ -261,6 +261,19 @@ config POSIX_MQUEUE_SYSCTL |
8521 |
- depends on SYSCTL |
8522 |
- default y |
8523 |
- |
8524 |
-+config KDBUS |
8525 |
-+ tristate "kdbus interprocess communication" |
8526 |
-+ depends on TMPFS |
8527 |
-+ help |
8528 |
-+ D-Bus is a system for low-latency, low-overhead, easy to use |
8529 |
-+ interprocess communication (IPC). |
8530 |
-+ |
8531 |
-+ See the man-pages and HTML files in Documentation/kdbus/ |
8532 |
-+ that are generated by 'make mandocs' and 'make htmldocs'. |
8533 |
-+ |
8534 |
-+ If you have an ordinary machine, select M here. The module |
8535 |
-+ will be called kdbus. |
8536 |
-+ |
8537 |
- config CROSS_MEMORY_ATTACH |
8538 |
- bool "Enable process_vm_readv/writev syscalls" |
8539 |
- depends on MMU |
8540 |
-diff --git a/ipc/Makefile b/ipc/Makefile |
8541 |
-index 86c7300..68ec416 100644 |
8542 |
---- a/ipc/Makefile |
8543 |
-+++ b/ipc/Makefile |
8544 |
-@@ -9,4 +9,4 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
8545 |
- obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
8546 |
- obj-$(CONFIG_IPC_NS) += namespace.o |
8547 |
- obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o |
8548 |
-- |
8549 |
-+obj-$(CONFIG_KDBUS) += kdbus/ |
8550 |
-diff --git a/ipc/kdbus/Makefile b/ipc/kdbus/Makefile |
8551 |
-new file mode 100644 |
8552 |
-index 0000000..66663a1 |
8553 |
---- /dev/null |
8554 |
-+++ b/ipc/kdbus/Makefile |
8555 |
-@@ -0,0 +1,33 @@ |
8556 |
-+# |
8557 |
-+# By setting KDBUS_EXT=2, the kdbus module will be built as kdbus2.ko, and |
8558 |
-+# KBUILD_MODNAME=kdbus2. This has the effect that all exported objects have |
8559 |
-+# different names than usually (kdbus2fs, /sys/fs/kdbus2/) and you can run |
8560 |
-+# your test-infrastructure against the kdbus2.ko, while running your system |
8561 |
-+# on kdbus.ko. |
8562 |
-+# |
8563 |
-+# To just build the module, use: |
8564 |
-+# make KDBUS_EXT=2 M=ipc/kdbus |
8565 |
-+# |
8566 |
-+ |
8567 |
-+kdbus$(KDBUS_EXT)-y := \ |
8568 |
-+ bus.o \ |
8569 |
-+ connection.o \ |
8570 |
-+ endpoint.o \ |
8571 |
-+ fs.o \ |
8572 |
-+ handle.o \ |
8573 |
-+ item.o \ |
8574 |
-+ main.o \ |
8575 |
-+ match.o \ |
8576 |
-+ message.o \ |
8577 |
-+ metadata.o \ |
8578 |
-+ names.o \ |
8579 |
-+ node.o \ |
8580 |
-+ notify.o \ |
8581 |
-+ domain.o \ |
8582 |
-+ policy.o \ |
8583 |
-+ pool.o \ |
8584 |
-+ reply.o \ |
8585 |
-+ queue.o \ |
8586 |
-+ util.o |
8587 |
-+ |
8588 |
-+obj-$(CONFIG_KDBUS) += kdbus$(KDBUS_EXT).o |
8589 |
-diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c |
8590 |
-new file mode 100644 |
8591 |
-index 0000000..a67f825 |
8592 |
---- /dev/null |
8593 |
-+++ b/ipc/kdbus/bus.c |
8594 |
-@@ -0,0 +1,514 @@ |
8595 |
-+/* |
8596 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
8597 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
8598 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
8599 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
8600 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
8601 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
8602 |
-+ * |
8603 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
8604 |
-+ * the terms of the GNU Lesser General Public License as published by the |
8605 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
8606 |
-+ * your option) any later version. |
8607 |
-+ */ |
8608 |
-+ |
8609 |
-+#include <linux/fs.h> |
8610 |
-+#include <linux/hashtable.h> |
8611 |
-+#include <linux/init.h> |
8612 |
-+#include <linux/module.h> |
8613 |
-+#include <linux/random.h> |
8614 |
-+#include <linux/sched.h> |
8615 |
-+#include <linux/sizes.h> |
8616 |
-+#include <linux/slab.h> |
8617 |
-+#include <linux/uaccess.h> |
8618 |
-+#include <linux/uio.h> |
8619 |
-+ |
8620 |
-+#include "bus.h" |
8621 |
-+#include "notify.h" |
8622 |
-+#include "connection.h" |
8623 |
-+#include "domain.h" |
8624 |
-+#include "endpoint.h" |
8625 |
-+#include "handle.h" |
8626 |
-+#include "item.h" |
8627 |
-+#include "match.h" |
8628 |
-+#include "message.h" |
8629 |
-+#include "metadata.h" |
8630 |
-+#include "names.h" |
8631 |
-+#include "policy.h" |
8632 |
-+#include "util.h" |
8633 |
-+ |
8634 |
-+static void kdbus_bus_free(struct kdbus_node *node) |
8635 |
-+{ |
8636 |
-+ struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node); |
8637 |
-+ |
8638 |
-+ WARN_ON(!list_empty(&bus->monitors_list)); |
8639 |
-+ WARN_ON(!hash_empty(bus->conn_hash)); |
8640 |
-+ |
8641 |
-+ kdbus_notify_free(bus); |
8642 |
-+ |
8643 |
-+ kdbus_user_unref(bus->creator); |
8644 |
-+ kdbus_name_registry_free(bus->name_registry); |
8645 |
-+ kdbus_domain_unref(bus->domain); |
8646 |
-+ kdbus_policy_db_clear(&bus->policy_db); |
8647 |
-+ kdbus_meta_proc_unref(bus->creator_meta); |
8648 |
-+ kfree(bus); |
8649 |
-+} |
8650 |
-+ |
8651 |
-+static void kdbus_bus_release(struct kdbus_node *node, bool was_active) |
8652 |
-+{ |
8653 |
-+ struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node); |
8654 |
-+ |
8655 |
-+ if (was_active) |
8656 |
-+ atomic_dec(&bus->creator->buses); |
8657 |
-+} |
8658 |
-+ |
8659 |
-+static struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain, |
8660 |
-+ const char *name, |
8661 |
-+ struct kdbus_bloom_parameter *bloom, |
8662 |
-+ const u64 *pattach_owner, |
8663 |
-+ u64 flags, kuid_t uid, kgid_t gid) |
8664 |
-+{ |
8665 |
-+ struct kdbus_bus *b; |
8666 |
-+ u64 attach_owner; |
8667 |
-+ int ret; |
8668 |
-+ |
8669 |
-+ if (bloom->size < 8 || bloom->size > KDBUS_BUS_BLOOM_MAX_SIZE || |
8670 |
-+ !KDBUS_IS_ALIGNED8(bloom->size) || bloom->n_hash < 1) |
8671 |
-+ return ERR_PTR(-EINVAL); |
8672 |
-+ |
8673 |
-+ ret = kdbus_sanitize_attach_flags(pattach_owner ? *pattach_owner : 0, |
8674 |
-+ &attach_owner); |
8675 |
-+ if (ret < 0) |
8676 |
-+ return ERR_PTR(ret); |
8677 |
-+ |
8678 |
-+ ret = kdbus_verify_uid_prefix(name, domain->user_namespace, uid); |
8679 |
-+ if (ret < 0) |
8680 |
-+ return ERR_PTR(ret); |
8681 |
-+ |
8682 |
-+ b = kzalloc(sizeof(*b), GFP_KERNEL); |
8683 |
-+ if (!b) |
8684 |
-+ return ERR_PTR(-ENOMEM); |
8685 |
-+ |
8686 |
-+ kdbus_node_init(&b->node, KDBUS_NODE_BUS); |
8687 |
-+ |
8688 |
-+ b->node.free_cb = kdbus_bus_free; |
8689 |
-+ b->node.release_cb = kdbus_bus_release; |
8690 |
-+ b->node.uid = uid; |
8691 |
-+ b->node.gid = gid; |
8692 |
-+ b->node.mode = S_IRUSR | S_IXUSR; |
8693 |
-+ |
8694 |
-+ if (flags & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
8695 |
-+ b->node.mode |= S_IRGRP | S_IXGRP; |
8696 |
-+ if (flags & KDBUS_MAKE_ACCESS_WORLD) |
8697 |
-+ b->node.mode |= S_IROTH | S_IXOTH; |
8698 |
-+ |
8699 |
-+ b->id = atomic64_inc_return(&domain->last_id); |
8700 |
-+ b->bus_flags = flags; |
8701 |
-+ b->attach_flags_owner = attach_owner; |
8702 |
-+ generate_random_uuid(b->id128); |
8703 |
-+ b->bloom = *bloom; |
8704 |
-+ b->domain = kdbus_domain_ref(domain); |
8705 |
-+ |
8706 |
-+ kdbus_policy_db_init(&b->policy_db); |
8707 |
-+ |
8708 |
-+ init_rwsem(&b->conn_rwlock); |
8709 |
-+ hash_init(b->conn_hash); |
8710 |
-+ INIT_LIST_HEAD(&b->monitors_list); |
8711 |
-+ |
8712 |
-+ INIT_LIST_HEAD(&b->notify_list); |
8713 |
-+ spin_lock_init(&b->notify_lock); |
8714 |
-+ mutex_init(&b->notify_flush_lock); |
8715 |
-+ |
8716 |
-+ ret = kdbus_node_link(&b->node, &domain->node, name); |
8717 |
-+ if (ret < 0) |
8718 |
-+ goto exit_unref; |
8719 |
-+ |
8720 |
-+ /* cache the metadata/credentials of the creator */ |
8721 |
-+ b->creator_meta = kdbus_meta_proc_new(); |
8722 |
-+ if (IS_ERR(b->creator_meta)) { |
8723 |
-+ ret = PTR_ERR(b->creator_meta); |
8724 |
-+ b->creator_meta = NULL; |
8725 |
-+ goto exit_unref; |
8726 |
-+ } |
8727 |
-+ |
8728 |
-+ ret = kdbus_meta_proc_collect(b->creator_meta, |
8729 |
-+ KDBUS_ATTACH_CREDS | |
8730 |
-+ KDBUS_ATTACH_PIDS | |
8731 |
-+ KDBUS_ATTACH_AUXGROUPS | |
8732 |
-+ KDBUS_ATTACH_TID_COMM | |
8733 |
-+ KDBUS_ATTACH_PID_COMM | |
8734 |
-+ KDBUS_ATTACH_EXE | |
8735 |
-+ KDBUS_ATTACH_CMDLINE | |
8736 |
-+ KDBUS_ATTACH_CGROUP | |
8737 |
-+ KDBUS_ATTACH_CAPS | |
8738 |
-+ KDBUS_ATTACH_SECLABEL | |
8739 |
-+ KDBUS_ATTACH_AUDIT); |
8740 |
-+ if (ret < 0) |
8741 |
-+ goto exit_unref; |
8742 |
-+ |
8743 |
-+ b->name_registry = kdbus_name_registry_new(); |
8744 |
-+ if (IS_ERR(b->name_registry)) { |
8745 |
-+ ret = PTR_ERR(b->name_registry); |
8746 |
-+ b->name_registry = NULL; |
8747 |
-+ goto exit_unref; |
8748 |
-+ } |
8749 |
-+ |
8750 |
-+ /* |
8751 |
-+ * Bus-limits of the creator are accounted on its real UID, just like |
8752 |
-+ * all other per-user limits. |
8753 |
-+ */ |
8754 |
-+ b->creator = kdbus_user_lookup(domain, current_uid()); |
8755 |
-+ if (IS_ERR(b->creator)) { |
8756 |
-+ ret = PTR_ERR(b->creator); |
8757 |
-+ b->creator = NULL; |
8758 |
-+ goto exit_unref; |
8759 |
-+ } |
8760 |
-+ |
8761 |
-+ return b; |
8762 |
-+ |
8763 |
-+exit_unref: |
8764 |
-+ kdbus_node_deactivate(&b->node); |
8765 |
-+ kdbus_node_unref(&b->node); |
8766 |
-+ return ERR_PTR(ret); |
8767 |
-+} |
8768 |
-+ |
8769 |
-+/** |
8770 |
-+ * kdbus_bus_ref() - increase the reference counter of a kdbus_bus |
8771 |
-+ * @bus: The bus to reference |
8772 |
-+ * |
8773 |
-+ * Every user of a bus, except for its creator, must add a reference to the |
8774 |
-+ * kdbus_bus using this function. |
8775 |
-+ * |
8776 |
-+ * Return: the bus itself |
8777 |
-+ */ |
8778 |
-+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus) |
8779 |
-+{ |
8780 |
-+ if (bus) |
8781 |
-+ kdbus_node_ref(&bus->node); |
8782 |
-+ return bus; |
8783 |
-+} |
8784 |
-+ |
8785 |
-+/** |
8786 |
-+ * kdbus_bus_unref() - decrease the reference counter of a kdbus_bus |
8787 |
-+ * @bus: The bus to unref |
8788 |
-+ * |
8789 |
-+ * Release a reference. If the reference count drops to 0, the bus will be |
8790 |
-+ * freed. |
8791 |
-+ * |
8792 |
-+ * Return: NULL |
8793 |
-+ */ |
8794 |
-+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus) |
8795 |
-+{ |
8796 |
-+ if (bus) |
8797 |
-+ kdbus_node_unref(&bus->node); |
8798 |
-+ return NULL; |
8799 |
-+} |
8800 |
-+ |
8801 |
-+/** |
8802 |
-+ * kdbus_bus_find_conn_by_id() - find a connection with a given id |
8803 |
-+ * @bus: The bus to look for the connection |
8804 |
-+ * @id: The 64-bit connection id |
8805 |
-+ * |
8806 |
-+ * Looks up a connection with a given id. The returned connection |
8807 |
-+ * is ref'ed, and needs to be unref'ed by the user. Returns NULL if |
8808 |
-+ * the connection can't be found. |
8809 |
-+ */ |
8810 |
-+struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id) |
8811 |
-+{ |
8812 |
-+ struct kdbus_conn *conn, *found = NULL; |
8813 |
-+ |
8814 |
-+ down_read(&bus->conn_rwlock); |
8815 |
-+ hash_for_each_possible(bus->conn_hash, conn, hentry, id) |
8816 |
-+ if (conn->id == id) { |
8817 |
-+ found = kdbus_conn_ref(conn); |
8818 |
-+ break; |
8819 |
-+ } |
8820 |
-+ up_read(&bus->conn_rwlock); |
8821 |
-+ |
8822 |
-+ return found; |
8823 |
-+} |
8824 |
-+ |
8825 |
-+/** |
8826 |
-+ * kdbus_bus_broadcast() - send a message to all subscribed connections |
8827 |
-+ * @bus: The bus the connections are connected to |
8828 |
-+ * @conn_src: The source connection, may be %NULL for kernel notifications |
8829 |
-+ * @staging: Staging object containing the message to send |
8830 |
-+ * |
8831 |
-+ * Send message to all connections that are currently active on the bus. |
8832 |
-+ * Connections must still have matches installed in order to let the message |
8833 |
-+ * pass. |
8834 |
-+ * |
8835 |
-+ * The caller must hold the name-registry lock of @bus. |
8836 |
-+ */ |
8837 |
-+void kdbus_bus_broadcast(struct kdbus_bus *bus, |
8838 |
-+ struct kdbus_conn *conn_src, |
8839 |
-+ struct kdbus_staging *staging) |
8840 |
-+{ |
8841 |
-+ struct kdbus_conn *conn_dst; |
8842 |
-+ unsigned int i; |
8843 |
-+ int ret; |
8844 |
-+ |
8845 |
-+ lockdep_assert_held(&bus->name_registry->rwlock); |
8846 |
-+ |
8847 |
-+ /* |
8848 |
-+ * Make sure broadcast are queued on monitors before we send it out to |
8849 |
-+ * anyone else. Otherwise, connections might react to broadcasts before |
8850 |
-+ * the monitor gets the broadcast queued. In the worst case, the |
8851 |
-+ * monitor sees a reaction to the broadcast before the broadcast itself. |
8852 |
-+ * We don't give ordering guarantees across connections (and monitors |
8853 |
-+ * can re-construct order via sequence numbers), but we should at least |
8854 |
-+ * try to avoid re-ordering for monitors. |
8855 |
-+ */ |
8856 |
-+ kdbus_bus_eavesdrop(bus, conn_src, staging); |
8857 |
-+ |
8858 |
-+ down_read(&bus->conn_rwlock); |
8859 |
-+ hash_for_each(bus->conn_hash, i, conn_dst, hentry) { |
8860 |
-+ if (!kdbus_conn_is_ordinary(conn_dst)) |
8861 |
-+ continue; |
8862 |
-+ |
8863 |
-+ /* |
8864 |
-+ * Check if there is a match for the kmsg object in |
8865 |
-+ * the destination connection match db |
8866 |
-+ */ |
8867 |
-+ if (!kdbus_match_db_match_msg(conn_dst->match_db, conn_src, |
8868 |
-+ staging)) |
8869 |
-+ continue; |
8870 |
-+ |
8871 |
-+ if (conn_src) { |
8872 |
-+ /* |
8873 |
-+ * Anyone can send broadcasts, as they have no |
8874 |
-+ * destination. But a receiver needs TALK access to |
8875 |
-+ * the sender in order to receive broadcasts. |
8876 |
-+ */ |
8877 |
-+ if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src)) |
8878 |
-+ continue; |
8879 |
-+ } else { |
8880 |
-+ /* |
8881 |
-+ * Check if there is a policy db that prevents the |
8882 |
-+ * destination connection from receiving this kernel |
8883 |
-+ * notification |
8884 |
-+ */ |
8885 |
-+ if (!kdbus_conn_policy_see_notification(conn_dst, NULL, |
8886 |
-+ staging->msg)) |
8887 |
-+ continue; |
8888 |
-+ } |
8889 |
-+ |
8890 |
-+ ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging, |
8891 |
-+ NULL, NULL); |
8892 |
-+ if (ret < 0) |
8893 |
-+ kdbus_conn_lost_message(conn_dst); |
8894 |
-+ } |
8895 |
-+ up_read(&bus->conn_rwlock); |
8896 |
-+} |
8897 |
-+ |
8898 |
-+/** |
8899 |
-+ * kdbus_bus_eavesdrop() - send a message to all subscribed monitors |
8900 |
-+ * @bus: The bus the monitors are connected to |
8901 |
-+ * @conn_src: The source connection, may be %NULL for kernel notifications |
8902 |
-+ * @staging: Staging object containing the message to send |
8903 |
-+ * |
8904 |
-+ * Send message to all monitors that are currently active on the bus. Monitors |
8905 |
-+ * must still have matches installed in order to let the message pass. |
8906 |
-+ * |
8907 |
-+ * The caller must hold the name-registry lock of @bus. |
8908 |
-+ */ |
8909 |
-+void kdbus_bus_eavesdrop(struct kdbus_bus *bus, |
8910 |
-+ struct kdbus_conn *conn_src, |
8911 |
-+ struct kdbus_staging *staging) |
8912 |
-+{ |
8913 |
-+ struct kdbus_conn *conn_dst; |
8914 |
-+ int ret; |
8915 |
-+ |
8916 |
-+ /* |
8917 |
-+ * Monitor connections get all messages; ignore possible errors |
8918 |
-+ * when sending messages to monitor connections. |
8919 |
-+ */ |
8920 |
-+ |
8921 |
-+ lockdep_assert_held(&bus->name_registry->rwlock); |
8922 |
-+ |
8923 |
-+ down_read(&bus->conn_rwlock); |
8924 |
-+ list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) { |
8925 |
-+ ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging, |
8926 |
-+ NULL, NULL); |
8927 |
-+ if (ret < 0) |
8928 |
-+ kdbus_conn_lost_message(conn_dst); |
8929 |
-+ } |
8930 |
-+ up_read(&bus->conn_rwlock); |
8931 |
-+} |
8932 |
-+ |
8933 |
-+/** |
8934 |
-+ * kdbus_cmd_bus_make() - handle KDBUS_CMD_BUS_MAKE |
8935 |
-+ * @domain: domain to operate on |
8936 |
-+ * @argp: command payload |
8937 |
-+ * |
8938 |
-+ * Return: NULL or newly created bus on success, ERR_PTR on failure. |
8939 |
-+ */ |
8940 |
-+struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, |
8941 |
-+ void __user *argp) |
8942 |
-+{ |
8943 |
-+ struct kdbus_bus *bus = NULL; |
8944 |
-+ struct kdbus_cmd *cmd; |
8945 |
-+ struct kdbus_ep *ep = NULL; |
8946 |
-+ int ret; |
8947 |
-+ |
8948 |
-+ struct kdbus_arg argv[] = { |
8949 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
8950 |
-+ { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, |
8951 |
-+ { .type = KDBUS_ITEM_BLOOM_PARAMETER, .mandatory = true }, |
8952 |
-+ { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND }, |
8953 |
-+ }; |
8954 |
-+ struct kdbus_args args = { |
8955 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
8956 |
-+ KDBUS_MAKE_ACCESS_GROUP | |
8957 |
-+ KDBUS_MAKE_ACCESS_WORLD, |
8958 |
-+ .argv = argv, |
8959 |
-+ .argc = ARRAY_SIZE(argv), |
8960 |
-+ }; |
8961 |
-+ |
8962 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
8963 |
-+ if (ret < 0) |
8964 |
-+ return ERR_PTR(ret); |
8965 |
-+ if (ret > 0) |
8966 |
-+ return NULL; |
8967 |
-+ |
8968 |
-+ bus = kdbus_bus_new(domain, |
8969 |
-+ argv[1].item->str, &argv[2].item->bloom_parameter, |
8970 |
-+ argv[3].item ? argv[3].item->data64 : NULL, |
8971 |
-+ cmd->flags, current_euid(), current_egid()); |
8972 |
-+ if (IS_ERR(bus)) { |
8973 |
-+ ret = PTR_ERR(bus); |
8974 |
-+ bus = NULL; |
8975 |
-+ goto exit; |
8976 |
-+ } |
8977 |
-+ |
8978 |
-+ if (atomic_inc_return(&bus->creator->buses) > KDBUS_USER_MAX_BUSES) { |
8979 |
-+ atomic_dec(&bus->creator->buses); |
8980 |
-+ ret = -EMFILE; |
8981 |
-+ goto exit; |
8982 |
-+ } |
8983 |
-+ |
8984 |
-+ if (!kdbus_node_activate(&bus->node)) { |
8985 |
-+ atomic_dec(&bus->creator->buses); |
8986 |
-+ ret = -ESHUTDOWN; |
8987 |
-+ goto exit; |
8988 |
-+ } |
8989 |
-+ |
8990 |
-+ ep = kdbus_ep_new(bus, "bus", cmd->flags, bus->node.uid, bus->node.gid, |
8991 |
-+ false); |
8992 |
-+ if (IS_ERR(ep)) { |
8993 |
-+ ret = PTR_ERR(ep); |
8994 |
-+ ep = NULL; |
8995 |
-+ goto exit; |
8996 |
-+ } |
8997 |
-+ |
8998 |
-+ if (!kdbus_node_activate(&ep->node)) { |
8999 |
-+ ret = -ESHUTDOWN; |
9000 |
-+ goto exit; |
9001 |
-+ } |
9002 |
-+ |
9003 |
-+ /* |
9004 |
-+ * Drop our own reference, effectively causing the endpoint to be |
9005 |
-+ * deactivated and released when the parent bus is. |
9006 |
-+ */ |
9007 |
-+ ep = kdbus_ep_unref(ep); |
9008 |
-+ |
9009 |
-+exit: |
9010 |
-+ ret = kdbus_args_clear(&args, ret); |
9011 |
-+ if (ret < 0) { |
9012 |
-+ if (ep) { |
9013 |
-+ kdbus_node_deactivate(&ep->node); |
9014 |
-+ kdbus_ep_unref(ep); |
9015 |
-+ } |
9016 |
-+ if (bus) { |
9017 |
-+ kdbus_node_deactivate(&bus->node); |
9018 |
-+ kdbus_bus_unref(bus); |
9019 |
-+ } |
9020 |
-+ return ERR_PTR(ret); |
9021 |
-+ } |
9022 |
-+ return bus; |
9023 |
-+} |
9024 |
-+ |
9025 |
-+/** |
9026 |
-+ * kdbus_cmd_bus_creator_info() - handle KDBUS_CMD_BUS_CREATOR_INFO |
9027 |
-+ * @conn: connection to operate on |
9028 |
-+ * @argp: command payload |
9029 |
-+ * |
9030 |
-+ * Return: >=0 on success, negative error code on failure. |
9031 |
-+ */ |
9032 |
-+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp) |
9033 |
-+{ |
9034 |
-+ struct kdbus_cmd_info *cmd; |
9035 |
-+ struct kdbus_bus *bus = conn->ep->bus; |
9036 |
-+ struct kdbus_pool_slice *slice = NULL; |
9037 |
-+ struct kdbus_item *meta_items = NULL; |
9038 |
-+ struct kdbus_item_header item_hdr; |
9039 |
-+ struct kdbus_info info = {}; |
9040 |
-+ size_t meta_size, name_len, cnt = 0; |
9041 |
-+ struct kvec kvec[6]; |
9042 |
-+ u64 attach_flags, size = 0; |
9043 |
-+ int ret; |
9044 |
-+ |
9045 |
-+ struct kdbus_arg argv[] = { |
9046 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
9047 |
-+ }; |
9048 |
-+ struct kdbus_args args = { |
9049 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
9050 |
-+ .argv = argv, |
9051 |
-+ .argc = ARRAY_SIZE(argv), |
9052 |
-+ }; |
9053 |
-+ |
9054 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
9055 |
-+ if (ret != 0) |
9056 |
-+ return ret; |
9057 |
-+ |
9058 |
-+ ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags); |
9059 |
-+ if (ret < 0) |
9060 |
-+ goto exit; |
9061 |
-+ |
9062 |
-+ attach_flags &= bus->attach_flags_owner; |
9063 |
-+ |
9064 |
-+ ret = kdbus_meta_emit(bus->creator_meta, NULL, NULL, conn, |
9065 |
-+ attach_flags, &meta_items, &meta_size); |
9066 |
-+ if (ret < 0) |
9067 |
-+ goto exit; |
9068 |
-+ |
9069 |
-+ name_len = strlen(bus->node.name) + 1; |
9070 |
-+ info.id = bus->id; |
9071 |
-+ info.flags = bus->bus_flags; |
9072 |
-+ item_hdr.type = KDBUS_ITEM_MAKE_NAME; |
9073 |
-+ item_hdr.size = KDBUS_ITEM_HEADER_SIZE + name_len; |
9074 |
-+ |
9075 |
-+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size); |
9076 |
-+ kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &size); |
9077 |
-+ kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &size); |
9078 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &size); |
9079 |
-+ if (meta_size > 0) { |
9080 |
-+ kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size); |
9081 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &size); |
9082 |
-+ } |
9083 |
-+ |
9084 |
-+ info.size = size; |
9085 |
-+ |
9086 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
9087 |
-+ if (IS_ERR(slice)) { |
9088 |
-+ ret = PTR_ERR(slice); |
9089 |
-+ slice = NULL; |
9090 |
-+ goto exit; |
9091 |
-+ } |
9092 |
-+ |
9093 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, size); |
9094 |
-+ if (ret < 0) |
9095 |
-+ goto exit; |
9096 |
-+ |
9097 |
-+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size); |
9098 |
-+ |
9099 |
-+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
9100 |
-+ kdbus_member_set_user(&cmd->info_size, argp, |
9101 |
-+ typeof(*cmd), info_size)) |
9102 |
-+ ret = -EFAULT; |
9103 |
-+ |
9104 |
-+exit: |
9105 |
-+ kdbus_pool_slice_release(slice); |
9106 |
-+ kfree(meta_items); |
9107 |
-+ return kdbus_args_clear(&args, ret); |
9108 |
-+} |
9109 |
-diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h |
9110 |
-new file mode 100644 |
9111 |
-index 0000000..8c2acae |
9112 |
---- /dev/null |
9113 |
-+++ b/ipc/kdbus/bus.h |
9114 |
-@@ -0,0 +1,101 @@ |
9115 |
-+/* |
9116 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
9117 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
9118 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
9119 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
9120 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
9121 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
9122 |
-+ * |
9123 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
9124 |
-+ * the terms of the GNU Lesser General Public License as published by the |
9125 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
9126 |
-+ * your option) any later version. |
9127 |
-+ */ |
9128 |
-+ |
9129 |
-+#ifndef __KDBUS_BUS_H |
9130 |
-+#define __KDBUS_BUS_H |
9131 |
-+ |
9132 |
-+#include <linux/hashtable.h> |
9133 |
-+#include <linux/list.h> |
9134 |
-+#include <linux/mutex.h> |
9135 |
-+#include <linux/rwsem.h> |
9136 |
-+#include <linux/spinlock.h> |
9137 |
-+#include <uapi/linux/kdbus.h> |
9138 |
-+ |
9139 |
-+#include "metadata.h" |
9140 |
-+#include "names.h" |
9141 |
-+#include "node.h" |
9142 |
-+#include "policy.h" |
9143 |
-+ |
9144 |
-+struct kdbus_conn; |
9145 |
-+struct kdbus_domain; |
9146 |
-+struct kdbus_staging; |
9147 |
-+struct kdbus_user; |
9148 |
-+ |
9149 |
-+/** |
9150 |
-+ * struct kdbus_bus - bus in a domain |
9151 |
-+ * @node: kdbus_node |
9152 |
-+ * @id: ID of this bus in the domain |
9153 |
-+ * @bus_flags: Simple pass-through flags from userspace to userspace |
9154 |
-+ * @attach_flags_owner: KDBUS_ATTACH_* flags of bus creator that other |
9155 |
-+ * connections can see or query |
9156 |
-+ * @id128: Unique random 128 bit ID of this bus |
9157 |
-+ * @bloom: Bloom parameters |
9158 |
-+ * @domain: Domain of this bus |
9159 |
-+ * @creator: Creator of the bus |
9160 |
-+ * @creator_meta: Meta information about the bus creator |
9161 |
-+ * @last_message_id: Last used message id |
9162 |
-+ * @policy_db: Policy database for this bus |
9163 |
-+ * @name_registry: Name registry of this bus |
9164 |
-+ * @conn_rwlock: Read/Write lock for all lists of child connections |
9165 |
-+ * @conn_hash: Map of connection IDs |
9166 |
-+ * @monitors_list: Connections that monitor this bus |
9167 |
-+ * @notify_list: List of pending kernel-generated messages |
9168 |
-+ * @notify_lock: Notification list lock |
9169 |
-+ * @notify_flush_lock: Notification flushing lock |
9170 |
-+ */ |
9171 |
-+struct kdbus_bus { |
9172 |
-+ struct kdbus_node node; |
9173 |
-+ |
9174 |
-+ /* static */ |
9175 |
-+ u64 id; |
9176 |
-+ u64 bus_flags; |
9177 |
-+ u64 attach_flags_owner; |
9178 |
-+ u8 id128[16]; |
9179 |
-+ struct kdbus_bloom_parameter bloom; |
9180 |
-+ struct kdbus_domain *domain; |
9181 |
-+ struct kdbus_user *creator; |
9182 |
-+ struct kdbus_meta_proc *creator_meta; |
9183 |
-+ |
9184 |
-+ /* protected by own locks */ |
9185 |
-+ atomic64_t last_message_id; |
9186 |
-+ struct kdbus_policy_db policy_db; |
9187 |
-+ struct kdbus_name_registry *name_registry; |
9188 |
-+ |
9189 |
-+ /* protected by conn_rwlock */ |
9190 |
-+ struct rw_semaphore conn_rwlock; |
9191 |
-+ DECLARE_HASHTABLE(conn_hash, 8); |
9192 |
-+ struct list_head monitors_list; |
9193 |
-+ |
9194 |
-+ /* protected by notify_lock */ |
9195 |
-+ struct list_head notify_list; |
9196 |
-+ spinlock_t notify_lock; |
9197 |
-+ struct mutex notify_flush_lock; |
9198 |
-+}; |
9199 |
-+ |
9200 |
-+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus); |
9201 |
-+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus); |
9202 |
-+ |
9203 |
-+struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id); |
9204 |
-+void kdbus_bus_broadcast(struct kdbus_bus *bus, |
9205 |
-+ struct kdbus_conn *conn_src, |
9206 |
-+ struct kdbus_staging *staging); |
9207 |
-+void kdbus_bus_eavesdrop(struct kdbus_bus *bus, |
9208 |
-+ struct kdbus_conn *conn_src, |
9209 |
-+ struct kdbus_staging *staging); |
9210 |
-+ |
9211 |
-+struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, |
9212 |
-+ void __user *argp); |
9213 |
-+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp); |
9214 |
-+ |
9215 |
-+#endif |
9216 |
-diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c |
9217 |
-new file mode 100644 |
9218 |
-index 0000000..ef63d65 |
9219 |
---- /dev/null |
9220 |
-+++ b/ipc/kdbus/connection.c |
9221 |
-@@ -0,0 +1,2227 @@ |
9222 |
-+/* |
9223 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
9224 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
9225 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
9226 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
9227 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
9228 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
9229 |
-+ * |
9230 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
9231 |
-+ * the terms of the GNU Lesser General Public License as published by the |
9232 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
9233 |
-+ * your option) any later version. |
9234 |
-+ */ |
9235 |
-+ |
9236 |
-+#include <linux/audit.h> |
9237 |
-+#include <linux/file.h> |
9238 |
-+#include <linux/fs.h> |
9239 |
-+#include <linux/fs_struct.h> |
9240 |
-+#include <linux/hashtable.h> |
9241 |
-+#include <linux/idr.h> |
9242 |
-+#include <linux/init.h> |
9243 |
-+#include <linux/math64.h> |
9244 |
-+#include <linux/mm.h> |
9245 |
-+#include <linux/module.h> |
9246 |
-+#include <linux/mutex.h> |
9247 |
-+#include <linux/path.h> |
9248 |
-+#include <linux/poll.h> |
9249 |
-+#include <linux/sched.h> |
9250 |
-+#include <linux/shmem_fs.h> |
9251 |
-+#include <linux/sizes.h> |
9252 |
-+#include <linux/slab.h> |
9253 |
-+#include <linux/syscalls.h> |
9254 |
-+#include <linux/uio.h> |
9255 |
-+ |
9256 |
-+#include "bus.h" |
9257 |
-+#include "connection.h" |
9258 |
-+#include "endpoint.h" |
9259 |
-+#include "handle.h" |
9260 |
-+#include "match.h" |
9261 |
-+#include "message.h" |
9262 |
-+#include "metadata.h" |
9263 |
-+#include "names.h" |
9264 |
-+#include "domain.h" |
9265 |
-+#include "item.h" |
9266 |
-+#include "notify.h" |
9267 |
-+#include "policy.h" |
9268 |
-+#include "pool.h" |
9269 |
-+#include "reply.h" |
9270 |
-+#include "util.h" |
9271 |
-+#include "queue.h" |
9272 |
-+ |
9273 |
-+#define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2) |
9274 |
-+#define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1) |
9275 |
-+ |
9276 |
-+static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, |
9277 |
-+ struct file *file, |
9278 |
-+ struct kdbus_cmd_hello *hello, |
9279 |
-+ const char *name, |
9280 |
-+ const struct kdbus_creds *creds, |
9281 |
-+ const struct kdbus_pids *pids, |
9282 |
-+ const char *seclabel, |
9283 |
-+ const char *conn_description) |
9284 |
-+{ |
9285 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9286 |
-+ static struct lock_class_key __key; |
9287 |
-+#endif |
9288 |
-+ struct kdbus_pool_slice *slice = NULL; |
9289 |
-+ struct kdbus_bus *bus = ep->bus; |
9290 |
-+ struct kdbus_conn *conn; |
9291 |
-+ u64 attach_flags_send; |
9292 |
-+ u64 attach_flags_recv; |
9293 |
-+ u64 items_size = 0; |
9294 |
-+ bool is_policy_holder; |
9295 |
-+ bool is_activator; |
9296 |
-+ bool is_monitor; |
9297 |
-+ bool privileged; |
9298 |
-+ bool owner; |
9299 |
-+ struct kvec kvec; |
9300 |
-+ int ret; |
9301 |
-+ |
9302 |
-+ struct { |
9303 |
-+ u64 size; |
9304 |
-+ u64 type; |
9305 |
-+ struct kdbus_bloom_parameter bloom; |
9306 |
-+ } bloom_item; |
9307 |
-+ |
9308 |
-+ privileged = kdbus_ep_is_privileged(ep, file); |
9309 |
-+ owner = kdbus_ep_is_owner(ep, file); |
9310 |
-+ |
9311 |
-+ is_monitor = hello->flags & KDBUS_HELLO_MONITOR; |
9312 |
-+ is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR; |
9313 |
-+ is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER; |
9314 |
-+ |
9315 |
-+ if (!hello->pool_size || !IS_ALIGNED(hello->pool_size, PAGE_SIZE)) |
9316 |
-+ return ERR_PTR(-EINVAL); |
9317 |
-+ if (is_monitor + is_activator + is_policy_holder > 1) |
9318 |
-+ return ERR_PTR(-EINVAL); |
9319 |
-+ if (name && !is_activator && !is_policy_holder) |
9320 |
-+ return ERR_PTR(-EINVAL); |
9321 |
-+ if (!name && (is_activator || is_policy_holder)) |
9322 |
-+ return ERR_PTR(-EINVAL); |
9323 |
-+ if (name && !kdbus_name_is_valid(name, true)) |
9324 |
-+ return ERR_PTR(-EINVAL); |
9325 |
-+ if (is_monitor && ep->user) |
9326 |
-+ return ERR_PTR(-EOPNOTSUPP); |
9327 |
-+ if (!owner && (is_activator || is_policy_holder || is_monitor)) |
9328 |
-+ return ERR_PTR(-EPERM); |
9329 |
-+ if (!owner && (creds || pids || seclabel)) |
9330 |
-+ return ERR_PTR(-EPERM); |
9331 |
-+ |
9332 |
-+ ret = kdbus_sanitize_attach_flags(hello->attach_flags_send, |
9333 |
-+ &attach_flags_send); |
9334 |
-+ if (ret < 0) |
9335 |
-+ return ERR_PTR(ret); |
9336 |
-+ |
9337 |
-+ ret = kdbus_sanitize_attach_flags(hello->attach_flags_recv, |
9338 |
-+ &attach_flags_recv); |
9339 |
-+ if (ret < 0) |
9340 |
-+ return ERR_PTR(ret); |
9341 |
-+ |
9342 |
-+ conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
9343 |
-+ if (!conn) |
9344 |
-+ return ERR_PTR(-ENOMEM); |
9345 |
-+ |
9346 |
-+ kref_init(&conn->kref); |
9347 |
-+ atomic_set(&conn->active, KDBUS_CONN_ACTIVE_NEW); |
9348 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9349 |
-+ lockdep_init_map(&conn->dep_map, "s_active", &__key, 0); |
9350 |
-+#endif |
9351 |
-+ mutex_init(&conn->lock); |
9352 |
-+ INIT_LIST_HEAD(&conn->names_list); |
9353 |
-+ INIT_LIST_HEAD(&conn->reply_list); |
9354 |
-+ atomic_set(&conn->request_count, 0); |
9355 |
-+ atomic_set(&conn->lost_count, 0); |
9356 |
-+ INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work); |
9357 |
-+ conn->cred = get_cred(file->f_cred); |
9358 |
-+ conn->pid = get_pid(task_pid(current)); |
9359 |
-+ get_fs_root(current->fs, &conn->root_path); |
9360 |
-+ init_waitqueue_head(&conn->wait); |
9361 |
-+ kdbus_queue_init(&conn->queue); |
9362 |
-+ conn->privileged = privileged; |
9363 |
-+ conn->owner = owner; |
9364 |
-+ conn->ep = kdbus_ep_ref(ep); |
9365 |
-+ conn->id = atomic64_inc_return(&bus->domain->last_id); |
9366 |
-+ conn->flags = hello->flags; |
9367 |
-+ atomic64_set(&conn->attach_flags_send, attach_flags_send); |
9368 |
-+ atomic64_set(&conn->attach_flags_recv, attach_flags_recv); |
9369 |
-+ INIT_LIST_HEAD(&conn->monitor_entry); |
9370 |
-+ |
9371 |
-+ if (conn_description) { |
9372 |
-+ conn->description = kstrdup(conn_description, GFP_KERNEL); |
9373 |
-+ if (!conn->description) { |
9374 |
-+ ret = -ENOMEM; |
9375 |
-+ goto exit_unref; |
9376 |
-+ } |
9377 |
-+ } |
9378 |
-+ |
9379 |
-+ conn->pool = kdbus_pool_new(conn->description, hello->pool_size); |
9380 |
-+ if (IS_ERR(conn->pool)) { |
9381 |
-+ ret = PTR_ERR(conn->pool); |
9382 |
-+ conn->pool = NULL; |
9383 |
-+ goto exit_unref; |
9384 |
-+ } |
9385 |
-+ |
9386 |
-+ conn->match_db = kdbus_match_db_new(); |
9387 |
-+ if (IS_ERR(conn->match_db)) { |
9388 |
-+ ret = PTR_ERR(conn->match_db); |
9389 |
-+ conn->match_db = NULL; |
9390 |
-+ goto exit_unref; |
9391 |
-+ } |
9392 |
-+ |
9393 |
-+ /* return properties of this connection to the caller */ |
9394 |
-+ hello->bus_flags = bus->bus_flags; |
9395 |
-+ hello->id = conn->id; |
9396 |
-+ |
9397 |
-+ BUILD_BUG_ON(sizeof(bus->id128) != sizeof(hello->id128)); |
9398 |
-+ memcpy(hello->id128, bus->id128, sizeof(hello->id128)); |
9399 |
-+ |
9400 |
-+ /* privileged processes can impersonate somebody else */ |
9401 |
-+ if (creds || pids || seclabel) { |
9402 |
-+ conn->meta_fake = kdbus_meta_fake_new(); |
9403 |
-+ if (IS_ERR(conn->meta_fake)) { |
9404 |
-+ ret = PTR_ERR(conn->meta_fake); |
9405 |
-+ conn->meta_fake = NULL; |
9406 |
-+ goto exit_unref; |
9407 |
-+ } |
9408 |
-+ |
9409 |
-+ ret = kdbus_meta_fake_collect(conn->meta_fake, |
9410 |
-+ creds, pids, seclabel); |
9411 |
-+ if (ret < 0) |
9412 |
-+ goto exit_unref; |
9413 |
-+ } else { |
9414 |
-+ conn->meta_proc = kdbus_meta_proc_new(); |
9415 |
-+ if (IS_ERR(conn->meta_proc)) { |
9416 |
-+ ret = PTR_ERR(conn->meta_proc); |
9417 |
-+ conn->meta_proc = NULL; |
9418 |
-+ goto exit_unref; |
9419 |
-+ } |
9420 |
-+ |
9421 |
-+ ret = kdbus_meta_proc_collect(conn->meta_proc, |
9422 |
-+ KDBUS_ATTACH_CREDS | |
9423 |
-+ KDBUS_ATTACH_PIDS | |
9424 |
-+ KDBUS_ATTACH_AUXGROUPS | |
9425 |
-+ KDBUS_ATTACH_TID_COMM | |
9426 |
-+ KDBUS_ATTACH_PID_COMM | |
9427 |
-+ KDBUS_ATTACH_EXE | |
9428 |
-+ KDBUS_ATTACH_CMDLINE | |
9429 |
-+ KDBUS_ATTACH_CGROUP | |
9430 |
-+ KDBUS_ATTACH_CAPS | |
9431 |
-+ KDBUS_ATTACH_SECLABEL | |
9432 |
-+ KDBUS_ATTACH_AUDIT); |
9433 |
-+ if (ret < 0) |
9434 |
-+ goto exit_unref; |
9435 |
-+ } |
9436 |
-+ |
9437 |
-+ /* |
9438 |
-+ * Account the connection against the current user (UID), or for |
9439 |
-+ * custom endpoints use the anonymous user assigned to the endpoint. |
9440 |
-+ * Note that limits are always accounted against the real UID, not |
9441 |
-+ * the effective UID (cred->user always points to the accounting of |
9442 |
-+ * cred->uid, not cred->euid). |
9443 |
-+ * In case the caller is privileged, we allow changing the accounting |
9444 |
-+ * to the faked user. |
9445 |
-+ */ |
9446 |
-+ if (ep->user) { |
9447 |
-+ conn->user = kdbus_user_ref(ep->user); |
9448 |
-+ } else { |
9449 |
-+ kuid_t uid; |
9450 |
-+ |
9451 |
-+ if (conn->meta_fake && uid_valid(conn->meta_fake->uid) && |
9452 |
-+ conn->privileged) |
9453 |
-+ uid = conn->meta_fake->uid; |
9454 |
-+ else |
9455 |
-+ uid = conn->cred->uid; |
9456 |
-+ |
9457 |
-+ conn->user = kdbus_user_lookup(ep->bus->domain, uid); |
9458 |
-+ if (IS_ERR(conn->user)) { |
9459 |
-+ ret = PTR_ERR(conn->user); |
9460 |
-+ conn->user = NULL; |
9461 |
-+ goto exit_unref; |
9462 |
-+ } |
9463 |
-+ } |
9464 |
-+ |
9465 |
-+ if (atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) { |
9466 |
-+ /* decremented by destructor as conn->user is valid */ |
9467 |
-+ ret = -EMFILE; |
9468 |
-+ goto exit_unref; |
9469 |
-+ } |
9470 |
-+ |
9471 |
-+ bloom_item.size = sizeof(bloom_item); |
9472 |
-+ bloom_item.type = KDBUS_ITEM_BLOOM_PARAMETER; |
9473 |
-+ bloom_item.bloom = bus->bloom; |
9474 |
-+ kdbus_kvec_set(&kvec, &bloom_item, bloom_item.size, &items_size); |
9475 |
-+ |
9476 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, items_size, false); |
9477 |
-+ if (IS_ERR(slice)) { |
9478 |
-+ ret = PTR_ERR(slice); |
9479 |
-+ slice = NULL; |
9480 |
-+ goto exit_unref; |
9481 |
-+ } |
9482 |
-+ |
9483 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, 0, &kvec, 1, items_size); |
9484 |
-+ if (ret < 0) |
9485 |
-+ goto exit_unref; |
9486 |
-+ |
9487 |
-+ kdbus_pool_slice_publish(slice, &hello->offset, &hello->items_size); |
9488 |
-+ kdbus_pool_slice_release(slice); |
9489 |
-+ |
9490 |
-+ return conn; |
9491 |
-+ |
9492 |
-+exit_unref: |
9493 |
-+ kdbus_pool_slice_release(slice); |
9494 |
-+ kdbus_conn_unref(conn); |
9495 |
-+ return ERR_PTR(ret); |
9496 |
-+} |
9497 |
-+ |
9498 |
-+static void __kdbus_conn_free(struct kref *kref) |
9499 |
-+{ |
9500 |
-+ struct kdbus_conn *conn = container_of(kref, struct kdbus_conn, kref); |
9501 |
-+ |
9502 |
-+ WARN_ON(kdbus_conn_active(conn)); |
9503 |
-+ WARN_ON(delayed_work_pending(&conn->work)); |
9504 |
-+ WARN_ON(!list_empty(&conn->queue.msg_list)); |
9505 |
-+ WARN_ON(!list_empty(&conn->names_list)); |
9506 |
-+ WARN_ON(!list_empty(&conn->reply_list)); |
9507 |
-+ |
9508 |
-+ if (conn->user) { |
9509 |
-+ atomic_dec(&conn->user->connections); |
9510 |
-+ kdbus_user_unref(conn->user); |
9511 |
-+ } |
9512 |
-+ |
9513 |
-+ kdbus_meta_fake_free(conn->meta_fake); |
9514 |
-+ kdbus_meta_proc_unref(conn->meta_proc); |
9515 |
-+ kdbus_match_db_free(conn->match_db); |
9516 |
-+ kdbus_pool_free(conn->pool); |
9517 |
-+ kdbus_ep_unref(conn->ep); |
9518 |
-+ path_put(&conn->root_path); |
9519 |
-+ put_pid(conn->pid); |
9520 |
-+ put_cred(conn->cred); |
9521 |
-+ kfree(conn->description); |
9522 |
-+ kfree(conn->quota); |
9523 |
-+ kfree(conn); |
9524 |
-+} |
9525 |
-+ |
9526 |
-+/** |
9527 |
-+ * kdbus_conn_ref() - take a connection reference |
9528 |
-+ * @conn: Connection, may be %NULL |
9529 |
-+ * |
9530 |
-+ * Return: the connection itself |
9531 |
-+ */ |
9532 |
-+struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn) |
9533 |
-+{ |
9534 |
-+ if (conn) |
9535 |
-+ kref_get(&conn->kref); |
9536 |
-+ return conn; |
9537 |
-+} |
9538 |
-+ |
9539 |
-+/** |
9540 |
-+ * kdbus_conn_unref() - drop a connection reference |
9541 |
-+ * @conn: Connection (may be NULL) |
9542 |
-+ * |
9543 |
-+ * When the last reference is dropped, the connection's internal structure |
9544 |
-+ * is freed. |
9545 |
-+ * |
9546 |
-+ * Return: NULL |
9547 |
-+ */ |
9548 |
-+struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn) |
9549 |
-+{ |
9550 |
-+ if (conn) |
9551 |
-+ kref_put(&conn->kref, __kdbus_conn_free); |
9552 |
-+ return NULL; |
9553 |
-+} |
9554 |
-+ |
9555 |
-+/** |
9556 |
-+ * kdbus_conn_active() - connection is not disconnected |
9557 |
-+ * @conn: Connection to check |
9558 |
-+ * |
9559 |
-+ * Return true if the connection was not disconnected, yet. Note that a |
9560 |
-+ * connection might be disconnected asynchronously, unless you hold the |
9561 |
-+ * connection lock. If that's not suitable for you, see kdbus_conn_acquire() to |
9562 |
-+ * suppress connection shutdown for a short period. |
9563 |
-+ * |
9564 |
-+ * Return: true if the connection is still active |
9565 |
-+ */ |
9566 |
-+bool kdbus_conn_active(const struct kdbus_conn *conn) |
9567 |
-+{ |
9568 |
-+ return atomic_read(&conn->active) >= 0; |
9569 |
-+} |
9570 |
-+ |
9571 |
-+/** |
9572 |
-+ * kdbus_conn_acquire() - acquire an active connection reference |
9573 |
-+ * @conn: Connection |
9574 |
-+ * |
9575 |
-+ * Users can close a connection via KDBUS_BYEBYE (or by destroying the |
9576 |
-+ * endpoint/bus/...) at any time. Whenever this happens, we should deny any |
9577 |
-+ * user-visible action on this connection and signal ECONNRESET instead. |
9578 |
-+ * To avoid testing for connection availability everytime you take the |
9579 |
-+ * connection-lock, you can acquire a connection for short periods. |
9580 |
-+ * |
9581 |
-+ * By calling kdbus_conn_acquire(), you gain an "active reference" to the |
9582 |
-+ * connection. You must also hold a regular reference at any time! As long as |
9583 |
-+ * you hold the active-ref, the connection will not be shut down. However, if |
9584 |
-+ * the connection was shut down, you can never acquire an active-ref again. |
9585 |
-+ * |
9586 |
-+ * kdbus_conn_disconnect() disables the connection and then waits for all active |
9587 |
-+ * references to be dropped. It will also wake up any pending operation. |
9588 |
-+ * However, you must not sleep for an indefinite period while holding an |
9589 |
-+ * active-reference. Otherwise, kdbus_conn_disconnect() might stall. If you need |
9590 |
-+ * to sleep for an indefinite period, either release the reference and try to |
9591 |
-+ * acquire it again after waking up, or make kdbus_conn_disconnect() wake up |
9592 |
-+ * your wait-queue. |
9593 |
-+ * |
9594 |
-+ * Return: 0 on success, negative error code on failure. |
9595 |
-+ */ |
9596 |
-+int kdbus_conn_acquire(struct kdbus_conn *conn) |
9597 |
-+{ |
9598 |
-+ if (!atomic_inc_unless_negative(&conn->active)) |
9599 |
-+ return -ECONNRESET; |
9600 |
-+ |
9601 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9602 |
-+ rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_); |
9603 |
-+#endif |
9604 |
-+ |
9605 |
-+ return 0; |
9606 |
-+} |
9607 |
-+ |
9608 |
-+/** |
9609 |
-+ * kdbus_conn_release() - release an active connection reference |
9610 |
-+ * @conn: Connection |
9611 |
-+ * |
9612 |
-+ * This releases an active reference that has been acquired via |
9613 |
-+ * kdbus_conn_acquire(). If the connection was already disabled and this is the |
9614 |
-+ * last active-ref that is dropped, the disconnect-waiter will be woken up and |
9615 |
-+ * properly close the connection. |
9616 |
-+ */ |
9617 |
-+void kdbus_conn_release(struct kdbus_conn *conn) |
9618 |
-+{ |
9619 |
-+ int v; |
9620 |
-+ |
9621 |
-+ if (!conn) |
9622 |
-+ return; |
9623 |
-+ |
9624 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9625 |
-+ rwsem_release(&conn->dep_map, 1, _RET_IP_); |
9626 |
-+#endif |
9627 |
-+ |
9628 |
-+ v = atomic_dec_return(&conn->active); |
9629 |
-+ if (v != KDBUS_CONN_ACTIVE_BIAS) |
9630 |
-+ return; |
9631 |
-+ |
9632 |
-+ wake_up_all(&conn->wait); |
9633 |
-+} |
9634 |
-+ |
9635 |
-+static int kdbus_conn_connect(struct kdbus_conn *conn, const char *name) |
9636 |
-+{ |
9637 |
-+ struct kdbus_ep *ep = conn->ep; |
9638 |
-+ struct kdbus_bus *bus = ep->bus; |
9639 |
-+ int ret; |
9640 |
-+ |
9641 |
-+ if (WARN_ON(atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_NEW)) |
9642 |
-+ return -EALREADY; |
9643 |
-+ |
9644 |
-+ /* make sure the ep-node is active while we add our connection */ |
9645 |
-+ if (!kdbus_node_acquire(&ep->node)) |
9646 |
-+ return -ESHUTDOWN; |
9647 |
-+ |
9648 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
9649 |
-+ mutex_lock(&ep->lock); |
9650 |
-+ down_write(&bus->conn_rwlock); |
9651 |
-+ |
9652 |
-+ /* link into monitor list */ |
9653 |
-+ if (kdbus_conn_is_monitor(conn)) |
9654 |
-+ list_add_tail(&conn->monitor_entry, &bus->monitors_list); |
9655 |
-+ |
9656 |
-+ /* link into bus and endpoint */ |
9657 |
-+ list_add_tail(&conn->ep_entry, &ep->conn_list); |
9658 |
-+ hash_add(bus->conn_hash, &conn->hentry, conn->id); |
9659 |
-+ |
9660 |
-+ /* enable lookups and acquire active ref */ |
9661 |
-+ atomic_set(&conn->active, 1); |
9662 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9663 |
-+ rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_); |
9664 |
-+#endif |
9665 |
-+ |
9666 |
-+ up_write(&bus->conn_rwlock); |
9667 |
-+ mutex_unlock(&ep->lock); |
9668 |
-+ |
9669 |
-+ kdbus_node_release(&ep->node); |
9670 |
-+ |
9671 |
-+ /* |
9672 |
-+ * Notify subscribers about the new active connection, unless it is |
9673 |
-+ * a monitor. Monitors are invisible on the bus, can't be addressed |
9674 |
-+ * directly, and won't cause any notifications. |
9675 |
-+ */ |
9676 |
-+ if (!kdbus_conn_is_monitor(conn)) { |
9677 |
-+ ret = kdbus_notify_id_change(bus, KDBUS_ITEM_ID_ADD, |
9678 |
-+ conn->id, conn->flags); |
9679 |
-+ if (ret < 0) |
9680 |
-+ goto exit_disconnect; |
9681 |
-+ } |
9682 |
-+ |
9683 |
-+ if (kdbus_conn_is_activator(conn)) { |
9684 |
-+ u64 flags = KDBUS_NAME_ACTIVATOR; |
9685 |
-+ |
9686 |
-+ if (WARN_ON(!name)) { |
9687 |
-+ ret = -EINVAL; |
9688 |
-+ goto exit_disconnect; |
9689 |
-+ } |
9690 |
-+ |
9691 |
-+ ret = kdbus_name_acquire(bus->name_registry, conn, name, |
9692 |
-+ flags, NULL); |
9693 |
-+ if (ret < 0) |
9694 |
-+ goto exit_disconnect; |
9695 |
-+ } |
9696 |
-+ |
9697 |
-+ kdbus_conn_release(conn); |
9698 |
-+ kdbus_notify_flush(bus); |
9699 |
-+ return 0; |
9700 |
-+ |
9701 |
-+exit_disconnect: |
9702 |
-+ kdbus_conn_release(conn); |
9703 |
-+ kdbus_conn_disconnect(conn, false); |
9704 |
-+ return ret; |
9705 |
-+} |
9706 |
-+ |
9707 |
-+/** |
9708 |
-+ * kdbus_conn_disconnect() - disconnect a connection |
9709 |
-+ * @conn: The connection to disconnect |
9710 |
-+ * @ensure_queue_empty: Flag to indicate if the call should fail in |
9711 |
-+ * case the connection's message list is not |
9712 |
-+ * empty |
9713 |
-+ * |
9714 |
-+ * If @ensure_msg_list_empty is true, and the connection has pending messages, |
9715 |
-+ * -EBUSY is returned. |
9716 |
-+ * |
9717 |
-+ * Return: 0 on success, negative errno on failure |
9718 |
-+ */ |
9719 |
-+int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty) |
9720 |
-+{ |
9721 |
-+ struct kdbus_queue_entry *entry, *tmp; |
9722 |
-+ struct kdbus_bus *bus = conn->ep->bus; |
9723 |
-+ struct kdbus_reply *r, *r_tmp; |
9724 |
-+ struct kdbus_conn *c; |
9725 |
-+ int i, v; |
9726 |
-+ |
9727 |
-+ mutex_lock(&conn->lock); |
9728 |
-+ v = atomic_read(&conn->active); |
9729 |
-+ if (v == KDBUS_CONN_ACTIVE_NEW) { |
9730 |
-+ /* was never connected */ |
9731 |
-+ mutex_unlock(&conn->lock); |
9732 |
-+ return 0; |
9733 |
-+ } |
9734 |
-+ if (v < 0) { |
9735 |
-+ /* already dead */ |
9736 |
-+ mutex_unlock(&conn->lock); |
9737 |
-+ return -ECONNRESET; |
9738 |
-+ } |
9739 |
-+ if (ensure_queue_empty && !list_empty(&conn->queue.msg_list)) { |
9740 |
-+ /* still busy */ |
9741 |
-+ mutex_unlock(&conn->lock); |
9742 |
-+ return -EBUSY; |
9743 |
-+ } |
9744 |
-+ |
9745 |
-+ atomic_add(KDBUS_CONN_ACTIVE_BIAS, &conn->active); |
9746 |
-+ mutex_unlock(&conn->lock); |
9747 |
-+ |
9748 |
-+ wake_up_interruptible(&conn->wait); |
9749 |
-+ |
9750 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9751 |
-+ rwsem_acquire(&conn->dep_map, 0, 0, _RET_IP_); |
9752 |
-+ if (atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_BIAS) |
9753 |
-+ lock_contended(&conn->dep_map, _RET_IP_); |
9754 |
-+#endif |
9755 |
-+ |
9756 |
-+ wait_event(conn->wait, |
9757 |
-+ atomic_read(&conn->active) == KDBUS_CONN_ACTIVE_BIAS); |
9758 |
-+ |
9759 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
9760 |
-+ lock_acquired(&conn->dep_map, _RET_IP_); |
9761 |
-+ rwsem_release(&conn->dep_map, 1, _RET_IP_); |
9762 |
-+#endif |
9763 |
-+ |
9764 |
-+ cancel_delayed_work_sync(&conn->work); |
9765 |
-+ kdbus_policy_remove_owner(&conn->ep->bus->policy_db, conn); |
9766 |
-+ |
9767 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
9768 |
-+ mutex_lock(&conn->ep->lock); |
9769 |
-+ down_write(&bus->conn_rwlock); |
9770 |
-+ |
9771 |
-+ /* remove from bus and endpoint */ |
9772 |
-+ hash_del(&conn->hentry); |
9773 |
-+ list_del(&conn->monitor_entry); |
9774 |
-+ list_del(&conn->ep_entry); |
9775 |
-+ |
9776 |
-+ up_write(&bus->conn_rwlock); |
9777 |
-+ mutex_unlock(&conn->ep->lock); |
9778 |
-+ |
9779 |
-+ /* |
9780 |
-+ * Remove all names associated with this connection; this possibly |
9781 |
-+ * moves queued messages back to the activator connection. |
9782 |
-+ */ |
9783 |
-+ kdbus_name_release_all(bus->name_registry, conn); |
9784 |
-+ |
9785 |
-+ /* if we die while other connections wait for our reply, notify them */ |
9786 |
-+ mutex_lock(&conn->lock); |
9787 |
-+ list_for_each_entry_safe(entry, tmp, &conn->queue.msg_list, entry) { |
9788 |
-+ if (entry->reply) |
9789 |
-+ kdbus_notify_reply_dead(bus, |
9790 |
-+ entry->reply->reply_dst->id, |
9791 |
-+ entry->reply->cookie); |
9792 |
-+ kdbus_queue_entry_free(entry); |
9793 |
-+ } |
9794 |
-+ |
9795 |
-+ list_for_each_entry_safe(r, r_tmp, &conn->reply_list, entry) |
9796 |
-+ kdbus_reply_unlink(r); |
9797 |
-+ mutex_unlock(&conn->lock); |
9798 |
-+ |
9799 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
9800 |
-+ down_read(&bus->conn_rwlock); |
9801 |
-+ hash_for_each(bus->conn_hash, i, c, hentry) { |
9802 |
-+ mutex_lock(&c->lock); |
9803 |
-+ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) { |
9804 |
-+ if (r->reply_src != conn) |
9805 |
-+ continue; |
9806 |
-+ |
9807 |
-+ if (r->sync) |
9808 |
-+ kdbus_sync_reply_wakeup(r, -EPIPE); |
9809 |
-+ else |
9810 |
-+ /* send a 'connection dead' notification */ |
9811 |
-+ kdbus_notify_reply_dead(bus, c->id, r->cookie); |
9812 |
-+ |
9813 |
-+ kdbus_reply_unlink(r); |
9814 |
-+ } |
9815 |
-+ mutex_unlock(&c->lock); |
9816 |
-+ } |
9817 |
-+ up_read(&bus->conn_rwlock); |
9818 |
-+ |
9819 |
-+ if (!kdbus_conn_is_monitor(conn)) |
9820 |
-+ kdbus_notify_id_change(bus, KDBUS_ITEM_ID_REMOVE, |
9821 |
-+ conn->id, conn->flags); |
9822 |
-+ |
9823 |
-+ kdbus_notify_flush(bus); |
9824 |
-+ |
9825 |
-+ return 0; |
9826 |
-+} |
9827 |
-+ |
9828 |
-+/** |
9829 |
-+ * kdbus_conn_has_name() - check if a connection owns a name |
9830 |
-+ * @conn: Connection |
9831 |
-+ * @name: Well-know name to check for |
9832 |
-+ * |
9833 |
-+ * The caller must hold the registry lock of conn->ep->bus. |
9834 |
-+ * |
9835 |
-+ * Return: true if the name is currently owned by the connection |
9836 |
-+ */ |
9837 |
-+bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name) |
9838 |
-+{ |
9839 |
-+ struct kdbus_name_owner *owner; |
9840 |
-+ |
9841 |
-+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
9842 |
-+ |
9843 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) |
9844 |
-+ if (!(owner->flags & KDBUS_NAME_IN_QUEUE) && |
9845 |
-+ !strcmp(name, owner->name->name)) |
9846 |
-+ return true; |
9847 |
-+ |
9848 |
-+ return false; |
9849 |
-+} |
9850 |
-+ |
9851 |
-+struct kdbus_quota { |
9852 |
-+ u32 memory; |
9853 |
-+ u16 msgs; |
9854 |
-+ u8 fds; |
9855 |
-+}; |
9856 |
-+ |
9857 |
-+/** |
9858 |
-+ * kdbus_conn_quota_inc() - increase quota accounting |
9859 |
-+ * @c: connection owning the quota tracking |
9860 |
-+ * @u: user to account for (or NULL for kernel accounting) |
9861 |
-+ * @memory: size of memory to account for |
9862 |
-+ * @fds: number of FDs to account for |
9863 |
-+ * |
9864 |
-+ * This call manages the quotas on resource @c. That is, it's used if other |
9865 |
-+ * users want to use the resources of connection @c, which so far only concerns |
9866 |
-+ * the receive queue of the destination. |
9867 |
-+ * |
9868 |
-+ * This increases the quota-accounting for user @u by @memory bytes and @fds |
9869 |
-+ * file descriptors. If the user has already reached the quota limits, this call |
9870 |
-+ * will not do any accounting but return a negative error code indicating the |
9871 |
-+ * failure. |
9872 |
-+ * |
9873 |
-+ * Return: 0 on success, negative error code on failure. |
9874 |
-+ */ |
9875 |
-+int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, |
9876 |
-+ size_t memory, size_t fds) |
9877 |
-+{ |
9878 |
-+ struct kdbus_quota *quota; |
9879 |
-+ size_t available, accounted; |
9880 |
-+ unsigned int id; |
9881 |
-+ |
9882 |
-+ /* |
9883 |
-+ * Pool Layout: |
9884 |
-+ * 50% of a pool is always owned by the connection. It is reserved for |
9885 |
-+ * kernel queries, handling received messages and other tasks that are |
9886 |
-+ * under control of the pool owner. The other 50% of the pool are used |
9887 |
-+ * as incoming queue. |
9888 |
-+ * As we optionally support user-space based policies, we need fair |
9889 |
-+ * allocation schemes. Furthermore, resource utilization should be |
9890 |
-+ * maximized, so only minimal resources stay reserved. However, we need |
9891 |
-+ * to adapt to a dynamic number of users, as we cannot know how many |
9892 |
-+ * users will talk to a connection. Therefore, the current allocation |
9893 |
-+ * works like this: |
9894 |
-+ * We limit the number of bytes in a destination's pool per sending |
9895 |
-+ * user. The space available for a user is 33% of the unused pool space |
9896 |
-+ * (whereas the space used by the user itself is also treated as |
9897 |
-+ * 'unused'). This way, we favor users coming first, but keep enough |
9898 |
-+ * pool space available for any following users. Given that messages are |
9899 |
-+ * dequeued in FIFO order, this should balance nicely if the number of |
9900 |
-+ * users grows. At the same time, this algorithm guarantees that the |
9901 |
-+ * space available to a connection is reduced dynamically, the more |
9902 |
-+ * concurrent users talk to a connection. |
9903 |
-+ */ |
9904 |
-+ |
9905 |
-+ /* per user-accounting is expensive, so we keep state small */ |
9906 |
-+ BUILD_BUG_ON(sizeof(quota->memory) != 4); |
9907 |
-+ BUILD_BUG_ON(sizeof(quota->msgs) != 2); |
9908 |
-+ BUILD_BUG_ON(sizeof(quota->fds) != 1); |
9909 |
-+ BUILD_BUG_ON(KDBUS_CONN_MAX_MSGS > U16_MAX); |
9910 |
-+ BUILD_BUG_ON(KDBUS_CONN_MAX_FDS_PER_USER > U8_MAX); |
9911 |
-+ |
9912 |
-+ id = u ? u->id : KDBUS_USER_KERNEL_ID; |
9913 |
-+ if (id >= c->n_quota) { |
9914 |
-+ unsigned int users; |
9915 |
-+ |
9916 |
-+ users = max(KDBUS_ALIGN8(id) + 8, id); |
9917 |
-+ quota = krealloc(c->quota, users * sizeof(*quota), |
9918 |
-+ GFP_KERNEL | __GFP_ZERO); |
9919 |
-+ if (!quota) |
9920 |
-+ return -ENOMEM; |
9921 |
-+ |
9922 |
-+ c->n_quota = users; |
9923 |
-+ c->quota = quota; |
9924 |
-+ } |
9925 |
-+ |
9926 |
-+ quota = &c->quota[id]; |
9927 |
-+ kdbus_pool_accounted(c->pool, &available, &accounted); |
9928 |
-+ |
9929 |
-+ /* half the pool is _always_ reserved for the pool owner */ |
9930 |
-+ available /= 2; |
9931 |
-+ |
9932 |
-+ /* |
9933 |
-+ * Pool owner slices are un-accounted slices; they can claim more |
9934 |
-+ * than 50% of the queue. However, the slices we're dealing with here |
9935 |
-+ * belong to the incoming queue, hence they are 'accounted' slices |
9936 |
-+ * to which the 50%-limit applies. |
9937 |
-+ */ |
9938 |
-+ if (available < accounted) |
9939 |
-+ return -ENOBUFS; |
9940 |
-+ |
9941 |
-+ /* 1/3 of the remaining space (including your own memory) */ |
9942 |
-+ available = (available - accounted + quota->memory) / 3; |
9943 |
-+ |
9944 |
-+ if (available < quota->memory || |
9945 |
-+ available - quota->memory < memory || |
9946 |
-+ quota->memory + memory > U32_MAX) |
9947 |
-+ return -ENOBUFS; |
9948 |
-+ if (quota->msgs >= KDBUS_CONN_MAX_MSGS) |
9949 |
-+ return -ENOBUFS; |
9950 |
-+ if (quota->fds + fds < quota->fds || |
9951 |
-+ quota->fds + fds > KDBUS_CONN_MAX_FDS_PER_USER) |
9952 |
-+ return -EMFILE; |
9953 |
-+ |
9954 |
-+ quota->memory += memory; |
9955 |
-+ quota->fds += fds; |
9956 |
-+ ++quota->msgs; |
9957 |
-+ return 0; |
9958 |
-+} |
9959 |
-+ |
9960 |
-+/** |
9961 |
-+ * kdbus_conn_quota_dec() - decrease quota accounting |
9962 |
-+ * @c: connection owning the quota tracking |
9963 |
-+ * @u: user which was accounted for (or NULL for kernel accounting) |
9964 |
-+ * @memory: size of memory which was accounted for |
9965 |
-+ * @fds: number of FDs which were accounted for |
9966 |
-+ * |
9967 |
-+ * This does the reverse of kdbus_conn_quota_inc(). You have to release any |
9968 |
-+ * accounted resources that you called kdbus_conn_quota_inc() for. However, you |
9969 |
-+ * must not call kdbus_conn_quota_dec() if the accounting failed (that is, |
9970 |
-+ * kdbus_conn_quota_inc() failed). |
9971 |
-+ */ |
9972 |
-+void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, |
9973 |
-+ size_t memory, size_t fds) |
9974 |
-+{ |
9975 |
-+ struct kdbus_quota *quota; |
9976 |
-+ unsigned int id; |
9977 |
-+ |
9978 |
-+ id = u ? u->id : KDBUS_USER_KERNEL_ID; |
9979 |
-+ if (WARN_ON(id >= c->n_quota)) |
9980 |
-+ return; |
9981 |
-+ |
9982 |
-+ quota = &c->quota[id]; |
9983 |
-+ |
9984 |
-+ if (!WARN_ON(quota->msgs == 0)) |
9985 |
-+ --quota->msgs; |
9986 |
-+ if (!WARN_ON(quota->memory < memory)) |
9987 |
-+ quota->memory -= memory; |
9988 |
-+ if (!WARN_ON(quota->fds < fds)) |
9989 |
-+ quota->fds -= fds; |
9990 |
-+} |
9991 |
-+ |
9992 |
-+/** |
9993 |
-+ * kdbus_conn_lost_message() - handle lost messages |
9994 |
-+ * @c: connection that lost a message |
9995 |
-+ * |
9996 |
-+ * kdbus is reliable. That means, we try hard to never lose messages. However, |
9997 |
-+ * memory is limited, so we cannot rely on transmissions to never fail. |
9998 |
-+ * Therefore, we use quota-limits to let callers know if their unicast message |
9999 |
-+ * cannot be transmitted to a peer. This works fine for unicasts, but for |
10000 |
-+ * broadcasts we cannot make the caller handle the transmission failure. |
10001 |
-+ * Instead, we must let the destination know that it couldn't receive a |
10002 |
-+ * broadcast. |
10003 |
-+ * As this is an unlikely scenario, we keep it simple. A single lost-counter |
10004 |
-+ * remembers the number of lost messages since the last call to RECV. The next |
10005 |
-+ * message retrieval will notify the connection that it lost messages since the |
10006 |
-+ * last message retrieval and thus should resync its state. |
10007 |
-+ */ |
10008 |
-+void kdbus_conn_lost_message(struct kdbus_conn *c) |
10009 |
-+{ |
10010 |
-+ if (atomic_inc_return(&c->lost_count) == 1) |
10011 |
-+ wake_up_interruptible(&c->wait); |
10012 |
-+} |
10013 |
-+ |
10014 |
-+/* Callers should take the conn_dst lock */ |
10015 |
-+static struct kdbus_queue_entry * |
10016 |
-+kdbus_conn_entry_make(struct kdbus_conn *conn_src, |
10017 |
-+ struct kdbus_conn *conn_dst, |
10018 |
-+ struct kdbus_staging *staging) |
10019 |
-+{ |
10020 |
-+ /* The remote connection was disconnected */ |
10021 |
-+ if (!kdbus_conn_active(conn_dst)) |
10022 |
-+ return ERR_PTR(-ECONNRESET); |
10023 |
-+ |
10024 |
-+ /* |
10025 |
-+ * If the connection does not accept file descriptors but the message |
10026 |
-+ * has some attached, refuse it. |
10027 |
-+ * |
10028 |
-+ * If this is a monitor connection, accept the message. In that |
10029 |
-+ * case, all file descriptors will be set to -1 at receive time. |
10030 |
-+ */ |
10031 |
-+ if (!kdbus_conn_is_monitor(conn_dst) && |
10032 |
-+ !(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) && |
10033 |
-+ staging->gaps && staging->gaps->n_fds > 0) |
10034 |
-+ return ERR_PTR(-ECOMM); |
10035 |
-+ |
10036 |
-+ return kdbus_queue_entry_new(conn_src, conn_dst, staging); |
10037 |
-+} |
10038 |
-+ |
10039 |
-+/* |
10040 |
-+ * Synchronously responding to a message, allocate a queue entry |
10041 |
-+ * and attach it to the reply tracking object. |
10042 |
-+ * The connection's queue will never get to see it. |
10043 |
-+ */ |
10044 |
-+static int kdbus_conn_entry_sync_attach(struct kdbus_conn *conn_dst, |
10045 |
-+ struct kdbus_staging *staging, |
10046 |
-+ struct kdbus_reply *reply_wake) |
10047 |
-+{ |
10048 |
-+ struct kdbus_queue_entry *entry; |
10049 |
-+ int remote_ret, ret = 0; |
10050 |
-+ |
10051 |
-+ mutex_lock(&reply_wake->reply_dst->lock); |
10052 |
-+ |
10053 |
-+ /* |
10054 |
-+ * If we are still waiting then proceed, allocate a queue |
10055 |
-+ * entry and attach it to the reply object |
10056 |
-+ */ |
10057 |
-+ if (reply_wake->waiting) { |
10058 |
-+ entry = kdbus_conn_entry_make(reply_wake->reply_src, conn_dst, |
10059 |
-+ staging); |
10060 |
-+ if (IS_ERR(entry)) |
10061 |
-+ ret = PTR_ERR(entry); |
10062 |
-+ else |
10063 |
-+ /* Attach the entry to the reply object */ |
10064 |
-+ reply_wake->queue_entry = entry; |
10065 |
-+ } else { |
10066 |
-+ ret = -ECONNRESET; |
10067 |
-+ } |
10068 |
-+ |
10069 |
-+ /* |
10070 |
-+ * Update the reply object and wake up remote peer only |
10071 |
-+ * on appropriate return codes |
10072 |
-+ * |
10073 |
-+ * * -ECOMM: if the replying connection failed with -ECOMM |
10074 |
-+ * then wakeup remote peer with -EREMOTEIO |
10075 |
-+ * |
10076 |
-+ * We do this to differenciate between -ECOMM errors |
10077 |
-+ * from the original sender perspective: |
10078 |
-+ * -ECOMM error during the sync send and |
10079 |
-+ * -ECOMM error during the sync reply, this last |
10080 |
-+ * one is rewritten to -EREMOTEIO |
10081 |
-+ * |
10082 |
-+ * * Wake up on all other return codes. |
10083 |
-+ */ |
10084 |
-+ remote_ret = ret; |
10085 |
-+ |
10086 |
-+ if (ret == -ECOMM) |
10087 |
-+ remote_ret = -EREMOTEIO; |
10088 |
-+ |
10089 |
-+ kdbus_sync_reply_wakeup(reply_wake, remote_ret); |
10090 |
-+ kdbus_reply_unlink(reply_wake); |
10091 |
-+ mutex_unlock(&reply_wake->reply_dst->lock); |
10092 |
-+ |
10093 |
-+ return ret; |
10094 |
-+} |
10095 |
-+ |
10096 |
-+/** |
10097 |
-+ * kdbus_conn_entry_insert() - enqueue a message into the receiver's pool |
10098 |
-+ * @conn_src: The sending connection |
10099 |
-+ * @conn_dst: The connection to queue into |
10100 |
-+ * @staging: Message to send |
10101 |
-+ * @reply: The reply tracker to attach to the queue entry |
10102 |
-+ * @name: Destination name this msg is sent to, or NULL |
10103 |
-+ * |
10104 |
-+ * Return: 0 on success. negative error otherwise. |
10105 |
-+ */ |
10106 |
-+int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, |
10107 |
-+ struct kdbus_conn *conn_dst, |
10108 |
-+ struct kdbus_staging *staging, |
10109 |
-+ struct kdbus_reply *reply, |
10110 |
-+ const struct kdbus_name_entry *name) |
10111 |
-+{ |
10112 |
-+ struct kdbus_queue_entry *entry; |
10113 |
-+ int ret; |
10114 |
-+ |
10115 |
-+ kdbus_conn_lock2(conn_src, conn_dst); |
10116 |
-+ |
10117 |
-+ entry = kdbus_conn_entry_make(conn_src, conn_dst, staging); |
10118 |
-+ if (IS_ERR(entry)) { |
10119 |
-+ ret = PTR_ERR(entry); |
10120 |
-+ goto exit_unlock; |
10121 |
-+ } |
10122 |
-+ |
10123 |
-+ if (reply) { |
10124 |
-+ kdbus_reply_link(reply); |
10125 |
-+ if (!reply->sync) |
10126 |
-+ schedule_delayed_work(&conn_src->work, 0); |
10127 |
-+ } |
10128 |
-+ |
10129 |
-+ /* |
10130 |
-+ * Record the sequence number of the registered name; it will |
10131 |
-+ * be remembered by the queue, in case messages addressed to a |
10132 |
-+ * name need to be moved from or to an activator. |
10133 |
-+ */ |
10134 |
-+ if (name) |
10135 |
-+ entry->dst_name_id = name->name_id; |
10136 |
-+ |
10137 |
-+ kdbus_queue_entry_enqueue(entry, reply); |
10138 |
-+ wake_up_interruptible(&conn_dst->wait); |
10139 |
-+ |
10140 |
-+ ret = 0; |
10141 |
-+ |
10142 |
-+exit_unlock: |
10143 |
-+ kdbus_conn_unlock2(conn_src, conn_dst); |
10144 |
-+ return ret; |
10145 |
-+} |
10146 |
-+ |
10147 |
-+static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src, |
10148 |
-+ struct kdbus_cmd_send *cmd_send, |
10149 |
-+ struct file *ioctl_file, |
10150 |
-+ struct file *cancel_fd, |
10151 |
-+ struct kdbus_reply *reply_wait, |
10152 |
-+ ktime_t expire) |
10153 |
-+{ |
10154 |
-+ struct kdbus_queue_entry *entry; |
10155 |
-+ struct poll_wqueues pwq = {}; |
10156 |
-+ int ret; |
10157 |
-+ |
10158 |
-+ if (WARN_ON(!reply_wait)) |
10159 |
-+ return -EIO; |
10160 |
-+ |
10161 |
-+ /* |
10162 |
-+ * Block until the reply arrives. reply_wait is left untouched |
10163 |
-+ * by the timeout scans that might be conducted for other, |
10164 |
-+ * asynchronous replies of conn_src. |
10165 |
-+ */ |
10166 |
-+ |
10167 |
-+ poll_initwait(&pwq); |
10168 |
-+ poll_wait(ioctl_file, &conn_src->wait, &pwq.pt); |
10169 |
-+ |
10170 |
-+ for (;;) { |
10171 |
-+ /* |
10172 |
-+ * Any of the following conditions will stop our synchronously |
10173 |
-+ * blocking SEND command: |
10174 |
-+ * |
10175 |
-+ * a) The origin sender closed its connection |
10176 |
-+ * b) The remote peer answered, setting reply_wait->waiting = 0 |
10177 |
-+ * c) The cancel FD was written to |
10178 |
-+ * d) A signal was received |
10179 |
-+ * e) The specified timeout was reached, and none of the above |
10180 |
-+ * conditions kicked in. |
10181 |
-+ */ |
10182 |
-+ |
10183 |
-+ /* |
10184 |
-+ * We have already acquired an active reference when |
10185 |
-+ * entering here, but another thread may call |
10186 |
-+ * KDBUS_CMD_BYEBYE which does not acquire an active |
10187 |
-+ * reference, therefore kdbus_conn_disconnect() will |
10188 |
-+ * not wait for us. |
10189 |
-+ */ |
10190 |
-+ if (!kdbus_conn_active(conn_src)) { |
10191 |
-+ ret = -ECONNRESET; |
10192 |
-+ break; |
10193 |
-+ } |
10194 |
-+ |
10195 |
-+ /* |
10196 |
-+ * After the replying peer unset the waiting variable |
10197 |
-+ * it will wake up us. |
10198 |
-+ */ |
10199 |
-+ if (!reply_wait->waiting) { |
10200 |
-+ ret = reply_wait->err; |
10201 |
-+ break; |
10202 |
-+ } |
10203 |
-+ |
10204 |
-+ if (cancel_fd) { |
10205 |
-+ unsigned int r; |
10206 |
-+ |
10207 |
-+ r = cancel_fd->f_op->poll(cancel_fd, &pwq.pt); |
10208 |
-+ if (r & POLLIN) { |
10209 |
-+ ret = -ECANCELED; |
10210 |
-+ break; |
10211 |
-+ } |
10212 |
-+ } |
10213 |
-+ |
10214 |
-+ if (signal_pending(current)) { |
10215 |
-+ ret = -EINTR; |
10216 |
-+ break; |
10217 |
-+ } |
10218 |
-+ |
10219 |
-+ if (!poll_schedule_timeout(&pwq, TASK_INTERRUPTIBLE, |
10220 |
-+ &expire, 0)) { |
10221 |
-+ ret = -ETIMEDOUT; |
10222 |
-+ break; |
10223 |
-+ } |
10224 |
-+ |
10225 |
-+ /* |
10226 |
-+ * Reset the poll worker func, so the waitqueues are not |
10227 |
-+ * added to the poll table again. We just reuse what we've |
10228 |
-+ * collected earlier for further iterations. |
10229 |
-+ */ |
10230 |
-+ init_poll_funcptr(&pwq.pt, NULL); |
10231 |
-+ } |
10232 |
-+ |
10233 |
-+ poll_freewait(&pwq); |
10234 |
-+ |
10235 |
-+ if (ret == -EINTR) { |
10236 |
-+ /* |
10237 |
-+ * Interrupted system call. Unref the reply object, and pass |
10238 |
-+ * the return value down the chain. Mark the reply as |
10239 |
-+ * interrupted, so the cleanup work can remove it, but do not |
10240 |
-+ * unlink it from the list. Once the syscall restarts, we'll |
10241 |
-+ * pick it up and wait on it again. |
10242 |
-+ */ |
10243 |
-+ mutex_lock(&conn_src->lock); |
10244 |
-+ reply_wait->interrupted = true; |
10245 |
-+ schedule_delayed_work(&conn_src->work, 0); |
10246 |
-+ mutex_unlock(&conn_src->lock); |
10247 |
-+ |
10248 |
-+ return -ERESTARTSYS; |
10249 |
-+ } |
10250 |
-+ |
10251 |
-+ mutex_lock(&conn_src->lock); |
10252 |
-+ reply_wait->waiting = false; |
10253 |
-+ entry = reply_wait->queue_entry; |
10254 |
-+ if (entry) { |
10255 |
-+ ret = kdbus_queue_entry_install(entry, |
10256 |
-+ &cmd_send->reply.return_flags, |
10257 |
-+ true); |
10258 |
-+ kdbus_pool_slice_publish(entry->slice, &cmd_send->reply.offset, |
10259 |
-+ &cmd_send->reply.msg_size); |
10260 |
-+ kdbus_queue_entry_free(entry); |
10261 |
-+ } |
10262 |
-+ kdbus_reply_unlink(reply_wait); |
10263 |
-+ mutex_unlock(&conn_src->lock); |
10264 |
-+ |
10265 |
-+ return ret; |
10266 |
-+} |
10267 |
-+ |
10268 |
-+static int kdbus_pin_dst(struct kdbus_bus *bus, |
10269 |
-+ struct kdbus_staging *staging, |
10270 |
-+ struct kdbus_name_entry **out_name, |
10271 |
-+ struct kdbus_conn **out_dst) |
10272 |
-+{ |
10273 |
-+ const struct kdbus_msg *msg = staging->msg; |
10274 |
-+ struct kdbus_name_owner *owner = NULL; |
10275 |
-+ struct kdbus_name_entry *name = NULL; |
10276 |
-+ struct kdbus_conn *dst = NULL; |
10277 |
-+ int ret; |
10278 |
-+ |
10279 |
-+ lockdep_assert_held(&bus->name_registry->rwlock); |
10280 |
-+ |
10281 |
-+ if (!staging->dst_name) { |
10282 |
-+ dst = kdbus_bus_find_conn_by_id(bus, msg->dst_id); |
10283 |
-+ if (!dst) |
10284 |
-+ return -ENXIO; |
10285 |
-+ |
10286 |
-+ if (!kdbus_conn_is_ordinary(dst)) { |
10287 |
-+ ret = -ENXIO; |
10288 |
-+ goto error; |
10289 |
-+ } |
10290 |
-+ } else { |
10291 |
-+ name = kdbus_name_lookup_unlocked(bus->name_registry, |
10292 |
-+ staging->dst_name); |
10293 |
-+ if (name) |
10294 |
-+ owner = kdbus_name_get_owner(name); |
10295 |
-+ if (!owner) |
10296 |
-+ return -ESRCH; |
10297 |
-+ |
10298 |
-+ /* |
10299 |
-+ * If both a name and a connection ID are given as destination |
10300 |
-+ * of a message, check that the currently owning connection of |
10301 |
-+ * the name matches the specified ID. |
10302 |
-+ * This way, we allow userspace to send the message to a |
10303 |
-+ * specific connection by ID only if the connection currently |
10304 |
-+ * owns the given name. |
10305 |
-+ */ |
10306 |
-+ if (msg->dst_id != KDBUS_DST_ID_NAME && |
10307 |
-+ msg->dst_id != owner->conn->id) |
10308 |
-+ return -EREMCHG; |
10309 |
-+ |
10310 |
-+ if ((msg->flags & KDBUS_MSG_NO_AUTO_START) && |
10311 |
-+ kdbus_conn_is_activator(owner->conn)) |
10312 |
-+ return -EADDRNOTAVAIL; |
10313 |
-+ |
10314 |
-+ dst = kdbus_conn_ref(owner->conn); |
10315 |
-+ } |
10316 |
-+ |
10317 |
-+ *out_name = name; |
10318 |
-+ *out_dst = dst; |
10319 |
-+ return 0; |
10320 |
-+ |
10321 |
-+error: |
10322 |
-+ kdbus_conn_unref(dst); |
10323 |
-+ return ret; |
10324 |
-+} |
10325 |
-+ |
10326 |
-+static int kdbus_conn_reply(struct kdbus_conn *src, |
10327 |
-+ struct kdbus_staging *staging) |
10328 |
-+{ |
10329 |
-+ const struct kdbus_msg *msg = staging->msg; |
10330 |
-+ struct kdbus_name_entry *name = NULL; |
10331 |
-+ struct kdbus_reply *reply, *wake = NULL; |
10332 |
-+ struct kdbus_conn *dst = NULL; |
10333 |
-+ struct kdbus_bus *bus = src->ep->bus; |
10334 |
-+ int ret; |
10335 |
-+ |
10336 |
-+ if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) || |
10337 |
-+ WARN_ON(msg->flags & KDBUS_MSG_EXPECT_REPLY) || |
10338 |
-+ WARN_ON(msg->flags & KDBUS_MSG_SIGNAL)) |
10339 |
-+ return -EINVAL; |
10340 |
-+ |
10341 |
-+ /* name-registry must be locked for lookup *and* collecting data */ |
10342 |
-+ down_read(&bus->name_registry->rwlock); |
10343 |
-+ |
10344 |
-+ /* find and pin destination */ |
10345 |
-+ |
10346 |
-+ ret = kdbus_pin_dst(bus, staging, &name, &dst); |
10347 |
-+ if (ret < 0) |
10348 |
-+ goto exit; |
10349 |
-+ |
10350 |
-+ mutex_lock(&dst->lock); |
10351 |
-+ reply = kdbus_reply_find(src, dst, msg->cookie_reply); |
10352 |
-+ if (reply) { |
10353 |
-+ if (reply->sync) |
10354 |
-+ wake = kdbus_reply_ref(reply); |
10355 |
-+ kdbus_reply_unlink(reply); |
10356 |
-+ } |
10357 |
-+ mutex_unlock(&dst->lock); |
10358 |
-+ |
10359 |
-+ if (!reply) { |
10360 |
-+ ret = -EBADSLT; |
10361 |
-+ goto exit; |
10362 |
-+ } |
10363 |
-+ |
10364 |
-+ /* send message */ |
10365 |
-+ |
10366 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10367 |
-+ |
10368 |
-+ if (wake) |
10369 |
-+ ret = kdbus_conn_entry_sync_attach(dst, staging, wake); |
10370 |
-+ else |
10371 |
-+ ret = kdbus_conn_entry_insert(src, dst, staging, NULL, name); |
10372 |
-+ |
10373 |
-+exit: |
10374 |
-+ up_read(&bus->name_registry->rwlock); |
10375 |
-+ kdbus_reply_unref(wake); |
10376 |
-+ kdbus_conn_unref(dst); |
10377 |
-+ return ret; |
10378 |
-+} |
10379 |
-+ |
10380 |
-+static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src, |
10381 |
-+ struct kdbus_staging *staging, |
10382 |
-+ ktime_t exp) |
10383 |
-+{ |
10384 |
-+ const struct kdbus_msg *msg = staging->msg; |
10385 |
-+ struct kdbus_name_entry *name = NULL; |
10386 |
-+ struct kdbus_reply *wait = NULL; |
10387 |
-+ struct kdbus_conn *dst = NULL; |
10388 |
-+ struct kdbus_bus *bus = src->ep->bus; |
10389 |
-+ int ret; |
10390 |
-+ |
10391 |
-+ if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) || |
10392 |
-+ WARN_ON(msg->flags & KDBUS_MSG_SIGNAL) || |
10393 |
-+ WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY))) |
10394 |
-+ return ERR_PTR(-EINVAL); |
10395 |
-+ |
10396 |
-+ /* resume previous wait-context, if available */ |
10397 |
-+ |
10398 |
-+ mutex_lock(&src->lock); |
10399 |
-+ wait = kdbus_reply_find(NULL, src, msg->cookie); |
10400 |
-+ if (wait) { |
10401 |
-+ if (wait->interrupted) { |
10402 |
-+ kdbus_reply_ref(wait); |
10403 |
-+ wait->interrupted = false; |
10404 |
-+ } else { |
10405 |
-+ wait = NULL; |
10406 |
-+ } |
10407 |
-+ } |
10408 |
-+ mutex_unlock(&src->lock); |
10409 |
-+ |
10410 |
-+ if (wait) |
10411 |
-+ return wait; |
10412 |
-+ |
10413 |
-+ if (ktime_compare(ktime_get(), exp) >= 0) |
10414 |
-+ return ERR_PTR(-ETIMEDOUT); |
10415 |
-+ |
10416 |
-+ /* name-registry must be locked for lookup *and* collecting data */ |
10417 |
-+ down_read(&bus->name_registry->rwlock); |
10418 |
-+ |
10419 |
-+ /* find and pin destination */ |
10420 |
-+ |
10421 |
-+ ret = kdbus_pin_dst(bus, staging, &name, &dst); |
10422 |
-+ if (ret < 0) |
10423 |
-+ goto exit; |
10424 |
-+ |
10425 |
-+ if (!kdbus_conn_policy_talk(src, current_cred(), dst)) { |
10426 |
-+ ret = -EPERM; |
10427 |
-+ goto exit; |
10428 |
-+ } |
10429 |
-+ |
10430 |
-+ wait = kdbus_reply_new(dst, src, msg, name, true); |
10431 |
-+ if (IS_ERR(wait)) { |
10432 |
-+ ret = PTR_ERR(wait); |
10433 |
-+ wait = NULL; |
10434 |
-+ goto exit; |
10435 |
-+ } |
10436 |
-+ |
10437 |
-+ /* send message */ |
10438 |
-+ |
10439 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10440 |
-+ |
10441 |
-+ ret = kdbus_conn_entry_insert(src, dst, staging, wait, name); |
10442 |
-+ if (ret < 0) |
10443 |
-+ goto exit; |
10444 |
-+ |
10445 |
-+ ret = 0; |
10446 |
-+ |
10447 |
-+exit: |
10448 |
-+ up_read(&bus->name_registry->rwlock); |
10449 |
-+ if (ret < 0) { |
10450 |
-+ kdbus_reply_unref(wait); |
10451 |
-+ wait = ERR_PTR(ret); |
10452 |
-+ } |
10453 |
-+ kdbus_conn_unref(dst); |
10454 |
-+ return wait; |
10455 |
-+} |
10456 |
-+ |
10457 |
-+static int kdbus_conn_unicast(struct kdbus_conn *src, |
10458 |
-+ struct kdbus_staging *staging) |
10459 |
-+{ |
10460 |
-+ const struct kdbus_msg *msg = staging->msg; |
10461 |
-+ struct kdbus_name_entry *name = NULL; |
10462 |
-+ struct kdbus_reply *wait = NULL; |
10463 |
-+ struct kdbus_conn *dst = NULL; |
10464 |
-+ struct kdbus_bus *bus = src->ep->bus; |
10465 |
-+ bool is_signal = (msg->flags & KDBUS_MSG_SIGNAL); |
10466 |
-+ int ret = 0; |
10467 |
-+ |
10468 |
-+ if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) || |
10469 |
-+ WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY) && |
10470 |
-+ msg->cookie_reply != 0)) |
10471 |
-+ return -EINVAL; |
10472 |
-+ |
10473 |
-+ /* name-registry must be locked for lookup *and* collecting data */ |
10474 |
-+ down_read(&bus->name_registry->rwlock); |
10475 |
-+ |
10476 |
-+ /* find and pin destination */ |
10477 |
-+ |
10478 |
-+ ret = kdbus_pin_dst(bus, staging, &name, &dst); |
10479 |
-+ if (ret < 0) |
10480 |
-+ goto exit; |
10481 |
-+ |
10482 |
-+ if (is_signal) { |
10483 |
-+ /* like broadcasts we eavesdrop even if the msg is dropped */ |
10484 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10485 |
-+ |
10486 |
-+ /* drop silently if peer is not interested or not privileged */ |
10487 |
-+ if (!kdbus_match_db_match_msg(dst->match_db, src, staging) || |
10488 |
-+ !kdbus_conn_policy_talk(dst, NULL, src)) |
10489 |
-+ goto exit; |
10490 |
-+ } else if (!kdbus_conn_policy_talk(src, current_cred(), dst)) { |
10491 |
-+ ret = -EPERM; |
10492 |
-+ goto exit; |
10493 |
-+ } else if (msg->flags & KDBUS_MSG_EXPECT_REPLY) { |
10494 |
-+ wait = kdbus_reply_new(dst, src, msg, name, false); |
10495 |
-+ if (IS_ERR(wait)) { |
10496 |
-+ ret = PTR_ERR(wait); |
10497 |
-+ wait = NULL; |
10498 |
-+ goto exit; |
10499 |
-+ } |
10500 |
-+ } |
10501 |
-+ |
10502 |
-+ /* send message */ |
10503 |
-+ |
10504 |
-+ if (!is_signal) |
10505 |
-+ kdbus_bus_eavesdrop(bus, src, staging); |
10506 |
-+ |
10507 |
-+ ret = kdbus_conn_entry_insert(src, dst, staging, wait, name); |
10508 |
-+ if (ret < 0 && !is_signal) |
10509 |
-+ goto exit; |
10510 |
-+ |
10511 |
-+ /* signals are treated like broadcasts, recv-errors are ignored */ |
10512 |
-+ ret = 0; |
10513 |
-+ |
10514 |
-+exit: |
10515 |
-+ up_read(&bus->name_registry->rwlock); |
10516 |
-+ kdbus_reply_unref(wait); |
10517 |
-+ kdbus_conn_unref(dst); |
10518 |
-+ return ret; |
10519 |
-+} |
10520 |
-+ |
10521 |
-+/** |
10522 |
-+ * kdbus_conn_move_messages() - move messages from one connection to another |
10523 |
-+ * @conn_dst: Connection to copy to |
10524 |
-+ * @conn_src: Connection to copy from |
10525 |
-+ * @name_id: Filter for the sequence number of the registered |
10526 |
-+ * name, 0 means no filtering. |
10527 |
-+ * |
10528 |
-+ * Move all messages from one connection to another. This is used when |
10529 |
-+ * an implementer connection is taking over/giving back a well-known name |
10530 |
-+ * from/to an activator connection. |
10531 |
-+ */ |
10532 |
-+void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, |
10533 |
-+ struct kdbus_conn *conn_src, |
10534 |
-+ u64 name_id) |
10535 |
-+{ |
10536 |
-+ struct kdbus_queue_entry *e, *e_tmp; |
10537 |
-+ struct kdbus_reply *r, *r_tmp; |
10538 |
-+ struct kdbus_bus *bus; |
10539 |
-+ struct kdbus_conn *c; |
10540 |
-+ LIST_HEAD(msg_list); |
10541 |
-+ int i, ret = 0; |
10542 |
-+ |
10543 |
-+ if (WARN_ON(conn_src == conn_dst)) |
10544 |
-+ return; |
10545 |
-+ |
10546 |
-+ bus = conn_src->ep->bus; |
10547 |
-+ |
10548 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
10549 |
-+ down_read(&bus->conn_rwlock); |
10550 |
-+ hash_for_each(bus->conn_hash, i, c, hentry) { |
10551 |
-+ if (c == conn_src || c == conn_dst) |
10552 |
-+ continue; |
10553 |
-+ |
10554 |
-+ mutex_lock(&c->lock); |
10555 |
-+ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) { |
10556 |
-+ if (r->reply_src != conn_src) |
10557 |
-+ continue; |
10558 |
-+ |
10559 |
-+ /* filter messages for a specific name */ |
10560 |
-+ if (name_id > 0 && r->name_id != name_id) |
10561 |
-+ continue; |
10562 |
-+ |
10563 |
-+ kdbus_conn_unref(r->reply_src); |
10564 |
-+ r->reply_src = kdbus_conn_ref(conn_dst); |
10565 |
-+ } |
10566 |
-+ mutex_unlock(&c->lock); |
10567 |
-+ } |
10568 |
-+ up_read(&bus->conn_rwlock); |
10569 |
-+ |
10570 |
-+ kdbus_conn_lock2(conn_src, conn_dst); |
10571 |
-+ list_for_each_entry_safe(e, e_tmp, &conn_src->queue.msg_list, entry) { |
10572 |
-+ /* filter messages for a specific name */ |
10573 |
-+ if (name_id > 0 && e->dst_name_id != name_id) |
10574 |
-+ continue; |
10575 |
-+ |
10576 |
-+ if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) && |
10577 |
-+ e->gaps && e->gaps->n_fds > 0) { |
10578 |
-+ kdbus_conn_lost_message(conn_dst); |
10579 |
-+ kdbus_queue_entry_free(e); |
10580 |
-+ continue; |
10581 |
-+ } |
10582 |
-+ |
10583 |
-+ ret = kdbus_queue_entry_move(e, conn_dst); |
10584 |
-+ if (ret < 0) { |
10585 |
-+ kdbus_conn_lost_message(conn_dst); |
10586 |
-+ kdbus_queue_entry_free(e); |
10587 |
-+ continue; |
10588 |
-+ } |
10589 |
-+ } |
10590 |
-+ kdbus_conn_unlock2(conn_src, conn_dst); |
10591 |
-+ |
10592 |
-+ /* wake up poll() */ |
10593 |
-+ wake_up_interruptible(&conn_dst->wait); |
10594 |
-+} |
10595 |
-+ |
10596 |
-+/* query the policy-database for all names of @whom */ |
10597 |
-+static bool kdbus_conn_policy_query_all(struct kdbus_conn *conn, |
10598 |
-+ const struct cred *conn_creds, |
10599 |
-+ struct kdbus_policy_db *db, |
10600 |
-+ struct kdbus_conn *whom, |
10601 |
-+ unsigned int access) |
10602 |
-+{ |
10603 |
-+ struct kdbus_name_owner *owner; |
10604 |
-+ bool pass = false; |
10605 |
-+ int res; |
10606 |
-+ |
10607 |
-+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
10608 |
-+ |
10609 |
-+ down_read(&db->entries_rwlock); |
10610 |
-+ mutex_lock(&whom->lock); |
10611 |
-+ |
10612 |
-+ list_for_each_entry(owner, &whom->names_list, conn_entry) { |
10613 |
-+ if (owner->flags & KDBUS_NAME_IN_QUEUE) |
10614 |
-+ continue; |
10615 |
-+ |
10616 |
-+ res = kdbus_policy_query_unlocked(db, |
10617 |
-+ conn_creds ? : conn->cred, |
10618 |
-+ owner->name->name, |
10619 |
-+ kdbus_strhash(owner->name->name)); |
10620 |
-+ if (res >= (int)access) { |
10621 |
-+ pass = true; |
10622 |
-+ break; |
10623 |
-+ } |
10624 |
-+ } |
10625 |
-+ |
10626 |
-+ mutex_unlock(&whom->lock); |
10627 |
-+ up_read(&db->entries_rwlock); |
10628 |
-+ |
10629 |
-+ return pass; |
10630 |
-+} |
10631 |
-+ |
10632 |
-+/** |
10633 |
-+ * kdbus_conn_policy_own_name() - verify a connection can own the given name |
10634 |
-+ * @conn: Connection |
10635 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10636 |
-+ * @name: Name |
10637 |
-+ * |
10638 |
-+ * This verifies that @conn is allowed to acquire the well-known name @name. |
10639 |
-+ * |
10640 |
-+ * Return: true if allowed, false if not. |
10641 |
-+ */ |
10642 |
-+bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, |
10643 |
-+ const struct cred *conn_creds, |
10644 |
-+ const char *name) |
10645 |
-+{ |
10646 |
-+ unsigned int hash = kdbus_strhash(name); |
10647 |
-+ int res; |
10648 |
-+ |
10649 |
-+ if (!conn_creds) |
10650 |
-+ conn_creds = conn->cred; |
10651 |
-+ |
10652 |
-+ if (conn->ep->user) { |
10653 |
-+ res = kdbus_policy_query(&conn->ep->policy_db, conn_creds, |
10654 |
-+ name, hash); |
10655 |
-+ if (res < KDBUS_POLICY_OWN) |
10656 |
-+ return false; |
10657 |
-+ } |
10658 |
-+ |
10659 |
-+ if (conn->owner) |
10660 |
-+ return true; |
10661 |
-+ |
10662 |
-+ res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds, |
10663 |
-+ name, hash); |
10664 |
-+ return res >= KDBUS_POLICY_OWN; |
10665 |
-+} |
10666 |
-+ |
10667 |
-+/** |
10668 |
-+ * kdbus_conn_policy_talk() - verify a connection can talk to a given peer |
10669 |
-+ * @conn: Connection that tries to talk |
10670 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10671 |
-+ * @to: Connection that is talked to |
10672 |
-+ * |
10673 |
-+ * This verifies that @conn is allowed to talk to @to. |
10674 |
-+ * |
10675 |
-+ * Return: true if allowed, false if not. |
10676 |
-+ */ |
10677 |
-+bool kdbus_conn_policy_talk(struct kdbus_conn *conn, |
10678 |
-+ const struct cred *conn_creds, |
10679 |
-+ struct kdbus_conn *to) |
10680 |
-+{ |
10681 |
-+ if (!conn_creds) |
10682 |
-+ conn_creds = conn->cred; |
10683 |
-+ |
10684 |
-+ if (conn->ep->user && |
10685 |
-+ !kdbus_conn_policy_query_all(conn, conn_creds, &conn->ep->policy_db, |
10686 |
-+ to, KDBUS_POLICY_TALK)) |
10687 |
-+ return false; |
10688 |
-+ |
10689 |
-+ if (conn->owner) |
10690 |
-+ return true; |
10691 |
-+ if (uid_eq(conn_creds->euid, to->cred->uid)) |
10692 |
-+ return true; |
10693 |
-+ |
10694 |
-+ return kdbus_conn_policy_query_all(conn, conn_creds, |
10695 |
-+ &conn->ep->bus->policy_db, to, |
10696 |
-+ KDBUS_POLICY_TALK); |
10697 |
-+} |
10698 |
-+ |
10699 |
-+/** |
10700 |
-+ * kdbus_conn_policy_see_name_unlocked() - verify a connection can see a given |
10701 |
-+ * name |
10702 |
-+ * @conn: Connection |
10703 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10704 |
-+ * @name: Name |
10705 |
-+ * |
10706 |
-+ * This verifies that @conn is allowed to see the well-known name @name. Caller |
10707 |
-+ * must hold policy-lock. |
10708 |
-+ * |
10709 |
-+ * Return: true if allowed, false if not. |
10710 |
-+ */ |
10711 |
-+bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, |
10712 |
-+ const struct cred *conn_creds, |
10713 |
-+ const char *name) |
10714 |
-+{ |
10715 |
-+ int res; |
10716 |
-+ |
10717 |
-+ /* |
10718 |
-+ * By default, all names are visible on a bus. SEE policies can only be |
10719 |
-+ * installed on custom endpoints, where by default no name is visible. |
10720 |
-+ */ |
10721 |
-+ if (!conn->ep->user) |
10722 |
-+ return true; |
10723 |
-+ |
10724 |
-+ res = kdbus_policy_query_unlocked(&conn->ep->policy_db, |
10725 |
-+ conn_creds ? : conn->cred, |
10726 |
-+ name, kdbus_strhash(name)); |
10727 |
-+ return res >= KDBUS_POLICY_SEE; |
10728 |
-+} |
10729 |
-+ |
10730 |
-+static bool kdbus_conn_policy_see_name(struct kdbus_conn *conn, |
10731 |
-+ const struct cred *conn_creds, |
10732 |
-+ const char *name) |
10733 |
-+{ |
10734 |
-+ bool res; |
10735 |
-+ |
10736 |
-+ down_read(&conn->ep->policy_db.entries_rwlock); |
10737 |
-+ res = kdbus_conn_policy_see_name_unlocked(conn, conn_creds, name); |
10738 |
-+ up_read(&conn->ep->policy_db.entries_rwlock); |
10739 |
-+ |
10740 |
-+ return res; |
10741 |
-+} |
10742 |
-+ |
10743 |
-+static bool kdbus_conn_policy_see(struct kdbus_conn *conn, |
10744 |
-+ const struct cred *conn_creds, |
10745 |
-+ struct kdbus_conn *whom) |
10746 |
-+{ |
10747 |
-+ /* |
10748 |
-+ * By default, all names are visible on a bus, so a connection can |
10749 |
-+ * always see other connections. SEE policies can only be installed on |
10750 |
-+ * custom endpoints, where by default no name is visible and we hide |
10751 |
-+ * peers from each other, unless you see at least _one_ name of the |
10752 |
-+ * peer. |
10753 |
-+ */ |
10754 |
-+ return !conn->ep->user || |
10755 |
-+ kdbus_conn_policy_query_all(conn, conn_creds, |
10756 |
-+ &conn->ep->policy_db, whom, |
10757 |
-+ KDBUS_POLICY_SEE); |
10758 |
-+} |
10759 |
-+ |
10760 |
-+/** |
10761 |
-+ * kdbus_conn_policy_see_notification() - verify a connection is allowed to |
10762 |
-+ * receive a given kernel notification |
10763 |
-+ * @conn: Connection |
10764 |
-+ * @conn_creds: Credentials of @conn to use for policy check |
10765 |
-+ * @msg: Notification message |
10766 |
-+ * |
10767 |
-+ * This checks whether @conn is allowed to see the kernel notification. |
10768 |
-+ * |
10769 |
-+ * Return: true if allowed, false if not. |
10770 |
-+ */ |
10771 |
-+bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, |
10772 |
-+ const struct cred *conn_creds, |
10773 |
-+ const struct kdbus_msg *msg) |
10774 |
-+{ |
10775 |
-+ /* |
10776 |
-+ * Depending on the notification type, broadcasted kernel notifications |
10777 |
-+ * have to be filtered: |
10778 |
-+ * |
10779 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}: This notification is forwarded |
10780 |
-+ * to a peer if, and only if, that peer can see the name this |
10781 |
-+ * notification is for. |
10782 |
-+ * |
10783 |
-+ * KDBUS_ITEM_ID_{ADD,REMOVE}: Notifications for ID changes are |
10784 |
-+ * broadcast to everyone, to allow tracking peers. |
10785 |
-+ */ |
10786 |
-+ |
10787 |
-+ switch (msg->items[0].type) { |
10788 |
-+ case KDBUS_ITEM_NAME_ADD: |
10789 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
10790 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
10791 |
-+ return kdbus_conn_policy_see_name(conn, conn_creds, |
10792 |
-+ msg->items[0].name_change.name); |
10793 |
-+ |
10794 |
-+ case KDBUS_ITEM_ID_ADD: |
10795 |
-+ case KDBUS_ITEM_ID_REMOVE: |
10796 |
-+ return true; |
10797 |
-+ |
10798 |
-+ default: |
10799 |
-+ WARN(1, "Invalid type for notification broadcast: %llu\n", |
10800 |
-+ (unsigned long long)msg->items[0].type); |
10801 |
-+ return false; |
10802 |
-+ } |
10803 |
-+} |
10804 |
-+ |
10805 |
-+/** |
10806 |
-+ * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO |
10807 |
-+ * @ep: Endpoint to operate on |
10808 |
-+ * @file: File this connection is opened on |
10809 |
-+ * @argp: Command payload |
10810 |
-+ * |
10811 |
-+ * Return: NULL or newly created connection on success, ERR_PTR on failure. |
10812 |
-+ */ |
10813 |
-+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file, |
10814 |
-+ void __user *argp) |
10815 |
-+{ |
10816 |
-+ struct kdbus_cmd_hello *cmd; |
10817 |
-+ struct kdbus_conn *c = NULL; |
10818 |
-+ const char *item_name; |
10819 |
-+ int ret; |
10820 |
-+ |
10821 |
-+ struct kdbus_arg argv[] = { |
10822 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
10823 |
-+ { .type = KDBUS_ITEM_NAME }, |
10824 |
-+ { .type = KDBUS_ITEM_CREDS }, |
10825 |
-+ { .type = KDBUS_ITEM_PIDS }, |
10826 |
-+ { .type = KDBUS_ITEM_SECLABEL }, |
10827 |
-+ { .type = KDBUS_ITEM_CONN_DESCRIPTION }, |
10828 |
-+ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
10829 |
-+ }; |
10830 |
-+ struct kdbus_args args = { |
10831 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
10832 |
-+ KDBUS_HELLO_ACCEPT_FD | |
10833 |
-+ KDBUS_HELLO_ACTIVATOR | |
10834 |
-+ KDBUS_HELLO_POLICY_HOLDER | |
10835 |
-+ KDBUS_HELLO_MONITOR, |
10836 |
-+ .argv = argv, |
10837 |
-+ .argc = ARRAY_SIZE(argv), |
10838 |
-+ }; |
10839 |
-+ |
10840 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
10841 |
-+ if (ret < 0) |
10842 |
-+ return ERR_PTR(ret); |
10843 |
-+ if (ret > 0) |
10844 |
-+ return NULL; |
10845 |
-+ |
10846 |
-+ item_name = argv[1].item ? argv[1].item->str : NULL; |
10847 |
-+ |
10848 |
-+ c = kdbus_conn_new(ep, file, cmd, item_name, |
10849 |
-+ argv[2].item ? &argv[2].item->creds : NULL, |
10850 |
-+ argv[3].item ? &argv[3].item->pids : NULL, |
10851 |
-+ argv[4].item ? argv[4].item->str : NULL, |
10852 |
-+ argv[5].item ? argv[5].item->str : NULL); |
10853 |
-+ if (IS_ERR(c)) { |
10854 |
-+ ret = PTR_ERR(c); |
10855 |
-+ c = NULL; |
10856 |
-+ goto exit; |
10857 |
-+ } |
10858 |
-+ |
10859 |
-+ ret = kdbus_conn_connect(c, item_name); |
10860 |
-+ if (ret < 0) |
10861 |
-+ goto exit; |
10862 |
-+ |
10863 |
-+ if (kdbus_conn_is_activator(c) || kdbus_conn_is_policy_holder(c)) { |
10864 |
-+ ret = kdbus_conn_acquire(c); |
10865 |
-+ if (ret < 0) |
10866 |
-+ goto exit; |
10867 |
-+ |
10868 |
-+ ret = kdbus_policy_set(&c->ep->bus->policy_db, args.items, |
10869 |
-+ args.items_size, 1, |
10870 |
-+ kdbus_conn_is_policy_holder(c), c); |
10871 |
-+ kdbus_conn_release(c); |
10872 |
-+ if (ret < 0) |
10873 |
-+ goto exit; |
10874 |
-+ } |
10875 |
-+ |
10876 |
-+ if (copy_to_user(argp, cmd, sizeof(*cmd))) |
10877 |
-+ ret = -EFAULT; |
10878 |
-+ |
10879 |
-+exit: |
10880 |
-+ ret = kdbus_args_clear(&args, ret); |
10881 |
-+ if (ret < 0) { |
10882 |
-+ if (c) { |
10883 |
-+ kdbus_conn_disconnect(c, false); |
10884 |
-+ kdbus_conn_unref(c); |
10885 |
-+ } |
10886 |
-+ return ERR_PTR(ret); |
10887 |
-+ } |
10888 |
-+ return c; |
10889 |
-+} |
10890 |
-+ |
10891 |
-+/** |
10892 |
-+ * kdbus_cmd_byebye_unlocked() - handle KDBUS_CMD_BYEBYE |
10893 |
-+ * @conn: connection to operate on |
10894 |
-+ * @argp: command payload |
10895 |
-+ * |
10896 |
-+ * The caller must not hold any active reference to @conn or this will deadlock. |
10897 |
-+ * |
10898 |
-+ * Return: >=0 on success, negative error code on failure. |
10899 |
-+ */ |
10900 |
-+int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp) |
10901 |
-+{ |
10902 |
-+ struct kdbus_cmd *cmd; |
10903 |
-+ int ret; |
10904 |
-+ |
10905 |
-+ struct kdbus_arg argv[] = { |
10906 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
10907 |
-+ }; |
10908 |
-+ struct kdbus_args args = { |
10909 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
10910 |
-+ .argv = argv, |
10911 |
-+ .argc = ARRAY_SIZE(argv), |
10912 |
-+ }; |
10913 |
-+ |
10914 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
10915 |
-+ return -EOPNOTSUPP; |
10916 |
-+ |
10917 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
10918 |
-+ if (ret != 0) |
10919 |
-+ return ret; |
10920 |
-+ |
10921 |
-+ ret = kdbus_conn_disconnect(conn, true); |
10922 |
-+ return kdbus_args_clear(&args, ret); |
10923 |
-+} |
10924 |
-+ |
10925 |
-+/** |
10926 |
-+ * kdbus_cmd_conn_info() - handle KDBUS_CMD_CONN_INFO |
10927 |
-+ * @conn: connection to operate on |
10928 |
-+ * @argp: command payload |
10929 |
-+ * |
10930 |
-+ * Return: >=0 on success, negative error code on failure. |
10931 |
-+ */ |
10932 |
-+int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp) |
10933 |
-+{ |
10934 |
-+ struct kdbus_meta_conn *conn_meta = NULL; |
10935 |
-+ struct kdbus_pool_slice *slice = NULL; |
10936 |
-+ struct kdbus_name_entry *entry = NULL; |
10937 |
-+ struct kdbus_name_owner *owner = NULL; |
10938 |
-+ struct kdbus_conn *owner_conn = NULL; |
10939 |
-+ struct kdbus_item *meta_items = NULL; |
10940 |
-+ struct kdbus_info info = {}; |
10941 |
-+ struct kdbus_cmd_info *cmd; |
10942 |
-+ struct kdbus_bus *bus = conn->ep->bus; |
10943 |
-+ struct kvec kvec[3]; |
10944 |
-+ size_t meta_size, cnt = 0; |
10945 |
-+ const char *name; |
10946 |
-+ u64 attach_flags, size = 0; |
10947 |
-+ int ret; |
10948 |
-+ |
10949 |
-+ struct kdbus_arg argv[] = { |
10950 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
10951 |
-+ { .type = KDBUS_ITEM_NAME }, |
10952 |
-+ }; |
10953 |
-+ struct kdbus_args args = { |
10954 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
10955 |
-+ .argv = argv, |
10956 |
-+ .argc = ARRAY_SIZE(argv), |
10957 |
-+ }; |
10958 |
-+ |
10959 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
10960 |
-+ if (ret != 0) |
10961 |
-+ return ret; |
10962 |
-+ |
10963 |
-+ /* registry must be held throughout lookup *and* collecting data */ |
10964 |
-+ down_read(&bus->name_registry->rwlock); |
10965 |
-+ |
10966 |
-+ ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags); |
10967 |
-+ if (ret < 0) |
10968 |
-+ goto exit; |
10969 |
-+ |
10970 |
-+ name = argv[1].item ? argv[1].item->str : NULL; |
10971 |
-+ |
10972 |
-+ if (name) { |
10973 |
-+ entry = kdbus_name_lookup_unlocked(bus->name_registry, name); |
10974 |
-+ if (entry) |
10975 |
-+ owner = kdbus_name_get_owner(entry); |
10976 |
-+ if (!owner || |
10977 |
-+ !kdbus_conn_policy_see_name(conn, current_cred(), name) || |
10978 |
-+ (cmd->id != 0 && owner->conn->id != cmd->id)) { |
10979 |
-+ /* pretend a name doesn't exist if you cannot see it */ |
10980 |
-+ ret = -ESRCH; |
10981 |
-+ goto exit; |
10982 |
-+ } |
10983 |
-+ |
10984 |
-+ owner_conn = kdbus_conn_ref(owner->conn); |
10985 |
-+ } else if (cmd->id > 0) { |
10986 |
-+ owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id); |
10987 |
-+ if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(), |
10988 |
-+ owner_conn)) { |
10989 |
-+ /* pretend an id doesn't exist if you cannot see it */ |
10990 |
-+ ret = -ENXIO; |
10991 |
-+ goto exit; |
10992 |
-+ } |
10993 |
-+ } else { |
10994 |
-+ ret = -EINVAL; |
10995 |
-+ goto exit; |
10996 |
-+ } |
10997 |
-+ |
10998 |
-+ attach_flags &= atomic64_read(&owner_conn->attach_flags_send); |
10999 |
-+ |
11000 |
-+ conn_meta = kdbus_meta_conn_new(); |
11001 |
-+ if (IS_ERR(conn_meta)) { |
11002 |
-+ ret = PTR_ERR(conn_meta); |
11003 |
-+ conn_meta = NULL; |
11004 |
-+ goto exit; |
11005 |
-+ } |
11006 |
-+ |
11007 |
-+ ret = kdbus_meta_conn_collect(conn_meta, owner_conn, 0, attach_flags); |
11008 |
-+ if (ret < 0) |
11009 |
-+ goto exit; |
11010 |
-+ |
11011 |
-+ ret = kdbus_meta_emit(owner_conn->meta_proc, owner_conn->meta_fake, |
11012 |
-+ conn_meta, conn, attach_flags, |
11013 |
-+ &meta_items, &meta_size); |
11014 |
-+ if (ret < 0) |
11015 |
-+ goto exit; |
11016 |
-+ |
11017 |
-+ info.id = owner_conn->id; |
11018 |
-+ info.flags = owner_conn->flags; |
11019 |
-+ |
11020 |
-+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size); |
11021 |
-+ if (meta_size > 0) { |
11022 |
-+ kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size); |
11023 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &size); |
11024 |
-+ } |
11025 |
-+ |
11026 |
-+ info.size = size; |
11027 |
-+ |
11028 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
11029 |
-+ if (IS_ERR(slice)) { |
11030 |
-+ ret = PTR_ERR(slice); |
11031 |
-+ slice = NULL; |
11032 |
-+ goto exit; |
11033 |
-+ } |
11034 |
-+ |
11035 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, size); |
11036 |
-+ if (ret < 0) |
11037 |
-+ goto exit; |
11038 |
-+ |
11039 |
-+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size); |
11040 |
-+ |
11041 |
-+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
11042 |
-+ kdbus_member_set_user(&cmd->info_size, argp, |
11043 |
-+ typeof(*cmd), info_size)) { |
11044 |
-+ ret = -EFAULT; |
11045 |
-+ goto exit; |
11046 |
-+ } |
11047 |
-+ |
11048 |
-+ ret = 0; |
11049 |
-+ |
11050 |
-+exit: |
11051 |
-+ up_read(&bus->name_registry->rwlock); |
11052 |
-+ kdbus_pool_slice_release(slice); |
11053 |
-+ kfree(meta_items); |
11054 |
-+ kdbus_meta_conn_unref(conn_meta); |
11055 |
-+ kdbus_conn_unref(owner_conn); |
11056 |
-+ return kdbus_args_clear(&args, ret); |
11057 |
-+} |
11058 |
-+ |
11059 |
-+/** |
11060 |
-+ * kdbus_cmd_update() - handle KDBUS_CMD_UPDATE |
11061 |
-+ * @conn: connection to operate on |
11062 |
-+ * @argp: command payload |
11063 |
-+ * |
11064 |
-+ * Return: >=0 on success, negative error code on failure. |
11065 |
-+ */ |
11066 |
-+int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp) |
11067 |
-+{ |
11068 |
-+ struct kdbus_item *item_policy; |
11069 |
-+ u64 *item_attach_send = NULL; |
11070 |
-+ u64 *item_attach_recv = NULL; |
11071 |
-+ struct kdbus_cmd *cmd; |
11072 |
-+ u64 attach_send; |
11073 |
-+ u64 attach_recv; |
11074 |
-+ int ret; |
11075 |
-+ |
11076 |
-+ struct kdbus_arg argv[] = { |
11077 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11078 |
-+ { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND }, |
11079 |
-+ { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV }, |
11080 |
-+ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
11081 |
-+ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
11082 |
-+ }; |
11083 |
-+ struct kdbus_args args = { |
11084 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11085 |
-+ .argv = argv, |
11086 |
-+ .argc = ARRAY_SIZE(argv), |
11087 |
-+ }; |
11088 |
-+ |
11089 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11090 |
-+ if (ret != 0) |
11091 |
-+ return ret; |
11092 |
-+ |
11093 |
-+ item_attach_send = argv[1].item ? &argv[1].item->data64[0] : NULL; |
11094 |
-+ item_attach_recv = argv[2].item ? &argv[2].item->data64[0] : NULL; |
11095 |
-+ item_policy = argv[3].item ? : argv[4].item; |
11096 |
-+ |
11097 |
-+ if (item_attach_send) { |
11098 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11099 |
-+ !kdbus_conn_is_monitor(conn)) { |
11100 |
-+ ret = -EOPNOTSUPP; |
11101 |
-+ goto exit; |
11102 |
-+ } |
11103 |
-+ |
11104 |
-+ ret = kdbus_sanitize_attach_flags(*item_attach_send, |
11105 |
-+ &attach_send); |
11106 |
-+ if (ret < 0) |
11107 |
-+ goto exit; |
11108 |
-+ } |
11109 |
-+ |
11110 |
-+ if (item_attach_recv) { |
11111 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11112 |
-+ !kdbus_conn_is_monitor(conn) && |
11113 |
-+ !kdbus_conn_is_activator(conn)) { |
11114 |
-+ ret = -EOPNOTSUPP; |
11115 |
-+ goto exit; |
11116 |
-+ } |
11117 |
-+ |
11118 |
-+ ret = kdbus_sanitize_attach_flags(*item_attach_recv, |
11119 |
-+ &attach_recv); |
11120 |
-+ if (ret < 0) |
11121 |
-+ goto exit; |
11122 |
-+ } |
11123 |
-+ |
11124 |
-+ if (item_policy && !kdbus_conn_is_policy_holder(conn)) { |
11125 |
-+ ret = -EOPNOTSUPP; |
11126 |
-+ goto exit; |
11127 |
-+ } |
11128 |
-+ |
11129 |
-+ /* now that we verified the input, update the connection */ |
11130 |
-+ |
11131 |
-+ if (item_policy) { |
11132 |
-+ ret = kdbus_policy_set(&conn->ep->bus->policy_db, cmd->items, |
11133 |
-+ KDBUS_ITEMS_SIZE(cmd, items), |
11134 |
-+ 1, true, conn); |
11135 |
-+ if (ret < 0) |
11136 |
-+ goto exit; |
11137 |
-+ } |
11138 |
-+ |
11139 |
-+ if (item_attach_send) |
11140 |
-+ atomic64_set(&conn->attach_flags_send, attach_send); |
11141 |
-+ |
11142 |
-+ if (item_attach_recv) |
11143 |
-+ atomic64_set(&conn->attach_flags_recv, attach_recv); |
11144 |
-+ |
11145 |
-+exit: |
11146 |
-+ return kdbus_args_clear(&args, ret); |
11147 |
-+} |
11148 |
-+ |
11149 |
-+/** |
11150 |
-+ * kdbus_cmd_send() - handle KDBUS_CMD_SEND |
11151 |
-+ * @conn: connection to operate on |
11152 |
-+ * @f: file this command was called on |
11153 |
-+ * @argp: command payload |
11154 |
-+ * |
11155 |
-+ * Return: >=0 on success, negative error code on failure. |
11156 |
-+ */ |
11157 |
-+int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp) |
11158 |
-+{ |
11159 |
-+ struct kdbus_cmd_send *cmd; |
11160 |
-+ struct kdbus_staging *staging = NULL; |
11161 |
-+ struct kdbus_msg *msg = NULL; |
11162 |
-+ struct file *cancel_fd = NULL; |
11163 |
-+ int ret, ret2; |
11164 |
-+ |
11165 |
-+ /* command arguments */ |
11166 |
-+ struct kdbus_arg argv[] = { |
11167 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11168 |
-+ { .type = KDBUS_ITEM_CANCEL_FD }, |
11169 |
-+ }; |
11170 |
-+ struct kdbus_args args = { |
11171 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11172 |
-+ KDBUS_SEND_SYNC_REPLY, |
11173 |
-+ .argv = argv, |
11174 |
-+ .argc = ARRAY_SIZE(argv), |
11175 |
-+ }; |
11176 |
-+ |
11177 |
-+ /* message arguments */ |
11178 |
-+ struct kdbus_arg msg_argv[] = { |
11179 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11180 |
-+ { .type = KDBUS_ITEM_PAYLOAD_VEC, .multiple = true }, |
11181 |
-+ { .type = KDBUS_ITEM_PAYLOAD_MEMFD, .multiple = true }, |
11182 |
-+ { .type = KDBUS_ITEM_FDS }, |
11183 |
-+ { .type = KDBUS_ITEM_BLOOM_FILTER }, |
11184 |
-+ { .type = KDBUS_ITEM_DST_NAME }, |
11185 |
-+ }; |
11186 |
-+ struct kdbus_args msg_args = { |
11187 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11188 |
-+ KDBUS_MSG_EXPECT_REPLY | |
11189 |
-+ KDBUS_MSG_NO_AUTO_START | |
11190 |
-+ KDBUS_MSG_SIGNAL, |
11191 |
-+ .argv = msg_argv, |
11192 |
-+ .argc = ARRAY_SIZE(msg_argv), |
11193 |
-+ }; |
11194 |
-+ |
11195 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
11196 |
-+ return -EOPNOTSUPP; |
11197 |
-+ |
11198 |
-+ /* make sure to parse both, @cmd and @msg on negotiation */ |
11199 |
-+ |
11200 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11201 |
-+ if (ret < 0) |
11202 |
-+ goto exit; |
11203 |
-+ else if (ret > 0 && !cmd->msg_address) /* negotiation without msg */ |
11204 |
-+ goto exit; |
11205 |
-+ |
11206 |
-+ ret2 = kdbus_args_parse_msg(&msg_args, KDBUS_PTR(cmd->msg_address), |
11207 |
-+ &msg); |
11208 |
-+ if (ret2 < 0) { /* cannot parse message */ |
11209 |
-+ ret = ret2; |
11210 |
-+ goto exit; |
11211 |
-+ } else if (ret2 > 0 && !ret) { /* msg-negot implies cmd-negot */ |
11212 |
-+ ret = -EINVAL; |
11213 |
-+ goto exit; |
11214 |
-+ } else if (ret > 0) { /* negotiation */ |
11215 |
-+ goto exit; |
11216 |
-+ } |
11217 |
-+ |
11218 |
-+ /* here we parsed both, @cmd and @msg, and neither wants negotiation */ |
11219 |
-+ |
11220 |
-+ cmd->reply.return_flags = 0; |
11221 |
-+ kdbus_pool_publish_empty(conn->pool, &cmd->reply.offset, |
11222 |
-+ &cmd->reply.msg_size); |
11223 |
-+ |
11224 |
-+ if (argv[1].item) { |
11225 |
-+ cancel_fd = fget(argv[1].item->fds[0]); |
11226 |
-+ if (!cancel_fd) { |
11227 |
-+ ret = -EBADF; |
11228 |
-+ goto exit; |
11229 |
-+ } |
11230 |
-+ |
11231 |
-+ if (!cancel_fd->f_op->poll) { |
11232 |
-+ ret = -EINVAL; |
11233 |
-+ goto exit; |
11234 |
-+ } |
11235 |
-+ } |
11236 |
-+ |
11237 |
-+ /* patch-in the source of this message */ |
11238 |
-+ if (msg->src_id > 0 && msg->src_id != conn->id) { |
11239 |
-+ ret = -EINVAL; |
11240 |
-+ goto exit; |
11241 |
-+ } |
11242 |
-+ msg->src_id = conn->id; |
11243 |
-+ |
11244 |
-+ staging = kdbus_staging_new_user(conn->ep->bus, cmd, msg); |
11245 |
-+ if (IS_ERR(staging)) { |
11246 |
-+ ret = PTR_ERR(staging); |
11247 |
-+ staging = NULL; |
11248 |
-+ goto exit; |
11249 |
-+ } |
11250 |
-+ |
11251 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST) { |
11252 |
-+ down_read(&conn->ep->bus->name_registry->rwlock); |
11253 |
-+ kdbus_bus_broadcast(conn->ep->bus, conn, staging); |
11254 |
-+ up_read(&conn->ep->bus->name_registry->rwlock); |
11255 |
-+ } else if (cmd->flags & KDBUS_SEND_SYNC_REPLY) { |
11256 |
-+ struct kdbus_reply *r; |
11257 |
-+ ktime_t exp; |
11258 |
-+ |
11259 |
-+ exp = ns_to_ktime(msg->timeout_ns); |
11260 |
-+ r = kdbus_conn_call(conn, staging, exp); |
11261 |
-+ if (IS_ERR(r)) { |
11262 |
-+ ret = PTR_ERR(r); |
11263 |
-+ goto exit; |
11264 |
-+ } |
11265 |
-+ |
11266 |
-+ ret = kdbus_conn_wait_reply(conn, cmd, f, cancel_fd, r, exp); |
11267 |
-+ kdbus_reply_unref(r); |
11268 |
-+ if (ret < 0) |
11269 |
-+ goto exit; |
11270 |
-+ } else if ((msg->flags & KDBUS_MSG_EXPECT_REPLY) || |
11271 |
-+ msg->cookie_reply == 0) { |
11272 |
-+ ret = kdbus_conn_unicast(conn, staging); |
11273 |
-+ if (ret < 0) |
11274 |
-+ goto exit; |
11275 |
-+ } else { |
11276 |
-+ ret = kdbus_conn_reply(conn, staging); |
11277 |
-+ if (ret < 0) |
11278 |
-+ goto exit; |
11279 |
-+ } |
11280 |
-+ |
11281 |
-+ if (kdbus_member_set_user(&cmd->reply, argp, typeof(*cmd), reply)) |
11282 |
-+ ret = -EFAULT; |
11283 |
-+ |
11284 |
-+exit: |
11285 |
-+ if (cancel_fd) |
11286 |
-+ fput(cancel_fd); |
11287 |
-+ kdbus_staging_free(staging); |
11288 |
-+ ret = kdbus_args_clear(&msg_args, ret); |
11289 |
-+ return kdbus_args_clear(&args, ret); |
11290 |
-+} |
11291 |
-+ |
11292 |
-+/** |
11293 |
-+ * kdbus_cmd_recv() - handle KDBUS_CMD_RECV |
11294 |
-+ * @conn: connection to operate on |
11295 |
-+ * @argp: command payload |
11296 |
-+ * |
11297 |
-+ * Return: >=0 on success, negative error code on failure. |
11298 |
-+ */ |
11299 |
-+int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp) |
11300 |
-+{ |
11301 |
-+ struct kdbus_queue_entry *entry; |
11302 |
-+ struct kdbus_cmd_recv *cmd; |
11303 |
-+ int ret; |
11304 |
-+ |
11305 |
-+ struct kdbus_arg argv[] = { |
11306 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11307 |
-+ }; |
11308 |
-+ struct kdbus_args args = { |
11309 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
11310 |
-+ KDBUS_RECV_PEEK | |
11311 |
-+ KDBUS_RECV_DROP | |
11312 |
-+ KDBUS_RECV_USE_PRIORITY, |
11313 |
-+ .argv = argv, |
11314 |
-+ .argc = ARRAY_SIZE(argv), |
11315 |
-+ }; |
11316 |
-+ |
11317 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11318 |
-+ !kdbus_conn_is_monitor(conn) && |
11319 |
-+ !kdbus_conn_is_activator(conn)) |
11320 |
-+ return -EOPNOTSUPP; |
11321 |
-+ |
11322 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11323 |
-+ if (ret != 0) |
11324 |
-+ return ret; |
11325 |
-+ |
11326 |
-+ cmd->dropped_msgs = 0; |
11327 |
-+ cmd->msg.return_flags = 0; |
11328 |
-+ kdbus_pool_publish_empty(conn->pool, &cmd->msg.offset, |
11329 |
-+ &cmd->msg.msg_size); |
11330 |
-+ |
11331 |
-+ /* DROP+priority is not realiably, so prevent it */ |
11332 |
-+ if ((cmd->flags & KDBUS_RECV_DROP) && |
11333 |
-+ (cmd->flags & KDBUS_RECV_USE_PRIORITY)) { |
11334 |
-+ ret = -EINVAL; |
11335 |
-+ goto exit; |
11336 |
-+ } |
11337 |
-+ |
11338 |
-+ mutex_lock(&conn->lock); |
11339 |
-+ |
11340 |
-+ entry = kdbus_queue_peek(&conn->queue, cmd->priority, |
11341 |
-+ cmd->flags & KDBUS_RECV_USE_PRIORITY); |
11342 |
-+ if (!entry) { |
11343 |
-+ mutex_unlock(&conn->lock); |
11344 |
-+ ret = -EAGAIN; |
11345 |
-+ } else if (cmd->flags & KDBUS_RECV_DROP) { |
11346 |
-+ struct kdbus_reply *reply = kdbus_reply_ref(entry->reply); |
11347 |
-+ |
11348 |
-+ kdbus_queue_entry_free(entry); |
11349 |
-+ |
11350 |
-+ mutex_unlock(&conn->lock); |
11351 |
-+ |
11352 |
-+ if (reply) { |
11353 |
-+ mutex_lock(&reply->reply_dst->lock); |
11354 |
-+ if (!list_empty(&reply->entry)) { |
11355 |
-+ kdbus_reply_unlink(reply); |
11356 |
-+ if (reply->sync) |
11357 |
-+ kdbus_sync_reply_wakeup(reply, -EPIPE); |
11358 |
-+ else |
11359 |
-+ kdbus_notify_reply_dead(conn->ep->bus, |
11360 |
-+ reply->reply_dst->id, |
11361 |
-+ reply->cookie); |
11362 |
-+ } |
11363 |
-+ mutex_unlock(&reply->reply_dst->lock); |
11364 |
-+ kdbus_notify_flush(conn->ep->bus); |
11365 |
-+ } |
11366 |
-+ |
11367 |
-+ kdbus_reply_unref(reply); |
11368 |
-+ } else { |
11369 |
-+ bool install_fds; |
11370 |
-+ |
11371 |
-+ /* |
11372 |
-+ * PEEK just returns the location of the next message. Do not |
11373 |
-+ * install FDs nor memfds nor anything else. The only |
11374 |
-+ * information of interest should be the message header and |
11375 |
-+ * metadata. Any FD numbers in the payload is undefined for |
11376 |
-+ * PEEK'ed messages. |
11377 |
-+ * Also make sure to never install fds into a connection that |
11378 |
-+ * has refused to receive any. Ordinary connections will not get |
11379 |
-+ * messages with FDs queued (the receiver will get -ECOMM), but |
11380 |
-+ * eavesdroppers might. |
11381 |
-+ */ |
11382 |
-+ install_fds = (conn->flags & KDBUS_HELLO_ACCEPT_FD) && |
11383 |
-+ !(cmd->flags & KDBUS_RECV_PEEK); |
11384 |
-+ |
11385 |
-+ ret = kdbus_queue_entry_install(entry, |
11386 |
-+ &cmd->msg.return_flags, |
11387 |
-+ install_fds); |
11388 |
-+ if (ret < 0) { |
11389 |
-+ mutex_unlock(&conn->lock); |
11390 |
-+ goto exit; |
11391 |
-+ } |
11392 |
-+ |
11393 |
-+ kdbus_pool_slice_publish(entry->slice, &cmd->msg.offset, |
11394 |
-+ &cmd->msg.msg_size); |
11395 |
-+ |
11396 |
-+ if (!(cmd->flags & KDBUS_RECV_PEEK)) |
11397 |
-+ kdbus_queue_entry_free(entry); |
11398 |
-+ |
11399 |
-+ mutex_unlock(&conn->lock); |
11400 |
-+ } |
11401 |
-+ |
11402 |
-+ cmd->dropped_msgs = atomic_xchg(&conn->lost_count, 0); |
11403 |
-+ if (cmd->dropped_msgs > 0) |
11404 |
-+ cmd->return_flags |= KDBUS_RECV_RETURN_DROPPED_MSGS; |
11405 |
-+ |
11406 |
-+ if (kdbus_member_set_user(&cmd->msg, argp, typeof(*cmd), msg) || |
11407 |
-+ kdbus_member_set_user(&cmd->dropped_msgs, argp, typeof(*cmd), |
11408 |
-+ dropped_msgs)) |
11409 |
-+ ret = -EFAULT; |
11410 |
-+ |
11411 |
-+exit: |
11412 |
-+ return kdbus_args_clear(&args, ret); |
11413 |
-+} |
11414 |
-+ |
11415 |
-+/** |
11416 |
-+ * kdbus_cmd_free() - handle KDBUS_CMD_FREE |
11417 |
-+ * @conn: connection to operate on |
11418 |
-+ * @argp: command payload |
11419 |
-+ * |
11420 |
-+ * Return: >=0 on success, negative error code on failure. |
11421 |
-+ */ |
11422 |
-+int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp) |
11423 |
-+{ |
11424 |
-+ struct kdbus_cmd_free *cmd; |
11425 |
-+ int ret; |
11426 |
-+ |
11427 |
-+ struct kdbus_arg argv[] = { |
11428 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
11429 |
-+ }; |
11430 |
-+ struct kdbus_args args = { |
11431 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
11432 |
-+ .argv = argv, |
11433 |
-+ .argc = ARRAY_SIZE(argv), |
11434 |
-+ }; |
11435 |
-+ |
11436 |
-+ if (!kdbus_conn_is_ordinary(conn) && |
11437 |
-+ !kdbus_conn_is_monitor(conn) && |
11438 |
-+ !kdbus_conn_is_activator(conn)) |
11439 |
-+ return -EOPNOTSUPP; |
11440 |
-+ |
11441 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
11442 |
-+ if (ret != 0) |
11443 |
-+ return ret; |
11444 |
-+ |
11445 |
-+ ret = kdbus_pool_release_offset(conn->pool, cmd->offset); |
11446 |
-+ |
11447 |
-+ return kdbus_args_clear(&args, ret); |
11448 |
-+} |
11449 |
-diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h |
11450 |
-new file mode 100644 |
11451 |
-index 0000000..1ad0820 |
11452 |
---- /dev/null |
11453 |
-+++ b/ipc/kdbus/connection.h |
11454 |
-@@ -0,0 +1,260 @@ |
11455 |
-+/* |
11456 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
11457 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
11458 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
11459 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
11460 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
11461 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
11462 |
-+ * |
11463 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
11464 |
-+ * the terms of the GNU Lesser General Public License as published by the |
11465 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
11466 |
-+ * your option) any later version. |
11467 |
-+ */ |
11468 |
-+ |
11469 |
-+#ifndef __KDBUS_CONNECTION_H |
11470 |
-+#define __KDBUS_CONNECTION_H |
11471 |
-+ |
11472 |
-+#include <linux/atomic.h> |
11473 |
-+#include <linux/kref.h> |
11474 |
-+#include <linux/lockdep.h> |
11475 |
-+#include <linux/path.h> |
11476 |
-+ |
11477 |
-+#include "limits.h" |
11478 |
-+#include "metadata.h" |
11479 |
-+#include "pool.h" |
11480 |
-+#include "queue.h" |
11481 |
-+#include "util.h" |
11482 |
-+ |
11483 |
-+#define KDBUS_HELLO_SPECIAL_CONN (KDBUS_HELLO_ACTIVATOR | \ |
11484 |
-+ KDBUS_HELLO_POLICY_HOLDER | \ |
11485 |
-+ KDBUS_HELLO_MONITOR) |
11486 |
-+ |
11487 |
-+struct kdbus_name_entry; |
11488 |
-+struct kdbus_quota; |
11489 |
-+struct kdbus_staging; |
11490 |
-+ |
11491 |
-+/** |
11492 |
-+ * struct kdbus_conn - connection to a bus |
11493 |
-+ * @kref: Reference count |
11494 |
-+ * @active: Active references to the connection |
11495 |
-+ * @id: Connection ID |
11496 |
-+ * @flags: KDBUS_HELLO_* flags |
11497 |
-+ * @attach_flags_send: KDBUS_ATTACH_* flags for sending |
11498 |
-+ * @attach_flags_recv: KDBUS_ATTACH_* flags for receiving |
11499 |
-+ * @description: Human-readable connection description, used for |
11500 |
-+ * debugging. This field is only set when the |
11501 |
-+ * connection is created. |
11502 |
-+ * @ep: The endpoint this connection belongs to |
11503 |
-+ * @lock: Connection data lock |
11504 |
-+ * @hentry: Entry in ID <-> connection map |
11505 |
-+ * @ep_entry: Entry in endpoint |
11506 |
-+ * @monitor_entry: Entry in monitor, if the connection is a monitor |
11507 |
-+ * @reply_list: List of connections this connection should |
11508 |
-+ * reply to |
11509 |
-+ * @work: Delayed work to handle timeouts |
11510 |
-+ * activator for |
11511 |
-+ * @match_db: Subscription filter to broadcast messages |
11512 |
-+ * @meta_proc: Process metadata of connection creator, or NULL |
11513 |
-+ * @meta_fake: Faked metadata, or NULL |
11514 |
-+ * @pool: The user's buffer to receive messages |
11515 |
-+ * @user: Owner of the connection |
11516 |
-+ * @cred: The credentials of the connection at creation time |
11517 |
-+ * @pid: Pid at creation time |
11518 |
-+ * @root_path: Root path at creation time |
11519 |
-+ * @request_count: Number of pending requests issued by this |
11520 |
-+ * connection that are waiting for replies from |
11521 |
-+ * other peers |
11522 |
-+ * @lost_count: Number of lost broadcast messages |
11523 |
-+ * @wait: Wake up this endpoint |
11524 |
-+ * @queue: The message queue associated with this connection |
11525 |
-+ * @quota: Array of per-user quota indexed by user->id |
11526 |
-+ * @n_quota: Number of elements in quota array |
11527 |
-+ * @names_list: List of well-known names |
11528 |
-+ * @name_count: Number of owned well-known names |
11529 |
-+ * @privileged: Whether this connection is privileged on the domain |
11530 |
-+ * @owner: Owned by the same user as the bus owner |
11531 |
-+ */ |
11532 |
-+struct kdbus_conn { |
11533 |
-+ struct kref kref; |
11534 |
-+ atomic_t active; |
11535 |
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC |
11536 |
-+ struct lockdep_map dep_map; |
11537 |
-+#endif |
11538 |
-+ u64 id; |
11539 |
-+ u64 flags; |
11540 |
-+ atomic64_t attach_flags_send; |
11541 |
-+ atomic64_t attach_flags_recv; |
11542 |
-+ const char *description; |
11543 |
-+ struct kdbus_ep *ep; |
11544 |
-+ struct mutex lock; |
11545 |
-+ struct hlist_node hentry; |
11546 |
-+ struct list_head ep_entry; |
11547 |
-+ struct list_head monitor_entry; |
11548 |
-+ struct list_head reply_list; |
11549 |
-+ struct delayed_work work; |
11550 |
-+ struct kdbus_match_db *match_db; |
11551 |
-+ struct kdbus_meta_proc *meta_proc; |
11552 |
-+ struct kdbus_meta_fake *meta_fake; |
11553 |
-+ struct kdbus_pool *pool; |
11554 |
-+ struct kdbus_user *user; |
11555 |
-+ const struct cred *cred; |
11556 |
-+ struct pid *pid; |
11557 |
-+ struct path root_path; |
11558 |
-+ atomic_t request_count; |
11559 |
-+ atomic_t lost_count; |
11560 |
-+ wait_queue_head_t wait; |
11561 |
-+ struct kdbus_queue queue; |
11562 |
-+ |
11563 |
-+ struct kdbus_quota *quota; |
11564 |
-+ unsigned int n_quota; |
11565 |
-+ |
11566 |
-+ /* protected by registry->rwlock */ |
11567 |
-+ struct list_head names_list; |
11568 |
-+ unsigned int name_count; |
11569 |
-+ |
11570 |
-+ bool privileged:1; |
11571 |
-+ bool owner:1; |
11572 |
-+}; |
11573 |
-+ |
11574 |
-+struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn); |
11575 |
-+struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn); |
11576 |
-+bool kdbus_conn_active(const struct kdbus_conn *conn); |
11577 |
-+int kdbus_conn_acquire(struct kdbus_conn *conn); |
11578 |
-+void kdbus_conn_release(struct kdbus_conn *conn); |
11579 |
-+int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty); |
11580 |
-+bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name); |
11581 |
-+int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, |
11582 |
-+ size_t memory, size_t fds); |
11583 |
-+void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, |
11584 |
-+ size_t memory, size_t fds); |
11585 |
-+void kdbus_conn_lost_message(struct kdbus_conn *c); |
11586 |
-+int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, |
11587 |
-+ struct kdbus_conn *conn_dst, |
11588 |
-+ struct kdbus_staging *staging, |
11589 |
-+ struct kdbus_reply *reply, |
11590 |
-+ const struct kdbus_name_entry *name); |
11591 |
-+void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, |
11592 |
-+ struct kdbus_conn *conn_src, |
11593 |
-+ u64 name_id); |
11594 |
-+ |
11595 |
-+/* policy */ |
11596 |
-+bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, |
11597 |
-+ const struct cred *conn_creds, |
11598 |
-+ const char *name); |
11599 |
-+bool kdbus_conn_policy_talk(struct kdbus_conn *conn, |
11600 |
-+ const struct cred *conn_creds, |
11601 |
-+ struct kdbus_conn *to); |
11602 |
-+bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, |
11603 |
-+ const struct cred *curr_creds, |
11604 |
-+ const char *name); |
11605 |
-+bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, |
11606 |
-+ const struct cred *curr_creds, |
11607 |
-+ const struct kdbus_msg *msg); |
11608 |
-+ |
11609 |
-+/* command dispatcher */ |
11610 |
-+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file, |
11611 |
-+ void __user *argp); |
11612 |
-+int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp); |
11613 |
-+int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp); |
11614 |
-+int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp); |
11615 |
-+int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp); |
11616 |
-+int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp); |
11617 |
-+int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp); |
11618 |
-+ |
11619 |
-+/** |
11620 |
-+ * kdbus_conn_is_ordinary() - Check if connection is ordinary |
11621 |
-+ * @conn: The connection to check |
11622 |
-+ * |
11623 |
-+ * Return: Non-zero if the connection is an ordinary connection |
11624 |
-+ */ |
11625 |
-+static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn) |
11626 |
-+{ |
11627 |
-+ return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN); |
11628 |
-+} |
11629 |
-+ |
11630 |
-+/** |
11631 |
-+ * kdbus_conn_is_activator() - Check if connection is an activator |
11632 |
-+ * @conn: The connection to check |
11633 |
-+ * |
11634 |
-+ * Return: Non-zero if the connection is an activator |
11635 |
-+ */ |
11636 |
-+static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn) |
11637 |
-+{ |
11638 |
-+ return conn->flags & KDBUS_HELLO_ACTIVATOR; |
11639 |
-+} |
11640 |
-+ |
11641 |
-+/** |
11642 |
-+ * kdbus_conn_is_policy_holder() - Check if connection is a policy holder |
11643 |
-+ * @conn: The connection to check |
11644 |
-+ * |
11645 |
-+ * Return: Non-zero if the connection is a policy holder |
11646 |
-+ */ |
11647 |
-+static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn) |
11648 |
-+{ |
11649 |
-+ return conn->flags & KDBUS_HELLO_POLICY_HOLDER; |
11650 |
-+} |
11651 |
-+ |
11652 |
-+/** |
11653 |
-+ * kdbus_conn_is_monitor() - Check if connection is a monitor |
11654 |
-+ * @conn: The connection to check |
11655 |
-+ * |
11656 |
-+ * Return: Non-zero if the connection is a monitor |
11657 |
-+ */ |
11658 |
-+static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn) |
11659 |
-+{ |
11660 |
-+ return conn->flags & KDBUS_HELLO_MONITOR; |
11661 |
-+} |
11662 |
-+ |
11663 |
-+/** |
11664 |
-+ * kdbus_conn_lock2() - Lock two connections |
11665 |
-+ * @a: connection A to lock or NULL |
11666 |
-+ * @b: connection B to lock or NULL |
11667 |
-+ * |
11668 |
-+ * Lock two connections at once. As we need to have a stable locking order, we |
11669 |
-+ * always lock the connection with lower memory address first. |
11670 |
-+ */ |
11671 |
-+static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b) |
11672 |
-+{ |
11673 |
-+ if (a < b) { |
11674 |
-+ if (a) |
11675 |
-+ mutex_lock(&a->lock); |
11676 |
-+ if (b && b != a) |
11677 |
-+ mutex_lock_nested(&b->lock, !!a); |
11678 |
-+ } else { |
11679 |
-+ if (b) |
11680 |
-+ mutex_lock(&b->lock); |
11681 |
-+ if (a && a != b) |
11682 |
-+ mutex_lock_nested(&a->lock, !!b); |
11683 |
-+ } |
11684 |
-+} |
11685 |
-+ |
11686 |
-+/** |
11687 |
-+ * kdbus_conn_unlock2() - Unlock two connections |
11688 |
-+ * @a: connection A to unlock or NULL |
11689 |
-+ * @b: connection B to unlock or NULL |
11690 |
-+ * |
11691 |
-+ * Unlock two connections at once. See kdbus_conn_lock2(). |
11692 |
-+ */ |
11693 |
-+static inline void kdbus_conn_unlock2(struct kdbus_conn *a, |
11694 |
-+ struct kdbus_conn *b) |
11695 |
-+{ |
11696 |
-+ if (a) |
11697 |
-+ mutex_unlock(&a->lock); |
11698 |
-+ if (b && b != a) |
11699 |
-+ mutex_unlock(&b->lock); |
11700 |
-+} |
11701 |
-+ |
11702 |
-+/** |
11703 |
-+ * kdbus_conn_assert_active() - lockdep assert on active lock |
11704 |
-+ * @conn: connection that shall be active |
11705 |
-+ * |
11706 |
-+ * This verifies via lockdep that the caller holds an active reference to the |
11707 |
-+ * given connection. |
11708 |
-+ */ |
11709 |
-+static inline void kdbus_conn_assert_active(struct kdbus_conn *conn) |
11710 |
-+{ |
11711 |
-+ lockdep_assert_held(conn); |
11712 |
-+} |
11713 |
-+ |
11714 |
-+#endif |
11715 |
-diff --git a/ipc/kdbus/domain.c b/ipc/kdbus/domain.c |
11716 |
-new file mode 100644 |
11717 |
-index 0000000..ac9f760 |
11718 |
---- /dev/null |
11719 |
-+++ b/ipc/kdbus/domain.c |
11720 |
-@@ -0,0 +1,296 @@ |
11721 |
-+/* |
11722 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
11723 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
11724 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
11725 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
11726 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
11727 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
11728 |
-+ * |
11729 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
11730 |
-+ * the terms of the GNU Lesser General Public License as published by the |
11731 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
11732 |
-+ * your option) any later version. |
11733 |
-+ */ |
11734 |
-+ |
11735 |
-+#include <linux/fs.h> |
11736 |
-+#include <linux/idr.h> |
11737 |
-+#include <linux/init.h> |
11738 |
-+#include <linux/module.h> |
11739 |
-+#include <linux/sched.h> |
11740 |
-+#include <linux/sizes.h> |
11741 |
-+#include <linux/slab.h> |
11742 |
-+#include <linux/uaccess.h> |
11743 |
-+ |
11744 |
-+#include "bus.h" |
11745 |
-+#include "domain.h" |
11746 |
-+#include "handle.h" |
11747 |
-+#include "item.h" |
11748 |
-+#include "limits.h" |
11749 |
-+#include "util.h" |
11750 |
-+ |
11751 |
-+static void kdbus_domain_control_free(struct kdbus_node *node) |
11752 |
-+{ |
11753 |
-+ kfree(node); |
11754 |
-+} |
11755 |
-+ |
11756 |
-+static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain, |
11757 |
-+ unsigned int access) |
11758 |
-+{ |
11759 |
-+ struct kdbus_node *node; |
11760 |
-+ int ret; |
11761 |
-+ |
11762 |
-+ node = kzalloc(sizeof(*node), GFP_KERNEL); |
11763 |
-+ if (!node) |
11764 |
-+ return ERR_PTR(-ENOMEM); |
11765 |
-+ |
11766 |
-+ kdbus_node_init(node, KDBUS_NODE_CONTROL); |
11767 |
-+ |
11768 |
-+ node->free_cb = kdbus_domain_control_free; |
11769 |
-+ node->mode = domain->node.mode; |
11770 |
-+ node->mode = S_IRUSR | S_IWUSR; |
11771 |
-+ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
11772 |
-+ node->mode |= S_IRGRP | S_IWGRP; |
11773 |
-+ if (access & KDBUS_MAKE_ACCESS_WORLD) |
11774 |
-+ node->mode |= S_IROTH | S_IWOTH; |
11775 |
-+ |
11776 |
-+ ret = kdbus_node_link(node, &domain->node, "control"); |
11777 |
-+ if (ret < 0) |
11778 |
-+ goto exit_free; |
11779 |
-+ |
11780 |
-+ return node; |
11781 |
-+ |
11782 |
-+exit_free: |
11783 |
-+ kdbus_node_deactivate(node); |
11784 |
-+ kdbus_node_unref(node); |
11785 |
-+ return ERR_PTR(ret); |
11786 |
-+} |
11787 |
-+ |
11788 |
-+static void kdbus_domain_free(struct kdbus_node *node) |
11789 |
-+{ |
11790 |
-+ struct kdbus_domain *domain = |
11791 |
-+ container_of(node, struct kdbus_domain, node); |
11792 |
-+ |
11793 |
-+ put_user_ns(domain->user_namespace); |
11794 |
-+ ida_destroy(&domain->user_ida); |
11795 |
-+ idr_destroy(&domain->user_idr); |
11796 |
-+ kfree(domain); |
11797 |
-+} |
11798 |
-+ |
11799 |
-+/** |
11800 |
-+ * kdbus_domain_new() - create a new domain |
11801 |
-+ * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*) |
11802 |
-+ * |
11803 |
-+ * Return: a new kdbus_domain on success, ERR_PTR on failure |
11804 |
-+ */ |
11805 |
-+struct kdbus_domain *kdbus_domain_new(unsigned int access) |
11806 |
-+{ |
11807 |
-+ struct kdbus_domain *d; |
11808 |
-+ int ret; |
11809 |
-+ |
11810 |
-+ d = kzalloc(sizeof(*d), GFP_KERNEL); |
11811 |
-+ if (!d) |
11812 |
-+ return ERR_PTR(-ENOMEM); |
11813 |
-+ |
11814 |
-+ kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN); |
11815 |
-+ |
11816 |
-+ d->node.free_cb = kdbus_domain_free; |
11817 |
-+ d->node.mode = S_IRUSR | S_IXUSR; |
11818 |
-+ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
11819 |
-+ d->node.mode |= S_IRGRP | S_IXGRP; |
11820 |
-+ if (access & KDBUS_MAKE_ACCESS_WORLD) |
11821 |
-+ d->node.mode |= S_IROTH | S_IXOTH; |
11822 |
-+ |
11823 |
-+ mutex_init(&d->lock); |
11824 |
-+ idr_init(&d->user_idr); |
11825 |
-+ ida_init(&d->user_ida); |
11826 |
-+ |
11827 |
-+ /* Pin user namespace so we can guarantee domain-unique bus * names. */ |
11828 |
-+ d->user_namespace = get_user_ns(current_user_ns()); |
11829 |
-+ |
11830 |
-+ ret = kdbus_node_link(&d->node, NULL, NULL); |
11831 |
-+ if (ret < 0) |
11832 |
-+ goto exit_unref; |
11833 |
-+ |
11834 |
-+ return d; |
11835 |
-+ |
11836 |
-+exit_unref: |
11837 |
-+ kdbus_node_deactivate(&d->node); |
11838 |
-+ kdbus_node_unref(&d->node); |
11839 |
-+ return ERR_PTR(ret); |
11840 |
-+} |
11841 |
-+ |
11842 |
-+/** |
11843 |
-+ * kdbus_domain_ref() - take a domain reference |
11844 |
-+ * @domain: Domain |
11845 |
-+ * |
11846 |
-+ * Return: the domain itself |
11847 |
-+ */ |
11848 |
-+struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain) |
11849 |
-+{ |
11850 |
-+ if (domain) |
11851 |
-+ kdbus_node_ref(&domain->node); |
11852 |
-+ return domain; |
11853 |
-+} |
11854 |
-+ |
11855 |
-+/** |
11856 |
-+ * kdbus_domain_unref() - drop a domain reference |
11857 |
-+ * @domain: Domain |
11858 |
-+ * |
11859 |
-+ * When the last reference is dropped, the domain internal structure |
11860 |
-+ * is freed. |
11861 |
-+ * |
11862 |
-+ * Return: NULL |
11863 |
-+ */ |
11864 |
-+struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain) |
11865 |
-+{ |
11866 |
-+ if (domain) |
11867 |
-+ kdbus_node_unref(&domain->node); |
11868 |
-+ return NULL; |
11869 |
-+} |
11870 |
-+ |
11871 |
-+/** |
11872 |
-+ * kdbus_domain_populate() - populate static domain nodes |
11873 |
-+ * @domain: domain to populate |
11874 |
-+ * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes |
11875 |
-+ * |
11876 |
-+ * Allocate and activate static sub-nodes of the given domain. This will fail if |
11877 |
-+ * you call it on a non-active node or if the domain was already populated. |
11878 |
-+ * |
11879 |
-+ * Return: 0 on success, negative error code on failure. |
11880 |
-+ */ |
11881 |
-+int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access) |
11882 |
-+{ |
11883 |
-+ struct kdbus_node *control; |
11884 |
-+ |
11885 |
-+ /* |
11886 |
-+ * Create a control-node for this domain. We drop our own reference |
11887 |
-+ * immediately, effectively causing the node to be deactivated and |
11888 |
-+ * released when the parent domain is. |
11889 |
-+ */ |
11890 |
-+ control = kdbus_domain_control_new(domain, access); |
11891 |
-+ if (IS_ERR(control)) |
11892 |
-+ return PTR_ERR(control); |
11893 |
-+ |
11894 |
-+ kdbus_node_activate(control); |
11895 |
-+ kdbus_node_unref(control); |
11896 |
-+ return 0; |
11897 |
-+} |
11898 |
-+ |
11899 |
-+/** |
11900 |
-+ * kdbus_user_lookup() - lookup a kdbus_user object |
11901 |
-+ * @domain: domain of the user |
11902 |
-+ * @uid: uid of the user; INVALID_UID for an anon user |
11903 |
-+ * |
11904 |
-+ * Lookup the kdbus user accounting object for the given domain. If INVALID_UID |
11905 |
-+ * is passed, a new anonymous user is created which is private to the caller. |
11906 |
-+ * |
11907 |
-+ * Return: The user object is returned, ERR_PTR on failure. |
11908 |
-+ */ |
11909 |
-+struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid) |
11910 |
-+{ |
11911 |
-+ struct kdbus_user *u = NULL, *old = NULL; |
11912 |
-+ int ret; |
11913 |
-+ |
11914 |
-+ mutex_lock(&domain->lock); |
11915 |
-+ |
11916 |
-+ if (uid_valid(uid)) { |
11917 |
-+ old = idr_find(&domain->user_idr, __kuid_val(uid)); |
11918 |
-+ /* |
11919 |
-+ * If the object is about to be destroyed, ignore it and |
11920 |
-+ * replace the slot in the IDR later on. |
11921 |
-+ */ |
11922 |
-+ if (old && kref_get_unless_zero(&old->kref)) { |
11923 |
-+ mutex_unlock(&domain->lock); |
11924 |
-+ return old; |
11925 |
-+ } |
11926 |
-+ } |
11927 |
-+ |
11928 |
-+ u = kzalloc(sizeof(*u), GFP_KERNEL); |
11929 |
-+ if (!u) { |
11930 |
-+ ret = -ENOMEM; |
11931 |
-+ goto exit; |
11932 |
-+ } |
11933 |
-+ |
11934 |
-+ kref_init(&u->kref); |
11935 |
-+ u->domain = kdbus_domain_ref(domain); |
11936 |
-+ u->uid = uid; |
11937 |
-+ atomic_set(&u->buses, 0); |
11938 |
-+ atomic_set(&u->connections, 0); |
11939 |
-+ |
11940 |
-+ if (uid_valid(uid)) { |
11941 |
-+ if (old) { |
11942 |
-+ idr_replace(&domain->user_idr, u, __kuid_val(uid)); |
11943 |
-+ old->uid = INVALID_UID; /* mark old as removed */ |
11944 |
-+ } else { |
11945 |
-+ ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid), |
11946 |
-+ __kuid_val(uid) + 1, GFP_KERNEL); |
11947 |
-+ if (ret < 0) |
11948 |
-+ goto exit; |
11949 |
-+ } |
11950 |
-+ } |
11951 |
-+ |
11952 |
-+ /* |
11953 |
-+ * Allocate the smallest possible index for this user; used |
11954 |
-+ * in arrays for accounting user quota in receiver queues. |
11955 |
-+ */ |
11956 |
-+ ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL); |
11957 |
-+ if (ret < 0) |
11958 |
-+ goto exit; |
11959 |
-+ |
11960 |
-+ u->id = ret; |
11961 |
-+ mutex_unlock(&domain->lock); |
11962 |
-+ return u; |
11963 |
-+ |
11964 |
-+exit: |
11965 |
-+ if (u) { |
11966 |
-+ if (uid_valid(u->uid)) |
11967 |
-+ idr_remove(&domain->user_idr, __kuid_val(u->uid)); |
11968 |
-+ kdbus_domain_unref(u->domain); |
11969 |
-+ kfree(u); |
11970 |
-+ } |
11971 |
-+ mutex_unlock(&domain->lock); |
11972 |
-+ return ERR_PTR(ret); |
11973 |
-+} |
11974 |
-+ |
11975 |
-+static void __kdbus_user_free(struct kref *kref) |
11976 |
-+{ |
11977 |
-+ struct kdbus_user *user = container_of(kref, struct kdbus_user, kref); |
11978 |
-+ |
11979 |
-+ WARN_ON(atomic_read(&user->buses) > 0); |
11980 |
-+ WARN_ON(atomic_read(&user->connections) > 0); |
11981 |
-+ |
11982 |
-+ mutex_lock(&user->domain->lock); |
11983 |
-+ ida_simple_remove(&user->domain->user_ida, user->id); |
11984 |
-+ if (uid_valid(user->uid)) |
11985 |
-+ idr_remove(&user->domain->user_idr, __kuid_val(user->uid)); |
11986 |
-+ mutex_unlock(&user->domain->lock); |
11987 |
-+ |
11988 |
-+ kdbus_domain_unref(user->domain); |
11989 |
-+ kfree(user); |
11990 |
-+} |
11991 |
-+ |
11992 |
-+/** |
11993 |
-+ * kdbus_user_ref() - take a user reference |
11994 |
-+ * @u: User |
11995 |
-+ * |
11996 |
-+ * Return: @u is returned |
11997 |
-+ */ |
11998 |
-+struct kdbus_user *kdbus_user_ref(struct kdbus_user *u) |
11999 |
-+{ |
12000 |
-+ if (u) |
12001 |
-+ kref_get(&u->kref); |
12002 |
-+ return u; |
12003 |
-+} |
12004 |
-+ |
12005 |
-+/** |
12006 |
-+ * kdbus_user_unref() - drop a user reference |
12007 |
-+ * @u: User |
12008 |
-+ * |
12009 |
-+ * Return: NULL |
12010 |
-+ */ |
12011 |
-+struct kdbus_user *kdbus_user_unref(struct kdbus_user *u) |
12012 |
-+{ |
12013 |
-+ if (u) |
12014 |
-+ kref_put(&u->kref, __kdbus_user_free); |
12015 |
-+ return NULL; |
12016 |
-+} |
12017 |
-diff --git a/ipc/kdbus/domain.h b/ipc/kdbus/domain.h |
12018 |
-new file mode 100644 |
12019 |
-index 0000000..447a2bd |
12020 |
---- /dev/null |
12021 |
-+++ b/ipc/kdbus/domain.h |
12022 |
-@@ -0,0 +1,77 @@ |
12023 |
-+/* |
12024 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12025 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12026 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12027 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12028 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12029 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12030 |
-+ * |
12031 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12032 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12033 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12034 |
-+ * your option) any later version. |
12035 |
-+ */ |
12036 |
-+ |
12037 |
-+#ifndef __KDBUS_DOMAIN_H |
12038 |
-+#define __KDBUS_DOMAIN_H |
12039 |
-+ |
12040 |
-+#include <linux/fs.h> |
12041 |
-+#include <linux/idr.h> |
12042 |
-+#include <linux/kref.h> |
12043 |
-+#include <linux/user_namespace.h> |
12044 |
-+ |
12045 |
-+#include "node.h" |
12046 |
-+ |
12047 |
-+/** |
12048 |
-+ * struct kdbus_domain - domain for buses |
12049 |
-+ * @node: Underlying API node |
12050 |
-+ * @lock: Domain data lock |
12051 |
-+ * @last_id: Last used object id |
12052 |
-+ * @user_idr: Set of all users indexed by UID |
12053 |
-+ * @user_ida: Set of all users to compute small indices |
12054 |
-+ * @user_namespace: User namespace, pinned at creation time |
12055 |
-+ * @dentry: Root dentry of VFS mount (don't use outside of kdbusfs) |
12056 |
-+ */ |
12057 |
-+struct kdbus_domain { |
12058 |
-+ struct kdbus_node node; |
12059 |
-+ struct mutex lock; |
12060 |
-+ atomic64_t last_id; |
12061 |
-+ struct idr user_idr; |
12062 |
-+ struct ida user_ida; |
12063 |
-+ struct user_namespace *user_namespace; |
12064 |
-+ struct dentry *dentry; |
12065 |
-+}; |
12066 |
-+ |
12067 |
-+/** |
12068 |
-+ * struct kdbus_user - resource accounting for users |
12069 |
-+ * @kref: Reference counter |
12070 |
-+ * @domain: Domain of the user |
12071 |
-+ * @id: Index of this user |
12072 |
-+ * @uid: UID of the user |
12073 |
-+ * @buses: Number of buses the user has created |
12074 |
-+ * @connections: Number of connections the user has created |
12075 |
-+ */ |
12076 |
-+struct kdbus_user { |
12077 |
-+ struct kref kref; |
12078 |
-+ struct kdbus_domain *domain; |
12079 |
-+ unsigned int id; |
12080 |
-+ kuid_t uid; |
12081 |
-+ atomic_t buses; |
12082 |
-+ atomic_t connections; |
12083 |
-+}; |
12084 |
-+ |
12085 |
-+#define kdbus_domain_from_node(_node) \ |
12086 |
-+ container_of((_node), struct kdbus_domain, node) |
12087 |
-+ |
12088 |
-+struct kdbus_domain *kdbus_domain_new(unsigned int access); |
12089 |
-+struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain); |
12090 |
-+struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain); |
12091 |
-+int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access); |
12092 |
-+ |
12093 |
-+#define KDBUS_USER_KERNEL_ID 0 /* ID 0 is reserved for kernel accounting */ |
12094 |
-+ |
12095 |
-+struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid); |
12096 |
-+struct kdbus_user *kdbus_user_ref(struct kdbus_user *u); |
12097 |
-+struct kdbus_user *kdbus_user_unref(struct kdbus_user *u); |
12098 |
-+ |
12099 |
-+#endif |
12100 |
-diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c |
12101 |
-new file mode 100644 |
12102 |
-index 0000000..44e7a20 |
12103 |
---- /dev/null |
12104 |
-+++ b/ipc/kdbus/endpoint.c |
12105 |
-@@ -0,0 +1,303 @@ |
12106 |
-+/* |
12107 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12108 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12109 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12110 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12111 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12112 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12113 |
-+ * |
12114 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12115 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12116 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12117 |
-+ * your option) any later version. |
12118 |
-+ */ |
12119 |
-+ |
12120 |
-+#include <linux/fs.h> |
12121 |
-+#include <linux/idr.h> |
12122 |
-+#include <linux/init.h> |
12123 |
-+#include <linux/module.h> |
12124 |
-+#include <linux/sched.h> |
12125 |
-+#include <linux/sizes.h> |
12126 |
-+#include <linux/slab.h> |
12127 |
-+#include <linux/uaccess.h> |
12128 |
-+#include <linux/uio.h> |
12129 |
-+ |
12130 |
-+#include "bus.h" |
12131 |
-+#include "connection.h" |
12132 |
-+#include "domain.h" |
12133 |
-+#include "endpoint.h" |
12134 |
-+#include "handle.h" |
12135 |
-+#include "item.h" |
12136 |
-+#include "message.h" |
12137 |
-+#include "policy.h" |
12138 |
-+ |
12139 |
-+static void kdbus_ep_free(struct kdbus_node *node) |
12140 |
-+{ |
12141 |
-+ struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); |
12142 |
-+ |
12143 |
-+ WARN_ON(!list_empty(&ep->conn_list)); |
12144 |
-+ |
12145 |
-+ kdbus_policy_db_clear(&ep->policy_db); |
12146 |
-+ kdbus_bus_unref(ep->bus); |
12147 |
-+ kdbus_user_unref(ep->user); |
12148 |
-+ kfree(ep); |
12149 |
-+} |
12150 |
-+ |
12151 |
-+static void kdbus_ep_release(struct kdbus_node *node, bool was_active) |
12152 |
-+{ |
12153 |
-+ struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); |
12154 |
-+ |
12155 |
-+ /* disconnect all connections to this endpoint */ |
12156 |
-+ for (;;) { |
12157 |
-+ struct kdbus_conn *conn; |
12158 |
-+ |
12159 |
-+ mutex_lock(&ep->lock); |
12160 |
-+ conn = list_first_entry_or_null(&ep->conn_list, |
12161 |
-+ struct kdbus_conn, |
12162 |
-+ ep_entry); |
12163 |
-+ if (!conn) { |
12164 |
-+ mutex_unlock(&ep->lock); |
12165 |
-+ break; |
12166 |
-+ } |
12167 |
-+ |
12168 |
-+ /* take reference, release lock, disconnect without lock */ |
12169 |
-+ kdbus_conn_ref(conn); |
12170 |
-+ mutex_unlock(&ep->lock); |
12171 |
-+ |
12172 |
-+ kdbus_conn_disconnect(conn, false); |
12173 |
-+ kdbus_conn_unref(conn); |
12174 |
-+ } |
12175 |
-+} |
12176 |
-+ |
12177 |
-+/** |
12178 |
-+ * kdbus_ep_new() - create a new endpoint |
12179 |
-+ * @bus: The bus this endpoint will be created for |
12180 |
-+ * @name: The name of the endpoint |
12181 |
-+ * @access: The access flags for this node (KDBUS_MAKE_ACCESS_*) |
12182 |
-+ * @uid: The uid of the node |
12183 |
-+ * @gid: The gid of the node |
12184 |
-+ * @is_custom: Whether this is a custom endpoint |
12185 |
-+ * |
12186 |
-+ * This function will create a new endpoint with the given |
12187 |
-+ * name and properties for a given bus. |
12188 |
-+ * |
12189 |
-+ * Return: a new kdbus_ep on success, ERR_PTR on failure. |
12190 |
-+ */ |
12191 |
-+struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, |
12192 |
-+ unsigned int access, kuid_t uid, kgid_t gid, |
12193 |
-+ bool is_custom) |
12194 |
-+{ |
12195 |
-+ struct kdbus_ep *e; |
12196 |
-+ int ret; |
12197 |
-+ |
12198 |
-+ /* |
12199 |
-+ * Validate only custom endpoints names, default endpoints |
12200 |
-+ * with a "bus" name are created when the bus is created |
12201 |
-+ */ |
12202 |
-+ if (is_custom) { |
12203 |
-+ ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace, |
12204 |
-+ uid); |
12205 |
-+ if (ret < 0) |
12206 |
-+ return ERR_PTR(ret); |
12207 |
-+ } |
12208 |
-+ |
12209 |
-+ e = kzalloc(sizeof(*e), GFP_KERNEL); |
12210 |
-+ if (!e) |
12211 |
-+ return ERR_PTR(-ENOMEM); |
12212 |
-+ |
12213 |
-+ kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT); |
12214 |
-+ |
12215 |
-+ e->node.free_cb = kdbus_ep_free; |
12216 |
-+ e->node.release_cb = kdbus_ep_release; |
12217 |
-+ e->node.uid = uid; |
12218 |
-+ e->node.gid = gid; |
12219 |
-+ e->node.mode = S_IRUSR | S_IWUSR; |
12220 |
-+ if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) |
12221 |
-+ e->node.mode |= S_IRGRP | S_IWGRP; |
12222 |
-+ if (access & KDBUS_MAKE_ACCESS_WORLD) |
12223 |
-+ e->node.mode |= S_IROTH | S_IWOTH; |
12224 |
-+ |
12225 |
-+ mutex_init(&e->lock); |
12226 |
-+ INIT_LIST_HEAD(&e->conn_list); |
12227 |
-+ kdbus_policy_db_init(&e->policy_db); |
12228 |
-+ e->bus = kdbus_bus_ref(bus); |
12229 |
-+ |
12230 |
-+ ret = kdbus_node_link(&e->node, &bus->node, name); |
12231 |
-+ if (ret < 0) |
12232 |
-+ goto exit_unref; |
12233 |
-+ |
12234 |
-+ /* |
12235 |
-+ * Transactions on custom endpoints are never accounted on the global |
12236 |
-+ * user limits. Instead, for each custom endpoint, we create a custom, |
12237 |
-+ * unique user, which all transactions are accounted on. Regardless of |
12238 |
-+ * the user using that endpoint, it is always accounted on the same |
12239 |
-+ * user-object. This budget is not shared with ordinary users on |
12240 |
-+ * non-custom endpoints. |
12241 |
-+ */ |
12242 |
-+ if (is_custom) { |
12243 |
-+ e->user = kdbus_user_lookup(bus->domain, INVALID_UID); |
12244 |
-+ if (IS_ERR(e->user)) { |
12245 |
-+ ret = PTR_ERR(e->user); |
12246 |
-+ e->user = NULL; |
12247 |
-+ goto exit_unref; |
12248 |
-+ } |
12249 |
-+ } |
12250 |
-+ |
12251 |
-+ return e; |
12252 |
-+ |
12253 |
-+exit_unref: |
12254 |
-+ kdbus_node_deactivate(&e->node); |
12255 |
-+ kdbus_node_unref(&e->node); |
12256 |
-+ return ERR_PTR(ret); |
12257 |
-+} |
12258 |
-+ |
12259 |
-+/** |
12260 |
-+ * kdbus_ep_ref() - increase the reference counter of a kdbus_ep |
12261 |
-+ * @ep: The endpoint to reference |
12262 |
-+ * |
12263 |
-+ * Every user of an endpoint, except for its creator, must add a reference to |
12264 |
-+ * the kdbus_ep instance using this function. |
12265 |
-+ * |
12266 |
-+ * Return: the ep itself |
12267 |
-+ */ |
12268 |
-+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep) |
12269 |
-+{ |
12270 |
-+ if (ep) |
12271 |
-+ kdbus_node_ref(&ep->node); |
12272 |
-+ return ep; |
12273 |
-+} |
12274 |
-+ |
12275 |
-+/** |
12276 |
-+ * kdbus_ep_unref() - decrease the reference counter of a kdbus_ep |
12277 |
-+ * @ep: The ep to unref |
12278 |
-+ * |
12279 |
-+ * Release a reference. If the reference count drops to 0, the ep will be |
12280 |
-+ * freed. |
12281 |
-+ * |
12282 |
-+ * Return: NULL |
12283 |
-+ */ |
12284 |
-+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep) |
12285 |
-+{ |
12286 |
-+ if (ep) |
12287 |
-+ kdbus_node_unref(&ep->node); |
12288 |
-+ return NULL; |
12289 |
-+} |
12290 |
-+ |
12291 |
-+/** |
12292 |
-+ * kdbus_ep_is_privileged() - check whether a file is privileged |
12293 |
-+ * @ep: endpoint to operate on |
12294 |
-+ * @file: file to test |
12295 |
-+ * |
12296 |
-+ * Return: True if @file is privileged in the domain of @ep. |
12297 |
-+ */ |
12298 |
-+bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file) |
12299 |
-+{ |
12300 |
-+ return !ep->user && |
12301 |
-+ file_ns_capable(file, ep->bus->domain->user_namespace, |
12302 |
-+ CAP_IPC_OWNER); |
12303 |
-+} |
12304 |
-+ |
12305 |
-+/** |
12306 |
-+ * kdbus_ep_is_owner() - check whether a file should be treated as bus owner |
12307 |
-+ * @ep: endpoint to operate on |
12308 |
-+ * @file: file to test |
12309 |
-+ * |
12310 |
-+ * Return: True if @file should be treated as bus owner on @ep |
12311 |
-+ */ |
12312 |
-+bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file) |
12313 |
-+{ |
12314 |
-+ return !ep->user && |
12315 |
-+ (uid_eq(file->f_cred->euid, ep->bus->node.uid) || |
12316 |
-+ kdbus_ep_is_privileged(ep, file)); |
12317 |
-+} |
12318 |
-+ |
12319 |
-+/** |
12320 |
-+ * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE |
12321 |
-+ * @bus: bus to operate on |
12322 |
-+ * @argp: command payload |
12323 |
-+ * |
12324 |
-+ * Return: NULL or newly created endpoint on success, ERR_PTR on failure. |
12325 |
-+ */ |
12326 |
-+struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp) |
12327 |
-+{ |
12328 |
-+ const char *item_make_name; |
12329 |
-+ struct kdbus_ep *ep = NULL; |
12330 |
-+ struct kdbus_cmd *cmd; |
12331 |
-+ int ret; |
12332 |
-+ |
12333 |
-+ struct kdbus_arg argv[] = { |
12334 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
12335 |
-+ { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, |
12336 |
-+ }; |
12337 |
-+ struct kdbus_args args = { |
12338 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
12339 |
-+ KDBUS_MAKE_ACCESS_GROUP | |
12340 |
-+ KDBUS_MAKE_ACCESS_WORLD, |
12341 |
-+ .argv = argv, |
12342 |
-+ .argc = ARRAY_SIZE(argv), |
12343 |
-+ }; |
12344 |
-+ |
12345 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
12346 |
-+ if (ret < 0) |
12347 |
-+ return ERR_PTR(ret); |
12348 |
-+ if (ret > 0) |
12349 |
-+ return NULL; |
12350 |
-+ |
12351 |
-+ item_make_name = argv[1].item->str; |
12352 |
-+ |
12353 |
-+ ep = kdbus_ep_new(bus, item_make_name, cmd->flags, |
12354 |
-+ current_euid(), current_egid(), true); |
12355 |
-+ if (IS_ERR(ep)) { |
12356 |
-+ ret = PTR_ERR(ep); |
12357 |
-+ ep = NULL; |
12358 |
-+ goto exit; |
12359 |
-+ } |
12360 |
-+ |
12361 |
-+ if (!kdbus_node_activate(&ep->node)) { |
12362 |
-+ ret = -ESHUTDOWN; |
12363 |
-+ goto exit; |
12364 |
-+ } |
12365 |
-+ |
12366 |
-+exit: |
12367 |
-+ ret = kdbus_args_clear(&args, ret); |
12368 |
-+ if (ret < 0) { |
12369 |
-+ if (ep) { |
12370 |
-+ kdbus_node_deactivate(&ep->node); |
12371 |
-+ kdbus_ep_unref(ep); |
12372 |
-+ } |
12373 |
-+ return ERR_PTR(ret); |
12374 |
-+ } |
12375 |
-+ return ep; |
12376 |
-+} |
12377 |
-+ |
12378 |
-+/** |
12379 |
-+ * kdbus_cmd_ep_update() - handle KDBUS_CMD_ENDPOINT_UPDATE |
12380 |
-+ * @ep: endpoint to operate on |
12381 |
-+ * @argp: command payload |
12382 |
-+ * |
12383 |
-+ * Return: >=0 on success, negative error code on failure. |
12384 |
-+ */ |
12385 |
-+int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp) |
12386 |
-+{ |
12387 |
-+ struct kdbus_cmd *cmd; |
12388 |
-+ int ret; |
12389 |
-+ |
12390 |
-+ struct kdbus_arg argv[] = { |
12391 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
12392 |
-+ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
12393 |
-+ { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, |
12394 |
-+ }; |
12395 |
-+ struct kdbus_args args = { |
12396 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
12397 |
-+ .argv = argv, |
12398 |
-+ .argc = ARRAY_SIZE(argv), |
12399 |
-+ }; |
12400 |
-+ |
12401 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
12402 |
-+ if (ret != 0) |
12403 |
-+ return ret; |
12404 |
-+ |
12405 |
-+ ret = kdbus_policy_set(&ep->policy_db, args.items, args.items_size, |
12406 |
-+ 0, true, ep); |
12407 |
-+ return kdbus_args_clear(&args, ret); |
12408 |
-+} |
12409 |
-diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h |
12410 |
-new file mode 100644 |
12411 |
-index 0000000..e0da59f |
12412 |
---- /dev/null |
12413 |
-+++ b/ipc/kdbus/endpoint.h |
12414 |
-@@ -0,0 +1,70 @@ |
12415 |
-+/* |
12416 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
12417 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
12418 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
12419 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
12420 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
12421 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
12422 |
-+ * |
12423 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
12424 |
-+ * the terms of the GNU Lesser General Public License as published by the |
12425 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
12426 |
-+ * your option) any later version. |
12427 |
-+ */ |
12428 |
-+ |
12429 |
-+#ifndef __KDBUS_ENDPOINT_H |
12430 |
-+#define __KDBUS_ENDPOINT_H |
12431 |
-+ |
12432 |
-+#include <linux/list.h> |
12433 |
-+#include <linux/mutex.h> |
12434 |
-+#include <linux/uidgid.h> |
12435 |
-+#include "node.h" |
12436 |
-+#include "policy.h" |
12437 |
-+ |
12438 |
-+struct kdbus_bus; |
12439 |
-+struct kdbus_user; |
12440 |
-+ |
12441 |
-+/** |
12442 |
-+ * struct kdbus_ep - endpoint to access a bus |
12443 |
-+ * @node: The kdbus node |
12444 |
-+ * @lock: Endpoint data lock |
12445 |
-+ * @bus: Bus behind this endpoint |
12446 |
-+ * @user: Custom enpoints account against an anonymous user |
12447 |
-+ * @policy_db: Uploaded policy |
12448 |
-+ * @conn_list: Connections of this endpoint |
12449 |
-+ * |
12450 |
-+ * An endpoint offers access to a bus; the default endpoint node name is "bus". |
12451 |
-+ * Additional custom endpoints to the same bus can be created and they can |
12452 |
-+ * carry their own policies/filters. |
12453 |
-+ */ |
12454 |
-+struct kdbus_ep { |
12455 |
-+ struct kdbus_node node; |
12456 |
-+ struct mutex lock; |
12457 |
-+ |
12458 |
-+ /* static */ |
12459 |
-+ struct kdbus_bus *bus; |
12460 |
-+ struct kdbus_user *user; |
12461 |
-+ |
12462 |
-+ /* protected by own locks */ |
12463 |
-+ struct kdbus_policy_db policy_db; |
12464 |
-+ |
12465 |
-+ /* protected by ep->lock */ |
12466 |
-+ struct list_head conn_list; |
12467 |
-+}; |
12468 |
-+ |
12469 |
-+#define kdbus_ep_from_node(_node) \ |
12470 |
-+ container_of((_node), struct kdbus_ep, node) |
12471 |
-+ |
12472 |
-+struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, |
12473 |
-+ unsigned int access, kuid_t uid, kgid_t gid, |
12474 |
-+ bool policy); |
12475 |
-+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep); |
12476 |
-+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep); |
12477 |
-+ |
12478 |
-+bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file); |
12479 |
-+bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file); |
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..09c4809 |
12488 |
---- /dev/null |
12489 |
-+++ b/ipc/kdbus/fs.c |
12490 |
-@@ -0,0 +1,508 @@ |
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 necessarily 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 |
-+ kdbus_domain_unref(domain); |
12819 |
-+} |
12820 |
-+ |
12821 |
-+static int fs_super_set(struct super_block *sb, void *data) |
12822 |
-+{ |
12823 |
-+ int ret; |
12824 |
-+ |
12825 |
-+ ret = set_anon_super(sb, data); |
12826 |
-+ if (!ret) |
12827 |
-+ sb->s_fs_info = data; |
12828 |
-+ |
12829 |
-+ return ret; |
12830 |
-+} |
12831 |
-+ |
12832 |
-+static struct dentry *fs_super_mount(struct file_system_type *fs_type, |
12833 |
-+ int flags, const char *dev_name, |
12834 |
-+ void *data) |
12835 |
-+{ |
12836 |
-+ struct kdbus_domain *domain; |
12837 |
-+ struct super_block *sb; |
12838 |
-+ int ret; |
12839 |
-+ |
12840 |
-+ domain = kdbus_domain_new(KDBUS_MAKE_ACCESS_WORLD); |
12841 |
-+ if (IS_ERR(domain)) |
12842 |
-+ return ERR_CAST(domain); |
12843 |
-+ |
12844 |
-+ sb = sget(fs_type, NULL, fs_super_set, flags, domain); |
12845 |
-+ if (IS_ERR(sb)) { |
12846 |
-+ kdbus_node_deactivate(&domain->node); |
12847 |
-+ kdbus_domain_unref(domain); |
12848 |
-+ return ERR_CAST(sb); |
12849 |
-+ } |
12850 |
-+ |
12851 |
-+ WARN_ON(sb->s_fs_info != domain); |
12852 |
-+ WARN_ON(sb->s_root); |
12853 |
-+ |
12854 |
-+ ret = fs_super_fill(sb); |
12855 |
-+ if (ret < 0) { |
12856 |
-+ /* calls into ->kill_sb() when done */ |
12857 |
-+ deactivate_locked_super(sb); |
12858 |
-+ return ERR_PTR(ret); |
12859 |
-+ } |
12860 |
-+ |
12861 |
-+ return dget(sb->s_root); |
12862 |
-+} |
12863 |
-+ |
12864 |
-+static struct file_system_type fs_type = { |
12865 |
-+ .name = KBUILD_MODNAME "fs", |
12866 |
-+ .owner = THIS_MODULE, |
12867 |
-+ .mount = fs_super_mount, |
12868 |
-+ .kill_sb = fs_super_kill, |
12869 |
-+ .fs_flags = FS_USERNS_MOUNT, |
12870 |
-+}; |
12871 |
-+ |
12872 |
-+/** |
12873 |
-+ * kdbus_fs_init() - register kdbus filesystem |
12874 |
-+ * |
12875 |
-+ * This registers a filesystem with the VFS layer. The filesystem is called |
12876 |
-+ * `KBUILD_MODNAME "fs"', which usually resolves to `kdbusfs'. The nameing |
12877 |
-+ * scheme allows to set KBUILD_MODNAME to "kdbus2" and you will get an |
12878 |
-+ * independent filesystem for developers. |
12879 |
-+ * |
12880 |
-+ * Each mount of the kdbusfs filesystem has an kdbus_domain attached. |
12881 |
-+ * Operations on this mount will only affect the attached domain. On each mount |
12882 |
-+ * a new domain is automatically created and used for this mount exclusively. |
12883 |
-+ * If you want to share a domain across multiple mounts, you need to bind-mount |
12884 |
-+ * it. |
12885 |
-+ * |
12886 |
-+ * Mounts of kdbusfs (with a different domain each) are unrelated to each other |
12887 |
-+ * and will never have any effect on any domain but their own. |
12888 |
-+ * |
12889 |
-+ * Return: 0 on success, negative error otherwise. |
12890 |
-+ */ |
12891 |
-+int kdbus_fs_init(void) |
12892 |
-+{ |
12893 |
-+ return register_filesystem(&fs_type); |
12894 |
-+} |
12895 |
-+ |
12896 |
-+/** |
12897 |
-+ * kdbus_fs_exit() - unregister kdbus filesystem |
12898 |
-+ * |
12899 |
-+ * This does the reverse to kdbus_fs_init(). It unregisters the kdbusfs |
12900 |
-+ * filesystem from VFS and cleans up any allocated resources. |
12901 |
-+ */ |
12902 |
-+void kdbus_fs_exit(void) |
12903 |
-+{ |
12904 |
-+ unregister_filesystem(&fs_type); |
12905 |
-+} |
12906 |
-+ |
12907 |
-+/* acquire domain of @node, making sure all ancestors are active */ |
12908 |
-+static struct kdbus_domain *fs_acquire_domain(struct kdbus_node *node) |
12909 |
-+{ |
12910 |
-+ struct kdbus_domain *domain; |
12911 |
-+ struct kdbus_node *iter; |
12912 |
-+ |
12913 |
-+ /* caller must guarantee that @node is linked */ |
12914 |
-+ for (iter = node; iter->parent; iter = iter->parent) |
12915 |
-+ if (!kdbus_node_is_active(iter->parent)) |
12916 |
-+ return NULL; |
12917 |
-+ |
12918 |
-+ /* root nodes are always domains */ |
12919 |
-+ if (WARN_ON(iter->type != KDBUS_NODE_DOMAIN)) |
12920 |
-+ return NULL; |
12921 |
-+ |
12922 |
-+ domain = kdbus_domain_from_node(iter); |
12923 |
-+ if (!kdbus_node_acquire(&domain->node)) |
12924 |
-+ return NULL; |
12925 |
-+ |
12926 |
-+ return domain; |
12927 |
-+} |
12928 |
-+ |
12929 |
-+/** |
12930 |
-+ * kdbus_fs_flush() - flush dcache entries of a node |
12931 |
-+ * @node: Node to flush entries of |
12932 |
-+ * |
12933 |
-+ * This flushes all VFS filesystem cache entries for a node and all its |
12934 |
-+ * children. This should be called whenever a node is destroyed during |
12935 |
-+ * runtime. It will flush the cache entries so the linked objects can be |
12936 |
-+ * deallocated. |
12937 |
-+ * |
12938 |
-+ * This is a no-op if you call it on active nodes (they really should stay in |
12939 |
-+ * cache) or on nodes with deactivated parents (flushing the parent is enough). |
12940 |
-+ * Furthermore, there is no need to call it on nodes whose lifetime is bound to |
12941 |
-+ * their parents'. In those cases, the parent-flush will always also flush the |
12942 |
-+ * children. |
12943 |
-+ */ |
12944 |
-+void kdbus_fs_flush(struct kdbus_node *node) |
12945 |
-+{ |
12946 |
-+ struct dentry *dentry, *parent_dentry = NULL; |
12947 |
-+ struct kdbus_domain *domain; |
12948 |
-+ struct qstr name; |
12949 |
-+ |
12950 |
-+ /* active nodes should remain in cache */ |
12951 |
-+ if (!kdbus_node_is_deactivated(node)) |
12952 |
-+ return; |
12953 |
-+ |
12954 |
-+ /* nodes that were never linked were never instantiated */ |
12955 |
-+ if (!node->parent) |
12956 |
-+ return; |
12957 |
-+ |
12958 |
-+ /* acquire domain and verify all ancestors are active */ |
12959 |
-+ domain = fs_acquire_domain(node); |
12960 |
-+ if (!domain) |
12961 |
-+ return; |
12962 |
-+ |
12963 |
-+ switch (node->type) { |
12964 |
-+ case KDBUS_NODE_ENDPOINT: |
12965 |
-+ if (WARN_ON(!node->parent || !node->parent->name)) |
12966 |
-+ goto exit; |
12967 |
-+ |
12968 |
-+ name.name = node->parent->name; |
12969 |
-+ name.len = strlen(node->parent->name); |
12970 |
-+ parent_dentry = d_hash_and_lookup(domain->dentry, &name); |
12971 |
-+ if (IS_ERR_OR_NULL(parent_dentry)) |
12972 |
-+ goto exit; |
12973 |
-+ |
12974 |
-+ /* fallthrough */ |
12975 |
-+ case KDBUS_NODE_BUS: |
12976 |
-+ if (WARN_ON(!node->name)) |
12977 |
-+ goto exit; |
12978 |
-+ |
12979 |
-+ name.name = node->name; |
12980 |
-+ name.len = strlen(node->name); |
12981 |
-+ dentry = d_hash_and_lookup(parent_dentry ? : domain->dentry, |
12982 |
-+ &name); |
12983 |
-+ if (!IS_ERR_OR_NULL(dentry)) { |
12984 |
-+ d_invalidate(dentry); |
12985 |
-+ dput(dentry); |
12986 |
-+ } |
12987 |
-+ |
12988 |
-+ dput(parent_dentry); |
12989 |
-+ break; |
12990 |
-+ |
12991 |
-+ default: |
12992 |
-+ /* all other types are bound to their parent lifetime */ |
12993 |
-+ break; |
12994 |
-+ } |
12995 |
-+ |
12996 |
-+exit: |
12997 |
-+ kdbus_node_release(&domain->node); |
12998 |
-+} |
12999 |
-diff --git a/ipc/kdbus/fs.h b/ipc/kdbus/fs.h |
13000 |
-new file mode 100644 |
13001 |
-index 0000000..62f7d6a |
13002 |
---- /dev/null |
13003 |
-+++ b/ipc/kdbus/fs.h |
13004 |
-@@ -0,0 +1,28 @@ |
13005 |
-+/* |
13006 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13007 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13008 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13009 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13010 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13011 |
-+ * |
13012 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13013 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13014 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13015 |
-+ * your option) any later version. |
13016 |
-+ */ |
13017 |
-+ |
13018 |
-+#ifndef __KDBUSFS_H |
13019 |
-+#define __KDBUSFS_H |
13020 |
-+ |
13021 |
-+#include <linux/kernel.h> |
13022 |
-+ |
13023 |
-+struct kdbus_node; |
13024 |
-+ |
13025 |
-+int kdbus_fs_init(void); |
13026 |
-+void kdbus_fs_exit(void); |
13027 |
-+void kdbus_fs_flush(struct kdbus_node *node); |
13028 |
-+ |
13029 |
-+#define kdbus_node_from_inode(_inode) \ |
13030 |
-+ ((struct kdbus_node *)(_inode)->i_private) |
13031 |
-+ |
13032 |
-+#endif |
13033 |
-diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c |
13034 |
-new file mode 100644 |
13035 |
-index 0000000..fc60932 |
13036 |
---- /dev/null |
13037 |
-+++ b/ipc/kdbus/handle.c |
13038 |
-@@ -0,0 +1,691 @@ |
13039 |
-+/* |
13040 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13041 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13042 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13043 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13044 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13045 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
13046 |
-+ * |
13047 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13048 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13049 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13050 |
-+ * your option) any later version. |
13051 |
-+ */ |
13052 |
-+ |
13053 |
-+#include <linux/file.h> |
13054 |
-+#include <linux/fs.h> |
13055 |
-+#include <linux/idr.h> |
13056 |
-+#include <linux/init.h> |
13057 |
-+#include <linux/kdev_t.h> |
13058 |
-+#include <linux/module.h> |
13059 |
-+#include <linux/mutex.h> |
13060 |
-+#include <linux/poll.h> |
13061 |
-+#include <linux/rwsem.h> |
13062 |
-+#include <linux/sched.h> |
13063 |
-+#include <linux/sizes.h> |
13064 |
-+#include <linux/slab.h> |
13065 |
-+#include <linux/uaccess.h> |
13066 |
-+#include <linux/syscalls.h> |
13067 |
-+ |
13068 |
-+#include "bus.h" |
13069 |
-+#include "connection.h" |
13070 |
-+#include "endpoint.h" |
13071 |
-+#include "fs.h" |
13072 |
-+#include "handle.h" |
13073 |
-+#include "item.h" |
13074 |
-+#include "match.h" |
13075 |
-+#include "message.h" |
13076 |
-+#include "names.h" |
13077 |
-+#include "domain.h" |
13078 |
-+#include "policy.h" |
13079 |
-+ |
13080 |
-+static int kdbus_args_verify(struct kdbus_args *args) |
13081 |
-+{ |
13082 |
-+ struct kdbus_item *item; |
13083 |
-+ size_t i; |
13084 |
-+ int ret; |
13085 |
-+ |
13086 |
-+ KDBUS_ITEMS_FOREACH(item, args->items, args->items_size) { |
13087 |
-+ struct kdbus_arg *arg = NULL; |
13088 |
-+ |
13089 |
-+ if (!KDBUS_ITEM_VALID(item, args->items, args->items_size)) |
13090 |
-+ return -EINVAL; |
13091 |
-+ |
13092 |
-+ for (i = 0; i < args->argc; ++i) |
13093 |
-+ if (args->argv[i].type == item->type) |
13094 |
-+ break; |
13095 |
-+ if (i >= args->argc) |
13096 |
-+ return -EINVAL; |
13097 |
-+ |
13098 |
-+ arg = &args->argv[i]; |
13099 |
-+ |
13100 |
-+ ret = kdbus_item_validate(item); |
13101 |
-+ if (ret < 0) |
13102 |
-+ return ret; |
13103 |
-+ |
13104 |
-+ if (arg->item && !arg->multiple) |
13105 |
-+ return -EINVAL; |
13106 |
-+ |
13107 |
-+ arg->item = item; |
13108 |
-+ } |
13109 |
-+ |
13110 |
-+ if (!KDBUS_ITEMS_END(item, args->items, args->items_size)) |
13111 |
-+ return -EINVAL; |
13112 |
-+ |
13113 |
-+ return 0; |
13114 |
-+} |
13115 |
-+ |
13116 |
-+static int kdbus_args_negotiate(struct kdbus_args *args) |
13117 |
-+{ |
13118 |
-+ struct kdbus_item __user *user; |
13119 |
-+ struct kdbus_item *negotiation; |
13120 |
-+ size_t i, j, num; |
13121 |
-+ |
13122 |
-+ /* |
13123 |
-+ * If KDBUS_FLAG_NEGOTIATE is set, we overwrite the flags field with |
13124 |
-+ * the set of supported flags. Furthermore, if an KDBUS_ITEM_NEGOTIATE |
13125 |
-+ * item is passed, we iterate its payload (array of u64, each set to an |
13126 |
-+ * item type) and clear all unsupported item-types to 0. |
13127 |
-+ * The caller might do this recursively, if other flags or objects are |
13128 |
-+ * embedded in the payload itself. |
13129 |
-+ */ |
13130 |
-+ |
13131 |
-+ if (args->cmd->flags & KDBUS_FLAG_NEGOTIATE) { |
13132 |
-+ if (put_user(args->allowed_flags & ~KDBUS_FLAG_NEGOTIATE, |
13133 |
-+ &args->user->flags)) |
13134 |
-+ return -EFAULT; |
13135 |
-+ } |
13136 |
-+ |
13137 |
-+ if (args->argc < 1 || args->argv[0].type != KDBUS_ITEM_NEGOTIATE || |
13138 |
-+ !args->argv[0].item) |
13139 |
-+ return 0; |
13140 |
-+ |
13141 |
-+ negotiation = args->argv[0].item; |
13142 |
-+ user = (struct kdbus_item __user *) |
13143 |
-+ ((u8 __user *)args->user + |
13144 |
-+ ((u8 *)negotiation - (u8 *)args->cmd)); |
13145 |
-+ num = KDBUS_ITEM_PAYLOAD_SIZE(negotiation) / sizeof(u64); |
13146 |
-+ |
13147 |
-+ for (i = 0; i < num; ++i) { |
13148 |
-+ for (j = 0; j < args->argc; ++j) |
13149 |
-+ if (negotiation->data64[i] == args->argv[j].type) |
13150 |
-+ break; |
13151 |
-+ |
13152 |
-+ if (j < args->argc) |
13153 |
-+ continue; |
13154 |
-+ |
13155 |
-+ /* this item is not supported, clear it out */ |
13156 |
-+ negotiation->data64[i] = 0; |
13157 |
-+ if (put_user(negotiation->data64[i], &user->data64[i])) |
13158 |
-+ return -EFAULT; |
13159 |
-+ } |
13160 |
-+ |
13161 |
-+ return 0; |
13162 |
-+} |
13163 |
-+ |
13164 |
-+/** |
13165 |
-+ * __kdbus_args_parse() - parse payload of kdbus command |
13166 |
-+ * @args: object to parse data into |
13167 |
-+ * @is_cmd: whether this is a command or msg payload |
13168 |
-+ * @argp: user-space location of command payload to parse |
13169 |
-+ * @type_size: overall size of command payload to parse |
13170 |
-+ * @items_offset: offset of items array in command payload |
13171 |
-+ * @out: output variable to store pointer to copied payload |
13172 |
-+ * |
13173 |
-+ * This parses the ioctl payload at user-space location @argp into @args. @args |
13174 |
-+ * must be pre-initialized by the caller to reflect the supported flags and |
13175 |
-+ * items of this command. This parser will then copy the command payload into |
13176 |
-+ * kernel-space, verify correctness and consistency and cache pointers to parsed |
13177 |
-+ * items and other data in @args. |
13178 |
-+ * |
13179 |
-+ * If this function succeeded, you must call kdbus_args_clear() to release |
13180 |
-+ * allocated resources before destroying @args. |
13181 |
-+ * |
13182 |
-+ * This can also be used to import kdbus_msg objects. In that case, @is_cmd must |
13183 |
-+ * be set to 'false' and the 'return_flags' field will not be touched (as it |
13184 |
-+ * doesn't exist on kdbus_msg). |
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, bool is_cmd, void __user *argp, |
13190 |
-+ size_t type_size, size_t items_offset, void **out) |
13191 |
-+{ |
13192 |
-+ u64 user_size; |
13193 |
-+ int ret, i; |
13194 |
-+ |
13195 |
-+ ret = kdbus_copy_from_user(&user_size, argp, sizeof(user_size)); |
13196 |
-+ if (ret < 0) |
13197 |
-+ return ret; |
13198 |
-+ |
13199 |
-+ if (user_size < type_size) |
13200 |
-+ return -EINVAL; |
13201 |
-+ if (user_size > KDBUS_CMD_MAX_SIZE) |
13202 |
-+ return -EMSGSIZE; |
13203 |
-+ |
13204 |
-+ if (user_size <= sizeof(args->cmd_buf)) { |
13205 |
-+ if (copy_from_user(args->cmd_buf, argp, user_size)) |
13206 |
-+ return -EFAULT; |
13207 |
-+ args->cmd = (void*)args->cmd_buf; |
13208 |
-+ } else { |
13209 |
-+ args->cmd = memdup_user(argp, user_size); |
13210 |
-+ if (IS_ERR(args->cmd)) |
13211 |
-+ return PTR_ERR(args->cmd); |
13212 |
-+ } |
13213 |
-+ |
13214 |
-+ if (args->cmd->size != user_size) { |
13215 |
-+ ret = -EINVAL; |
13216 |
-+ goto error; |
13217 |
-+ } |
13218 |
-+ |
13219 |
-+ if (is_cmd) |
13220 |
-+ args->cmd->return_flags = 0; |
13221 |
-+ args->user = argp; |
13222 |
-+ args->items = (void *)((u8 *)args->cmd + items_offset); |
13223 |
-+ args->items_size = args->cmd->size - items_offset; |
13224 |
-+ args->is_cmd = is_cmd; |
13225 |
-+ |
13226 |
-+ if (args->cmd->flags & ~args->allowed_flags) { |
13227 |
-+ ret = -EINVAL; |
13228 |
-+ goto error; |
13229 |
-+ } |
13230 |
-+ |
13231 |
-+ ret = kdbus_args_verify(args); |
13232 |
-+ if (ret < 0) |
13233 |
-+ goto error; |
13234 |
-+ |
13235 |
-+ ret = kdbus_args_negotiate(args); |
13236 |
-+ if (ret < 0) |
13237 |
-+ goto error; |
13238 |
-+ |
13239 |
-+ /* mandatory items must be given (but not on negotiation) */ |
13240 |
-+ if (!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE)) { |
13241 |
-+ for (i = 0; i < args->argc; ++i) |
13242 |
-+ if (args->argv[i].mandatory && !args->argv[i].item) { |
13243 |
-+ ret = -EINVAL; |
13244 |
-+ goto error; |
13245 |
-+ } |
13246 |
-+ } |
13247 |
-+ |
13248 |
-+ *out = args->cmd; |
13249 |
-+ return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE); |
13250 |
-+ |
13251 |
-+error: |
13252 |
-+ return kdbus_args_clear(args, ret); |
13253 |
-+} |
13254 |
-+ |
13255 |
-+/** |
13256 |
-+ * kdbus_args_clear() - release allocated command resources |
13257 |
-+ * @args: object to release resources of |
13258 |
-+ * @ret: return value of this command |
13259 |
-+ * |
13260 |
-+ * This frees all allocated resources on @args and copies the command result |
13261 |
-+ * flags into user-space. @ret is usually returned unchanged by this function, |
13262 |
-+ * so it can be used in the final 'return' statement of the command handler. |
13263 |
-+ * |
13264 |
-+ * Return: -EFAULT if return values cannot be copied into user-space, otherwise |
13265 |
-+ * @ret is returned unchanged. |
13266 |
-+ */ |
13267 |
-+int kdbus_args_clear(struct kdbus_args *args, int ret) |
13268 |
-+{ |
13269 |
-+ if (!args) |
13270 |
-+ return ret; |
13271 |
-+ |
13272 |
-+ if (!IS_ERR_OR_NULL(args->cmd)) { |
13273 |
-+ if (args->is_cmd && put_user(args->cmd->return_flags, |
13274 |
-+ &args->user->return_flags)) |
13275 |
-+ ret = -EFAULT; |
13276 |
-+ if (args->cmd != (void*)args->cmd_buf) |
13277 |
-+ kfree(args->cmd); |
13278 |
-+ args->cmd = NULL; |
13279 |
-+ } |
13280 |
-+ |
13281 |
-+ return ret; |
13282 |
-+} |
13283 |
-+ |
13284 |
-+/** |
13285 |
-+ * enum kdbus_handle_type - type an handle can be of |
13286 |
-+ * @KDBUS_HANDLE_NONE: no type set, yet |
13287 |
-+ * @KDBUS_HANDLE_BUS_OWNER: bus owner |
13288 |
-+ * @KDBUS_HANDLE_EP_OWNER: endpoint owner |
13289 |
-+ * @KDBUS_HANDLE_CONNECTED: endpoint connection after HELLO |
13290 |
-+ */ |
13291 |
-+enum kdbus_handle_type { |
13292 |
-+ KDBUS_HANDLE_NONE, |
13293 |
-+ KDBUS_HANDLE_BUS_OWNER, |
13294 |
-+ KDBUS_HANDLE_EP_OWNER, |
13295 |
-+ KDBUS_HANDLE_CONNECTED, |
13296 |
-+}; |
13297 |
-+ |
13298 |
-+/** |
13299 |
-+ * struct kdbus_handle - handle to the kdbus system |
13300 |
-+ * @lock: handle lock |
13301 |
-+ * @type: type of this handle (KDBUS_HANDLE_*) |
13302 |
-+ * @bus_owner: bus this handle owns |
13303 |
-+ * @ep_owner: endpoint this handle owns |
13304 |
-+ * @conn: connection this handle owns |
13305 |
-+ */ |
13306 |
-+struct kdbus_handle { |
13307 |
-+ struct mutex lock; |
13308 |
-+ |
13309 |
-+ enum kdbus_handle_type type; |
13310 |
-+ union { |
13311 |
-+ struct kdbus_bus *bus_owner; |
13312 |
-+ struct kdbus_ep *ep_owner; |
13313 |
-+ struct kdbus_conn *conn; |
13314 |
-+ }; |
13315 |
-+}; |
13316 |
-+ |
13317 |
-+static int kdbus_handle_open(struct inode *inode, struct file *file) |
13318 |
-+{ |
13319 |
-+ struct kdbus_handle *handle; |
13320 |
-+ struct kdbus_node *node; |
13321 |
-+ int ret; |
13322 |
-+ |
13323 |
-+ node = kdbus_node_from_inode(inode); |
13324 |
-+ if (!kdbus_node_acquire(node)) |
13325 |
-+ return -ESHUTDOWN; |
13326 |
-+ |
13327 |
-+ handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
13328 |
-+ if (!handle) { |
13329 |
-+ ret = -ENOMEM; |
13330 |
-+ goto exit; |
13331 |
-+ } |
13332 |
-+ |
13333 |
-+ mutex_init(&handle->lock); |
13334 |
-+ handle->type = KDBUS_HANDLE_NONE; |
13335 |
-+ |
13336 |
-+ file->private_data = handle; |
13337 |
-+ ret = 0; |
13338 |
-+ |
13339 |
-+exit: |
13340 |
-+ kdbus_node_release(node); |
13341 |
-+ return ret; |
13342 |
-+} |
13343 |
-+ |
13344 |
-+static int kdbus_handle_release(struct inode *inode, struct file *file) |
13345 |
-+{ |
13346 |
-+ struct kdbus_handle *handle = file->private_data; |
13347 |
-+ |
13348 |
-+ switch (handle->type) { |
13349 |
-+ case KDBUS_HANDLE_BUS_OWNER: |
13350 |
-+ if (handle->bus_owner) { |
13351 |
-+ kdbus_node_deactivate(&handle->bus_owner->node); |
13352 |
-+ kdbus_bus_unref(handle->bus_owner); |
13353 |
-+ } |
13354 |
-+ break; |
13355 |
-+ case KDBUS_HANDLE_EP_OWNER: |
13356 |
-+ if (handle->ep_owner) { |
13357 |
-+ kdbus_node_deactivate(&handle->ep_owner->node); |
13358 |
-+ kdbus_ep_unref(handle->ep_owner); |
13359 |
-+ } |
13360 |
-+ break; |
13361 |
-+ case KDBUS_HANDLE_CONNECTED: |
13362 |
-+ kdbus_conn_disconnect(handle->conn, false); |
13363 |
-+ kdbus_conn_unref(handle->conn); |
13364 |
-+ break; |
13365 |
-+ case KDBUS_HANDLE_NONE: |
13366 |
-+ /* nothing to clean up */ |
13367 |
-+ break; |
13368 |
-+ } |
13369 |
-+ |
13370 |
-+ kfree(handle); |
13371 |
-+ |
13372 |
-+ return 0; |
13373 |
-+} |
13374 |
-+ |
13375 |
-+static long kdbus_handle_ioctl_control(struct file *file, unsigned int cmd, |
13376 |
-+ void __user *argp) |
13377 |
-+{ |
13378 |
-+ struct kdbus_handle *handle = file->private_data; |
13379 |
-+ struct kdbus_node *node = file_inode(file)->i_private; |
13380 |
-+ struct kdbus_domain *domain; |
13381 |
-+ int ret = 0; |
13382 |
-+ |
13383 |
-+ if (!kdbus_node_acquire(node)) |
13384 |
-+ return -ESHUTDOWN; |
13385 |
-+ |
13386 |
-+ /* |
13387 |
-+ * The parent of control-nodes is always a domain, make sure to pin it |
13388 |
-+ * so the parent is actually valid. |
13389 |
-+ */ |
13390 |
-+ domain = kdbus_domain_from_node(node->parent); |
13391 |
-+ if (!kdbus_node_acquire(&domain->node)) { |
13392 |
-+ kdbus_node_release(node); |
13393 |
-+ return -ESHUTDOWN; |
13394 |
-+ } |
13395 |
-+ |
13396 |
-+ switch (cmd) { |
13397 |
-+ case KDBUS_CMD_BUS_MAKE: { |
13398 |
-+ struct kdbus_bus *bus; |
13399 |
-+ |
13400 |
-+ bus = kdbus_cmd_bus_make(domain, argp); |
13401 |
-+ if (IS_ERR_OR_NULL(bus)) { |
13402 |
-+ ret = PTR_ERR_OR_ZERO(bus); |
13403 |
-+ break; |
13404 |
-+ } |
13405 |
-+ |
13406 |
-+ handle->bus_owner = bus; |
13407 |
-+ ret = KDBUS_HANDLE_BUS_OWNER; |
13408 |
-+ break; |
13409 |
-+ } |
13410 |
-+ |
13411 |
-+ default: |
13412 |
-+ ret = -EBADFD; |
13413 |
-+ break; |
13414 |
-+ } |
13415 |
-+ |
13416 |
-+ kdbus_node_release(&domain->node); |
13417 |
-+ kdbus_node_release(node); |
13418 |
-+ return ret; |
13419 |
-+} |
13420 |
-+ |
13421 |
-+static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd, |
13422 |
-+ void __user *buf) |
13423 |
-+{ |
13424 |
-+ struct kdbus_handle *handle = file->private_data; |
13425 |
-+ struct kdbus_node *node = file_inode(file)->i_private; |
13426 |
-+ struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node); |
13427 |
-+ struct kdbus_bus *bus = file_ep->bus; |
13428 |
-+ struct kdbus_conn *conn; |
13429 |
-+ int ret = 0; |
13430 |
-+ |
13431 |
-+ if (!kdbus_node_acquire(node)) |
13432 |
-+ return -ESHUTDOWN; |
13433 |
-+ |
13434 |
-+ switch (cmd) { |
13435 |
-+ case KDBUS_CMD_ENDPOINT_MAKE: { |
13436 |
-+ /* creating custom endpoints is a privileged operation */ |
13437 |
-+ if (!kdbus_ep_is_owner(file_ep, file)) { |
13438 |
-+ ret = -EPERM; |
13439 |
-+ break; |
13440 |
-+ } |
13441 |
-+ |
13442 |
-+ ep = kdbus_cmd_ep_make(bus, buf); |
13443 |
-+ if (IS_ERR_OR_NULL(ep)) { |
13444 |
-+ ret = PTR_ERR_OR_ZERO(ep); |
13445 |
-+ break; |
13446 |
-+ } |
13447 |
-+ |
13448 |
-+ handle->ep_owner = ep; |
13449 |
-+ ret = KDBUS_HANDLE_EP_OWNER; |
13450 |
-+ break; |
13451 |
-+ } |
13452 |
-+ |
13453 |
-+ case KDBUS_CMD_HELLO: |
13454 |
-+ conn = kdbus_cmd_hello(file_ep, file, buf); |
13455 |
-+ if (IS_ERR_OR_NULL(conn)) { |
13456 |
-+ ret = PTR_ERR_OR_ZERO(conn); |
13457 |
-+ break; |
13458 |
-+ } |
13459 |
-+ |
13460 |
-+ handle->conn = conn; |
13461 |
-+ ret = KDBUS_HANDLE_CONNECTED; |
13462 |
-+ break; |
13463 |
-+ |
13464 |
-+ default: |
13465 |
-+ ret = -EBADFD; |
13466 |
-+ break; |
13467 |
-+ } |
13468 |
-+ |
13469 |
-+ kdbus_node_release(node); |
13470 |
-+ return ret; |
13471 |
-+} |
13472 |
-+ |
13473 |
-+static long kdbus_handle_ioctl_ep_owner(struct file *file, unsigned int command, |
13474 |
-+ void __user *buf) |
13475 |
-+{ |
13476 |
-+ struct kdbus_handle *handle = file->private_data; |
13477 |
-+ struct kdbus_ep *ep = handle->ep_owner; |
13478 |
-+ int ret; |
13479 |
-+ |
13480 |
-+ if (!kdbus_node_acquire(&ep->node)) |
13481 |
-+ return -ESHUTDOWN; |
13482 |
-+ |
13483 |
-+ switch (command) { |
13484 |
-+ case KDBUS_CMD_ENDPOINT_UPDATE: |
13485 |
-+ ret = kdbus_cmd_ep_update(ep, buf); |
13486 |
-+ break; |
13487 |
-+ default: |
13488 |
-+ ret = -EBADFD; |
13489 |
-+ break; |
13490 |
-+ } |
13491 |
-+ |
13492 |
-+ kdbus_node_release(&ep->node); |
13493 |
-+ return ret; |
13494 |
-+} |
13495 |
-+ |
13496 |
-+static long kdbus_handle_ioctl_connected(struct file *file, |
13497 |
-+ unsigned int command, void __user *buf) |
13498 |
-+{ |
13499 |
-+ struct kdbus_handle *handle = file->private_data; |
13500 |
-+ struct kdbus_conn *conn = handle->conn; |
13501 |
-+ struct kdbus_conn *release_conn = NULL; |
13502 |
-+ int ret; |
13503 |
-+ |
13504 |
-+ release_conn = conn; |
13505 |
-+ ret = kdbus_conn_acquire(release_conn); |
13506 |
-+ if (ret < 0) |
13507 |
-+ return ret; |
13508 |
-+ |
13509 |
-+ switch (command) { |
13510 |
-+ case KDBUS_CMD_BYEBYE: |
13511 |
-+ /* |
13512 |
-+ * BYEBYE is special; we must not acquire a connection when |
13513 |
-+ * calling into kdbus_conn_disconnect() or we will deadlock, |
13514 |
-+ * because kdbus_conn_disconnect() will wait for all acquired |
13515 |
-+ * references to be dropped. |
13516 |
-+ */ |
13517 |
-+ kdbus_conn_release(release_conn); |
13518 |
-+ release_conn = NULL; |
13519 |
-+ ret = kdbus_cmd_byebye_unlocked(conn, buf); |
13520 |
-+ break; |
13521 |
-+ case KDBUS_CMD_NAME_ACQUIRE: |
13522 |
-+ ret = kdbus_cmd_name_acquire(conn, buf); |
13523 |
-+ break; |
13524 |
-+ case KDBUS_CMD_NAME_RELEASE: |
13525 |
-+ ret = kdbus_cmd_name_release(conn, buf); |
13526 |
-+ break; |
13527 |
-+ case KDBUS_CMD_LIST: |
13528 |
-+ ret = kdbus_cmd_list(conn, buf); |
13529 |
-+ break; |
13530 |
-+ case KDBUS_CMD_CONN_INFO: |
13531 |
-+ ret = kdbus_cmd_conn_info(conn, buf); |
13532 |
-+ break; |
13533 |
-+ case KDBUS_CMD_BUS_CREATOR_INFO: |
13534 |
-+ ret = kdbus_cmd_bus_creator_info(conn, buf); |
13535 |
-+ break; |
13536 |
-+ case KDBUS_CMD_UPDATE: |
13537 |
-+ ret = kdbus_cmd_update(conn, buf); |
13538 |
-+ break; |
13539 |
-+ case KDBUS_CMD_MATCH_ADD: |
13540 |
-+ ret = kdbus_cmd_match_add(conn, buf); |
13541 |
-+ break; |
13542 |
-+ case KDBUS_CMD_MATCH_REMOVE: |
13543 |
-+ ret = kdbus_cmd_match_remove(conn, buf); |
13544 |
-+ break; |
13545 |
-+ case KDBUS_CMD_SEND: |
13546 |
-+ ret = kdbus_cmd_send(conn, file, buf); |
13547 |
-+ break; |
13548 |
-+ case KDBUS_CMD_RECV: |
13549 |
-+ ret = kdbus_cmd_recv(conn, buf); |
13550 |
-+ break; |
13551 |
-+ case KDBUS_CMD_FREE: |
13552 |
-+ ret = kdbus_cmd_free(conn, buf); |
13553 |
-+ break; |
13554 |
-+ default: |
13555 |
-+ ret = -EBADFD; |
13556 |
-+ break; |
13557 |
-+ } |
13558 |
-+ |
13559 |
-+ kdbus_conn_release(release_conn); |
13560 |
-+ return ret; |
13561 |
-+} |
13562 |
-+ |
13563 |
-+static long kdbus_handle_ioctl(struct file *file, unsigned int cmd, |
13564 |
-+ unsigned long arg) |
13565 |
-+{ |
13566 |
-+ struct kdbus_handle *handle = file->private_data; |
13567 |
-+ struct kdbus_node *node = kdbus_node_from_inode(file_inode(file)); |
13568 |
-+ void __user *argp = (void __user *)arg; |
13569 |
-+ long ret = -EBADFD; |
13570 |
-+ |
13571 |
-+ switch (cmd) { |
13572 |
-+ case KDBUS_CMD_BUS_MAKE: |
13573 |
-+ case KDBUS_CMD_ENDPOINT_MAKE: |
13574 |
-+ case KDBUS_CMD_HELLO: |
13575 |
-+ mutex_lock(&handle->lock); |
13576 |
-+ if (handle->type == KDBUS_HANDLE_NONE) { |
13577 |
-+ if (node->type == KDBUS_NODE_CONTROL) |
13578 |
-+ ret = kdbus_handle_ioctl_control(file, cmd, |
13579 |
-+ argp); |
13580 |
-+ else if (node->type == KDBUS_NODE_ENDPOINT) |
13581 |
-+ ret = kdbus_handle_ioctl_ep(file, cmd, argp); |
13582 |
-+ |
13583 |
-+ if (ret > 0) { |
13584 |
-+ /* |
13585 |
-+ * The data given via open() is not sufficient |
13586 |
-+ * to setup a kdbus handle. Hence, we require |
13587 |
-+ * the user to perform a setup ioctl. This setup |
13588 |
-+ * can only be performed once and defines the |
13589 |
-+ * type of the handle. The different setup |
13590 |
-+ * ioctls are locked against each other so they |
13591 |
-+ * cannot race. Once the handle type is set, |
13592 |
-+ * the type-dependent ioctls are enabled. To |
13593 |
-+ * improve performance, we don't lock those via |
13594 |
-+ * handle->lock. Instead, we issue a |
13595 |
-+ * write-barrier before performing the |
13596 |
-+ * type-change, which pairs with smp_rmb() in |
13597 |
-+ * all handlers that access the type field. This |
13598 |
-+ * guarantees the handle is fully setup, if |
13599 |
-+ * handle->type is set. If handle->type is |
13600 |
-+ * unset, you must not make any assumptions |
13601 |
-+ * without taking handle->lock. |
13602 |
-+ * Note that handle->type is only set once. It |
13603 |
-+ * will never change afterwards. |
13604 |
-+ */ |
13605 |
-+ smp_wmb(); |
13606 |
-+ handle->type = ret; |
13607 |
-+ } |
13608 |
-+ } |
13609 |
-+ mutex_unlock(&handle->lock); |
13610 |
-+ break; |
13611 |
-+ |
13612 |
-+ case KDBUS_CMD_ENDPOINT_UPDATE: |
13613 |
-+ case KDBUS_CMD_BYEBYE: |
13614 |
-+ case KDBUS_CMD_NAME_ACQUIRE: |
13615 |
-+ case KDBUS_CMD_NAME_RELEASE: |
13616 |
-+ case KDBUS_CMD_LIST: |
13617 |
-+ case KDBUS_CMD_CONN_INFO: |
13618 |
-+ case KDBUS_CMD_BUS_CREATOR_INFO: |
13619 |
-+ case KDBUS_CMD_UPDATE: |
13620 |
-+ case KDBUS_CMD_MATCH_ADD: |
13621 |
-+ case KDBUS_CMD_MATCH_REMOVE: |
13622 |
-+ case KDBUS_CMD_SEND: |
13623 |
-+ case KDBUS_CMD_RECV: |
13624 |
-+ case KDBUS_CMD_FREE: { |
13625 |
-+ enum kdbus_handle_type type; |
13626 |
-+ |
13627 |
-+ /* |
13628 |
-+ * This read-barrier pairs with smp_wmb() of the handle setup. |
13629 |
-+ * it guarantees the handle is fully written, in case the |
13630 |
-+ * type has been set. It allows us to access the handle without |
13631 |
-+ * taking handle->lock, given the guarantee that the type is |
13632 |
-+ * only ever set once, and stays constant afterwards. |
13633 |
-+ * Furthermore, the handle object itself is not modified in any |
13634 |
-+ * way after the type is set. That is, the type-field is the |
13635 |
-+ * last field that is written on any handle. If it has not been |
13636 |
-+ * set, we must not access the handle here. |
13637 |
-+ */ |
13638 |
-+ type = handle->type; |
13639 |
-+ smp_rmb(); |
13640 |
-+ |
13641 |
-+ if (type == KDBUS_HANDLE_EP_OWNER) |
13642 |
-+ ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp); |
13643 |
-+ else if (type == KDBUS_HANDLE_CONNECTED) |
13644 |
-+ ret = kdbus_handle_ioctl_connected(file, cmd, argp); |
13645 |
-+ |
13646 |
-+ break; |
13647 |
-+ } |
13648 |
-+ default: |
13649 |
-+ ret = -ENOTTY; |
13650 |
-+ break; |
13651 |
-+ } |
13652 |
-+ |
13653 |
-+ return ret < 0 ? ret : 0; |
13654 |
-+} |
13655 |
-+ |
13656 |
-+static unsigned int kdbus_handle_poll(struct file *file, |
13657 |
-+ struct poll_table_struct *wait) |
13658 |
-+{ |
13659 |
-+ struct kdbus_handle *handle = file->private_data; |
13660 |
-+ enum kdbus_handle_type type; |
13661 |
-+ unsigned int mask = POLLOUT | POLLWRNORM; |
13662 |
-+ |
13663 |
-+ /* |
13664 |
-+ * This pairs with smp_wmb() during handle setup. It guarantees that |
13665 |
-+ * _iff_ the handle type is set, handle->conn is valid. Furthermore, |
13666 |
-+ * _iff_ the type is set, the handle object is constant and never |
13667 |
-+ * changed again. If it's not set, we must not access the handle but |
13668 |
-+ * bail out. We also must assume no setup has taken place, yet. |
13669 |
-+ */ |
13670 |
-+ type = handle->type; |
13671 |
-+ smp_rmb(); |
13672 |
-+ |
13673 |
-+ /* Only a connected endpoint can read/write data */ |
13674 |
-+ if (type != KDBUS_HANDLE_CONNECTED) |
13675 |
-+ return POLLERR | POLLHUP; |
13676 |
-+ |
13677 |
-+ poll_wait(file, &handle->conn->wait, wait); |
13678 |
-+ |
13679 |
-+ /* |
13680 |
-+ * Verify the connection hasn't been deactivated _after_ adding the |
13681 |
-+ * wait-queue. This guarantees, that if the connection is deactivated |
13682 |
-+ * after we checked it, the waitqueue is signaled and we're called |
13683 |
-+ * again. |
13684 |
-+ */ |
13685 |
-+ if (!kdbus_conn_active(handle->conn)) |
13686 |
-+ return POLLERR | POLLHUP; |
13687 |
-+ |
13688 |
-+ if (!list_empty(&handle->conn->queue.msg_list) || |
13689 |
-+ atomic_read(&handle->conn->lost_count) > 0) |
13690 |
-+ mask |= POLLIN | POLLRDNORM; |
13691 |
-+ |
13692 |
-+ return mask; |
13693 |
-+} |
13694 |
-+ |
13695 |
-+static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma) |
13696 |
-+{ |
13697 |
-+ struct kdbus_handle *handle = file->private_data; |
13698 |
-+ enum kdbus_handle_type type; |
13699 |
-+ int ret = -EBADFD; |
13700 |
-+ |
13701 |
-+ /* |
13702 |
-+ * This pairs with smp_wmb() during handle setup. It guarantees that |
13703 |
-+ * _iff_ the handle type is set, handle->conn is valid. Furthermore, |
13704 |
-+ * _iff_ the type is set, the handle object is constant and never |
13705 |
-+ * changed again. If it's not set, we must not access the handle but |
13706 |
-+ * bail out. We also must assume no setup has taken place, yet. |
13707 |
-+ */ |
13708 |
-+ type = handle->type; |
13709 |
-+ smp_rmb(); |
13710 |
-+ |
13711 |
-+ /* Only connected handles have a pool we can map */ |
13712 |
-+ if (type == KDBUS_HANDLE_CONNECTED) |
13713 |
-+ ret = kdbus_pool_mmap(handle->conn->pool, vma); |
13714 |
-+ |
13715 |
-+ return ret; |
13716 |
-+} |
13717 |
-+ |
13718 |
-+const struct file_operations kdbus_handle_ops = { |
13719 |
-+ .owner = THIS_MODULE, |
13720 |
-+ .open = kdbus_handle_open, |
13721 |
-+ .release = kdbus_handle_release, |
13722 |
-+ .poll = kdbus_handle_poll, |
13723 |
-+ .llseek = noop_llseek, |
13724 |
-+ .unlocked_ioctl = kdbus_handle_ioctl, |
13725 |
-+ .mmap = kdbus_handle_mmap, |
13726 |
-+#ifdef CONFIG_COMPAT |
13727 |
-+ .compat_ioctl = kdbus_handle_ioctl, |
13728 |
-+#endif |
13729 |
-+}; |
13730 |
-diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h |
13731 |
-new file mode 100644 |
13732 |
-index 0000000..5dde2c1 |
13733 |
---- /dev/null |
13734 |
-+++ b/ipc/kdbus/handle.h |
13735 |
-@@ -0,0 +1,103 @@ |
13736 |
-+/* |
13737 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13738 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13739 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13740 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13741 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13742 |
-+ * |
13743 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13744 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13745 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13746 |
-+ * your option) any later version. |
13747 |
-+ */ |
13748 |
-+ |
13749 |
-+#ifndef __KDBUS_HANDLE_H |
13750 |
-+#define __KDBUS_HANDLE_H |
13751 |
-+ |
13752 |
-+#include <linux/fs.h> |
13753 |
-+#include <uapi/linux/kdbus.h> |
13754 |
-+ |
13755 |
-+extern const struct file_operations kdbus_handle_ops; |
13756 |
-+ |
13757 |
-+/** |
13758 |
-+ * kdbus_arg - information and state of a single ioctl command item |
13759 |
-+ * @type: item type |
13760 |
-+ * @item: set by the parser to the first found item of this type |
13761 |
-+ * @multiple: whether multiple items of this type are allowed |
13762 |
-+ * @mandatory: whether at least one item of this type is required |
13763 |
-+ * |
13764 |
-+ * This structure describes a single item in an ioctl command payload. The |
13765 |
-+ * caller has to pre-fill the type and flags, the parser will then use this |
13766 |
-+ * information to verify the ioctl payload. @item is set by the parser to point |
13767 |
-+ * to the first occurrence of the item. |
13768 |
-+ */ |
13769 |
-+struct kdbus_arg { |
13770 |
-+ u64 type; |
13771 |
-+ struct kdbus_item *item; |
13772 |
-+ bool multiple : 1; |
13773 |
-+ bool mandatory : 1; |
13774 |
-+}; |
13775 |
-+ |
13776 |
-+/** |
13777 |
-+ * kdbus_args - information and state of ioctl command parser |
13778 |
-+ * @allowed_flags: set of flags this command supports |
13779 |
-+ * @argc: number of items in @argv |
13780 |
-+ * @argv: array of items this command supports |
13781 |
-+ * @user: set by parser to user-space location of current command |
13782 |
-+ * @cmd: set by parser to kernel copy of command payload |
13783 |
-+ * @cmd_buf: inline buf to avoid kmalloc() on small cmds |
13784 |
-+ * @items: points to item array in @cmd |
13785 |
-+ * @items_size: size of @items in bytes |
13786 |
-+ * @is_cmd: whether this is a command-payload or msg-payload |
13787 |
-+ * |
13788 |
-+ * This structure is used to parse ioctl command payloads on each invocation. |
13789 |
-+ * The ioctl handler has to pre-fill the flags and allowed items before passing |
13790 |
-+ * the object to kdbus_args_parse(). The parser will copy the command payload |
13791 |
-+ * into kernel-space and verify the correctness of the data. |
13792 |
-+ * |
13793 |
-+ * We use a 256 bytes buffer for small command payloads, to be allocated on |
13794 |
-+ * stack on syscall entrance. |
13795 |
-+ */ |
13796 |
-+struct kdbus_args { |
13797 |
-+ u64 allowed_flags; |
13798 |
-+ size_t argc; |
13799 |
-+ struct kdbus_arg *argv; |
13800 |
-+ |
13801 |
-+ struct kdbus_cmd __user *user; |
13802 |
-+ struct kdbus_cmd *cmd; |
13803 |
-+ u8 cmd_buf[256]; |
13804 |
-+ |
13805 |
-+ struct kdbus_item *items; |
13806 |
-+ size_t items_size; |
13807 |
-+ bool is_cmd : 1; |
13808 |
-+}; |
13809 |
-+ |
13810 |
-+int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp, |
13811 |
-+ size_t type_size, size_t items_offset, void **out); |
13812 |
-+int kdbus_args_clear(struct kdbus_args *args, int ret); |
13813 |
-+ |
13814 |
-+#define kdbus_args_parse(_args, _argp, _v) \ |
13815 |
-+ ({ \ |
13816 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ |
13817 |
-+ offsetof(struct kdbus_cmd, size)); \ |
13818 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ |
13819 |
-+ offsetof(struct kdbus_cmd, flags)); \ |
13820 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), return_flags) != \ |
13821 |
-+ offsetof(struct kdbus_cmd, return_flags)); \ |
13822 |
-+ __kdbus_args_parse((_args), 1, (_argp), sizeof(**(_v)), \ |
13823 |
-+ offsetof(typeof(**(_v)), items), \ |
13824 |
-+ (void **)(_v)); \ |
13825 |
-+ }) |
13826 |
-+ |
13827 |
-+#define kdbus_args_parse_msg(_args, _argp, _v) \ |
13828 |
-+ ({ \ |
13829 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ |
13830 |
-+ offsetof(struct kdbus_cmd, size)); \ |
13831 |
-+ BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ |
13832 |
-+ offsetof(struct kdbus_cmd, flags)); \ |
13833 |
-+ __kdbus_args_parse((_args), 0, (_argp), sizeof(**(_v)), \ |
13834 |
-+ offsetof(typeof(**(_v)), items), \ |
13835 |
-+ (void **)(_v)); \ |
13836 |
-+ }) |
13837 |
-+ |
13838 |
-+#endif |
13839 |
-diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c |
13840 |
-new file mode 100644 |
13841 |
-index 0000000..ce78dba |
13842 |
---- /dev/null |
13843 |
-+++ b/ipc/kdbus/item.c |
13844 |
-@@ -0,0 +1,293 @@ |
13845 |
-+/* |
13846 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
13847 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
13848 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
13849 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
13850 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
13851 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
13852 |
-+ * |
13853 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
13854 |
-+ * the terms of the GNU Lesser General Public License as published by the |
13855 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
13856 |
-+ * your option) any later version. |
13857 |
-+ */ |
13858 |
-+ |
13859 |
-+#include <linux/ctype.h> |
13860 |
-+#include <linux/fs.h> |
13861 |
-+#include <linux/string.h> |
13862 |
-+ |
13863 |
-+#include "item.h" |
13864 |
-+#include "limits.h" |
13865 |
-+#include "util.h" |
13866 |
-+ |
13867 |
-+/* |
13868 |
-+ * This verifies the string at position @str with size @size is properly |
13869 |
-+ * zero-terminated and does not contain a 0-byte but at the end. |
13870 |
-+ */ |
13871 |
-+static bool kdbus_str_valid(const char *str, size_t size) |
13872 |
-+{ |
13873 |
-+ return size > 0 && memchr(str, '\0', size) == str + size - 1; |
13874 |
-+} |
13875 |
-+ |
13876 |
-+/** |
13877 |
-+ * kdbus_item_validate_name() - validate an item containing a name |
13878 |
-+ * @item: Item to validate |
13879 |
-+ * |
13880 |
-+ * Return: zero on success or an negative error code on failure |
13881 |
-+ */ |
13882 |
-+int kdbus_item_validate_name(const struct kdbus_item *item) |
13883 |
-+{ |
13884 |
-+ const char *name = item->str; |
13885 |
-+ unsigned int i; |
13886 |
-+ size_t len; |
13887 |
-+ |
13888 |
-+ if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) |
13889 |
-+ return -EINVAL; |
13890 |
-+ |
13891 |
-+ if (item->size > KDBUS_ITEM_HEADER_SIZE + |
13892 |
-+ KDBUS_SYSNAME_MAX_LEN + 1) |
13893 |
-+ return -ENAMETOOLONG; |
13894 |
-+ |
13895 |
-+ if (!kdbus_str_valid(name, KDBUS_ITEM_PAYLOAD_SIZE(item))) |
13896 |
-+ return -EINVAL; |
13897 |
-+ |
13898 |
-+ len = strlen(name); |
13899 |
-+ if (len == 0) |
13900 |
-+ return -EINVAL; |
13901 |
-+ |
13902 |
-+ for (i = 0; i < len; i++) { |
13903 |
-+ if (isalpha(name[i])) |
13904 |
-+ continue; |
13905 |
-+ if (isdigit(name[i])) |
13906 |
-+ continue; |
13907 |
-+ if (name[i] == '_') |
13908 |
-+ continue; |
13909 |
-+ if (i > 0 && i + 1 < len && (name[i] == '-' || name[i] == '.')) |
13910 |
-+ continue; |
13911 |
-+ |
13912 |
-+ return -EINVAL; |
13913 |
-+ } |
13914 |
-+ |
13915 |
-+ return 0; |
13916 |
-+} |
13917 |
-+ |
13918 |
-+/** |
13919 |
-+ * kdbus_item_validate() - validate a single item |
13920 |
-+ * @item: item to validate |
13921 |
-+ * |
13922 |
-+ * Return: 0 if item is valid, negative error code if not. |
13923 |
-+ */ |
13924 |
-+int kdbus_item_validate(const struct kdbus_item *item) |
13925 |
-+{ |
13926 |
-+ size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item); |
13927 |
-+ size_t l; |
13928 |
-+ int ret; |
13929 |
-+ |
13930 |
-+ BUILD_BUG_ON(KDBUS_ITEM_HEADER_SIZE != |
13931 |
-+ sizeof(struct kdbus_item_header)); |
13932 |
-+ |
13933 |
-+ if (item->size < KDBUS_ITEM_HEADER_SIZE) |
13934 |
-+ return -EINVAL; |
13935 |
-+ |
13936 |
-+ switch (item->type) { |
13937 |
-+ case KDBUS_ITEM_NEGOTIATE: |
13938 |
-+ if (payload_size % sizeof(u64) != 0) |
13939 |
-+ return -EINVAL; |
13940 |
-+ break; |
13941 |
-+ |
13942 |
-+ case KDBUS_ITEM_PAYLOAD_VEC: |
13943 |
-+ case KDBUS_ITEM_PAYLOAD_OFF: |
13944 |
-+ if (payload_size != sizeof(struct kdbus_vec)) |
13945 |
-+ return -EINVAL; |
13946 |
-+ if (item->vec.size == 0 || item->vec.size > SIZE_MAX) |
13947 |
-+ return -EINVAL; |
13948 |
-+ break; |
13949 |
-+ |
13950 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: |
13951 |
-+ if (payload_size != sizeof(struct kdbus_memfd)) |
13952 |
-+ return -EINVAL; |
13953 |
-+ if (item->memfd.size == 0 || item->memfd.size > SIZE_MAX) |
13954 |
-+ return -EINVAL; |
13955 |
-+ if (item->memfd.fd < 0) |
13956 |
-+ return -EBADF; |
13957 |
-+ break; |
13958 |
-+ |
13959 |
-+ case KDBUS_ITEM_FDS: |
13960 |
-+ if (payload_size % sizeof(int) != 0) |
13961 |
-+ return -EINVAL; |
13962 |
-+ break; |
13963 |
-+ |
13964 |
-+ case KDBUS_ITEM_CANCEL_FD: |
13965 |
-+ if (payload_size != sizeof(int)) |
13966 |
-+ return -EINVAL; |
13967 |
-+ break; |
13968 |
-+ |
13969 |
-+ case KDBUS_ITEM_BLOOM_PARAMETER: |
13970 |
-+ if (payload_size != sizeof(struct kdbus_bloom_parameter)) |
13971 |
-+ return -EINVAL; |
13972 |
-+ break; |
13973 |
-+ |
13974 |
-+ case KDBUS_ITEM_BLOOM_FILTER: |
13975 |
-+ /* followed by the bloom-mask, depends on the bloom-size */ |
13976 |
-+ if (payload_size < sizeof(struct kdbus_bloom_filter)) |
13977 |
-+ return -EINVAL; |
13978 |
-+ break; |
13979 |
-+ |
13980 |
-+ case KDBUS_ITEM_BLOOM_MASK: |
13981 |
-+ /* size depends on bloom-size of bus */ |
13982 |
-+ break; |
13983 |
-+ |
13984 |
-+ case KDBUS_ITEM_CONN_DESCRIPTION: |
13985 |
-+ case KDBUS_ITEM_MAKE_NAME: |
13986 |
-+ ret = kdbus_item_validate_name(item); |
13987 |
-+ if (ret < 0) |
13988 |
-+ return ret; |
13989 |
-+ break; |
13990 |
-+ |
13991 |
-+ case KDBUS_ITEM_ATTACH_FLAGS_SEND: |
13992 |
-+ case KDBUS_ITEM_ATTACH_FLAGS_RECV: |
13993 |
-+ case KDBUS_ITEM_ID: |
13994 |
-+ case KDBUS_ITEM_DST_ID: |
13995 |
-+ if (payload_size != sizeof(u64)) |
13996 |
-+ return -EINVAL; |
13997 |
-+ break; |
13998 |
-+ |
13999 |
-+ case KDBUS_ITEM_TIMESTAMP: |
14000 |
-+ if (payload_size != sizeof(struct kdbus_timestamp)) |
14001 |
-+ return -EINVAL; |
14002 |
-+ break; |
14003 |
-+ |
14004 |
-+ case KDBUS_ITEM_CREDS: |
14005 |
-+ if (payload_size != sizeof(struct kdbus_creds)) |
14006 |
-+ return -EINVAL; |
14007 |
-+ break; |
14008 |
-+ |
14009 |
-+ case KDBUS_ITEM_AUXGROUPS: |
14010 |
-+ if (payload_size % sizeof(u32) != 0) |
14011 |
-+ return -EINVAL; |
14012 |
-+ break; |
14013 |
-+ |
14014 |
-+ case KDBUS_ITEM_NAME: |
14015 |
-+ case KDBUS_ITEM_DST_NAME: |
14016 |
-+ case KDBUS_ITEM_PID_COMM: |
14017 |
-+ case KDBUS_ITEM_TID_COMM: |
14018 |
-+ case KDBUS_ITEM_EXE: |
14019 |
-+ case KDBUS_ITEM_CMDLINE: |
14020 |
-+ case KDBUS_ITEM_CGROUP: |
14021 |
-+ case KDBUS_ITEM_SECLABEL: |
14022 |
-+ if (!kdbus_str_valid(item->str, payload_size)) |
14023 |
-+ return -EINVAL; |
14024 |
-+ break; |
14025 |
-+ |
14026 |
-+ case KDBUS_ITEM_CAPS: |
14027 |
-+ if (payload_size < sizeof(u32)) |
14028 |
-+ return -EINVAL; |
14029 |
-+ if (payload_size < sizeof(u32) + |
14030 |
-+ 4 * CAP_TO_INDEX(item->caps.last_cap) * sizeof(u32)) |
14031 |
-+ return -EINVAL; |
14032 |
-+ break; |
14033 |
-+ |
14034 |
-+ case KDBUS_ITEM_AUDIT: |
14035 |
-+ if (payload_size != sizeof(struct kdbus_audit)) |
14036 |
-+ return -EINVAL; |
14037 |
-+ break; |
14038 |
-+ |
14039 |
-+ case KDBUS_ITEM_POLICY_ACCESS: |
14040 |
-+ if (payload_size != sizeof(struct kdbus_policy_access)) |
14041 |
-+ return -EINVAL; |
14042 |
-+ break; |
14043 |
-+ |
14044 |
-+ case KDBUS_ITEM_NAME_ADD: |
14045 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14046 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14047 |
-+ if (payload_size < sizeof(struct kdbus_notify_name_change)) |
14048 |
-+ return -EINVAL; |
14049 |
-+ l = payload_size - offsetof(struct kdbus_notify_name_change, |
14050 |
-+ name); |
14051 |
-+ if (l > 0 && !kdbus_str_valid(item->name_change.name, l)) |
14052 |
-+ return -EINVAL; |
14053 |
-+ break; |
14054 |
-+ |
14055 |
-+ case KDBUS_ITEM_ID_ADD: |
14056 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14057 |
-+ if (payload_size != sizeof(struct kdbus_notify_id_change)) |
14058 |
-+ return -EINVAL; |
14059 |
-+ break; |
14060 |
-+ |
14061 |
-+ case KDBUS_ITEM_REPLY_TIMEOUT: |
14062 |
-+ case KDBUS_ITEM_REPLY_DEAD: |
14063 |
-+ if (payload_size != 0) |
14064 |
-+ return -EINVAL; |
14065 |
-+ break; |
14066 |
-+ |
14067 |
-+ default: |
14068 |
-+ break; |
14069 |
-+ } |
14070 |
-+ |
14071 |
-+ return 0; |
14072 |
-+} |
14073 |
-+ |
14074 |
-+/** |
14075 |
-+ * kdbus_items_validate() - validate items passed by user-space |
14076 |
-+ * @items: items to validate |
14077 |
-+ * @items_size: number of items |
14078 |
-+ * |
14079 |
-+ * This verifies that the passed items pointer is consistent and valid. |
14080 |
-+ * Furthermore, each item is checked for: |
14081 |
-+ * - valid "size" value |
14082 |
-+ * - payload is of expected type |
14083 |
-+ * - payload is fully included in the item |
14084 |
-+ * - string payloads are zero-terminated |
14085 |
-+ * |
14086 |
-+ * Return: 0 on success, negative error code on failure. |
14087 |
-+ */ |
14088 |
-+int kdbus_items_validate(const struct kdbus_item *items, size_t items_size) |
14089 |
-+{ |
14090 |
-+ const struct kdbus_item *item; |
14091 |
-+ int ret; |
14092 |
-+ |
14093 |
-+ KDBUS_ITEMS_FOREACH(item, items, items_size) { |
14094 |
-+ if (!KDBUS_ITEM_VALID(item, items, items_size)) |
14095 |
-+ return -EINVAL; |
14096 |
-+ |
14097 |
-+ ret = kdbus_item_validate(item); |
14098 |
-+ if (ret < 0) |
14099 |
-+ return ret; |
14100 |
-+ } |
14101 |
-+ |
14102 |
-+ if (!KDBUS_ITEMS_END(item, items, items_size)) |
14103 |
-+ return -EINVAL; |
14104 |
-+ |
14105 |
-+ return 0; |
14106 |
-+} |
14107 |
-+ |
14108 |
-+/** |
14109 |
-+ * kdbus_item_set() - Set item content |
14110 |
-+ * @item: The item to modify |
14111 |
-+ * @type: The item type to set (KDBUS_ITEM_*) |
14112 |
-+ * @data: Data to copy to item->data, may be %NULL |
14113 |
-+ * @len: Number of bytes in @data |
14114 |
-+ * |
14115 |
-+ * This sets type, size and data fields of an item. If @data is NULL, the data |
14116 |
-+ * memory is cleared. |
14117 |
-+ * |
14118 |
-+ * Note that you must align your @data memory to 8 bytes. Trailing padding (in |
14119 |
-+ * case @len is not 8byte aligned) is cleared by this call. |
14120 |
-+ * |
14121 |
-+ * Returns: Pointer to the following item. |
14122 |
-+ */ |
14123 |
-+struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, |
14124 |
-+ const void *data, size_t len) |
14125 |
-+{ |
14126 |
-+ item->type = type; |
14127 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + len; |
14128 |
-+ |
14129 |
-+ if (data) { |
14130 |
-+ memcpy(item->data, data, len); |
14131 |
-+ memset(item->data + len, 0, KDBUS_ALIGN8(len) - len); |
14132 |
-+ } else { |
14133 |
-+ memset(item->data, 0, KDBUS_ALIGN8(len)); |
14134 |
-+ } |
14135 |
-+ |
14136 |
-+ return KDBUS_ITEM_NEXT(item); |
14137 |
-+} |
14138 |
-diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h |
14139 |
-new file mode 100644 |
14140 |
-index 0000000..3a7e6cc |
14141 |
---- /dev/null |
14142 |
-+++ b/ipc/kdbus/item.h |
14143 |
-@@ -0,0 +1,61 @@ |
14144 |
-+/* |
14145 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14146 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14147 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14148 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14149 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14150 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14151 |
-+ * |
14152 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14153 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14154 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14155 |
-+ * your option) any later version. |
14156 |
-+ */ |
14157 |
-+ |
14158 |
-+#ifndef __KDBUS_ITEM_H |
14159 |
-+#define __KDBUS_ITEM_H |
14160 |
-+ |
14161 |
-+#include <linux/kernel.h> |
14162 |
-+#include <uapi/linux/kdbus.h> |
14163 |
-+ |
14164 |
-+#include "util.h" |
14165 |
-+ |
14166 |
-+/* generic access and iterators over a stream of items */ |
14167 |
-+#define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size)) |
14168 |
-+#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is)) |
14169 |
-+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
14170 |
-+#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s)) |
14171 |
-+#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE) |
14172 |
-+ |
14173 |
-+#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \ |
14174 |
-+ for ((_i) = (_is); \ |
14175 |
-+ ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \ |
14176 |
-+ ((u8 *)(_i) >= (u8 *)(_is)); \ |
14177 |
-+ (_i) = KDBUS_ITEM_NEXT(_i)) |
14178 |
-+ |
14179 |
-+#define KDBUS_ITEM_VALID(_i, _is, _s) \ |
14180 |
-+ ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \ |
14181 |
-+ (u8 *)(_i) + (_i)->size > (u8 *)(_i) && \ |
14182 |
-+ (u8 *)(_i) + (_i)->size <= (u8 *)(_is) + (_s) && \ |
14183 |
-+ (u8 *)(_i) >= (u8 *)(_is)) |
14184 |
-+ |
14185 |
-+#define KDBUS_ITEMS_END(_i, _is, _s) \ |
14186 |
-+ ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s))) |
14187 |
-+ |
14188 |
-+/** |
14189 |
-+ * struct kdbus_item_header - Describes the fix part of an item |
14190 |
-+ * @size: The total size of the item |
14191 |
-+ * @type: The item type, one of KDBUS_ITEM_* |
14192 |
-+ */ |
14193 |
-+struct kdbus_item_header { |
14194 |
-+ u64 size; |
14195 |
-+ u64 type; |
14196 |
-+}; |
14197 |
-+ |
14198 |
-+int kdbus_item_validate_name(const struct kdbus_item *item); |
14199 |
-+int kdbus_item_validate(const struct kdbus_item *item); |
14200 |
-+int kdbus_items_validate(const struct kdbus_item *items, size_t items_size); |
14201 |
-+struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, |
14202 |
-+ const void *data, size_t len); |
14203 |
-+ |
14204 |
-+#endif |
14205 |
-diff --git a/ipc/kdbus/limits.h b/ipc/kdbus/limits.h |
14206 |
-new file mode 100644 |
14207 |
-index 0000000..c54925a |
14208 |
---- /dev/null |
14209 |
-+++ b/ipc/kdbus/limits.h |
14210 |
-@@ -0,0 +1,61 @@ |
14211 |
-+/* |
14212 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14213 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14214 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14215 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14216 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14217 |
-+ * |
14218 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14219 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14220 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14221 |
-+ * your option) any later version. |
14222 |
-+ */ |
14223 |
-+ |
14224 |
-+#ifndef __KDBUS_DEFAULTS_H |
14225 |
-+#define __KDBUS_DEFAULTS_H |
14226 |
-+ |
14227 |
-+#include <linux/kernel.h> |
14228 |
-+ |
14229 |
-+/* maximum size of message header and items */ |
14230 |
-+#define KDBUS_MSG_MAX_SIZE SZ_8K |
14231 |
-+ |
14232 |
-+/* maximum number of memfd items per message */ |
14233 |
-+#define KDBUS_MSG_MAX_MEMFD_ITEMS 16 |
14234 |
-+ |
14235 |
-+/* max size of ioctl command data */ |
14236 |
-+#define KDBUS_CMD_MAX_SIZE SZ_32K |
14237 |
-+ |
14238 |
-+/* maximum number of inflight fds in a target queue per user */ |
14239 |
-+#define KDBUS_CONN_MAX_FDS_PER_USER 16 |
14240 |
-+ |
14241 |
-+/* maximum message payload size */ |
14242 |
-+#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE SZ_2M |
14243 |
-+ |
14244 |
-+/* maximum size of bloom bit field in bytes */ |
14245 |
-+#define KDBUS_BUS_BLOOM_MAX_SIZE SZ_4K |
14246 |
-+ |
14247 |
-+/* maximum length of well-known bus name */ |
14248 |
-+#define KDBUS_NAME_MAX_LEN 255 |
14249 |
-+ |
14250 |
-+/* maximum length of bus, domain, ep name */ |
14251 |
-+#define KDBUS_SYSNAME_MAX_LEN 63 |
14252 |
-+ |
14253 |
-+/* maximum number of matches per connection */ |
14254 |
-+#define KDBUS_MATCH_MAX 256 |
14255 |
-+ |
14256 |
-+/* maximum number of queued messages from the same individual user */ |
14257 |
-+#define KDBUS_CONN_MAX_MSGS 256 |
14258 |
-+ |
14259 |
-+/* maximum number of well-known names per connection */ |
14260 |
-+#define KDBUS_CONN_MAX_NAMES 256 |
14261 |
-+ |
14262 |
-+/* maximum number of queued requests waiting for a reply */ |
14263 |
-+#define KDBUS_CONN_MAX_REQUESTS_PENDING 128 |
14264 |
-+ |
14265 |
-+/* maximum number of connections per user in one domain */ |
14266 |
-+#define KDBUS_USER_MAX_CONN 1024 |
14267 |
-+ |
14268 |
-+/* maximum number of buses per user in one domain */ |
14269 |
-+#define KDBUS_USER_MAX_BUSES 16 |
14270 |
-+ |
14271 |
-+#endif |
14272 |
-diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c |
14273 |
-new file mode 100644 |
14274 |
-index 0000000..1ad4dc8 |
14275 |
---- /dev/null |
14276 |
-+++ b/ipc/kdbus/main.c |
14277 |
-@@ -0,0 +1,114 @@ |
14278 |
-+/* |
14279 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14280 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14281 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14282 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14283 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14284 |
-+ * |
14285 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14286 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14287 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14288 |
-+ * your option) any later version. |
14289 |
-+ */ |
14290 |
-+ |
14291 |
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14292 |
-+#include <linux/fs.h> |
14293 |
-+#include <linux/init.h> |
14294 |
-+#include <linux/module.h> |
14295 |
-+ |
14296 |
-+#include "util.h" |
14297 |
-+#include "fs.h" |
14298 |
-+#include "handle.h" |
14299 |
-+#include "metadata.h" |
14300 |
-+#include "node.h" |
14301 |
-+ |
14302 |
-+/* |
14303 |
-+ * This is a simplified outline of the internal kdbus object relations, for |
14304 |
-+ * those interested in the inner life of the driver implementation. |
14305 |
-+ * |
14306 |
-+ * From a mount point's (domain's) perspective: |
14307 |
-+ * |
14308 |
-+ * struct kdbus_domain |
14309 |
-+ * |» struct kdbus_user *user (many, owned) |
14310 |
-+ * '» struct kdbus_node node (embedded) |
14311 |
-+ * |» struct kdbus_node children (many, referenced) |
14312 |
-+ * |» struct kdbus_node *parent (pinned) |
14313 |
-+ * '» struct kdbus_bus (many, pinned) |
14314 |
-+ * |» struct kdbus_node node (embedded) |
14315 |
-+ * '» struct kdbus_ep (many, pinned) |
14316 |
-+ * |» struct kdbus_node node (embedded) |
14317 |
-+ * |» struct kdbus_bus *bus (pinned) |
14318 |
-+ * |» struct kdbus_conn conn_list (many, pinned) |
14319 |
-+ * | |» struct kdbus_ep *ep (pinned) |
14320 |
-+ * | |» struct kdbus_name_entry *activator_of (owned) |
14321 |
-+ * | |» struct kdbus_match_db *match_db (owned) |
14322 |
-+ * | |» struct kdbus_meta *meta (owned) |
14323 |
-+ * | |» struct kdbus_match_db *match_db (owned) |
14324 |
-+ * | | '» struct kdbus_match_entry (many, owned) |
14325 |
-+ * | | |
14326 |
-+ * | |» struct kdbus_pool *pool (owned) |
14327 |
-+ * | | '» struct kdbus_pool_slice *slices (many, owned) |
14328 |
-+ * | | '» struct kdbus_pool *pool (pinned) |
14329 |
-+ * | | |
14330 |
-+ * | |» struct kdbus_user *user (pinned) |
14331 |
-+ * | `» struct kdbus_queue_entry entries (many, embedded) |
14332 |
-+ * | |» struct kdbus_pool_slice *slice (pinned) |
14333 |
-+ * | |» struct kdbus_conn_reply *reply (owned) |
14334 |
-+ * | '» struct kdbus_user *user (pinned) |
14335 |
-+ * | |
14336 |
-+ * '» struct kdbus_user *user (pinned) |
14337 |
-+ * '» struct kdbus_policy_db policy_db (embedded) |
14338 |
-+ * |» struct kdbus_policy_db_entry (many, owned) |
14339 |
-+ * | |» struct kdbus_conn (pinned) |
14340 |
-+ * | '» struct kdbus_ep (pinned) |
14341 |
-+ * | |
14342 |
-+ * '» struct kdbus_policy_db_cache_entry (many, owned) |
14343 |
-+ * '» struct kdbus_conn (pinned) |
14344 |
-+ * |
14345 |
-+ * For the life-time of a file descriptor derived from calling open() on a file |
14346 |
-+ * inside the mount point: |
14347 |
-+ * |
14348 |
-+ * struct kdbus_handle |
14349 |
-+ * |» struct kdbus_meta *meta (owned) |
14350 |
-+ * |» struct kdbus_ep *ep (pinned) |
14351 |
-+ * |» struct kdbus_conn *conn (owned) |
14352 |
-+ * '» struct kdbus_ep *ep (owned) |
14353 |
-+ */ |
14354 |
-+ |
14355 |
-+/* kdbus mount-point /sys/fs/kdbus */ |
14356 |
-+static struct kobject *kdbus_dir; |
14357 |
-+ |
14358 |
-+static int __init kdbus_init(void) |
14359 |
-+{ |
14360 |
-+ int ret; |
14361 |
-+ |
14362 |
-+ kdbus_dir = kobject_create_and_add(KBUILD_MODNAME, fs_kobj); |
14363 |
-+ if (!kdbus_dir) |
14364 |
-+ return -ENOMEM; |
14365 |
-+ |
14366 |
-+ ret = kdbus_fs_init(); |
14367 |
-+ if (ret < 0) { |
14368 |
-+ pr_err("cannot register filesystem: %d\n", ret); |
14369 |
-+ goto exit_dir; |
14370 |
-+ } |
14371 |
-+ |
14372 |
-+ pr_info("initialized\n"); |
14373 |
-+ return 0; |
14374 |
-+ |
14375 |
-+exit_dir: |
14376 |
-+ kobject_put(kdbus_dir); |
14377 |
-+ return ret; |
14378 |
-+} |
14379 |
-+ |
14380 |
-+static void __exit kdbus_exit(void) |
14381 |
-+{ |
14382 |
-+ kdbus_fs_exit(); |
14383 |
-+ kobject_put(kdbus_dir); |
14384 |
-+ ida_destroy(&kdbus_node_ida); |
14385 |
-+} |
14386 |
-+ |
14387 |
-+module_init(kdbus_init); |
14388 |
-+module_exit(kdbus_exit); |
14389 |
-+MODULE_LICENSE("GPL"); |
14390 |
-+MODULE_DESCRIPTION("D-Bus, powerful, easy to use interprocess communication"); |
14391 |
-+MODULE_ALIAS_FS(KBUILD_MODNAME "fs"); |
14392 |
-diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c |
14393 |
-new file mode 100644 |
14394 |
-index 0000000..4ee6a1f |
14395 |
---- /dev/null |
14396 |
-+++ b/ipc/kdbus/match.c |
14397 |
-@@ -0,0 +1,546 @@ |
14398 |
-+/* |
14399 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14400 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14401 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14402 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14403 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14404 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14405 |
-+ * |
14406 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14407 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14408 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14409 |
-+ * your option) any later version. |
14410 |
-+ */ |
14411 |
-+ |
14412 |
-+#include <linux/fs.h> |
14413 |
-+#include <linux/hash.h> |
14414 |
-+#include <linux/init.h> |
14415 |
-+#include <linux/mutex.h> |
14416 |
-+#include <linux/sched.h> |
14417 |
-+#include <linux/sizes.h> |
14418 |
-+#include <linux/slab.h> |
14419 |
-+#include <linux/uaccess.h> |
14420 |
-+ |
14421 |
-+#include "bus.h" |
14422 |
-+#include "connection.h" |
14423 |
-+#include "endpoint.h" |
14424 |
-+#include "handle.h" |
14425 |
-+#include "item.h" |
14426 |
-+#include "match.h" |
14427 |
-+#include "message.h" |
14428 |
-+#include "names.h" |
14429 |
-+ |
14430 |
-+/** |
14431 |
-+ * struct kdbus_match_db - message filters |
14432 |
-+ * @entries_list: List of matches |
14433 |
-+ * @mdb_rwlock: Match data lock |
14434 |
-+ * @entries_count: Number of entries in database |
14435 |
-+ */ |
14436 |
-+struct kdbus_match_db { |
14437 |
-+ struct list_head entries_list; |
14438 |
-+ struct rw_semaphore mdb_rwlock; |
14439 |
-+ unsigned int entries_count; |
14440 |
-+}; |
14441 |
-+ |
14442 |
-+/** |
14443 |
-+ * struct kdbus_match_entry - a match database entry |
14444 |
-+ * @cookie: User-supplied cookie to lookup the entry |
14445 |
-+ * @list_entry: The list entry element for the db list |
14446 |
-+ * @rules_list: The list head for tracking rules of this entry |
14447 |
-+ */ |
14448 |
-+struct kdbus_match_entry { |
14449 |
-+ u64 cookie; |
14450 |
-+ struct list_head list_entry; |
14451 |
-+ struct list_head rules_list; |
14452 |
-+}; |
14453 |
-+ |
14454 |
-+/** |
14455 |
-+ * struct kdbus_bloom_mask - mask to match against filter |
14456 |
-+ * @generations: Number of generations carried |
14457 |
-+ * @data: Array of bloom bit fields |
14458 |
-+ */ |
14459 |
-+struct kdbus_bloom_mask { |
14460 |
-+ u64 generations; |
14461 |
-+ u64 *data; |
14462 |
-+}; |
14463 |
-+ |
14464 |
-+/** |
14465 |
-+ * struct kdbus_match_rule - a rule appended to a match entry |
14466 |
-+ * @type: An item type to match against |
14467 |
-+ * @bloom_mask: Bloom mask to match a message's filter against, used |
14468 |
-+ * with KDBUS_ITEM_BLOOM_MASK |
14469 |
-+ * @name: Name to match against, used with KDBUS_ITEM_NAME, |
14470 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} |
14471 |
-+ * @old_id: ID to match against, used with |
14472 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}, |
14473 |
-+ * KDBUS_ITEM_ID_REMOVE |
14474 |
-+ * @new_id: ID to match against, used with |
14475 |
-+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}, |
14476 |
-+ * KDBUS_ITEM_ID_REMOVE |
14477 |
-+ * @src_id: ID to match against, used with KDBUS_ITEM_ID |
14478 |
-+ * @dst_id: Message destination ID, used with KDBUS_ITEM_DST_ID |
14479 |
-+ * @rules_entry: Entry in the entry's rules list |
14480 |
-+ */ |
14481 |
-+struct kdbus_match_rule { |
14482 |
-+ u64 type; |
14483 |
-+ union { |
14484 |
-+ struct kdbus_bloom_mask bloom_mask; |
14485 |
-+ struct { |
14486 |
-+ char *name; |
14487 |
-+ u64 old_id; |
14488 |
-+ u64 new_id; |
14489 |
-+ }; |
14490 |
-+ u64 src_id; |
14491 |
-+ u64 dst_id; |
14492 |
-+ }; |
14493 |
-+ struct list_head rules_entry; |
14494 |
-+}; |
14495 |
-+ |
14496 |
-+static void kdbus_match_rule_free(struct kdbus_match_rule *rule) |
14497 |
-+{ |
14498 |
-+ if (!rule) |
14499 |
-+ return; |
14500 |
-+ |
14501 |
-+ switch (rule->type) { |
14502 |
-+ case KDBUS_ITEM_BLOOM_MASK: |
14503 |
-+ kfree(rule->bloom_mask.data); |
14504 |
-+ break; |
14505 |
-+ |
14506 |
-+ case KDBUS_ITEM_NAME: |
14507 |
-+ case KDBUS_ITEM_NAME_ADD: |
14508 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14509 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14510 |
-+ kfree(rule->name); |
14511 |
-+ break; |
14512 |
-+ |
14513 |
-+ case KDBUS_ITEM_ID: |
14514 |
-+ case KDBUS_ITEM_DST_ID: |
14515 |
-+ case KDBUS_ITEM_ID_ADD: |
14516 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14517 |
-+ break; |
14518 |
-+ |
14519 |
-+ default: |
14520 |
-+ BUG(); |
14521 |
-+ } |
14522 |
-+ |
14523 |
-+ list_del(&rule->rules_entry); |
14524 |
-+ kfree(rule); |
14525 |
-+} |
14526 |
-+ |
14527 |
-+static void kdbus_match_entry_free(struct kdbus_match_entry *entry) |
14528 |
-+{ |
14529 |
-+ struct kdbus_match_rule *r, *tmp; |
14530 |
-+ |
14531 |
-+ if (!entry) |
14532 |
-+ return; |
14533 |
-+ |
14534 |
-+ list_for_each_entry_safe(r, tmp, &entry->rules_list, rules_entry) |
14535 |
-+ kdbus_match_rule_free(r); |
14536 |
-+ |
14537 |
-+ list_del(&entry->list_entry); |
14538 |
-+ kfree(entry); |
14539 |
-+} |
14540 |
-+ |
14541 |
-+/** |
14542 |
-+ * kdbus_match_db_free() - free match db resources |
14543 |
-+ * @mdb: The match database |
14544 |
-+ */ |
14545 |
-+void kdbus_match_db_free(struct kdbus_match_db *mdb) |
14546 |
-+{ |
14547 |
-+ struct kdbus_match_entry *entry, *tmp; |
14548 |
-+ |
14549 |
-+ if (!mdb) |
14550 |
-+ return; |
14551 |
-+ |
14552 |
-+ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry) |
14553 |
-+ kdbus_match_entry_free(entry); |
14554 |
-+ |
14555 |
-+ kfree(mdb); |
14556 |
-+} |
14557 |
-+ |
14558 |
-+/** |
14559 |
-+ * kdbus_match_db_new() - create a new match database |
14560 |
-+ * |
14561 |
-+ * Return: a new kdbus_match_db on success, ERR_PTR on failure. |
14562 |
-+ */ |
14563 |
-+struct kdbus_match_db *kdbus_match_db_new(void) |
14564 |
-+{ |
14565 |
-+ struct kdbus_match_db *d; |
14566 |
-+ |
14567 |
-+ d = kzalloc(sizeof(*d), GFP_KERNEL); |
14568 |
-+ if (!d) |
14569 |
-+ return ERR_PTR(-ENOMEM); |
14570 |
-+ |
14571 |
-+ init_rwsem(&d->mdb_rwlock); |
14572 |
-+ INIT_LIST_HEAD(&d->entries_list); |
14573 |
-+ |
14574 |
-+ return d; |
14575 |
-+} |
14576 |
-+ |
14577 |
-+static bool kdbus_match_bloom(const struct kdbus_bloom_filter *filter, |
14578 |
-+ const struct kdbus_bloom_mask *mask, |
14579 |
-+ const struct kdbus_conn *conn) |
14580 |
-+{ |
14581 |
-+ size_t n = conn->ep->bus->bloom.size / sizeof(u64); |
14582 |
-+ const u64 *m; |
14583 |
-+ size_t i; |
14584 |
-+ |
14585 |
-+ /* |
14586 |
-+ * The message's filter carries a generation identifier, the |
14587 |
-+ * match's mask possibly carries an array of multiple generations |
14588 |
-+ * of the mask. Select the mask with the closest match of the |
14589 |
-+ * filter's generation. |
14590 |
-+ */ |
14591 |
-+ m = mask->data + (min(filter->generation, mask->generations - 1) * n); |
14592 |
-+ |
14593 |
-+ /* |
14594 |
-+ * The message's filter contains the messages properties, |
14595 |
-+ * the match's mask contains the properties to look for in the |
14596 |
-+ * message. Check the mask bit field against the filter bit field, |
14597 |
-+ * if the message possibly carries the properties the connection |
14598 |
-+ * has subscribed to. |
14599 |
-+ */ |
14600 |
-+ for (i = 0; i < n; i++) |
14601 |
-+ if ((filter->data[i] & m[i]) != m[i]) |
14602 |
-+ return false; |
14603 |
-+ |
14604 |
-+ return true; |
14605 |
-+} |
14606 |
-+ |
14607 |
-+static bool kdbus_match_rule_conn(const struct kdbus_match_rule *r, |
14608 |
-+ struct kdbus_conn *c, |
14609 |
-+ const struct kdbus_staging *s) |
14610 |
-+{ |
14611 |
-+ lockdep_assert_held(&c->ep->bus->name_registry->rwlock); |
14612 |
-+ |
14613 |
-+ switch (r->type) { |
14614 |
-+ case KDBUS_ITEM_BLOOM_MASK: |
14615 |
-+ return kdbus_match_bloom(s->bloom_filter, &r->bloom_mask, c); |
14616 |
-+ case KDBUS_ITEM_ID: |
14617 |
-+ return r->src_id == c->id || r->src_id == KDBUS_MATCH_ID_ANY; |
14618 |
-+ case KDBUS_ITEM_DST_ID: |
14619 |
-+ return r->dst_id == s->msg->dst_id || |
14620 |
-+ r->dst_id == KDBUS_MATCH_ID_ANY; |
14621 |
-+ case KDBUS_ITEM_NAME: |
14622 |
-+ return kdbus_conn_has_name(c, r->name); |
14623 |
-+ default: |
14624 |
-+ return false; |
14625 |
-+ } |
14626 |
-+} |
14627 |
-+ |
14628 |
-+static bool kdbus_match_rule_kernel(const struct kdbus_match_rule *r, |
14629 |
-+ const struct kdbus_staging *s) |
14630 |
-+{ |
14631 |
-+ struct kdbus_item *n = s->notify; |
14632 |
-+ |
14633 |
-+ if (WARN_ON(!n) || n->type != r->type) |
14634 |
-+ return false; |
14635 |
-+ |
14636 |
-+ switch (r->type) { |
14637 |
-+ case KDBUS_ITEM_ID_ADD: |
14638 |
-+ return r->new_id == KDBUS_MATCH_ID_ANY || |
14639 |
-+ r->new_id == n->id_change.id; |
14640 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14641 |
-+ return r->old_id == KDBUS_MATCH_ID_ANY || |
14642 |
-+ r->old_id == n->id_change.id; |
14643 |
-+ case KDBUS_ITEM_NAME_ADD: |
14644 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14645 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14646 |
-+ return (r->old_id == KDBUS_MATCH_ID_ANY || |
14647 |
-+ r->old_id == n->name_change.old_id.id) && |
14648 |
-+ (r->new_id == KDBUS_MATCH_ID_ANY || |
14649 |
-+ r->new_id == n->name_change.new_id.id) && |
14650 |
-+ (!r->name || !strcmp(r->name, n->name_change.name)); |
14651 |
-+ default: |
14652 |
-+ return false; |
14653 |
-+ } |
14654 |
-+} |
14655 |
-+ |
14656 |
-+static bool kdbus_match_rules(const struct kdbus_match_entry *entry, |
14657 |
-+ struct kdbus_conn *c, |
14658 |
-+ const struct kdbus_staging *s) |
14659 |
-+{ |
14660 |
-+ struct kdbus_match_rule *r; |
14661 |
-+ |
14662 |
-+ list_for_each_entry(r, &entry->rules_list, rules_entry) |
14663 |
-+ if ((c && !kdbus_match_rule_conn(r, c, s)) || |
14664 |
-+ (!c && !kdbus_match_rule_kernel(r, s))) |
14665 |
-+ return false; |
14666 |
-+ |
14667 |
-+ return true; |
14668 |
-+} |
14669 |
-+ |
14670 |
-+/** |
14671 |
-+ * kdbus_match_db_match_msg() - match a msg object agains the database entries |
14672 |
-+ * @mdb: The match database |
14673 |
-+ * @conn_src: The connection object originating the message |
14674 |
-+ * @staging: Staging object containing the message to match against |
14675 |
-+ * |
14676 |
-+ * This function will walk through all the database entries previously uploaded |
14677 |
-+ * with kdbus_match_db_add(). As soon as any of them has an all-satisfied rule |
14678 |
-+ * set, this function will return true. |
14679 |
-+ * |
14680 |
-+ * The caller must hold the registry lock of conn_src->ep->bus, in case conn_src |
14681 |
-+ * is non-NULL. |
14682 |
-+ * |
14683 |
-+ * Return: true if there was a matching database entry, false otherwise. |
14684 |
-+ */ |
14685 |
-+bool kdbus_match_db_match_msg(struct kdbus_match_db *mdb, |
14686 |
-+ struct kdbus_conn *conn_src, |
14687 |
-+ const struct kdbus_staging *staging) |
14688 |
-+{ |
14689 |
-+ struct kdbus_match_entry *entry; |
14690 |
-+ bool matched = false; |
14691 |
-+ |
14692 |
-+ down_read(&mdb->mdb_rwlock); |
14693 |
-+ list_for_each_entry(entry, &mdb->entries_list, list_entry) { |
14694 |
-+ matched = kdbus_match_rules(entry, conn_src, staging); |
14695 |
-+ if (matched) |
14696 |
-+ break; |
14697 |
-+ } |
14698 |
-+ up_read(&mdb->mdb_rwlock); |
14699 |
-+ |
14700 |
-+ return matched; |
14701 |
-+} |
14702 |
-+ |
14703 |
-+static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb, |
14704 |
-+ u64 cookie) |
14705 |
-+{ |
14706 |
-+ struct kdbus_match_entry *entry, *tmp; |
14707 |
-+ bool found = false; |
14708 |
-+ |
14709 |
-+ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry) |
14710 |
-+ if (entry->cookie == cookie) { |
14711 |
-+ kdbus_match_entry_free(entry); |
14712 |
-+ --mdb->entries_count; |
14713 |
-+ found = true; |
14714 |
-+ } |
14715 |
-+ |
14716 |
-+ return found ? 0 : -EBADSLT; |
14717 |
-+} |
14718 |
-+ |
14719 |
-+/** |
14720 |
-+ * kdbus_cmd_match_add() - handle KDBUS_CMD_MATCH_ADD |
14721 |
-+ * @conn: connection to operate on |
14722 |
-+ * @argp: command payload |
14723 |
-+ * |
14724 |
-+ * One call to this function (or one ioctl(KDBUS_CMD_MATCH_ADD), respectively, |
14725 |
-+ * adds one new database entry with n rules attached to it. Each rule is |
14726 |
-+ * described with an kdbus_item, and an entry is considered matching if all |
14727 |
-+ * its rules are satisfied. |
14728 |
-+ * |
14729 |
-+ * The items attached to a kdbus_cmd_match struct have the following mapping: |
14730 |
-+ * |
14731 |
-+ * KDBUS_ITEM_BLOOM_MASK: A bloom mask |
14732 |
-+ * KDBUS_ITEM_NAME: A connection's source name |
14733 |
-+ * KDBUS_ITEM_ID: A connection ID |
14734 |
-+ * KDBUS_ITEM_DST_ID: A connection ID |
14735 |
-+ * KDBUS_ITEM_NAME_ADD: |
14736 |
-+ * KDBUS_ITEM_NAME_REMOVE: |
14737 |
-+ * KDBUS_ITEM_NAME_CHANGE: Well-known name changes, carry |
14738 |
-+ * kdbus_notify_name_change |
14739 |
-+ * KDBUS_ITEM_ID_ADD: |
14740 |
-+ * KDBUS_ITEM_ID_REMOVE: Connection ID changes, carry |
14741 |
-+ * kdbus_notify_id_change |
14742 |
-+ * |
14743 |
-+ * For kdbus_notify_{id,name}_change structs, only the ID and name fields |
14744 |
-+ * are looked at when adding an entry. The flags are unused. |
14745 |
-+ * |
14746 |
-+ * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME, KDBUS_ITEM_ID, |
14747 |
-+ * and KDBUS_ITEM_DST_ID are used to match messages from userspace, while the |
14748 |
-+ * others apply to kernel-generated notifications. |
14749 |
-+ * |
14750 |
-+ * Return: >=0 on success, negative error code on failure. |
14751 |
-+ */ |
14752 |
-+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp) |
14753 |
-+{ |
14754 |
-+ struct kdbus_match_db *mdb = conn->match_db; |
14755 |
-+ struct kdbus_match_entry *entry = NULL; |
14756 |
-+ struct kdbus_cmd_match *cmd; |
14757 |
-+ struct kdbus_item *item; |
14758 |
-+ int ret; |
14759 |
-+ |
14760 |
-+ struct kdbus_arg argv[] = { |
14761 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
14762 |
-+ { .type = KDBUS_ITEM_BLOOM_MASK, .multiple = true }, |
14763 |
-+ { .type = KDBUS_ITEM_NAME, .multiple = true }, |
14764 |
-+ { .type = KDBUS_ITEM_ID, .multiple = true }, |
14765 |
-+ { .type = KDBUS_ITEM_DST_ID, .multiple = true }, |
14766 |
-+ { .type = KDBUS_ITEM_NAME_ADD, .multiple = true }, |
14767 |
-+ { .type = KDBUS_ITEM_NAME_REMOVE, .multiple = true }, |
14768 |
-+ { .type = KDBUS_ITEM_NAME_CHANGE, .multiple = true }, |
14769 |
-+ { .type = KDBUS_ITEM_ID_ADD, .multiple = true }, |
14770 |
-+ { .type = KDBUS_ITEM_ID_REMOVE, .multiple = true }, |
14771 |
-+ }; |
14772 |
-+ struct kdbus_args args = { |
14773 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
14774 |
-+ KDBUS_MATCH_REPLACE, |
14775 |
-+ .argv = argv, |
14776 |
-+ .argc = ARRAY_SIZE(argv), |
14777 |
-+ }; |
14778 |
-+ |
14779 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
14780 |
-+ return -EOPNOTSUPP; |
14781 |
-+ |
14782 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
14783 |
-+ if (ret != 0) |
14784 |
-+ return ret; |
14785 |
-+ |
14786 |
-+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
14787 |
-+ if (!entry) { |
14788 |
-+ ret = -ENOMEM; |
14789 |
-+ goto exit; |
14790 |
-+ } |
14791 |
-+ |
14792 |
-+ entry->cookie = cmd->cookie; |
14793 |
-+ INIT_LIST_HEAD(&entry->list_entry); |
14794 |
-+ INIT_LIST_HEAD(&entry->rules_list); |
14795 |
-+ |
14796 |
-+ KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) { |
14797 |
-+ struct kdbus_match_rule *rule; |
14798 |
-+ size_t size = item->size - offsetof(struct kdbus_item, data); |
14799 |
-+ |
14800 |
-+ rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
14801 |
-+ if (!rule) { |
14802 |
-+ ret = -ENOMEM; |
14803 |
-+ goto exit; |
14804 |
-+ } |
14805 |
-+ |
14806 |
-+ rule->type = item->type; |
14807 |
-+ INIT_LIST_HEAD(&rule->rules_entry); |
14808 |
-+ |
14809 |
-+ switch (item->type) { |
14810 |
-+ case KDBUS_ITEM_BLOOM_MASK: { |
14811 |
-+ u64 bsize = conn->ep->bus->bloom.size; |
14812 |
-+ u64 generations; |
14813 |
-+ u64 remainder; |
14814 |
-+ |
14815 |
-+ generations = div64_u64_rem(size, bsize, &remainder); |
14816 |
-+ if (size < bsize || remainder > 0) { |
14817 |
-+ ret = -EDOM; |
14818 |
-+ break; |
14819 |
-+ } |
14820 |
-+ |
14821 |
-+ rule->bloom_mask.data = kmemdup(item->data, |
14822 |
-+ size, GFP_KERNEL); |
14823 |
-+ if (!rule->bloom_mask.data) { |
14824 |
-+ ret = -ENOMEM; |
14825 |
-+ break; |
14826 |
-+ } |
14827 |
-+ |
14828 |
-+ rule->bloom_mask.generations = generations; |
14829 |
-+ break; |
14830 |
-+ } |
14831 |
-+ |
14832 |
-+ case KDBUS_ITEM_NAME: |
14833 |
-+ if (!kdbus_name_is_valid(item->str, false)) { |
14834 |
-+ ret = -EINVAL; |
14835 |
-+ break; |
14836 |
-+ } |
14837 |
-+ |
14838 |
-+ rule->name = kstrdup(item->str, GFP_KERNEL); |
14839 |
-+ if (!rule->name) |
14840 |
-+ ret = -ENOMEM; |
14841 |
-+ |
14842 |
-+ break; |
14843 |
-+ |
14844 |
-+ case KDBUS_ITEM_ID: |
14845 |
-+ rule->src_id = item->id; |
14846 |
-+ break; |
14847 |
-+ |
14848 |
-+ case KDBUS_ITEM_DST_ID: |
14849 |
-+ rule->dst_id = item->id; |
14850 |
-+ break; |
14851 |
-+ |
14852 |
-+ case KDBUS_ITEM_NAME_ADD: |
14853 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
14854 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
14855 |
-+ rule->old_id = item->name_change.old_id.id; |
14856 |
-+ rule->new_id = item->name_change.new_id.id; |
14857 |
-+ |
14858 |
-+ if (size > sizeof(struct kdbus_notify_name_change)) { |
14859 |
-+ rule->name = kstrdup(item->name_change.name, |
14860 |
-+ GFP_KERNEL); |
14861 |
-+ if (!rule->name) |
14862 |
-+ ret = -ENOMEM; |
14863 |
-+ } |
14864 |
-+ |
14865 |
-+ break; |
14866 |
-+ |
14867 |
-+ case KDBUS_ITEM_ID_ADD: |
14868 |
-+ case KDBUS_ITEM_ID_REMOVE: |
14869 |
-+ if (item->type == KDBUS_ITEM_ID_ADD) |
14870 |
-+ rule->new_id = item->id_change.id; |
14871 |
-+ else |
14872 |
-+ rule->old_id = item->id_change.id; |
14873 |
-+ |
14874 |
-+ break; |
14875 |
-+ } |
14876 |
-+ |
14877 |
-+ if (ret < 0) { |
14878 |
-+ kdbus_match_rule_free(rule); |
14879 |
-+ goto exit; |
14880 |
-+ } |
14881 |
-+ |
14882 |
-+ list_add_tail(&rule->rules_entry, &entry->rules_list); |
14883 |
-+ } |
14884 |
-+ |
14885 |
-+ down_write(&mdb->mdb_rwlock); |
14886 |
-+ |
14887 |
-+ /* Remove any entry that has the same cookie as the current one. */ |
14888 |
-+ if (cmd->flags & KDBUS_MATCH_REPLACE) |
14889 |
-+ kdbus_match_db_remove_unlocked(mdb, entry->cookie); |
14890 |
-+ |
14891 |
-+ /* |
14892 |
-+ * If the above removal caught any entry, there will be room for the |
14893 |
-+ * new one. |
14894 |
-+ */ |
14895 |
-+ if (++mdb->entries_count > KDBUS_MATCH_MAX) { |
14896 |
-+ --mdb->entries_count; |
14897 |
-+ ret = -EMFILE; |
14898 |
-+ } else { |
14899 |
-+ list_add_tail(&entry->list_entry, &mdb->entries_list); |
14900 |
-+ entry = NULL; |
14901 |
-+ } |
14902 |
-+ |
14903 |
-+ up_write(&mdb->mdb_rwlock); |
14904 |
-+ |
14905 |
-+exit: |
14906 |
-+ kdbus_match_entry_free(entry); |
14907 |
-+ return kdbus_args_clear(&args, ret); |
14908 |
-+} |
14909 |
-+ |
14910 |
-+/** |
14911 |
-+ * kdbus_cmd_match_remove() - handle KDBUS_CMD_MATCH_REMOVE |
14912 |
-+ * @conn: connection to operate on |
14913 |
-+ * @argp: command payload |
14914 |
-+ * |
14915 |
-+ * Return: >=0 on success, negative error code on failure. |
14916 |
-+ */ |
14917 |
-+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp) |
14918 |
-+{ |
14919 |
-+ struct kdbus_cmd_match *cmd; |
14920 |
-+ int ret; |
14921 |
-+ |
14922 |
-+ struct kdbus_arg argv[] = { |
14923 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
14924 |
-+ }; |
14925 |
-+ struct kdbus_args args = { |
14926 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
14927 |
-+ .argv = argv, |
14928 |
-+ .argc = ARRAY_SIZE(argv), |
14929 |
-+ }; |
14930 |
-+ |
14931 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
14932 |
-+ return -EOPNOTSUPP; |
14933 |
-+ |
14934 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
14935 |
-+ if (ret != 0) |
14936 |
-+ return ret; |
14937 |
-+ |
14938 |
-+ down_write(&conn->match_db->mdb_rwlock); |
14939 |
-+ ret = kdbus_match_db_remove_unlocked(conn->match_db, cmd->cookie); |
14940 |
-+ up_write(&conn->match_db->mdb_rwlock); |
14941 |
-+ |
14942 |
-+ return kdbus_args_clear(&args, ret); |
14943 |
-+} |
14944 |
-diff --git a/ipc/kdbus/match.h b/ipc/kdbus/match.h |
14945 |
-new file mode 100644 |
14946 |
-index 0000000..ceb492f |
14947 |
---- /dev/null |
14948 |
-+++ b/ipc/kdbus/match.h |
14949 |
-@@ -0,0 +1,35 @@ |
14950 |
-+/* |
14951 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14952 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14953 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14954 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14955 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14956 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14957 |
-+ * |
14958 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
14959 |
-+ * the terms of the GNU Lesser General Public License as published by the |
14960 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
14961 |
-+ * your option) any later version. |
14962 |
-+ */ |
14963 |
-+ |
14964 |
-+#ifndef __KDBUS_MATCH_H |
14965 |
-+#define __KDBUS_MATCH_H |
14966 |
-+ |
14967 |
-+struct kdbus_conn; |
14968 |
-+struct kdbus_match_db; |
14969 |
-+struct kdbus_staging; |
14970 |
-+ |
14971 |
-+struct kdbus_match_db *kdbus_match_db_new(void); |
14972 |
-+void kdbus_match_db_free(struct kdbus_match_db *db); |
14973 |
-+int kdbus_match_db_add(struct kdbus_conn *conn, |
14974 |
-+ struct kdbus_cmd_match *cmd); |
14975 |
-+int kdbus_match_db_remove(struct kdbus_conn *conn, |
14976 |
-+ struct kdbus_cmd_match *cmd); |
14977 |
-+bool kdbus_match_db_match_msg(struct kdbus_match_db *db, |
14978 |
-+ struct kdbus_conn *conn_src, |
14979 |
-+ const struct kdbus_staging *staging); |
14980 |
-+ |
14981 |
-+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp); |
14982 |
-+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp); |
14983 |
-+ |
14984 |
-+#endif |
14985 |
-diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c |
14986 |
-new file mode 100644 |
14987 |
-index 0000000..ae565cd |
14988 |
---- /dev/null |
14989 |
-+++ b/ipc/kdbus/message.c |
14990 |
-@@ -0,0 +1,1040 @@ |
14991 |
-+/* |
14992 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
14993 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
14994 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
14995 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
14996 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
14997 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
14998 |
-+ * |
14999 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
15000 |
-+ * the terms of the GNU Lesser General Public License as published by the |
15001 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
15002 |
-+ * your option) any later version. |
15003 |
-+ */ |
15004 |
-+ |
15005 |
-+#include <linux/capability.h> |
15006 |
-+#include <linux/cgroup.h> |
15007 |
-+#include <linux/cred.h> |
15008 |
-+#include <linux/file.h> |
15009 |
-+#include <linux/init.h> |
15010 |
-+#include <linux/module.h> |
15011 |
-+#include <linux/mutex.h> |
15012 |
-+#include <linux/sched.h> |
15013 |
-+#include <linux/shmem_fs.h> |
15014 |
-+#include <linux/sizes.h> |
15015 |
-+#include <linux/slab.h> |
15016 |
-+#include <linux/uaccess.h> |
15017 |
-+#include <net/sock.h> |
15018 |
-+ |
15019 |
-+#include "bus.h" |
15020 |
-+#include "connection.h" |
15021 |
-+#include "domain.h" |
15022 |
-+#include "endpoint.h" |
15023 |
-+#include "handle.h" |
15024 |
-+#include "item.h" |
15025 |
-+#include "match.h" |
15026 |
-+#include "message.h" |
15027 |
-+#include "names.h" |
15028 |
-+#include "policy.h" |
15029 |
-+ |
15030 |
-+static const char * const zeros = "\0\0\0\0\0\0\0"; |
15031 |
-+ |
15032 |
-+static struct kdbus_gaps *kdbus_gaps_new(size_t n_memfds, size_t n_fds) |
15033 |
-+{ |
15034 |
-+ size_t size_offsets, size_memfds, size_fds, size; |
15035 |
-+ struct kdbus_gaps *gaps; |
15036 |
-+ |
15037 |
-+ size_offsets = n_memfds * sizeof(*gaps->memfd_offsets); |
15038 |
-+ size_memfds = n_memfds * sizeof(*gaps->memfd_files); |
15039 |
-+ size_fds = n_fds * sizeof(*gaps->fd_files); |
15040 |
-+ size = sizeof(*gaps) + size_offsets + size_memfds + size_fds; |
15041 |
-+ |
15042 |
-+ gaps = kzalloc(size, GFP_KERNEL); |
15043 |
-+ if (!gaps) |
15044 |
-+ return ERR_PTR(-ENOMEM); |
15045 |
-+ |
15046 |
-+ kref_init(&gaps->kref); |
15047 |
-+ gaps->n_memfds = 0; /* we reserve n_memfds, but don't enforce them */ |
15048 |
-+ gaps->memfd_offsets = (void *)(gaps + 1); |
15049 |
-+ gaps->memfd_files = (void *)((u8 *)gaps->memfd_offsets + size_offsets); |
15050 |
-+ gaps->n_fds = 0; /* we reserve n_fds, but don't enforce them */ |
15051 |
-+ gaps->fd_files = (void *)((u8 *)gaps->memfd_files + size_memfds); |
15052 |
-+ |
15053 |
-+ return gaps; |
15054 |
-+} |
15055 |
-+ |
15056 |
-+static void kdbus_gaps_free(struct kref *kref) |
15057 |
-+{ |
15058 |
-+ struct kdbus_gaps *gaps = container_of(kref, struct kdbus_gaps, kref); |
15059 |
-+ size_t i; |
15060 |
-+ |
15061 |
-+ for (i = 0; i < gaps->n_fds; ++i) |
15062 |
-+ if (gaps->fd_files[i]) |
15063 |
-+ fput(gaps->fd_files[i]); |
15064 |
-+ for (i = 0; i < gaps->n_memfds; ++i) |
15065 |
-+ if (gaps->memfd_files[i]) |
15066 |
-+ fput(gaps->memfd_files[i]); |
15067 |
-+ |
15068 |
-+ kfree(gaps); |
15069 |
-+} |
15070 |
-+ |
15071 |
-+/** |
15072 |
-+ * kdbus_gaps_ref() - gain reference |
15073 |
-+ * @gaps: gaps object |
15074 |
-+ * |
15075 |
-+ * Return: @gaps is returned |
15076 |
-+ */ |
15077 |
-+struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps) |
15078 |
-+{ |
15079 |
-+ if (gaps) |
15080 |
-+ kref_get(&gaps->kref); |
15081 |
-+ return gaps; |
15082 |
-+} |
15083 |
-+ |
15084 |
-+/** |
15085 |
-+ * kdbus_gaps_unref() - drop reference |
15086 |
-+ * @gaps: gaps object |
15087 |
-+ * |
15088 |
-+ * Return: NULL |
15089 |
-+ */ |
15090 |
-+struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps) |
15091 |
-+{ |
15092 |
-+ if (gaps) |
15093 |
-+ kref_put(&gaps->kref, kdbus_gaps_free); |
15094 |
-+ return NULL; |
15095 |
-+} |
15096 |
-+ |
15097 |
-+/** |
15098 |
-+ * kdbus_gaps_install() - install file-descriptors |
15099 |
-+ * @gaps: gaps object, or NULL |
15100 |
-+ * @slice: pool slice that contains the message |
15101 |
-+ * @out_incomplete output variable to note incomplete fds |
15102 |
-+ * |
15103 |
-+ * This function installs all file-descriptors of @gaps into the current |
15104 |
-+ * process and copies the file-descriptor numbers into the target pool slice. |
15105 |
-+ * |
15106 |
-+ * If the file-descriptors were only partially installed, then @out_incomplete |
15107 |
-+ * will be set to true. Otherwise, it's set to false. |
15108 |
-+ * |
15109 |
-+ * Return: 0 on success, negative error code on failure |
15110 |
-+ */ |
15111 |
-+int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice, |
15112 |
-+ bool *out_incomplete) |
15113 |
-+{ |
15114 |
-+ bool incomplete_fds = false; |
15115 |
-+ struct kvec kvec; |
15116 |
-+ size_t i, n_fds; |
15117 |
-+ int ret, *fds; |
15118 |
-+ |
15119 |
-+ if (!gaps) { |
15120 |
-+ /* nothing to do */ |
15121 |
-+ *out_incomplete = incomplete_fds; |
15122 |
-+ return 0; |
15123 |
-+ } |
15124 |
-+ |
15125 |
-+ n_fds = gaps->n_fds + gaps->n_memfds; |
15126 |
-+ if (n_fds < 1) { |
15127 |
-+ /* nothing to do */ |
15128 |
-+ *out_incomplete = incomplete_fds; |
15129 |
-+ return 0; |
15130 |
-+ } |
15131 |
-+ |
15132 |
-+ fds = kmalloc_array(n_fds, sizeof(*fds), GFP_TEMPORARY); |
15133 |
-+ n_fds = 0; |
15134 |
-+ if (!fds) |
15135 |
-+ return -ENOMEM; |
15136 |
-+ |
15137 |
-+ /* 1) allocate fds and copy them over */ |
15138 |
-+ |
15139 |
-+ if (gaps->n_fds > 0) { |
15140 |
-+ for (i = 0; i < gaps->n_fds; ++i) { |
15141 |
-+ int fd; |
15142 |
-+ |
15143 |
-+ fd = get_unused_fd_flags(O_CLOEXEC); |
15144 |
-+ if (fd < 0) |
15145 |
-+ incomplete_fds = true; |
15146 |
-+ |
15147 |
-+ WARN_ON(!gaps->fd_files[i]); |
15148 |
-+ |
15149 |
-+ fds[n_fds++] = fd < 0 ? -1 : fd; |
15150 |
-+ } |
15151 |
-+ |
15152 |
-+ /* |
15153 |
-+ * The file-descriptor array can only be present once per |
15154 |
-+ * message. Hence, prepare all fds and then copy them over with |
15155 |
-+ * a single kvec. |
15156 |
-+ */ |
15157 |
-+ |
15158 |
-+ WARN_ON(!gaps->fd_offset); |
15159 |
-+ |
15160 |
-+ kvec.iov_base = fds; |
15161 |
-+ kvec.iov_len = gaps->n_fds * sizeof(*fds); |
15162 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, gaps->fd_offset, |
15163 |
-+ &kvec, 1, kvec.iov_len); |
15164 |
-+ if (ret < 0) |
15165 |
-+ goto exit; |
15166 |
-+ } |
15167 |
-+ |
15168 |
-+ for (i = 0; i < gaps->n_memfds; ++i) { |
15169 |
-+ int memfd; |
15170 |
-+ |
15171 |
-+ memfd = get_unused_fd_flags(O_CLOEXEC); |
15172 |
-+ if (memfd < 0) { |
15173 |
-+ incomplete_fds = true; |
15174 |
-+ /* memfds are initialized to -1, skip copying it */ |
15175 |
-+ continue; |
15176 |
-+ } |
15177 |
-+ |
15178 |
-+ fds[n_fds++] = memfd; |
15179 |
-+ |
15180 |
-+ /* |
15181 |
-+ * memfds have to be copied individually as they each are put |
15182 |
-+ * into a separate item. This should not be an issue, though, |
15183 |
-+ * as usually there is no need to send more than one memfd per |
15184 |
-+ * message. |
15185 |
-+ */ |
15186 |
-+ |
15187 |
-+ WARN_ON(!gaps->memfd_offsets[i]); |
15188 |
-+ WARN_ON(!gaps->memfd_files[i]); |
15189 |
-+ |
15190 |
-+ kvec.iov_base = &memfd; |
15191 |
-+ kvec.iov_len = sizeof(memfd); |
15192 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, gaps->memfd_offsets[i], |
15193 |
-+ &kvec, 1, kvec.iov_len); |
15194 |
-+ if (ret < 0) |
15195 |
-+ goto exit; |
15196 |
-+ } |
15197 |
-+ |
15198 |
-+ /* 2) install fds now that everything was successful */ |
15199 |
-+ |
15200 |
-+ for (i = 0; i < gaps->n_fds; ++i) |
15201 |
-+ if (fds[i] >= 0) |
15202 |
-+ fd_install(fds[i], get_file(gaps->fd_files[i])); |
15203 |
-+ for (i = 0; i < gaps->n_memfds; ++i) |
15204 |
-+ if (fds[gaps->n_fds + i] >= 0) |
15205 |
-+ fd_install(fds[gaps->n_fds + i], |
15206 |
-+ get_file(gaps->memfd_files[i])); |
15207 |
-+ |
15208 |
-+ ret = 0; |
15209 |
-+ |
15210 |
-+exit: |
15211 |
-+ if (ret < 0) |
15212 |
-+ for (i = 0; i < n_fds; ++i) |
15213 |
-+ put_unused_fd(fds[i]); |
15214 |
-+ kfree(fds); |
15215 |
-+ *out_incomplete = incomplete_fds; |
15216 |
-+ return ret; |
15217 |
-+} |
15218 |
-+ |
15219 |
-+static struct file *kdbus_get_fd(int fd) |
15220 |
-+{ |
15221 |
-+ struct file *f, *ret; |
15222 |
-+ struct inode *inode; |
15223 |
-+ struct socket *sock; |
15224 |
-+ |
15225 |
-+ if (fd < 0) |
15226 |
-+ return ERR_PTR(-EBADF); |
15227 |
-+ |
15228 |
-+ f = fget_raw(fd); |
15229 |
-+ if (!f) |
15230 |
-+ return ERR_PTR(-EBADF); |
15231 |
-+ |
15232 |
-+ inode = file_inode(f); |
15233 |
-+ sock = S_ISSOCK(inode->i_mode) ? SOCKET_I(inode) : NULL; |
15234 |
-+ |
15235 |
-+ if (f->f_mode & FMODE_PATH) |
15236 |
-+ ret = f; /* O_PATH is always allowed */ |
15237 |
-+ else if (f->f_op == &kdbus_handle_ops) |
15238 |
-+ ret = ERR_PTR(-EOPNOTSUPP); /* disallow kdbus-fd over kdbus */ |
15239 |
-+ else if (sock && sock->sk && sock->ops && sock->ops->family == PF_UNIX) |
15240 |
-+ ret = ERR_PTR(-EOPNOTSUPP); /* disallow UDS over kdbus */ |
15241 |
-+ else |
15242 |
-+ ret = f; /* all other are allowed */ |
15243 |
-+ |
15244 |
-+ if (f != ret) |
15245 |
-+ fput(f); |
15246 |
-+ |
15247 |
-+ return ret; |
15248 |
-+} |
15249 |
-+ |
15250 |
-+static struct file *kdbus_get_memfd(const struct kdbus_memfd *memfd) |
15251 |
-+{ |
15252 |
-+ const int m = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL; |
15253 |
-+ struct file *f, *ret; |
15254 |
-+ int s; |
15255 |
-+ |
15256 |
-+ if (memfd->fd < 0) |
15257 |
-+ return ERR_PTR(-EBADF); |
15258 |
-+ |
15259 |
-+ f = fget(memfd->fd); |
15260 |
-+ if (!f) |
15261 |
-+ return ERR_PTR(-EBADF); |
15262 |
-+ |
15263 |
-+ s = shmem_get_seals(f); |
15264 |
-+ if (s < 0) |
15265 |
-+ ret = ERR_PTR(-EMEDIUMTYPE); |
15266 |
-+ else if ((s & m) != m) |
15267 |
-+ ret = ERR_PTR(-ETXTBSY); |
15268 |
-+ else if (memfd->start + memfd->size > (u64)i_size_read(file_inode(f))) |
15269 |
-+ ret = ERR_PTR(-EFAULT); |
15270 |
-+ else |
15271 |
-+ ret = f; |
15272 |
-+ |
15273 |
-+ if (f != ret) |
15274 |
-+ fput(f); |
15275 |
-+ |
15276 |
-+ return ret; |
15277 |
-+} |
15278 |
-+ |
15279 |
-+static int kdbus_msg_examine(struct kdbus_msg *msg, struct kdbus_bus *bus, |
15280 |
-+ struct kdbus_cmd_send *cmd, size_t *out_n_memfds, |
15281 |
-+ size_t *out_n_fds, size_t *out_n_parts) |
15282 |
-+{ |
15283 |
-+ struct kdbus_item *item, *fds = NULL, *bloom = NULL, *dstname = NULL; |
15284 |
-+ u64 n_parts, n_memfds, n_fds, vec_size; |
15285 |
-+ |
15286 |
-+ /* |
15287 |
-+ * Step 1: |
15288 |
-+ * Validate the message and command parameters. |
15289 |
-+ */ |
15290 |
-+ |
15291 |
-+ /* KDBUS_PAYLOAD_KERNEL is reserved to kernel messages */ |
15292 |
-+ if (msg->payload_type == KDBUS_PAYLOAD_KERNEL) |
15293 |
-+ return -EINVAL; |
15294 |
-+ |
15295 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST) { |
15296 |
-+ /* broadcasts must be marked as signals */ |
15297 |
-+ if (!(msg->flags & KDBUS_MSG_SIGNAL)) |
15298 |
-+ return -EBADMSG; |
15299 |
-+ /* broadcasts cannot have timeouts */ |
15300 |
-+ if (msg->timeout_ns > 0) |
15301 |
-+ return -ENOTUNIQ; |
15302 |
-+ } |
15303 |
-+ |
15304 |
-+ if (msg->flags & KDBUS_MSG_EXPECT_REPLY) { |
15305 |
-+ /* if you expect a reply, you must specify a timeout */ |
15306 |
-+ if (msg->timeout_ns == 0) |
15307 |
-+ return -EINVAL; |
15308 |
-+ /* signals cannot have replies */ |
15309 |
-+ if (msg->flags & KDBUS_MSG_SIGNAL) |
15310 |
-+ return -ENOTUNIQ; |
15311 |
-+ } else { |
15312 |
-+ /* must expect reply if sent as synchronous call */ |
15313 |
-+ if (cmd->flags & KDBUS_SEND_SYNC_REPLY) |
15314 |
-+ return -EINVAL; |
15315 |
-+ /* cannot mark replies as signal */ |
15316 |
-+ if (msg->cookie_reply && (msg->flags & KDBUS_MSG_SIGNAL)) |
15317 |
-+ return -EINVAL; |
15318 |
-+ } |
15319 |
-+ |
15320 |
-+ /* |
15321 |
-+ * Step 2: |
15322 |
-+ * Validate all passed items. While at it, select some statistics that |
15323 |
-+ * are required to allocate state objects later on. |
15324 |
-+ * |
15325 |
-+ * Generic item validation has already been done via |
15326 |
-+ * kdbus_item_validate(). Furthermore, the number of items is naturally |
15327 |
-+ * limited by the maximum message size. Hence, only non-generic item |
15328 |
-+ * checks are performed here (mainly integer overflow tests). |
15329 |
-+ */ |
15330 |
-+ |
15331 |
-+ n_parts = 0; |
15332 |
-+ n_memfds = 0; |
15333 |
-+ n_fds = 0; |
15334 |
-+ vec_size = 0; |
15335 |
-+ |
15336 |
-+ KDBUS_ITEMS_FOREACH(item, msg->items, KDBUS_ITEMS_SIZE(msg, items)) { |
15337 |
-+ switch (item->type) { |
15338 |
-+ case KDBUS_ITEM_PAYLOAD_VEC: { |
15339 |
-+ void __force __user *ptr = KDBUS_PTR(item->vec.address); |
15340 |
-+ u64 size = item->vec.size; |
15341 |
-+ |
15342 |
-+ if (vec_size + size < vec_size) |
15343 |
-+ return -EMSGSIZE; |
15344 |
-+ if (vec_size + size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE) |
15345 |
-+ return -EMSGSIZE; |
15346 |
-+ if (ptr && unlikely(!access_ok(VERIFY_READ, ptr, size))) |
15347 |
-+ return -EFAULT; |
15348 |
-+ |
15349 |
-+ if (ptr || size % 8) /* data or padding */ |
15350 |
-+ ++n_parts; |
15351 |
-+ break; |
15352 |
-+ } |
15353 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
15354 |
-+ u64 start = item->memfd.start; |
15355 |
-+ u64 size = item->memfd.size; |
15356 |
-+ |
15357 |
-+ if (start + size < start) |
15358 |
-+ return -EMSGSIZE; |
15359 |
-+ if (n_memfds >= KDBUS_MSG_MAX_MEMFD_ITEMS) |
15360 |
-+ return -E2BIG; |
15361 |
-+ |
15362 |
-+ ++n_memfds; |
15363 |
-+ if (size % 8) /* vec-padding required */ |
15364 |
-+ ++n_parts; |
15365 |
-+ break; |
15366 |
-+ } |
15367 |
-+ case KDBUS_ITEM_FDS: { |
15368 |
-+ if (fds) |
15369 |
-+ return -EEXIST; |
15370 |
-+ |
15371 |
-+ fds = item; |
15372 |
-+ n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int); |
15373 |
-+ if (n_fds > KDBUS_CONN_MAX_FDS_PER_USER) |
15374 |
-+ return -EMFILE; |
15375 |
-+ |
15376 |
-+ break; |
15377 |
-+ } |
15378 |
-+ case KDBUS_ITEM_BLOOM_FILTER: { |
15379 |
-+ u64 bloom_size; |
15380 |
-+ |
15381 |
-+ if (bloom) |
15382 |
-+ return -EEXIST; |
15383 |
-+ |
15384 |
-+ bloom = item; |
15385 |
-+ bloom_size = KDBUS_ITEM_PAYLOAD_SIZE(item) - |
15386 |
-+ offsetof(struct kdbus_bloom_filter, data); |
15387 |
-+ if (!KDBUS_IS_ALIGNED8(bloom_size)) |
15388 |
-+ return -EFAULT; |
15389 |
-+ if (bloom_size != bus->bloom.size) |
15390 |
-+ return -EDOM; |
15391 |
-+ |
15392 |
-+ break; |
15393 |
-+ } |
15394 |
-+ case KDBUS_ITEM_DST_NAME: { |
15395 |
-+ if (dstname) |
15396 |
-+ return -EEXIST; |
15397 |
-+ |
15398 |
-+ dstname = item; |
15399 |
-+ if (!kdbus_name_is_valid(item->str, false)) |
15400 |
-+ return -EINVAL; |
15401 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST) |
15402 |
-+ return -EBADMSG; |
15403 |
-+ |
15404 |
-+ break; |
15405 |
-+ } |
15406 |
-+ default: |
15407 |
-+ return -EINVAL; |
15408 |
-+ } |
15409 |
-+ } |
15410 |
-+ |
15411 |
-+ /* |
15412 |
-+ * Step 3: |
15413 |
-+ * Validate that required items were actually passed, and that no item |
15414 |
-+ * contradicts the message flags. |
15415 |
-+ */ |
15416 |
-+ |
15417 |
-+ /* bloom filters must be attached _iff_ it's a signal */ |
15418 |
-+ if (!(msg->flags & KDBUS_MSG_SIGNAL) != !bloom) |
15419 |
-+ return -EBADMSG; |
15420 |
-+ /* destination name is required if no ID is given */ |
15421 |
-+ if (msg->dst_id == KDBUS_DST_ID_NAME && !dstname) |
15422 |
-+ return -EDESTADDRREQ; |
15423 |
-+ /* cannot send file-descriptors attached to broadcasts */ |
15424 |
-+ if (msg->dst_id == KDBUS_DST_ID_BROADCAST && fds) |
15425 |
-+ return -ENOTUNIQ; |
15426 |
-+ |
15427 |
-+ *out_n_memfds = n_memfds; |
15428 |
-+ *out_n_fds = n_fds; |
15429 |
-+ *out_n_parts = n_parts; |
15430 |
-+ |
15431 |
-+ return 0; |
15432 |
-+} |
15433 |
-+ |
15434 |
-+static bool kdbus_staging_merge_vecs(struct kdbus_staging *staging, |
15435 |
-+ struct kdbus_item **prev_item, |
15436 |
-+ struct iovec **prev_vec, |
15437 |
-+ const struct kdbus_item *merge) |
15438 |
-+{ |
15439 |
-+ void __user *ptr = (void __user *)KDBUS_PTR(merge->vec.address); |
15440 |
-+ u64 padding = merge->vec.size % 8; |
15441 |
-+ struct kdbus_item *prev = *prev_item; |
15442 |
-+ struct iovec *vec = *prev_vec; |
15443 |
-+ |
15444 |
-+ /* XXX: merging is disabled so far */ |
15445 |
-+ if (0 && prev && prev->type == KDBUS_ITEM_PAYLOAD_OFF && |
15446 |
-+ !merge->vec.address == !prev->vec.address) { |
15447 |
-+ /* |
15448 |
-+ * If we merge two VECs, we can always drop the second |
15449 |
-+ * PAYLOAD_VEC item. Hence, include its size in the previous |
15450 |
-+ * one. |
15451 |
-+ */ |
15452 |
-+ prev->vec.size += merge->vec.size; |
15453 |
-+ |
15454 |
-+ if (ptr) { |
15455 |
-+ /* |
15456 |
-+ * If we merge two data VECs, we need two iovecs to copy |
15457 |
-+ * the data. But the items can be easily merged by |
15458 |
-+ * summing their lengths. |
15459 |
-+ */ |
15460 |
-+ vec = &staging->parts[staging->n_parts++]; |
15461 |
-+ vec->iov_len = merge->vec.size; |
15462 |
-+ vec->iov_base = ptr; |
15463 |
-+ staging->n_payload += vec->iov_len; |
15464 |
-+ } else if (padding) { |
15465 |
-+ /* |
15466 |
-+ * If we merge two 0-vecs with the second 0-vec |
15467 |
-+ * requiring padding, we need to insert an iovec to copy |
15468 |
-+ * the 0-padding. We try merging it with the previous |
15469 |
-+ * 0-padding iovec. This might end up with an |
15470 |
-+ * iov_len==0, in which case we simply drop the iovec. |
15471 |
-+ */ |
15472 |
-+ if (vec) { |
15473 |
-+ staging->n_payload -= vec->iov_len; |
15474 |
-+ vec->iov_len = prev->vec.size % 8; |
15475 |
-+ if (!vec->iov_len) { |
15476 |
-+ --staging->n_parts; |
15477 |
-+ vec = NULL; |
15478 |
-+ } else { |
15479 |
-+ staging->n_payload += vec->iov_len; |
15480 |
-+ } |
15481 |
-+ } else { |
15482 |
-+ vec = &staging->parts[staging->n_parts++]; |
15483 |
-+ vec->iov_len = padding; |
15484 |
-+ vec->iov_base = (char __user *)zeros; |
15485 |
-+ staging->n_payload += vec->iov_len; |
15486 |
-+ } |
15487 |
-+ } else { |
15488 |
-+ /* |
15489 |
-+ * If we merge two 0-vecs with the second 0-vec having |
15490 |
-+ * no padding, we know the padding of the first stays |
15491 |
-+ * the same. Hence, @vec needs no adjustment. |
15492 |
-+ */ |
15493 |
-+ } |
15494 |
-+ |
15495 |
-+ /* successfully merged with previous item */ |
15496 |
-+ merge = prev; |
15497 |
-+ } else { |
15498 |
-+ /* |
15499 |
-+ * If we cannot merge the payload item with the previous one, |
15500 |
-+ * we simply insert a new iovec for the data/padding. |
15501 |
-+ */ |
15502 |
-+ if (ptr) { |
15503 |
-+ vec = &staging->parts[staging->n_parts++]; |
15504 |
-+ vec->iov_len = merge->vec.size; |
15505 |
-+ vec->iov_base = ptr; |
15506 |
-+ staging->n_payload += vec->iov_len; |
15507 |
-+ } else if (padding) { |
15508 |
-+ vec = &staging->parts[staging->n_parts++]; |
15509 |
-+ vec->iov_len = padding; |
15510 |
-+ vec->iov_base = (char __user *)zeros; |
15511 |
-+ staging->n_payload += vec->iov_len; |
15512 |
-+ } else { |
15513 |
-+ vec = NULL; |
15514 |
-+ } |
15515 |
-+ } |
15516 |
-+ |
15517 |
-+ *prev_item = (struct kdbus_item *)merge; |
15518 |
-+ *prev_vec = vec; |
15519 |
-+ |
15520 |
-+ return merge == prev; |
15521 |
-+} |
15522 |
-+ |
15523 |
-+static int kdbus_staging_import(struct kdbus_staging *staging) |
15524 |
-+{ |
15525 |
-+ struct kdbus_item *it, *item, *last, *prev_payload; |
15526 |
-+ struct kdbus_gaps *gaps = staging->gaps; |
15527 |
-+ struct kdbus_msg *msg = staging->msg; |
15528 |
-+ struct iovec *part, *prev_part; |
15529 |
-+ bool drop_item; |
15530 |
-+ |
15531 |
-+ drop_item = false; |
15532 |
-+ last = NULL; |
15533 |
-+ prev_payload = NULL; |
15534 |
-+ prev_part = NULL; |
15535 |
-+ |
15536 |
-+ /* |
15537 |
-+ * We modify msg->items along the way; make sure to use @item as offset |
15538 |
-+ * to the next item (instead of the iterator @it). |
15539 |
-+ */ |
15540 |
-+ for (it = item = msg->items; |
15541 |
-+ it >= msg->items && |
15542 |
-+ (u8 *)it < (u8 *)msg + msg->size && |
15543 |
-+ (u8 *)it + it->size <= (u8 *)msg + msg->size; ) { |
15544 |
-+ /* |
15545 |
-+ * If we dropped items along the way, move current item to |
15546 |
-+ * front. We must not access @it afterwards, but use @item |
15547 |
-+ * instead! |
15548 |
-+ */ |
15549 |
-+ if (it != item) |
15550 |
-+ memmove(item, it, it->size); |
15551 |
-+ it = (void *)((u8 *)it + KDBUS_ALIGN8(item->size)); |
15552 |
-+ |
15553 |
-+ switch (item->type) { |
15554 |
-+ case KDBUS_ITEM_PAYLOAD_VEC: { |
15555 |
-+ size_t offset = staging->n_payload; |
15556 |
-+ |
15557 |
-+ if (kdbus_staging_merge_vecs(staging, &prev_payload, |
15558 |
-+ &prev_part, item)) { |
15559 |
-+ drop_item = true; |
15560 |
-+ } else if (item->vec.address) { |
15561 |
-+ /* real offset is patched later on */ |
15562 |
-+ item->type = KDBUS_ITEM_PAYLOAD_OFF; |
15563 |
-+ item->vec.offset = offset; |
15564 |
-+ } else { |
15565 |
-+ item->type = KDBUS_ITEM_PAYLOAD_OFF; |
15566 |
-+ item->vec.offset = ~0ULL; |
15567 |
-+ } |
15568 |
-+ |
15569 |
-+ break; |
15570 |
-+ } |
15571 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
15572 |
-+ struct file *f; |
15573 |
-+ |
15574 |
-+ f = kdbus_get_memfd(&item->memfd); |
15575 |
-+ if (IS_ERR(f)) |
15576 |
-+ return PTR_ERR(f); |
15577 |
-+ |
15578 |
-+ gaps->memfd_files[gaps->n_memfds] = f; |
15579 |
-+ gaps->memfd_offsets[gaps->n_memfds] = |
15580 |
-+ (u8 *)&item->memfd.fd - (u8 *)msg; |
15581 |
-+ ++gaps->n_memfds; |
15582 |
-+ |
15583 |
-+ /* memfds cannot be merged */ |
15584 |
-+ prev_payload = item; |
15585 |
-+ prev_part = NULL; |
15586 |
-+ |
15587 |
-+ /* insert padding to make following VECs aligned */ |
15588 |
-+ if (item->memfd.size % 8) { |
15589 |
-+ part = &staging->parts[staging->n_parts++]; |
15590 |
-+ part->iov_len = item->memfd.size % 8; |
15591 |
-+ part->iov_base = (char __user *)zeros; |
15592 |
-+ staging->n_payload += part->iov_len; |
15593 |
-+ } |
15594 |
-+ |
15595 |
-+ break; |
15596 |
-+ } |
15597 |
-+ case KDBUS_ITEM_FDS: { |
15598 |
-+ size_t i, n_fds; |
15599 |
-+ |
15600 |
-+ n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int); |
15601 |
-+ for (i = 0; i < n_fds; ++i) { |
15602 |
-+ struct file *f; |
15603 |
-+ |
15604 |
-+ f = kdbus_get_fd(item->fds[i]); |
15605 |
-+ if (IS_ERR(f)) |
15606 |
-+ return PTR_ERR(f); |
15607 |
-+ |
15608 |
-+ gaps->fd_files[gaps->n_fds++] = f; |
15609 |
-+ } |
15610 |
-+ |
15611 |
-+ gaps->fd_offset = (u8 *)item->fds - (u8 *)msg; |
15612 |
-+ |
15613 |
-+ break; |
15614 |
-+ } |
15615 |
-+ case KDBUS_ITEM_BLOOM_FILTER: |
15616 |
-+ staging->bloom_filter = &item->bloom_filter; |
15617 |
-+ break; |
15618 |
-+ case KDBUS_ITEM_DST_NAME: |
15619 |
-+ staging->dst_name = item->str; |
15620 |
-+ break; |
15621 |
-+ } |
15622 |
-+ |
15623 |
-+ /* drop item if we merged it with a previous one */ |
15624 |
-+ if (drop_item) { |
15625 |
-+ drop_item = false; |
15626 |
-+ } else { |
15627 |
-+ last = item; |
15628 |
-+ item = KDBUS_ITEM_NEXT(item); |
15629 |
-+ } |
15630 |
-+ } |
15631 |
-+ |
15632 |
-+ /* adjust message size regarding dropped items */ |
15633 |
-+ msg->size = offsetof(struct kdbus_msg, items); |
15634 |
-+ if (last) |
15635 |
-+ msg->size += ((u8 *)last - (u8 *)msg->items) + last->size; |
15636 |
-+ |
15637 |
-+ return 0; |
15638 |
-+} |
15639 |
-+ |
15640 |
-+static void kdbus_staging_reserve(struct kdbus_staging *staging) |
15641 |
-+{ |
15642 |
-+ struct iovec *part; |
15643 |
-+ |
15644 |
-+ part = &staging->parts[staging->n_parts++]; |
15645 |
-+ part->iov_base = (void __user *)zeros; |
15646 |
-+ part->iov_len = 0; |
15647 |
-+} |
15648 |
-+ |
15649 |
-+static struct kdbus_staging *kdbus_staging_new(struct kdbus_bus *bus, |
15650 |
-+ size_t n_parts, |
15651 |
-+ size_t msg_extra_size) |
15652 |
-+{ |
15653 |
-+ const size_t reserved_parts = 5; /* see below for explanation */ |
15654 |
-+ struct kdbus_staging *staging; |
15655 |
-+ int ret; |
15656 |
-+ |
15657 |
-+ n_parts += reserved_parts; |
15658 |
-+ |
15659 |
-+ staging = kzalloc(sizeof(*staging) + n_parts * sizeof(*staging->parts) + |
15660 |
-+ msg_extra_size, GFP_TEMPORARY); |
15661 |
-+ if (!staging) |
15662 |
-+ return ERR_PTR(-ENOMEM); |
15663 |
-+ |
15664 |
-+ staging->msg_seqnum = atomic64_inc_return(&bus->last_message_id); |
15665 |
-+ staging->n_parts = 0; /* we reserve n_parts, but don't enforce them */ |
15666 |
-+ staging->parts = (void *)(staging + 1); |
15667 |
-+ |
15668 |
-+ if (msg_extra_size) /* if requested, allocate message, too */ |
15669 |
-+ staging->msg = (void *)((u8 *)staging->parts + |
15670 |
-+ n_parts * sizeof(*staging->parts)); |
15671 |
-+ |
15672 |
-+ staging->meta_proc = kdbus_meta_proc_new(); |
15673 |
-+ if (IS_ERR(staging->meta_proc)) { |
15674 |
-+ ret = PTR_ERR(staging->meta_proc); |
15675 |
-+ staging->meta_proc = NULL; |
15676 |
-+ goto error; |
15677 |
-+ } |
15678 |
-+ |
15679 |
-+ staging->meta_conn = kdbus_meta_conn_new(); |
15680 |
-+ if (IS_ERR(staging->meta_conn)) { |
15681 |
-+ ret = PTR_ERR(staging->meta_conn); |
15682 |
-+ staging->meta_conn = NULL; |
15683 |
-+ goto error; |
15684 |
-+ } |
15685 |
-+ |
15686 |
-+ /* |
15687 |
-+ * Prepare iovecs to copy the message into the target pool. We use the |
15688 |
-+ * following iovecs: |
15689 |
-+ * * iovec to copy "kdbus_msg.size" |
15690 |
-+ * * iovec to copy "struct kdbus_msg" (minus size) plus items |
15691 |
-+ * * iovec for possible padding after the items |
15692 |
-+ * * iovec for metadata items |
15693 |
-+ * * iovec for possible padding after the items |
15694 |
-+ * |
15695 |
-+ * Make sure to update @reserved_parts if you add more parts here. |
15696 |
-+ */ |
15697 |
-+ |
15698 |
-+ kdbus_staging_reserve(staging); /* msg.size */ |
15699 |
-+ kdbus_staging_reserve(staging); /* msg (minus msg.size) plus items */ |
15700 |
-+ kdbus_staging_reserve(staging); /* msg padding */ |
15701 |
-+ kdbus_staging_reserve(staging); /* meta */ |
15702 |
-+ kdbus_staging_reserve(staging); /* meta padding */ |
15703 |
-+ |
15704 |
-+ return staging; |
15705 |
-+ |
15706 |
-+error: |
15707 |
-+ kdbus_staging_free(staging); |
15708 |
-+ return ERR_PTR(ret); |
15709 |
-+} |
15710 |
-+ |
15711 |
-+struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus, |
15712 |
-+ u64 dst, u64 cookie_timeout, |
15713 |
-+ size_t it_size, size_t it_type) |
15714 |
-+{ |
15715 |
-+ struct kdbus_staging *staging; |
15716 |
-+ size_t size; |
15717 |
-+ |
15718 |
-+ size = offsetof(struct kdbus_msg, items) + |
15719 |
-+ KDBUS_ITEM_HEADER_SIZE + it_size; |
15720 |
-+ |
15721 |
-+ staging = kdbus_staging_new(bus, 0, KDBUS_ALIGN8(size)); |
15722 |
-+ if (IS_ERR(staging)) |
15723 |
-+ return ERR_CAST(staging); |
15724 |
-+ |
15725 |
-+ staging->msg->size = size; |
15726 |
-+ staging->msg->flags = (dst == KDBUS_DST_ID_BROADCAST) ? |
15727 |
-+ KDBUS_MSG_SIGNAL : 0; |
15728 |
-+ staging->msg->dst_id = dst; |
15729 |
-+ staging->msg->src_id = KDBUS_SRC_ID_KERNEL; |
15730 |
-+ staging->msg->payload_type = KDBUS_PAYLOAD_KERNEL; |
15731 |
-+ staging->msg->cookie_reply = cookie_timeout; |
15732 |
-+ staging->notify = staging->msg->items; |
15733 |
-+ staging->notify->size = KDBUS_ITEM_HEADER_SIZE + it_size; |
15734 |
-+ staging->notify->type = it_type; |
15735 |
-+ |
15736 |
-+ return staging; |
15737 |
-+} |
15738 |
-+ |
15739 |
-+struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus, |
15740 |
-+ struct kdbus_cmd_send *cmd, |
15741 |
-+ struct kdbus_msg *msg) |
15742 |
-+{ |
15743 |
-+ const size_t reserved_parts = 1; /* see below for explanation */ |
15744 |
-+ size_t n_memfds, n_fds, n_parts; |
15745 |
-+ struct kdbus_staging *staging; |
15746 |
-+ int ret; |
15747 |
-+ |
15748 |
-+ /* |
15749 |
-+ * Examine user-supplied message and figure out how many resources we |
15750 |
-+ * need to allocate in our staging area. This requires us to iterate |
15751 |
-+ * the message twice, but saves us from re-allocating our resources |
15752 |
-+ * all the time. |
15753 |
-+ */ |
15754 |
-+ |
15755 |
-+ ret = kdbus_msg_examine(msg, bus, cmd, &n_memfds, &n_fds, &n_parts); |
15756 |
-+ if (ret < 0) |
15757 |
-+ return ERR_PTR(ret); |
15758 |
-+ |
15759 |
-+ n_parts += reserved_parts; |
15760 |
-+ |
15761 |
-+ /* |
15762 |
-+ * Allocate staging area with the number of required resources. Make |
15763 |
-+ * sure that we have enough iovecs for all required parts pre-allocated |
15764 |
-+ * so this will hopefully be the only memory allocation for this |
15765 |
-+ * message transaction. |
15766 |
-+ */ |
15767 |
-+ |
15768 |
-+ staging = kdbus_staging_new(bus, n_parts, 0); |
15769 |
-+ if (IS_ERR(staging)) |
15770 |
-+ return ERR_CAST(staging); |
15771 |
-+ |
15772 |
-+ staging->msg = msg; |
15773 |
-+ |
15774 |
-+ /* |
15775 |
-+ * If the message contains memfds or fd items, we need to remember some |
15776 |
-+ * state so we can fill in the requested information at RECV time. |
15777 |
-+ * File-descriptors cannot be passed at SEND time. Hence, allocate a |
15778 |
-+ * gaps-object to remember that state. That gaps object is linked to |
15779 |
-+ * from the staging area, but will also be linked to from the message |
15780 |
-+ * queue of each peer. Hence, each receiver owns a reference to it, and |
15781 |
-+ * it will later be used to fill the 'gaps' in message that couldn't be |
15782 |
-+ * filled at SEND time. |
15783 |
-+ * Note that the 'gaps' object is read-only once the staging-allocator |
15784 |
-+ * returns. There might be connections receiving a queued message while |
15785 |
-+ * the sender still broadcasts the message to other receivers. |
15786 |
-+ */ |
15787 |
-+ |
15788 |
-+ if (n_memfds > 0 || n_fds > 0) { |
15789 |
-+ staging->gaps = kdbus_gaps_new(n_memfds, n_fds); |
15790 |
-+ if (IS_ERR(staging->gaps)) { |
15791 |
-+ ret = PTR_ERR(staging->gaps); |
15792 |
-+ staging->gaps = NULL; |
15793 |
-+ kdbus_staging_free(staging); |
15794 |
-+ return ERR_PTR(ret); |
15795 |
-+ } |
15796 |
-+ } |
15797 |
-+ |
15798 |
-+ /* |
15799 |
-+ * kdbus_staging_new() already reserves parts for message setup. For |
15800 |
-+ * user-supplied messages, we add the following iovecs: |
15801 |
-+ * ... variable number of iovecs for payload ... |
15802 |
-+ * * final iovec for possible padding of payload |
15803 |
-+ * |
15804 |
-+ * Make sure to update @reserved_parts if you add more parts here. |
15805 |
-+ */ |
15806 |
-+ |
15807 |
-+ ret = kdbus_staging_import(staging); /* payload */ |
15808 |
-+ kdbus_staging_reserve(staging); /* payload padding */ |
15809 |
-+ |
15810 |
-+ if (ret < 0) |
15811 |
-+ goto error; |
15812 |
-+ |
15813 |
-+ return staging; |
15814 |
-+ |
15815 |
-+error: |
15816 |
-+ kdbus_staging_free(staging); |
15817 |
-+ return ERR_PTR(ret); |
15818 |
-+} |
15819 |
-+ |
15820 |
-+struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging) |
15821 |
-+{ |
15822 |
-+ if (!staging) |
15823 |
-+ return NULL; |
15824 |
-+ |
15825 |
-+ kdbus_meta_conn_unref(staging->meta_conn); |
15826 |
-+ kdbus_meta_proc_unref(staging->meta_proc); |
15827 |
-+ kdbus_gaps_unref(staging->gaps); |
15828 |
-+ kfree(staging); |
15829 |
-+ |
15830 |
-+ return NULL; |
15831 |
-+} |
15832 |
-+ |
15833 |
-+static int kdbus_staging_collect_metadata(struct kdbus_staging *staging, |
15834 |
-+ struct kdbus_conn *src, |
15835 |
-+ struct kdbus_conn *dst, |
15836 |
-+ u64 *out_attach) |
15837 |
-+{ |
15838 |
-+ u64 attach; |
15839 |
-+ int ret; |
15840 |
-+ |
15841 |
-+ if (src) |
15842 |
-+ attach = kdbus_meta_msg_mask(src, dst); |
15843 |
-+ else |
15844 |
-+ attach = KDBUS_ATTACH_TIMESTAMP; /* metadata for kernel msgs */ |
15845 |
-+ |
15846 |
-+ if (src && !src->meta_fake) { |
15847 |
-+ ret = kdbus_meta_proc_collect(staging->meta_proc, attach); |
15848 |
-+ if (ret < 0) |
15849 |
-+ return ret; |
15850 |
-+ } |
15851 |
-+ |
15852 |
-+ ret = kdbus_meta_conn_collect(staging->meta_conn, src, |
15853 |
-+ staging->msg_seqnum, attach); |
15854 |
-+ if (ret < 0) |
15855 |
-+ return ret; |
15856 |
-+ |
15857 |
-+ *out_attach = attach; |
15858 |
-+ return 0; |
15859 |
-+} |
15860 |
-+ |
15861 |
-+/** |
15862 |
-+ * kdbus_staging_emit() - emit linearized message in target pool |
15863 |
-+ * @staging: staging object to create message from |
15864 |
-+ * @src: sender of the message (or NULL) |
15865 |
-+ * @dst: target connection to allocate message for |
15866 |
-+ * |
15867 |
-+ * This allocates a pool-slice for @dst and copies the message provided by |
15868 |
-+ * @staging into it. The new slice is then returned to the caller for further |
15869 |
-+ * processing. It's not linked into any queue, yet. |
15870 |
-+ * |
15871 |
-+ * Return: Newly allocated slice or ERR_PTR on failure. |
15872 |
-+ */ |
15873 |
-+struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging, |
15874 |
-+ struct kdbus_conn *src, |
15875 |
-+ struct kdbus_conn *dst) |
15876 |
-+{ |
15877 |
-+ struct kdbus_item *item, *meta_items = NULL; |
15878 |
-+ struct kdbus_pool_slice *slice = NULL; |
15879 |
-+ size_t off, size, meta_size; |
15880 |
-+ struct iovec *v; |
15881 |
-+ u64 attach, msg_size; |
15882 |
-+ int ret; |
15883 |
-+ |
15884 |
-+ /* |
15885 |
-+ * Step 1: |
15886 |
-+ * Collect metadata from @src depending on the attach-flags allowed for |
15887 |
-+ * @dst. Translate it into the namespaces pinned by @dst. |
15888 |
-+ */ |
15889 |
-+ |
15890 |
-+ ret = kdbus_staging_collect_metadata(staging, src, dst, &attach); |
15891 |
-+ if (ret < 0) |
15892 |
-+ goto error; |
15893 |
-+ |
15894 |
-+ ret = kdbus_meta_emit(staging->meta_proc, NULL, staging->meta_conn, |
15895 |
-+ dst, attach, &meta_items, &meta_size); |
15896 |
-+ if (ret < 0) |
15897 |
-+ goto error; |
15898 |
-+ |
15899 |
-+ /* |
15900 |
-+ * Step 2: |
15901 |
-+ * Setup iovecs for the message. See kdbus_staging_new() for allocation |
15902 |
-+ * of those iovecs. All reserved iovecs have been initialized with |
15903 |
-+ * iov_len=0 + iov_base=zeros. Furthermore, the iovecs to copy the |
15904 |
-+ * actual message payload have already been initialized and need not be |
15905 |
-+ * touched. |
15906 |
-+ */ |
15907 |
-+ |
15908 |
-+ v = staging->parts; |
15909 |
-+ msg_size = staging->msg->size; |
15910 |
-+ |
15911 |
-+ /* msg.size */ |
15912 |
-+ v->iov_len = sizeof(msg_size); |
15913 |
-+ v->iov_base = (void __user *)&msg_size; |
15914 |
-+ ++v; |
15915 |
-+ |
15916 |
-+ /* msg (after msg.size) plus items */ |
15917 |
-+ v->iov_len = staging->msg->size - sizeof(staging->msg->size); |
15918 |
-+ v->iov_base = (void __user *)((u8 *)staging->msg + |
15919 |
-+ sizeof(staging->msg->size)); |
15920 |
-+ ++v; |
15921 |
-+ |
15922 |
-+ /* padding after msg */ |
15923 |
-+ v->iov_len = KDBUS_ALIGN8(staging->msg->size) - staging->msg->size; |
15924 |
-+ v->iov_base = (void __user *)zeros; |
15925 |
-+ ++v; |
15926 |
-+ |
15927 |
-+ if (meta_size > 0) { |
15928 |
-+ /* metadata items */ |
15929 |
-+ v->iov_len = meta_size; |
15930 |
-+ v->iov_base = (void __user *)meta_items; |
15931 |
-+ ++v; |
15932 |
-+ |
15933 |
-+ /* padding after metadata */ |
15934 |
-+ v->iov_len = KDBUS_ALIGN8(meta_size) - meta_size; |
15935 |
-+ v->iov_base = (void __user *)zeros; |
15936 |
-+ ++v; |
15937 |
-+ |
15938 |
-+ msg_size = KDBUS_ALIGN8(msg_size) + meta_size; |
15939 |
-+ } else { |
15940 |
-+ /* metadata items */ |
15941 |
-+ v->iov_len = 0; |
15942 |
-+ v->iov_base = (void __user *)zeros; |
15943 |
-+ ++v; |
15944 |
-+ |
15945 |
-+ /* padding after metadata */ |
15946 |
-+ v->iov_len = 0; |
15947 |
-+ v->iov_base = (void __user *)zeros; |
15948 |
-+ ++v; |
15949 |
-+ } |
15950 |
-+ |
15951 |
-+ /* ... payload iovecs are already filled in ... */ |
15952 |
-+ |
15953 |
-+ /* compute overall size and fill in padding after payload */ |
15954 |
-+ size = KDBUS_ALIGN8(msg_size); |
15955 |
-+ |
15956 |
-+ if (staging->n_payload > 0) { |
15957 |
-+ size += staging->n_payload; |
15958 |
-+ |
15959 |
-+ v = &staging->parts[staging->n_parts - 1]; |
15960 |
-+ v->iov_len = KDBUS_ALIGN8(size) - size; |
15961 |
-+ v->iov_base = (void __user *)zeros; |
15962 |
-+ |
15963 |
-+ size = KDBUS_ALIGN8(size); |
15964 |
-+ } |
15965 |
-+ |
15966 |
-+ /* |
15967 |
-+ * Step 3: |
15968 |
-+ * The PAYLOAD_OFF items in the message contain a relative 'offset' |
15969 |
-+ * field that tells the receiver where to find the actual payload. This |
15970 |
-+ * offset is relative to the start of the message, and as such depends |
15971 |
-+ * on the size of the metadata items we inserted. This size is variable |
15972 |
-+ * and changes for each peer we send the message to. Hence, we remember |
15973 |
-+ * the last relative offset that was used to calculate the 'offset' |
15974 |
-+ * fields. For each message, we re-calculate it and patch all items, in |
15975 |
-+ * case it changed. |
15976 |
-+ */ |
15977 |
-+ |
15978 |
-+ off = KDBUS_ALIGN8(msg_size); |
15979 |
-+ |
15980 |
-+ if (off != staging->i_payload) { |
15981 |
-+ KDBUS_ITEMS_FOREACH(item, staging->msg->items, |
15982 |
-+ KDBUS_ITEMS_SIZE(staging->msg, items)) { |
15983 |
-+ if (item->type != KDBUS_ITEM_PAYLOAD_OFF) |
15984 |
-+ continue; |
15985 |
-+ |
15986 |
-+ item->vec.offset -= staging->i_payload; |
15987 |
-+ item->vec.offset += off; |
15988 |
-+ } |
15989 |
-+ |
15990 |
-+ staging->i_payload = off; |
15991 |
-+ } |
15992 |
-+ |
15993 |
-+ /* |
15994 |
-+ * Step 4: |
15995 |
-+ * Allocate pool slice and copy over all data. Make sure to properly |
15996 |
-+ * account on user quota. |
15997 |
-+ */ |
15998 |
-+ |
15999 |
-+ ret = kdbus_conn_quota_inc(dst, src ? src->user : NULL, size, |
16000 |
-+ staging->gaps ? staging->gaps->n_fds : 0); |
16001 |
-+ if (ret < 0) |
16002 |
-+ goto error; |
16003 |
-+ |
16004 |
-+ slice = kdbus_pool_slice_alloc(dst->pool, size, true); |
16005 |
-+ if (IS_ERR(slice)) { |
16006 |
-+ ret = PTR_ERR(slice); |
16007 |
-+ slice = NULL; |
16008 |
-+ goto error; |
16009 |
-+ } |
16010 |
-+ |
16011 |
-+ WARN_ON(kdbus_pool_slice_size(slice) != size); |
16012 |
-+ |
16013 |
-+ ret = kdbus_pool_slice_copy_iovec(slice, 0, staging->parts, |
16014 |
-+ staging->n_parts, size); |
16015 |
-+ if (ret < 0) |
16016 |
-+ goto error; |
16017 |
-+ |
16018 |
-+ /* all done, return slice to caller */ |
16019 |
-+ goto exit; |
16020 |
-+ |
16021 |
-+error: |
16022 |
-+ if (slice) |
16023 |
-+ kdbus_conn_quota_dec(dst, src ? src->user : NULL, size, |
16024 |
-+ staging->gaps ? staging->gaps->n_fds : 0); |
16025 |
-+ kdbus_pool_slice_release(slice); |
16026 |
-+ slice = ERR_PTR(ret); |
16027 |
-+exit: |
16028 |
-+ kfree(meta_items); |
16029 |
-+ return slice; |
16030 |
-+} |
16031 |
-diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h |
16032 |
-new file mode 100644 |
16033 |
-index 0000000..298f9c9 |
16034 |
---- /dev/null |
16035 |
-+++ b/ipc/kdbus/message.h |
16036 |
-@@ -0,0 +1,120 @@ |
16037 |
-+/* |
16038 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
16039 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
16040 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
16041 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
16042 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
16043 |
-+ * |
16044 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
16045 |
-+ * the terms of the GNU Lesser General Public License as published by the |
16046 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
16047 |
-+ * your option) any later version. |
16048 |
-+ */ |
16049 |
-+ |
16050 |
-+#ifndef __KDBUS_MESSAGE_H |
16051 |
-+#define __KDBUS_MESSAGE_H |
16052 |
-+ |
16053 |
-+#include <linux/fs.h> |
16054 |
-+#include <linux/kref.h> |
16055 |
-+#include <uapi/linux/kdbus.h> |
16056 |
-+ |
16057 |
-+struct kdbus_bus; |
16058 |
-+struct kdbus_conn; |
16059 |
-+struct kdbus_meta_conn; |
16060 |
-+struct kdbus_meta_proc; |
16061 |
-+struct kdbus_pool_slice; |
16062 |
-+ |
16063 |
-+/** |
16064 |
-+ * struct kdbus_gaps - gaps in message to be filled later |
16065 |
-+ * @kref: Reference counter |
16066 |
-+ * @n_memfd_offs: Number of memfds |
16067 |
-+ * @memfd_offs: Offsets of kdbus_memfd items in target slice |
16068 |
-+ * @n_fds: Number of fds |
16069 |
-+ * @fds: Array of sent fds |
16070 |
-+ * @fds_offset: Offset of fd-array in target slice |
16071 |
-+ * |
16072 |
-+ * The 'gaps' object is used to track data that is needed to fill gaps in a |
16073 |
-+ * message at RECV time. Usually, we try to compile the whole message at SEND |
16074 |
-+ * time. This has the advantage, that we don't have to cache any information and |
16075 |
-+ * can keep the memory consumption small. Furthermore, all copy operations can |
16076 |
-+ * be combined into a single function call, which speeds up transactions |
16077 |
-+ * considerably. |
16078 |
-+ * However, things like file-descriptors can only be fully installed at RECV |
16079 |
-+ * time. The gaps object tracks this data and pins it until a message is |
16080 |
-+ * received. The gaps object is shared between all receivers of the same |
16081 |
-+ * message. |
16082 |
-+ */ |
16083 |
-+struct kdbus_gaps { |
16084 |
-+ struct kref kref; |
16085 |
-+ |
16086 |
-+ /* state tracking for KDBUS_ITEM_PAYLOAD_MEMFD entries */ |
16087 |
-+ size_t n_memfds; |
16088 |
-+ u64 *memfd_offsets; |
16089 |
-+ struct file **memfd_files; |
16090 |
-+ |
16091 |
-+ /* state tracking for KDBUS_ITEM_FDS */ |
16092 |
-+ size_t n_fds; |
16093 |
-+ struct file **fd_files; |
16094 |
-+ u64 fd_offset; |
16095 |
-+}; |
16096 |
-+ |
16097 |
-+struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps); |
16098 |
-+struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps); |
16099 |
-+int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice, |
16100 |
-+ bool *out_incomplete); |
16101 |
-+ |
16102 |
-+/** |
16103 |
-+ * struct kdbus_staging - staging area to import messages |
16104 |
-+ * @msg: User-supplied message |
16105 |
-+ * @gaps: Gaps-object created during import (or NULL if empty) |
16106 |
-+ * @msg_seqnum: Message sequence number |
16107 |
-+ * @notify_entry: Entry into list of kernel-generated notifications |
16108 |
-+ * @i_payload: Current relative index of start of payload |
16109 |
-+ * @n_payload: Total number of bytes needed for payload |
16110 |
-+ * @n_parts: Number of parts |
16111 |
-+ * @parts: Array of iovecs that make up the whole message |
16112 |
-+ * @meta_proc: Process metadata of the sender (or NULL if empty) |
16113 |
-+ * @meta_conn: Connection metadata of the sender (or NULL if empty) |
16114 |
-+ * @bloom_filter: Pointer to the bloom-item in @msg, or NULL |
16115 |
-+ * @dst_name: Pointer to the dst-name-item in @msg, or NULL |
16116 |
-+ * @notify: Pointer to the notification item in @msg, or NULL |
16117 |
-+ * |
16118 |
-+ * The kdbus_staging object is a temporary staging area to import user-supplied |
16119 |
-+ * messages into the kernel. It is only used during SEND and dropped once the |
16120 |
-+ * message is queued. Any data that cannot be collected during SEND, is |
16121 |
-+ * collected in a kdbus_gaps object and attached to the message queue. |
16122 |
-+ */ |
16123 |
-+struct kdbus_staging { |
16124 |
-+ struct kdbus_msg *msg; |
16125 |
-+ struct kdbus_gaps *gaps; |
16126 |
-+ u64 msg_seqnum; |
16127 |
-+ struct list_head notify_entry; |
16128 |
-+ |
16129 |
-+ /* crafted iovecs to copy the message */ |
16130 |
-+ size_t i_payload; |
16131 |
-+ size_t n_payload; |
16132 |
-+ size_t n_parts; |
16133 |
-+ struct iovec *parts; |
16134 |
-+ |
16135 |
-+ /* metadata state */ |
16136 |
-+ struct kdbus_meta_proc *meta_proc; |
16137 |
-+ struct kdbus_meta_conn *meta_conn; |
16138 |
-+ |
16139 |
-+ /* cached pointers into @msg */ |
16140 |
-+ const struct kdbus_bloom_filter *bloom_filter; |
16141 |
-+ const char *dst_name; |
16142 |
-+ struct kdbus_item *notify; |
16143 |
-+}; |
16144 |
-+ |
16145 |
-+struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus, |
16146 |
-+ u64 dst, u64 cookie_timeout, |
16147 |
-+ size_t it_size, size_t it_type); |
16148 |
-+struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus, |
16149 |
-+ struct kdbus_cmd_send *cmd, |
16150 |
-+ struct kdbus_msg *msg); |
16151 |
-+struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging); |
16152 |
-+struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging, |
16153 |
-+ struct kdbus_conn *src, |
16154 |
-+ struct kdbus_conn *dst); |
16155 |
-+ |
16156 |
-+#endif |
16157 |
-diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c |
16158 |
-new file mode 100644 |
16159 |
-index 0000000..71ca475 |
16160 |
---- /dev/null |
16161 |
-+++ b/ipc/kdbus/metadata.c |
16162 |
-@@ -0,0 +1,1347 @@ |
16163 |
-+/* |
16164 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
16165 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
16166 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
16167 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
16168 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
16169 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
16170 |
-+ * |
16171 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
16172 |
-+ * the terms of the GNU Lesser General Public License as published by the |
16173 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
16174 |
-+ * your option) any later version. |
16175 |
-+ */ |
16176 |
-+ |
16177 |
-+#include <linux/audit.h> |
16178 |
-+#include <linux/capability.h> |
16179 |
-+#include <linux/cgroup.h> |
16180 |
-+#include <linux/cred.h> |
16181 |
-+#include <linux/file.h> |
16182 |
-+#include <linux/fs_struct.h> |
16183 |
-+#include <linux/init.h> |
16184 |
-+#include <linux/kref.h> |
16185 |
-+#include <linux/mutex.h> |
16186 |
-+#include <linux/sched.h> |
16187 |
-+#include <linux/security.h> |
16188 |
-+#include <linux/sizes.h> |
16189 |
-+#include <linux/slab.h> |
16190 |
-+#include <linux/uaccess.h> |
16191 |
-+#include <linux/uidgid.h> |
16192 |
-+#include <linux/uio.h> |
16193 |
-+#include <linux/user_namespace.h> |
16194 |
-+ |
16195 |
-+#include "bus.h" |
16196 |
-+#include "connection.h" |
16197 |
-+#include "endpoint.h" |
16198 |
-+#include "item.h" |
16199 |
-+#include "message.h" |
16200 |
-+#include "metadata.h" |
16201 |
-+#include "names.h" |
16202 |
-+ |
16203 |
-+/** |
16204 |
-+ * struct kdbus_meta_proc - Process metadata |
16205 |
-+ * @kref: Reference counting |
16206 |
-+ * @lock: Object lock |
16207 |
-+ * @collected: Bitmask of collected items |
16208 |
-+ * @valid: Bitmask of collected and valid items |
16209 |
-+ * @cred: Credentials |
16210 |
-+ * @pid: PID of process |
16211 |
-+ * @tgid: TGID of process |
16212 |
-+ * @ppid: PPID of process |
16213 |
-+ * @tid_comm: TID comm line |
16214 |
-+ * @pid_comm: PID comm line |
16215 |
-+ * @exe_path: Executable path |
16216 |
-+ * @root_path: Root-FS path |
16217 |
-+ * @cmdline: Command-line |
16218 |
-+ * @cgroup: Full cgroup path |
16219 |
-+ * @seclabel: Seclabel |
16220 |
-+ * @audit_loginuid: Audit login-UID |
16221 |
-+ * @audit_sessionid: Audit session-ID |
16222 |
-+ */ |
16223 |
-+struct kdbus_meta_proc { |
16224 |
-+ struct kref kref; |
16225 |
-+ struct mutex lock; |
16226 |
-+ u64 collected; |
16227 |
-+ u64 valid; |
16228 |
-+ |
16229 |
-+ /* KDBUS_ITEM_CREDS */ |
16230 |
-+ /* KDBUS_ITEM_AUXGROUPS */ |
16231 |
-+ /* KDBUS_ITEM_CAPS */ |
16232 |
-+ const struct cred *cred; |
16233 |
-+ |
16234 |
-+ /* KDBUS_ITEM_PIDS */ |
16235 |
-+ struct pid *pid; |
16236 |
-+ struct pid *tgid; |
16237 |
-+ struct pid *ppid; |
16238 |
-+ |
16239 |
-+ /* KDBUS_ITEM_TID_COMM */ |
16240 |
-+ char tid_comm[TASK_COMM_LEN]; |
16241 |
-+ /* KDBUS_ITEM_PID_COMM */ |
16242 |
-+ char pid_comm[TASK_COMM_LEN]; |
16243 |
-+ |
16244 |
-+ /* KDBUS_ITEM_EXE */ |
16245 |
-+ struct path exe_path; |
16246 |
-+ struct path root_path; |
16247 |
-+ |
16248 |
-+ /* KDBUS_ITEM_CMDLINE */ |
16249 |
-+ char *cmdline; |
16250 |
-+ |
16251 |
-+ /* KDBUS_ITEM_CGROUP */ |
16252 |
-+ char *cgroup; |
16253 |
-+ |
16254 |
-+ /* KDBUS_ITEM_SECLABEL */ |
16255 |
-+ char *seclabel; |
16256 |
-+ |
16257 |
-+ /* KDBUS_ITEM_AUDIT */ |
16258 |
-+ kuid_t audit_loginuid; |
16259 |
-+ unsigned int audit_sessionid; |
16260 |
-+}; |
16261 |
-+ |
16262 |
-+/** |
16263 |
-+ * struct kdbus_meta_conn |
16264 |
-+ * @kref: Reference counting |
16265 |
-+ * @lock: Object lock |
16266 |
-+ * @collected: Bitmask of collected items |
16267 |
-+ * @valid: Bitmask of collected and valid items |
16268 |
-+ * @ts: Timestamp values |
16269 |
-+ * @owned_names_items: Serialized items for owned names |
16270 |
-+ * @owned_names_size: Size of @owned_names_items |
16271 |
-+ * @conn_description: Connection description |
16272 |
-+ */ |
16273 |
-+struct kdbus_meta_conn { |
16274 |
-+ struct kref kref; |
16275 |
-+ struct mutex lock; |
16276 |
-+ u64 collected; |
16277 |
-+ u64 valid; |
16278 |
-+ |
16279 |
-+ /* KDBUS_ITEM_TIMESTAMP */ |
16280 |
-+ struct kdbus_timestamp ts; |
16281 |
-+ |
16282 |
-+ /* KDBUS_ITEM_OWNED_NAME */ |
16283 |
-+ struct kdbus_item *owned_names_items; |
16284 |
-+ size_t owned_names_size; |
16285 |
-+ |
16286 |
-+ /* KDBUS_ITEM_CONN_DESCRIPTION */ |
16287 |
-+ char *conn_description; |
16288 |
-+}; |
16289 |
-+ |
16290 |
-+/* fixed size equivalent of "kdbus_caps" */ |
16291 |
-+struct kdbus_meta_caps { |
16292 |
-+ u32 last_cap; |
16293 |
-+ struct { |
16294 |
-+ u32 caps[_KERNEL_CAPABILITY_U32S]; |
16295 |
-+ } set[4]; |
16296 |
-+}; |
16297 |
-+ |
16298 |
-+/** |
16299 |
-+ * kdbus_meta_proc_new() - Create process metadata object |
16300 |
-+ * |
16301 |
-+ * Return: Pointer to new object on success, ERR_PTR on failure. |
16302 |
-+ */ |
16303 |
-+struct kdbus_meta_proc *kdbus_meta_proc_new(void) |
16304 |
-+{ |
16305 |
-+ struct kdbus_meta_proc *mp; |
16306 |
-+ |
16307 |
-+ mp = kzalloc(sizeof(*mp), GFP_KERNEL); |
16308 |
-+ if (!mp) |
16309 |
-+ return ERR_PTR(-ENOMEM); |
16310 |
-+ |
16311 |
-+ kref_init(&mp->kref); |
16312 |
-+ mutex_init(&mp->lock); |
16313 |
-+ |
16314 |
-+ return mp; |
16315 |
-+} |
16316 |
-+ |
16317 |
-+static void kdbus_meta_proc_free(struct kref *kref) |
16318 |
-+{ |
16319 |
-+ struct kdbus_meta_proc *mp = container_of(kref, struct kdbus_meta_proc, |
16320 |
-+ kref); |
16321 |
-+ |
16322 |
-+ path_put(&mp->exe_path); |
16323 |
-+ path_put(&mp->root_path); |
16324 |
-+ if (mp->cred) |
16325 |
-+ put_cred(mp->cred); |
16326 |
-+ put_pid(mp->ppid); |
16327 |
-+ put_pid(mp->tgid); |
16328 |
-+ put_pid(mp->pid); |
16329 |
-+ |
16330 |
-+ kfree(mp->seclabel); |
16331 |
-+ kfree(mp->cmdline); |
16332 |
-+ kfree(mp->cgroup); |
16333 |
-+ kfree(mp); |
16334 |
-+} |
16335 |
-+ |
16336 |
-+/** |
16337 |
-+ * kdbus_meta_proc_ref() - Gain reference |
16338 |
-+ * @mp: Process metadata object |
16339 |
-+ * |
16340 |
-+ * Return: @mp is returned |
16341 |
-+ */ |
16342 |
-+struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp) |
16343 |
-+{ |
16344 |
-+ if (mp) |
16345 |
-+ kref_get(&mp->kref); |
16346 |
-+ return mp; |
16347 |
-+} |
16348 |
-+ |
16349 |
-+/** |
16350 |
-+ * kdbus_meta_proc_unref() - Drop reference |
16351 |
-+ * @mp: Process metadata object |
16352 |
-+ * |
16353 |
-+ * Return: NULL |
16354 |
-+ */ |
16355 |
-+struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp) |
16356 |
-+{ |
16357 |
-+ if (mp) |
16358 |
-+ kref_put(&mp->kref, kdbus_meta_proc_free); |
16359 |
-+ return NULL; |
16360 |
-+} |
16361 |
-+ |
16362 |
-+static void kdbus_meta_proc_collect_pids(struct kdbus_meta_proc *mp) |
16363 |
-+{ |
16364 |
-+ struct task_struct *parent; |
16365 |
-+ |
16366 |
-+ mp->pid = get_pid(task_pid(current)); |
16367 |
-+ mp->tgid = get_pid(task_tgid(current)); |
16368 |
-+ |
16369 |
-+ rcu_read_lock(); |
16370 |
-+ parent = rcu_dereference(current->real_parent); |
16371 |
-+ mp->ppid = get_pid(task_tgid(parent)); |
16372 |
-+ rcu_read_unlock(); |
16373 |
-+ |
16374 |
-+ mp->valid |= KDBUS_ATTACH_PIDS; |
16375 |
-+} |
16376 |
-+ |
16377 |
-+static void kdbus_meta_proc_collect_tid_comm(struct kdbus_meta_proc *mp) |
16378 |
-+{ |
16379 |
-+ get_task_comm(mp->tid_comm, current); |
16380 |
-+ mp->valid |= KDBUS_ATTACH_TID_COMM; |
16381 |
-+} |
16382 |
-+ |
16383 |
-+static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp) |
16384 |
-+{ |
16385 |
-+ get_task_comm(mp->pid_comm, current->group_leader); |
16386 |
-+ mp->valid |= KDBUS_ATTACH_PID_COMM; |
16387 |
-+} |
16388 |
-+ |
16389 |
-+static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp) |
16390 |
-+{ |
16391 |
-+ struct file *exe_file; |
16392 |
-+ |
16393 |
-+ rcu_read_lock(); |
16394 |
-+ exe_file = rcu_dereference(current->mm->exe_file); |
16395 |
-+ if (exe_file) { |
16396 |
-+ mp->exe_path = exe_file->f_path; |
16397 |
-+ path_get(&mp->exe_path); |
16398 |
-+ get_fs_root(current->fs, &mp->root_path); |
16399 |
-+ mp->valid |= KDBUS_ATTACH_EXE; |
16400 |
-+ } |
16401 |
-+ rcu_read_unlock(); |
16402 |
-+} |
16403 |
-+ |
16404 |
-+static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp) |
16405 |
-+{ |
16406 |
-+ struct mm_struct *mm = current->mm; |
16407 |
-+ char *cmdline; |
16408 |
-+ |
16409 |
-+ if (!mm->arg_end) |
16410 |
-+ return 0; |
16411 |
-+ |
16412 |
-+ cmdline = strndup_user((const char __user *)mm->arg_start, |
16413 |
-+ mm->arg_end - mm->arg_start); |
16414 |
-+ if (IS_ERR(cmdline)) |
16415 |
-+ return PTR_ERR(cmdline); |
16416 |
-+ |
16417 |
-+ mp->cmdline = cmdline; |
16418 |
-+ mp->valid |= KDBUS_ATTACH_CMDLINE; |
16419 |
-+ |
16420 |
-+ return 0; |
16421 |
-+} |
16422 |
-+ |
16423 |
-+static int kdbus_meta_proc_collect_cgroup(struct kdbus_meta_proc *mp) |
16424 |
-+{ |
16425 |
-+#ifdef CONFIG_CGROUPS |
16426 |
-+ void *page; |
16427 |
-+ char *s; |
16428 |
-+ |
16429 |
-+ page = (void *)__get_free_page(GFP_TEMPORARY); |
16430 |
-+ if (!page) |
16431 |
-+ return -ENOMEM; |
16432 |
-+ |
16433 |
-+ s = task_cgroup_path(current, page, PAGE_SIZE); |
16434 |
-+ if (s) { |
16435 |
-+ mp->cgroup = kstrdup(s, GFP_KERNEL); |
16436 |
-+ if (!mp->cgroup) { |
16437 |
-+ free_page((unsigned long)page); |
16438 |
-+ return -ENOMEM; |
16439 |
-+ } |
16440 |
-+ } |
16441 |
-+ |
16442 |
-+ free_page((unsigned long)page); |
16443 |
-+ mp->valid |= KDBUS_ATTACH_CGROUP; |
16444 |
-+#endif |
16445 |
-+ |
16446 |
-+ return 0; |
16447 |
-+} |
16448 |
-+ |
16449 |
-+static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp) |
16450 |
-+{ |
16451 |
-+#ifdef CONFIG_SECURITY |
16452 |
-+ char *ctx = NULL; |
16453 |
-+ u32 sid, len; |
16454 |
-+ int ret; |
16455 |
-+ |
16456 |
-+ security_task_getsecid(current, &sid); |
16457 |
-+ ret = security_secid_to_secctx(sid, &ctx, &len); |
16458 |
-+ if (ret < 0) { |
16459 |
-+ /* |
16460 |
-+ * EOPNOTSUPP means no security module is active, |
16461 |
-+ * lets skip adding the seclabel then. This effectively |
16462 |
-+ * drops the SECLABEL item. |
16463 |
-+ */ |
16464 |
-+ return (ret == -EOPNOTSUPP) ? 0 : ret; |
16465 |
-+ } |
16466 |
-+ |
16467 |
-+ mp->seclabel = kstrdup(ctx, GFP_KERNEL); |
16468 |
-+ security_release_secctx(ctx, len); |
16469 |
-+ if (!mp->seclabel) |
16470 |
-+ return -ENOMEM; |
16471 |
-+ |
16472 |
-+ mp->valid |= KDBUS_ATTACH_SECLABEL; |
16473 |
-+#endif |
16474 |
-+ |
16475 |
-+ return 0; |
16476 |
-+} |
16477 |
-+ |
16478 |
-+static void kdbus_meta_proc_collect_audit(struct kdbus_meta_proc *mp) |
16479 |
-+{ |
16480 |
-+#ifdef CONFIG_AUDITSYSCALL |
16481 |
-+ mp->audit_loginuid = audit_get_loginuid(current); |
16482 |
-+ mp->audit_sessionid = audit_get_sessionid(current); |
16483 |
-+ mp->valid |= KDBUS_ATTACH_AUDIT; |
16484 |
-+#endif |
16485 |
-+} |
16486 |
-+ |
16487 |
-+/** |
16488 |
-+ * kdbus_meta_proc_collect() - Collect process metadata |
16489 |
-+ * @mp: Process metadata object |
16490 |
-+ * @what: Attach flags to collect |
16491 |
-+ * |
16492 |
-+ * This collects process metadata from current and saves it in @mp. |
16493 |
-+ * |
16494 |
-+ * Return: 0 on success, negative error code on failure. |
16495 |
-+ */ |
16496 |
-+int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what) |
16497 |
-+{ |
16498 |
-+ int ret; |
16499 |
-+ |
16500 |
-+ if (!mp || !(what & (KDBUS_ATTACH_CREDS | |
16501 |
-+ KDBUS_ATTACH_PIDS | |
16502 |
-+ KDBUS_ATTACH_AUXGROUPS | |
16503 |
-+ KDBUS_ATTACH_TID_COMM | |
16504 |
-+ KDBUS_ATTACH_PID_COMM | |
16505 |
-+ KDBUS_ATTACH_EXE | |
16506 |
-+ KDBUS_ATTACH_CMDLINE | |
16507 |
-+ KDBUS_ATTACH_CGROUP | |
16508 |
-+ KDBUS_ATTACH_CAPS | |
16509 |
-+ KDBUS_ATTACH_SECLABEL | |
16510 |
-+ KDBUS_ATTACH_AUDIT))) |
16511 |
-+ return 0; |
16512 |
-+ |
16513 |
-+ mutex_lock(&mp->lock); |
16514 |
-+ |
16515 |
-+ /* creds, auxgrps and caps share "struct cred" as context */ |
16516 |
-+ { |
16517 |
-+ const u64 m_cred = KDBUS_ATTACH_CREDS | |
16518 |
-+ KDBUS_ATTACH_AUXGROUPS | |
16519 |
-+ KDBUS_ATTACH_CAPS; |
16520 |
-+ |
16521 |
-+ if ((what & m_cred) && !(mp->collected & m_cred)) { |
16522 |
-+ mp->cred = get_current_cred(); |
16523 |
-+ mp->valid |= m_cred; |
16524 |
-+ mp->collected |= m_cred; |
16525 |
-+ } |
16526 |
-+ } |
16527 |
-+ |
16528 |
-+ if ((what & KDBUS_ATTACH_PIDS) && |
16529 |
-+ !(mp->collected & KDBUS_ATTACH_PIDS)) { |
16530 |
-+ kdbus_meta_proc_collect_pids(mp); |
16531 |
-+ mp->collected |= KDBUS_ATTACH_PIDS; |
16532 |
-+ } |
16533 |
-+ |
16534 |
-+ if ((what & KDBUS_ATTACH_TID_COMM) && |
16535 |
-+ !(mp->collected & KDBUS_ATTACH_TID_COMM)) { |
16536 |
-+ kdbus_meta_proc_collect_tid_comm(mp); |
16537 |
-+ mp->collected |= KDBUS_ATTACH_TID_COMM; |
16538 |
-+ } |
16539 |
-+ |
16540 |
-+ if ((what & KDBUS_ATTACH_PID_COMM) && |
16541 |
-+ !(mp->collected & KDBUS_ATTACH_PID_COMM)) { |
16542 |
-+ kdbus_meta_proc_collect_pid_comm(mp); |
16543 |
-+ mp->collected |= KDBUS_ATTACH_PID_COMM; |
16544 |
-+ } |
16545 |
-+ |
16546 |
-+ if ((what & KDBUS_ATTACH_EXE) && |
16547 |
-+ !(mp->collected & KDBUS_ATTACH_EXE)) { |
16548 |
-+ kdbus_meta_proc_collect_exe(mp); |
16549 |
-+ mp->collected |= KDBUS_ATTACH_EXE; |
16550 |
-+ } |
16551 |
-+ |
16552 |
-+ if ((what & KDBUS_ATTACH_CMDLINE) && |
16553 |
-+ !(mp->collected & KDBUS_ATTACH_CMDLINE)) { |
16554 |
-+ ret = kdbus_meta_proc_collect_cmdline(mp); |
16555 |
-+ if (ret < 0) |
16556 |
-+ goto exit_unlock; |
16557 |
-+ mp->collected |= KDBUS_ATTACH_CMDLINE; |
16558 |
-+ } |
16559 |
-+ |
16560 |
-+ if ((what & KDBUS_ATTACH_CGROUP) && |
16561 |
-+ !(mp->collected & KDBUS_ATTACH_CGROUP)) { |
16562 |
-+ ret = kdbus_meta_proc_collect_cgroup(mp); |
16563 |
-+ if (ret < 0) |
16564 |
-+ goto exit_unlock; |
16565 |
-+ mp->collected |= KDBUS_ATTACH_CGROUP; |
16566 |
-+ } |
16567 |
-+ |
16568 |
-+ if ((what & KDBUS_ATTACH_SECLABEL) && |
16569 |
-+ !(mp->collected & KDBUS_ATTACH_SECLABEL)) { |
16570 |
-+ ret = kdbus_meta_proc_collect_seclabel(mp); |
16571 |
-+ if (ret < 0) |
16572 |
-+ goto exit_unlock; |
16573 |
-+ mp->collected |= KDBUS_ATTACH_SECLABEL; |
16574 |
-+ } |
16575 |
-+ |
16576 |
-+ if ((what & KDBUS_ATTACH_AUDIT) && |
16577 |
-+ !(mp->collected & KDBUS_ATTACH_AUDIT)) { |
16578 |
-+ kdbus_meta_proc_collect_audit(mp); |
16579 |
-+ mp->collected |= KDBUS_ATTACH_AUDIT; |
16580 |
-+ } |
16581 |
-+ |
16582 |
-+ ret = 0; |
16583 |
-+ |
16584 |
-+exit_unlock: |
16585 |
-+ mutex_unlock(&mp->lock); |
16586 |
-+ return ret; |
16587 |
-+} |
16588 |
-+ |
16589 |
-+/** |
16590 |
-+ * kdbus_meta_fake_new() - Create fake metadata object |
16591 |
-+ * |
16592 |
-+ * Return: Pointer to new object on success, ERR_PTR on failure. |
16593 |
-+ */ |
16594 |
-+struct kdbus_meta_fake *kdbus_meta_fake_new(void) |
16595 |
-+{ |
16596 |
-+ struct kdbus_meta_fake *mf; |
16597 |
-+ |
16598 |
-+ mf = kzalloc(sizeof(*mf), GFP_KERNEL); |
16599 |
-+ if (!mf) |
16600 |
-+ return ERR_PTR(-ENOMEM); |
16601 |
-+ |
16602 |
-+ return mf; |
16603 |
-+} |
16604 |
-+ |
16605 |
-+/** |
16606 |
-+ * kdbus_meta_fake_free() - Free fake metadata object |
16607 |
-+ * @mf: Fake metadata object |
16608 |
-+ * |
16609 |
-+ * Return: NULL |
16610 |
-+ */ |
16611 |
-+struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf) |
16612 |
-+{ |
16613 |
-+ if (mf) { |
16614 |
-+ put_pid(mf->ppid); |
16615 |
-+ put_pid(mf->tgid); |
16616 |
-+ put_pid(mf->pid); |
16617 |
-+ kfree(mf->seclabel); |
16618 |
-+ kfree(mf); |
16619 |
-+ } |
16620 |
-+ |
16621 |
-+ return NULL; |
16622 |
-+} |
16623 |
-+ |
16624 |
-+/** |
16625 |
-+ * kdbus_meta_fake_collect() - Fill fake metadata from faked credentials |
16626 |
-+ * @mf: Fake metadata object |
16627 |
-+ * @creds: Creds to set, may be %NULL |
16628 |
-+ * @pids: PIDs to set, may be %NULL |
16629 |
-+ * @seclabel: Seclabel to set, may be %NULL |
16630 |
-+ * |
16631 |
-+ * This function takes information stored in @creds, @pids and @seclabel and |
16632 |
-+ * resolves them to kernel-representations, if possible. This call uses the |
16633 |
-+ * current task's namespaces to resolve the given information. |
16634 |
-+ * |
16635 |
-+ * Return: 0 on success, negative error code on failure. |
16636 |
-+ */ |
16637 |
-+int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf, |
16638 |
-+ const struct kdbus_creds *creds, |
16639 |
-+ const struct kdbus_pids *pids, |
16640 |
-+ const char *seclabel) |
16641 |
-+{ |
16642 |
-+ if (mf->valid) |
16643 |
-+ return -EALREADY; |
16644 |
-+ |
16645 |
-+ if (creds) { |
16646 |
-+ struct user_namespace *ns = current_user_ns(); |
16647 |
-+ |
16648 |
-+ mf->uid = make_kuid(ns, creds->uid); |
16649 |
-+ mf->euid = make_kuid(ns, creds->euid); |
16650 |
-+ mf->suid = make_kuid(ns, creds->suid); |
16651 |
-+ mf->fsuid = make_kuid(ns, creds->fsuid); |
16652 |
-+ |
16653 |
-+ mf->gid = make_kgid(ns, creds->gid); |
16654 |
-+ mf->egid = make_kgid(ns, creds->egid); |
16655 |
-+ mf->sgid = make_kgid(ns, creds->sgid); |
16656 |
-+ mf->fsgid = make_kgid(ns, creds->fsgid); |
16657 |
-+ |
16658 |
-+ if ((creds->uid != (uid_t)-1 && !uid_valid(mf->uid)) || |
16659 |
-+ (creds->euid != (uid_t)-1 && !uid_valid(mf->euid)) || |
16660 |
-+ (creds->suid != (uid_t)-1 && !uid_valid(mf->suid)) || |
16661 |
-+ (creds->fsuid != (uid_t)-1 && !uid_valid(mf->fsuid)) || |
16662 |
-+ (creds->gid != (gid_t)-1 && !gid_valid(mf->gid)) || |
16663 |
-+ (creds->egid != (gid_t)-1 && !gid_valid(mf->egid)) || |
16664 |
-+ (creds->sgid != (gid_t)-1 && !gid_valid(mf->sgid)) || |
16665 |
-+ (creds->fsgid != (gid_t)-1 && !gid_valid(mf->fsgid))) |
16666 |
-+ return -EINVAL; |
16667 |
-+ |
16668 |
-+ mf->valid |= KDBUS_ATTACH_CREDS; |
16669 |
-+ } |
16670 |
-+ |
16671 |
-+ if (pids) { |
16672 |
-+ mf->pid = get_pid(find_vpid(pids->tid)); |
16673 |
-+ mf->tgid = get_pid(find_vpid(pids->pid)); |
16674 |
-+ mf->ppid = get_pid(find_vpid(pids->ppid)); |
16675 |
-+ |
16676 |
-+ if ((pids->tid != 0 && !mf->pid) || |
16677 |
-+ (pids->pid != 0 && !mf->tgid) || |
16678 |
-+ (pids->ppid != 0 && !mf->ppid)) { |
16679 |
-+ put_pid(mf->pid); |
16680 |
-+ put_pid(mf->tgid); |
16681 |
-+ put_pid(mf->ppid); |
16682 |
-+ mf->pid = NULL; |
16683 |
-+ mf->tgid = NULL; |
16684 |
-+ mf->ppid = NULL; |
16685 |
-+ return -EINVAL; |
16686 |
-+ } |
16687 |
-+ |
16688 |
-+ mf->valid |= KDBUS_ATTACH_PIDS; |
16689 |
-+ } |
16690 |
-+ |
16691 |
-+ if (seclabel) { |
16692 |
-+ mf->seclabel = kstrdup(seclabel, GFP_KERNEL); |
16693 |
-+ if (!mf->seclabel) |
16694 |
-+ return -ENOMEM; |
16695 |
-+ |
16696 |
-+ mf->valid |= KDBUS_ATTACH_SECLABEL; |
16697 |
-+ } |
16698 |
-+ |
16699 |
-+ return 0; |
16700 |
-+} |
16701 |
-+ |
16702 |
-+/** |
16703 |
-+ * kdbus_meta_conn_new() - Create connection metadata object |
16704 |
-+ * |
16705 |
-+ * Return: Pointer to new object on success, ERR_PTR on failure. |
16706 |
-+ */ |
16707 |
-+struct kdbus_meta_conn *kdbus_meta_conn_new(void) |
16708 |
-+{ |
16709 |
-+ struct kdbus_meta_conn *mc; |
16710 |
-+ |
16711 |
-+ mc = kzalloc(sizeof(*mc), GFP_KERNEL); |
16712 |
-+ if (!mc) |
16713 |
-+ return ERR_PTR(-ENOMEM); |
16714 |
-+ |
16715 |
-+ kref_init(&mc->kref); |
16716 |
-+ mutex_init(&mc->lock); |
16717 |
-+ |
16718 |
-+ return mc; |
16719 |
-+} |
16720 |
-+ |
16721 |
-+static void kdbus_meta_conn_free(struct kref *kref) |
16722 |
-+{ |
16723 |
-+ struct kdbus_meta_conn *mc = |
16724 |
-+ container_of(kref, struct kdbus_meta_conn, kref); |
16725 |
-+ |
16726 |
-+ kfree(mc->conn_description); |
16727 |
-+ kfree(mc->owned_names_items); |
16728 |
-+ kfree(mc); |
16729 |
-+} |
16730 |
-+ |
16731 |
-+/** |
16732 |
-+ * kdbus_meta_conn_ref() - Gain reference |
16733 |
-+ * @mc: Connection metadata object |
16734 |
-+ */ |
16735 |
-+struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc) |
16736 |
-+{ |
16737 |
-+ if (mc) |
16738 |
-+ kref_get(&mc->kref); |
16739 |
-+ return mc; |
16740 |
-+} |
16741 |
-+ |
16742 |
-+/** |
16743 |
-+ * kdbus_meta_conn_unref() - Drop reference |
16744 |
-+ * @mc: Connection metadata object |
16745 |
-+ */ |
16746 |
-+struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc) |
16747 |
-+{ |
16748 |
-+ if (mc) |
16749 |
-+ kref_put(&mc->kref, kdbus_meta_conn_free); |
16750 |
-+ return NULL; |
16751 |
-+} |
16752 |
-+ |
16753 |
-+static void kdbus_meta_conn_collect_timestamp(struct kdbus_meta_conn *mc, |
16754 |
-+ u64 msg_seqnum) |
16755 |
-+{ |
16756 |
-+ mc->ts.monotonic_ns = ktime_get_ns(); |
16757 |
-+ mc->ts.realtime_ns = ktime_get_real_ns(); |
16758 |
-+ |
16759 |
-+ if (msg_seqnum) |
16760 |
-+ mc->ts.seqnum = msg_seqnum; |
16761 |
-+ |
16762 |
-+ mc->valid |= KDBUS_ATTACH_TIMESTAMP; |
16763 |
-+} |
16764 |
-+ |
16765 |
-+static int kdbus_meta_conn_collect_names(struct kdbus_meta_conn *mc, |
16766 |
-+ struct kdbus_conn *conn) |
16767 |
-+{ |
16768 |
-+ const struct kdbus_name_owner *owner; |
16769 |
-+ struct kdbus_item *item; |
16770 |
-+ size_t slen, size; |
16771 |
-+ |
16772 |
-+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock); |
16773 |
-+ |
16774 |
-+ size = 0; |
16775 |
-+ /* open-code length calculation to avoid final padding */ |
16776 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) |
16777 |
-+ if (!(owner->flags & KDBUS_NAME_IN_QUEUE)) |
16778 |
-+ size = KDBUS_ALIGN8(size) + KDBUS_ITEM_HEADER_SIZE + |
16779 |
-+ sizeof(struct kdbus_name) + |
16780 |
-+ strlen(owner->name->name) + 1; |
16781 |
-+ |
16782 |
-+ if (!size) |
16783 |
-+ return 0; |
16784 |
-+ |
16785 |
-+ /* make sure we include zeroed padding for convenience helpers */ |
16786 |
-+ item = kmalloc(KDBUS_ALIGN8(size), GFP_KERNEL); |
16787 |
-+ if (!item) |
16788 |
-+ return -ENOMEM; |
16789 |
-+ |
16790 |
-+ mc->owned_names_items = item; |
16791 |
-+ mc->owned_names_size = size; |
16792 |
-+ |
16793 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) { |
16794 |
-+ if (owner->flags & KDBUS_NAME_IN_QUEUE) |
16795 |
-+ continue; |
16796 |
-+ |
16797 |
-+ slen = strlen(owner->name->name) + 1; |
16798 |
-+ kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL, |
16799 |
-+ sizeof(struct kdbus_name) + slen); |
16800 |
-+ item->name.flags = owner->flags; |
16801 |
-+ memcpy(item->name.name, owner->name->name, slen); |
16802 |
-+ item = KDBUS_ITEM_NEXT(item); |
16803 |
-+ } |
16804 |
-+ |
16805 |
-+ /* sanity check: the buffer should be completely written now */ |
16806 |
-+ WARN_ON((u8 *)item != |
16807 |
-+ (u8 *)mc->owned_names_items + KDBUS_ALIGN8(size)); |
16808 |
-+ |
16809 |
-+ mc->valid |= KDBUS_ATTACH_NAMES; |
16810 |
-+ return 0; |
16811 |
-+} |
16812 |
-+ |
16813 |
-+static int kdbus_meta_conn_collect_description(struct kdbus_meta_conn *mc, |
16814 |
-+ struct kdbus_conn *conn) |
16815 |
-+{ |
16816 |
-+ if (!conn->description) |
16817 |
-+ return 0; |
16818 |
-+ |
16819 |
-+ mc->conn_description = kstrdup(conn->description, GFP_KERNEL); |
16820 |
-+ if (!mc->conn_description) |
16821 |
-+ return -ENOMEM; |
16822 |
-+ |
16823 |
-+ mc->valid |= KDBUS_ATTACH_CONN_DESCRIPTION; |
16824 |
-+ return 0; |
16825 |
-+} |
16826 |
-+ |
16827 |
-+/** |
16828 |
-+ * kdbus_meta_conn_collect() - Collect connection metadata |
16829 |
-+ * @mc: Message metadata object |
16830 |
-+ * @conn: Connection to collect data from |
16831 |
-+ * @msg_seqnum: Sequence number of the message to send |
16832 |
-+ * @what: Attach flags to collect |
16833 |
-+ * |
16834 |
-+ * This collects connection metadata from @msg_seqnum and @conn and saves it |
16835 |
-+ * in @mc. |
16836 |
-+ * |
16837 |
-+ * If KDBUS_ATTACH_NAMES is set in @what and @conn is non-NULL, the caller must |
16838 |
-+ * hold the name-registry read-lock of conn->ep->bus->registry. |
16839 |
-+ * |
16840 |
-+ * Return: 0 on success, negative error code on failure. |
16841 |
-+ */ |
16842 |
-+int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, |
16843 |
-+ struct kdbus_conn *conn, |
16844 |
-+ u64 msg_seqnum, u64 what) |
16845 |
-+{ |
16846 |
-+ int ret; |
16847 |
-+ |
16848 |
-+ if (!mc || !(what & (KDBUS_ATTACH_TIMESTAMP | |
16849 |
-+ KDBUS_ATTACH_NAMES | |
16850 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION))) |
16851 |
-+ return 0; |
16852 |
-+ |
16853 |
-+ mutex_lock(&mc->lock); |
16854 |
-+ |
16855 |
-+ if (msg_seqnum && (what & KDBUS_ATTACH_TIMESTAMP) && |
16856 |
-+ !(mc->collected & KDBUS_ATTACH_TIMESTAMP)) { |
16857 |
-+ kdbus_meta_conn_collect_timestamp(mc, msg_seqnum); |
16858 |
-+ mc->collected |= KDBUS_ATTACH_TIMESTAMP; |
16859 |
-+ } |
16860 |
-+ |
16861 |
-+ if (conn && (what & KDBUS_ATTACH_NAMES) && |
16862 |
-+ !(mc->collected & KDBUS_ATTACH_NAMES)) { |
16863 |
-+ ret = kdbus_meta_conn_collect_names(mc, conn); |
16864 |
-+ if (ret < 0) |
16865 |
-+ goto exit_unlock; |
16866 |
-+ mc->collected |= KDBUS_ATTACH_NAMES; |
16867 |
-+ } |
16868 |
-+ |
16869 |
-+ if (conn && (what & KDBUS_ATTACH_CONN_DESCRIPTION) && |
16870 |
-+ !(mc->collected & KDBUS_ATTACH_CONN_DESCRIPTION)) { |
16871 |
-+ ret = kdbus_meta_conn_collect_description(mc, conn); |
16872 |
-+ if (ret < 0) |
16873 |
-+ goto exit_unlock; |
16874 |
-+ mc->collected |= KDBUS_ATTACH_CONN_DESCRIPTION; |
16875 |
-+ } |
16876 |
-+ |
16877 |
-+ ret = 0; |
16878 |
-+ |
16879 |
-+exit_unlock: |
16880 |
-+ mutex_unlock(&mc->lock); |
16881 |
-+ return ret; |
16882 |
-+} |
16883 |
-+ |
16884 |
-+static void kdbus_meta_export_caps(struct kdbus_meta_caps *out, |
16885 |
-+ const struct kdbus_meta_proc *mp, |
16886 |
-+ struct user_namespace *user_ns) |
16887 |
-+{ |
16888 |
-+ struct user_namespace *iter; |
16889 |
-+ const struct cred *cred = mp->cred; |
16890 |
-+ bool parent = false, owner = false; |
16891 |
-+ int i; |
16892 |
-+ |
16893 |
-+ /* |
16894 |
-+ * This translates the effective capabilities of 'cred' into the given |
16895 |
-+ * user-namespace. If the given user-namespace is a child-namespace of |
16896 |
-+ * the user-namespace of 'cred', the mask can be copied verbatim. If |
16897 |
-+ * not, the mask is cleared. |
16898 |
-+ * There's one exception: If 'cred' is the owner of any user-namespace |
16899 |
-+ * in the path between the given user-namespace and the user-namespace |
16900 |
-+ * of 'cred', then it has all effective capabilities set. This means, |
16901 |
-+ * the user who created a user-namespace always has all effective |
16902 |
-+ * capabilities in any child namespaces. Note that this is based on the |
16903 |
-+ * uid of the namespace creator, not the task hierarchy. |
16904 |
-+ */ |
16905 |
-+ for (iter = user_ns; iter; iter = iter->parent) { |
16906 |
-+ if (iter == cred->user_ns) { |
16907 |
-+ parent = true; |
16908 |
-+ break; |
16909 |
-+ } |
16910 |
-+ |
16911 |
-+ if (iter == &init_user_ns) |
16912 |
-+ break; |
16913 |
-+ |
16914 |
-+ if ((iter->parent == cred->user_ns) && |
16915 |
-+ uid_eq(iter->owner, cred->euid)) { |
16916 |
-+ owner = true; |
16917 |
-+ break; |
16918 |
-+ } |
16919 |
-+ } |
16920 |
-+ |
16921 |
-+ out->last_cap = CAP_LAST_CAP; |
16922 |
-+ |
16923 |
-+ CAP_FOR_EACH_U32(i) { |
16924 |
-+ if (parent) { |
16925 |
-+ out->set[0].caps[i] = cred->cap_inheritable.cap[i]; |
16926 |
-+ out->set[1].caps[i] = cred->cap_permitted.cap[i]; |
16927 |
-+ out->set[2].caps[i] = cred->cap_effective.cap[i]; |
16928 |
-+ out->set[3].caps[i] = cred->cap_bset.cap[i]; |
16929 |
-+ } else if (owner) { |
16930 |
-+ out->set[0].caps[i] = 0U; |
16931 |
-+ out->set[1].caps[i] = ~0U; |
16932 |
-+ out->set[2].caps[i] = ~0U; |
16933 |
-+ out->set[3].caps[i] = ~0U; |
16934 |
-+ } else { |
16935 |
-+ out->set[0].caps[i] = 0U; |
16936 |
-+ out->set[1].caps[i] = 0U; |
16937 |
-+ out->set[2].caps[i] = 0U; |
16938 |
-+ out->set[3].caps[i] = 0U; |
16939 |
-+ } |
16940 |
-+ } |
16941 |
-+ |
16942 |
-+ /* clear unused bits */ |
16943 |
-+ for (i = 0; i < 4; i++) |
16944 |
-+ out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &= |
16945 |
-+ CAP_LAST_U32_VALID_MASK; |
16946 |
-+} |
16947 |
-+ |
16948 |
-+/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */ |
16949 |
-+static uid_t kdbus_from_kuid_keep(struct user_namespace *ns, kuid_t uid) |
16950 |
-+{ |
16951 |
-+ return uid_valid(uid) ? from_kuid_munged(ns, uid) : ((uid_t)-1); |
16952 |
-+} |
16953 |
-+ |
16954 |
-+/* This is equivalent to from_kgid_munged(), but maps INVALID_GID to itself */ |
16955 |
-+static gid_t kdbus_from_kgid_keep(struct user_namespace *ns, kgid_t gid) |
16956 |
-+{ |
16957 |
-+ return gid_valid(gid) ? from_kgid_munged(ns, gid) : ((gid_t)-1); |
16958 |
-+} |
16959 |
-+ |
16960 |
-+struct kdbus_meta_staging { |
16961 |
-+ const struct kdbus_meta_proc *mp; |
16962 |
-+ const struct kdbus_meta_fake *mf; |
16963 |
-+ const struct kdbus_meta_conn *mc; |
16964 |
-+ const struct kdbus_conn *conn; |
16965 |
-+ u64 mask; |
16966 |
-+ |
16967 |
-+ void *exe; |
16968 |
-+ const char *exe_path; |
16969 |
-+}; |
16970 |
-+ |
16971 |
-+static size_t kdbus_meta_measure(struct kdbus_meta_staging *staging) |
16972 |
-+{ |
16973 |
-+ const struct kdbus_meta_proc *mp = staging->mp; |
16974 |
-+ const struct kdbus_meta_fake *mf = staging->mf; |
16975 |
-+ const struct kdbus_meta_conn *mc = staging->mc; |
16976 |
-+ const u64 mask = staging->mask; |
16977 |
-+ size_t size = 0; |
16978 |
-+ |
16979 |
-+ /* process metadata */ |
16980 |
-+ |
16981 |
-+ if (mf && (mask & KDBUS_ATTACH_CREDS)) |
16982 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds)); |
16983 |
-+ else if (mp && (mask & KDBUS_ATTACH_CREDS)) |
16984 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds)); |
16985 |
-+ |
16986 |
-+ if (mf && (mask & KDBUS_ATTACH_PIDS)) |
16987 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids)); |
16988 |
-+ else if (mp && (mask & KDBUS_ATTACH_PIDS)) |
16989 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids)); |
16990 |
-+ |
16991 |
-+ if (mp && (mask & KDBUS_ATTACH_AUXGROUPS)) |
16992 |
-+ size += KDBUS_ITEM_SIZE(mp->cred->group_info->ngroups * |
16993 |
-+ sizeof(u64)); |
16994 |
-+ |
16995 |
-+ if (mp && (mask & KDBUS_ATTACH_TID_COMM)) |
16996 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->tid_comm) + 1); |
16997 |
-+ |
16998 |
-+ if (mp && (mask & KDBUS_ATTACH_PID_COMM)) |
16999 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->pid_comm) + 1); |
17000 |
-+ |
17001 |
-+ if (staging->exe_path && (mask & KDBUS_ATTACH_EXE)) |
17002 |
-+ size += KDBUS_ITEM_SIZE(strlen(staging->exe_path) + 1); |
17003 |
-+ |
17004 |
-+ if (mp && (mask & KDBUS_ATTACH_CMDLINE)) |
17005 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->cmdline) + 1); |
17006 |
-+ |
17007 |
-+ if (mp && (mask & KDBUS_ATTACH_CGROUP)) |
17008 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1); |
17009 |
-+ |
17010 |
-+ if (mp && (mask & KDBUS_ATTACH_CAPS)) |
17011 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps)); |
17012 |
-+ |
17013 |
-+ if (mf && (mask & KDBUS_ATTACH_SECLABEL)) |
17014 |
-+ size += KDBUS_ITEM_SIZE(strlen(mf->seclabel) + 1); |
17015 |
-+ else if (mp && (mask & KDBUS_ATTACH_SECLABEL)) |
17016 |
-+ size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1); |
17017 |
-+ |
17018 |
-+ if (mp && (mask & KDBUS_ATTACH_AUDIT)) |
17019 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit)); |
17020 |
-+ |
17021 |
-+ /* connection metadata */ |
17022 |
-+ |
17023 |
-+ if (mc && (mask & KDBUS_ATTACH_NAMES)) |
17024 |
-+ size += KDBUS_ALIGN8(mc->owned_names_size); |
17025 |
-+ |
17026 |
-+ if (mc && (mask & KDBUS_ATTACH_CONN_DESCRIPTION)) |
17027 |
-+ size += KDBUS_ITEM_SIZE(strlen(mc->conn_description) + 1); |
17028 |
-+ |
17029 |
-+ if (mc && (mask & KDBUS_ATTACH_TIMESTAMP)) |
17030 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_timestamp)); |
17031 |
-+ |
17032 |
-+ return size; |
17033 |
-+} |
17034 |
-+ |
17035 |
-+static struct kdbus_item *kdbus_write_head(struct kdbus_item **iter, |
17036 |
-+ u64 type, u64 size) |
17037 |
-+{ |
17038 |
-+ struct kdbus_item *item = *iter; |
17039 |
-+ size_t padding; |
17040 |
-+ |
17041 |
-+ item->type = type; |
17042 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + size; |
17043 |
-+ |
17044 |
-+ /* clear padding */ |
17045 |
-+ padding = KDBUS_ALIGN8(item->size) - item->size; |
17046 |
-+ if (padding) |
17047 |
-+ memset(item->data + size, 0, padding); |
17048 |
-+ |
17049 |
-+ *iter = KDBUS_ITEM_NEXT(item); |
17050 |
-+ return item; |
17051 |
-+} |
17052 |
-+ |
17053 |
-+static struct kdbus_item *kdbus_write_full(struct kdbus_item **iter, |
17054 |
-+ u64 type, u64 size, const void *data) |
17055 |
-+{ |
17056 |
-+ struct kdbus_item *item; |
17057 |
-+ |
17058 |
-+ item = kdbus_write_head(iter, type, size); |
17059 |
-+ memcpy(item->data, data, size); |
17060 |
-+ return item; |
17061 |
-+} |
17062 |
-+ |
17063 |
-+static size_t kdbus_meta_write(struct kdbus_meta_staging *staging, void *mem, |
17064 |
-+ size_t size) |
17065 |
-+{ |
17066 |
-+ struct user_namespace *user_ns = staging->conn->cred->user_ns; |
17067 |
-+ struct pid_namespace *pid_ns = ns_of_pid(staging->conn->pid); |
17068 |
-+ struct kdbus_item *item = NULL, *items = mem; |
17069 |
-+ u8 *end, *owned_names_end = NULL; |
17070 |
-+ |
17071 |
-+ /* process metadata */ |
17072 |
-+ |
17073 |
-+ if (staging->mf && (staging->mask & KDBUS_ATTACH_CREDS)) { |
17074 |
-+ const struct kdbus_meta_fake *mf = staging->mf; |
17075 |
-+ |
17076 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_CREDS, |
17077 |
-+ sizeof(struct kdbus_creds)); |
17078 |
-+ item->creds = (struct kdbus_creds){ |
17079 |
-+ .uid = kdbus_from_kuid_keep(user_ns, mf->uid), |
17080 |
-+ .euid = kdbus_from_kuid_keep(user_ns, mf->euid), |
17081 |
-+ .suid = kdbus_from_kuid_keep(user_ns, mf->suid), |
17082 |
-+ .fsuid = kdbus_from_kuid_keep(user_ns, mf->fsuid), |
17083 |
-+ .gid = kdbus_from_kgid_keep(user_ns, mf->gid), |
17084 |
-+ .egid = kdbus_from_kgid_keep(user_ns, mf->egid), |
17085 |
-+ .sgid = kdbus_from_kgid_keep(user_ns, mf->sgid), |
17086 |
-+ .fsgid = kdbus_from_kgid_keep(user_ns, mf->fsgid), |
17087 |
-+ }; |
17088 |
-+ } else if (staging->mp && (staging->mask & KDBUS_ATTACH_CREDS)) { |
17089 |
-+ const struct cred *c = staging->mp->cred; |
17090 |
-+ |
17091 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_CREDS, |
17092 |
-+ sizeof(struct kdbus_creds)); |
17093 |
-+ item->creds = (struct kdbus_creds){ |
17094 |
-+ .uid = kdbus_from_kuid_keep(user_ns, c->uid), |
17095 |
-+ .euid = kdbus_from_kuid_keep(user_ns, c->euid), |
17096 |
-+ .suid = kdbus_from_kuid_keep(user_ns, c->suid), |
17097 |
-+ .fsuid = kdbus_from_kuid_keep(user_ns, c->fsuid), |
17098 |
-+ .gid = kdbus_from_kgid_keep(user_ns, c->gid), |
17099 |
-+ .egid = kdbus_from_kgid_keep(user_ns, c->egid), |
17100 |
-+ .sgid = kdbus_from_kgid_keep(user_ns, c->sgid), |
17101 |
-+ .fsgid = kdbus_from_kgid_keep(user_ns, c->fsgid), |
17102 |
-+ }; |
17103 |
-+ } |
17104 |
-+ |
17105 |
-+ if (staging->mf && (staging->mask & KDBUS_ATTACH_PIDS)) { |
17106 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_PIDS, |
17107 |
-+ sizeof(struct kdbus_pids)); |
17108 |
-+ item->pids = (struct kdbus_pids){ |
17109 |
-+ .pid = pid_nr_ns(staging->mf->tgid, pid_ns), |
17110 |
-+ .tid = pid_nr_ns(staging->mf->pid, pid_ns), |
17111 |
-+ .ppid = pid_nr_ns(staging->mf->ppid, pid_ns), |
17112 |
-+ }; |
17113 |
-+ } else if (staging->mp && (staging->mask & KDBUS_ATTACH_PIDS)) { |
17114 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_PIDS, |
17115 |
-+ sizeof(struct kdbus_pids)); |
17116 |
-+ item->pids = (struct kdbus_pids){ |
17117 |
-+ .pid = pid_nr_ns(staging->mp->tgid, pid_ns), |
17118 |
-+ .tid = pid_nr_ns(staging->mp->pid, pid_ns), |
17119 |
-+ .ppid = pid_nr_ns(staging->mp->ppid, pid_ns), |
17120 |
-+ }; |
17121 |
-+ } |
17122 |
-+ |
17123 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_AUXGROUPS)) { |
17124 |
-+ const struct group_info *info = staging->mp->cred->group_info; |
17125 |
-+ size_t i; |
17126 |
-+ |
17127 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_AUXGROUPS, |
17128 |
-+ info->ngroups * sizeof(u64)); |
17129 |
-+ for (i = 0; i < info->ngroups; ++i) |
17130 |
-+ item->data64[i] = from_kgid_munged(user_ns, |
17131 |
-+ GROUP_AT(info, i)); |
17132 |
-+ } |
17133 |
-+ |
17134 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_TID_COMM)) |
17135 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_TID_COMM, |
17136 |
-+ strlen(staging->mp->tid_comm) + 1, |
17137 |
-+ staging->mp->tid_comm); |
17138 |
-+ |
17139 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_PID_COMM)) |
17140 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_PID_COMM, |
17141 |
-+ strlen(staging->mp->pid_comm) + 1, |
17142 |
-+ staging->mp->pid_comm); |
17143 |
-+ |
17144 |
-+ if (staging->exe_path && (staging->mask & KDBUS_ATTACH_EXE)) |
17145 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_EXE, |
17146 |
-+ strlen(staging->exe_path) + 1, |
17147 |
-+ staging->exe_path); |
17148 |
-+ |
17149 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_CMDLINE)) |
17150 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_CMDLINE, |
17151 |
-+ strlen(staging->mp->cmdline) + 1, |
17152 |
-+ staging->mp->cmdline); |
17153 |
-+ |
17154 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_CGROUP)) |
17155 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_CGROUP, |
17156 |
-+ strlen(staging->mp->cgroup) + 1, |
17157 |
-+ staging->mp->cgroup); |
17158 |
-+ |
17159 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_CAPS)) { |
17160 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_CAPS, |
17161 |
-+ sizeof(struct kdbus_meta_caps)); |
17162 |
-+ kdbus_meta_export_caps((void*)&item->caps, staging->mp, |
17163 |
-+ user_ns); |
17164 |
-+ } |
17165 |
-+ |
17166 |
-+ if (staging->mf && (staging->mask & KDBUS_ATTACH_SECLABEL)) |
17167 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL, |
17168 |
-+ strlen(staging->mf->seclabel) + 1, |
17169 |
-+ staging->mf->seclabel); |
17170 |
-+ else if (staging->mp && (staging->mask & KDBUS_ATTACH_SECLABEL)) |
17171 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL, |
17172 |
-+ strlen(staging->mp->seclabel) + 1, |
17173 |
-+ staging->mp->seclabel); |
17174 |
-+ |
17175 |
-+ if (staging->mp && (staging->mask & KDBUS_ATTACH_AUDIT)) { |
17176 |
-+ item = kdbus_write_head(&items, KDBUS_ITEM_AUDIT, |
17177 |
-+ sizeof(struct kdbus_audit)); |
17178 |
-+ item->audit = (struct kdbus_audit){ |
17179 |
-+ .loginuid = from_kuid(user_ns, |
17180 |
-+ staging->mp->audit_loginuid), |
17181 |
-+ .sessionid = staging->mp->audit_sessionid, |
17182 |
-+ }; |
17183 |
-+ } |
17184 |
-+ |
17185 |
-+ /* connection metadata */ |
17186 |
-+ |
17187 |
-+ if (staging->mc && (staging->mask & KDBUS_ATTACH_NAMES)) { |
17188 |
-+ memcpy(items, staging->mc->owned_names_items, |
17189 |
-+ KDBUS_ALIGN8(staging->mc->owned_names_size)); |
17190 |
-+ owned_names_end = (u8 *)items + staging->mc->owned_names_size; |
17191 |
-+ items = (void *)KDBUS_ALIGN8((unsigned long)owned_names_end); |
17192 |
-+ } |
17193 |
-+ |
17194 |
-+ if (staging->mc && (staging->mask & KDBUS_ATTACH_CONN_DESCRIPTION)) |
17195 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_CONN_DESCRIPTION, |
17196 |
-+ strlen(staging->mc->conn_description) + 1, |
17197 |
-+ staging->mc->conn_description); |
17198 |
-+ |
17199 |
-+ if (staging->mc && (staging->mask & KDBUS_ATTACH_TIMESTAMP)) |
17200 |
-+ item = kdbus_write_full(&items, KDBUS_ITEM_TIMESTAMP, |
17201 |
-+ sizeof(staging->mc->ts), |
17202 |
-+ &staging->mc->ts); |
17203 |
-+ |
17204 |
-+ /* |
17205 |
-+ * Return real size (minus trailing padding). In case of 'owned_names' |
17206 |
-+ * we cannot deduce it from item->size, so treat it special. |
17207 |
-+ */ |
17208 |
-+ |
17209 |
-+ if (items == (void *)KDBUS_ALIGN8((unsigned long)owned_names_end)) |
17210 |
-+ end = owned_names_end; |
17211 |
-+ else if (item) |
17212 |
-+ end = (u8 *)item + item->size; |
17213 |
-+ else |
17214 |
-+ end = mem; |
17215 |
-+ |
17216 |
-+ WARN_ON((u8 *)items - (u8 *)mem != size); |
17217 |
-+ WARN_ON((void *)KDBUS_ALIGN8((unsigned long)end) != (void *)items); |
17218 |
-+ |
17219 |
-+ return end - (u8 *)mem; |
17220 |
-+} |
17221 |
-+ |
17222 |
-+int kdbus_meta_emit(struct kdbus_meta_proc *mp, |
17223 |
-+ struct kdbus_meta_fake *mf, |
17224 |
-+ struct kdbus_meta_conn *mc, |
17225 |
-+ struct kdbus_conn *conn, |
17226 |
-+ u64 mask, |
17227 |
-+ struct kdbus_item **out_items, |
17228 |
-+ size_t *out_size) |
17229 |
-+{ |
17230 |
-+ struct kdbus_meta_staging staging = {}; |
17231 |
-+ struct kdbus_item *items = NULL; |
17232 |
-+ size_t size = 0; |
17233 |
-+ int ret; |
17234 |
-+ |
17235 |
-+ if (WARN_ON(mf && mp)) |
17236 |
-+ mp = NULL; |
17237 |
-+ |
17238 |
-+ staging.mp = mp; |
17239 |
-+ staging.mf = mf; |
17240 |
-+ staging.mc = mc; |
17241 |
-+ staging.conn = conn; |
17242 |
-+ |
17243 |
-+ /* get mask of valid items */ |
17244 |
-+ if (mf) |
17245 |
-+ staging.mask |= mf->valid; |
17246 |
-+ if (mp) { |
17247 |
-+ mutex_lock(&mp->lock); |
17248 |
-+ staging.mask |= mp->valid; |
17249 |
-+ mutex_unlock(&mp->lock); |
17250 |
-+ } |
17251 |
-+ if (mc) { |
17252 |
-+ mutex_lock(&mc->lock); |
17253 |
-+ staging.mask |= mc->valid; |
17254 |
-+ mutex_unlock(&mc->lock); |
17255 |
-+ } |
17256 |
-+ |
17257 |
-+ staging.mask &= mask; |
17258 |
-+ |
17259 |
-+ if (!staging.mask) { /* bail out if nothing to do */ |
17260 |
-+ ret = 0; |
17261 |
-+ goto exit; |
17262 |
-+ } |
17263 |
-+ |
17264 |
-+ /* EXE is special as it needs a temporary page to assemble */ |
17265 |
-+ if (mp && (staging.mask & KDBUS_ATTACH_EXE)) { |
17266 |
-+ struct path p; |
17267 |
-+ |
17268 |
-+ /* |
17269 |
-+ * XXX: We need access to __d_path() so we can write the path |
17270 |
-+ * relative to conn->root_path. Once upstream, we need |
17271 |
-+ * EXPORT_SYMBOL(__d_path) or an equivalent of d_path() that |
17272 |
-+ * takes the root path directly. Until then, we drop this item |
17273 |
-+ * if the root-paths differ. |
17274 |
-+ */ |
17275 |
-+ |
17276 |
-+ get_fs_root(current->fs, &p); |
17277 |
-+ if (path_equal(&p, &conn->root_path)) { |
17278 |
-+ staging.exe = (void *)__get_free_page(GFP_TEMPORARY); |
17279 |
-+ if (!staging.exe) { |
17280 |
-+ path_put(&p); |
17281 |
-+ ret = -ENOMEM; |
17282 |
-+ goto exit; |
17283 |
-+ } |
17284 |
-+ |
17285 |
-+ staging.exe_path = d_path(&mp->exe_path, staging.exe, |
17286 |
-+ PAGE_SIZE); |
17287 |
-+ if (IS_ERR(staging.exe_path)) { |
17288 |
-+ path_put(&p); |
17289 |
-+ ret = PTR_ERR(staging.exe_path); |
17290 |
-+ goto exit; |
17291 |
-+ } |
17292 |
-+ } |
17293 |
-+ path_put(&p); |
17294 |
-+ } |
17295 |
-+ |
17296 |
-+ size = kdbus_meta_measure(&staging); |
17297 |
-+ if (!size) { /* bail out if nothing to do */ |
17298 |
-+ ret = 0; |
17299 |
-+ goto exit; |
17300 |
-+ } |
17301 |
-+ |
17302 |
-+ items = kmalloc(size, GFP_KERNEL); |
17303 |
-+ if (!items) { |
17304 |
-+ ret = -ENOMEM; |
17305 |
-+ goto exit; |
17306 |
-+ } |
17307 |
-+ |
17308 |
-+ size = kdbus_meta_write(&staging, items, size); |
17309 |
-+ if (!size) { |
17310 |
-+ kfree(items); |
17311 |
-+ items = NULL; |
17312 |
-+ } |
17313 |
-+ |
17314 |
-+ ret = 0; |
17315 |
-+ |
17316 |
-+exit: |
17317 |
-+ if (staging.exe) |
17318 |
-+ free_page((unsigned long)staging.exe); |
17319 |
-+ if (ret >= 0) { |
17320 |
-+ *out_items = items; |
17321 |
-+ *out_size = size; |
17322 |
-+ } |
17323 |
-+ return ret; |
17324 |
-+} |
17325 |
-+ |
17326 |
-+enum { |
17327 |
-+ KDBUS_META_PROC_NONE, |
17328 |
-+ KDBUS_META_PROC_NORMAL, |
17329 |
-+}; |
17330 |
-+ |
17331 |
-+/** |
17332 |
-+ * kdbus_proc_permission() - check /proc permissions on target pid |
17333 |
-+ * @pid_ns: namespace we operate in |
17334 |
-+ * @cred: credentials of requestor |
17335 |
-+ * @target: target process |
17336 |
-+ * |
17337 |
-+ * This checks whether a process with credentials @cred can access information |
17338 |
-+ * of @target in the namespace @pid_ns. This tries to follow /proc permissions, |
17339 |
-+ * but is slightly more restrictive. |
17340 |
-+ * |
17341 |
-+ * Return: The /proc access level (KDBUS_META_PROC_*) is returned. |
17342 |
-+ */ |
17343 |
-+static unsigned int kdbus_proc_permission(const struct pid_namespace *pid_ns, |
17344 |
-+ const struct cred *cred, |
17345 |
-+ struct pid *target) |
17346 |
-+{ |
17347 |
-+ if (pid_ns->hide_pid < 1) |
17348 |
-+ return KDBUS_META_PROC_NORMAL; |
17349 |
-+ |
17350 |
-+ /* XXX: we need groups_search() exported for aux-groups */ |
17351 |
-+ if (gid_eq(cred->egid, pid_ns->pid_gid)) |
17352 |
-+ return KDBUS_META_PROC_NORMAL; |
17353 |
-+ |
17354 |
-+ /* |
17355 |
-+ * XXX: If ptrace_may_access(PTRACE_MODE_READ) is granted, you can |
17356 |
-+ * overwrite hide_pid. However, ptrace_may_access() only supports |
17357 |
-+ * checking 'current', hence, we cannot use this here. But we |
17358 |
-+ * simply decide to not support this override, so no need to worry. |
17359 |
-+ */ |
17360 |
-+ |
17361 |
-+ return KDBUS_META_PROC_NONE; |
17362 |
-+} |
17363 |
-+ |
17364 |
-+/** |
17365 |
-+ * kdbus_meta_proc_mask() - calculate which metadata would be visible to |
17366 |
-+ * a connection via /proc |
17367 |
-+ * @prv_pid: pid of metadata provider |
17368 |
-+ * @req_pid: pid of metadata requestor |
17369 |
-+ * @req_cred: credentials of metadata reqeuestor |
17370 |
-+ * @wanted: metadata that is requested |
17371 |
-+ * |
17372 |
-+ * This checks which metadata items of @prv_pid can be read via /proc by the |
17373 |
-+ * requestor @req_pid. |
17374 |
-+ * |
17375 |
-+ * Return: Set of metadata flags the requestor can see (limited by @wanted). |
17376 |
-+ */ |
17377 |
-+static u64 kdbus_meta_proc_mask(struct pid *prv_pid, |
17378 |
-+ struct pid *req_pid, |
17379 |
-+ const struct cred *req_cred, |
17380 |
-+ u64 wanted) |
17381 |
-+{ |
17382 |
-+ struct pid_namespace *prv_ns, *req_ns; |
17383 |
-+ unsigned int proc; |
17384 |
-+ |
17385 |
-+ prv_ns = ns_of_pid(prv_pid); |
17386 |
-+ req_ns = ns_of_pid(req_pid); |
17387 |
-+ |
17388 |
-+ /* |
17389 |
-+ * If the sender is not visible in the receiver namespace, then the |
17390 |
-+ * receiver cannot access the sender via its own procfs. Hence, we do |
17391 |
-+ * not attach any additional metadata. |
17392 |
-+ */ |
17393 |
-+ if (!pid_nr_ns(prv_pid, req_ns)) |
17394 |
-+ return 0; |
17395 |
-+ |
17396 |
-+ /* |
17397 |
-+ * If the pid-namespace of the receiver has hide_pid set, it cannot see |
17398 |
-+ * any process but its own. We shortcut this /proc permission check if |
17399 |
-+ * provider and requestor are the same. If not, we perform rather |
17400 |
-+ * expensive /proc permission checks. |
17401 |
-+ */ |
17402 |
-+ if (prv_pid == req_pid) |
17403 |
-+ proc = KDBUS_META_PROC_NORMAL; |
17404 |
-+ else |
17405 |
-+ proc = kdbus_proc_permission(req_ns, req_cred, prv_pid); |
17406 |
-+ |
17407 |
-+ /* you need /proc access to read standard process attributes */ |
17408 |
-+ if (proc < KDBUS_META_PROC_NORMAL) |
17409 |
-+ wanted &= ~(KDBUS_ATTACH_TID_COMM | |
17410 |
-+ KDBUS_ATTACH_PID_COMM | |
17411 |
-+ KDBUS_ATTACH_SECLABEL | |
17412 |
-+ KDBUS_ATTACH_CMDLINE | |
17413 |
-+ KDBUS_ATTACH_CGROUP | |
17414 |
-+ KDBUS_ATTACH_AUDIT | |
17415 |
-+ KDBUS_ATTACH_CAPS | |
17416 |
-+ KDBUS_ATTACH_EXE); |
17417 |
-+ |
17418 |
-+ /* clear all non-/proc flags */ |
17419 |
-+ return wanted & (KDBUS_ATTACH_TID_COMM | |
17420 |
-+ KDBUS_ATTACH_PID_COMM | |
17421 |
-+ KDBUS_ATTACH_SECLABEL | |
17422 |
-+ KDBUS_ATTACH_CMDLINE | |
17423 |
-+ KDBUS_ATTACH_CGROUP | |
17424 |
-+ KDBUS_ATTACH_AUDIT | |
17425 |
-+ KDBUS_ATTACH_CAPS | |
17426 |
-+ KDBUS_ATTACH_EXE); |
17427 |
-+} |
17428 |
-+ |
17429 |
-+/** |
17430 |
-+ * kdbus_meta_get_mask() - calculate attach flags mask for metadata request |
17431 |
-+ * @prv_pid: pid of metadata provider |
17432 |
-+ * @prv_mask: mask of metadata the provide grants unchecked |
17433 |
-+ * @req_pid: pid of metadata requestor |
17434 |
-+ * @req_cred: credentials of metadata requestor |
17435 |
-+ * @req_mask: mask of metadata that is requested |
17436 |
-+ * |
17437 |
-+ * This calculates the metadata items that the requestor @req_pid can access |
17438 |
-+ * from the metadata provider @prv_pid. This permission check consists of |
17439 |
-+ * several different parts: |
17440 |
-+ * - Providers can grant metadata items unchecked. Regardless of their type, |
17441 |
-+ * they're always granted to the requestor. This mask is passed as @prv_mask. |
17442 |
-+ * - Basic items (credentials and connection metadata) are granted implicitly |
17443 |
-+ * to everyone. They're publicly available to any bus-user that can see the |
17444 |
-+ * provider. |
17445 |
-+ * - Process credentials that are not granted implicitly follow the same |
17446 |
-+ * permission checks as /proc. This means, we always assume a requestor |
17447 |
-+ * process has access to their *own* /proc mount, if they have access to |
17448 |
-+ * kdbusfs. |
17449 |
-+ * |
17450 |
-+ * Return: Mask of metadata that is granted. |
17451 |
-+ */ |
17452 |
-+static u64 kdbus_meta_get_mask(struct pid *prv_pid, u64 prv_mask, |
17453 |
-+ struct pid *req_pid, |
17454 |
-+ const struct cred *req_cred, u64 req_mask) |
17455 |
-+{ |
17456 |
-+ u64 missing, impl_mask, proc_mask = 0; |
17457 |
-+ |
17458 |
-+ /* |
17459 |
-+ * Connection metadata and basic unix process credentials are |
17460 |
-+ * transmitted implicitly, and cannot be suppressed. Both are required |
17461 |
-+ * to perform user-space policies on the receiver-side. Furthermore, |
17462 |
-+ * connection metadata is public state, anyway, and unix credentials |
17463 |
-+ * are needed for UDS-compatibility. We extend them slightly by |
17464 |
-+ * auxiliary groups and additional uids/gids/pids. |
17465 |
-+ */ |
17466 |
-+ impl_mask = /* connection metadata */ |
17467 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION | |
17468 |
-+ KDBUS_ATTACH_TIMESTAMP | |
17469 |
-+ KDBUS_ATTACH_NAMES | |
17470 |
-+ /* credentials and pids */ |
17471 |
-+ KDBUS_ATTACH_AUXGROUPS | |
17472 |
-+ KDBUS_ATTACH_CREDS | |
17473 |
-+ KDBUS_ATTACH_PIDS; |
17474 |
-+ |
17475 |
-+ /* |
17476 |
-+ * Calculate the set of metadata that is not granted implicitly nor by |
17477 |
-+ * the sender, but still requested by the receiver. If any are left, |
17478 |
-+ * perform rather expensive /proc access checks for them. |
17479 |
-+ */ |
17480 |
-+ missing = req_mask & ~((prv_mask | impl_mask) & req_mask); |
17481 |
-+ if (missing) |
17482 |
-+ proc_mask = kdbus_meta_proc_mask(prv_pid, req_pid, req_cred, |
17483 |
-+ missing); |
17484 |
-+ |
17485 |
-+ return (prv_mask | impl_mask | proc_mask) & req_mask; |
17486 |
-+} |
17487 |
-+ |
17488 |
-+/** |
17489 |
-+ */ |
17490 |
-+u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask) |
17491 |
-+{ |
17492 |
-+ return kdbus_meta_get_mask(conn->pid, |
17493 |
-+ atomic64_read(&conn->attach_flags_send), |
17494 |
-+ task_pid(current), |
17495 |
-+ current_cred(), |
17496 |
-+ mask); |
17497 |
-+} |
17498 |
-+ |
17499 |
-+/** |
17500 |
-+ */ |
17501 |
-+u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd, |
17502 |
-+ const struct kdbus_conn *rcv) |
17503 |
-+{ |
17504 |
-+ return kdbus_meta_get_mask(task_pid(current), |
17505 |
-+ atomic64_read(&snd->attach_flags_send), |
17506 |
-+ rcv->pid, |
17507 |
-+ rcv->cred, |
17508 |
-+ atomic64_read(&rcv->attach_flags_recv)); |
17509 |
-+} |
17510 |
-diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h |
17511 |
-new file mode 100644 |
17512 |
-index 0000000..dba7cc7 |
17513 |
---- /dev/null |
17514 |
-+++ b/ipc/kdbus/metadata.h |
17515 |
-@@ -0,0 +1,86 @@ |
17516 |
-+/* |
17517 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
17518 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
17519 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
17520 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
17521 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
17522 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
17523 |
-+ * |
17524 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
17525 |
-+ * the terms of the GNU Lesser General Public License as published by the |
17526 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
17527 |
-+ * your option) any later version. |
17528 |
-+ */ |
17529 |
-+ |
17530 |
-+#ifndef __KDBUS_METADATA_H |
17531 |
-+#define __KDBUS_METADATA_H |
17532 |
-+ |
17533 |
-+#include <linux/kernel.h> |
17534 |
-+ |
17535 |
-+struct kdbus_conn; |
17536 |
-+struct kdbus_pool_slice; |
17537 |
-+ |
17538 |
-+struct kdbus_meta_proc; |
17539 |
-+struct kdbus_meta_conn; |
17540 |
-+ |
17541 |
-+/** |
17542 |
-+ * struct kdbus_meta_fake - Fake metadata |
17543 |
-+ * @valid: Bitmask of collected and valid items |
17544 |
-+ * @uid: UID of process |
17545 |
-+ * @euid: EUID of process |
17546 |
-+ * @suid: SUID of process |
17547 |
-+ * @fsuid: FSUID of process |
17548 |
-+ * @gid: GID of process |
17549 |
-+ * @egid: EGID of process |
17550 |
-+ * @sgid: SGID of process |
17551 |
-+ * @fsgid: FSGID of process |
17552 |
-+ * @pid: PID of process |
17553 |
-+ * @tgid: TGID of process |
17554 |
-+ * @ppid: PPID of process |
17555 |
-+ * @seclabel: Seclabel |
17556 |
-+ */ |
17557 |
-+struct kdbus_meta_fake { |
17558 |
-+ u64 valid; |
17559 |
-+ |
17560 |
-+ /* KDBUS_ITEM_CREDS */ |
17561 |
-+ kuid_t uid, euid, suid, fsuid; |
17562 |
-+ kgid_t gid, egid, sgid, fsgid; |
17563 |
-+ |
17564 |
-+ /* KDBUS_ITEM_PIDS */ |
17565 |
-+ struct pid *pid, *tgid, *ppid; |
17566 |
-+ |
17567 |
-+ /* KDBUS_ITEM_SECLABEL */ |
17568 |
-+ char *seclabel; |
17569 |
-+}; |
17570 |
-+ |
17571 |
-+struct kdbus_meta_proc *kdbus_meta_proc_new(void); |
17572 |
-+struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp); |
17573 |
-+struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp); |
17574 |
-+int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what); |
17575 |
-+ |
17576 |
-+struct kdbus_meta_fake *kdbus_meta_fake_new(void); |
17577 |
-+struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf); |
17578 |
-+int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf, |
17579 |
-+ const struct kdbus_creds *creds, |
17580 |
-+ const struct kdbus_pids *pids, |
17581 |
-+ const char *seclabel); |
17582 |
-+ |
17583 |
-+struct kdbus_meta_conn *kdbus_meta_conn_new(void); |
17584 |
-+struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc); |
17585 |
-+struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc); |
17586 |
-+int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, |
17587 |
-+ struct kdbus_conn *conn, |
17588 |
-+ u64 msg_seqnum, u64 what); |
17589 |
-+ |
17590 |
-+int kdbus_meta_emit(struct kdbus_meta_proc *mp, |
17591 |
-+ struct kdbus_meta_fake *mf, |
17592 |
-+ struct kdbus_meta_conn *mc, |
17593 |
-+ struct kdbus_conn *conn, |
17594 |
-+ u64 mask, |
17595 |
-+ struct kdbus_item **out_items, |
17596 |
-+ size_t *out_size); |
17597 |
-+u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask); |
17598 |
-+u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd, |
17599 |
-+ const struct kdbus_conn *rcv); |
17600 |
-+ |
17601 |
-+#endif |
17602 |
-diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c |
17603 |
-new file mode 100644 |
17604 |
-index 0000000..bf44ca3 |
17605 |
---- /dev/null |
17606 |
-+++ b/ipc/kdbus/names.c |
17607 |
-@@ -0,0 +1,854 @@ |
17608 |
-+/* |
17609 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
17610 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
17611 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
17612 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
17613 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
17614 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
17615 |
-+ * |
17616 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
17617 |
-+ * the terms of the GNU Lesser General Public License as published by the |
17618 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
17619 |
-+ * your option) any later version. |
17620 |
-+ */ |
17621 |
-+ |
17622 |
-+#include <linux/ctype.h> |
17623 |
-+#include <linux/fs.h> |
17624 |
-+#include <linux/hash.h> |
17625 |
-+#include <linux/idr.h> |
17626 |
-+#include <linux/init.h> |
17627 |
-+#include <linux/module.h> |
17628 |
-+#include <linux/mutex.h> |
17629 |
-+#include <linux/rwsem.h> |
17630 |
-+#include <linux/sched.h> |
17631 |
-+#include <linux/slab.h> |
17632 |
-+#include <linux/uaccess.h> |
17633 |
-+#include <linux/uio.h> |
17634 |
-+ |
17635 |
-+#include "bus.h" |
17636 |
-+#include "connection.h" |
17637 |
-+#include "endpoint.h" |
17638 |
-+#include "handle.h" |
17639 |
-+#include "item.h" |
17640 |
-+#include "names.h" |
17641 |
-+#include "notify.h" |
17642 |
-+#include "policy.h" |
17643 |
-+ |
17644 |
-+#define KDBUS_NAME_SAVED_MASK (KDBUS_NAME_ALLOW_REPLACEMENT | \ |
17645 |
-+ KDBUS_NAME_QUEUE) |
17646 |
-+ |
17647 |
-+static bool kdbus_name_owner_is_used(struct kdbus_name_owner *owner) |
17648 |
-+{ |
17649 |
-+ return !list_empty(&owner->name_entry) || |
17650 |
-+ owner == owner->name->activator; |
17651 |
-+} |
17652 |
-+ |
17653 |
-+static struct kdbus_name_owner * |
17654 |
-+kdbus_name_owner_new(struct kdbus_conn *conn, struct kdbus_name_entry *name, |
17655 |
-+ u64 flags) |
17656 |
-+{ |
17657 |
-+ struct kdbus_name_owner *owner; |
17658 |
-+ |
17659 |
-+ kdbus_conn_assert_active(conn); |
17660 |
-+ |
17661 |
-+ if (conn->name_count >= KDBUS_CONN_MAX_NAMES) |
17662 |
-+ return ERR_PTR(-E2BIG); |
17663 |
-+ |
17664 |
-+ owner = kmalloc(sizeof(*owner), GFP_KERNEL); |
17665 |
-+ if (!owner) |
17666 |
-+ return ERR_PTR(-ENOMEM); |
17667 |
-+ |
17668 |
-+ owner->flags = flags & KDBUS_NAME_SAVED_MASK; |
17669 |
-+ owner->conn = conn; |
17670 |
-+ owner->name = name; |
17671 |
-+ list_add_tail(&owner->conn_entry, &conn->names_list); |
17672 |
-+ INIT_LIST_HEAD(&owner->name_entry); |
17673 |
-+ |
17674 |
-+ ++conn->name_count; |
17675 |
-+ return owner; |
17676 |
-+} |
17677 |
-+ |
17678 |
-+static void kdbus_name_owner_free(struct kdbus_name_owner *owner) |
17679 |
-+{ |
17680 |
-+ if (!owner) |
17681 |
-+ return; |
17682 |
-+ |
17683 |
-+ WARN_ON(kdbus_name_owner_is_used(owner)); |
17684 |
-+ --owner->conn->name_count; |
17685 |
-+ list_del(&owner->conn_entry); |
17686 |
-+ kfree(owner); |
17687 |
-+} |
17688 |
-+ |
17689 |
-+static struct kdbus_name_owner * |
17690 |
-+kdbus_name_owner_find(struct kdbus_name_entry *name, struct kdbus_conn *conn) |
17691 |
-+{ |
17692 |
-+ struct kdbus_name_owner *owner; |
17693 |
-+ |
17694 |
-+ /* |
17695 |
-+ * Use conn->names_list over name->queue to make sure boundaries of |
17696 |
-+ * this linear search are controlled by the connection itself. |
17697 |
-+ * Furthermore, this will find normal owners as well as activators |
17698 |
-+ * without any additional code. |
17699 |
-+ */ |
17700 |
-+ list_for_each_entry(owner, &conn->names_list, conn_entry) |
17701 |
-+ if (owner->name == name) |
17702 |
-+ return owner; |
17703 |
-+ |
17704 |
-+ return NULL; |
17705 |
-+} |
17706 |
-+ |
17707 |
-+static bool kdbus_name_entry_is_used(struct kdbus_name_entry *name) |
17708 |
-+{ |
17709 |
-+ return !list_empty(&name->queue) || name->activator; |
17710 |
-+} |
17711 |
-+ |
17712 |
-+static struct kdbus_name_owner * |
17713 |
-+kdbus_name_entry_first(struct kdbus_name_entry *name) |
17714 |
-+{ |
17715 |
-+ return list_first_entry_or_null(&name->queue, struct kdbus_name_owner, |
17716 |
-+ name_entry); |
17717 |
-+} |
17718 |
-+ |
17719 |
-+static struct kdbus_name_entry * |
17720 |
-+kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash, |
17721 |
-+ const char *name_str) |
17722 |
-+{ |
17723 |
-+ struct kdbus_name_entry *name; |
17724 |
-+ size_t namelen; |
17725 |
-+ |
17726 |
-+ lockdep_assert_held(&r->rwlock); |
17727 |
-+ |
17728 |
-+ namelen = strlen(name_str); |
17729 |
-+ |
17730 |
-+ name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL); |
17731 |
-+ if (!name) |
17732 |
-+ return ERR_PTR(-ENOMEM); |
17733 |
-+ |
17734 |
-+ name->name_id = ++r->name_seq_last; |
17735 |
-+ name->activator = NULL; |
17736 |
-+ INIT_LIST_HEAD(&name->queue); |
17737 |
-+ hash_add(r->entries_hash, &name->hentry, hash); |
17738 |
-+ memcpy(name->name, name_str, namelen + 1); |
17739 |
-+ |
17740 |
-+ return name; |
17741 |
-+} |
17742 |
-+ |
17743 |
-+static void kdbus_name_entry_free(struct kdbus_name_entry *name) |
17744 |
-+{ |
17745 |
-+ if (!name) |
17746 |
-+ return; |
17747 |
-+ |
17748 |
-+ WARN_ON(kdbus_name_entry_is_used(name)); |
17749 |
-+ hash_del(&name->hentry); |
17750 |
-+ kfree(name); |
17751 |
-+} |
17752 |
-+ |
17753 |
-+static struct kdbus_name_entry * |
17754 |
-+kdbus_name_entry_find(struct kdbus_name_registry *r, u32 hash, |
17755 |
-+ const char *name_str) |
17756 |
-+{ |
17757 |
-+ struct kdbus_name_entry *name; |
17758 |
-+ |
17759 |
-+ lockdep_assert_held(&r->rwlock); |
17760 |
-+ |
17761 |
-+ hash_for_each_possible(r->entries_hash, name, hentry, hash) |
17762 |
-+ if (!strcmp(name->name, name_str)) |
17763 |
-+ return name; |
17764 |
-+ |
17765 |
-+ return NULL; |
17766 |
-+} |
17767 |
-+ |
17768 |
-+/** |
17769 |
-+ * kdbus_name_registry_new() - create a new name registry |
17770 |
-+ * |
17771 |
-+ * Return: a new kdbus_name_registry on success, ERR_PTR on failure. |
17772 |
-+ */ |
17773 |
-+struct kdbus_name_registry *kdbus_name_registry_new(void) |
17774 |
-+{ |
17775 |
-+ struct kdbus_name_registry *r; |
17776 |
-+ |
17777 |
-+ r = kmalloc(sizeof(*r), GFP_KERNEL); |
17778 |
-+ if (!r) |
17779 |
-+ return ERR_PTR(-ENOMEM); |
17780 |
-+ |
17781 |
-+ hash_init(r->entries_hash); |
17782 |
-+ init_rwsem(&r->rwlock); |
17783 |
-+ r->name_seq_last = 0; |
17784 |
-+ |
17785 |
-+ return r; |
17786 |
-+} |
17787 |
-+ |
17788 |
-+/** |
17789 |
-+ * kdbus_name_registry_free() - free name registry |
17790 |
-+ * @r: name registry to free, or NULL |
17791 |
-+ * |
17792 |
-+ * Free a name registry and cleanup all internal objects. This is a no-op if |
17793 |
-+ * you pass NULL as registry. |
17794 |
-+ */ |
17795 |
-+void kdbus_name_registry_free(struct kdbus_name_registry *r) |
17796 |
-+{ |
17797 |
-+ if (!r) |
17798 |
-+ return; |
17799 |
-+ |
17800 |
-+ WARN_ON(!hash_empty(r->entries_hash)); |
17801 |
-+ kfree(r); |
17802 |
-+} |
17803 |
-+ |
17804 |
-+/** |
17805 |
-+ * kdbus_name_lookup_unlocked() - lookup name in registry |
17806 |
-+ * @reg: name registry |
17807 |
-+ * @name: name to lookup |
17808 |
-+ * |
17809 |
-+ * This looks up @name in the given name-registry and returns the |
17810 |
-+ * kdbus_name_entry object. The caller must hold the registry-lock and must not |
17811 |
-+ * access the returned object after releasing the lock. |
17812 |
-+ * |
17813 |
-+ * Return: Pointer to name-entry, or NULL if not found. |
17814 |
-+ */ |
17815 |
-+struct kdbus_name_entry * |
17816 |
-+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name) |
17817 |
-+{ |
17818 |
-+ return kdbus_name_entry_find(reg, kdbus_strhash(name), name); |
17819 |
-+} |
17820 |
-+ |
17821 |
-+static int kdbus_name_become_activator(struct kdbus_name_owner *owner, |
17822 |
-+ u64 *return_flags) |
17823 |
-+{ |
17824 |
-+ if (kdbus_name_owner_is_used(owner)) |
17825 |
-+ return -EALREADY; |
17826 |
-+ if (owner->name->activator) |
17827 |
-+ return -EEXIST; |
17828 |
-+ |
17829 |
-+ owner->name->activator = owner; |
17830 |
-+ owner->flags |= KDBUS_NAME_ACTIVATOR; |
17831 |
-+ |
17832 |
-+ if (kdbus_name_entry_first(owner->name)) { |
17833 |
-+ owner->flags |= KDBUS_NAME_IN_QUEUE; |
17834 |
-+ } else { |
17835 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17836 |
-+ kdbus_notify_name_change(owner->conn->ep->bus, |
17837 |
-+ KDBUS_ITEM_NAME_ADD, |
17838 |
-+ 0, owner->conn->id, |
17839 |
-+ 0, owner->flags, |
17840 |
-+ owner->name->name); |
17841 |
-+ } |
17842 |
-+ |
17843 |
-+ if (return_flags) |
17844 |
-+ *return_flags = owner->flags | KDBUS_NAME_ACQUIRED; |
17845 |
-+ |
17846 |
-+ return 0; |
17847 |
-+} |
17848 |
-+ |
17849 |
-+static int kdbus_name_update(struct kdbus_name_owner *owner, u64 flags, |
17850 |
-+ u64 *return_flags) |
17851 |
-+{ |
17852 |
-+ struct kdbus_name_owner *primary, *activator; |
17853 |
-+ struct kdbus_name_entry *name; |
17854 |
-+ struct kdbus_bus *bus; |
17855 |
-+ u64 nflags = 0; |
17856 |
-+ int ret = 0; |
17857 |
-+ |
17858 |
-+ name = owner->name; |
17859 |
-+ bus = owner->conn->ep->bus; |
17860 |
-+ primary = kdbus_name_entry_first(name); |
17861 |
-+ activator = name->activator; |
17862 |
-+ |
17863 |
-+ /* cannot be activator and acquire a name */ |
17864 |
-+ if (owner == activator) |
17865 |
-+ return -EUCLEAN; |
17866 |
-+ |
17867 |
-+ /* update saved flags */ |
17868 |
-+ owner->flags = flags & KDBUS_NAME_SAVED_MASK; |
17869 |
-+ |
17870 |
-+ if (!primary) { |
17871 |
-+ /* |
17872 |
-+ * No primary owner (but maybe an activator). Take over the |
17873 |
-+ * name. |
17874 |
-+ */ |
17875 |
-+ |
17876 |
-+ list_add(&owner->name_entry, &name->queue); |
17877 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17878 |
-+ nflags |= KDBUS_NAME_ACQUIRED; |
17879 |
-+ |
17880 |
-+ /* move messages to new owner on activation */ |
17881 |
-+ if (activator) { |
17882 |
-+ kdbus_conn_move_messages(owner->conn, activator->conn, |
17883 |
-+ name->name_id); |
17884 |
-+ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE, |
17885 |
-+ activator->conn->id, owner->conn->id, |
17886 |
-+ activator->flags, owner->flags, |
17887 |
-+ name->name); |
17888 |
-+ activator->flags &= ~KDBUS_NAME_PRIMARY; |
17889 |
-+ activator->flags |= KDBUS_NAME_IN_QUEUE; |
17890 |
-+ } else { |
17891 |
-+ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_ADD, |
17892 |
-+ 0, owner->conn->id, |
17893 |
-+ 0, owner->flags, |
17894 |
-+ name->name); |
17895 |
-+ } |
17896 |
-+ |
17897 |
-+ } else if (owner == primary) { |
17898 |
-+ /* |
17899 |
-+ * Already the primary owner of the name, flags were already |
17900 |
-+ * updated. Nothing to do. |
17901 |
-+ */ |
17902 |
-+ |
17903 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17904 |
-+ |
17905 |
-+ } else if ((primary->flags & KDBUS_NAME_ALLOW_REPLACEMENT) && |
17906 |
-+ (flags & KDBUS_NAME_REPLACE_EXISTING)) { |
17907 |
-+ /* |
17908 |
-+ * We're not the primary owner but can replace it. Move us |
17909 |
-+ * ahead of the primary owner and acquire the name (possibly |
17910 |
-+ * skipping queued owners ahead of us). |
17911 |
-+ */ |
17912 |
-+ |
17913 |
-+ list_del_init(&owner->name_entry); |
17914 |
-+ list_add(&owner->name_entry, &name->queue); |
17915 |
-+ owner->flags |= KDBUS_NAME_PRIMARY; |
17916 |
-+ nflags |= KDBUS_NAME_ACQUIRED; |
17917 |
-+ |
17918 |
-+ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE, |
17919 |
-+ primary->conn->id, owner->conn->id, |
17920 |
-+ primary->flags, owner->flags, |
17921 |
-+ name->name); |
17922 |
-+ |
17923 |
-+ /* requeue old primary, or drop if queueing not wanted */ |
17924 |
-+ if (primary->flags & KDBUS_NAME_QUEUE) { |
17925 |
-+ primary->flags &= ~KDBUS_NAME_PRIMARY; |
17926 |
-+ primary->flags |= KDBUS_NAME_IN_QUEUE; |
17927 |
-+ } else { |
17928 |
-+ list_del_init(&primary->name_entry); |
17929 |
-+ kdbus_name_owner_free(primary); |
17930 |
-+ } |
17931 |
-+ |
17932 |
-+ } else if (flags & KDBUS_NAME_QUEUE) { |
17933 |
-+ /* |
17934 |
-+ * Name is already occupied and we cannot take it over, but |
17935 |
-+ * queuing is allowed. Put us silently on the queue, if not |
17936 |
-+ * already there. |
17937 |
-+ */ |
17938 |
-+ |
17939 |
-+ owner->flags |= KDBUS_NAME_IN_QUEUE; |
17940 |
-+ if (!kdbus_name_owner_is_used(owner)) { |
17941 |
-+ list_add_tail(&owner->name_entry, &name->queue); |
17942 |
-+ nflags |= KDBUS_NAME_ACQUIRED; |
17943 |
-+ } |
17944 |
-+ } else if (kdbus_name_owner_is_used(owner)) { |
17945 |
-+ /* |
17946 |
-+ * Already queued on name, but re-queueing was not requested. |
17947 |
-+ * Make sure to unlink it from the name, the caller is |
17948 |
-+ * responsible for releasing it. |
17949 |
-+ */ |
17950 |
-+ |
17951 |
-+ list_del_init(&owner->name_entry); |
17952 |
-+ } else { |
17953 |
-+ /* |
17954 |
-+ * Name is already claimed and queueing is not requested. |
17955 |
-+ * Return error to the caller. |
17956 |
-+ */ |
17957 |
-+ |
17958 |
-+ ret = -EEXIST; |
17959 |
-+ } |
17960 |
-+ |
17961 |
-+ if (return_flags) |
17962 |
-+ *return_flags = owner->flags | nflags; |
17963 |
-+ |
17964 |
-+ return ret; |
17965 |
-+} |
17966 |
-+ |
17967 |
-+int kdbus_name_acquire(struct kdbus_name_registry *reg, |
17968 |
-+ struct kdbus_conn *conn, const char *name_str, |
17969 |
-+ u64 flags, u64 *return_flags) |
17970 |
-+{ |
17971 |
-+ struct kdbus_name_entry *name = NULL; |
17972 |
-+ struct kdbus_name_owner *owner = NULL; |
17973 |
-+ u32 hash; |
17974 |
-+ int ret; |
17975 |
-+ |
17976 |
-+ kdbus_conn_assert_active(conn); |
17977 |
-+ |
17978 |
-+ down_write(®->rwlock); |
17979 |
-+ |
17980 |
-+ /* |
17981 |
-+ * Verify the connection has access to the name. Do this before testing |
17982 |
-+ * for double-acquisitions and other errors to make sure we do not leak |
17983 |
-+ * information about this name through possible custom endpoints. |
17984 |
-+ */ |
17985 |
-+ if (!kdbus_conn_policy_own_name(conn, current_cred(), name_str)) { |
17986 |
-+ ret = -EPERM; |
17987 |
-+ goto exit; |
17988 |
-+ } |
17989 |
-+ |
17990 |
-+ /* |
17991 |
-+ * Lookup the name entry. If it already exists, search for an owner |
17992 |
-+ * entry as we might already own that name. If either does not exist, |
17993 |
-+ * we will allocate a fresh one. |
17994 |
-+ */ |
17995 |
-+ hash = kdbus_strhash(name_str); |
17996 |
-+ name = kdbus_name_entry_find(reg, hash, name_str); |
17997 |
-+ if (name) { |
17998 |
-+ owner = kdbus_name_owner_find(name, conn); |
17999 |
-+ } else { |
18000 |
-+ name = kdbus_name_entry_new(reg, hash, name_str); |
18001 |
-+ if (IS_ERR(name)) { |
18002 |
-+ ret = PTR_ERR(name); |
18003 |
-+ name = NULL; |
18004 |
-+ goto exit; |
18005 |
-+ } |
18006 |
-+ } |
18007 |
-+ |
18008 |
-+ /* create name owner object if not already queued */ |
18009 |
-+ if (!owner) { |
18010 |
-+ owner = kdbus_name_owner_new(conn, name, flags); |
18011 |
-+ if (IS_ERR(owner)) { |
18012 |
-+ ret = PTR_ERR(owner); |
18013 |
-+ owner = NULL; |
18014 |
-+ goto exit; |
18015 |
-+ } |
18016 |
-+ } |
18017 |
-+ |
18018 |
-+ if (flags & KDBUS_NAME_ACTIVATOR) |
18019 |
-+ ret = kdbus_name_become_activator(owner, return_flags); |
18020 |
-+ else |
18021 |
-+ ret = kdbus_name_update(owner, flags, return_flags); |
18022 |
-+ if (ret < 0) |
18023 |
-+ goto exit; |
18024 |
-+ |
18025 |
-+exit: |
18026 |
-+ if (owner && !kdbus_name_owner_is_used(owner)) |
18027 |
-+ kdbus_name_owner_free(owner); |
18028 |
-+ if (name && !kdbus_name_entry_is_used(name)) |
18029 |
-+ kdbus_name_entry_free(name); |
18030 |
-+ up_write(®->rwlock); |
18031 |
-+ kdbus_notify_flush(conn->ep->bus); |
18032 |
-+ return ret; |
18033 |
-+} |
18034 |
-+ |
18035 |
-+static void kdbus_name_release_unlocked(struct kdbus_name_owner *owner) |
18036 |
-+{ |
18037 |
-+ struct kdbus_name_owner *primary, *next; |
18038 |
-+ struct kdbus_name_entry *name; |
18039 |
-+ |
18040 |
-+ name = owner->name; |
18041 |
-+ primary = kdbus_name_entry_first(name); |
18042 |
-+ |
18043 |
-+ list_del_init(&owner->name_entry); |
18044 |
-+ if (owner == name->activator) |
18045 |
-+ name->activator = NULL; |
18046 |
-+ |
18047 |
-+ if (!primary || owner == primary) { |
18048 |
-+ next = kdbus_name_entry_first(name); |
18049 |
-+ if (!next) |
18050 |
-+ next = name->activator; |
18051 |
-+ |
18052 |
-+ if (next) { |
18053 |
-+ /* hand to next in queue */ |
18054 |
-+ next->flags &= ~KDBUS_NAME_IN_QUEUE; |
18055 |
-+ next->flags |= KDBUS_NAME_PRIMARY; |
18056 |
-+ if (next == name->activator) |
18057 |
-+ kdbus_conn_move_messages(next->conn, |
18058 |
-+ owner->conn, |
18059 |
-+ name->name_id); |
18060 |
-+ |
18061 |
-+ kdbus_notify_name_change(owner->conn->ep->bus, |
18062 |
-+ KDBUS_ITEM_NAME_CHANGE, |
18063 |
-+ owner->conn->id, next->conn->id, |
18064 |
-+ owner->flags, next->flags, |
18065 |
-+ name->name); |
18066 |
-+ } else { |
18067 |
-+ kdbus_notify_name_change(owner->conn->ep->bus, |
18068 |
-+ KDBUS_ITEM_NAME_REMOVE, |
18069 |
-+ owner->conn->id, 0, |
18070 |
-+ owner->flags, 0, |
18071 |
-+ name->name); |
18072 |
-+ } |
18073 |
-+ } |
18074 |
-+ |
18075 |
-+ kdbus_name_owner_free(owner); |
18076 |
-+ if (!kdbus_name_entry_is_used(name)) |
18077 |
-+ kdbus_name_entry_free(name); |
18078 |
-+} |
18079 |
-+ |
18080 |
-+static int kdbus_name_release(struct kdbus_name_registry *reg, |
18081 |
-+ struct kdbus_conn *conn, |
18082 |
-+ const char *name_str) |
18083 |
-+{ |
18084 |
-+ struct kdbus_name_owner *owner; |
18085 |
-+ struct kdbus_name_entry *name; |
18086 |
-+ int ret = 0; |
18087 |
-+ |
18088 |
-+ down_write(®->rwlock); |
18089 |
-+ name = kdbus_name_entry_find(reg, kdbus_strhash(name_str), name_str); |
18090 |
-+ if (name) { |
18091 |
-+ owner = kdbus_name_owner_find(name, conn); |
18092 |
-+ if (owner) |
18093 |
-+ kdbus_name_release_unlocked(owner); |
18094 |
-+ else |
18095 |
-+ ret = -EADDRINUSE; |
18096 |
-+ } else { |
18097 |
-+ ret = -ESRCH; |
18098 |
-+ } |
18099 |
-+ up_write(®->rwlock); |
18100 |
-+ |
18101 |
-+ kdbus_notify_flush(conn->ep->bus); |
18102 |
-+ return ret; |
18103 |
-+} |
18104 |
-+ |
18105 |
-+/** |
18106 |
-+ * kdbus_name_release_all() - remove all name entries of a given connection |
18107 |
-+ * @reg: name registry |
18108 |
-+ * @conn: connection |
18109 |
-+ */ |
18110 |
-+void kdbus_name_release_all(struct kdbus_name_registry *reg, |
18111 |
-+ struct kdbus_conn *conn) |
18112 |
-+{ |
18113 |
-+ struct kdbus_name_owner *owner; |
18114 |
-+ |
18115 |
-+ down_write(®->rwlock); |
18116 |
-+ |
18117 |
-+ while ((owner = list_first_entry_or_null(&conn->names_list, |
18118 |
-+ struct kdbus_name_owner, |
18119 |
-+ conn_entry))) |
18120 |
-+ kdbus_name_release_unlocked(owner); |
18121 |
-+ |
18122 |
-+ up_write(®->rwlock); |
18123 |
-+ |
18124 |
-+ kdbus_notify_flush(conn->ep->bus); |
18125 |
-+} |
18126 |
-+ |
18127 |
-+/** |
18128 |
-+ * kdbus_name_is_valid() - check if a name is valid |
18129 |
-+ * @p: The name to check |
18130 |
-+ * @allow_wildcard: Whether or not to allow a wildcard name |
18131 |
-+ * |
18132 |
-+ * A name is valid if all of the following criterias are met: |
18133 |
-+ * |
18134 |
-+ * - The name has two or more elements separated by a period ('.') character. |
18135 |
-+ * - All elements must contain at least one character. |
18136 |
-+ * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-" |
18137 |
-+ * and must not begin with a digit. |
18138 |
-+ * - The name must not exceed KDBUS_NAME_MAX_LEN. |
18139 |
-+ * - If @allow_wildcard is true, the name may end on '.*' |
18140 |
-+ */ |
18141 |
-+bool kdbus_name_is_valid(const char *p, bool allow_wildcard) |
18142 |
-+{ |
18143 |
-+ bool dot, found_dot = false; |
18144 |
-+ const char *q; |
18145 |
-+ |
18146 |
-+ for (dot = true, q = p; *q; q++) { |
18147 |
-+ if (*q == '.') { |
18148 |
-+ if (dot) |
18149 |
-+ return false; |
18150 |
-+ |
18151 |
-+ found_dot = true; |
18152 |
-+ dot = true; |
18153 |
-+ } else { |
18154 |
-+ bool good; |
18155 |
-+ |
18156 |
-+ good = isalpha(*q) || (!dot && isdigit(*q)) || |
18157 |
-+ *q == '_' || *q == '-' || |
18158 |
-+ (allow_wildcard && dot && |
18159 |
-+ *q == '*' && *(q + 1) == '\0'); |
18160 |
-+ |
18161 |
-+ if (!good) |
18162 |
-+ return false; |
18163 |
-+ |
18164 |
-+ dot = false; |
18165 |
-+ } |
18166 |
-+ } |
18167 |
-+ |
18168 |
-+ if (q - p > KDBUS_NAME_MAX_LEN) |
18169 |
-+ return false; |
18170 |
-+ |
18171 |
-+ if (dot) |
18172 |
-+ return false; |
18173 |
-+ |
18174 |
-+ if (!found_dot) |
18175 |
-+ return false; |
18176 |
-+ |
18177 |
-+ return true; |
18178 |
-+} |
18179 |
-+ |
18180 |
-+/** |
18181 |
-+ * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE |
18182 |
-+ * @conn: connection to operate on |
18183 |
-+ * @argp: command payload |
18184 |
-+ * |
18185 |
-+ * Return: >=0 on success, negative error code on failure. |
18186 |
-+ */ |
18187 |
-+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp) |
18188 |
-+{ |
18189 |
-+ const char *item_name; |
18190 |
-+ struct kdbus_cmd *cmd; |
18191 |
-+ int ret; |
18192 |
-+ |
18193 |
-+ struct kdbus_arg argv[] = { |
18194 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
18195 |
-+ { .type = KDBUS_ITEM_NAME, .mandatory = true }, |
18196 |
-+ }; |
18197 |
-+ struct kdbus_args args = { |
18198 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
18199 |
-+ KDBUS_NAME_REPLACE_EXISTING | |
18200 |
-+ KDBUS_NAME_ALLOW_REPLACEMENT | |
18201 |
-+ KDBUS_NAME_QUEUE, |
18202 |
-+ .argv = argv, |
18203 |
-+ .argc = ARRAY_SIZE(argv), |
18204 |
-+ }; |
18205 |
-+ |
18206 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
18207 |
-+ return -EOPNOTSUPP; |
18208 |
-+ |
18209 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
18210 |
-+ if (ret != 0) |
18211 |
-+ return ret; |
18212 |
-+ |
18213 |
-+ item_name = argv[1].item->str; |
18214 |
-+ if (!kdbus_name_is_valid(item_name, false)) { |
18215 |
-+ ret = -EINVAL; |
18216 |
-+ goto exit; |
18217 |
-+ } |
18218 |
-+ |
18219 |
-+ ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name, |
18220 |
-+ cmd->flags, &cmd->return_flags); |
18221 |
-+ |
18222 |
-+exit: |
18223 |
-+ return kdbus_args_clear(&args, ret); |
18224 |
-+} |
18225 |
-+ |
18226 |
-+/** |
18227 |
-+ * kdbus_cmd_name_release() - handle KDBUS_CMD_NAME_RELEASE |
18228 |
-+ * @conn: connection to operate on |
18229 |
-+ * @argp: command payload |
18230 |
-+ * |
18231 |
-+ * Return: >=0 on success, negative error code on failure. |
18232 |
-+ */ |
18233 |
-+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp) |
18234 |
-+{ |
18235 |
-+ struct kdbus_cmd *cmd; |
18236 |
-+ int ret; |
18237 |
-+ |
18238 |
-+ struct kdbus_arg argv[] = { |
18239 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
18240 |
-+ { .type = KDBUS_ITEM_NAME, .mandatory = true }, |
18241 |
-+ }; |
18242 |
-+ struct kdbus_args args = { |
18243 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE, |
18244 |
-+ .argv = argv, |
18245 |
-+ .argc = ARRAY_SIZE(argv), |
18246 |
-+ }; |
18247 |
-+ |
18248 |
-+ if (!kdbus_conn_is_ordinary(conn)) |
18249 |
-+ return -EOPNOTSUPP; |
18250 |
-+ |
18251 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
18252 |
-+ if (ret != 0) |
18253 |
-+ return ret; |
18254 |
-+ |
18255 |
-+ ret = kdbus_name_release(conn->ep->bus->name_registry, conn, |
18256 |
-+ argv[1].item->str); |
18257 |
-+ return kdbus_args_clear(&args, ret); |
18258 |
-+} |
18259 |
-+ |
18260 |
-+static int kdbus_list_write(struct kdbus_conn *conn, |
18261 |
-+ struct kdbus_conn *c, |
18262 |
-+ struct kdbus_pool_slice *slice, |
18263 |
-+ size_t *pos, |
18264 |
-+ struct kdbus_name_owner *o, |
18265 |
-+ bool write) |
18266 |
-+{ |
18267 |
-+ struct kvec kvec[4]; |
18268 |
-+ size_t cnt = 0; |
18269 |
-+ int ret; |
18270 |
-+ |
18271 |
-+ /* info header */ |
18272 |
-+ struct kdbus_info info = { |
18273 |
-+ .size = 0, |
18274 |
-+ .id = c->id, |
18275 |
-+ .flags = c->flags, |
18276 |
-+ }; |
18277 |
-+ |
18278 |
-+ /* fake the header of a kdbus_name item */ |
18279 |
-+ struct { |
18280 |
-+ u64 size; |
18281 |
-+ u64 type; |
18282 |
-+ u64 flags; |
18283 |
-+ } h = {}; |
18284 |
-+ |
18285 |
-+ if (o && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(), |
18286 |
-+ o->name->name)) |
18287 |
-+ return 0; |
18288 |
-+ |
18289 |
-+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size); |
18290 |
-+ |
18291 |
-+ /* append name */ |
18292 |
-+ if (o) { |
18293 |
-+ size_t slen = strlen(o->name->name) + 1; |
18294 |
-+ |
18295 |
-+ h.size = offsetof(struct kdbus_item, name.name) + slen; |
18296 |
-+ h.type = KDBUS_ITEM_OWNED_NAME; |
18297 |
-+ h.flags = o->flags; |
18298 |
-+ |
18299 |
-+ kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size); |
18300 |
-+ kdbus_kvec_set(&kvec[cnt++], o->name->name, slen, &info.size); |
18301 |
-+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size); |
18302 |
-+ } |
18303 |
-+ |
18304 |
-+ if (write) { |
18305 |
-+ ret = kdbus_pool_slice_copy_kvec(slice, *pos, kvec, |
18306 |
-+ cnt, info.size); |
18307 |
-+ if (ret < 0) |
18308 |
-+ return ret; |
18309 |
-+ } |
18310 |
-+ |
18311 |
-+ *pos += info.size; |
18312 |
-+ return 0; |
18313 |
-+} |
18314 |
-+ |
18315 |
-+static int kdbus_list_all(struct kdbus_conn *conn, u64 flags, |
18316 |
-+ struct kdbus_pool_slice *slice, |
18317 |
-+ size_t *pos, bool write) |
18318 |
-+{ |
18319 |
-+ struct kdbus_conn *c; |
18320 |
-+ size_t p = *pos; |
18321 |
-+ int ret, i; |
18322 |
-+ |
18323 |
-+ hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) { |
18324 |
-+ bool added = false; |
18325 |
-+ |
18326 |
-+ /* skip monitors */ |
18327 |
-+ if (kdbus_conn_is_monitor(c)) |
18328 |
-+ continue; |
18329 |
-+ |
18330 |
-+ /* all names the connection owns */ |
18331 |
-+ if (flags & (KDBUS_LIST_NAMES | |
18332 |
-+ KDBUS_LIST_ACTIVATORS | |
18333 |
-+ KDBUS_LIST_QUEUED)) { |
18334 |
-+ struct kdbus_name_owner *o; |
18335 |
-+ |
18336 |
-+ list_for_each_entry(o, &c->names_list, conn_entry) { |
18337 |
-+ if (o->flags & KDBUS_NAME_ACTIVATOR) { |
18338 |
-+ if (!(flags & KDBUS_LIST_ACTIVATORS)) |
18339 |
-+ continue; |
18340 |
-+ |
18341 |
-+ ret = kdbus_list_write(conn, c, slice, |
18342 |
-+ &p, o, write); |
18343 |
-+ if (ret < 0) { |
18344 |
-+ mutex_unlock(&c->lock); |
18345 |
-+ return ret; |
18346 |
-+ } |
18347 |
-+ |
18348 |
-+ added = true; |
18349 |
-+ } else if (o->flags & KDBUS_NAME_IN_QUEUE) { |
18350 |
-+ if (!(flags & KDBUS_LIST_QUEUED)) |
18351 |
-+ continue; |
18352 |
-+ |
18353 |
-+ ret = kdbus_list_write(conn, c, slice, |
18354 |
-+ &p, o, write); |
18355 |
-+ if (ret < 0) { |
18356 |
-+ mutex_unlock(&c->lock); |
18357 |
-+ return ret; |
18358 |
-+ } |
18359 |
-+ |
18360 |
-+ added = true; |
18361 |
-+ } else if (flags & KDBUS_LIST_NAMES) { |
18362 |
-+ ret = kdbus_list_write(conn, c, slice, |
18363 |
-+ &p, o, write); |
18364 |
-+ if (ret < 0) { |
18365 |
-+ mutex_unlock(&c->lock); |
18366 |
-+ return ret; |
18367 |
-+ } |
18368 |
-+ |
18369 |
-+ added = true; |
18370 |
-+ } |
18371 |
-+ } |
18372 |
-+ } |
18373 |
-+ |
18374 |
-+ /* nothing added so far, just add the unique ID */ |
18375 |
-+ if (!added && (flags & KDBUS_LIST_UNIQUE)) { |
18376 |
-+ ret = kdbus_list_write(conn, c, slice, &p, NULL, write); |
18377 |
-+ if (ret < 0) |
18378 |
-+ return ret; |
18379 |
-+ } |
18380 |
-+ } |
18381 |
-+ |
18382 |
-+ *pos = p; |
18383 |
-+ return 0; |
18384 |
-+} |
18385 |
-+ |
18386 |
-+/** |
18387 |
-+ * kdbus_cmd_list() - handle KDBUS_CMD_LIST |
18388 |
-+ * @conn: connection to operate on |
18389 |
-+ * @argp: command payload |
18390 |
-+ * |
18391 |
-+ * Return: >=0 on success, negative error code on failure. |
18392 |
-+ */ |
18393 |
-+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp) |
18394 |
-+{ |
18395 |
-+ struct kdbus_name_registry *reg = conn->ep->bus->name_registry; |
18396 |
-+ struct kdbus_pool_slice *slice = NULL; |
18397 |
-+ struct kdbus_cmd_list *cmd; |
18398 |
-+ size_t pos, size; |
18399 |
-+ int ret; |
18400 |
-+ |
18401 |
-+ struct kdbus_arg argv[] = { |
18402 |
-+ { .type = KDBUS_ITEM_NEGOTIATE }, |
18403 |
-+ }; |
18404 |
-+ struct kdbus_args args = { |
18405 |
-+ .allowed_flags = KDBUS_FLAG_NEGOTIATE | |
18406 |
-+ KDBUS_LIST_UNIQUE | |
18407 |
-+ KDBUS_LIST_NAMES | |
18408 |
-+ KDBUS_LIST_ACTIVATORS | |
18409 |
-+ KDBUS_LIST_QUEUED, |
18410 |
-+ .argv = argv, |
18411 |
-+ .argc = ARRAY_SIZE(argv), |
18412 |
-+ }; |
18413 |
-+ |
18414 |
-+ ret = kdbus_args_parse(&args, argp, &cmd); |
18415 |
-+ if (ret != 0) |
18416 |
-+ return ret; |
18417 |
-+ |
18418 |
-+ /* lock order: domain -> bus -> ep -> names -> conn */ |
18419 |
-+ down_read(®->rwlock); |
18420 |
-+ down_read(&conn->ep->bus->conn_rwlock); |
18421 |
-+ down_read(&conn->ep->policy_db.entries_rwlock); |
18422 |
-+ |
18423 |
-+ /* size of records */ |
18424 |
-+ size = 0; |
18425 |
-+ ret = kdbus_list_all(conn, cmd->flags, NULL, &size, false); |
18426 |
-+ if (ret < 0) |
18427 |
-+ goto exit_unlock; |
18428 |
-+ |
18429 |
-+ if (size == 0) { |
18430 |
-+ kdbus_pool_publish_empty(conn->pool, &cmd->offset, |
18431 |
-+ &cmd->list_size); |
18432 |
-+ } else { |
18433 |
-+ slice = kdbus_pool_slice_alloc(conn->pool, size, false); |
18434 |
-+ if (IS_ERR(slice)) { |
18435 |
-+ ret = PTR_ERR(slice); |
18436 |
-+ slice = NULL; |
18437 |
-+ goto exit_unlock; |
18438 |
-+ } |
18439 |
-+ |
18440 |
-+ /* copy the records */ |
18441 |
-+ pos = 0; |
18442 |
-+ ret = kdbus_list_all(conn, cmd->flags, slice, &pos, true); |
18443 |
-+ if (ret < 0) |
18444 |
-+ goto exit_unlock; |
18445 |
-+ |
18446 |
-+ WARN_ON(pos != size); |
18447 |
-+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->list_size); |
18448 |
-+ } |
18449 |
-+ |
18450 |
-+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) || |
18451 |
-+ kdbus_member_set_user(&cmd->list_size, argp, |
18452 |
-+ typeof(*cmd), list_size)) |
18453 |
-+ ret = -EFAULT; |
18454 |
-+ |
18455 |
-+exit_unlock: |
18456 |
-+ up_read(&conn->ep->policy_db.entries_rwlock); |
18457 |
-+ up_read(&conn->ep->bus->conn_rwlock); |
18458 |
-+ up_read(®->rwlock); |
18459 |
-+ kdbus_pool_slice_release(slice); |
18460 |
-+ return kdbus_args_clear(&args, ret); |
18461 |
-+} |
18462 |
-diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h |
18463 |
-new file mode 100644 |
18464 |
-index 0000000..edac59d |
18465 |
---- /dev/null |
18466 |
-+++ b/ipc/kdbus/names.h |
18467 |
-@@ -0,0 +1,105 @@ |
18468 |
-+/* |
18469 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
18470 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
18471 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
18472 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
18473 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
18474 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
18475 |
-+ * |
18476 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
18477 |
-+ * the terms of the GNU Lesser General Public License as published by the |
18478 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
18479 |
-+ * your option) any later version. |
18480 |
-+ */ |
18481 |
-+ |
18482 |
-+#ifndef __KDBUS_NAMES_H |
18483 |
-+#define __KDBUS_NAMES_H |
18484 |
-+ |
18485 |
-+#include <linux/hashtable.h> |
18486 |
-+#include <linux/rwsem.h> |
18487 |
-+ |
18488 |
-+struct kdbus_name_entry; |
18489 |
-+struct kdbus_name_owner; |
18490 |
-+struct kdbus_name_registry; |
18491 |
-+ |
18492 |
-+/** |
18493 |
-+ * struct kdbus_name_registry - names registered for a bus |
18494 |
-+ * @entries_hash: Map of entries |
18495 |
-+ * @lock: Registry data lock |
18496 |
-+ * @name_seq_last: Last used sequence number to assign to a name entry |
18497 |
-+ */ |
18498 |
-+struct kdbus_name_registry { |
18499 |
-+ DECLARE_HASHTABLE(entries_hash, 8); |
18500 |
-+ struct rw_semaphore rwlock; |
18501 |
-+ u64 name_seq_last; |
18502 |
-+}; |
18503 |
-+ |
18504 |
-+/** |
18505 |
-+ * struct kdbus_name_entry - well-know name entry |
18506 |
-+ * @name_id: sequence number of name entry to be able to uniquely |
18507 |
-+ * identify a name over its registration lifetime |
18508 |
-+ * @activator: activator of this name, or NULL |
18509 |
-+ * @queue: list of queued owners |
18510 |
-+ * @hentry: entry in registry map |
18511 |
-+ * @name: well-known name |
18512 |
-+ */ |
18513 |
-+struct kdbus_name_entry { |
18514 |
-+ u64 name_id; |
18515 |
-+ struct kdbus_name_owner *activator; |
18516 |
-+ struct list_head queue; |
18517 |
-+ struct hlist_node hentry; |
18518 |
-+ char name[]; |
18519 |
-+}; |
18520 |
-+ |
18521 |
-+/** |
18522 |
-+ * struct kdbus_name_owner - owner of a well-known name |
18523 |
-+ * @flags: KDBUS_NAME_* flags of this owner |
18524 |
-+ * @conn: connection owning the name |
18525 |
-+ * @name: name that is owned |
18526 |
-+ * @conn_entry: link into @conn |
18527 |
-+ * @name_entry: link into @name |
18528 |
-+ */ |
18529 |
-+struct kdbus_name_owner { |
18530 |
-+ u64 flags; |
18531 |
-+ struct kdbus_conn *conn; |
18532 |
-+ struct kdbus_name_entry *name; |
18533 |
-+ struct list_head conn_entry; |
18534 |
-+ struct list_head name_entry; |
18535 |
-+}; |
18536 |
-+ |
18537 |
-+bool kdbus_name_is_valid(const char *p, bool allow_wildcard); |
18538 |
-+ |
18539 |
-+struct kdbus_name_registry *kdbus_name_registry_new(void); |
18540 |
-+void kdbus_name_registry_free(struct kdbus_name_registry *reg); |
18541 |
-+ |
18542 |
-+struct kdbus_name_entry * |
18543 |
-+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name); |
18544 |
-+ |
18545 |
-+int kdbus_name_acquire(struct kdbus_name_registry *reg, |
18546 |
-+ struct kdbus_conn *conn, const char *name, |
18547 |
-+ u64 flags, u64 *return_flags); |
18548 |
-+void kdbus_name_release_all(struct kdbus_name_registry *reg, |
18549 |
-+ struct kdbus_conn *conn); |
18550 |
-+ |
18551 |
-+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp); |
18552 |
-+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp); |
18553 |
-+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp); |
18554 |
-+ |
18555 |
-+/** |
18556 |
-+ * kdbus_name_get_owner() - get current owner of a name |
18557 |
-+ * @name: name to get current owner of |
18558 |
-+ * |
18559 |
-+ * This returns a pointer to the current owner of a name (or its activator if |
18560 |
-+ * there is no owner). The caller must make sure @name is valid and does not |
18561 |
-+ * vanish. |
18562 |
-+ * |
18563 |
-+ * Return: Pointer to current owner or NULL if there is none. |
18564 |
-+ */ |
18565 |
-+static inline struct kdbus_name_owner * |
18566 |
-+kdbus_name_get_owner(struct kdbus_name_entry *name) |
18567 |
-+{ |
18568 |
-+ return list_first_entry_or_null(&name->queue, struct kdbus_name_owner, |
18569 |
-+ name_entry) ? : name->activator; |
18570 |
-+} |
18571 |
-+ |
18572 |
-+#endif |
18573 |
-diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c |
18574 |
-new file mode 100644 |
18575 |
-index 0000000..89f58bc |
18576 |
---- /dev/null |
18577 |
-+++ b/ipc/kdbus/node.c |
18578 |
-@@ -0,0 +1,897 @@ |
18579 |
-+/* |
18580 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
18581 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
18582 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
18583 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
18584 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
18585 |
-+ * |
18586 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
18587 |
-+ * the terms of the GNU Lesser General Public License as published by the |
18588 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
18589 |
-+ * your option) any later version. |
18590 |
-+ */ |
18591 |
-+ |
18592 |
-+#include <linux/atomic.h> |
18593 |
-+#include <linux/fs.h> |
18594 |
-+#include <linux/idr.h> |
18595 |
-+#include <linux/kdev_t.h> |
18596 |
-+#include <linux/rbtree.h> |
18597 |
-+#include <linux/rwsem.h> |
18598 |
-+#include <linux/sched.h> |
18599 |
-+#include <linux/slab.h> |
18600 |
-+#include <linux/wait.h> |
18601 |
-+ |
18602 |
-+#include "bus.h" |
18603 |
-+#include "domain.h" |
18604 |
-+#include "endpoint.h" |
18605 |
-+#include "fs.h" |
18606 |
-+#include "handle.h" |
18607 |
-+#include "node.h" |
18608 |
-+#include "util.h" |
18609 |
-+ |
18610 |
-+/** |
18611 |
-+ * DOC: kdbus nodes |
18612 |
-+ * |
18613 |
-+ * Nodes unify lifetime management across exposed kdbus objects and provide a |
18614 |
-+ * hierarchy. Each kdbus object, that might be exposed to user-space, has a |
18615 |
-+ * kdbus_node object embedded and is linked into the hierarchy. Each node can |
18616 |
-+ * have any number (0-n) of child nodes linked. Each child retains a reference |
18617 |
-+ * to its parent node. For root-nodes, the parent is NULL. |
18618 |
-+ * |
18619 |
-+ * Each node object goes through a bunch of states during it's lifetime: |
18620 |
-+ * * NEW |
18621 |
-+ * * LINKED (can be skipped by NEW->FREED transition) |
18622 |
-+ * * ACTIVE (can be skipped by LINKED->INACTIVE transition) |
18623 |
-+ * * INACTIVE |
18624 |
-+ * * DRAINED |
18625 |
-+ * * FREED |
18626 |
-+ * |
18627 |
-+ * Each node is allocated by the caller and initialized via kdbus_node_init(). |
18628 |
-+ * This never fails and sets the object into state NEW. From now on, ref-counts |
18629 |
-+ * on the node manage its lifetime. During init, the ref-count is set to 1. Once |
18630 |
-+ * it drops to 0, the node goes to state FREED and the node->free_cb() callback |
18631 |
-+ * is called to deallocate any memory. |
18632 |
-+ * |
18633 |
-+ * After initializing a node, you usually link it into the hierarchy. You need |
18634 |
-+ * to provide a parent node and a name. The node will be linked as child to the |
18635 |
-+ * parent and a globally unique ID is assigned to the child. The name of the |
18636 |
-+ * child must be unique for all children of this parent. Otherwise, linking the |
18637 |
-+ * child will fail with -EEXIST. |
18638 |
-+ * Note that the child is not marked active, yet. Admittedly, it prevents any |
18639 |
-+ * other node from being linked with the same name (thus, it reserves that |
18640 |
-+ * name), but any child-lookup (via name or unique ID) will never return this |
18641 |
-+ * child unless it has been marked active. |
18642 |
-+ * |
18643 |
-+ * Once successfully linked, you can use kdbus_node_activate() to activate a |
18644 |
-+ * child. This will mark the child active. This state can be skipped by directly |
18645 |
-+ * deactivating the child via kdbus_node_deactivate() (see below). |
18646 |
-+ * By activating a child, you enable any lookups on this child to succeed from |
18647 |
-+ * now on. Furthermore, any code that got its hands on a reference to the node, |
18648 |
-+ * can from now on "acquire" the node. |
18649 |
-+ * |
18650 |
-+ * Active References (or: 'acquiring' and 'releasing' a node) |
18651 |
-+ * Additionally to normal object references, nodes support something we call |
18652 |
-+ * "active references". An active reference can be acquired via |
18653 |
-+ * kdbus_node_acquire() and released via kdbus_node_release(). A caller |
18654 |
-+ * _must_ own a normal object reference whenever calling those functions. |
18655 |
-+ * Unlike object references, acquiring an active reference can fail (by |
18656 |
-+ * returning 'false' from kdbus_node_acquire()). An active reference can |
18657 |
-+ * only be acquired if the node is marked active. If it is not marked |
18658 |
-+ * active, yet, or if it was already deactivated, no more active references |
18659 |
-+ * can be acquired, ever! |
18660 |
-+ * Active references are used to track tasks working on a node. Whenever a |
18661 |
-+ * task enters kernel-space to perform an action on a node, it acquires an |
18662 |
-+ * active reference, performs the action and releases the reference again. |
18663 |
-+ * While holding an active reference, the node is guaranteed to stay active. |
18664 |
-+ * If the node is deactivated in parallel, the node is marked as |
18665 |
-+ * deactivated, then we wait for all active references to be dropped, before |
18666 |
-+ * we finally proceed with any cleanups. That is, if you hold an active |
18667 |
-+ * reference to a node, any resources that are bound to the "active" state |
18668 |
-+ * are guaranteed to stay accessible until you release your reference. |
18669 |
-+ * |
18670 |
-+ * Active-references are very similar to rw-locks, where acquiring a node is |
18671 |
-+ * equal to try-read-lock and releasing to read-unlock. Deactivating a node |
18672 |
-+ * means write-lock and never releasing it again. |
18673 |
-+ * Unlike rw-locks, the 'active reference' concept is more versatile and |
18674 |
-+ * avoids unusual rw-lock usage (never releasing a write-lock..). |
18675 |
-+ * |
18676 |
-+ * It is safe to acquire multiple active-references recursively. But you |
18677 |
-+ * need to check the return value of kdbus_node_acquire() on _each_ call. It |
18678 |
-+ * may stop granting references at _any_ time. |
18679 |
-+ * |
18680 |
-+ * You're free to perform any operations you want while holding an active |
18681 |
-+ * reference, except sleeping for an indefinite period. Sleeping for a fixed |
18682 |
-+ * amount of time is fine, but you usually should not wait on wait-queues |
18683 |
-+ * without a timeout. |
18684 |
-+ * For example, if you wait for I/O to happen, you should gather all data |
18685 |
-+ * and schedule the I/O operation, then release your active reference and |
18686 |
-+ * wait for it to complete. Then try to acquire a new reference. If it |
18687 |
-+ * fails, perform any cleanup (the node is now dead). Otherwise, you can |
18688 |
-+ * finish your operation. |
18689 |
-+ * |
18690 |
-+ * All nodes can be deactivated via kdbus_node_deactivate() at any time. You can |
18691 |
-+ * call this multiple times, even in parallel or on nodes that were never |
18692 |
-+ * linked, and it will just work. The only restriction is, you must not hold an |
18693 |
-+ * active reference when calling kdbus_node_deactivate(). |
18694 |
-+ * By deactivating a node, it is immediately marked inactive. Then, we wait for |
18695 |
-+ * all active references to be released (called 'draining' the node). This |
18696 |
-+ * shouldn't take very long as we don't perform long-lasting operations while |
18697 |
-+ * holding an active reference. Note that once the node is marked inactive, no |
18698 |
-+ * new active references can be acquired. |
18699 |
-+ * Once all active references are dropped, the node is considered 'drained'. Now |
18700 |
-+ * kdbus_node_deactivate() is called on each child of the node before we |
18701 |
-+ * continue deactivating our node. That is, once all children are entirely |
18702 |
-+ * deactivated, we call ->release_cb() of our node. ->release_cb() can release |
18703 |
-+ * any resources on that node which are bound to the "active" state of a node. |
18704 |
-+ * When done, we unlink the node from its parent rb-tree, mark it as |
18705 |
-+ * 'released' and return. |
18706 |
-+ * If kdbus_node_deactivate() is called multiple times (even in parallel), all |
18707 |
-+ * but one caller will just wait until the node is fully deactivated. That is, |
18708 |
-+ * one random caller of kdbus_node_deactivate() is selected to call |
18709 |
-+ * ->release_cb() and cleanup the node. Only once all this is done, all other |
18710 |
-+ * callers will return from kdbus_node_deactivate(). That is, it doesn't matter |
18711 |
-+ * whether you're the selected caller or not, it will only return after |
18712 |
-+ * everything is fully done. |
18713 |
-+ * |
18714 |
-+ * When a node is activated, we acquire a normal object reference to the node. |
18715 |
-+ * This reference is dropped after deactivation is fully done (and only iff the |
18716 |
-+ * node really was activated). This allows callers to link+activate a child node |
18717 |
-+ * and then drop all refs. The node will be deactivated together with the |
18718 |
-+ * parent, and then be freed when this reference is dropped. |
18719 |
-+ * |
18720 |
-+ * Currently, nodes provide a bunch of resources that external code can use |
18721 |
-+ * directly. This includes: |
18722 |
-+ * |
18723 |
-+ * * node->waitq: Each node has its own wait-queue that is used to manage |
18724 |
-+ * the 'active' state. When a node is deactivated, we wait on |
18725 |
-+ * this queue until all active refs are dropped. Analogously, |
18726 |
-+ * when you release an active reference on a deactivated |
18727 |
-+ * node, and the active ref-count drops to 0, we wake up a |
18728 |
-+ * single thread on this queue. Furthermore, once the |
18729 |
-+ * ->release_cb() callback finished, we wake up all waiters. |
18730 |
-+ * The node-owner is free to re-use this wait-queue for other |
18731 |
-+ * purposes. As node-management uses this queue only during |
18732 |
-+ * deactivation, it is usually totally fine to re-use the |
18733 |
-+ * queue for other, preferably low-overhead, use-cases. |
18734 |
-+ * |
18735 |
-+ * * node->type: This field defines the type of the owner of this node. It |
18736 |
-+ * must be set during node initialization and must remain |
18737 |
-+ * constant. The node management never looks at this value, |
18738 |
-+ * but external users might use to gain access to the owner |
18739 |
-+ * object of a node. |
18740 |
-+ * It is totally up to the owner of the node to define what |
18741 |
-+ * their type means. Usually it means you can access the |
18742 |
-+ * parent structure via container_of(), as long as you hold an |
18743 |
-+ * active reference to the node. |
18744 |
-+ * |
18745 |
-+ * * node->free_cb: callback after all references are dropped |
18746 |
-+ * node->release_cb: callback during node deactivation |
18747 |
-+ * These fields must be set by the node owner during |
18748 |
-+ * node initialization. They must remain constant. If |
18749 |
-+ * NULL, they're skipped. |
18750 |
-+ * |
18751 |
-+ * * node->mode: filesystem access modes |
18752 |
-+ * node->uid: filesystem owner uid |
18753 |
-+ * node->gid: filesystem owner gid |
18754 |
-+ * These fields must be set by the node owner during node |
18755 |
-+ * initialization. They must remain constant and may be |
18756 |
-+ * accessed by other callers to properly initialize |
18757 |
-+ * filesystem nodes. |
18758 |
-+ * |
18759 |
-+ * * node->id: This is an unsigned 32bit integer allocated by an IDA. It is |
18760 |
-+ * always kept as small as possible during allocation and is |
18761 |
-+ * globally unique across all nodes allocated by this module. 0 |
18762 |
-+ * is reserved as "not assigned" and is the default. |
18763 |
-+ * The ID is assigned during kdbus_node_link() and is kept until |
18764 |
-+ * the object is freed. Thus, the ID surpasses the active |
18765 |
-+ * lifetime of a node. As long as you hold an object reference |
18766 |
-+ * to a node (and the node was linked once), the ID is valid and |
18767 |
-+ * unique. |
18768 |
-+ * |
18769 |
-+ * * node->name: name of this node |
18770 |
-+ * node->hash: 31bit hash-value of @name (range [2..INT_MAX-1]) |
18771 |
-+ * These values follow the same lifetime rules as node->id. |
18772 |
-+ * They're initialized when the node is linked and then remain |
18773 |
-+ * constant until the last object reference is dropped. |
18774 |
-+ * Unlike the id, the name is only unique across all siblings |
18775 |
-+ * and only until the node is deactivated. Currently, the name |
18776 |
-+ * is even unique if linked but not activated, yet. This might |
18777 |
-+ * change in the future, though. Code should not rely on this. |
18778 |
-+ * |
18779 |
-+ * * node->lock: lock to protect node->children, node->rb, node->parent |
18780 |
-+ * * node->parent: Reference to parent node. This is set during LINK time |
18781 |
-+ * and is dropped during destruction. You must not access |
18782 |
-+ * it unless you hold an active reference to the node or if |
18783 |
-+ * you know the node is dead. |
18784 |
-+ * * node->children: rb-tree of all linked children of this node. You must |
18785 |
-+ * not access this directly, but use one of the iterator |
18786 |
-+ * or lookup helpers. |
18787 |
-+ */ |
18788 |
-+ |
18789 |
-+/* |
18790 |
-+ * Bias values track states of "active references". They're all negative. If a |
18791 |
-+ * node is active, its active-ref-counter is >=0 and tracks all active |
18792 |
-+ * references. Once a node is deactivaed, we subtract NODE_BIAS. This means, the |
18793 |
-+ * counter is now negative but still counts the active references. Once it drops |
18794 |
-+ * to exactly NODE_BIAS, we know all active references were dropped. Exactly one |
18795 |
-+ * thread will change it to NODE_RELEASE now, perform cleanup and then put it |
18796 |
-+ * into NODE_DRAINED. Once drained, all other threads that tried deactivating |
18797 |
-+ * the node will now be woken up (thus, they wait until the node is fully done). |
18798 |
-+ * The initial state during node-setup is NODE_NEW. If a node is directly |
18799 |
-+ * deactivated without having ever been active, it is put into |
18800 |
-+ * NODE_RELEASE_DIRECT instead of NODE_BIAS. This tracks this one-bit state |
18801 |
-+ * across node-deactivation. The task putting it into NODE_RELEASE now knows |
18802 |
-+ * whether the node was active before or not. |
18803 |
-+ * |
18804 |
-+ * Some archs implement atomic_sub(v) with atomic_add(-v), so reserve INT_MIN |
18805 |
-+ * to avoid overflows if multiplied by -1. |
18806 |
-+ */ |
18807 |
-+#define KDBUS_NODE_BIAS (INT_MIN + 5) |
18808 |
-+#define KDBUS_NODE_RELEASE_DIRECT (KDBUS_NODE_BIAS - 1) |
18809 |
-+#define KDBUS_NODE_RELEASE (KDBUS_NODE_BIAS - 2) |
18810 |
-+#define KDBUS_NODE_DRAINED (KDBUS_NODE_BIAS - 3) |
18811 |
-+#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4) |
18812 |
-+ |
18813 |
-+/* global unique ID mapping for kdbus nodes */ |
18814 |
-+DEFINE_IDA(kdbus_node_ida); |
18815 |
-+ |
18816 |
-+/** |
18817 |
-+ * kdbus_node_name_hash() - hash a name |
18818 |
-+ * @name: The string to hash |
18819 |
-+ * |
18820 |
-+ * This computes the hash of @name. It is guaranteed to be in the range |
18821 |
-+ * [2..INT_MAX-1]. The values 1, 2 and INT_MAX are unused as they are reserved |
18822 |
-+ * for the filesystem code. |
18823 |
-+ * |
18824 |
-+ * Return: hash value of the passed string |
18825 |
-+ */ |
18826 |
-+static unsigned int kdbus_node_name_hash(const char *name) |
18827 |
-+{ |
18828 |
-+ unsigned int hash; |
18829 |
-+ |
18830 |
-+ /* reserve hash numbers 0, 1 and >=INT_MAX for magic directories */ |
18831 |
-+ hash = kdbus_strhash(name) & INT_MAX; |
18832 |
-+ if (hash < 2) |
18833 |
-+ hash += 2; |
18834 |
-+ if (hash >= INT_MAX) |
18835 |
-+ hash = INT_MAX - 1; |
18836 |
-+ |
18837 |
-+ return hash; |
18838 |
-+} |
18839 |
-+ |
18840 |
-+/** |
18841 |
-+ * kdbus_node_name_compare() - compare a name with a node's name |
18842 |
-+ * @hash: hash of the string to compare the node with |
18843 |
-+ * @name: name to compare the node with |
18844 |
-+ * @node: node to compare the name with |
18845 |
-+ * |
18846 |
-+ * Return: 0 if @name and @hash exactly match the information in @node, or |
18847 |
-+ * an integer less than or greater than zero if @name is found, respectively, |
18848 |
-+ * to be less than or be greater than the string stored in @node. |
18849 |
-+ */ |
18850 |
-+static int kdbus_node_name_compare(unsigned int hash, const char *name, |
18851 |
-+ const struct kdbus_node *node) |
18852 |
-+{ |
18853 |
-+ if (hash != node->hash) |
18854 |
-+ return hash - node->hash; |
18855 |
-+ |
18856 |
-+ return strcmp(name, node->name); |
18857 |
-+} |
18858 |
-+ |
18859 |
-+/** |
18860 |
-+ * kdbus_node_init() - initialize a kdbus_node |
18861 |
-+ * @node: Pointer to the node to initialize |
18862 |
-+ * @type: The type the node will have (KDBUS_NODE_*) |
18863 |
-+ * |
18864 |
-+ * The caller is responsible of allocating @node and initializating it to zero. |
18865 |
-+ * Once this call returns, you must use the node_ref() and node_unref() |
18866 |
-+ * functions to manage this node. |
18867 |
-+ */ |
18868 |
-+void kdbus_node_init(struct kdbus_node *node, unsigned int type) |
18869 |
-+{ |
18870 |
-+ atomic_set(&node->refcnt, 1); |
18871 |
-+ mutex_init(&node->lock); |
18872 |
-+ node->id = 0; |
18873 |
-+ node->type = type; |
18874 |
-+ RB_CLEAR_NODE(&node->rb); |
18875 |
-+ node->children = RB_ROOT; |
18876 |
-+ init_waitqueue_head(&node->waitq); |
18877 |
-+ atomic_set(&node->active, KDBUS_NODE_NEW); |
18878 |
-+} |
18879 |
-+ |
18880 |
-+/** |
18881 |
-+ * kdbus_node_link() - link a node into the nodes system |
18882 |
-+ * @node: Pointer to the node to initialize |
18883 |
-+ * @parent: Pointer to a parent node, may be %NULL |
18884 |
-+ * @name: The name of the node (or NULL if root node) |
18885 |
-+ * |
18886 |
-+ * This links a node into the hierarchy. This must not be called multiple times. |
18887 |
-+ * If @parent is NULL, the node becomes a new root node. |
18888 |
-+ * |
18889 |
-+ * This call will fail if @name is not unique across all its siblings or if no |
18890 |
-+ * ID could be allocated. You must not activate a node if linking failed! It is |
18891 |
-+ * safe to deactivate it, though. |
18892 |
-+ * |
18893 |
-+ * Once you linked a node, you must call kdbus_node_deactivate() before you drop |
18894 |
-+ * the last reference (even if you never activate the node). |
18895 |
-+ * |
18896 |
-+ * Return: 0 on success. negative error otherwise. |
18897 |
-+ */ |
18898 |
-+int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, |
18899 |
-+ const char *name) |
18900 |
-+{ |
18901 |
-+ int ret; |
18902 |
-+ |
18903 |
-+ if (WARN_ON(node->type != KDBUS_NODE_DOMAIN && !parent)) |
18904 |
-+ return -EINVAL; |
18905 |
-+ |
18906 |
-+ if (WARN_ON(parent && !name)) |
18907 |
-+ return -EINVAL; |
18908 |
-+ |
18909 |
-+ if (name) { |
18910 |
-+ node->name = kstrdup(name, GFP_KERNEL); |
18911 |
-+ if (!node->name) |
18912 |
-+ return -ENOMEM; |
18913 |
-+ |
18914 |
-+ node->hash = kdbus_node_name_hash(name); |
18915 |
-+ } |
18916 |
-+ |
18917 |
-+ ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL); |
18918 |
-+ if (ret < 0) |
18919 |
-+ return ret; |
18920 |
-+ |
18921 |
-+ node->id = ret; |
18922 |
-+ ret = 0; |
18923 |
-+ |
18924 |
-+ if (parent) { |
18925 |
-+ struct rb_node **n, *prev; |
18926 |
-+ |
18927 |
-+ if (!kdbus_node_acquire(parent)) |
18928 |
-+ return -ESHUTDOWN; |
18929 |
-+ |
18930 |
-+ mutex_lock(&parent->lock); |
18931 |
-+ |
18932 |
-+ n = &parent->children.rb_node; |
18933 |
-+ prev = NULL; |
18934 |
-+ |
18935 |
-+ while (*n) { |
18936 |
-+ struct kdbus_node *pos; |
18937 |
-+ int result; |
18938 |
-+ |
18939 |
-+ pos = kdbus_node_from_rb(*n); |
18940 |
-+ prev = *n; |
18941 |
-+ result = kdbus_node_name_compare(node->hash, |
18942 |
-+ node->name, |
18943 |
-+ pos); |
18944 |
-+ if (result == 0) { |
18945 |
-+ ret = -EEXIST; |
18946 |
-+ goto exit_unlock; |
18947 |
-+ } |
18948 |
-+ |
18949 |
-+ if (result < 0) |
18950 |
-+ n = &pos->rb.rb_left; |
18951 |
-+ else |
18952 |
-+ n = &pos->rb.rb_right; |
18953 |
-+ } |
18954 |
-+ |
18955 |
-+ /* add new node and rebalance the tree */ |
18956 |
-+ rb_link_node(&node->rb, prev, n); |
18957 |
-+ rb_insert_color(&node->rb, &parent->children); |
18958 |
-+ node->parent = kdbus_node_ref(parent); |
18959 |
-+ |
18960 |
-+exit_unlock: |
18961 |
-+ mutex_unlock(&parent->lock); |
18962 |
-+ kdbus_node_release(parent); |
18963 |
-+ } |
18964 |
-+ |
18965 |
-+ return ret; |
18966 |
-+} |
18967 |
-+ |
18968 |
-+/** |
18969 |
-+ * kdbus_node_ref() - Acquire object reference |
18970 |
-+ * @node: node to acquire reference to (or NULL) |
18971 |
-+ * |
18972 |
-+ * This acquires a new reference to @node. You must already own a reference when |
18973 |
-+ * calling this! |
18974 |
-+ * If @node is NULL, this is a no-op. |
18975 |
-+ * |
18976 |
-+ * Return: @node is returned |
18977 |
-+ */ |
18978 |
-+struct kdbus_node *kdbus_node_ref(struct kdbus_node *node) |
18979 |
-+{ |
18980 |
-+ if (node) |
18981 |
-+ atomic_inc(&node->refcnt); |
18982 |
-+ return node; |
18983 |
-+} |
18984 |
-+ |
18985 |
-+/** |
18986 |
-+ * kdbus_node_unref() - Drop object reference |
18987 |
-+ * @node: node to drop reference to (or NULL) |
18988 |
-+ * |
18989 |
-+ * This drops an object reference to @node. You must not access the node if you |
18990 |
-+ * no longer own a reference. |
18991 |
-+ * If the ref-count drops to 0, the object will be destroyed (->free_cb will be |
18992 |
-+ * called). |
18993 |
-+ * |
18994 |
-+ * If you linked or activated the node, you must deactivate the node before you |
18995 |
-+ * drop your last reference! If you didn't link or activate the node, you can |
18996 |
-+ * drop any reference you want. |
18997 |
-+ * |
18998 |
-+ * Note that this calls into ->free_cb() and thus _might_ sleep. The ->free_cb() |
18999 |
-+ * callbacks must not acquire any outer locks, though. So you can safely drop |
19000 |
-+ * references while holding locks. |
19001 |
-+ * |
19002 |
-+ * If @node is NULL, this is a no-op. |
19003 |
-+ * |
19004 |
-+ * Return: This always returns NULL |
19005 |
-+ */ |
19006 |
-+struct kdbus_node *kdbus_node_unref(struct kdbus_node *node) |
19007 |
-+{ |
19008 |
-+ if (node && atomic_dec_and_test(&node->refcnt)) { |
19009 |
-+ struct kdbus_node safe = *node; |
19010 |
-+ |
19011 |
-+ WARN_ON(atomic_read(&node->active) != KDBUS_NODE_DRAINED); |
19012 |
-+ WARN_ON(!RB_EMPTY_NODE(&node->rb)); |
19013 |
-+ |
19014 |
-+ if (node->free_cb) |
19015 |
-+ node->free_cb(node); |
19016 |
-+ if (safe.id > 0) |
19017 |
-+ ida_simple_remove(&kdbus_node_ida, safe.id); |
19018 |
-+ |
19019 |
-+ kfree(safe.name); |
19020 |
-+ |
19021 |
-+ /* |
19022 |
-+ * kdbusfs relies on the parent to be available even after the |
19023 |
-+ * node was deactivated and unlinked. Therefore, we pin it |
19024 |
-+ * until a node is destroyed. |
19025 |
-+ */ |
19026 |
-+ kdbus_node_unref(safe.parent); |
19027 |
-+ } |
19028 |
-+ |
19029 |
-+ return NULL; |
19030 |
-+} |
19031 |
-+ |
19032 |
-+/** |
19033 |
-+ * kdbus_node_is_active() - test whether a node is active |
19034 |
-+ * @node: node to test |
19035 |
-+ * |
19036 |
-+ * This checks whether @node is active. That means, @node was linked and |
19037 |
-+ * activated by the node owner and hasn't been deactivated, yet. If, and only |
19038 |
-+ * if, a node is active, kdbus_node_acquire() will be able to acquire active |
19039 |
-+ * references. |
19040 |
-+ * |
19041 |
-+ * Note that this function does not give any lifetime guarantees. After this |
19042 |
-+ * call returns, the node might be deactivated immediately. Normally, what you |
19043 |
-+ * want is to acquire a real active reference via kdbus_node_acquire(). |
19044 |
-+ * |
19045 |
-+ * Return: true if @node is active, false otherwise |
19046 |
-+ */ |
19047 |
-+bool kdbus_node_is_active(struct kdbus_node *node) |
19048 |
-+{ |
19049 |
-+ return atomic_read(&node->active) >= 0; |
19050 |
-+} |
19051 |
-+ |
19052 |
-+/** |
19053 |
-+ * kdbus_node_is_deactivated() - test whether a node was already deactivated |
19054 |
-+ * @node: node to test |
19055 |
-+ * |
19056 |
-+ * This checks whether kdbus_node_deactivate() was called on @node. Note that |
19057 |
-+ * this might be true even if you never deactivated the node directly, but only |
19058 |
-+ * one of its ancestors. |
19059 |
-+ * |
19060 |
-+ * Note that even if this returns 'false', the node might get deactivated |
19061 |
-+ * immediately after the call returns. |
19062 |
-+ * |
19063 |
-+ * Return: true if @node was already deactivated, false if not |
19064 |
-+ */ |
19065 |
-+bool kdbus_node_is_deactivated(struct kdbus_node *node) |
19066 |
-+{ |
19067 |
-+ int v; |
19068 |
-+ |
19069 |
-+ v = atomic_read(&node->active); |
19070 |
-+ return v != KDBUS_NODE_NEW && v < 0; |
19071 |
-+} |
19072 |
-+ |
19073 |
-+/** |
19074 |
-+ * kdbus_node_activate() - activate a node |
19075 |
-+ * @node: node to activate |
19076 |
-+ * |
19077 |
-+ * This marks @node as active if, and only if, the node wasn't activated nor |
19078 |
-+ * deactivated, yet, and the parent is still active. Any but the first call to |
19079 |
-+ * kdbus_node_activate() is a no-op. |
19080 |
-+ * If you called kdbus_node_deactivate() before, then even the first call to |
19081 |
-+ * kdbus_node_activate() will be a no-op. |
19082 |
-+ * |
19083 |
-+ * This call doesn't give any lifetime guarantees. The node might get |
19084 |
-+ * deactivated immediately after this call returns. Or the parent might already |
19085 |
-+ * be deactivated, which will make this call a no-op. |
19086 |
-+ * |
19087 |
-+ * If this call successfully activated a node, it will take an object reference |
19088 |
-+ * to it. This reference is dropped after the node is deactivated. Therefore, |
19089 |
-+ * the object owner can safely drop their reference to @node iff they know that |
19090 |
-+ * its parent node will get deactivated at some point. Once the parent node is |
19091 |
-+ * deactivated, it will deactivate all its child and thus drop this reference |
19092 |
-+ * again. |
19093 |
-+ * |
19094 |
-+ * Return: True if this call successfully activated the node, otherwise false. |
19095 |
-+ * Note that this might return false, even if the node is still active |
19096 |
-+ * (eg., if you called this a second time). |
19097 |
-+ */ |
19098 |
-+bool kdbus_node_activate(struct kdbus_node *node) |
19099 |
-+{ |
19100 |
-+ bool res = false; |
19101 |
-+ |
19102 |
-+ mutex_lock(&node->lock); |
19103 |
-+ if (atomic_read(&node->active) == KDBUS_NODE_NEW) { |
19104 |
-+ atomic_sub(KDBUS_NODE_NEW, &node->active); |
19105 |
-+ /* activated nodes have ref +1 */ |
19106 |
-+ kdbus_node_ref(node); |
19107 |
-+ res = true; |
19108 |
-+ } |
19109 |
-+ mutex_unlock(&node->lock); |
19110 |
-+ |
19111 |
-+ return res; |
19112 |
-+} |
19113 |
-+ |
19114 |
-+/** |
19115 |
-+ * kdbus_node_deactivate() - deactivate a node |
19116 |
-+ * @node: The node to deactivate. |
19117 |
-+ * |
19118 |
-+ * This function recursively deactivates this node and all its children. It |
19119 |
-+ * returns only once all children and the node itself were recursively disabled |
19120 |
-+ * (even if you call this function multiple times in parallel). |
19121 |
-+ * |
19122 |
-+ * It is safe to call this function on _any_ node that was initialized _any_ |
19123 |
-+ * number of times. |
19124 |
-+ * |
19125 |
-+ * This call may sleep, as it waits for all active references to be dropped. |
19126 |
-+ */ |
19127 |
-+void kdbus_node_deactivate(struct kdbus_node *node) |
19128 |
-+{ |
19129 |
-+ struct kdbus_node *pos, *child; |
19130 |
-+ struct rb_node *rb; |
19131 |
-+ int v_pre, v_post; |
19132 |
-+ |
19133 |
-+ pos = node; |
19134 |
-+ |
19135 |
-+ /* |
19136 |
-+ * To avoid recursion, we perform back-tracking while deactivating |
19137 |
-+ * nodes. For each node we enter, we first mark the active-counter as |
19138 |
-+ * deactivated by adding BIAS. If the node as children, we set the first |
19139 |
-+ * child as current position and start over. If the node has no |
19140 |
-+ * children, we drain the node by waiting for all active refs to be |
19141 |
-+ * dropped and then releasing the node. |
19142 |
-+ * |
19143 |
-+ * After the node is released, we set its parent as current position |
19144 |
-+ * and start over. If the current position was the initial node, we're |
19145 |
-+ * done. |
19146 |
-+ * |
19147 |
-+ * Note that this function can be called in parallel by multiple |
19148 |
-+ * callers. We make sure that each node is only released once, and any |
19149 |
-+ * racing caller will wait until the other thread fully released that |
19150 |
-+ * node. |
19151 |
-+ */ |
19152 |
-+ |
19153 |
-+ for (;;) { |
19154 |
-+ /* |
19155 |
-+ * Add BIAS to node->active to mark it as inactive. If it was |
19156 |
-+ * never active before, immediately mark it as RELEASE_INACTIVE |
19157 |
-+ * so we remember this state. |
19158 |
-+ * We cannot remember v_pre as we might iterate into the |
19159 |
-+ * children, overwriting v_pre, before we can release our node. |
19160 |
-+ */ |
19161 |
-+ mutex_lock(&pos->lock); |
19162 |
-+ v_pre = atomic_read(&pos->active); |
19163 |
-+ if (v_pre >= 0) |
19164 |
-+ atomic_add_return(KDBUS_NODE_BIAS, &pos->active); |
19165 |
-+ else if (v_pre == KDBUS_NODE_NEW) |
19166 |
-+ atomic_set(&pos->active, KDBUS_NODE_RELEASE_DIRECT); |
19167 |
-+ mutex_unlock(&pos->lock); |
19168 |
-+ |
19169 |
-+ /* wait until all active references were dropped */ |
19170 |
-+ wait_event(pos->waitq, |
19171 |
-+ atomic_read(&pos->active) <= KDBUS_NODE_BIAS); |
19172 |
-+ |
19173 |
-+ mutex_lock(&pos->lock); |
19174 |
-+ /* recurse into first child if any */ |
19175 |
-+ rb = rb_first(&pos->children); |
19176 |
-+ if (rb) { |
19177 |
-+ child = kdbus_node_ref(kdbus_node_from_rb(rb)); |
19178 |
-+ mutex_unlock(&pos->lock); |
19179 |
-+ pos = child; |
19180 |
-+ continue; |
19181 |
-+ } |
19182 |
-+ |
19183 |
-+ /* mark object as RELEASE */ |
19184 |
-+ v_post = atomic_read(&pos->active); |
19185 |
-+ if (v_post == KDBUS_NODE_BIAS || |
19186 |
-+ v_post == KDBUS_NODE_RELEASE_DIRECT) |
19187 |
-+ atomic_set(&pos->active, KDBUS_NODE_RELEASE); |
19188 |
-+ mutex_unlock(&pos->lock); |
19189 |
-+ |
19190 |
-+ /* |
19191 |
-+ * If this is the thread that marked the object as RELEASE, we |
19192 |
-+ * perform the actual release. Otherwise, we wait until the |
19193 |
-+ * release is done and the node is marked as DRAINED. |
19194 |
-+ */ |
19195 |
-+ if (v_post == KDBUS_NODE_BIAS || |
19196 |
-+ v_post == KDBUS_NODE_RELEASE_DIRECT) { |
19197 |
-+ if (pos->release_cb) |
19198 |
-+ pos->release_cb(pos, v_post == KDBUS_NODE_BIAS); |
19199 |
-+ |
19200 |
-+ if (pos->parent) { |
19201 |
-+ mutex_lock(&pos->parent->lock); |
19202 |
-+ if (!RB_EMPTY_NODE(&pos->rb)) { |
19203 |
-+ rb_erase(&pos->rb, |
19204 |
-+ &pos->parent->children); |
19205 |
-+ RB_CLEAR_NODE(&pos->rb); |
19206 |
-+ } |
19207 |
-+ mutex_unlock(&pos->parent->lock); |
19208 |
-+ } |
19209 |
-+ |
19210 |
-+ /* mark as DRAINED */ |
19211 |
-+ atomic_set(&pos->active, KDBUS_NODE_DRAINED); |
19212 |
-+ wake_up_all(&pos->waitq); |
19213 |
-+ |
19214 |
-+ /* drop VFS cache */ |
19215 |
-+ kdbus_fs_flush(pos); |
19216 |
-+ |
19217 |
-+ /* |
19218 |
-+ * If the node was activated and someone subtracted BIAS |
19219 |
-+ * from it to deactivate it, we, and only us, are |
19220 |
-+ * responsible to release the extra ref-count that was |
19221 |
-+ * taken once in kdbus_node_activate(). |
19222 |
-+ * If the node was never activated, no-one ever |
19223 |
-+ * subtracted BIAS, but instead skipped that state and |
19224 |
-+ * immediately went to NODE_RELEASE_DIRECT. In that case |
19225 |
-+ * we must not drop the reference. |
19226 |
-+ */ |
19227 |
-+ if (v_post == KDBUS_NODE_BIAS) |
19228 |
-+ kdbus_node_unref(pos); |
19229 |
-+ } else { |
19230 |
-+ /* wait until object is DRAINED */ |
19231 |
-+ wait_event(pos->waitq, |
19232 |
-+ atomic_read(&pos->active) == KDBUS_NODE_DRAINED); |
19233 |
-+ } |
19234 |
-+ |
19235 |
-+ /* |
19236 |
-+ * We're done with the current node. Continue on its parent |
19237 |
-+ * again, which will try deactivating its next child, or itself |
19238 |
-+ * if no child is left. |
19239 |
-+ * If we've reached our initial node again, we are done and |
19240 |
-+ * can safely return. |
19241 |
-+ */ |
19242 |
-+ if (pos == node) |
19243 |
-+ break; |
19244 |
-+ |
19245 |
-+ child = pos; |
19246 |
-+ pos = pos->parent; |
19247 |
-+ kdbus_node_unref(child); |
19248 |
-+ } |
19249 |
-+} |
19250 |
-+ |
19251 |
-+/** |
19252 |
-+ * kdbus_node_acquire() - Acquire an active ref on a node |
19253 |
-+ * @node: The node |
19254 |
-+ * |
19255 |
-+ * This acquires an active-reference to @node. This will only succeed if the |
19256 |
-+ * node is active. You must release this active reference via |
19257 |
-+ * kdbus_node_release() again. |
19258 |
-+ * |
19259 |
-+ * See the introduction to "active references" for more details. |
19260 |
-+ * |
19261 |
-+ * Return: %true if @node was non-NULL and active |
19262 |
-+ */ |
19263 |
-+bool kdbus_node_acquire(struct kdbus_node *node) |
19264 |
-+{ |
19265 |
-+ return node && atomic_inc_unless_negative(&node->active); |
19266 |
-+} |
19267 |
-+ |
19268 |
-+/** |
19269 |
-+ * kdbus_node_release() - Release an active ref on a node |
19270 |
-+ * @node: The node |
19271 |
-+ * |
19272 |
-+ * This releases an active reference that was previously acquired via |
19273 |
-+ * kdbus_node_acquire(). See kdbus_node_acquire() for details. |
19274 |
-+ */ |
19275 |
-+void kdbus_node_release(struct kdbus_node *node) |
19276 |
-+{ |
19277 |
-+ if (node && atomic_dec_return(&node->active) == KDBUS_NODE_BIAS) |
19278 |
-+ wake_up(&node->waitq); |
19279 |
-+} |
19280 |
-+ |
19281 |
-+/** |
19282 |
-+ * kdbus_node_find_child() - Find child by name |
19283 |
-+ * @node: parent node to search through |
19284 |
-+ * @name: name of child node |
19285 |
-+ * |
19286 |
-+ * This searches through all children of @node for a child-node with name @name. |
19287 |
-+ * If not found, or if the child is deactivated, NULL is returned. Otherwise, |
19288 |
-+ * the child is acquired and a new reference is returned. |
19289 |
-+ * |
19290 |
-+ * If you're done with the child, you need to release it and drop your |
19291 |
-+ * reference. |
19292 |
-+ * |
19293 |
-+ * This function does not acquire the parent node. However, if the parent was |
19294 |
-+ * already deactivated, then kdbus_node_deactivate() will, at some point, also |
19295 |
-+ * deactivate the child. Therefore, we can rely on the explicit ordering during |
19296 |
-+ * deactivation. |
19297 |
-+ * |
19298 |
-+ * Return: Reference to acquired child node, or NULL if not found / not active. |
19299 |
-+ */ |
19300 |
-+struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, |
19301 |
-+ const char *name) |
19302 |
-+{ |
19303 |
-+ struct kdbus_node *child; |
19304 |
-+ struct rb_node *rb; |
19305 |
-+ unsigned int hash; |
19306 |
-+ int ret; |
19307 |
-+ |
19308 |
-+ hash = kdbus_node_name_hash(name); |
19309 |
-+ |
19310 |
-+ mutex_lock(&node->lock); |
19311 |
-+ rb = node->children.rb_node; |
19312 |
-+ while (rb) { |
19313 |
-+ child = kdbus_node_from_rb(rb); |
19314 |
-+ ret = kdbus_node_name_compare(hash, name, child); |
19315 |
-+ if (ret < 0) |
19316 |
-+ rb = rb->rb_left; |
19317 |
-+ else if (ret > 0) |
19318 |
-+ rb = rb->rb_right; |
19319 |
-+ else |
19320 |
-+ break; |
19321 |
-+ } |
19322 |
-+ if (rb && kdbus_node_acquire(child)) |
19323 |
-+ kdbus_node_ref(child); |
19324 |
-+ else |
19325 |
-+ child = NULL; |
19326 |
-+ mutex_unlock(&node->lock); |
19327 |
-+ |
19328 |
-+ return child; |
19329 |
-+} |
19330 |
-+ |
19331 |
-+static struct kdbus_node *node_find_closest_unlocked(struct kdbus_node *node, |
19332 |
-+ unsigned int hash, |
19333 |
-+ const char *name) |
19334 |
-+{ |
19335 |
-+ struct kdbus_node *n, *pos = NULL; |
19336 |
-+ struct rb_node *rb; |
19337 |
-+ int res; |
19338 |
-+ |
19339 |
-+ /* |
19340 |
-+ * Find the closest child with ``node->hash >= hash'', or, if @name is |
19341 |
-+ * valid, ``node->name >= name'' (where '>=' is the lex. order). |
19342 |
-+ */ |
19343 |
-+ |
19344 |
-+ rb = node->children.rb_node; |
19345 |
-+ while (rb) { |
19346 |
-+ n = kdbus_node_from_rb(rb); |
19347 |
-+ |
19348 |
-+ if (name) |
19349 |
-+ res = kdbus_node_name_compare(hash, name, n); |
19350 |
-+ else |
19351 |
-+ res = hash - n->hash; |
19352 |
-+ |
19353 |
-+ if (res <= 0) { |
19354 |
-+ rb = rb->rb_left; |
19355 |
-+ pos = n; |
19356 |
-+ } else { /* ``hash > n->hash'', ``name > n->name'' */ |
19357 |
-+ rb = rb->rb_right; |
19358 |
-+ } |
19359 |
-+ } |
19360 |
-+ |
19361 |
-+ return pos; |
19362 |
-+} |
19363 |
-+ |
19364 |
-+/** |
19365 |
-+ * kdbus_node_find_closest() - Find closest child-match |
19366 |
-+ * @node: parent node to search through |
19367 |
-+ * @hash: hash value to find closest match for |
19368 |
-+ * |
19369 |
-+ * Find the closest child of @node with a hash greater than or equal to @hash. |
19370 |
-+ * The closest match is the left-most child of @node with this property. Which |
19371 |
-+ * means, it is the first child with that hash returned by |
19372 |
-+ * kdbus_node_next_child(), if you'd iterate the whole parent node. |
19373 |
-+ * |
19374 |
-+ * Return: Reference to acquired child, or NULL if none found. |
19375 |
-+ */ |
19376 |
-+struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, |
19377 |
-+ unsigned int hash) |
19378 |
-+{ |
19379 |
-+ struct kdbus_node *child; |
19380 |
-+ struct rb_node *rb; |
19381 |
-+ |
19382 |
-+ mutex_lock(&node->lock); |
19383 |
-+ |
19384 |
-+ child = node_find_closest_unlocked(node, hash, NULL); |
19385 |
-+ while (child && !kdbus_node_acquire(child)) { |
19386 |
-+ rb = rb_next(&child->rb); |
19387 |
-+ if (rb) |
19388 |
-+ child = kdbus_node_from_rb(rb); |
19389 |
-+ else |
19390 |
-+ child = NULL; |
19391 |
-+ } |
19392 |
-+ kdbus_node_ref(child); |
19393 |
-+ |
19394 |
-+ mutex_unlock(&node->lock); |
19395 |
-+ |
19396 |
-+ return child; |
19397 |
-+} |
19398 |
-+ |
19399 |
-+/** |
19400 |
-+ * kdbus_node_next_child() - Acquire next child |
19401 |
-+ * @node: parent node |
19402 |
-+ * @prev: previous child-node position or NULL |
19403 |
-+ * |
19404 |
-+ * This function returns a reference to the next active child of @node, after |
19405 |
-+ * the passed position @prev. If @prev is NULL, a reference to the first active |
19406 |
-+ * child is returned. If no more active children are found, NULL is returned. |
19407 |
-+ * |
19408 |
-+ * This function acquires the next child it returns. If you're done with the |
19409 |
-+ * returned pointer, you need to release _and_ unref it. |
19410 |
-+ * |
19411 |
-+ * The passed in pointer @prev is not modified by this function, and it does |
19412 |
-+ * *not* have to be active. If @prev was acquired via different means, or if it |
19413 |
-+ * was unlinked from its parent before you pass it in, then this iterator will |
19414 |
-+ * still return the next active child (it will have to search through the |
19415 |
-+ * rb-tree based on the node-name, though). |
19416 |
-+ * However, @prev must not be linked to a different parent than @node! |
19417 |
-+ * |
19418 |
-+ * Return: Reference to next acquired child, or NULL if at the end. |
19419 |
-+ */ |
19420 |
-+struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, |
19421 |
-+ struct kdbus_node *prev) |
19422 |
-+{ |
19423 |
-+ struct kdbus_node *pos = NULL; |
19424 |
-+ struct rb_node *rb; |
19425 |
-+ |
19426 |
-+ mutex_lock(&node->lock); |
19427 |
-+ |
19428 |
-+ if (!prev) { |
19429 |
-+ /* |
19430 |
-+ * New iteration; find first node in rb-tree and try to acquire |
19431 |
-+ * it. If we got it, directly return it as first element. |
19432 |
-+ * Otherwise, the loop below will find the next active node. |
19433 |
-+ */ |
19434 |
-+ rb = rb_first(&node->children); |
19435 |
-+ if (!rb) |
19436 |
-+ goto exit; |
19437 |
-+ pos = kdbus_node_from_rb(rb); |
19438 |
-+ if (kdbus_node_acquire(pos)) |
19439 |
-+ goto exit; |
19440 |
-+ } else if (RB_EMPTY_NODE(&prev->rb)) { |
19441 |
-+ /* |
19442 |
-+ * The current iterator is no longer linked to the rb-tree. Use |
19443 |
-+ * its hash value and name to find the next _higher_ node and |
19444 |
-+ * acquire it. If we got it, return it as next element. |
19445 |
-+ * Otherwise, the loop below will find the next active node. |
19446 |
-+ */ |
19447 |
-+ pos = node_find_closest_unlocked(node, prev->hash, prev->name); |
19448 |
-+ if (!pos) |
19449 |
-+ goto exit; |
19450 |
-+ if (kdbus_node_acquire(pos)) |
19451 |
-+ goto exit; |
19452 |
-+ } else { |
19453 |
-+ /* |
19454 |
-+ * The current iterator is still linked to the parent. Set it |
19455 |
-+ * as current position and use the loop below to find the next |
19456 |
-+ * active element. |
19457 |
-+ */ |
19458 |
-+ pos = prev; |
19459 |
-+ } |
19460 |
-+ |
19461 |
-+ /* @pos was already returned or is inactive; find next active node */ |
19462 |
-+ do { |
19463 |
-+ rb = rb_next(&pos->rb); |
19464 |
-+ if (rb) |
19465 |
-+ pos = kdbus_node_from_rb(rb); |
19466 |
-+ else |
19467 |
-+ pos = NULL; |
19468 |
-+ } while (pos && !kdbus_node_acquire(pos)); |
19469 |
-+ |
19470 |
-+exit: |
19471 |
-+ /* @pos is NULL or acquired. Take ref if non-NULL and return it */ |
19472 |
-+ kdbus_node_ref(pos); |
19473 |
-+ mutex_unlock(&node->lock); |
19474 |
-+ return pos; |
19475 |
-+} |
19476 |
-diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h |
19477 |
-new file mode 100644 |
19478 |
-index 0000000..970e02b |
19479 |
---- /dev/null |
19480 |
-+++ b/ipc/kdbus/node.h |
19481 |
-@@ -0,0 +1,86 @@ |
19482 |
-+/* |
19483 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19484 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19485 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19486 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19487 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19488 |
-+ * |
19489 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19490 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19491 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19492 |
-+ * your option) any later version. |
19493 |
-+ */ |
19494 |
-+ |
19495 |
-+#ifndef __KDBUS_NODE_H |
19496 |
-+#define __KDBUS_NODE_H |
19497 |
-+ |
19498 |
-+#include <linux/atomic.h> |
19499 |
-+#include <linux/kernel.h> |
19500 |
-+#include <linux/mutex.h> |
19501 |
-+#include <linux/wait.h> |
19502 |
-+ |
19503 |
-+struct kdbus_node; |
19504 |
-+ |
19505 |
-+enum kdbus_node_type { |
19506 |
-+ KDBUS_NODE_DOMAIN, |
19507 |
-+ KDBUS_NODE_CONTROL, |
19508 |
-+ KDBUS_NODE_BUS, |
19509 |
-+ KDBUS_NODE_ENDPOINT, |
19510 |
-+}; |
19511 |
-+ |
19512 |
-+typedef void (*kdbus_node_free_t) (struct kdbus_node *node); |
19513 |
-+typedef void (*kdbus_node_release_t) (struct kdbus_node *node, bool was_active); |
19514 |
-+ |
19515 |
-+struct kdbus_node { |
19516 |
-+ atomic_t refcnt; |
19517 |
-+ atomic_t active; |
19518 |
-+ wait_queue_head_t waitq; |
19519 |
-+ |
19520 |
-+ /* static members */ |
19521 |
-+ unsigned int type; |
19522 |
-+ kdbus_node_free_t free_cb; |
19523 |
-+ kdbus_node_release_t release_cb; |
19524 |
-+ umode_t mode; |
19525 |
-+ kuid_t uid; |
19526 |
-+ kgid_t gid; |
19527 |
-+ |
19528 |
-+ /* valid once linked */ |
19529 |
-+ char *name; |
19530 |
-+ unsigned int hash; |
19531 |
-+ unsigned int id; |
19532 |
-+ struct kdbus_node *parent; /* may be NULL */ |
19533 |
-+ |
19534 |
-+ /* valid iff active */ |
19535 |
-+ struct mutex lock; |
19536 |
-+ struct rb_node rb; |
19537 |
-+ struct rb_root children; |
19538 |
-+}; |
19539 |
-+ |
19540 |
-+#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb) |
19541 |
-+ |
19542 |
-+extern struct ida kdbus_node_ida; |
19543 |
-+ |
19544 |
-+void kdbus_node_init(struct kdbus_node *node, unsigned int type); |
19545 |
-+ |
19546 |
-+int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, |
19547 |
-+ const char *name); |
19548 |
-+ |
19549 |
-+struct kdbus_node *kdbus_node_ref(struct kdbus_node *node); |
19550 |
-+struct kdbus_node *kdbus_node_unref(struct kdbus_node *node); |
19551 |
-+ |
19552 |
-+bool kdbus_node_is_active(struct kdbus_node *node); |
19553 |
-+bool kdbus_node_is_deactivated(struct kdbus_node *node); |
19554 |
-+bool kdbus_node_activate(struct kdbus_node *node); |
19555 |
-+void kdbus_node_deactivate(struct kdbus_node *node); |
19556 |
-+ |
19557 |
-+bool kdbus_node_acquire(struct kdbus_node *node); |
19558 |
-+void kdbus_node_release(struct kdbus_node *node); |
19559 |
-+ |
19560 |
-+struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, |
19561 |
-+ const char *name); |
19562 |
-+struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, |
19563 |
-+ unsigned int hash); |
19564 |
-+struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, |
19565 |
-+ struct kdbus_node *prev); |
19566 |
-+ |
19567 |
-+#endif |
19568 |
-diff --git a/ipc/kdbus/notify.c b/ipc/kdbus/notify.c |
19569 |
-new file mode 100644 |
19570 |
-index 0000000..375758c |
19571 |
---- /dev/null |
19572 |
-+++ b/ipc/kdbus/notify.c |
19573 |
-@@ -0,0 +1,204 @@ |
19574 |
-+/* |
19575 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19576 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19577 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19578 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19579 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19580 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
19581 |
-+ * |
19582 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19583 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19584 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19585 |
-+ * your option) any later version. |
19586 |
-+ */ |
19587 |
-+ |
19588 |
-+#include <linux/fs.h> |
19589 |
-+#include <linux/init.h> |
19590 |
-+#include <linux/module.h> |
19591 |
-+#include <linux/mutex.h> |
19592 |
-+#include <linux/spinlock.h> |
19593 |
-+#include <linux/sched.h> |
19594 |
-+#include <linux/slab.h> |
19595 |
-+ |
19596 |
-+#include "bus.h" |
19597 |
-+#include "connection.h" |
19598 |
-+#include "domain.h" |
19599 |
-+#include "endpoint.h" |
19600 |
-+#include "item.h" |
19601 |
-+#include "message.h" |
19602 |
-+#include "notify.h" |
19603 |
-+ |
19604 |
-+static inline void kdbus_notify_add_tail(struct kdbus_staging *staging, |
19605 |
-+ struct kdbus_bus *bus) |
19606 |
-+{ |
19607 |
-+ spin_lock(&bus->notify_lock); |
19608 |
-+ list_add_tail(&staging->notify_entry, &bus->notify_list); |
19609 |
-+ spin_unlock(&bus->notify_lock); |
19610 |
-+} |
19611 |
-+ |
19612 |
-+static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id, |
19613 |
-+ u64 cookie, u64 msg_type) |
19614 |
-+{ |
19615 |
-+ struct kdbus_staging *s; |
19616 |
-+ |
19617 |
-+ s = kdbus_staging_new_kernel(bus, id, cookie, 0, msg_type); |
19618 |
-+ if (IS_ERR(s)) |
19619 |
-+ return PTR_ERR(s); |
19620 |
-+ |
19621 |
-+ kdbus_notify_add_tail(s, bus); |
19622 |
-+ return 0; |
19623 |
-+} |
19624 |
-+ |
19625 |
-+/** |
19626 |
-+ * kdbus_notify_reply_timeout() - queue a timeout reply |
19627 |
-+ * @bus: Bus which queues the messages |
19628 |
-+ * @id: The destination's connection ID |
19629 |
-+ * @cookie: The cookie to set in the reply. |
19630 |
-+ * |
19631 |
-+ * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached. |
19632 |
-+ * |
19633 |
-+ * Return: 0 on success, negative errno on failure. |
19634 |
-+ */ |
19635 |
-+int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie) |
19636 |
-+{ |
19637 |
-+ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT); |
19638 |
-+} |
19639 |
-+ |
19640 |
-+/** |
19641 |
-+ * kdbus_notify_reply_dead() - queue a 'dead' reply |
19642 |
-+ * @bus: Bus which queues the messages |
19643 |
-+ * @id: The destination's connection ID |
19644 |
-+ * @cookie: The cookie to set in the reply. |
19645 |
-+ * |
19646 |
-+ * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached. |
19647 |
-+ * |
19648 |
-+ * Return: 0 on success, negative errno on failure. |
19649 |
-+ */ |
19650 |
-+int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie) |
19651 |
-+{ |
19652 |
-+ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD); |
19653 |
-+} |
19654 |
-+ |
19655 |
-+/** |
19656 |
-+ * kdbus_notify_name_change() - queue a notification about a name owner change |
19657 |
-+ * @bus: Bus which queues the messages |
19658 |
-+ * @type: The type if the notification; KDBUS_ITEM_NAME_ADD, |
19659 |
-+ * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE |
19660 |
-+ * @old_id: The id of the connection that used to own the name |
19661 |
-+ * @new_id: The id of the new owner connection |
19662 |
-+ * @old_flags: The flags to pass in the KDBUS_ITEM flags field for |
19663 |
-+ * the old owner |
19664 |
-+ * @new_flags: The flags to pass in the KDBUS_ITEM flags field for |
19665 |
-+ * the new owner |
19666 |
-+ * @name: The name that was removed or assigned to a new owner |
19667 |
-+ * |
19668 |
-+ * Return: 0 on success, negative errno on failure. |
19669 |
-+ */ |
19670 |
-+int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, |
19671 |
-+ u64 old_id, u64 new_id, |
19672 |
-+ u64 old_flags, u64 new_flags, |
19673 |
-+ const char *name) |
19674 |
-+{ |
19675 |
-+ size_t name_len, extra_size; |
19676 |
-+ struct kdbus_staging *s; |
19677 |
-+ |
19678 |
-+ name_len = strlen(name) + 1; |
19679 |
-+ extra_size = sizeof(struct kdbus_notify_name_change) + name_len; |
19680 |
-+ |
19681 |
-+ s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0, |
19682 |
-+ extra_size, type); |
19683 |
-+ if (IS_ERR(s)) |
19684 |
-+ return PTR_ERR(s); |
19685 |
-+ |
19686 |
-+ s->notify->name_change.old_id.id = old_id; |
19687 |
-+ s->notify->name_change.old_id.flags = old_flags; |
19688 |
-+ s->notify->name_change.new_id.id = new_id; |
19689 |
-+ s->notify->name_change.new_id.flags = new_flags; |
19690 |
-+ memcpy(s->notify->name_change.name, name, name_len); |
19691 |
-+ |
19692 |
-+ kdbus_notify_add_tail(s, bus); |
19693 |
-+ return 0; |
19694 |
-+} |
19695 |
-+ |
19696 |
-+/** |
19697 |
-+ * kdbus_notify_id_change() - queue a notification about a unique ID change |
19698 |
-+ * @bus: Bus which queues the messages |
19699 |
-+ * @type: The type if the notification; KDBUS_ITEM_ID_ADD or |
19700 |
-+ * KDBUS_ITEM_ID_REMOVE |
19701 |
-+ * @id: The id of the connection that was added or removed |
19702 |
-+ * @flags: The flags to pass in the KDBUS_ITEM flags field |
19703 |
-+ * |
19704 |
-+ * Return: 0 on success, negative errno on failure. |
19705 |
-+ */ |
19706 |
-+int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags) |
19707 |
-+{ |
19708 |
-+ struct kdbus_staging *s; |
19709 |
-+ size_t extra_size; |
19710 |
-+ |
19711 |
-+ extra_size = sizeof(struct kdbus_notify_id_change); |
19712 |
-+ s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0, |
19713 |
-+ extra_size, type); |
19714 |
-+ if (IS_ERR(s)) |
19715 |
-+ return PTR_ERR(s); |
19716 |
-+ |
19717 |
-+ s->notify->id_change.id = id; |
19718 |
-+ s->notify->id_change.flags = flags; |
19719 |
-+ |
19720 |
-+ kdbus_notify_add_tail(s, bus); |
19721 |
-+ return 0; |
19722 |
-+} |
19723 |
-+ |
19724 |
-+/** |
19725 |
-+ * kdbus_notify_flush() - send a list of collected messages |
19726 |
-+ * @bus: Bus which queues the messages |
19727 |
-+ * |
19728 |
-+ * The list is empty after sending the messages. |
19729 |
-+ */ |
19730 |
-+void kdbus_notify_flush(struct kdbus_bus *bus) |
19731 |
-+{ |
19732 |
-+ LIST_HEAD(notify_list); |
19733 |
-+ struct kdbus_staging *s, *tmp; |
19734 |
-+ |
19735 |
-+ mutex_lock(&bus->notify_flush_lock); |
19736 |
-+ down_read(&bus->name_registry->rwlock); |
19737 |
-+ |
19738 |
-+ spin_lock(&bus->notify_lock); |
19739 |
-+ list_splice_init(&bus->notify_list, ¬ify_list); |
19740 |
-+ spin_unlock(&bus->notify_lock); |
19741 |
-+ |
19742 |
-+ list_for_each_entry_safe(s, tmp, ¬ify_list, notify_entry) { |
19743 |
-+ if (s->msg->dst_id != KDBUS_DST_ID_BROADCAST) { |
19744 |
-+ struct kdbus_conn *conn; |
19745 |
-+ |
19746 |
-+ conn = kdbus_bus_find_conn_by_id(bus, s->msg->dst_id); |
19747 |
-+ if (conn) { |
19748 |
-+ kdbus_bus_eavesdrop(bus, NULL, s); |
19749 |
-+ kdbus_conn_entry_insert(NULL, conn, s, NULL, |
19750 |
-+ NULL); |
19751 |
-+ kdbus_conn_unref(conn); |
19752 |
-+ } |
19753 |
-+ } else { |
19754 |
-+ kdbus_bus_broadcast(bus, NULL, s); |
19755 |
-+ } |
19756 |
-+ |
19757 |
-+ list_del(&s->notify_entry); |
19758 |
-+ kdbus_staging_free(s); |
19759 |
-+ } |
19760 |
-+ |
19761 |
-+ up_read(&bus->name_registry->rwlock); |
19762 |
-+ mutex_unlock(&bus->notify_flush_lock); |
19763 |
-+} |
19764 |
-+ |
19765 |
-+/** |
19766 |
-+ * kdbus_notify_free() - free a list of collected messages |
19767 |
-+ * @bus: Bus which queues the messages |
19768 |
-+ */ |
19769 |
-+void kdbus_notify_free(struct kdbus_bus *bus) |
19770 |
-+{ |
19771 |
-+ struct kdbus_staging *s, *tmp; |
19772 |
-+ |
19773 |
-+ list_for_each_entry_safe(s, tmp, &bus->notify_list, notify_entry) { |
19774 |
-+ list_del(&s->notify_entry); |
19775 |
-+ kdbus_staging_free(s); |
19776 |
-+ } |
19777 |
-+} |
19778 |
-diff --git a/ipc/kdbus/notify.h b/ipc/kdbus/notify.h |
19779 |
-new file mode 100644 |
19780 |
-index 0000000..03df464 |
19781 |
---- /dev/null |
19782 |
-+++ b/ipc/kdbus/notify.h |
19783 |
-@@ -0,0 +1,30 @@ |
19784 |
-+/* |
19785 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19786 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19787 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19788 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19789 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19790 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
19791 |
-+ * |
19792 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19793 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19794 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19795 |
-+ * your option) any later version. |
19796 |
-+ */ |
19797 |
-+ |
19798 |
-+#ifndef __KDBUS_NOTIFY_H |
19799 |
-+#define __KDBUS_NOTIFY_H |
19800 |
-+ |
19801 |
-+struct kdbus_bus; |
19802 |
-+ |
19803 |
-+int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags); |
19804 |
-+int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie); |
19805 |
-+int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie); |
19806 |
-+int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, |
19807 |
-+ u64 old_id, u64 new_id, |
19808 |
-+ u64 old_flags, u64 new_flags, |
19809 |
-+ const char *name); |
19810 |
-+void kdbus_notify_flush(struct kdbus_bus *bus); |
19811 |
-+void kdbus_notify_free(struct kdbus_bus *bus); |
19812 |
-+ |
19813 |
-+#endif |
19814 |
-diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c |
19815 |
-new file mode 100644 |
19816 |
-index 0000000..f2618e15 |
19817 |
---- /dev/null |
19818 |
-+++ b/ipc/kdbus/policy.c |
19819 |
-@@ -0,0 +1,489 @@ |
19820 |
-+/* |
19821 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
19822 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
19823 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
19824 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
19825 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
19826 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
19827 |
-+ * |
19828 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
19829 |
-+ * the terms of the GNU Lesser General Public License as published by the |
19830 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
19831 |
-+ * your option) any later version. |
19832 |
-+ */ |
19833 |
-+ |
19834 |
-+#include <linux/dcache.h> |
19835 |
-+#include <linux/fs.h> |
19836 |
-+#include <linux/init.h> |
19837 |
-+#include <linux/mutex.h> |
19838 |
-+#include <linux/sched.h> |
19839 |
-+#include <linux/sizes.h> |
19840 |
-+#include <linux/slab.h> |
19841 |
-+#include <linux/uaccess.h> |
19842 |
-+ |
19843 |
-+#include "bus.h" |
19844 |
-+#include "connection.h" |
19845 |
-+#include "domain.h" |
19846 |
-+#include "item.h" |
19847 |
-+#include "names.h" |
19848 |
-+#include "policy.h" |
19849 |
-+ |
19850 |
-+#define KDBUS_POLICY_HASH_SIZE 64 |
19851 |
-+ |
19852 |
-+/** |
19853 |
-+ * struct kdbus_policy_db_entry_access - a database entry access item |
19854 |
-+ * @type: One of KDBUS_POLICY_ACCESS_* types |
19855 |
-+ * @access: Access to grant. One of KDBUS_POLICY_* |
19856 |
-+ * @uid: For KDBUS_POLICY_ACCESS_USER, the global uid |
19857 |
-+ * @gid: For KDBUS_POLICY_ACCESS_GROUP, the global gid |
19858 |
-+ * @list: List entry item for the entry's list |
19859 |
-+ * |
19860 |
-+ * This is the internal version of struct kdbus_policy_db_access. |
19861 |
-+ */ |
19862 |
-+struct kdbus_policy_db_entry_access { |
19863 |
-+ u8 type; /* USER, GROUP, WORLD */ |
19864 |
-+ u8 access; /* OWN, TALK, SEE */ |
19865 |
-+ union { |
19866 |
-+ kuid_t uid; /* global uid */ |
19867 |
-+ kgid_t gid; /* global gid */ |
19868 |
-+ }; |
19869 |
-+ struct list_head list; |
19870 |
-+}; |
19871 |
-+ |
19872 |
-+/** |
19873 |
-+ * struct kdbus_policy_db_entry - a policy database entry |
19874 |
-+ * @name: The name to match the policy entry against |
19875 |
-+ * @hentry: The hash entry for the database's entries_hash |
19876 |
-+ * @access_list: List head for keeping tracks of the entry's |
19877 |
-+ * access items. |
19878 |
-+ * @owner: The owner of this entry. Can be a kdbus_conn or |
19879 |
-+ * a kdbus_ep object. |
19880 |
-+ * @wildcard: The name is a wildcard, such as ending on '.*' |
19881 |
-+ */ |
19882 |
-+struct kdbus_policy_db_entry { |
19883 |
-+ char *name; |
19884 |
-+ struct hlist_node hentry; |
19885 |
-+ struct list_head access_list; |
19886 |
-+ const void *owner; |
19887 |
-+ bool wildcard:1; |
19888 |
-+}; |
19889 |
-+ |
19890 |
-+static void kdbus_policy_entry_free(struct kdbus_policy_db_entry *e) |
19891 |
-+{ |
19892 |
-+ struct kdbus_policy_db_entry_access *a, *tmp; |
19893 |
-+ |
19894 |
-+ list_for_each_entry_safe(a, tmp, &e->access_list, list) { |
19895 |
-+ list_del(&a->list); |
19896 |
-+ kfree(a); |
19897 |
-+ } |
19898 |
-+ |
19899 |
-+ kfree(e->name); |
19900 |
-+ kfree(e); |
19901 |
-+} |
19902 |
-+ |
19903 |
-+static unsigned int kdbus_strnhash(const char *str, size_t len) |
19904 |
-+{ |
19905 |
-+ unsigned long hash = init_name_hash(); |
19906 |
-+ |
19907 |
-+ while (len--) |
19908 |
-+ hash = partial_name_hash(*str++, hash); |
19909 |
-+ |
19910 |
-+ return end_name_hash(hash); |
19911 |
-+} |
19912 |
-+ |
19913 |
-+static const struct kdbus_policy_db_entry * |
19914 |
-+kdbus_policy_lookup(struct kdbus_policy_db *db, const char *name, u32 hash) |
19915 |
-+{ |
19916 |
-+ struct kdbus_policy_db_entry *e; |
19917 |
-+ const char *dot; |
19918 |
-+ size_t len; |
19919 |
-+ |
19920 |
-+ /* find exact match */ |
19921 |
-+ hash_for_each_possible(db->entries_hash, e, hentry, hash) |
19922 |
-+ if (strcmp(e->name, name) == 0 && !e->wildcard) |
19923 |
-+ return e; |
19924 |
-+ |
19925 |
-+ /* find wildcard match */ |
19926 |
-+ |
19927 |
-+ dot = strrchr(name, '.'); |
19928 |
-+ if (!dot) |
19929 |
-+ return NULL; |
19930 |
-+ |
19931 |
-+ len = dot - name; |
19932 |
-+ hash = kdbus_strnhash(name, len); |
19933 |
-+ |
19934 |
-+ hash_for_each_possible(db->entries_hash, e, hentry, hash) |
19935 |
-+ if (e->wildcard && !strncmp(e->name, name, len) && |
19936 |
-+ !e->name[len]) |
19937 |
-+ return e; |
19938 |
-+ |
19939 |
-+ return NULL; |
19940 |
-+} |
19941 |
-+ |
19942 |
-+/** |
19943 |
-+ * kdbus_policy_db_clear - release all memory from a policy db |
19944 |
-+ * @db: The policy database |
19945 |
-+ */ |
19946 |
-+void kdbus_policy_db_clear(struct kdbus_policy_db *db) |
19947 |
-+{ |
19948 |
-+ struct kdbus_policy_db_entry *e; |
19949 |
-+ struct hlist_node *tmp; |
19950 |
-+ unsigned int i; |
19951 |
-+ |
19952 |
-+ /* purge entries */ |
19953 |
-+ down_write(&db->entries_rwlock); |
19954 |
-+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) { |
19955 |
-+ hash_del(&e->hentry); |
19956 |
-+ kdbus_policy_entry_free(e); |
19957 |
-+ } |
19958 |
-+ up_write(&db->entries_rwlock); |
19959 |
-+} |
19960 |
-+ |
19961 |
-+/** |
19962 |
-+ * kdbus_policy_db_init() - initialize a new policy database |
19963 |
-+ * @db: The location of the database |
19964 |
-+ * |
19965 |
-+ * This initializes a new policy-db. The underlying memory must have been |
19966 |
-+ * cleared to zero by the caller. |
19967 |
-+ */ |
19968 |
-+void kdbus_policy_db_init(struct kdbus_policy_db *db) |
19969 |
-+{ |
19970 |
-+ hash_init(db->entries_hash); |
19971 |
-+ init_rwsem(&db->entries_rwlock); |
19972 |
-+} |
19973 |
-+ |
19974 |
-+/** |
19975 |
-+ * kdbus_policy_query_unlocked() - Query the policy database |
19976 |
-+ * @db: Policy database |
19977 |
-+ * @cred: Credentials to test against |
19978 |
-+ * @name: Name to query |
19979 |
-+ * @hash: Hash value of @name |
19980 |
-+ * |
19981 |
-+ * Same as kdbus_policy_query() but requires the caller to lock the policy |
19982 |
-+ * database against concurrent writes. |
19983 |
-+ * |
19984 |
-+ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. |
19985 |
-+ */ |
19986 |
-+int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, |
19987 |
-+ const struct cred *cred, const char *name, |
19988 |
-+ unsigned int hash) |
19989 |
-+{ |
19990 |
-+ struct kdbus_policy_db_entry_access *a; |
19991 |
-+ const struct kdbus_policy_db_entry *e; |
19992 |
-+ int i, highest = -EPERM; |
19993 |
-+ |
19994 |
-+ e = kdbus_policy_lookup(db, name, hash); |
19995 |
-+ if (!e) |
19996 |
-+ return -EPERM; |
19997 |
-+ |
19998 |
-+ list_for_each_entry(a, &e->access_list, list) { |
19999 |
-+ if ((int)a->access <= highest) |
20000 |
-+ continue; |
20001 |
-+ |
20002 |
-+ switch (a->type) { |
20003 |
-+ case KDBUS_POLICY_ACCESS_USER: |
20004 |
-+ if (uid_eq(cred->euid, a->uid)) |
20005 |
-+ highest = a->access; |
20006 |
-+ break; |
20007 |
-+ case KDBUS_POLICY_ACCESS_GROUP: |
20008 |
-+ if (gid_eq(cred->egid, a->gid)) { |
20009 |
-+ highest = a->access; |
20010 |
-+ break; |
20011 |
-+ } |
20012 |
-+ |
20013 |
-+ for (i = 0; i < cred->group_info->ngroups; i++) { |
20014 |
-+ kgid_t gid = GROUP_AT(cred->group_info, i); |
20015 |
-+ |
20016 |
-+ if (gid_eq(gid, a->gid)) { |
20017 |
-+ highest = a->access; |
20018 |
-+ break; |
20019 |
-+ } |
20020 |
-+ } |
20021 |
-+ |
20022 |
-+ break; |
20023 |
-+ case KDBUS_POLICY_ACCESS_WORLD: |
20024 |
-+ highest = a->access; |
20025 |
-+ break; |
20026 |
-+ } |
20027 |
-+ |
20028 |
-+ /* OWN is the highest possible policy */ |
20029 |
-+ if (highest >= KDBUS_POLICY_OWN) |
20030 |
-+ break; |
20031 |
-+ } |
20032 |
-+ |
20033 |
-+ return highest; |
20034 |
-+} |
20035 |
-+ |
20036 |
-+/** |
20037 |
-+ * kdbus_policy_query() - Query the policy database |
20038 |
-+ * @db: Policy database |
20039 |
-+ * @cred: Credentials to test against |
20040 |
-+ * @name: Name to query |
20041 |
-+ * @hash: Hash value of @name |
20042 |
-+ * |
20043 |
-+ * Query the policy database @db for the access rights of @cred to the name |
20044 |
-+ * @name. The access rights of @cred are returned, or -EPERM if no access is |
20045 |
-+ * granted. |
20046 |
-+ * |
20047 |
-+ * This call effectively searches for the highest access-right granted to |
20048 |
-+ * @cred. The caller should really cache those as policy lookups are rather |
20049 |
-+ * expensive. |
20050 |
-+ * |
20051 |
-+ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. |
20052 |
-+ */ |
20053 |
-+int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, |
20054 |
-+ const char *name, unsigned int hash) |
20055 |
-+{ |
20056 |
-+ int ret; |
20057 |
-+ |
20058 |
-+ down_read(&db->entries_rwlock); |
20059 |
-+ ret = kdbus_policy_query_unlocked(db, cred, name, hash); |
20060 |
-+ up_read(&db->entries_rwlock); |
20061 |
-+ |
20062 |
-+ return ret; |
20063 |
-+} |
20064 |
-+ |
20065 |
-+static void __kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
20066 |
-+ const void *owner) |
20067 |
-+{ |
20068 |
-+ struct kdbus_policy_db_entry *e; |
20069 |
-+ struct hlist_node *tmp; |
20070 |
-+ int i; |
20071 |
-+ |
20072 |
-+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) |
20073 |
-+ if (e->owner == owner) { |
20074 |
-+ hash_del(&e->hentry); |
20075 |
-+ kdbus_policy_entry_free(e); |
20076 |
-+ } |
20077 |
-+} |
20078 |
-+ |
20079 |
-+/** |
20080 |
-+ * kdbus_policy_remove_owner() - remove all entries related to a connection |
20081 |
-+ * @db: The policy database |
20082 |
-+ * @owner: The connection which items to remove |
20083 |
-+ */ |
20084 |
-+void kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
20085 |
-+ const void *owner) |
20086 |
-+{ |
20087 |
-+ down_write(&db->entries_rwlock); |
20088 |
-+ __kdbus_policy_remove_owner(db, owner); |
20089 |
-+ up_write(&db->entries_rwlock); |
20090 |
-+} |
20091 |
-+ |
20092 |
-+/* |
20093 |
-+ * Convert user provided policy access to internal kdbus policy |
20094 |
-+ * access |
20095 |
-+ */ |
20096 |
-+static struct kdbus_policy_db_entry_access * |
20097 |
-+kdbus_policy_make_access(const struct kdbus_policy_access *uaccess) |
20098 |
-+{ |
20099 |
-+ int ret; |
20100 |
-+ struct kdbus_policy_db_entry_access *a; |
20101 |
-+ |
20102 |
-+ a = kzalloc(sizeof(*a), GFP_KERNEL); |
20103 |
-+ if (!a) |
20104 |
-+ return ERR_PTR(-ENOMEM); |
20105 |
-+ |
20106 |
-+ ret = -EINVAL; |
20107 |
-+ switch (uaccess->access) { |
20108 |
-+ case KDBUS_POLICY_SEE: |
20109 |
-+ case KDBUS_POLICY_TALK: |
20110 |
-+ case KDBUS_POLICY_OWN: |
20111 |
-+ a->access = uaccess->access; |
20112 |
-+ break; |
20113 |
-+ default: |
20114 |
-+ goto err; |
20115 |
-+ } |
20116 |
-+ |
20117 |
-+ switch (uaccess->type) { |
20118 |
-+ case KDBUS_POLICY_ACCESS_USER: |
20119 |
-+ a->uid = make_kuid(current_user_ns(), uaccess->id); |
20120 |
-+ if (!uid_valid(a->uid)) |
20121 |
-+ goto err; |
20122 |
-+ |
20123 |
-+ break; |
20124 |
-+ case KDBUS_POLICY_ACCESS_GROUP: |
20125 |
-+ a->gid = make_kgid(current_user_ns(), uaccess->id); |
20126 |
-+ if (!gid_valid(a->gid)) |
20127 |
-+ goto err; |
20128 |
-+ |
20129 |
-+ break; |
20130 |
-+ case KDBUS_POLICY_ACCESS_WORLD: |
20131 |
-+ break; |
20132 |
-+ default: |
20133 |
-+ goto err; |
20134 |
-+ } |
20135 |
-+ |
20136 |
-+ a->type = uaccess->type; |
20137 |
-+ |
20138 |
-+ return a; |
20139 |
-+ |
20140 |
-+err: |
20141 |
-+ kfree(a); |
20142 |
-+ return ERR_PTR(ret); |
20143 |
-+} |
20144 |
-+ |
20145 |
-+/** |
20146 |
-+ * kdbus_policy_set() - set a connection's policy rules |
20147 |
-+ * @db: The policy database |
20148 |
-+ * @items: A list of kdbus_item elements that contain both |
20149 |
-+ * names and access rules to set. |
20150 |
-+ * @items_size: The total size of the items. |
20151 |
-+ * @max_policies: The maximum number of policy entries to allow. |
20152 |
-+ * Pass 0 for no limit. |
20153 |
-+ * @allow_wildcards: Boolean value whether wildcard entries (such |
20154 |
-+ * ending on '.*') should be allowed. |
20155 |
-+ * @owner: The owner of the new policy items. |
20156 |
-+ * |
20157 |
-+ * This function sets a new set of policies for a given owner. The names and |
20158 |
-+ * access rules are gathered by walking the list of items passed in as |
20159 |
-+ * argument. An item of type KDBUS_ITEM_NAME is expected before any number of |
20160 |
-+ * KDBUS_ITEM_POLICY_ACCESS items. If there are more repetitions of this |
20161 |
-+ * pattern than denoted in @max_policies, -EINVAL is returned. |
20162 |
-+ * |
20163 |
-+ * In order to allow atomic replacement of rules, the function first removes |
20164 |
-+ * all entries that have been created for the given owner previously. |
20165 |
-+ * |
20166 |
-+ * Callers to this function must make sure that the owner is a custom |
20167 |
-+ * endpoint, or if the endpoint is a default endpoint, then it must be |
20168 |
-+ * either a policy holder or an activator. |
20169 |
-+ * |
20170 |
-+ * Return: 0 on success, negative errno on failure. |
20171 |
-+ */ |
20172 |
-+int kdbus_policy_set(struct kdbus_policy_db *db, |
20173 |
-+ const struct kdbus_item *items, |
20174 |
-+ size_t items_size, |
20175 |
-+ size_t max_policies, |
20176 |
-+ bool allow_wildcards, |
20177 |
-+ const void *owner) |
20178 |
-+{ |
20179 |
-+ struct kdbus_policy_db_entry_access *a; |
20180 |
-+ struct kdbus_policy_db_entry *e, *p; |
20181 |
-+ const struct kdbus_item *item; |
20182 |
-+ struct hlist_node *tmp; |
20183 |
-+ HLIST_HEAD(entries); |
20184 |
-+ HLIST_HEAD(restore); |
20185 |
-+ size_t count = 0; |
20186 |
-+ int i, ret = 0; |
20187 |
-+ u32 hash; |
20188 |
-+ |
20189 |
-+ /* Walk the list of items and look for new policies */ |
20190 |
-+ e = NULL; |
20191 |
-+ KDBUS_ITEMS_FOREACH(item, items, items_size) { |
20192 |
-+ switch (item->type) { |
20193 |
-+ case KDBUS_ITEM_NAME: { |
20194 |
-+ size_t len; |
20195 |
-+ |
20196 |
-+ if (max_policies && ++count > max_policies) { |
20197 |
-+ ret = -E2BIG; |
20198 |
-+ goto exit; |
20199 |
-+ } |
20200 |
-+ |
20201 |
-+ if (!kdbus_name_is_valid(item->str, true)) { |
20202 |
-+ ret = -EINVAL; |
20203 |
-+ goto exit; |
20204 |
-+ } |
20205 |
-+ |
20206 |
-+ e = kzalloc(sizeof(*e), GFP_KERNEL); |
20207 |
-+ if (!e) { |
20208 |
-+ ret = -ENOMEM; |
20209 |
-+ goto exit; |
20210 |
-+ } |
20211 |
-+ |
20212 |
-+ INIT_LIST_HEAD(&e->access_list); |
20213 |
-+ e->owner = owner; |
20214 |
-+ hlist_add_head(&e->hentry, &entries); |
20215 |
-+ |
20216 |
-+ e->name = kstrdup(item->str, GFP_KERNEL); |
20217 |
-+ if (!e->name) { |
20218 |
-+ ret = -ENOMEM; |
20219 |
-+ goto exit; |
20220 |
-+ } |
20221 |
-+ |
20222 |
-+ /* |
20223 |
-+ * If a supplied name ends with an '.*', cut off that |
20224 |
-+ * part, only store anything before it, and mark the |
20225 |
-+ * entry as wildcard. |
20226 |
-+ */ |
20227 |
-+ len = strlen(e->name); |
20228 |
-+ if (len > 2 && |
20229 |
-+ e->name[len - 3] == '.' && |
20230 |
-+ e->name[len - 2] == '*') { |
20231 |
-+ if (!allow_wildcards) { |
20232 |
-+ ret = -EINVAL; |
20233 |
-+ goto exit; |
20234 |
-+ } |
20235 |
-+ |
20236 |
-+ e->name[len - 3] = '\0'; |
20237 |
-+ e->wildcard = true; |
20238 |
-+ } |
20239 |
-+ |
20240 |
-+ break; |
20241 |
-+ } |
20242 |
-+ |
20243 |
-+ case KDBUS_ITEM_POLICY_ACCESS: |
20244 |
-+ if (!e) { |
20245 |
-+ ret = -EINVAL; |
20246 |
-+ goto exit; |
20247 |
-+ } |
20248 |
-+ |
20249 |
-+ a = kdbus_policy_make_access(&item->policy_access); |
20250 |
-+ if (IS_ERR(a)) { |
20251 |
-+ ret = PTR_ERR(a); |
20252 |
-+ goto exit; |
20253 |
-+ } |
20254 |
-+ |
20255 |
-+ list_add_tail(&a->list, &e->access_list); |
20256 |
-+ break; |
20257 |
-+ } |
20258 |
-+ } |
20259 |
-+ |
20260 |
-+ down_write(&db->entries_rwlock); |
20261 |
-+ |
20262 |
-+ /* remember previous entries to restore in case of failure */ |
20263 |
-+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) |
20264 |
-+ if (e->owner == owner) { |
20265 |
-+ hash_del(&e->hentry); |
20266 |
-+ hlist_add_head(&e->hentry, &restore); |
20267 |
-+ } |
20268 |
-+ |
20269 |
-+ hlist_for_each_entry_safe(e, tmp, &entries, hentry) { |
20270 |
-+ /* prevent duplicates */ |
20271 |
-+ hash = kdbus_strhash(e->name); |
20272 |
-+ hash_for_each_possible(db->entries_hash, p, hentry, hash) |
20273 |
-+ if (strcmp(e->name, p->name) == 0 && |
20274 |
-+ e->wildcard == p->wildcard) { |
20275 |
-+ ret = -EEXIST; |
20276 |
-+ goto restore; |
20277 |
-+ } |
20278 |
-+ |
20279 |
-+ hlist_del(&e->hentry); |
20280 |
-+ hash_add(db->entries_hash, &e->hentry, hash); |
20281 |
-+ } |
20282 |
-+ |
20283 |
-+restore: |
20284 |
-+ /* if we failed, flush all entries we added so far */ |
20285 |
-+ if (ret < 0) |
20286 |
-+ __kdbus_policy_remove_owner(db, owner); |
20287 |
-+ |
20288 |
-+ /* if we failed, restore entries, otherwise release them */ |
20289 |
-+ hlist_for_each_entry_safe(e, tmp, &restore, hentry) { |
20290 |
-+ hlist_del(&e->hentry); |
20291 |
-+ if (ret < 0) { |
20292 |
-+ hash = kdbus_strhash(e->name); |
20293 |
-+ hash_add(db->entries_hash, &e->hentry, hash); |
20294 |
-+ } else { |
20295 |
-+ kdbus_policy_entry_free(e); |
20296 |
-+ } |
20297 |
-+ } |
20298 |
-+ |
20299 |
-+ up_write(&db->entries_rwlock); |
20300 |
-+ |
20301 |
-+exit: |
20302 |
-+ hlist_for_each_entry_safe(e, tmp, &entries, hentry) { |
20303 |
-+ hlist_del(&e->hentry); |
20304 |
-+ kdbus_policy_entry_free(e); |
20305 |
-+ } |
20306 |
-+ |
20307 |
-+ return ret; |
20308 |
-+} |
20309 |
-diff --git a/ipc/kdbus/policy.h b/ipc/kdbus/policy.h |
20310 |
-new file mode 100644 |
20311 |
-index 0000000..15dd7bc |
20312 |
---- /dev/null |
20313 |
-+++ b/ipc/kdbus/policy.h |
20314 |
-@@ -0,0 +1,51 @@ |
20315 |
-+/* |
20316 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
20317 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
20318 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
20319 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
20320 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
20321 |
-+ * |
20322 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
20323 |
-+ * the terms of the GNU Lesser General Public License as published by the |
20324 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
20325 |
-+ * your option) any later version. |
20326 |
-+ */ |
20327 |
-+ |
20328 |
-+#ifndef __KDBUS_POLICY_H |
20329 |
-+#define __KDBUS_POLICY_H |
20330 |
-+ |
20331 |
-+#include <linux/hashtable.h> |
20332 |
-+#include <linux/rwsem.h> |
20333 |
-+ |
20334 |
-+struct kdbus_conn; |
20335 |
-+struct kdbus_item; |
20336 |
-+ |
20337 |
-+/** |
20338 |
-+ * struct kdbus_policy_db - policy database |
20339 |
-+ * @entries_hash: Hashtable of entries |
20340 |
-+ * @entries_rwlock: Mutex to protect the database's access entries |
20341 |
-+ */ |
20342 |
-+struct kdbus_policy_db { |
20343 |
-+ DECLARE_HASHTABLE(entries_hash, 6); |
20344 |
-+ struct rw_semaphore entries_rwlock; |
20345 |
-+}; |
20346 |
-+ |
20347 |
-+void kdbus_policy_db_init(struct kdbus_policy_db *db); |
20348 |
-+void kdbus_policy_db_clear(struct kdbus_policy_db *db); |
20349 |
-+ |
20350 |
-+int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, |
20351 |
-+ const struct cred *cred, const char *name, |
20352 |
-+ unsigned int hash); |
20353 |
-+int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, |
20354 |
-+ const char *name, unsigned int hash); |
20355 |
-+ |
20356 |
-+void kdbus_policy_remove_owner(struct kdbus_policy_db *db, |
20357 |
-+ const void *owner); |
20358 |
-+int kdbus_policy_set(struct kdbus_policy_db *db, |
20359 |
-+ const struct kdbus_item *items, |
20360 |
-+ size_t items_size, |
20361 |
-+ size_t max_policies, |
20362 |
-+ bool allow_wildcards, |
20363 |
-+ const void *owner); |
20364 |
-+ |
20365 |
-+#endif |
20366 |
-diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c |
20367 |
-new file mode 100644 |
20368 |
-index 0000000..63ccd55 |
20369 |
---- /dev/null |
20370 |
-+++ b/ipc/kdbus/pool.c |
20371 |
-@@ -0,0 +1,728 @@ |
20372 |
-+/* |
20373 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
20374 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
20375 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
20376 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
20377 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
20378 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
20379 |
-+ * |
20380 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
20381 |
-+ * the terms of the GNU Lesser General Public License as published by the |
20382 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
20383 |
-+ * your option) any later version. |
20384 |
-+ */ |
20385 |
-+ |
20386 |
-+#include <linux/aio.h> |
20387 |
-+#include <linux/file.h> |
20388 |
-+#include <linux/fs.h> |
20389 |
-+#include <linux/highmem.h> |
20390 |
-+#include <linux/init.h> |
20391 |
-+#include <linux/mm.h> |
20392 |
-+#include <linux/module.h> |
20393 |
-+#include <linux/pagemap.h> |
20394 |
-+#include <linux/rbtree.h> |
20395 |
-+#include <linux/sched.h> |
20396 |
-+#include <linux/shmem_fs.h> |
20397 |
-+#include <linux/sizes.h> |
20398 |
-+#include <linux/slab.h> |
20399 |
-+#include <linux/uaccess.h> |
20400 |
-+#include <linux/uio.h> |
20401 |
-+ |
20402 |
-+#include "pool.h" |
20403 |
-+#include "util.h" |
20404 |
-+ |
20405 |
-+/** |
20406 |
-+ * struct kdbus_pool - the receiver's buffer |
20407 |
-+ * @f: The backing shmem file |
20408 |
-+ * @size: The size of the file |
20409 |
-+ * @accounted_size: Currently accounted memory in bytes |
20410 |
-+ * @lock: Pool data lock |
20411 |
-+ * @slices: All slices sorted by address |
20412 |
-+ * @slices_busy: Tree of allocated slices |
20413 |
-+ * @slices_free: Tree of free slices |
20414 |
-+ * |
20415 |
-+ * The receiver's buffer, managed as a pool of allocated and free |
20416 |
-+ * slices containing the queued messages. |
20417 |
-+ * |
20418 |
-+ * Messages sent with KDBUS_CMD_SEND are copied directly by the |
20419 |
-+ * sending process into the receiver's pool. |
20420 |
-+ * |
20421 |
-+ * Messages received with KDBUS_CMD_RECV just return the offset |
20422 |
-+ * to the data placed in the pool. |
20423 |
-+ * |
20424 |
-+ * The internally allocated memory needs to be returned by the receiver |
20425 |
-+ * with KDBUS_CMD_FREE. |
20426 |
-+ */ |
20427 |
-+struct kdbus_pool { |
20428 |
-+ struct file *f; |
20429 |
-+ size_t size; |
20430 |
-+ size_t accounted_size; |
20431 |
-+ struct mutex lock; |
20432 |
-+ |
20433 |
-+ struct list_head slices; |
20434 |
-+ struct rb_root slices_busy; |
20435 |
-+ struct rb_root slices_free; |
20436 |
-+}; |
20437 |
-+ |
20438 |
-+/** |
20439 |
-+ * struct kdbus_pool_slice - allocated element in kdbus_pool |
20440 |
-+ * @pool: Pool this slice belongs to |
20441 |
-+ * @off: Offset of slice in the shmem file |
20442 |
-+ * @size: Size of slice |
20443 |
-+ * @entry: Entry in "all slices" list |
20444 |
-+ * @rb_node: Entry in free or busy list |
20445 |
-+ * @free: Unused slice |
20446 |
-+ * @accounted: Accounted as queue slice |
20447 |
-+ * @ref_kernel: Kernel holds a reference |
20448 |
-+ * @ref_user: Userspace holds a reference |
20449 |
-+ * |
20450 |
-+ * The pool has one or more slices, always spanning the entire size of the |
20451 |
-+ * pool. |
20452 |
-+ * |
20453 |
-+ * Every slice is an element in a list sorted by the buffer address, to |
20454 |
-+ * provide access to the next neighbor slice. |
20455 |
-+ * |
20456 |
-+ * Every slice is member in either the busy or the free tree. The free |
20457 |
-+ * tree is organized by slice size, the busy tree organized by buffer |
20458 |
-+ * offset. |
20459 |
-+ */ |
20460 |
-+struct kdbus_pool_slice { |
20461 |
-+ struct kdbus_pool *pool; |
20462 |
-+ size_t off; |
20463 |
-+ size_t size; |
20464 |
-+ |
20465 |
-+ struct list_head entry; |
20466 |
-+ struct rb_node rb_node; |
20467 |
-+ |
20468 |
-+ bool free:1; |
20469 |
-+ bool accounted:1; |
20470 |
-+ bool ref_kernel:1; |
20471 |
-+ bool ref_user:1; |
20472 |
-+}; |
20473 |
-+ |
20474 |
-+static struct kdbus_pool_slice *kdbus_pool_slice_new(struct kdbus_pool *pool, |
20475 |
-+ size_t off, size_t size) |
20476 |
-+{ |
20477 |
-+ struct kdbus_pool_slice *slice; |
20478 |
-+ |
20479 |
-+ slice = kzalloc(sizeof(*slice), GFP_KERNEL); |
20480 |
-+ if (!slice) |
20481 |
-+ return NULL; |
20482 |
-+ |
20483 |
-+ slice->pool = pool; |
20484 |
-+ slice->off = off; |
20485 |
-+ slice->size = size; |
20486 |
-+ slice->free = true; |
20487 |
-+ return slice; |
20488 |
-+} |
20489 |
-+ |
20490 |
-+/* insert a slice into the free tree */ |
20491 |
-+static void kdbus_pool_add_free_slice(struct kdbus_pool *pool, |
20492 |
-+ struct kdbus_pool_slice *slice) |
20493 |
-+{ |
20494 |
-+ struct rb_node **n; |
20495 |
-+ struct rb_node *pn = NULL; |
20496 |
-+ |
20497 |
-+ n = &pool->slices_free.rb_node; |
20498 |
-+ while (*n) { |
20499 |
-+ struct kdbus_pool_slice *pslice; |
20500 |
-+ |
20501 |
-+ pn = *n; |
20502 |
-+ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node); |
20503 |
-+ if (slice->size < pslice->size) |
20504 |
-+ n = &pn->rb_left; |
20505 |
-+ else |
20506 |
-+ n = &pn->rb_right; |
20507 |
-+ } |
20508 |
-+ |
20509 |
-+ rb_link_node(&slice->rb_node, pn, n); |
20510 |
-+ rb_insert_color(&slice->rb_node, &pool->slices_free); |
20511 |
-+} |
20512 |
-+ |
20513 |
-+/* insert a slice into the busy tree */ |
20514 |
-+static void kdbus_pool_add_busy_slice(struct kdbus_pool *pool, |
20515 |
-+ struct kdbus_pool_slice *slice) |
20516 |
-+{ |
20517 |
-+ struct rb_node **n; |
20518 |
-+ struct rb_node *pn = NULL; |
20519 |
-+ |
20520 |
-+ n = &pool->slices_busy.rb_node; |
20521 |
-+ while (*n) { |
20522 |
-+ struct kdbus_pool_slice *pslice; |
20523 |
-+ |
20524 |
-+ pn = *n; |
20525 |
-+ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node); |
20526 |
-+ if (slice->off < pslice->off) |
20527 |
-+ n = &pn->rb_left; |
20528 |
-+ else if (slice->off > pslice->off) |
20529 |
-+ n = &pn->rb_right; |
20530 |
-+ else |
20531 |
-+ BUG(); |
20532 |
-+ } |
20533 |
-+ |
20534 |
-+ rb_link_node(&slice->rb_node, pn, n); |
20535 |
-+ rb_insert_color(&slice->rb_node, &pool->slices_busy); |
20536 |
-+} |
20537 |
-+ |
20538 |
-+static struct kdbus_pool_slice *kdbus_pool_find_slice(struct kdbus_pool *pool, |
20539 |
-+ size_t off) |
20540 |
-+{ |
20541 |
-+ struct rb_node *n; |
20542 |
-+ |
20543 |
-+ n = pool->slices_busy.rb_node; |
20544 |
-+ while (n) { |
20545 |
-+ struct kdbus_pool_slice *s; |
20546 |
-+ |
20547 |
-+ s = rb_entry(n, struct kdbus_pool_slice, rb_node); |
20548 |
-+ if (off < s->off) |
20549 |
-+ n = n->rb_left; |
20550 |
-+ else if (off > s->off) |
20551 |
-+ n = n->rb_right; |
20552 |
-+ else |
20553 |
-+ return s; |
20554 |
-+ } |
20555 |
-+ |
20556 |
-+ return NULL; |
20557 |
-+} |
20558 |
-+ |
20559 |
-+/** |
20560 |
-+ * kdbus_pool_slice_alloc() - allocate memory from a pool |
20561 |
-+ * @pool: The receiver's pool |
20562 |
-+ * @size: The number of bytes to allocate |
20563 |
-+ * @accounted: Whether this slice should be accounted for |
20564 |
-+ * |
20565 |
-+ * The returned slice is used for kdbus_pool_slice_release() to |
20566 |
-+ * free the allocated memory. If either @kvec or @iovec is non-NULL, the data |
20567 |
-+ * will be copied from kernel or userspace memory into the new slice at |
20568 |
-+ * offset 0. |
20569 |
-+ * |
20570 |
-+ * Return: the allocated slice on success, ERR_PTR on failure. |
20571 |
-+ */ |
20572 |
-+struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, |
20573 |
-+ size_t size, bool accounted) |
20574 |
-+{ |
20575 |
-+ size_t slice_size = KDBUS_ALIGN8(size); |
20576 |
-+ struct rb_node *n, *found = NULL; |
20577 |
-+ struct kdbus_pool_slice *s; |
20578 |
-+ int ret = 0; |
20579 |
-+ |
20580 |
-+ if (WARN_ON(!size)) |
20581 |
-+ return ERR_PTR(-EINVAL); |
20582 |
-+ |
20583 |
-+ /* search a free slice with the closest matching size */ |
20584 |
-+ mutex_lock(&pool->lock); |
20585 |
-+ n = pool->slices_free.rb_node; |
20586 |
-+ while (n) { |
20587 |
-+ s = rb_entry(n, struct kdbus_pool_slice, rb_node); |
20588 |
-+ if (slice_size < s->size) { |
20589 |
-+ found = n; |
20590 |
-+ n = n->rb_left; |
20591 |
-+ } else if (slice_size > s->size) { |
20592 |
-+ n = n->rb_right; |
20593 |
-+ } else { |
20594 |
-+ found = n; |
20595 |
-+ break; |
20596 |
-+ } |
20597 |
-+ } |
20598 |
-+ |
20599 |
-+ /* no slice with the minimum size found in the pool */ |
20600 |
-+ if (!found) { |
20601 |
-+ ret = -EXFULL; |
20602 |
-+ goto exit_unlock; |
20603 |
-+ } |
20604 |
-+ |
20605 |
-+ /* no exact match, use the closest one */ |
20606 |
-+ if (!n) { |
20607 |
-+ struct kdbus_pool_slice *s_new; |
20608 |
-+ |
20609 |
-+ s = rb_entry(found, struct kdbus_pool_slice, rb_node); |
20610 |
-+ |
20611 |
-+ /* split-off the remainder of the size to its own slice */ |
20612 |
-+ s_new = kdbus_pool_slice_new(pool, s->off + slice_size, |
20613 |
-+ s->size - slice_size); |
20614 |
-+ if (!s_new) { |
20615 |
-+ ret = -ENOMEM; |
20616 |
-+ goto exit_unlock; |
20617 |
-+ } |
20618 |
-+ |
20619 |
-+ list_add(&s_new->entry, &s->entry); |
20620 |
-+ kdbus_pool_add_free_slice(pool, s_new); |
20621 |
-+ |
20622 |
-+ /* adjust our size now that we split-off another slice */ |
20623 |
-+ s->size = slice_size; |
20624 |
-+ } |
20625 |
-+ |
20626 |
-+ /* move slice from free to the busy tree */ |
20627 |
-+ rb_erase(found, &pool->slices_free); |
20628 |
-+ kdbus_pool_add_busy_slice(pool, s); |
20629 |
-+ |
20630 |
-+ WARN_ON(s->ref_kernel || s->ref_user); |
20631 |
-+ |
20632 |
-+ s->ref_kernel = true; |
20633 |
-+ s->free = false; |
20634 |
-+ s->accounted = accounted; |
20635 |
-+ if (accounted) |
20636 |
-+ pool->accounted_size += s->size; |
20637 |
-+ mutex_unlock(&pool->lock); |
20638 |
-+ |
20639 |
-+ return s; |
20640 |
-+ |
20641 |
-+exit_unlock: |
20642 |
-+ mutex_unlock(&pool->lock); |
20643 |
-+ return ERR_PTR(ret); |
20644 |
-+} |
20645 |
-+ |
20646 |
-+static void __kdbus_pool_slice_release(struct kdbus_pool_slice *slice) |
20647 |
-+{ |
20648 |
-+ struct kdbus_pool *pool = slice->pool; |
20649 |
-+ |
20650 |
-+ /* don't free the slice if either has a reference */ |
20651 |
-+ if (slice->ref_kernel || slice->ref_user) |
20652 |
-+ return; |
20653 |
-+ |
20654 |
-+ if (WARN_ON(slice->free)) |
20655 |
-+ return; |
20656 |
-+ |
20657 |
-+ rb_erase(&slice->rb_node, &pool->slices_busy); |
20658 |
-+ |
20659 |
-+ /* merge with the next free slice */ |
20660 |
-+ if (!list_is_last(&slice->entry, &pool->slices)) { |
20661 |
-+ struct kdbus_pool_slice *s; |
20662 |
-+ |
20663 |
-+ s = list_entry(slice->entry.next, |
20664 |
-+ struct kdbus_pool_slice, entry); |
20665 |
-+ if (s->free) { |
20666 |
-+ rb_erase(&s->rb_node, &pool->slices_free); |
20667 |
-+ list_del(&s->entry); |
20668 |
-+ slice->size += s->size; |
20669 |
-+ kfree(s); |
20670 |
-+ } |
20671 |
-+ } |
20672 |
-+ |
20673 |
-+ /* merge with previous free slice */ |
20674 |
-+ if (pool->slices.next != &slice->entry) { |
20675 |
-+ struct kdbus_pool_slice *s; |
20676 |
-+ |
20677 |
-+ s = list_entry(slice->entry.prev, |
20678 |
-+ struct kdbus_pool_slice, entry); |
20679 |
-+ if (s->free) { |
20680 |
-+ rb_erase(&s->rb_node, &pool->slices_free); |
20681 |
-+ list_del(&slice->entry); |
20682 |
-+ s->size += slice->size; |
20683 |
-+ kfree(slice); |
20684 |
-+ slice = s; |
20685 |
-+ } |
20686 |
-+ } |
20687 |
-+ |
20688 |
-+ slice->free = true; |
20689 |
-+ kdbus_pool_add_free_slice(pool, slice); |
20690 |
-+} |
20691 |
-+ |
20692 |
-+/** |
20693 |
-+ * kdbus_pool_slice_release() - drop kernel-reference on allocated slice |
20694 |
-+ * @slice: Slice allocated from the pool |
20695 |
-+ * |
20696 |
-+ * This releases the kernel-reference on the given slice. If the |
20697 |
-+ * kernel-reference and the user-reference on a slice are dropped, the slice is |
20698 |
-+ * returned to the pool. |
20699 |
-+ * |
20700 |
-+ * So far, we do not implement full ref-counting on slices. Each, kernel and |
20701 |
-+ * user-space can have exactly one reference to a slice. If both are dropped at |
20702 |
-+ * the same time, the slice is released. |
20703 |
-+ */ |
20704 |
-+void kdbus_pool_slice_release(struct kdbus_pool_slice *slice) |
20705 |
-+{ |
20706 |
-+ struct kdbus_pool *pool; |
20707 |
-+ |
20708 |
-+ if (!slice) |
20709 |
-+ return; |
20710 |
-+ |
20711 |
-+ /* @slice may be freed, so keep local ptr to @pool */ |
20712 |
-+ pool = slice->pool; |
20713 |
-+ |
20714 |
-+ mutex_lock(&pool->lock); |
20715 |
-+ /* kernel must own a ref to @slice to drop it */ |
20716 |
-+ WARN_ON(!slice->ref_kernel); |
20717 |
-+ slice->ref_kernel = false; |
20718 |
-+ /* no longer kernel-owned, de-account slice */ |
20719 |
-+ if (slice->accounted && !WARN_ON(pool->accounted_size < slice->size)) |
20720 |
-+ pool->accounted_size -= slice->size; |
20721 |
-+ __kdbus_pool_slice_release(slice); |
20722 |
-+ mutex_unlock(&pool->lock); |
20723 |
-+} |
20724 |
-+ |
20725 |
-+/** |
20726 |
-+ * kdbus_pool_release_offset() - release a public offset |
20727 |
-+ * @pool: pool to operate on |
20728 |
-+ * @off: offset to release |
20729 |
-+ * |
20730 |
-+ * This should be called whenever user-space frees a slice given to them. It |
20731 |
-+ * verifies the slice is available and public, and then drops it. It ensures |
20732 |
-+ * correct locking and barriers against queues. |
20733 |
-+ * |
20734 |
-+ * Return: 0 on success, ENXIO if the offset is invalid or not public. |
20735 |
-+ */ |
20736 |
-+int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off) |
20737 |
-+{ |
20738 |
-+ struct kdbus_pool_slice *slice; |
20739 |
-+ int ret = 0; |
20740 |
-+ |
20741 |
-+ /* 'pool->size' is used as dummy offset for empty slices */ |
20742 |
-+ if (off == pool->size) |
20743 |
-+ return 0; |
20744 |
-+ |
20745 |
-+ mutex_lock(&pool->lock); |
20746 |
-+ slice = kdbus_pool_find_slice(pool, off); |
20747 |
-+ if (slice && slice->ref_user) { |
20748 |
-+ slice->ref_user = false; |
20749 |
-+ __kdbus_pool_slice_release(slice); |
20750 |
-+ } else { |
20751 |
-+ ret = -ENXIO; |
20752 |
-+ } |
20753 |
-+ mutex_unlock(&pool->lock); |
20754 |
-+ |
20755 |
-+ return ret; |
20756 |
-+} |
20757 |
-+ |
20758 |
-+/** |
20759 |
-+ * kdbus_pool_publish_empty() - publish empty slice to user-space |
20760 |
-+ * @pool: pool to operate on |
20761 |
-+ * @off: output storage for offset, or NULL |
20762 |
-+ * @size: output storage for size, or NULL |
20763 |
-+ * |
20764 |
-+ * This is the same as kdbus_pool_slice_publish(), but uses a dummy slice with |
20765 |
-+ * size 0. The returned offset points to the end of the pool and is never |
20766 |
-+ * returned on real slices. |
20767 |
-+ */ |
20768 |
-+void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size) |
20769 |
-+{ |
20770 |
-+ if (off) |
20771 |
-+ *off = pool->size; |
20772 |
-+ if (size) |
20773 |
-+ *size = 0; |
20774 |
-+} |
20775 |
-+ |
20776 |
-+/** |
20777 |
-+ * kdbus_pool_slice_publish() - publish slice to user-space |
20778 |
-+ * @slice: The slice |
20779 |
-+ * @out_offset: Output storage for offset, or NULL |
20780 |
-+ * @out_size: Output storage for size, or NULL |
20781 |
-+ * |
20782 |
-+ * This prepares a slice to be published to user-space. |
20783 |
-+ * |
20784 |
-+ * This call combines the following operations: |
20785 |
-+ * * the memory region is flushed so the user's memory view is consistent |
20786 |
-+ * * the slice is marked as referenced by user-space, so user-space has to |
20787 |
-+ * call KDBUS_CMD_FREE to release it |
20788 |
-+ * * the offset and size of the slice are written to the given output |
20789 |
-+ * arguments, if non-NULL |
20790 |
-+ */ |
20791 |
-+void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, |
20792 |
-+ u64 *out_offset, u64 *out_size) |
20793 |
-+{ |
20794 |
-+ mutex_lock(&slice->pool->lock); |
20795 |
-+ /* kernel must own a ref to @slice to gain a user-space ref */ |
20796 |
-+ WARN_ON(!slice->ref_kernel); |
20797 |
-+ slice->ref_user = true; |
20798 |
-+ mutex_unlock(&slice->pool->lock); |
20799 |
-+ |
20800 |
-+ if (out_offset) |
20801 |
-+ *out_offset = slice->off; |
20802 |
-+ if (out_size) |
20803 |
-+ *out_size = slice->size; |
20804 |
-+} |
20805 |
-+ |
20806 |
-+/** |
20807 |
-+ * kdbus_pool_slice_offset() - Get a slice's offset inside the pool |
20808 |
-+ * @slice: Slice to return the offset of |
20809 |
-+ * |
20810 |
-+ * Return: The internal offset @slice inside the pool. |
20811 |
-+ */ |
20812 |
-+off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice) |
20813 |
-+{ |
20814 |
-+ return slice->off; |
20815 |
-+} |
20816 |
-+ |
20817 |
-+/** |
20818 |
-+ * kdbus_pool_slice_size() - get size of a pool slice |
20819 |
-+ * @slice: slice to query |
20820 |
-+ * |
20821 |
-+ * Return: size of the given slice |
20822 |
-+ */ |
20823 |
-+size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice) |
20824 |
-+{ |
20825 |
-+ return slice->size; |
20826 |
-+} |
20827 |
-+ |
20828 |
-+/** |
20829 |
-+ * kdbus_pool_new() - create a new pool |
20830 |
-+ * @name: Name of the (deleted) file which shows up in |
20831 |
-+ * /proc, used for debugging |
20832 |
-+ * @size: Maximum size of the pool |
20833 |
-+ * |
20834 |
-+ * Return: a new kdbus_pool on success, ERR_PTR on failure. |
20835 |
-+ */ |
20836 |
-+struct kdbus_pool *kdbus_pool_new(const char *name, size_t size) |
20837 |
-+{ |
20838 |
-+ struct kdbus_pool_slice *s; |
20839 |
-+ struct kdbus_pool *p; |
20840 |
-+ struct file *f; |
20841 |
-+ char *n = NULL; |
20842 |
-+ int ret; |
20843 |
-+ |
20844 |
-+ p = kzalloc(sizeof(*p), GFP_KERNEL); |
20845 |
-+ if (!p) |
20846 |
-+ return ERR_PTR(-ENOMEM); |
20847 |
-+ |
20848 |
-+ if (name) { |
20849 |
-+ n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name); |
20850 |
-+ if (!n) { |
20851 |
-+ ret = -ENOMEM; |
20852 |
-+ goto exit_free; |
20853 |
-+ } |
20854 |
-+ } |
20855 |
-+ |
20856 |
-+ f = shmem_file_setup(n ?: KBUILD_MODNAME "-conn", size, 0); |
20857 |
-+ kfree(n); |
20858 |
-+ |
20859 |
-+ if (IS_ERR(f)) { |
20860 |
-+ ret = PTR_ERR(f); |
20861 |
-+ goto exit_free; |
20862 |
-+ } |
20863 |
-+ |
20864 |
-+ ret = get_write_access(file_inode(f)); |
20865 |
-+ if (ret < 0) |
20866 |
-+ goto exit_put_shmem; |
20867 |
-+ |
20868 |
-+ /* allocate first slice spanning the entire pool */ |
20869 |
-+ s = kdbus_pool_slice_new(p, 0, size); |
20870 |
-+ if (!s) { |
20871 |
-+ ret = -ENOMEM; |
20872 |
-+ goto exit_put_write; |
20873 |
-+ } |
20874 |
-+ |
20875 |
-+ p->f = f; |
20876 |
-+ p->size = size; |
20877 |
-+ p->slices_free = RB_ROOT; |
20878 |
-+ p->slices_busy = RB_ROOT; |
20879 |
-+ mutex_init(&p->lock); |
20880 |
-+ |
20881 |
-+ INIT_LIST_HEAD(&p->slices); |
20882 |
-+ list_add(&s->entry, &p->slices); |
20883 |
-+ |
20884 |
-+ kdbus_pool_add_free_slice(p, s); |
20885 |
-+ return p; |
20886 |
-+ |
20887 |
-+exit_put_write: |
20888 |
-+ put_write_access(file_inode(f)); |
20889 |
-+exit_put_shmem: |
20890 |
-+ fput(f); |
20891 |
-+exit_free: |
20892 |
-+ kfree(p); |
20893 |
-+ return ERR_PTR(ret); |
20894 |
-+} |
20895 |
-+ |
20896 |
-+/** |
20897 |
-+ * kdbus_pool_free() - destroy pool |
20898 |
-+ * @pool: The receiver's pool |
20899 |
-+ */ |
20900 |
-+void kdbus_pool_free(struct kdbus_pool *pool) |
20901 |
-+{ |
20902 |
-+ struct kdbus_pool_slice *s, *tmp; |
20903 |
-+ |
20904 |
-+ if (!pool) |
20905 |
-+ return; |
20906 |
-+ |
20907 |
-+ list_for_each_entry_safe(s, tmp, &pool->slices, entry) { |
20908 |
-+ list_del(&s->entry); |
20909 |
-+ kfree(s); |
20910 |
-+ } |
20911 |
-+ |
20912 |
-+ put_write_access(file_inode(pool->f)); |
20913 |
-+ fput(pool->f); |
20914 |
-+ kfree(pool); |
20915 |
-+} |
20916 |
-+ |
20917 |
-+/** |
20918 |
-+ * kdbus_pool_accounted() - retrieve accounting information |
20919 |
-+ * @pool: pool to query |
20920 |
-+ * @size: output for overall pool size |
20921 |
-+ * @acc: output for currently accounted size |
20922 |
-+ * |
20923 |
-+ * This returns accounting information of the pool. Note that the data might |
20924 |
-+ * change after the function returns, as the pool lock is dropped. You need to |
20925 |
-+ * protect the data via other means, if you need reliable accounting. |
20926 |
-+ */ |
20927 |
-+void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc) |
20928 |
-+{ |
20929 |
-+ mutex_lock(&pool->lock); |
20930 |
-+ if (size) |
20931 |
-+ *size = pool->size; |
20932 |
-+ if (acc) |
20933 |
-+ *acc = pool->accounted_size; |
20934 |
-+ mutex_unlock(&pool->lock); |
20935 |
-+} |
20936 |
-+ |
20937 |
-+/** |
20938 |
-+ * kdbus_pool_slice_copy_iovec() - copy user memory to a slice |
20939 |
-+ * @slice: The slice to write to |
20940 |
-+ * @off: Offset in the slice to write to |
20941 |
-+ * @iov: iovec array, pointing to data to copy |
20942 |
-+ * @iov_len: Number of elements in @iov |
20943 |
-+ * @total_len: Total number of bytes described in members of @iov |
20944 |
-+ * |
20945 |
-+ * User memory referenced by @iov will be copied into @slice at offset @off. |
20946 |
-+ * |
20947 |
-+ * Return: the numbers of bytes copied, negative errno on failure. |
20948 |
-+ */ |
20949 |
-+ssize_t |
20950 |
-+kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, loff_t off, |
20951 |
-+ struct iovec *iov, size_t iov_len, size_t total_len) |
20952 |
-+{ |
20953 |
-+ struct iov_iter iter; |
20954 |
-+ ssize_t len; |
20955 |
-+ |
20956 |
-+ if (WARN_ON(off + total_len > slice->size)) |
20957 |
-+ return -EFAULT; |
20958 |
-+ |
20959 |
-+ off += slice->off; |
20960 |
-+ iov_iter_init(&iter, WRITE, iov, iov_len, total_len); |
20961 |
-+ len = vfs_iter_write(slice->pool->f, &iter, &off); |
20962 |
-+ |
20963 |
-+ return (len >= 0 && len != total_len) ? -EFAULT : len; |
20964 |
-+} |
20965 |
-+ |
20966 |
-+/** |
20967 |
-+ * kdbus_pool_slice_copy_kvec() - copy kernel memory to a slice |
20968 |
-+ * @slice: The slice to write to |
20969 |
-+ * @off: Offset in the slice to write to |
20970 |
-+ * @kvec: kvec array, pointing to data to copy |
20971 |
-+ * @kvec_len: Number of elements in @kvec |
20972 |
-+ * @total_len: Total number of bytes described in members of @kvec |
20973 |
-+ * |
20974 |
-+ * Kernel memory referenced by @kvec will be copied into @slice at offset @off. |
20975 |
-+ * |
20976 |
-+ * Return: the numbers of bytes copied, negative errno on failure. |
20977 |
-+ */ |
20978 |
-+ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, |
20979 |
-+ loff_t off, struct kvec *kvec, |
20980 |
-+ size_t kvec_len, size_t total_len) |
20981 |
-+{ |
20982 |
-+ struct iov_iter iter; |
20983 |
-+ mm_segment_t old_fs; |
20984 |
-+ ssize_t len; |
20985 |
-+ |
20986 |
-+ if (WARN_ON(off + total_len > slice->size)) |
20987 |
-+ return -EFAULT; |
20988 |
-+ |
20989 |
-+ off += slice->off; |
20990 |
-+ iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len); |
20991 |
-+ |
20992 |
-+ old_fs = get_fs(); |
20993 |
-+ set_fs(get_ds()); |
20994 |
-+ len = vfs_iter_write(slice->pool->f, &iter, &off); |
20995 |
-+ set_fs(old_fs); |
20996 |
-+ |
20997 |
-+ return (len >= 0 && len != total_len) ? -EFAULT : len; |
20998 |
-+} |
20999 |
-+ |
21000 |
-+/** |
21001 |
-+ * kdbus_pool_slice_copy() - copy data from one slice into another |
21002 |
-+ * @slice_dst: destination slice |
21003 |
-+ * @slice_src: source slice |
21004 |
-+ * |
21005 |
-+ * Return: 0 on success, negative error number on failure. |
21006 |
-+ */ |
21007 |
-+int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, |
21008 |
-+ const struct kdbus_pool_slice *slice_src) |
21009 |
-+{ |
21010 |
-+ struct file *f_src = slice_src->pool->f; |
21011 |
-+ struct file *f_dst = slice_dst->pool->f; |
21012 |
-+ struct inode *i_dst = file_inode(f_dst); |
21013 |
-+ struct address_space *mapping_dst = f_dst->f_mapping; |
21014 |
-+ const struct address_space_operations *aops = mapping_dst->a_ops; |
21015 |
-+ unsigned long len = slice_src->size; |
21016 |
-+ loff_t off_src = slice_src->off; |
21017 |
-+ loff_t off_dst = slice_dst->off; |
21018 |
-+ mm_segment_t old_fs; |
21019 |
-+ int ret = 0; |
21020 |
-+ |
21021 |
-+ if (WARN_ON(slice_src->size != slice_dst->size) || |
21022 |
-+ WARN_ON(slice_src->free || slice_dst->free)) |
21023 |
-+ return -EINVAL; |
21024 |
-+ |
21025 |
-+ mutex_lock(&i_dst->i_mutex); |
21026 |
-+ old_fs = get_fs(); |
21027 |
-+ set_fs(get_ds()); |
21028 |
-+ while (len > 0) { |
21029 |
-+ unsigned long page_off; |
21030 |
-+ unsigned long copy_len; |
21031 |
-+ char __user *kaddr; |
21032 |
-+ struct page *page; |
21033 |
-+ ssize_t n_read; |
21034 |
-+ void *fsdata; |
21035 |
-+ long status; |
21036 |
-+ |
21037 |
-+ page_off = off_dst & (PAGE_CACHE_SIZE - 1); |
21038 |
-+ copy_len = min_t(unsigned long, |
21039 |
-+ PAGE_CACHE_SIZE - page_off, len); |
21040 |
-+ |
21041 |
-+ status = aops->write_begin(f_dst, mapping_dst, off_dst, |
21042 |
-+ copy_len, 0, &page, &fsdata); |
21043 |
-+ if (unlikely(status < 0)) { |
21044 |
-+ ret = status; |
21045 |
-+ break; |
21046 |
-+ } |
21047 |
-+ |
21048 |
-+ kaddr = (char __force __user *)kmap(page) + page_off; |
21049 |
-+ n_read = __vfs_read(f_src, kaddr, copy_len, &off_src); |
21050 |
-+ kunmap(page); |
21051 |
-+ mark_page_accessed(page); |
21052 |
-+ flush_dcache_page(page); |
21053 |
-+ |
21054 |
-+ if (unlikely(n_read != copy_len)) { |
21055 |
-+ ret = -EFAULT; |
21056 |
-+ break; |
21057 |
-+ } |
21058 |
-+ |
21059 |
-+ status = aops->write_end(f_dst, mapping_dst, off_dst, |
21060 |
-+ copy_len, copy_len, page, fsdata); |
21061 |
-+ if (unlikely(status != copy_len)) { |
21062 |
-+ ret = -EFAULT; |
21063 |
-+ break; |
21064 |
-+ } |
21065 |
-+ |
21066 |
-+ off_dst += copy_len; |
21067 |
-+ len -= copy_len; |
21068 |
-+ } |
21069 |
-+ set_fs(old_fs); |
21070 |
-+ mutex_unlock(&i_dst->i_mutex); |
21071 |
-+ |
21072 |
-+ return ret; |
21073 |
-+} |
21074 |
-+ |
21075 |
-+/** |
21076 |
-+ * kdbus_pool_mmap() - map the pool into the process |
21077 |
-+ * @pool: The receiver's pool |
21078 |
-+ * @vma: passed by mmap() syscall |
21079 |
-+ * |
21080 |
-+ * Return: the result of the mmap() call, negative errno on failure. |
21081 |
-+ */ |
21082 |
-+int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma) |
21083 |
-+{ |
21084 |
-+ /* deny write access to the pool */ |
21085 |
-+ if (vma->vm_flags & VM_WRITE) |
21086 |
-+ return -EPERM; |
21087 |
-+ vma->vm_flags &= ~VM_MAYWRITE; |
21088 |
-+ |
21089 |
-+ /* do not allow to map more than the size of the file */ |
21090 |
-+ if ((vma->vm_end - vma->vm_start) > pool->size) |
21091 |
-+ return -EFAULT; |
21092 |
-+ |
21093 |
-+ /* replace the connection file with our shmem file */ |
21094 |
-+ if (vma->vm_file) |
21095 |
-+ fput(vma->vm_file); |
21096 |
-+ vma->vm_file = get_file(pool->f); |
21097 |
-+ |
21098 |
-+ return pool->f->f_op->mmap(pool->f, vma); |
21099 |
-+} |
21100 |
-diff --git a/ipc/kdbus/pool.h b/ipc/kdbus/pool.h |
21101 |
-new file mode 100644 |
21102 |
-index 0000000..a903821 |
21103 |
---- /dev/null |
21104 |
-+++ b/ipc/kdbus/pool.h |
21105 |
-@@ -0,0 +1,46 @@ |
21106 |
-+/* |
21107 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21108 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21109 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21110 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21111 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21112 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21113 |
-+ * |
21114 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21115 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21116 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21117 |
-+ * your option) any later version. |
21118 |
-+ */ |
21119 |
-+ |
21120 |
-+#ifndef __KDBUS_POOL_H |
21121 |
-+#define __KDBUS_POOL_H |
21122 |
-+ |
21123 |
-+#include <linux/uio.h> |
21124 |
-+ |
21125 |
-+struct kdbus_pool; |
21126 |
-+struct kdbus_pool_slice; |
21127 |
-+ |
21128 |
-+struct kdbus_pool *kdbus_pool_new(const char *name, size_t size); |
21129 |
-+void kdbus_pool_free(struct kdbus_pool *pool); |
21130 |
-+void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc); |
21131 |
-+int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma); |
21132 |
-+int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off); |
21133 |
-+void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size); |
21134 |
-+ |
21135 |
-+struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, |
21136 |
-+ size_t size, bool accounted); |
21137 |
-+void kdbus_pool_slice_release(struct kdbus_pool_slice *slice); |
21138 |
-+void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, |
21139 |
-+ u64 *out_offset, u64 *out_size); |
21140 |
-+off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice); |
21141 |
-+size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice); |
21142 |
-+int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, |
21143 |
-+ const struct kdbus_pool_slice *slice_src); |
21144 |
-+ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, |
21145 |
-+ loff_t off, struct kvec *kvec, |
21146 |
-+ size_t kvec_count, size_t total_len); |
21147 |
-+ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, |
21148 |
-+ loff_t off, struct iovec *iov, |
21149 |
-+ size_t iov_count, size_t total_len); |
21150 |
-+ |
21151 |
-+#endif |
21152 |
-diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c |
21153 |
-new file mode 100644 |
21154 |
-index 0000000..f9c44d7 |
21155 |
---- /dev/null |
21156 |
-+++ b/ipc/kdbus/queue.c |
21157 |
-@@ -0,0 +1,363 @@ |
21158 |
-+/* |
21159 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21160 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21161 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21162 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21163 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21164 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21165 |
-+ * |
21166 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21167 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21168 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21169 |
-+ * your option) any later version. |
21170 |
-+ */ |
21171 |
-+ |
21172 |
-+#include <linux/audit.h> |
21173 |
-+#include <linux/file.h> |
21174 |
-+#include <linux/fs.h> |
21175 |
-+#include <linux/hashtable.h> |
21176 |
-+#include <linux/idr.h> |
21177 |
-+#include <linux/init.h> |
21178 |
-+#include <linux/math64.h> |
21179 |
-+#include <linux/mm.h> |
21180 |
-+#include <linux/module.h> |
21181 |
-+#include <linux/mutex.h> |
21182 |
-+#include <linux/poll.h> |
21183 |
-+#include <linux/sched.h> |
21184 |
-+#include <linux/sizes.h> |
21185 |
-+#include <linux/slab.h> |
21186 |
-+#include <linux/syscalls.h> |
21187 |
-+#include <linux/uio.h> |
21188 |
-+ |
21189 |
-+#include "util.h" |
21190 |
-+#include "domain.h" |
21191 |
-+#include "connection.h" |
21192 |
-+#include "item.h" |
21193 |
-+#include "message.h" |
21194 |
-+#include "metadata.h" |
21195 |
-+#include "queue.h" |
21196 |
-+#include "reply.h" |
21197 |
-+ |
21198 |
-+/** |
21199 |
-+ * kdbus_queue_init() - initialize data structure related to a queue |
21200 |
-+ * @queue: The queue to initialize |
21201 |
-+ */ |
21202 |
-+void kdbus_queue_init(struct kdbus_queue *queue) |
21203 |
-+{ |
21204 |
-+ INIT_LIST_HEAD(&queue->msg_list); |
21205 |
-+ queue->msg_prio_queue = RB_ROOT; |
21206 |
-+} |
21207 |
-+ |
21208 |
-+/** |
21209 |
-+ * kdbus_queue_peek() - Retrieves an entry from a queue |
21210 |
-+ * @queue: The queue |
21211 |
-+ * @priority: The minimum priority of the entry to peek |
21212 |
-+ * @use_priority: Boolean flag whether or not to peek by priority |
21213 |
-+ * |
21214 |
-+ * Look for a entry in a queue, either by priority, or the oldest one (FIFO). |
21215 |
-+ * The entry is not freed, put off the queue's lists or anything else. |
21216 |
-+ * |
21217 |
-+ * Return: the peeked queue entry on success, NULL if no suitable msg is found |
21218 |
-+ */ |
21219 |
-+struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, |
21220 |
-+ s64 priority, bool use_priority) |
21221 |
-+{ |
21222 |
-+ struct kdbus_queue_entry *e; |
21223 |
-+ |
21224 |
-+ if (list_empty(&queue->msg_list)) |
21225 |
-+ return NULL; |
21226 |
-+ |
21227 |
-+ if (use_priority) { |
21228 |
-+ /* get next entry with highest priority */ |
21229 |
-+ e = rb_entry(queue->msg_prio_highest, |
21230 |
-+ struct kdbus_queue_entry, prio_node); |
21231 |
-+ |
21232 |
-+ /* no entry with the requested priority */ |
21233 |
-+ if (e->priority > priority) |
21234 |
-+ return NULL; |
21235 |
-+ } else { |
21236 |
-+ /* ignore the priority, return the next entry in the entry */ |
21237 |
-+ e = list_first_entry(&queue->msg_list, |
21238 |
-+ struct kdbus_queue_entry, entry); |
21239 |
-+ } |
21240 |
-+ |
21241 |
-+ return e; |
21242 |
-+} |
21243 |
-+ |
21244 |
-+static void kdbus_queue_entry_link(struct kdbus_queue_entry *entry) |
21245 |
-+{ |
21246 |
-+ struct kdbus_queue *queue = &entry->conn->queue; |
21247 |
-+ struct rb_node **n, *pn = NULL; |
21248 |
-+ bool highest = true; |
21249 |
-+ |
21250 |
-+ lockdep_assert_held(&entry->conn->lock); |
21251 |
-+ if (WARN_ON(!list_empty(&entry->entry))) |
21252 |
-+ return; |
21253 |
-+ |
21254 |
-+ /* sort into priority entry tree */ |
21255 |
-+ n = &queue->msg_prio_queue.rb_node; |
21256 |
-+ while (*n) { |
21257 |
-+ struct kdbus_queue_entry *e; |
21258 |
-+ |
21259 |
-+ pn = *n; |
21260 |
-+ e = rb_entry(pn, struct kdbus_queue_entry, prio_node); |
21261 |
-+ |
21262 |
-+ /* existing node for this priority, add to its list */ |
21263 |
-+ if (likely(entry->priority == e->priority)) { |
21264 |
-+ list_add_tail(&entry->prio_entry, &e->prio_entry); |
21265 |
-+ goto prio_done; |
21266 |
-+ } |
21267 |
-+ |
21268 |
-+ if (entry->priority < e->priority) { |
21269 |
-+ n = &pn->rb_left; |
21270 |
-+ } else { |
21271 |
-+ n = &pn->rb_right; |
21272 |
-+ highest = false; |
21273 |
-+ } |
21274 |
-+ } |
21275 |
-+ |
21276 |
-+ /* cache highest-priority entry */ |
21277 |
-+ if (highest) |
21278 |
-+ queue->msg_prio_highest = &entry->prio_node; |
21279 |
-+ |
21280 |
-+ /* new node for this priority */ |
21281 |
-+ rb_link_node(&entry->prio_node, pn, n); |
21282 |
-+ rb_insert_color(&entry->prio_node, &queue->msg_prio_queue); |
21283 |
-+ INIT_LIST_HEAD(&entry->prio_entry); |
21284 |
-+ |
21285 |
-+prio_done: |
21286 |
-+ /* add to unsorted fifo list */ |
21287 |
-+ list_add_tail(&entry->entry, &queue->msg_list); |
21288 |
-+} |
21289 |
-+ |
21290 |
-+static void kdbus_queue_entry_unlink(struct kdbus_queue_entry *entry) |
21291 |
-+{ |
21292 |
-+ struct kdbus_queue *queue = &entry->conn->queue; |
21293 |
-+ |
21294 |
-+ lockdep_assert_held(&entry->conn->lock); |
21295 |
-+ if (list_empty(&entry->entry)) |
21296 |
-+ return; |
21297 |
-+ |
21298 |
-+ list_del_init(&entry->entry); |
21299 |
-+ |
21300 |
-+ if (list_empty(&entry->prio_entry)) { |
21301 |
-+ /* |
21302 |
-+ * Single entry for this priority, update cached |
21303 |
-+ * highest-priority entry, remove the tree node. |
21304 |
-+ */ |
21305 |
-+ if (queue->msg_prio_highest == &entry->prio_node) |
21306 |
-+ queue->msg_prio_highest = rb_next(&entry->prio_node); |
21307 |
-+ |
21308 |
-+ rb_erase(&entry->prio_node, &queue->msg_prio_queue); |
21309 |
-+ } else { |
21310 |
-+ struct kdbus_queue_entry *q; |
21311 |
-+ |
21312 |
-+ /* |
21313 |
-+ * Multiple entries for this priority entry, get next one in |
21314 |
-+ * the list. Update cached highest-priority entry, store the |
21315 |
-+ * new one as the tree node. |
21316 |
-+ */ |
21317 |
-+ q = list_first_entry(&entry->prio_entry, |
21318 |
-+ struct kdbus_queue_entry, prio_entry); |
21319 |
-+ list_del(&entry->prio_entry); |
21320 |
-+ |
21321 |
-+ if (queue->msg_prio_highest == &entry->prio_node) |
21322 |
-+ queue->msg_prio_highest = &q->prio_node; |
21323 |
-+ |
21324 |
-+ rb_replace_node(&entry->prio_node, &q->prio_node, |
21325 |
-+ &queue->msg_prio_queue); |
21326 |
-+ } |
21327 |
-+} |
21328 |
-+ |
21329 |
-+/** |
21330 |
-+ * kdbus_queue_entry_new() - allocate a queue entry |
21331 |
-+ * @src: source connection, or NULL |
21332 |
-+ * @dst: destination connection |
21333 |
-+ * @s: staging object carrying the message |
21334 |
-+ * |
21335 |
-+ * Allocates a queue entry based on a given msg and allocate space for |
21336 |
-+ * the message payload and the requested metadata in the connection's pool. |
21337 |
-+ * The entry is not actually added to the queue's lists at this point. |
21338 |
-+ * |
21339 |
-+ * Return: the allocated entry on success, or an ERR_PTR on failures. |
21340 |
-+ */ |
21341 |
-+struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src, |
21342 |
-+ struct kdbus_conn *dst, |
21343 |
-+ struct kdbus_staging *s) |
21344 |
-+{ |
21345 |
-+ struct kdbus_queue_entry *entry; |
21346 |
-+ int ret; |
21347 |
-+ |
21348 |
-+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
21349 |
-+ if (!entry) |
21350 |
-+ return ERR_PTR(-ENOMEM); |
21351 |
-+ |
21352 |
-+ INIT_LIST_HEAD(&entry->entry); |
21353 |
-+ entry->priority = s->msg->priority; |
21354 |
-+ entry->conn = kdbus_conn_ref(dst); |
21355 |
-+ entry->gaps = kdbus_gaps_ref(s->gaps); |
21356 |
-+ |
21357 |
-+ entry->slice = kdbus_staging_emit(s, src, dst); |
21358 |
-+ if (IS_ERR(entry->slice)) { |
21359 |
-+ ret = PTR_ERR(entry->slice); |
21360 |
-+ entry->slice = NULL; |
21361 |
-+ goto error; |
21362 |
-+ } |
21363 |
-+ |
21364 |
-+ entry->user = src ? kdbus_user_ref(src->user) : NULL; |
21365 |
-+ return entry; |
21366 |
-+ |
21367 |
-+error: |
21368 |
-+ kdbus_queue_entry_free(entry); |
21369 |
-+ return ERR_PTR(ret); |
21370 |
-+} |
21371 |
-+ |
21372 |
-+/** |
21373 |
-+ * kdbus_queue_entry_free() - free resources of an entry |
21374 |
-+ * @entry: The entry to free |
21375 |
-+ * |
21376 |
-+ * Removes resources allocated by a queue entry, along with the entry itself. |
21377 |
-+ * Note that the entry's slice is not freed at this point. |
21378 |
-+ */ |
21379 |
-+void kdbus_queue_entry_free(struct kdbus_queue_entry *entry) |
21380 |
-+{ |
21381 |
-+ if (!entry) |
21382 |
-+ return; |
21383 |
-+ |
21384 |
-+ lockdep_assert_held(&entry->conn->lock); |
21385 |
-+ |
21386 |
-+ kdbus_queue_entry_unlink(entry); |
21387 |
-+ kdbus_reply_unref(entry->reply); |
21388 |
-+ |
21389 |
-+ if (entry->slice) { |
21390 |
-+ kdbus_conn_quota_dec(entry->conn, entry->user, |
21391 |
-+ kdbus_pool_slice_size(entry->slice), |
21392 |
-+ entry->gaps ? entry->gaps->n_fds : 0); |
21393 |
-+ kdbus_pool_slice_release(entry->slice); |
21394 |
-+ } |
21395 |
-+ |
21396 |
-+ kdbus_user_unref(entry->user); |
21397 |
-+ kdbus_gaps_unref(entry->gaps); |
21398 |
-+ kdbus_conn_unref(entry->conn); |
21399 |
-+ kfree(entry); |
21400 |
-+} |
21401 |
-+ |
21402 |
-+/** |
21403 |
-+ * kdbus_queue_entry_install() - install message components into the |
21404 |
-+ * receiver's process |
21405 |
-+ * @entry: The queue entry to install |
21406 |
-+ * @return_flags: Pointer to store the return flags for userspace |
21407 |
-+ * @install_fds: Whether or not to install associated file descriptors |
21408 |
-+ * |
21409 |
-+ * Return: 0 on success. |
21410 |
-+ */ |
21411 |
-+int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, |
21412 |
-+ u64 *return_flags, bool install_fds) |
21413 |
-+{ |
21414 |
-+ bool incomplete_fds = false; |
21415 |
-+ int ret; |
21416 |
-+ |
21417 |
-+ lockdep_assert_held(&entry->conn->lock); |
21418 |
-+ |
21419 |
-+ ret = kdbus_gaps_install(entry->gaps, entry->slice, &incomplete_fds); |
21420 |
-+ if (ret < 0) |
21421 |
-+ return ret; |
21422 |
-+ |
21423 |
-+ if (incomplete_fds) |
21424 |
-+ *return_flags |= KDBUS_RECV_RETURN_INCOMPLETE_FDS; |
21425 |
-+ return 0; |
21426 |
-+} |
21427 |
-+ |
21428 |
-+/** |
21429 |
-+ * kdbus_queue_entry_enqueue() - enqueue an entry |
21430 |
-+ * @entry: entry to enqueue |
21431 |
-+ * @reply: reply to link to this entry (or NULL if none) |
21432 |
-+ * |
21433 |
-+ * This enqueues an unqueued entry into the message queue of the linked |
21434 |
-+ * connection. It also binds a reply object to the entry so we can remember it |
21435 |
-+ * when the message is moved. |
21436 |
-+ * |
21437 |
-+ * Once this call returns (and the connection lock is released), this entry can |
21438 |
-+ * be dequeued by the target connection. Note that the entry will not be removed |
21439 |
-+ * from the queue until it is destroyed. |
21440 |
-+ */ |
21441 |
-+void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, |
21442 |
-+ struct kdbus_reply *reply) |
21443 |
-+{ |
21444 |
-+ lockdep_assert_held(&entry->conn->lock); |
21445 |
-+ |
21446 |
-+ if (WARN_ON(entry->reply) || WARN_ON(!list_empty(&entry->entry))) |
21447 |
-+ return; |
21448 |
-+ |
21449 |
-+ entry->reply = kdbus_reply_ref(reply); |
21450 |
-+ kdbus_queue_entry_link(entry); |
21451 |
-+} |
21452 |
-+ |
21453 |
-+/** |
21454 |
-+ * kdbus_queue_entry_move() - move queue entry |
21455 |
-+ * @e: queue entry to move |
21456 |
-+ * @dst: destination connection to queue the entry on |
21457 |
-+ * |
21458 |
-+ * This moves a queue entry onto a different connection. It allocates a new |
21459 |
-+ * slice on the target connection and copies the message over. If the copy |
21460 |
-+ * succeeded, we move the entry from @src to @dst. |
21461 |
-+ * |
21462 |
-+ * On failure, the entry is left untouched. |
21463 |
-+ * |
21464 |
-+ * The queue entry must be queued right now, and after the call succeeds it will |
21465 |
-+ * be queued on the destination, but no longer on the source. |
21466 |
-+ * |
21467 |
-+ * The caller must hold the connection lock of the source *and* destination. |
21468 |
-+ * |
21469 |
-+ * Return: 0 on success, negative error code on failure. |
21470 |
-+ */ |
21471 |
-+int kdbus_queue_entry_move(struct kdbus_queue_entry *e, |
21472 |
-+ struct kdbus_conn *dst) |
21473 |
-+{ |
21474 |
-+ struct kdbus_pool_slice *slice = NULL; |
21475 |
-+ struct kdbus_conn *src = e->conn; |
21476 |
-+ size_t size, fds; |
21477 |
-+ int ret; |
21478 |
-+ |
21479 |
-+ lockdep_assert_held(&src->lock); |
21480 |
-+ lockdep_assert_held(&dst->lock); |
21481 |
-+ |
21482 |
-+ if (WARN_ON(list_empty(&e->entry))) |
21483 |
-+ return -EINVAL; |
21484 |
-+ if (src == dst) |
21485 |
-+ return 0; |
21486 |
-+ |
21487 |
-+ size = kdbus_pool_slice_size(e->slice); |
21488 |
-+ fds = e->gaps ? e->gaps->n_fds : 0; |
21489 |
-+ |
21490 |
-+ ret = kdbus_conn_quota_inc(dst, e->user, size, fds); |
21491 |
-+ if (ret < 0) |
21492 |
-+ return ret; |
21493 |
-+ |
21494 |
-+ slice = kdbus_pool_slice_alloc(dst->pool, size, true); |
21495 |
-+ if (IS_ERR(slice)) { |
21496 |
-+ ret = PTR_ERR(slice); |
21497 |
-+ slice = NULL; |
21498 |
-+ goto error; |
21499 |
-+ } |
21500 |
-+ |
21501 |
-+ ret = kdbus_pool_slice_copy(slice, e->slice); |
21502 |
-+ if (ret < 0) |
21503 |
-+ goto error; |
21504 |
-+ |
21505 |
-+ kdbus_queue_entry_unlink(e); |
21506 |
-+ kdbus_conn_quota_dec(src, e->user, size, fds); |
21507 |
-+ kdbus_pool_slice_release(e->slice); |
21508 |
-+ kdbus_conn_unref(e->conn); |
21509 |
-+ |
21510 |
-+ e->slice = slice; |
21511 |
-+ e->conn = kdbus_conn_ref(dst); |
21512 |
-+ kdbus_queue_entry_link(e); |
21513 |
-+ |
21514 |
-+ return 0; |
21515 |
-+ |
21516 |
-+error: |
21517 |
-+ kdbus_pool_slice_release(slice); |
21518 |
-+ kdbus_conn_quota_dec(dst, e->user, size, fds); |
21519 |
-+ return ret; |
21520 |
-+} |
21521 |
-diff --git a/ipc/kdbus/queue.h b/ipc/kdbus/queue.h |
21522 |
-new file mode 100644 |
21523 |
-index 0000000..bf686d1 |
21524 |
---- /dev/null |
21525 |
-+++ b/ipc/kdbus/queue.h |
21526 |
-@@ -0,0 +1,84 @@ |
21527 |
-+/* |
21528 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21529 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21530 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21531 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21532 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21533 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21534 |
-+ * |
21535 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21536 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21537 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21538 |
-+ * your option) any later version. |
21539 |
-+ */ |
21540 |
-+ |
21541 |
-+#ifndef __KDBUS_QUEUE_H |
21542 |
-+#define __KDBUS_QUEUE_H |
21543 |
-+ |
21544 |
-+#include <linux/list.h> |
21545 |
-+#include <linux/rbtree.h> |
21546 |
-+ |
21547 |
-+struct kdbus_conn; |
21548 |
-+struct kdbus_pool_slice; |
21549 |
-+struct kdbus_reply; |
21550 |
-+struct kdbus_staging; |
21551 |
-+struct kdbus_user; |
21552 |
-+ |
21553 |
-+/** |
21554 |
-+ * struct kdbus_queue - a connection's message queue |
21555 |
-+ * @msg_list: List head for kdbus_queue_entry objects |
21556 |
-+ * @msg_prio_queue: RB tree root for messages, sorted by priority |
21557 |
-+ * @msg_prio_highest: Link to the RB node referencing the message with the |
21558 |
-+ * highest priority in the tree. |
21559 |
-+ */ |
21560 |
-+struct kdbus_queue { |
21561 |
-+ struct list_head msg_list; |
21562 |
-+ struct rb_root msg_prio_queue; |
21563 |
-+ struct rb_node *msg_prio_highest; |
21564 |
-+}; |
21565 |
-+ |
21566 |
-+/** |
21567 |
-+ * struct kdbus_queue_entry - messages waiting to be read |
21568 |
-+ * @entry: Entry in the connection's list |
21569 |
-+ * @prio_node: Entry in the priority queue tree |
21570 |
-+ * @prio_entry: Queue tree node entry in the list of one priority |
21571 |
-+ * @priority: Message priority |
21572 |
-+ * @dst_name_id: The sequence number of the name this message is |
21573 |
-+ * addressed to, 0 for messages sent to an ID |
21574 |
-+ * @conn: Connection this entry is queued on |
21575 |
-+ * @gaps: Gaps object to fill message gaps at RECV time |
21576 |
-+ * @user: User used for accounting |
21577 |
-+ * @slice: Slice in the receiver's pool for the message |
21578 |
-+ * @reply: The reply block if a reply to this message is expected |
21579 |
-+ */ |
21580 |
-+struct kdbus_queue_entry { |
21581 |
-+ struct list_head entry; |
21582 |
-+ struct rb_node prio_node; |
21583 |
-+ struct list_head prio_entry; |
21584 |
-+ |
21585 |
-+ s64 priority; |
21586 |
-+ u64 dst_name_id; |
21587 |
-+ |
21588 |
-+ struct kdbus_conn *conn; |
21589 |
-+ struct kdbus_gaps *gaps; |
21590 |
-+ struct kdbus_user *user; |
21591 |
-+ struct kdbus_pool_slice *slice; |
21592 |
-+ struct kdbus_reply *reply; |
21593 |
-+}; |
21594 |
-+ |
21595 |
-+void kdbus_queue_init(struct kdbus_queue *queue); |
21596 |
-+struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, |
21597 |
-+ s64 priority, bool use_priority); |
21598 |
-+ |
21599 |
-+struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src, |
21600 |
-+ struct kdbus_conn *dst, |
21601 |
-+ struct kdbus_staging *s); |
21602 |
-+void kdbus_queue_entry_free(struct kdbus_queue_entry *entry); |
21603 |
-+int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, |
21604 |
-+ u64 *return_flags, bool install_fds); |
21605 |
-+void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, |
21606 |
-+ struct kdbus_reply *reply); |
21607 |
-+int kdbus_queue_entry_move(struct kdbus_queue_entry *entry, |
21608 |
-+ struct kdbus_conn *dst); |
21609 |
-+ |
21610 |
-+#endif /* __KDBUS_QUEUE_H */ |
21611 |
-diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c |
21612 |
-new file mode 100644 |
21613 |
-index 0000000..e6791d8 |
21614 |
---- /dev/null |
21615 |
-+++ b/ipc/kdbus/reply.c |
21616 |
-@@ -0,0 +1,252 @@ |
21617 |
-+#include <linux/init.h> |
21618 |
-+#include <linux/mm.h> |
21619 |
-+#include <linux/module.h> |
21620 |
-+#include <linux/mutex.h> |
21621 |
-+#include <linux/slab.h> |
21622 |
-+#include <linux/uio.h> |
21623 |
-+ |
21624 |
-+#include "bus.h" |
21625 |
-+#include "connection.h" |
21626 |
-+#include "endpoint.h" |
21627 |
-+#include "message.h" |
21628 |
-+#include "metadata.h" |
21629 |
-+#include "names.h" |
21630 |
-+#include "domain.h" |
21631 |
-+#include "item.h" |
21632 |
-+#include "notify.h" |
21633 |
-+#include "policy.h" |
21634 |
-+#include "reply.h" |
21635 |
-+#include "util.h" |
21636 |
-+ |
21637 |
-+/** |
21638 |
-+ * kdbus_reply_new() - Allocate and set up a new kdbus_reply object |
21639 |
-+ * @reply_src: The connection a reply is expected from |
21640 |
-+ * @reply_dst: The connection this reply object belongs to |
21641 |
-+ * @msg: Message associated with the reply |
21642 |
-+ * @name_entry: Name entry used to send the message |
21643 |
-+ * @sync: Whether or not to make this reply synchronous |
21644 |
-+ * |
21645 |
-+ * Allocate and fill a new kdbus_reply object. |
21646 |
-+ * |
21647 |
-+ * Return: New kdbus_conn object on success, ERR_PTR on error. |
21648 |
-+ */ |
21649 |
-+struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, |
21650 |
-+ struct kdbus_conn *reply_dst, |
21651 |
-+ const struct kdbus_msg *msg, |
21652 |
-+ struct kdbus_name_entry *name_entry, |
21653 |
-+ bool sync) |
21654 |
-+{ |
21655 |
-+ struct kdbus_reply *r; |
21656 |
-+ int ret; |
21657 |
-+ |
21658 |
-+ if (atomic_inc_return(&reply_dst->request_count) > |
21659 |
-+ KDBUS_CONN_MAX_REQUESTS_PENDING) { |
21660 |
-+ ret = -EMLINK; |
21661 |
-+ goto exit_dec_request_count; |
21662 |
-+ } |
21663 |
-+ |
21664 |
-+ r = kzalloc(sizeof(*r), GFP_KERNEL); |
21665 |
-+ if (!r) { |
21666 |
-+ ret = -ENOMEM; |
21667 |
-+ goto exit_dec_request_count; |
21668 |
-+ } |
21669 |
-+ |
21670 |
-+ kref_init(&r->kref); |
21671 |
-+ INIT_LIST_HEAD(&r->entry); |
21672 |
-+ r->reply_src = kdbus_conn_ref(reply_src); |
21673 |
-+ r->reply_dst = kdbus_conn_ref(reply_dst); |
21674 |
-+ r->cookie = msg->cookie; |
21675 |
-+ r->name_id = name_entry ? name_entry->name_id : 0; |
21676 |
-+ r->deadline_ns = msg->timeout_ns; |
21677 |
-+ |
21678 |
-+ if (sync) { |
21679 |
-+ r->sync = true; |
21680 |
-+ r->waiting = true; |
21681 |
-+ } |
21682 |
-+ |
21683 |
-+ return r; |
21684 |
-+ |
21685 |
-+exit_dec_request_count: |
21686 |
-+ atomic_dec(&reply_dst->request_count); |
21687 |
-+ return ERR_PTR(ret); |
21688 |
-+} |
21689 |
-+ |
21690 |
-+static void __kdbus_reply_free(struct kref *kref) |
21691 |
-+{ |
21692 |
-+ struct kdbus_reply *reply = |
21693 |
-+ container_of(kref, struct kdbus_reply, kref); |
21694 |
-+ |
21695 |
-+ atomic_dec(&reply->reply_dst->request_count); |
21696 |
-+ kdbus_conn_unref(reply->reply_src); |
21697 |
-+ kdbus_conn_unref(reply->reply_dst); |
21698 |
-+ kfree(reply); |
21699 |
-+} |
21700 |
-+ |
21701 |
-+/** |
21702 |
-+ * kdbus_reply_ref() - Increase reference on kdbus_reply |
21703 |
-+ * @r: The reply, may be %NULL |
21704 |
-+ * |
21705 |
-+ * Return: The reply object with an extra reference |
21706 |
-+ */ |
21707 |
-+struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r) |
21708 |
-+{ |
21709 |
-+ if (r) |
21710 |
-+ kref_get(&r->kref); |
21711 |
-+ return r; |
21712 |
-+} |
21713 |
-+ |
21714 |
-+/** |
21715 |
-+ * kdbus_reply_unref() - Decrease reference on kdbus_reply |
21716 |
-+ * @r: The reply, may be %NULL |
21717 |
-+ * |
21718 |
-+ * Return: NULL |
21719 |
-+ */ |
21720 |
-+struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r) |
21721 |
-+{ |
21722 |
-+ if (r) |
21723 |
-+ kref_put(&r->kref, __kdbus_reply_free); |
21724 |
-+ return NULL; |
21725 |
-+} |
21726 |
-+ |
21727 |
-+/** |
21728 |
-+ * kdbus_reply_link() - Link reply object into target connection |
21729 |
-+ * @r: Reply to link |
21730 |
-+ */ |
21731 |
-+void kdbus_reply_link(struct kdbus_reply *r) |
21732 |
-+{ |
21733 |
-+ if (WARN_ON(!list_empty(&r->entry))) |
21734 |
-+ return; |
21735 |
-+ |
21736 |
-+ list_add(&r->entry, &r->reply_dst->reply_list); |
21737 |
-+ kdbus_reply_ref(r); |
21738 |
-+} |
21739 |
-+ |
21740 |
-+/** |
21741 |
-+ * kdbus_reply_unlink() - Unlink reply object from target connection |
21742 |
-+ * @r: Reply to unlink |
21743 |
-+ */ |
21744 |
-+void kdbus_reply_unlink(struct kdbus_reply *r) |
21745 |
-+{ |
21746 |
-+ if (!list_empty(&r->entry)) { |
21747 |
-+ list_del_init(&r->entry); |
21748 |
-+ kdbus_reply_unref(r); |
21749 |
-+ } |
21750 |
-+} |
21751 |
-+ |
21752 |
-+/** |
21753 |
-+ * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply |
21754 |
-+ * @reply: The reply object |
21755 |
-+ * @err: Error code to set on the remote side |
21756 |
-+ * |
21757 |
-+ * Wake up remote peer (method origin) with the appropriate synchronous reply |
21758 |
-+ * code. |
21759 |
-+ */ |
21760 |
-+void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err) |
21761 |
-+{ |
21762 |
-+ if (WARN_ON(!reply->sync)) |
21763 |
-+ return; |
21764 |
-+ |
21765 |
-+ reply->waiting = false; |
21766 |
-+ reply->err = err; |
21767 |
-+ wake_up_interruptible(&reply->reply_dst->wait); |
21768 |
-+} |
21769 |
-+ |
21770 |
-+/** |
21771 |
-+ * kdbus_reply_find() - Find the corresponding reply object |
21772 |
-+ * @replying: The replying connection or NULL |
21773 |
-+ * @reply_dst: The connection the reply will be sent to |
21774 |
-+ * (method origin) |
21775 |
-+ * @cookie: The cookie of the requesting message |
21776 |
-+ * |
21777 |
-+ * Lookup a reply object that should be sent as a reply by |
21778 |
-+ * @replying to @reply_dst with the given cookie. |
21779 |
-+ * |
21780 |
-+ * Callers must take the @reply_dst lock. |
21781 |
-+ * |
21782 |
-+ * Return: the corresponding reply object or NULL if not found |
21783 |
-+ */ |
21784 |
-+struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, |
21785 |
-+ struct kdbus_conn *reply_dst, |
21786 |
-+ u64 cookie) |
21787 |
-+{ |
21788 |
-+ struct kdbus_reply *r; |
21789 |
-+ |
21790 |
-+ list_for_each_entry(r, &reply_dst->reply_list, entry) { |
21791 |
-+ if (r->cookie == cookie && |
21792 |
-+ (!replying || r->reply_src == replying)) |
21793 |
-+ return r; |
21794 |
-+ } |
21795 |
-+ |
21796 |
-+ return NULL; |
21797 |
-+} |
21798 |
-+ |
21799 |
-+/** |
21800 |
-+ * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a |
21801 |
-+ * connection for exceeded timeouts |
21802 |
-+ * @work: Work struct of the connection to scan |
21803 |
-+ * |
21804 |
-+ * Walk the list of replies stored with a connection and look for entries |
21805 |
-+ * that have exceeded their timeout. If such an entry is found, a timeout |
21806 |
-+ * notification is sent to the waiting peer, and the reply is removed from |
21807 |
-+ * the list. |
21808 |
-+ * |
21809 |
-+ * The work is rescheduled to the nearest timeout found during the list |
21810 |
-+ * iteration. |
21811 |
-+ */ |
21812 |
-+void kdbus_reply_list_scan_work(struct work_struct *work) |
21813 |
-+{ |
21814 |
-+ struct kdbus_conn *conn = |
21815 |
-+ container_of(work, struct kdbus_conn, work.work); |
21816 |
-+ struct kdbus_reply *reply, *reply_tmp; |
21817 |
-+ u64 deadline = ~0ULL; |
21818 |
-+ u64 now; |
21819 |
-+ |
21820 |
-+ now = ktime_get_ns(); |
21821 |
-+ |
21822 |
-+ mutex_lock(&conn->lock); |
21823 |
-+ if (!kdbus_conn_active(conn)) { |
21824 |
-+ mutex_unlock(&conn->lock); |
21825 |
-+ return; |
21826 |
-+ } |
21827 |
-+ |
21828 |
-+ list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) { |
21829 |
-+ /* |
21830 |
-+ * If the reply block is waiting for synchronous I/O, |
21831 |
-+ * the timeout is handled by wait_event_*_timeout(), |
21832 |
-+ * so we don't have to care for it here. |
21833 |
-+ */ |
21834 |
-+ if (reply->sync && !reply->interrupted) |
21835 |
-+ continue; |
21836 |
-+ |
21837 |
-+ WARN_ON(reply->reply_dst != conn); |
21838 |
-+ |
21839 |
-+ if (reply->deadline_ns > now) { |
21840 |
-+ /* remember next timeout */ |
21841 |
-+ if (deadline > reply->deadline_ns) |
21842 |
-+ deadline = reply->deadline_ns; |
21843 |
-+ |
21844 |
-+ continue; |
21845 |
-+ } |
21846 |
-+ |
21847 |
-+ /* |
21848 |
-+ * A zero deadline means the connection died, was |
21849 |
-+ * cleaned up already and the notification was sent. |
21850 |
-+ * Don't send notifications for reply trackers that were |
21851 |
-+ * left in an interrupted syscall state. |
21852 |
-+ */ |
21853 |
-+ if (reply->deadline_ns != 0 && !reply->interrupted) |
21854 |
-+ kdbus_notify_reply_timeout(conn->ep->bus, conn->id, |
21855 |
-+ reply->cookie); |
21856 |
-+ |
21857 |
-+ kdbus_reply_unlink(reply); |
21858 |
-+ } |
21859 |
-+ |
21860 |
-+ /* rearm delayed work with next timeout */ |
21861 |
-+ if (deadline != ~0ULL) |
21862 |
-+ schedule_delayed_work(&conn->work, |
21863 |
-+ nsecs_to_jiffies(deadline - now)); |
21864 |
-+ |
21865 |
-+ mutex_unlock(&conn->lock); |
21866 |
-+ |
21867 |
-+ kdbus_notify_flush(conn->ep->bus); |
21868 |
-+} |
21869 |
-diff --git a/ipc/kdbus/reply.h b/ipc/kdbus/reply.h |
21870 |
-new file mode 100644 |
21871 |
-index 0000000..68d5232 |
21872 |
---- /dev/null |
21873 |
-+++ b/ipc/kdbus/reply.h |
21874 |
-@@ -0,0 +1,68 @@ |
21875 |
-+/* |
21876 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21877 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21878 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21879 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21880 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21881 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21882 |
-+ * |
21883 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21884 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21885 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21886 |
-+ * your option) any later version. |
21887 |
-+ */ |
21888 |
-+ |
21889 |
-+#ifndef __KDBUS_REPLY_H |
21890 |
-+#define __KDBUS_REPLY_H |
21891 |
-+ |
21892 |
-+/** |
21893 |
-+ * struct kdbus_reply - an entry of kdbus_conn's list of replies |
21894 |
-+ * @kref: Ref-count of this object |
21895 |
-+ * @entry: The entry of the connection's reply_list |
21896 |
-+ * @reply_src: The connection the reply will be sent from |
21897 |
-+ * @reply_dst: The connection the reply will be sent to |
21898 |
-+ * @queue_entry: The queue entry item that is prepared by the replying |
21899 |
-+ * connection |
21900 |
-+ * @deadline_ns: The deadline of the reply, in nanoseconds |
21901 |
-+ * @cookie: The cookie of the requesting message |
21902 |
-+ * @name_id: ID of the well-known name the original msg was sent to |
21903 |
-+ * @sync: The reply block is waiting for synchronous I/O |
21904 |
-+ * @waiting: The condition to synchronously wait for |
21905 |
-+ * @interrupted: The sync reply was left in an interrupted state |
21906 |
-+ * @err: The error code for the synchronous reply |
21907 |
-+ */ |
21908 |
-+struct kdbus_reply { |
21909 |
-+ struct kref kref; |
21910 |
-+ struct list_head entry; |
21911 |
-+ struct kdbus_conn *reply_src; |
21912 |
-+ struct kdbus_conn *reply_dst; |
21913 |
-+ struct kdbus_queue_entry *queue_entry; |
21914 |
-+ u64 deadline_ns; |
21915 |
-+ u64 cookie; |
21916 |
-+ u64 name_id; |
21917 |
-+ bool sync:1; |
21918 |
-+ bool waiting:1; |
21919 |
-+ bool interrupted:1; |
21920 |
-+ int err; |
21921 |
-+}; |
21922 |
-+ |
21923 |
-+struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, |
21924 |
-+ struct kdbus_conn *reply_dst, |
21925 |
-+ const struct kdbus_msg *msg, |
21926 |
-+ struct kdbus_name_entry *name_entry, |
21927 |
-+ bool sync); |
21928 |
-+ |
21929 |
-+struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r); |
21930 |
-+struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r); |
21931 |
-+ |
21932 |
-+void kdbus_reply_link(struct kdbus_reply *r); |
21933 |
-+void kdbus_reply_unlink(struct kdbus_reply *r); |
21934 |
-+ |
21935 |
-+struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, |
21936 |
-+ struct kdbus_conn *reply_dst, |
21937 |
-+ u64 cookie); |
21938 |
-+ |
21939 |
-+void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err); |
21940 |
-+void kdbus_reply_list_scan_work(struct work_struct *work); |
21941 |
-+ |
21942 |
-+#endif /* __KDBUS_REPLY_H */ |
21943 |
-diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c |
21944 |
-new file mode 100644 |
21945 |
-index 0000000..72b1883 |
21946 |
---- /dev/null |
21947 |
-+++ b/ipc/kdbus/util.c |
21948 |
-@@ -0,0 +1,156 @@ |
21949 |
-+/* |
21950 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
21951 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
21952 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
21953 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
21954 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
21955 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
21956 |
-+ * |
21957 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
21958 |
-+ * the terms of the GNU Lesser General Public License as published by the |
21959 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
21960 |
-+ * your option) any later version. |
21961 |
-+ */ |
21962 |
-+ |
21963 |
-+#include <linux/capability.h> |
21964 |
-+#include <linux/cred.h> |
21965 |
-+#include <linux/ctype.h> |
21966 |
-+#include <linux/err.h> |
21967 |
-+#include <linux/file.h> |
21968 |
-+#include <linux/slab.h> |
21969 |
-+#include <linux/string.h> |
21970 |
-+#include <linux/uaccess.h> |
21971 |
-+#include <linux/uio.h> |
21972 |
-+#include <linux/user_namespace.h> |
21973 |
-+ |
21974 |
-+#include "limits.h" |
21975 |
-+#include "util.h" |
21976 |
-+ |
21977 |
-+/** |
21978 |
-+ * kdbus_copy_from_user() - copy aligned data from user-space |
21979 |
-+ * @dest: target buffer in kernel memory |
21980 |
-+ * @user_ptr: user-provided source buffer |
21981 |
-+ * @size: memory size to copy from user |
21982 |
-+ * |
21983 |
-+ * This copies @size bytes from @user_ptr into the kernel, just like |
21984 |
-+ * copy_from_user() does. But we enforce an 8-byte alignment and reject any |
21985 |
-+ * unaligned user-space pointers. |
21986 |
-+ * |
21987 |
-+ * Return: 0 on success, negative error code on failure. |
21988 |
-+ */ |
21989 |
-+int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size) |
21990 |
-+{ |
21991 |
-+ if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr)) |
21992 |
-+ return -EFAULT; |
21993 |
-+ |
21994 |
-+ if (copy_from_user(dest, user_ptr, size)) |
21995 |
-+ return -EFAULT; |
21996 |
-+ |
21997 |
-+ return 0; |
21998 |
-+} |
21999 |
-+ |
22000 |
-+/** |
22001 |
-+ * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name |
22002 |
-+ * @name: user-supplied name to verify |
22003 |
-+ * @user_ns: user-namespace to act in |
22004 |
-+ * @kuid: Kernel internal uid of user |
22005 |
-+ * |
22006 |
-+ * This verifies that the user-supplied name @name has their UID as prefix. This |
22007 |
-+ * is the default name-spacing policy we enforce on user-supplied names for |
22008 |
-+ * public kdbus entities like buses and endpoints. |
22009 |
-+ * |
22010 |
-+ * The user must supply names prefixed with "<UID>-", whereas the UID is |
22011 |
-+ * interpreted in the user-namespace of the domain. If the user fails to supply |
22012 |
-+ * such a prefixed name, we reject it. |
22013 |
-+ * |
22014 |
-+ * Return: 0 on success, negative error code on failure |
22015 |
-+ */ |
22016 |
-+int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, |
22017 |
-+ kuid_t kuid) |
22018 |
-+{ |
22019 |
-+ uid_t uid; |
22020 |
-+ char prefix[16]; |
22021 |
-+ |
22022 |
-+ /* |
22023 |
-+ * The kuid must have a mapping into the userns of the domain |
22024 |
-+ * otherwise do not allow creation of buses nor endpoints. |
22025 |
-+ */ |
22026 |
-+ uid = from_kuid(user_ns, kuid); |
22027 |
-+ if (uid == (uid_t) -1) |
22028 |
-+ return -EINVAL; |
22029 |
-+ |
22030 |
-+ snprintf(prefix, sizeof(prefix), "%u-", uid); |
22031 |
-+ if (strncmp(name, prefix, strlen(prefix)) != 0) |
22032 |
-+ return -EINVAL; |
22033 |
-+ |
22034 |
-+ return 0; |
22035 |
-+} |
22036 |
-+ |
22037 |
-+/** |
22038 |
-+ * kdbus_sanitize_attach_flags() - Sanitize attach flags from user-space |
22039 |
-+ * @flags: Attach flags provided by userspace |
22040 |
-+ * @attach_flags: A pointer where to store the valid attach flags |
22041 |
-+ * |
22042 |
-+ * Convert attach-flags provided by user-space into a valid mask. If the mask |
22043 |
-+ * is invalid, an error is returned. The sanitized attach flags are stored in |
22044 |
-+ * the output parameter. |
22045 |
-+ * |
22046 |
-+ * Return: 0 on success, negative error on failure. |
22047 |
-+ */ |
22048 |
-+int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags) |
22049 |
-+{ |
22050 |
-+ /* 'any' degrades to 'all' for compatibility */ |
22051 |
-+ if (flags == _KDBUS_ATTACH_ANY) |
22052 |
-+ flags = _KDBUS_ATTACH_ALL; |
22053 |
-+ |
22054 |
-+ /* reject unknown attach flags */ |
22055 |
-+ if (flags & ~_KDBUS_ATTACH_ALL) |
22056 |
-+ return -EINVAL; |
22057 |
-+ |
22058 |
-+ *attach_flags = flags; |
22059 |
-+ return 0; |
22060 |
-+} |
22061 |
-+ |
22062 |
-+/** |
22063 |
-+ * kdbus_kvec_set - helper utility to assemble kvec arrays |
22064 |
-+ * @kvec: kvec entry to use |
22065 |
-+ * @src: Source address to set in @kvec |
22066 |
-+ * @len: Number of bytes in @src |
22067 |
-+ * @total_len: Pointer to total length variable |
22068 |
-+ * |
22069 |
-+ * Set @src and @len in @kvec, and increase @total_len by @len. |
22070 |
-+ */ |
22071 |
-+void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len) |
22072 |
-+{ |
22073 |
-+ kvec->iov_base = src; |
22074 |
-+ kvec->iov_len = len; |
22075 |
-+ *total_len += len; |
22076 |
-+} |
22077 |
-+ |
22078 |
-+static const char * const zeros = "\0\0\0\0\0\0\0"; |
22079 |
-+ |
22080 |
-+/** |
22081 |
-+ * kdbus_kvec_pad - conditionally write a padding kvec |
22082 |
-+ * @kvec: kvec entry to use |
22083 |
-+ * @len: Total length used for kvec array |
22084 |
-+ * |
22085 |
-+ * Check if the current total byte length of the array in @len is aligned to |
22086 |
-+ * 8 bytes. If it isn't, fill @kvec with padding information and increase @len |
22087 |
-+ * by the number of bytes stored in @kvec. |
22088 |
-+ * |
22089 |
-+ * Return: the number of added padding bytes. |
22090 |
-+ */ |
22091 |
-+size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len) |
22092 |
-+{ |
22093 |
-+ size_t pad = KDBUS_ALIGN8(*len) - *len; |
22094 |
-+ |
22095 |
-+ if (!pad) |
22096 |
-+ return 0; |
22097 |
-+ |
22098 |
-+ kvec->iov_base = (void *)zeros; |
22099 |
-+ kvec->iov_len = pad; |
22100 |
-+ |
22101 |
-+ *len += pad; |
22102 |
-+ |
22103 |
-+ return pad; |
22104 |
-+} |
22105 |
-diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h |
22106 |
-new file mode 100644 |
22107 |
-index 0000000..5297166 |
22108 |
---- /dev/null |
22109 |
-+++ b/ipc/kdbus/util.h |
22110 |
-@@ -0,0 +1,73 @@ |
22111 |
-+/* |
22112 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
22113 |
-+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@×××××××××××××××.org> |
22114 |
-+ * Copyright (C) 2013-2015 Daniel Mack <daniel@××××××.org> |
22115 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
22116 |
-+ * Copyright (C) 2013-2015 Linux Foundation |
22117 |
-+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@××××××.org> |
22118 |
-+ * |
22119 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
22120 |
-+ * the terms of the GNU Lesser General Public License as published by the |
22121 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
22122 |
-+ * your option) any later version. |
22123 |
-+ */ |
22124 |
-+ |
22125 |
-+#ifndef __KDBUS_UTIL_H |
22126 |
-+#define __KDBUS_UTIL_H |
22127 |
-+ |
22128 |
-+#include <linux/dcache.h> |
22129 |
-+#include <linux/ioctl.h> |
22130 |
-+ |
22131 |
-+#include <uapi/linux/kdbus.h> |
22132 |
-+ |
22133 |
-+/* all exported addresses are 64 bit */ |
22134 |
-+#define KDBUS_PTR(addr) ((void __user *)(uintptr_t)(addr)) |
22135 |
-+ |
22136 |
-+/* all exported sizes are 64 bit and data aligned to 64 bit */ |
22137 |
-+#define KDBUS_ALIGN8(s) ALIGN((s), 8) |
22138 |
-+#define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8)) |
22139 |
-+ |
22140 |
-+/** |
22141 |
-+ * kdbus_member_set_user - write a structure member to user memory |
22142 |
-+ * @_s: Variable to copy from |
22143 |
-+ * @_b: Buffer to write to |
22144 |
-+ * @_t: Structure type |
22145 |
-+ * @_m: Member name in the passed structure |
22146 |
-+ * |
22147 |
-+ * Return: the result of copy_to_user() |
22148 |
-+ */ |
22149 |
-+#define kdbus_member_set_user(_s, _b, _t, _m) \ |
22150 |
-+({ \ |
22151 |
-+ u64 __user *_sz = \ |
22152 |
-+ (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \ |
22153 |
-+ copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \ |
22154 |
-+}) |
22155 |
-+ |
22156 |
-+/** |
22157 |
-+ * kdbus_strhash - calculate a hash |
22158 |
-+ * @str: String |
22159 |
-+ * |
22160 |
-+ * Return: hash value |
22161 |
-+ */ |
22162 |
-+static inline unsigned int kdbus_strhash(const char *str) |
22163 |
-+{ |
22164 |
-+ unsigned long hash = init_name_hash(); |
22165 |
-+ |
22166 |
-+ while (*str) |
22167 |
-+ hash = partial_name_hash(*str++, hash); |
22168 |
-+ |
22169 |
-+ return end_name_hash(hash); |
22170 |
-+} |
22171 |
-+ |
22172 |
-+int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, |
22173 |
-+ kuid_t kuid); |
22174 |
-+int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags); |
22175 |
-+ |
22176 |
-+int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size); |
22177 |
-+ |
22178 |
-+struct kvec; |
22179 |
-+ |
22180 |
-+void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len); |
22181 |
-+size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len); |
22182 |
-+ |
22183 |
-+#endif |
22184 |
-diff --git a/samples/Kconfig b/samples/Kconfig |
22185 |
-index 224ebb4..a4c6b2f 100644 |
22186 |
---- a/samples/Kconfig |
22187 |
-+++ b/samples/Kconfig |
22188 |
-@@ -55,6 +55,13 @@ config SAMPLE_KDB |
22189 |
- Build an example of how to dynamically add the hello |
22190 |
- command to the kdb shell. |
22191 |
- |
22192 |
-+config SAMPLE_KDBUS |
22193 |
-+ bool "Build kdbus API example" |
22194 |
-+ depends on KDBUS |
22195 |
-+ help |
22196 |
-+ Build an example of how the kdbus API can be used from |
22197 |
-+ userspace. |
22198 |
-+ |
22199 |
- config SAMPLE_RPMSG_CLIENT |
22200 |
- tristate "Build rpmsg client sample -- loadable modules only" |
22201 |
- depends on RPMSG && m |
22202 |
-diff --git a/samples/Makefile b/samples/Makefile |
22203 |
-index f00257b..f0ad51e 100644 |
22204 |
---- a/samples/Makefile |
22205 |
-+++ b/samples/Makefile |
22206 |
-@@ -1,4 +1,5 @@ |
22207 |
- # Makefile for Linux samples code |
22208 |
- |
22209 |
- obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ |
22210 |
-- hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ |
22211 |
-+ hw_breakpoint/ kfifo/ kdb/ kdbus/ hidraw/ rpmsg/ \ |
22212 |
-+ seccomp/ |
22213 |
-diff --git a/samples/kdbus/.gitignore b/samples/kdbus/.gitignore |
22214 |
-new file mode 100644 |
22215 |
-index 0000000..ee07d98 |
22216 |
---- /dev/null |
22217 |
-+++ b/samples/kdbus/.gitignore |
22218 |
-@@ -0,0 +1 @@ |
22219 |
-+kdbus-workers |
22220 |
-diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile |
22221 |
-new file mode 100644 |
22222 |
-index 0000000..137f842 |
22223 |
---- /dev/null |
22224 |
-+++ b/samples/kdbus/Makefile |
22225 |
-@@ -0,0 +1,9 @@ |
22226 |
-+# kbuild trick to avoid linker error. Can be omitted if a module is built. |
22227 |
-+obj- := dummy.o |
22228 |
-+ |
22229 |
-+hostprogs-$(CONFIG_SAMPLE_KDBUS) += kdbus-workers |
22230 |
-+ |
22231 |
-+always := $(hostprogs-y) |
22232 |
-+ |
22233 |
-+HOSTCFLAGS_kdbus-workers.o += -I$(objtree)/usr/include |
22234 |
-+HOSTLOADLIBES_kdbus-workers := -lrt |
22235 |
-diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h |
22236 |
-new file mode 100644 |
22237 |
-index 0000000..7f3abae |
22238 |
---- /dev/null |
22239 |
-+++ b/samples/kdbus/kdbus-api.h |
22240 |
-@@ -0,0 +1,114 @@ |
22241 |
-+#ifndef KDBUS_API_H |
22242 |
-+#define KDBUS_API_H |
22243 |
-+ |
22244 |
-+#include <sys/ioctl.h> |
22245 |
-+#include <linux/kdbus.h> |
22246 |
-+ |
22247 |
-+#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) |
22248 |
-+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
22249 |
-+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) |
22250 |
-+#define KDBUS_ITEM_NEXT(item) \ |
22251 |
-+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) |
22252 |
-+#define KDBUS_FOREACH(iter, first, _size) \ |
22253 |
-+ for ((iter) = (first); \ |
22254 |
-+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ |
22255 |
-+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ |
22256 |
-+ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size))) |
22257 |
-+ |
22258 |
-+static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd) |
22259 |
-+{ |
22260 |
-+ int ret = ioctl(control_fd, KDBUS_CMD_BUS_MAKE, cmd); |
22261 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22262 |
-+} |
22263 |
-+ |
22264 |
-+static inline int kdbus_cmd_endpoint_make(int bus_fd, struct kdbus_cmd *cmd) |
22265 |
-+{ |
22266 |
-+ int ret = ioctl(bus_fd, KDBUS_CMD_ENDPOINT_MAKE, cmd); |
22267 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22268 |
-+} |
22269 |
-+ |
22270 |
-+static inline int kdbus_cmd_endpoint_update(int ep_fd, struct kdbus_cmd *cmd) |
22271 |
-+{ |
22272 |
-+ int ret = ioctl(ep_fd, KDBUS_CMD_ENDPOINT_UPDATE, cmd); |
22273 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22274 |
-+} |
22275 |
-+ |
22276 |
-+static inline int kdbus_cmd_hello(int bus_fd, struct kdbus_cmd_hello *cmd) |
22277 |
-+{ |
22278 |
-+ int ret = ioctl(bus_fd, KDBUS_CMD_HELLO, cmd); |
22279 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22280 |
-+} |
22281 |
-+ |
22282 |
-+static inline int kdbus_cmd_update(int fd, struct kdbus_cmd *cmd) |
22283 |
-+{ |
22284 |
-+ int ret = ioctl(fd, KDBUS_CMD_UPDATE, cmd); |
22285 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22286 |
-+} |
22287 |
-+ |
22288 |
-+static inline int kdbus_cmd_byebye(int conn_fd, struct kdbus_cmd *cmd) |
22289 |
-+{ |
22290 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_BYEBYE, cmd); |
22291 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22292 |
-+} |
22293 |
-+ |
22294 |
-+static inline int kdbus_cmd_free(int conn_fd, struct kdbus_cmd_free *cmd) |
22295 |
-+{ |
22296 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_FREE, cmd); |
22297 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22298 |
-+} |
22299 |
-+ |
22300 |
-+static inline int kdbus_cmd_conn_info(int conn_fd, struct kdbus_cmd_info *cmd) |
22301 |
-+{ |
22302 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_CONN_INFO, cmd); |
22303 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22304 |
-+} |
22305 |
-+ |
22306 |
-+static inline int kdbus_cmd_bus_creator_info(int conn_fd, struct kdbus_cmd_info *cmd) |
22307 |
-+{ |
22308 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_BUS_CREATOR_INFO, cmd); |
22309 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22310 |
-+} |
22311 |
-+ |
22312 |
-+static inline int kdbus_cmd_list(int fd, struct kdbus_cmd_list *cmd) |
22313 |
-+{ |
22314 |
-+ int ret = ioctl(fd, KDBUS_CMD_LIST, cmd); |
22315 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22316 |
-+} |
22317 |
-+ |
22318 |
-+static inline int kdbus_cmd_send(int conn_fd, struct kdbus_cmd_send *cmd) |
22319 |
-+{ |
22320 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_SEND, cmd); |
22321 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22322 |
-+} |
22323 |
-+ |
22324 |
-+static inline int kdbus_cmd_recv(int conn_fd, struct kdbus_cmd_recv *cmd) |
22325 |
-+{ |
22326 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_RECV, cmd); |
22327 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22328 |
-+} |
22329 |
-+ |
22330 |
-+static inline int kdbus_cmd_name_acquire(int conn_fd, struct kdbus_cmd *cmd) |
22331 |
-+{ |
22332 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_ACQUIRE, cmd); |
22333 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22334 |
-+} |
22335 |
-+ |
22336 |
-+static inline int kdbus_cmd_name_release(int conn_fd, struct kdbus_cmd *cmd) |
22337 |
-+{ |
22338 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_RELEASE, cmd); |
22339 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22340 |
-+} |
22341 |
-+ |
22342 |
-+static inline int kdbus_cmd_match_add(int conn_fd, struct kdbus_cmd_match *cmd) |
22343 |
-+{ |
22344 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_ADD, cmd); |
22345 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22346 |
-+} |
22347 |
-+ |
22348 |
-+static inline int kdbus_cmd_match_remove(int conn_fd, struct kdbus_cmd_match *cmd) |
22349 |
-+{ |
22350 |
-+ int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_REMOVE, cmd); |
22351 |
-+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; |
22352 |
-+} |
22353 |
-+ |
22354 |
-+#endif /* KDBUS_API_H */ |
22355 |
-diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c |
22356 |
-new file mode 100644 |
22357 |
-index 0000000..5a6dfdc |
22358 |
---- /dev/null |
22359 |
-+++ b/samples/kdbus/kdbus-workers.c |
22360 |
-@@ -0,0 +1,1346 @@ |
22361 |
-+/* |
22362 |
-+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@×××××.com> |
22363 |
-+ * |
22364 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
22365 |
-+ * the terms of the GNU Lesser General Public License as published by the |
22366 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
22367 |
-+ * your option) any later version. |
22368 |
-+ */ |
22369 |
-+ |
22370 |
-+/* |
22371 |
-+ * Example: Workers |
22372 |
-+ * This program computes prime-numbers based on the sieve of Eratosthenes. The |
22373 |
-+ * master sets up a shared memory region and spawns workers which clear out the |
22374 |
-+ * non-primes. The master reacts to keyboard input and to client-requests to |
22375 |
-+ * control what each worker does. Note that this is in no way meant as efficient |
22376 |
-+ * way to compute primes. It should only serve as example how a master/worker |
22377 |
-+ * concept can be implemented with kdbus used as control messages. |
22378 |
-+ * |
22379 |
-+ * The main process is called the 'master'. It creates a new, private bus which |
22380 |
-+ * will be used between the master and its workers to communicate. The master |
22381 |
-+ * then spawns a fixed number of workers. Whenever a worker dies (detected via |
22382 |
-+ * SIGCHLD), the master spawns a new worker. When done, the master waits for all |
22383 |
-+ * workers to exit, prints a status report and exits itself. |
22384 |
-+ * |
22385 |
-+ * The master process does *not* keep track of its workers. Instead, this |
22386 |
-+ * example implements a PULL model. That is, the master acquires a well-known |
22387 |
-+ * name on the bus which each worker uses to request tasks from the master. If |
22388 |
-+ * there are no more tasks, the master will return an empty task-list, which |
22389 |
-+ * casues a worker to exit immediately. |
22390 |
-+ * |
22391 |
-+ * As tasks can be computationally expensive, we support cancellation. Whenever |
22392 |
-+ * the master process is interrupted, it will drop its well-known name on the |
22393 |
-+ * bus. This causes kdbus to broadcast a name-change notification. The workers |
22394 |
-+ * check for broadcast messages regularly and will exit if they receive one. |
22395 |
-+ * |
22396 |
-+ * This example exists of 4 objects: |
22397 |
-+ * * master: The master object contains the context of the master process. This |
22398 |
-+ * process manages the prime-context, spawns workers and assigns |
22399 |
-+ * prime-ranges to each worker to compute. |
22400 |
-+ * The master itself does not do any prime-computations itself. |
22401 |
-+ * * child: The child object contains the context of a worker. It inherits the |
22402 |
-+ * prime context from its parent (the master) and then creates a new |
22403 |
-+ * bus context to request prime-ranges to compute. |
22404 |
-+ * * prime: The "prime" object is used to abstract how we compute primes. When |
22405 |
-+ * allocated, it prepares a memory region to hold 1 bit for each |
22406 |
-+ * natural number up to a fixed maximum ('MAX_PRIMES'). |
22407 |
-+ * The memory region is backed by a memfd which we share between |
22408 |
-+ * processes. Each worker now gets assigned a range of natural |
22409 |
-+ * numbers which it clears multiples of off the memory region. The |
22410 |
-+ * master process is responsible of distributing all natural numbers |
22411 |
-+ * up to the fixed maximum to its workers. |
22412 |
-+ * * bus: The bus object is an abstraction of the kdbus API. It is pretty |
22413 |
-+ * straightfoward and only manages the connection-fd plus the |
22414 |
-+ * memory-mapped pool in a single object. |
22415 |
-+ * |
22416 |
-+ * This example is in reversed order, which should make it easier to read |
22417 |
-+ * top-down, but requires some forward-declarations. Just ignore those. |
22418 |
-+ */ |
22419 |
-+ |
22420 |
-+#include <stdio.h> |
22421 |
-+#include <stdlib.h> |
22422 |
-+#include <sys/syscall.h> |
22423 |
-+ |
22424 |
-+/* glibc < 2.7 does not ship sys/signalfd.h */ |
22425 |
-+/* we require kernels with __NR_memfd_create */ |
22426 |
-+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7 && defined(__NR_memfd_create) |
22427 |
-+ |
22428 |
-+#include <ctype.h> |
22429 |
-+#include <errno.h> |
22430 |
-+#include <fcntl.h> |
22431 |
-+#include <linux/memfd.h> |
22432 |
-+#include <signal.h> |
22433 |
-+#include <stdbool.h> |
22434 |
-+#include <stddef.h> |
22435 |
-+#include <stdint.h> |
22436 |
-+#include <string.h> |
22437 |
-+#include <sys/mman.h> |
22438 |
-+#include <sys/poll.h> |
22439 |
-+#include <sys/signalfd.h> |
22440 |
-+#include <sys/time.h> |
22441 |
-+#include <sys/wait.h> |
22442 |
-+#include <time.h> |
22443 |
-+#include <unistd.h> |
22444 |
-+#include "kdbus-api.h" |
22445 |
-+ |
22446 |
-+/* FORWARD DECLARATIONS */ |
22447 |
-+ |
22448 |
-+#define POOL_SIZE (16 * 1024 * 1024) |
22449 |
-+#define MAX_PRIMES (2UL << 24) |
22450 |
-+#define WORKER_COUNT (16) |
22451 |
-+#define PRIME_STEPS (65536 * 4) |
22452 |
-+ |
22453 |
-+static const char *arg_busname = "example-workers"; |
22454 |
-+static const char *arg_modname = "kdbus"; |
22455 |
-+static const char *arg_master = "org.freedesktop.master"; |
22456 |
-+ |
22457 |
-+static int err_assert(int r_errno, const char *msg, const char *func, int line, |
22458 |
-+ const char *file) |
22459 |
-+{ |
22460 |
-+ r_errno = (r_errno != 0) ? -abs(r_errno) : -EFAULT; |
22461 |
-+ if (r_errno < 0) { |
22462 |
-+ errno = -r_errno; |
22463 |
-+ fprintf(stderr, "ERR: %s: %m (%s:%d in %s)\n", |
22464 |
-+ msg, func, line, file); |
22465 |
-+ } |
22466 |
-+ return r_errno; |
22467 |
-+} |
22468 |
-+ |
22469 |
-+#define err_r(_r, _msg) err_assert((_r), (_msg), __func__, __LINE__, __FILE__) |
22470 |
-+#define err(_msg) err_r(errno, (_msg)) |
22471 |
-+ |
22472 |
-+struct prime; |
22473 |
-+struct bus; |
22474 |
-+struct master; |
22475 |
-+struct child; |
22476 |
-+ |
22477 |
-+struct prime { |
22478 |
-+ int fd; |
22479 |
-+ uint8_t *area; |
22480 |
-+ size_t max; |
22481 |
-+ size_t done; |
22482 |
-+ size_t status; |
22483 |
-+}; |
22484 |
-+ |
22485 |
-+static int prime_new(struct prime **out); |
22486 |
-+static void prime_free(struct prime *p); |
22487 |
-+static bool prime_done(struct prime *p); |
22488 |
-+static void prime_consume(struct prime *p, size_t amount); |
22489 |
-+static int prime_run(struct prime *p, struct bus *cancel, size_t number); |
22490 |
-+static void prime_print(struct prime *p); |
22491 |
-+ |
22492 |
-+struct bus { |
22493 |
-+ int fd; |
22494 |
-+ uint8_t *pool; |
22495 |
-+}; |
22496 |
-+ |
22497 |
-+static int bus_open_connection(struct bus **out, uid_t uid, const char *name, |
22498 |
-+ uint64_t recv_flags); |
22499 |
-+static void bus_close_connection(struct bus *b); |
22500 |
-+static void bus_poool_free_slice(struct bus *b, uint64_t offset); |
22501 |
-+static int bus_acquire_name(struct bus *b, const char *name); |
22502 |
-+static int bus_install_name_loss_match(struct bus *b, const char *name); |
22503 |
-+static int bus_poll(struct bus *b); |
22504 |
-+static int bus_make(uid_t uid, const char *name); |
22505 |
-+ |
22506 |
-+struct master { |
22507 |
-+ size_t n_workers; |
22508 |
-+ size_t max_workers; |
22509 |
-+ |
22510 |
-+ int signal_fd; |
22511 |
-+ int control_fd; |
22512 |
-+ |
22513 |
-+ struct prime *prime; |
22514 |
-+ struct bus *bus; |
22515 |
-+}; |
22516 |
-+ |
22517 |
-+static int master_new(struct master **out); |
22518 |
-+static void master_free(struct master *m); |
22519 |
-+static int master_run(struct master *m); |
22520 |
-+static int master_poll(struct master *m); |
22521 |
-+static int master_handle_stdin(struct master *m); |
22522 |
-+static int master_handle_signal(struct master *m); |
22523 |
-+static int master_handle_bus(struct master *m); |
22524 |
-+static int master_reply(struct master *m, const struct kdbus_msg *msg); |
22525 |
-+static int master_waitpid(struct master *m); |
22526 |
-+static int master_spawn(struct master *m); |
22527 |
-+ |
22528 |
-+struct child { |
22529 |
-+ struct bus *bus; |
22530 |
-+ struct prime *prime; |
22531 |
-+}; |
22532 |
-+ |
22533 |
-+static int child_new(struct child **out, struct prime *p); |
22534 |
-+static void child_free(struct child *c); |
22535 |
-+static int child_run(struct child *c); |
22536 |
-+ |
22537 |
-+/* END OF FORWARD DECLARATIONS */ |
22538 |
-+ |
22539 |
-+/* |
22540 |
-+ * This is the main entrypoint of this example. It is pretty straightforward. We |
22541 |
-+ * create a master object, run the computation, print a status report and then |
22542 |
-+ * exit. Nothing particularly interesting here, so lets look into the master |
22543 |
-+ * object... |
22544 |
-+ */ |
22545 |
-+int main(int argc, char **argv) |
22546 |
-+{ |
22547 |
-+ struct master *m = NULL; |
22548 |
-+ int r; |
22549 |
-+ |
22550 |
-+ r = master_new(&m); |
22551 |
-+ if (r < 0) |
22552 |
-+ goto out; |
22553 |
-+ |
22554 |
-+ r = master_run(m); |
22555 |
-+ if (r < 0) |
22556 |
-+ goto out; |
22557 |
-+ |
22558 |
-+ if (0) |
22559 |
-+ prime_print(m->prime); |
22560 |
-+ |
22561 |
-+out: |
22562 |
-+ master_free(m); |
22563 |
-+ if (r < 0 && r != -EINTR) |
22564 |
-+ fprintf(stderr, "failed\n"); |
22565 |
-+ else |
22566 |
-+ fprintf(stderr, "done\n"); |
22567 |
-+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
22568 |
-+} |
22569 |
-+ |
22570 |
-+/* |
22571 |
-+ * ...this will allocate a new master context. It keeps track of the current |
22572 |
-+ * number of children/workers that are running, manages a signalfd to track |
22573 |
-+ * SIGCHLD, and creates a private kdbus bus. Afterwards, it opens its connection |
22574 |
-+ * to the bus and acquires a well known-name (arg_master). |
22575 |
-+ */ |
22576 |
-+static int master_new(struct master **out) |
22577 |
-+{ |
22578 |
-+ struct master *m; |
22579 |
-+ sigset_t smask; |
22580 |
-+ int r; |
22581 |
-+ |
22582 |
-+ m = calloc(1, sizeof(*m)); |
22583 |
-+ if (!m) |
22584 |
-+ return err("cannot allocate master"); |
22585 |
-+ |
22586 |
-+ m->max_workers = WORKER_COUNT; |
22587 |
-+ m->signal_fd = -1; |
22588 |
-+ m->control_fd = -1; |
22589 |
-+ |
22590 |
-+ /* Block SIGINT and SIGCHLD signals */ |
22591 |
-+ sigemptyset(&smask); |
22592 |
-+ sigaddset(&smask, SIGINT); |
22593 |
-+ sigaddset(&smask, SIGCHLD); |
22594 |
-+ sigprocmask(SIG_BLOCK, &smask, NULL); |
22595 |
-+ |
22596 |
-+ m->signal_fd = signalfd(-1, &smask, SFD_CLOEXEC); |
22597 |
-+ if (m->signal_fd < 0) { |
22598 |
-+ r = err("cannot create signalfd"); |
22599 |
-+ goto error; |
22600 |
-+ } |
22601 |
-+ |
22602 |
-+ r = prime_new(&m->prime); |
22603 |
-+ if (r < 0) |
22604 |
-+ goto error; |
22605 |
-+ |
22606 |
-+ m->control_fd = bus_make(getuid(), arg_busname); |
22607 |
-+ if (m->control_fd < 0) { |
22608 |
-+ r = m->control_fd; |
22609 |
-+ goto error; |
22610 |
-+ } |
22611 |
-+ |
22612 |
-+ /* |
22613 |
-+ * Open a bus connection for the master, and require each received |
22614 |
-+ * message to have a metadata item of type KDBUS_ITEM_PIDS attached. |
22615 |
-+ * The current UID is needed to compute the name of the bus node to |
22616 |
-+ * connect to. |
22617 |
-+ */ |
22618 |
-+ r = bus_open_connection(&m->bus, getuid(), |
22619 |
-+ arg_busname, KDBUS_ATTACH_PIDS); |
22620 |
-+ if (r < 0) |
22621 |
-+ goto error; |
22622 |
-+ |
22623 |
-+ /* |
22624 |
-+ * Acquire a well-known name on the bus, so children can address |
22625 |
-+ * messages to the master using KDBUS_DST_ID_NAME as destination-ID |
22626 |
-+ * of messages. |
22627 |
-+ */ |
22628 |
-+ r = bus_acquire_name(m->bus, arg_master); |
22629 |
-+ if (r < 0) |
22630 |
-+ goto error; |
22631 |
-+ |
22632 |
-+ *out = m; |
22633 |
-+ return 0; |
22634 |
-+ |
22635 |
-+error: |
22636 |
-+ master_free(m); |
22637 |
-+ return r; |
22638 |
-+} |
22639 |
-+ |
22640 |
-+/* pretty straightforward destructor of a master object */ |
22641 |
-+static void master_free(struct master *m) |
22642 |
-+{ |
22643 |
-+ if (!m) |
22644 |
-+ return; |
22645 |
-+ |
22646 |
-+ bus_close_connection(m->bus); |
22647 |
-+ if (m->control_fd >= 0) |
22648 |
-+ close(m->control_fd); |
22649 |
-+ prime_free(m->prime); |
22650 |
-+ if (m->signal_fd >= 0) |
22651 |
-+ close(m->signal_fd); |
22652 |
-+ free(m); |
22653 |
-+} |
22654 |
-+ |
22655 |
-+static int master_run(struct master *m) |
22656 |
-+{ |
22657 |
-+ int res, r = 0; |
22658 |
-+ |
22659 |
-+ while (!prime_done(m->prime)) { |
22660 |
-+ while (m->n_workers < m->max_workers) { |
22661 |
-+ r = master_spawn(m); |
22662 |
-+ if (r < 0) |
22663 |
-+ break; |
22664 |
-+ } |
22665 |
-+ |
22666 |
-+ r = master_poll(m); |
22667 |
-+ if (r < 0) |
22668 |
-+ break; |
22669 |
-+ } |
22670 |
-+ |
22671 |
-+ if (r < 0) { |
22672 |
-+ bus_close_connection(m->bus); |
22673 |
-+ m->bus = NULL; |
22674 |
-+ } |
22675 |
-+ |
22676 |
-+ while (m->n_workers > 0) { |
22677 |
-+ res = master_poll(m); |
22678 |
-+ if (res < 0) { |
22679 |
-+ if (m->bus) { |
22680 |
-+ bus_close_connection(m->bus); |
22681 |
-+ m->bus = NULL; |
22682 |
-+ } |
22683 |
-+ r = res; |
22684 |
-+ } |
22685 |
-+ } |
22686 |
-+ |
22687 |
-+ return r == -EINTR ? 0 : r; |
22688 |
-+} |
22689 |
-+ |
22690 |
-+static int master_poll(struct master *m) |
22691 |
-+{ |
22692 |
-+ struct pollfd fds[3] = {}; |
22693 |
-+ int r = 0, n = 0; |
22694 |
-+ |
22695 |
-+ /* |
22696 |
-+ * Add stdin, the eventfd and the connection owner file descriptor to |
22697 |
-+ * the pollfd table, and handle incoming traffic on the latter in |
22698 |
-+ * master_handle_bus(). |
22699 |
-+ */ |
22700 |
-+ fds[n].fd = STDIN_FILENO; |
22701 |
-+ fds[n++].events = POLLIN; |
22702 |
-+ fds[n].fd = m->signal_fd; |
22703 |
-+ fds[n++].events = POLLIN; |
22704 |
-+ if (m->bus) { |
22705 |
-+ fds[n].fd = m->bus->fd; |
22706 |
-+ fds[n++].events = POLLIN; |
22707 |
-+ } |
22708 |
-+ |
22709 |
-+ r = poll(fds, n, -1); |
22710 |
-+ if (r < 0) |
22711 |
-+ return err("poll() failed"); |
22712 |
-+ |
22713 |
-+ if (fds[0].revents & POLLIN) |
22714 |
-+ r = master_handle_stdin(m); |
22715 |
-+ else if (fds[0].revents) |
22716 |
-+ r = err("ERR/HUP on stdin"); |
22717 |
-+ if (r < 0) |
22718 |
-+ return r; |
22719 |
-+ |
22720 |
-+ if (fds[1].revents & POLLIN) |
22721 |
-+ r = master_handle_signal(m); |
22722 |
-+ else if (fds[1].revents) |
22723 |
-+ r = err("ERR/HUP on signalfd"); |
22724 |
-+ if (r < 0) |
22725 |
-+ return r; |
22726 |
-+ |
22727 |
-+ if (fds[2].revents & POLLIN) |
22728 |
-+ r = master_handle_bus(m); |
22729 |
-+ else if (fds[2].revents) |
22730 |
-+ r = err("ERR/HUP on bus"); |
22731 |
-+ |
22732 |
-+ return r; |
22733 |
-+} |
22734 |
-+ |
22735 |
-+static int master_handle_stdin(struct master *m) |
22736 |
-+{ |
22737 |
-+ char buf[128]; |
22738 |
-+ ssize_t l; |
22739 |
-+ int r = 0; |
22740 |
-+ |
22741 |
-+ l = read(STDIN_FILENO, buf, sizeof(buf)); |
22742 |
-+ if (l < 0) |
22743 |
-+ return err("cannot read stdin"); |
22744 |
-+ if (l == 0) |
22745 |
-+ return err_r(-EINVAL, "EOF on stdin"); |
22746 |
-+ |
22747 |
-+ while (l-- > 0) { |
22748 |
-+ switch (buf[l]) { |
22749 |
-+ case 'q': |
22750 |
-+ /* quit */ |
22751 |
-+ r = -EINTR; |
22752 |
-+ break; |
22753 |
-+ case '\n': |
22754 |
-+ case ' ': |
22755 |
-+ /* ignore */ |
22756 |
-+ break; |
22757 |
-+ default: |
22758 |
-+ if (isgraph(buf[l])) |
22759 |
-+ fprintf(stderr, "invalid input '%c'\n", buf[l]); |
22760 |
-+ else |
22761 |
-+ fprintf(stderr, "invalid input 0x%x\n", buf[l]); |
22762 |
-+ break; |
22763 |
-+ } |
22764 |
-+ } |
22765 |
-+ |
22766 |
-+ return r; |
22767 |
-+} |
22768 |
-+ |
22769 |
-+static int master_handle_signal(struct master *m) |
22770 |
-+{ |
22771 |
-+ struct signalfd_siginfo val; |
22772 |
-+ ssize_t l; |
22773 |
-+ |
22774 |
-+ l = read(m->signal_fd, &val, sizeof(val)); |
22775 |
-+ if (l < 0) |
22776 |
-+ return err("cannot read signalfd"); |
22777 |
-+ if (l != sizeof(val)) |
22778 |
-+ return err_r(-EINVAL, "invalid data from signalfd"); |
22779 |
-+ |
22780 |
-+ switch (val.ssi_signo) { |
22781 |
-+ case SIGCHLD: |
22782 |
-+ return master_waitpid(m); |
22783 |
-+ case SIGINT: |
22784 |
-+ return err_r(-EINTR, "interrupted"); |
22785 |
-+ default: |
22786 |
-+ return err_r(-EINVAL, "caught invalid signal"); |
22787 |
-+ } |
22788 |
-+} |
22789 |
-+ |
22790 |
-+static int master_handle_bus(struct master *m) |
22791 |
-+{ |
22792 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
22793 |
-+ const struct kdbus_msg *msg = NULL; |
22794 |
-+ const struct kdbus_item *item; |
22795 |
-+ const struct kdbus_vec *vec = NULL; |
22796 |
-+ int r = 0; |
22797 |
-+ |
22798 |
-+ /* |
22799 |
-+ * To receive a message, the KDBUS_CMD_RECV ioctl is used. |
22800 |
-+ * It takes an argument of type 'struct kdbus_cmd_recv', which |
22801 |
-+ * will contain information on the received message when the call |
22802 |
-+ * returns. See kdbus.message(7). |
22803 |
-+ */ |
22804 |
-+ r = kdbus_cmd_recv(m->bus->fd, &recv); |
22805 |
-+ /* |
22806 |
-+ * EAGAIN is returned when there is no message waiting on this |
22807 |
-+ * connection. This is not an error - simply bail out. |
22808 |
-+ */ |
22809 |
-+ if (r == -EAGAIN) |
22810 |
-+ return 0; |
22811 |
-+ if (r < 0) |
22812 |
-+ return err_r(r, "cannot receive message"); |
22813 |
-+ |
22814 |
-+ /* |
22815 |
-+ * Messages received by a connection are stored inside the connection's |
22816 |
-+ * pool, at an offset that has been returned in the 'recv' command |
22817 |
-+ * struct above. The value describes the relative offset from the |
22818 |
-+ * start address of the pool. A message is described with |
22819 |
-+ * 'struct kdbus_msg'. See kdbus.message(7). |
22820 |
-+ */ |
22821 |
-+ msg = (void *)(m->bus->pool + recv.msg.offset); |
22822 |
-+ |
22823 |
-+ /* |
22824 |
-+ * A messages describes its actual payload in an array of items. |
22825 |
-+ * KDBUS_FOREACH() is a simple iterator that walks such an array. |
22826 |
-+ * struct kdbus_msg has a field to denote its total size, which is |
22827 |
-+ * needed to determine the number of items in the array. |
22828 |
-+ */ |
22829 |
-+ KDBUS_FOREACH(item, msg->items, |
22830 |
-+ msg->size - offsetof(struct kdbus_msg, items)) { |
22831 |
-+ /* |
22832 |
-+ * An item of type PAYLOAD_OFF describes in-line memory |
22833 |
-+ * stored in the pool at a described offset. That offset is |
22834 |
-+ * relative to the start address of the message header. |
22835 |
-+ * This example program only expects one single item of that |
22836 |
-+ * type, remembers the struct kdbus_vec member of the item |
22837 |
-+ * when it sees it, and bails out if there is more than one |
22838 |
-+ * of them. |
22839 |
-+ */ |
22840 |
-+ if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { |
22841 |
-+ if (vec) { |
22842 |
-+ r = err_r(-EEXIST, |
22843 |
-+ "message with multiple vecs"); |
22844 |
-+ break; |
22845 |
-+ } |
22846 |
-+ vec = &item->vec; |
22847 |
-+ if (vec->size != 1) { |
22848 |
-+ r = err_r(-EINVAL, "invalid message size"); |
22849 |
-+ break; |
22850 |
-+ } |
22851 |
-+ |
22852 |
-+ /* |
22853 |
-+ * MEMFDs are transported as items of type PAYLOAD_MEMFD. |
22854 |
-+ * If such an item is attached, a new file descriptor was |
22855 |
-+ * installed into the task when KDBUS_CMD_RECV was called, and |
22856 |
-+ * its number is stored in item->memfd.fd. |
22857 |
-+ * Implementers *must* handle this item type and close the |
22858 |
-+ * file descriptor when no longer needed in order to prevent |
22859 |
-+ * file descriptor exhaustion. This example program just bails |
22860 |
-+ * out with an error in this case, as memfds are not expected |
22861 |
-+ * in this context. |
22862 |
-+ */ |
22863 |
-+ } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) { |
22864 |
-+ r = err_r(-EINVAL, "message with memfd"); |
22865 |
-+ break; |
22866 |
-+ } |
22867 |
-+ } |
22868 |
-+ if (r < 0) |
22869 |
-+ goto exit; |
22870 |
-+ if (!vec) { |
22871 |
-+ r = err_r(-EINVAL, "empty message"); |
22872 |
-+ goto exit; |
22873 |
-+ } |
22874 |
-+ |
22875 |
-+ switch (*((const uint8_t *)msg + vec->offset)) { |
22876 |
-+ case 'r': { |
22877 |
-+ r = master_reply(m, msg); |
22878 |
-+ break; |
22879 |
-+ } |
22880 |
-+ default: |
22881 |
-+ r = err_r(-EINVAL, "invalid message type"); |
22882 |
-+ break; |
22883 |
-+ } |
22884 |
-+ |
22885 |
-+exit: |
22886 |
-+ /* |
22887 |
-+ * We are done with the memory slice that was given to us through |
22888 |
-+ * recv.msg.offset. Tell the kernel it can use it for other content |
22889 |
-+ * in the future. See kdbus.pool(7). |
22890 |
-+ */ |
22891 |
-+ bus_poool_free_slice(m->bus, recv.msg.offset); |
22892 |
-+ return r; |
22893 |
-+} |
22894 |
-+ |
22895 |
-+static int master_reply(struct master *m, const struct kdbus_msg *msg) |
22896 |
-+{ |
22897 |
-+ struct kdbus_cmd_send cmd; |
22898 |
-+ struct kdbus_item *item; |
22899 |
-+ struct kdbus_msg *reply; |
22900 |
-+ size_t size, status, p[2]; |
22901 |
-+ int r; |
22902 |
-+ |
22903 |
-+ /* |
22904 |
-+ * This functions sends a message over kdbus. To do this, it uses the |
22905 |
-+ * KDBUS_CMD_SEND ioctl, which takes a command struct argument of type |
22906 |
-+ * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual |
22907 |
-+ * message to send. See kdbus.message(7). |
22908 |
-+ */ |
22909 |
-+ p[0] = m->prime->done; |
22910 |
-+ p[1] = prime_done(m->prime) ? 0 : PRIME_STEPS; |
22911 |
-+ |
22912 |
-+ size = sizeof(*reply); |
22913 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
22914 |
-+ |
22915 |
-+ /* Prepare the message to send */ |
22916 |
-+ reply = alloca(size); |
22917 |
-+ memset(reply, 0, size); |
22918 |
-+ reply->size = size; |
22919 |
-+ |
22920 |
-+ /* Each message has a cookie that can be used to send replies */ |
22921 |
-+ reply->cookie = 1; |
22922 |
-+ |
22923 |
-+ /* The payload_type is arbitrary, but it must be non-zero */ |
22924 |
-+ reply->payload_type = 0xdeadbeef; |
22925 |
-+ |
22926 |
-+ /* |
22927 |
-+ * We are sending a reply. Let the kernel know the cookie of the |
22928 |
-+ * message we are replying to. |
22929 |
-+ */ |
22930 |
-+ reply->cookie_reply = msg->cookie; |
22931 |
-+ |
22932 |
-+ /* |
22933 |
-+ * Messages can either be directed to a well-known name (stored as |
22934 |
-+ * string) or to a unique name (stored as number). This example does |
22935 |
-+ * the latter. If the message would be directed to a well-known name |
22936 |
-+ * instead, the message's dst_id field would be set to |
22937 |
-+ * KDBUS_DST_ID_NAME, and the name would be attaches in an item of type |
22938 |
-+ * KDBUS_ITEM_DST_NAME. See below for an example, and also refer to |
22939 |
-+ * kdbus.message(7). |
22940 |
-+ */ |
22941 |
-+ reply->dst_id = msg->src_id; |
22942 |
-+ |
22943 |
-+ /* Our message has exactly one item to store its payload */ |
22944 |
-+ item = reply->items; |
22945 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
22946 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
22947 |
-+ item->vec.address = (uintptr_t)p; |
22948 |
-+ item->vec.size = sizeof(p); |
22949 |
-+ |
22950 |
-+ /* |
22951 |
-+ * Now prepare the command struct, and reference the message we want |
22952 |
-+ * to send. |
22953 |
-+ */ |
22954 |
-+ memset(&cmd, 0, sizeof(cmd)); |
22955 |
-+ cmd.size = sizeof(cmd); |
22956 |
-+ cmd.msg_address = (uintptr_t)reply; |
22957 |
-+ |
22958 |
-+ /* |
22959 |
-+ * Finally, employ the command on the connection owner |
22960 |
-+ * file descriptor. |
22961 |
-+ */ |
22962 |
-+ r = kdbus_cmd_send(m->bus->fd, &cmd); |
22963 |
-+ if (r < 0) |
22964 |
-+ return err_r(r, "cannot send reply"); |
22965 |
-+ |
22966 |
-+ if (p[1]) { |
22967 |
-+ prime_consume(m->prime, p[1]); |
22968 |
-+ status = m->prime->done * 10000 / m->prime->max; |
22969 |
-+ if (status != m->prime->status) { |
22970 |
-+ m->prime->status = status; |
22971 |
-+ fprintf(stderr, "status: %7.3lf%%\n", |
22972 |
-+ (double)status / 100); |
22973 |
-+ } |
22974 |
-+ } |
22975 |
-+ |
22976 |
-+ return 0; |
22977 |
-+} |
22978 |
-+ |
22979 |
-+static int master_waitpid(struct master *m) |
22980 |
-+{ |
22981 |
-+ pid_t pid; |
22982 |
-+ int r; |
22983 |
-+ |
22984 |
-+ while ((pid = waitpid(-1, &r, WNOHANG)) > 0) { |
22985 |
-+ if (m->n_workers > 0) |
22986 |
-+ --m->n_workers; |
22987 |
-+ if (!WIFEXITED(r)) |
22988 |
-+ r = err_r(-EINVAL, "child died unexpectedly"); |
22989 |
-+ else if (WEXITSTATUS(r) != 0) |
22990 |
-+ r = err_r(-WEXITSTATUS(r), "child failed"); |
22991 |
-+ } |
22992 |
-+ |
22993 |
-+ return r; |
22994 |
-+} |
22995 |
-+ |
22996 |
-+static int master_spawn(struct master *m) |
22997 |
-+{ |
22998 |
-+ struct child *c = NULL; |
22999 |
-+ struct prime *p = NULL; |
23000 |
-+ pid_t pid; |
23001 |
-+ int r; |
23002 |
-+ |
23003 |
-+ /* Spawn off one child and call child_run() inside it */ |
23004 |
-+ |
23005 |
-+ pid = fork(); |
23006 |
-+ if (pid < 0) |
23007 |
-+ return err("cannot fork"); |
23008 |
-+ if (pid > 0) { |
23009 |
-+ /* parent */ |
23010 |
-+ ++m->n_workers; |
23011 |
-+ return 0; |
23012 |
-+ } |
23013 |
-+ |
23014 |
-+ /* child */ |
23015 |
-+ |
23016 |
-+ p = m->prime; |
23017 |
-+ m->prime = NULL; |
23018 |
-+ master_free(m); |
23019 |
-+ |
23020 |
-+ r = child_new(&c, p); |
23021 |
-+ if (r < 0) |
23022 |
-+ goto exit; |
23023 |
-+ |
23024 |
-+ r = child_run(c); |
23025 |
-+ |
23026 |
-+exit: |
23027 |
-+ child_free(c); |
23028 |
-+ exit(abs(r)); |
23029 |
-+} |
23030 |
-+ |
23031 |
-+static int child_new(struct child **out, struct prime *p) |
23032 |
-+{ |
23033 |
-+ struct child *c; |
23034 |
-+ int r; |
23035 |
-+ |
23036 |
-+ c = calloc(1, sizeof(*c)); |
23037 |
-+ if (!c) |
23038 |
-+ return err("cannot allocate child"); |
23039 |
-+ |
23040 |
-+ c->prime = p; |
23041 |
-+ |
23042 |
-+ /* |
23043 |
-+ * Open a connection to the bus and require each received message to |
23044 |
-+ * carry a list of the well-known names the sendind connection currently |
23045 |
-+ * owns. The current UID is needed in order to determine the name of the |
23046 |
-+ * bus node to connect to. |
23047 |
-+ */ |
23048 |
-+ r = bus_open_connection(&c->bus, getuid(), |
23049 |
-+ arg_busname, KDBUS_ATTACH_NAMES); |
23050 |
-+ if (r < 0) |
23051 |
-+ goto error; |
23052 |
-+ |
23053 |
-+ /* |
23054 |
-+ * Install a kdbus match so the child's connection gets notified when |
23055 |
-+ * the master loses its well-known name. |
23056 |
-+ */ |
23057 |
-+ r = bus_install_name_loss_match(c->bus, arg_master); |
23058 |
-+ if (r < 0) |
23059 |
-+ goto error; |
23060 |
-+ |
23061 |
-+ *out = c; |
23062 |
-+ return 0; |
23063 |
-+ |
23064 |
-+error: |
23065 |
-+ child_free(c); |
23066 |
-+ return r; |
23067 |
-+} |
23068 |
-+ |
23069 |
-+static void child_free(struct child *c) |
23070 |
-+{ |
23071 |
-+ if (!c) |
23072 |
-+ return; |
23073 |
-+ |
23074 |
-+ bus_close_connection(c->bus); |
23075 |
-+ prime_free(c->prime); |
23076 |
-+ free(c); |
23077 |
-+} |
23078 |
-+ |
23079 |
-+static int child_run(struct child *c) |
23080 |
-+{ |
23081 |
-+ struct kdbus_cmd_send cmd; |
23082 |
-+ struct kdbus_item *item; |
23083 |
-+ struct kdbus_vec *vec = NULL; |
23084 |
-+ struct kdbus_msg *msg; |
23085 |
-+ struct timespec spec; |
23086 |
-+ size_t n, steps, size; |
23087 |
-+ int r = 0; |
23088 |
-+ |
23089 |
-+ /* |
23090 |
-+ * Let's send a message to the master and ask for work. To do this, |
23091 |
-+ * we use the KDBUS_CMD_SEND ioctl, which takes an argument of type |
23092 |
-+ * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual |
23093 |
-+ * message to send. See kdbus.message(7). |
23094 |
-+ */ |
23095 |
-+ size = sizeof(*msg); |
23096 |
-+ size += KDBUS_ITEM_SIZE(strlen(arg_master) + 1); |
23097 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
23098 |
-+ |
23099 |
-+ msg = alloca(size); |
23100 |
-+ memset(msg, 0, size); |
23101 |
-+ msg->size = size; |
23102 |
-+ |
23103 |
-+ /* |
23104 |
-+ * Tell the kernel that we expect a reply to this message. This means |
23105 |
-+ * that |
23106 |
-+ * |
23107 |
-+ * a) The remote peer will gain temporary permission to talk to us |
23108 |
-+ * even if it would not be allowed to normally. |
23109 |
-+ * |
23110 |
-+ * b) A timeout value is required. |
23111 |
-+ * |
23112 |
-+ * For asynchronous send commands, if no reply is received, we will |
23113 |
-+ * get a kernel notification with an item of type |
23114 |
-+ * KDBUS_ITEM_REPLY_TIMEOUT attached. |
23115 |
-+ * |
23116 |
-+ * For synchronous send commands (which this example does), the |
23117 |
-+ * ioctl will block until a reply is received or the timeout is |
23118 |
-+ * exceeded. |
23119 |
-+ */ |
23120 |
-+ msg->flags = KDBUS_MSG_EXPECT_REPLY; |
23121 |
-+ |
23122 |
-+ /* Set our cookie. Replies must use this cookie to send their reply. */ |
23123 |
-+ msg->cookie = 1; |
23124 |
-+ |
23125 |
-+ /* The payload_type is arbitrary, but it must be non-zero */ |
23126 |
-+ msg->payload_type = 0xdeadbeef; |
23127 |
-+ |
23128 |
-+ /* |
23129 |
-+ * We are sending our message to the current owner of a well-known |
23130 |
-+ * name. This makes an item of type KDBUS_ITEM_DST_NAME mandatory. |
23131 |
-+ */ |
23132 |
-+ msg->dst_id = KDBUS_DST_ID_NAME; |
23133 |
-+ |
23134 |
-+ /* |
23135 |
-+ * Set the reply timeout to 5 seconds. Timeouts are always set in |
23136 |
-+ * absolute timestamps, based con CLOCK_MONOTONIC. See kdbus.message(7). |
23137 |
-+ */ |
23138 |
-+ clock_gettime(CLOCK_MONOTONIC_COARSE, &spec); |
23139 |
-+ msg->timeout_ns += (5 + spec.tv_sec) * 1000ULL * 1000ULL * 1000ULL; |
23140 |
-+ msg->timeout_ns += spec.tv_nsec; |
23141 |
-+ |
23142 |
-+ /* |
23143 |
-+ * Fill the appended items. First, set the well-known name of the |
23144 |
-+ * destination we want to talk to. |
23145 |
-+ */ |
23146 |
-+ item = msg->items; |
23147 |
-+ item->type = KDBUS_ITEM_DST_NAME; |
23148 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(arg_master) + 1; |
23149 |
-+ strcpy(item->str, arg_master); |
23150 |
-+ |
23151 |
-+ /* |
23152 |
-+ * The 2nd item contains a vector to memory we want to send. It |
23153 |
-+ * can be content of any type. In our case, we're sending a one-byte |
23154 |
-+ * string only. The memory referenced by this item will be copied into |
23155 |
-+ * the pool of the receiver connection, and does not need to be valid |
23156 |
-+ * after the command is employed. |
23157 |
-+ */ |
23158 |
-+ item = KDBUS_ITEM_NEXT(item); |
23159 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
23160 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
23161 |
-+ item->vec.address = (uintptr_t)"r"; |
23162 |
-+ item->vec.size = 1; |
23163 |
-+ |
23164 |
-+ /* Set up the command struct and reference the message we prepared */ |
23165 |
-+ memset(&cmd, 0, sizeof(cmd)); |
23166 |
-+ cmd.size = sizeof(cmd); |
23167 |
-+ cmd.msg_address = (uintptr_t)msg; |
23168 |
-+ |
23169 |
-+ /* |
23170 |
-+ * The send commands knows a mode in which it will block until a |
23171 |
-+ * reply to a message is received. This example uses that mode. |
23172 |
-+ * The pool offset to the received reply will be stored in the command |
23173 |
-+ * struct after the send command returned. See below. |
23174 |
-+ */ |
23175 |
-+ cmd.flags = KDBUS_SEND_SYNC_REPLY; |
23176 |
-+ |
23177 |
-+ /* |
23178 |
-+ * Finally, employ the command on the connection owner |
23179 |
-+ * file descriptor. |
23180 |
-+ */ |
23181 |
-+ r = kdbus_cmd_send(c->bus->fd, &cmd); |
23182 |
-+ if (r == -ESRCH || r == -EPIPE || r == -ECONNRESET) |
23183 |
-+ return 0; |
23184 |
-+ if (r < 0) |
23185 |
-+ return err_r(r, "cannot send request to master"); |
23186 |
-+ |
23187 |
-+ /* |
23188 |
-+ * The command was sent with the KDBUS_SEND_SYNC_REPLY flag set, |
23189 |
-+ * and returned successfully, which means that cmd.reply.offset now |
23190 |
-+ * points to a message inside our connection's pool where the reply |
23191 |
-+ * is found. This is equivalent to receiving the reply with |
23192 |
-+ * KDBUS_CMD_RECV, but it doesn't require waiting for the reply with |
23193 |
-+ * poll() and also saves the ioctl to receive the message. |
23194 |
-+ */ |
23195 |
-+ msg = (void *)(c->bus->pool + cmd.reply.offset); |
23196 |
-+ |
23197 |
-+ /* |
23198 |
-+ * A messages describes its actual payload in an array of items. |
23199 |
-+ * KDBUS_FOREACH() is a simple iterator that walks such an array. |
23200 |
-+ * struct kdbus_msg has a field to denote its total size, which is |
23201 |
-+ * needed to determine the number of items in the array. |
23202 |
-+ */ |
23203 |
-+ KDBUS_FOREACH(item, msg->items, |
23204 |
-+ msg->size - offsetof(struct kdbus_msg, items)) { |
23205 |
-+ /* |
23206 |
-+ * An item of type PAYLOAD_OFF describes in-line memory |
23207 |
-+ * stored in the pool at a described offset. That offset is |
23208 |
-+ * relative to the start address of the message header. |
23209 |
-+ * This example program only expects one single item of that |
23210 |
-+ * type, remembers the struct kdbus_vec member of the item |
23211 |
-+ * when it sees it, and bails out if there is more than one |
23212 |
-+ * of them. |
23213 |
-+ */ |
23214 |
-+ if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { |
23215 |
-+ if (vec) { |
23216 |
-+ r = err_r(-EEXIST, |
23217 |
-+ "message with multiple vecs"); |
23218 |
-+ break; |
23219 |
-+ } |
23220 |
-+ vec = &item->vec; |
23221 |
-+ if (vec->size != 2 * sizeof(size_t)) { |
23222 |
-+ r = err_r(-EINVAL, "invalid message size"); |
23223 |
-+ break; |
23224 |
-+ } |
23225 |
-+ /* |
23226 |
-+ * MEMFDs are transported as items of type PAYLOAD_MEMFD. |
23227 |
-+ * If such an item is attached, a new file descriptor was |
23228 |
-+ * installed into the task when KDBUS_CMD_RECV was called, and |
23229 |
-+ * its number is stored in item->memfd.fd. |
23230 |
-+ * Implementers *must* handle this item type close the |
23231 |
-+ * file descriptor when no longer needed in order to prevent |
23232 |
-+ * file descriptor exhaustion. This example program just bails |
23233 |
-+ * out with an error in this case, as memfds are not expected |
23234 |
-+ * in this context. |
23235 |
-+ */ |
23236 |
-+ } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) { |
23237 |
-+ r = err_r(-EINVAL, "message with memfd"); |
23238 |
-+ break; |
23239 |
-+ } |
23240 |
-+ } |
23241 |
-+ if (r < 0) |
23242 |
-+ goto exit; |
23243 |
-+ if (!vec) { |
23244 |
-+ r = err_r(-EINVAL, "empty message"); |
23245 |
-+ goto exit; |
23246 |
-+ } |
23247 |
-+ |
23248 |
-+ n = ((size_t *)((const uint8_t *)msg + vec->offset))[0]; |
23249 |
-+ steps = ((size_t *)((const uint8_t *)msg + vec->offset))[1]; |
23250 |
-+ |
23251 |
-+ while (steps-- > 0) { |
23252 |
-+ ++n; |
23253 |
-+ r = prime_run(c->prime, c->bus, n); |
23254 |
-+ if (r < 0) |
23255 |
-+ break; |
23256 |
-+ r = bus_poll(c->bus); |
23257 |
-+ if (r != 0) { |
23258 |
-+ r = r < 0 ? r : -EINTR; |
23259 |
-+ break; |
23260 |
-+ } |
23261 |
-+ } |
23262 |
-+ |
23263 |
-+exit: |
23264 |
-+ /* |
23265 |
-+ * We are done with the memory slice that was given to us through |
23266 |
-+ * cmd.reply.offset. Tell the kernel it can use it for other content |
23267 |
-+ * in the future. See kdbus.pool(7). |
23268 |
-+ */ |
23269 |
-+ bus_poool_free_slice(c->bus, cmd.reply.offset); |
23270 |
-+ return r; |
23271 |
-+} |
23272 |
-+ |
23273 |
-+/* |
23274 |
-+ * Prime Computation |
23275 |
-+ * |
23276 |
-+ */ |
23277 |
-+ |
23278 |
-+static int prime_new(struct prime **out) |
23279 |
-+{ |
23280 |
-+ struct prime *p; |
23281 |
-+ int r; |
23282 |
-+ |
23283 |
-+ p = calloc(1, sizeof(*p)); |
23284 |
-+ if (!p) |
23285 |
-+ return err("cannot allocate prime memory"); |
23286 |
-+ |
23287 |
-+ p->fd = -1; |
23288 |
-+ p->area = MAP_FAILED; |
23289 |
-+ p->max = MAX_PRIMES; |
23290 |
-+ |
23291 |
-+ /* |
23292 |
-+ * Prepare and map a memfd to store the bit-fields for the number |
23293 |
-+ * ranges we want to perform the prime detection on. |
23294 |
-+ */ |
23295 |
-+ p->fd = syscall(__NR_memfd_create, "prime-area", MFD_CLOEXEC); |
23296 |
-+ if (p->fd < 0) { |
23297 |
-+ r = err("cannot create memfd"); |
23298 |
-+ goto error; |
23299 |
-+ } |
23300 |
-+ |
23301 |
-+ r = ftruncate(p->fd, p->max / 8 + 1); |
23302 |
-+ if (r < 0) { |
23303 |
-+ r = err("cannot ftruncate area"); |
23304 |
-+ goto error; |
23305 |
-+ } |
23306 |
-+ |
23307 |
-+ p->area = mmap(NULL, p->max / 8 + 1, PROT_READ | PROT_WRITE, |
23308 |
-+ MAP_SHARED, p->fd, 0); |
23309 |
-+ if (p->area == MAP_FAILED) { |
23310 |
-+ r = err("cannot mmap memfd"); |
23311 |
-+ goto error; |
23312 |
-+ } |
23313 |
-+ |
23314 |
-+ *out = p; |
23315 |
-+ return 0; |
23316 |
-+ |
23317 |
-+error: |
23318 |
-+ prime_free(p); |
23319 |
-+ return r; |
23320 |
-+} |
23321 |
-+ |
23322 |
-+static void prime_free(struct prime *p) |
23323 |
-+{ |
23324 |
-+ if (!p) |
23325 |
-+ return; |
23326 |
-+ |
23327 |
-+ if (p->area != MAP_FAILED) |
23328 |
-+ munmap(p->area, p->max / 8 + 1); |
23329 |
-+ if (p->fd >= 0) |
23330 |
-+ close(p->fd); |
23331 |
-+ free(p); |
23332 |
-+} |
23333 |
-+ |
23334 |
-+static bool prime_done(struct prime *p) |
23335 |
-+{ |
23336 |
-+ return p->done >= p->max; |
23337 |
-+} |
23338 |
-+ |
23339 |
-+static void prime_consume(struct prime *p, size_t amount) |
23340 |
-+{ |
23341 |
-+ p->done += amount; |
23342 |
-+} |
23343 |
-+ |
23344 |
-+static int prime_run(struct prime *p, struct bus *cancel, size_t number) |
23345 |
-+{ |
23346 |
-+ size_t i, n = 0; |
23347 |
-+ int r; |
23348 |
-+ |
23349 |
-+ if (number < 2 || number > 65535) |
23350 |
-+ return 0; |
23351 |
-+ |
23352 |
-+ for (i = number * number; |
23353 |
-+ i < p->max && i > number; |
23354 |
-+ i += number) { |
23355 |
-+ p->area[i / 8] |= 1 << (i % 8); |
23356 |
-+ |
23357 |
-+ if (!(++n % (1 << 20))) { |
23358 |
-+ r = bus_poll(cancel); |
23359 |
-+ if (r != 0) |
23360 |
-+ return r < 0 ? r : -EINTR; |
23361 |
-+ } |
23362 |
-+ } |
23363 |
-+ |
23364 |
-+ return 0; |
23365 |
-+} |
23366 |
-+ |
23367 |
-+static void prime_print(struct prime *p) |
23368 |
-+{ |
23369 |
-+ size_t i, l = 0; |
23370 |
-+ |
23371 |
-+ fprintf(stderr, "PRIMES:"); |
23372 |
-+ for (i = 0; i < p->max; ++i) { |
23373 |
-+ if (!(p->area[i / 8] & (1 << (i % 8)))) |
23374 |
-+ fprintf(stderr, "%c%7zu", !(l++ % 16) ? '\n' : ' ', i); |
23375 |
-+ } |
23376 |
-+ fprintf(stderr, "\nEND\n"); |
23377 |
-+} |
23378 |
-+ |
23379 |
-+static int bus_open_connection(struct bus **out, uid_t uid, const char *name, |
23380 |
-+ uint64_t recv_flags) |
23381 |
-+{ |
23382 |
-+ struct kdbus_cmd_hello hello; |
23383 |
-+ char path[128]; |
23384 |
-+ struct bus *b; |
23385 |
-+ int r; |
23386 |
-+ |
23387 |
-+ /* |
23388 |
-+ * The 'bus' object is our representation of a kdbus connection which |
23389 |
-+ * stores two details: the connection owner file descriptor, and the |
23390 |
-+ * mmap()ed memory of its associated pool. See kdbus.connection(7) and |
23391 |
-+ * kdbus.pool(7). |
23392 |
-+ */ |
23393 |
-+ b = calloc(1, sizeof(*b)); |
23394 |
-+ if (!b) |
23395 |
-+ return err("cannot allocate bus memory"); |
23396 |
-+ |
23397 |
-+ b->fd = -1; |
23398 |
-+ b->pool = MAP_FAILED; |
23399 |
-+ |
23400 |
-+ /* Compute the name of the bus node to connect to. */ |
23401 |
-+ snprintf(path, sizeof(path), "/sys/fs/%s/%lu-%s/bus", |
23402 |
-+ arg_modname, (unsigned long)uid, name); |
23403 |
-+ b->fd = open(path, O_RDWR | O_CLOEXEC); |
23404 |
-+ if (b->fd < 0) { |
23405 |
-+ r = err("cannot open bus"); |
23406 |
-+ goto error; |
23407 |
-+ } |
23408 |
-+ |
23409 |
-+ /* |
23410 |
-+ * To make a connection to the bus, the KDBUS_CMD_HELLO ioctl is used. |
23411 |
-+ * It takes an argument of type 'struct kdbus_cmd_hello'. |
23412 |
-+ */ |
23413 |
-+ memset(&hello, 0, sizeof(hello)); |
23414 |
-+ hello.size = sizeof(hello); |
23415 |
-+ |
23416 |
-+ /* |
23417 |
-+ * Specify a mask of metadata attach flags, describing metadata items |
23418 |
-+ * that this new connection allows to be sent. |
23419 |
-+ */ |
23420 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
23421 |
-+ |
23422 |
-+ /* |
23423 |
-+ * Specify a mask of metadata attach flags, describing metadata items |
23424 |
-+ * that this new connection wants to be receive along with each message. |
23425 |
-+ */ |
23426 |
-+ hello.attach_flags_recv = recv_flags; |
23427 |
-+ |
23428 |
-+ /* |
23429 |
-+ * A connection may choose the size of its pool, but the number has to |
23430 |
-+ * comply with two rules: a) it must be greater than 0, and b) it must |
23431 |
-+ * be a mulitple of PAGE_SIZE. See kdbus.pool(7). |
23432 |
-+ */ |
23433 |
-+ hello.pool_size = POOL_SIZE; |
23434 |
-+ |
23435 |
-+ /* |
23436 |
-+ * Now employ the command on the file descriptor opened above. |
23437 |
-+ * This command will turn the file descriptor into a connection-owner |
23438 |
-+ * file descriptor that controls the life-time of the connection; once |
23439 |
-+ * it's closed, the connection is shut down. |
23440 |
-+ */ |
23441 |
-+ r = kdbus_cmd_hello(b->fd, &hello); |
23442 |
-+ if (r < 0) { |
23443 |
-+ err_r(r, "HELLO failed"); |
23444 |
-+ goto error; |
23445 |
-+ } |
23446 |
-+ |
23447 |
-+ bus_poool_free_slice(b, hello.offset); |
23448 |
-+ |
23449 |
-+ /* |
23450 |
-+ * Map the pool of the connection. Its size has been set in the |
23451 |
-+ * command struct above. See kdbus.pool(7). |
23452 |
-+ */ |
23453 |
-+ b->pool = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, b->fd, 0); |
23454 |
-+ if (b->pool == MAP_FAILED) { |
23455 |
-+ r = err("cannot mmap pool"); |
23456 |
-+ goto error; |
23457 |
-+ } |
23458 |
-+ |
23459 |
-+ *out = b; |
23460 |
-+ return 0; |
23461 |
-+ |
23462 |
-+error: |
23463 |
-+ bus_close_connection(b); |
23464 |
-+ return r; |
23465 |
-+} |
23466 |
-+ |
23467 |
-+static void bus_close_connection(struct bus *b) |
23468 |
-+{ |
23469 |
-+ if (!b) |
23470 |
-+ return; |
23471 |
-+ |
23472 |
-+ /* |
23473 |
-+ * A bus connection is closed by simply calling close() on the |
23474 |
-+ * connection owner file descriptor. The unique name and all owned |
23475 |
-+ * well-known names of the conneciton will disappear. |
23476 |
-+ * See kdbus.connection(7). |
23477 |
-+ */ |
23478 |
-+ if (b->pool != MAP_FAILED) |
23479 |
-+ munmap(b->pool, POOL_SIZE); |
23480 |
-+ if (b->fd >= 0) |
23481 |
-+ close(b->fd); |
23482 |
-+ free(b); |
23483 |
-+} |
23484 |
-+ |
23485 |
-+static void bus_poool_free_slice(struct bus *b, uint64_t offset) |
23486 |
-+{ |
23487 |
-+ struct kdbus_cmd_free cmd = { |
23488 |
-+ .size = sizeof(cmd), |
23489 |
-+ .offset = offset, |
23490 |
-+ }; |
23491 |
-+ int r; |
23492 |
-+ |
23493 |
-+ /* |
23494 |
-+ * Once we're done with a piece of pool memory that was returned |
23495 |
-+ * by a command, we have to call the KDBUS_CMD_FREE ioctl on it so it |
23496 |
-+ * can be reused. The command takes an argument of type |
23497 |
-+ * 'struct kdbus_cmd_free', in which the pool offset of the slice to |
23498 |
-+ * free is stored. The ioctl is employed on the connection owner |
23499 |
-+ * file descriptor. See kdbus.pool(7), |
23500 |
-+ */ |
23501 |
-+ r = kdbus_cmd_free(b->fd, &cmd); |
23502 |
-+ if (r < 0) |
23503 |
-+ err_r(r, "cannot free pool slice"); |
23504 |
-+} |
23505 |
-+ |
23506 |
-+static int bus_acquire_name(struct bus *b, const char *name) |
23507 |
-+{ |
23508 |
-+ struct kdbus_item *item; |
23509 |
-+ struct kdbus_cmd *cmd; |
23510 |
-+ size_t size; |
23511 |
-+ int r; |
23512 |
-+ |
23513 |
-+ /* |
23514 |
-+ * This function acquires a well-known name on the bus through the |
23515 |
-+ * KDBUS_CMD_NAME_ACQUIRE ioctl. This ioctl takes an argument of type |
23516 |
-+ * 'struct kdbus_cmd', which is assembled below. See kdbus.name(7). |
23517 |
-+ */ |
23518 |
-+ size = sizeof(*cmd); |
23519 |
-+ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
23520 |
-+ |
23521 |
-+ cmd = alloca(size); |
23522 |
-+ memset(cmd, 0, size); |
23523 |
-+ cmd->size = size; |
23524 |
-+ |
23525 |
-+ /* |
23526 |
-+ * The command requires an item of type KDBUS_ITEM_NAME, and its |
23527 |
-+ * content must be a valid bus name. |
23528 |
-+ */ |
23529 |
-+ item = cmd->items; |
23530 |
-+ item->type = KDBUS_ITEM_NAME; |
23531 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
23532 |
-+ strcpy(item->str, name); |
23533 |
-+ |
23534 |
-+ /* |
23535 |
-+ * Employ the command on the connection owner file descriptor. |
23536 |
-+ */ |
23537 |
-+ r = kdbus_cmd_name_acquire(b->fd, cmd); |
23538 |
-+ if (r < 0) |
23539 |
-+ return err_r(r, "cannot acquire name"); |
23540 |
-+ |
23541 |
-+ return 0; |
23542 |
-+} |
23543 |
-+ |
23544 |
-+static int bus_install_name_loss_match(struct bus *b, const char *name) |
23545 |
-+{ |
23546 |
-+ struct kdbus_cmd_match *match; |
23547 |
-+ struct kdbus_item *item; |
23548 |
-+ size_t size; |
23549 |
-+ int r; |
23550 |
-+ |
23551 |
-+ /* |
23552 |
-+ * In order to install a match for signal messages, we have to |
23553 |
-+ * assemble a 'struct kdbus_cmd_match' and use it along with the |
23554 |
-+ * KDBUS_CMD_MATCH_ADD ioctl. See kdbus.match(7). |
23555 |
-+ */ |
23556 |
-+ size = sizeof(*match); |
23557 |
-+ size += KDBUS_ITEM_SIZE(sizeof(item->name_change) + strlen(name) + 1); |
23558 |
-+ |
23559 |
-+ match = alloca(size); |
23560 |
-+ memset(match, 0, size); |
23561 |
-+ match->size = size; |
23562 |
-+ |
23563 |
-+ /* |
23564 |
-+ * A match is comprised of many 'rules', each of which describes a |
23565 |
-+ * mandatory detail of the message. All rules of a match must be |
23566 |
-+ * satified in order to make a message pass. |
23567 |
-+ */ |
23568 |
-+ item = match->items; |
23569 |
-+ |
23570 |
-+ /* |
23571 |
-+ * In this case, we're interested in notifications that inform us |
23572 |
-+ * about a well-known name being removed from the bus. |
23573 |
-+ */ |
23574 |
-+ item->type = KDBUS_ITEM_NAME_REMOVE; |
23575 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
23576 |
-+ sizeof(item->name_change) + strlen(name) + 1; |
23577 |
-+ |
23578 |
-+ /* |
23579 |
-+ * We could limit the match further and require a specific unique-ID |
23580 |
-+ * to be the new or the old owner of the name. In this case, however, |
23581 |
-+ * we don't, and allow 'any' id. |
23582 |
-+ */ |
23583 |
-+ item->name_change.old_id.id = KDBUS_MATCH_ID_ANY; |
23584 |
-+ item->name_change.new_id.id = KDBUS_MATCH_ID_ANY; |
23585 |
-+ |
23586 |
-+ /* Copy in the well-known name we're interested in */ |
23587 |
-+ strcpy(item->name_change.name, name); |
23588 |
-+ |
23589 |
-+ /* |
23590 |
-+ * Add the match through the KDBUS_CMD_MATCH_ADD ioctl, employed on |
23591 |
-+ * the connection owner fd. |
23592 |
-+ */ |
23593 |
-+ r = kdbus_cmd_match_add(b->fd, match); |
23594 |
-+ if (r < 0) |
23595 |
-+ return err_r(r, "cannot add match"); |
23596 |
-+ |
23597 |
-+ return 0; |
23598 |
-+} |
23599 |
-+ |
23600 |
-+static int bus_poll(struct bus *b) |
23601 |
-+{ |
23602 |
-+ struct pollfd fds[1] = {}; |
23603 |
-+ int r; |
23604 |
-+ |
23605 |
-+ /* |
23606 |
-+ * A connection endpoint supports poll() and will wake-up the |
23607 |
-+ * task with POLLIN set once a message has arrived. |
23608 |
-+ */ |
23609 |
-+ fds[0].fd = b->fd; |
23610 |
-+ fds[0].events = POLLIN; |
23611 |
-+ r = poll(fds, sizeof(fds) / sizeof(*fds), 0); |
23612 |
-+ if (r < 0) |
23613 |
-+ return err("cannot poll bus"); |
23614 |
-+ return !!(fds[0].revents & POLLIN); |
23615 |
-+} |
23616 |
-+ |
23617 |
-+static int bus_make(uid_t uid, const char *name) |
23618 |
-+{ |
23619 |
-+ struct kdbus_item *item; |
23620 |
-+ struct kdbus_cmd *make; |
23621 |
-+ char path[128], busname[128]; |
23622 |
-+ size_t size; |
23623 |
-+ int r, fd; |
23624 |
-+ |
23625 |
-+ /* |
23626 |
-+ * Compute the full path to the 'control' node. 'arg_modname' may be |
23627 |
-+ * set to a different value than 'kdbus' for development purposes. |
23628 |
-+ * The 'control' node is the primary entry point to kdbus that must be |
23629 |
-+ * used in order to create a bus. See kdbus(7) and kdbus.bus(7). |
23630 |
-+ */ |
23631 |
-+ snprintf(path, sizeof(path), "/sys/fs/%s/control", arg_modname); |
23632 |
-+ |
23633 |
-+ /* |
23634 |
-+ * Compute the bus name. A valid bus name must always be prefixed with |
23635 |
-+ * the EUID of the currently running process in order to avoid name |
23636 |
-+ * conflicts. See kdbus.bus(7). |
23637 |
-+ */ |
23638 |
-+ snprintf(busname, sizeof(busname), "%lu-%s", (unsigned long)uid, name); |
23639 |
-+ |
23640 |
-+ fd = open(path, O_RDWR | O_CLOEXEC); |
23641 |
-+ if (fd < 0) |
23642 |
-+ return err("cannot open control file"); |
23643 |
-+ |
23644 |
-+ /* |
23645 |
-+ * The KDBUS_CMD_BUS_MAKE ioctl takes an argument of type |
23646 |
-+ * 'struct kdbus_cmd', and expects at least two items attached to |
23647 |
-+ * it: one to decribe the bloom parameters to be propagated to |
23648 |
-+ * connections of the bus, and the name of the bus that was computed |
23649 |
-+ * above. Assemble this struct now, and fill it with values. |
23650 |
-+ */ |
23651 |
-+ size = sizeof(*make); |
23652 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_parameter)); |
23653 |
-+ size += KDBUS_ITEM_SIZE(strlen(busname) + 1); |
23654 |
-+ |
23655 |
-+ make = alloca(size); |
23656 |
-+ memset(make, 0, size); |
23657 |
-+ make->size = size; |
23658 |
-+ |
23659 |
-+ /* |
23660 |
-+ * Each item has a 'type' and 'size' field, and must be stored at an |
23661 |
-+ * 8-byte aligned address. The KDBUS_ITEM_NEXT macro is used to advance |
23662 |
-+ * the pointer. See kdbus.item(7) for more details. |
23663 |
-+ */ |
23664 |
-+ item = make->items; |
23665 |
-+ item->type = KDBUS_ITEM_BLOOM_PARAMETER; |
23666 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->bloom_parameter); |
23667 |
-+ item->bloom_parameter.size = 8; |
23668 |
-+ item->bloom_parameter.n_hash = 1; |
23669 |
-+ |
23670 |
-+ /* The name of the new bus is stored in the next item. */ |
23671 |
-+ item = KDBUS_ITEM_NEXT(item); |
23672 |
-+ item->type = KDBUS_ITEM_MAKE_NAME; |
23673 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(busname) + 1; |
23674 |
-+ strcpy(item->str, busname); |
23675 |
-+ |
23676 |
-+ /* |
23677 |
-+ * Now create the bus via the KDBUS_CMD_BUS_MAKE ioctl and return the |
23678 |
-+ * fd that was used back to the caller of this function. This fd is now |
23679 |
-+ * called a 'bus owner file descriptor', and it controls the life-time |
23680 |
-+ * of the newly created bus; once the file descriptor is closed, the |
23681 |
-+ * bus goes away, and all connections are shut down. See kdbus.bus(7). |
23682 |
-+ */ |
23683 |
-+ r = kdbus_cmd_bus_make(fd, make); |
23684 |
-+ if (r < 0) { |
23685 |
-+ err_r(r, "cannot make bus"); |
23686 |
-+ close(fd); |
23687 |
-+ return r; |
23688 |
-+ } |
23689 |
-+ |
23690 |
-+ return fd; |
23691 |
-+} |
23692 |
-+ |
23693 |
-+#else |
23694 |
-+ |
23695 |
-+#warning "Skipping compilation due to unsupported libc version" |
23696 |
-+ |
23697 |
-+int main(int argc, char **argv) |
23698 |
-+{ |
23699 |
-+ fprintf(stderr, |
23700 |
-+ "Compilation of %s was skipped due to unsupported libc.\n", |
23701 |
-+ argv[0]); |
23702 |
-+ |
23703 |
-+ return EXIT_FAILURE; |
23704 |
-+} |
23705 |
-+ |
23706 |
-+#endif /* libc sanity check */ |
23707 |
-diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile |
23708 |
-index 95abddc..b57100c 100644 |
23709 |
---- a/tools/testing/selftests/Makefile |
23710 |
-+++ b/tools/testing/selftests/Makefile |
23711 |
-@@ -5,6 +5,7 @@ TARGETS += exec |
23712 |
- TARGETS += firmware |
23713 |
- TARGETS += ftrace |
23714 |
- TARGETS += kcmp |
23715 |
-+TARGETS += kdbus |
23716 |
- TARGETS += memfd |
23717 |
- TARGETS += memory-hotplug |
23718 |
- TARGETS += mount |
23719 |
-diff --git a/tools/testing/selftests/kdbus/.gitignore b/tools/testing/selftests/kdbus/.gitignore |
23720 |
-new file mode 100644 |
23721 |
-index 0000000..d3ef42f |
23722 |
---- /dev/null |
23723 |
-+++ b/tools/testing/selftests/kdbus/.gitignore |
23724 |
-@@ -0,0 +1 @@ |
23725 |
-+kdbus-test |
23726 |
-diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile |
23727 |
-new file mode 100644 |
23728 |
-index 0000000..8f36cb5 |
23729 |
---- /dev/null |
23730 |
-+++ b/tools/testing/selftests/kdbus/Makefile |
23731 |
-@@ -0,0 +1,49 @@ |
23732 |
-+CFLAGS += -I../../../../usr/include/ |
23733 |
-+CFLAGS += -I../../../../samples/kdbus/ |
23734 |
-+CFLAGS += -I../../../../include/uapi/ |
23735 |
-+CFLAGS += -std=gnu99 |
23736 |
-+CFLAGS += -DKBUILD_MODNAME=\"kdbus\" -D_GNU_SOURCE |
23737 |
-+LDLIBS = -pthread -lcap -lm |
23738 |
-+ |
23739 |
-+OBJS= \ |
23740 |
-+ kdbus-enum.o \ |
23741 |
-+ kdbus-util.o \ |
23742 |
-+ kdbus-test.o \ |
23743 |
-+ kdbus-test.o \ |
23744 |
-+ test-activator.o \ |
23745 |
-+ test-benchmark.o \ |
23746 |
-+ test-bus.o \ |
23747 |
-+ test-chat.o \ |
23748 |
-+ test-connection.o \ |
23749 |
-+ test-daemon.o \ |
23750 |
-+ test-endpoint.o \ |
23751 |
-+ test-fd.o \ |
23752 |
-+ test-free.o \ |
23753 |
-+ test-match.o \ |
23754 |
-+ test-message.o \ |
23755 |
-+ test-metadata-ns.o \ |
23756 |
-+ test-monitor.o \ |
23757 |
-+ test-names.o \ |
23758 |
-+ test-policy.o \ |
23759 |
-+ test-policy-ns.o \ |
23760 |
-+ test-policy-priv.o \ |
23761 |
-+ test-sync.o \ |
23762 |
-+ test-timeout.o |
23763 |
-+ |
23764 |
-+all: kdbus-test |
23765 |
-+ |
23766 |
-+include ../lib.mk |
23767 |
-+ |
23768 |
-+%.o: %.c kdbus-enum.h kdbus-test.h kdbus-util.h |
23769 |
-+ $(CC) $(CFLAGS) -c $< -o $@ |
23770 |
-+ |
23771 |
-+kdbus-test: $(OBJS) |
23772 |
-+ $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@ |
23773 |
-+ |
23774 |
-+TEST_PROGS := kdbus-test |
23775 |
-+ |
23776 |
-+run_tests: |
23777 |
-+ ./kdbus-test --tap |
23778 |
-+ |
23779 |
-+clean: |
23780 |
-+ rm -f *.o kdbus-test |
23781 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-enum.c b/tools/testing/selftests/kdbus/kdbus-enum.c |
23782 |
-new file mode 100644 |
23783 |
-index 0000000..4f1e579 |
23784 |
---- /dev/null |
23785 |
-+++ b/tools/testing/selftests/kdbus/kdbus-enum.c |
23786 |
-@@ -0,0 +1,94 @@ |
23787 |
-+/* |
23788 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
23789 |
-+ * |
23790 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
23791 |
-+ * the terms of the GNU Lesser General Public License as published by the |
23792 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
23793 |
-+ * your option) any later version. |
23794 |
-+ */ |
23795 |
-+ |
23796 |
-+#include <stdio.h> |
23797 |
-+#include <string.h> |
23798 |
-+#include <fcntl.h> |
23799 |
-+#include <stdlib.h> |
23800 |
-+#include <stddef.h> |
23801 |
-+#include <unistd.h> |
23802 |
-+#include <stdint.h> |
23803 |
-+#include <errno.h> |
23804 |
-+ |
23805 |
-+#include "kdbus-util.h" |
23806 |
-+#include "kdbus-enum.h" |
23807 |
-+ |
23808 |
-+struct kdbus_enum_table { |
23809 |
-+ long long id; |
23810 |
-+ const char *name; |
23811 |
-+}; |
23812 |
-+ |
23813 |
-+#define TABLE(what) static struct kdbus_enum_table kdbus_table_##what[] |
23814 |
-+#define ENUM(_id) { .id = _id, .name = STRINGIFY(_id) } |
23815 |
-+#define LOOKUP(what) \ |
23816 |
-+ const char *enum_##what(long long id) \ |
23817 |
-+ { \ |
23818 |
-+ for (size_t i = 0; i < ELEMENTSOF(kdbus_table_##what); i++) \ |
23819 |
-+ if (id == kdbus_table_##what[i].id) \ |
23820 |
-+ return kdbus_table_##what[i].name; \ |
23821 |
-+ return "UNKNOWN"; \ |
23822 |
-+ } |
23823 |
-+ |
23824 |
-+TABLE(CMD) = { |
23825 |
-+ ENUM(KDBUS_CMD_BUS_MAKE), |
23826 |
-+ ENUM(KDBUS_CMD_ENDPOINT_MAKE), |
23827 |
-+ ENUM(KDBUS_CMD_HELLO), |
23828 |
-+ ENUM(KDBUS_CMD_SEND), |
23829 |
-+ ENUM(KDBUS_CMD_RECV), |
23830 |
-+ ENUM(KDBUS_CMD_LIST), |
23831 |
-+ ENUM(KDBUS_CMD_NAME_RELEASE), |
23832 |
-+ ENUM(KDBUS_CMD_CONN_INFO), |
23833 |
-+ ENUM(KDBUS_CMD_MATCH_ADD), |
23834 |
-+ ENUM(KDBUS_CMD_MATCH_REMOVE), |
23835 |
-+}; |
23836 |
-+LOOKUP(CMD); |
23837 |
-+ |
23838 |
-+TABLE(MSG) = { |
23839 |
-+ ENUM(_KDBUS_ITEM_NULL), |
23840 |
-+ ENUM(KDBUS_ITEM_PAYLOAD_VEC), |
23841 |
-+ ENUM(KDBUS_ITEM_PAYLOAD_OFF), |
23842 |
-+ ENUM(KDBUS_ITEM_PAYLOAD_MEMFD), |
23843 |
-+ ENUM(KDBUS_ITEM_FDS), |
23844 |
-+ ENUM(KDBUS_ITEM_BLOOM_PARAMETER), |
23845 |
-+ ENUM(KDBUS_ITEM_BLOOM_FILTER), |
23846 |
-+ ENUM(KDBUS_ITEM_DST_NAME), |
23847 |
-+ ENUM(KDBUS_ITEM_MAKE_NAME), |
23848 |
-+ ENUM(KDBUS_ITEM_ATTACH_FLAGS_SEND), |
23849 |
-+ ENUM(KDBUS_ITEM_ATTACH_FLAGS_RECV), |
23850 |
-+ ENUM(KDBUS_ITEM_ID), |
23851 |
-+ ENUM(KDBUS_ITEM_NAME), |
23852 |
-+ ENUM(KDBUS_ITEM_TIMESTAMP), |
23853 |
-+ ENUM(KDBUS_ITEM_CREDS), |
23854 |
-+ ENUM(KDBUS_ITEM_PIDS), |
23855 |
-+ ENUM(KDBUS_ITEM_AUXGROUPS), |
23856 |
-+ ENUM(KDBUS_ITEM_OWNED_NAME), |
23857 |
-+ ENUM(KDBUS_ITEM_TID_COMM), |
23858 |
-+ ENUM(KDBUS_ITEM_PID_COMM), |
23859 |
-+ ENUM(KDBUS_ITEM_EXE), |
23860 |
-+ ENUM(KDBUS_ITEM_CMDLINE), |
23861 |
-+ ENUM(KDBUS_ITEM_CGROUP), |
23862 |
-+ ENUM(KDBUS_ITEM_CAPS), |
23863 |
-+ ENUM(KDBUS_ITEM_SECLABEL), |
23864 |
-+ ENUM(KDBUS_ITEM_AUDIT), |
23865 |
-+ ENUM(KDBUS_ITEM_CONN_DESCRIPTION), |
23866 |
-+ ENUM(KDBUS_ITEM_NAME_ADD), |
23867 |
-+ ENUM(KDBUS_ITEM_NAME_REMOVE), |
23868 |
-+ ENUM(KDBUS_ITEM_NAME_CHANGE), |
23869 |
-+ ENUM(KDBUS_ITEM_ID_ADD), |
23870 |
-+ ENUM(KDBUS_ITEM_ID_REMOVE), |
23871 |
-+ ENUM(KDBUS_ITEM_REPLY_TIMEOUT), |
23872 |
-+ ENUM(KDBUS_ITEM_REPLY_DEAD), |
23873 |
-+}; |
23874 |
-+LOOKUP(MSG); |
23875 |
-+ |
23876 |
-+TABLE(PAYLOAD) = { |
23877 |
-+ ENUM(KDBUS_PAYLOAD_KERNEL), |
23878 |
-+ ENUM(KDBUS_PAYLOAD_DBUS), |
23879 |
-+}; |
23880 |
-+LOOKUP(PAYLOAD); |
23881 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-enum.h b/tools/testing/selftests/kdbus/kdbus-enum.h |
23882 |
-new file mode 100644 |
23883 |
-index 0000000..ed28cca |
23884 |
---- /dev/null |
23885 |
-+++ b/tools/testing/selftests/kdbus/kdbus-enum.h |
23886 |
-@@ -0,0 +1,15 @@ |
23887 |
-+/* |
23888 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
23889 |
-+ * |
23890 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
23891 |
-+ * the terms of the GNU Lesser General Public License as published by the |
23892 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
23893 |
-+ * your option) any later version. |
23894 |
-+ */ |
23895 |
-+ |
23896 |
-+#pragma once |
23897 |
-+ |
23898 |
-+const char *enum_CMD(long long id); |
23899 |
-+const char *enum_MSG(long long id); |
23900 |
-+const char *enum_MATCH(long long id); |
23901 |
-+const char *enum_PAYLOAD(long long id); |
23902 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-test.c b/tools/testing/selftests/kdbus/kdbus-test.c |
23903 |
-new file mode 100644 |
23904 |
-index 0000000..db57381 |
23905 |
---- /dev/null |
23906 |
-+++ b/tools/testing/selftests/kdbus/kdbus-test.c |
23907 |
-@@ -0,0 +1,905 @@ |
23908 |
-+#include <errno.h> |
23909 |
-+#include <stdio.h> |
23910 |
-+#include <string.h> |
23911 |
-+#include <fcntl.h> |
23912 |
-+#include <stdlib.h> |
23913 |
-+#include <stddef.h> |
23914 |
-+#include <time.h> |
23915 |
-+#include <unistd.h> |
23916 |
-+#include <stdint.h> |
23917 |
-+#include <assert.h> |
23918 |
-+#include <getopt.h> |
23919 |
-+#include <stdbool.h> |
23920 |
-+#include <signal.h> |
23921 |
-+#include <sys/mount.h> |
23922 |
-+#include <sys/prctl.h> |
23923 |
-+#include <sys/wait.h> |
23924 |
-+#include <sys/syscall.h> |
23925 |
-+#include <sys/eventfd.h> |
23926 |
-+#include <linux/sched.h> |
23927 |
-+ |
23928 |
-+#include "kdbus-util.h" |
23929 |
-+#include "kdbus-enum.h" |
23930 |
-+#include "kdbus-test.h" |
23931 |
-+ |
23932 |
-+enum { |
23933 |
-+ TEST_CREATE_BUS = 1 << 0, |
23934 |
-+ TEST_CREATE_CONN = 1 << 1, |
23935 |
-+}; |
23936 |
-+ |
23937 |
-+struct kdbus_test { |
23938 |
-+ const char *name; |
23939 |
-+ const char *desc; |
23940 |
-+ int (*func)(struct kdbus_test_env *env); |
23941 |
-+ unsigned int flags; |
23942 |
-+}; |
23943 |
-+ |
23944 |
-+struct kdbus_test_args { |
23945 |
-+ bool mntns; |
23946 |
-+ bool pidns; |
23947 |
-+ bool userns; |
23948 |
-+ char *uid_map; |
23949 |
-+ char *gid_map; |
23950 |
-+ int loop; |
23951 |
-+ int wait; |
23952 |
-+ int fork; |
23953 |
-+ int tap_output; |
23954 |
-+ char *module; |
23955 |
-+ char *root; |
23956 |
-+ char *test; |
23957 |
-+ char *busname; |
23958 |
-+}; |
23959 |
-+ |
23960 |
-+static const struct kdbus_test tests[] = { |
23961 |
-+ { |
23962 |
-+ .name = "bus-make", |
23963 |
-+ .desc = "bus make functions", |
23964 |
-+ .func = kdbus_test_bus_make, |
23965 |
-+ .flags = 0, |
23966 |
-+ }, |
23967 |
-+ { |
23968 |
-+ .name = "hello", |
23969 |
-+ .desc = "the HELLO command", |
23970 |
-+ .func = kdbus_test_hello, |
23971 |
-+ .flags = TEST_CREATE_BUS, |
23972 |
-+ }, |
23973 |
-+ { |
23974 |
-+ .name = "byebye", |
23975 |
-+ .desc = "the BYEBYE command", |
23976 |
-+ .func = kdbus_test_byebye, |
23977 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23978 |
-+ }, |
23979 |
-+ { |
23980 |
-+ .name = "chat", |
23981 |
-+ .desc = "a chat pattern", |
23982 |
-+ .func = kdbus_test_chat, |
23983 |
-+ .flags = TEST_CREATE_BUS, |
23984 |
-+ }, |
23985 |
-+ { |
23986 |
-+ .name = "daemon", |
23987 |
-+ .desc = "a simple daemon", |
23988 |
-+ .func = kdbus_test_daemon, |
23989 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
23990 |
-+ }, |
23991 |
-+ { |
23992 |
-+ .name = "fd-passing", |
23993 |
-+ .desc = "file descriptor passing", |
23994 |
-+ .func = kdbus_test_fd_passing, |
23995 |
-+ .flags = TEST_CREATE_BUS, |
23996 |
-+ }, |
23997 |
-+ { |
23998 |
-+ .name = "endpoint", |
23999 |
-+ .desc = "custom endpoint", |
24000 |
-+ .func = kdbus_test_custom_endpoint, |
24001 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24002 |
-+ }, |
24003 |
-+ { |
24004 |
-+ .name = "monitor", |
24005 |
-+ .desc = "monitor functionality", |
24006 |
-+ .func = kdbus_test_monitor, |
24007 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24008 |
-+ }, |
24009 |
-+ { |
24010 |
-+ .name = "name-basics", |
24011 |
-+ .desc = "basic name registry functions", |
24012 |
-+ .func = kdbus_test_name_basic, |
24013 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24014 |
-+ }, |
24015 |
-+ { |
24016 |
-+ .name = "name-conflict", |
24017 |
-+ .desc = "name registry conflict details", |
24018 |
-+ .func = kdbus_test_name_conflict, |
24019 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24020 |
-+ }, |
24021 |
-+ { |
24022 |
-+ .name = "name-queue", |
24023 |
-+ .desc = "queuing of names", |
24024 |
-+ .func = kdbus_test_name_queue, |
24025 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24026 |
-+ }, |
24027 |
-+ { |
24028 |
-+ .name = "name-takeover", |
24029 |
-+ .desc = "takeover of names", |
24030 |
-+ .func = kdbus_test_name_takeover, |
24031 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24032 |
-+ }, |
24033 |
-+ { |
24034 |
-+ .name = "message-basic", |
24035 |
-+ .desc = "basic message handling", |
24036 |
-+ .func = kdbus_test_message_basic, |
24037 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24038 |
-+ }, |
24039 |
-+ { |
24040 |
-+ .name = "message-prio", |
24041 |
-+ .desc = "handling of messages with priority", |
24042 |
-+ .func = kdbus_test_message_prio, |
24043 |
-+ .flags = TEST_CREATE_BUS, |
24044 |
-+ }, |
24045 |
-+ { |
24046 |
-+ .name = "message-quota", |
24047 |
-+ .desc = "message quotas are enforced", |
24048 |
-+ .func = kdbus_test_message_quota, |
24049 |
-+ .flags = TEST_CREATE_BUS, |
24050 |
-+ }, |
24051 |
-+ { |
24052 |
-+ .name = "memory-access", |
24053 |
-+ .desc = "memory access", |
24054 |
-+ .func = kdbus_test_memory_access, |
24055 |
-+ .flags = TEST_CREATE_BUS, |
24056 |
-+ }, |
24057 |
-+ { |
24058 |
-+ .name = "timeout", |
24059 |
-+ .desc = "timeout", |
24060 |
-+ .func = kdbus_test_timeout, |
24061 |
-+ .flags = TEST_CREATE_BUS, |
24062 |
-+ }, |
24063 |
-+ { |
24064 |
-+ .name = "sync-byebye", |
24065 |
-+ .desc = "synchronous replies vs. BYEBYE", |
24066 |
-+ .func = kdbus_test_sync_byebye, |
24067 |
-+ .flags = TEST_CREATE_BUS, |
24068 |
-+ }, |
24069 |
-+ { |
24070 |
-+ .name = "sync-reply", |
24071 |
-+ .desc = "synchronous replies", |
24072 |
-+ .func = kdbus_test_sync_reply, |
24073 |
-+ .flags = TEST_CREATE_BUS, |
24074 |
-+ }, |
24075 |
-+ { |
24076 |
-+ .name = "message-free", |
24077 |
-+ .desc = "freeing of memory", |
24078 |
-+ .func = kdbus_test_free, |
24079 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24080 |
-+ }, |
24081 |
-+ { |
24082 |
-+ .name = "connection-info", |
24083 |
-+ .desc = "retrieving connection information", |
24084 |
-+ .func = kdbus_test_conn_info, |
24085 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24086 |
-+ }, |
24087 |
-+ { |
24088 |
-+ .name = "connection-update", |
24089 |
-+ .desc = "updating connection information", |
24090 |
-+ .func = kdbus_test_conn_update, |
24091 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24092 |
-+ }, |
24093 |
-+ { |
24094 |
-+ .name = "writable-pool", |
24095 |
-+ .desc = "verifying pools are never writable", |
24096 |
-+ .func = kdbus_test_writable_pool, |
24097 |
-+ .flags = TEST_CREATE_BUS, |
24098 |
-+ }, |
24099 |
-+ { |
24100 |
-+ .name = "policy", |
24101 |
-+ .desc = "policy", |
24102 |
-+ .func = kdbus_test_policy, |
24103 |
-+ .flags = TEST_CREATE_BUS, |
24104 |
-+ }, |
24105 |
-+ { |
24106 |
-+ .name = "policy-priv", |
24107 |
-+ .desc = "unprivileged bus access", |
24108 |
-+ .func = kdbus_test_policy_priv, |
24109 |
-+ .flags = TEST_CREATE_BUS, |
24110 |
-+ }, |
24111 |
-+ { |
24112 |
-+ .name = "policy-ns", |
24113 |
-+ .desc = "policy in user namespaces", |
24114 |
-+ .func = kdbus_test_policy_ns, |
24115 |
-+ .flags = TEST_CREATE_BUS, |
24116 |
-+ }, |
24117 |
-+ { |
24118 |
-+ .name = "metadata-ns", |
24119 |
-+ .desc = "metadata in different namespaces", |
24120 |
-+ .func = kdbus_test_metadata_ns, |
24121 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24122 |
-+ }, |
24123 |
-+ { |
24124 |
-+ .name = "match-id-add", |
24125 |
-+ .desc = "adding of matches by id", |
24126 |
-+ .func = kdbus_test_match_id_add, |
24127 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24128 |
-+ }, |
24129 |
-+ { |
24130 |
-+ .name = "match-id-remove", |
24131 |
-+ .desc = "removing of matches by id", |
24132 |
-+ .func = kdbus_test_match_id_remove, |
24133 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24134 |
-+ }, |
24135 |
-+ { |
24136 |
-+ .name = "match-replace", |
24137 |
-+ .desc = "replace of matches with the same cookie", |
24138 |
-+ .func = kdbus_test_match_replace, |
24139 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24140 |
-+ }, |
24141 |
-+ { |
24142 |
-+ .name = "match-name-add", |
24143 |
-+ .desc = "adding of matches by name", |
24144 |
-+ .func = kdbus_test_match_name_add, |
24145 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24146 |
-+ }, |
24147 |
-+ { |
24148 |
-+ .name = "match-name-remove", |
24149 |
-+ .desc = "removing of matches by name", |
24150 |
-+ .func = kdbus_test_match_name_remove, |
24151 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24152 |
-+ }, |
24153 |
-+ { |
24154 |
-+ .name = "match-name-change", |
24155 |
-+ .desc = "matching for name changes", |
24156 |
-+ .func = kdbus_test_match_name_change, |
24157 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24158 |
-+ }, |
24159 |
-+ { |
24160 |
-+ .name = "match-bloom", |
24161 |
-+ .desc = "matching with bloom filters", |
24162 |
-+ .func = kdbus_test_match_bloom, |
24163 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24164 |
-+ }, |
24165 |
-+ { |
24166 |
-+ .name = "activator", |
24167 |
-+ .desc = "activator connections", |
24168 |
-+ .func = kdbus_test_activator, |
24169 |
-+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN, |
24170 |
-+ }, |
24171 |
-+ { |
24172 |
-+ .name = "benchmark", |
24173 |
-+ .desc = "benchmark", |
24174 |
-+ .func = kdbus_test_benchmark, |
24175 |
-+ .flags = TEST_CREATE_BUS, |
24176 |
-+ }, |
24177 |
-+ { |
24178 |
-+ .name = "benchmark-nomemfds", |
24179 |
-+ .desc = "benchmark without using memfds", |
24180 |
-+ .func = kdbus_test_benchmark_nomemfds, |
24181 |
-+ .flags = TEST_CREATE_BUS, |
24182 |
-+ }, |
24183 |
-+ { |
24184 |
-+ .name = "benchmark-uds", |
24185 |
-+ .desc = "benchmark comparison to UDS", |
24186 |
-+ .func = kdbus_test_benchmark_uds, |
24187 |
-+ .flags = TEST_CREATE_BUS, |
24188 |
-+ }, |
24189 |
-+}; |
24190 |
-+ |
24191 |
-+#define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0]))) |
24192 |
-+ |
24193 |
-+static int test_prepare_env(const struct kdbus_test *t, |
24194 |
-+ const struct kdbus_test_args *args, |
24195 |
-+ struct kdbus_test_env *env) |
24196 |
-+{ |
24197 |
-+ if (t->flags & TEST_CREATE_BUS) { |
24198 |
-+ char *s; |
24199 |
-+ char *n = NULL; |
24200 |
-+ int ret; |
24201 |
-+ |
24202 |
-+ asprintf(&s, "%s/control", args->root); |
24203 |
-+ |
24204 |
-+ env->control_fd = open(s, O_RDWR); |
24205 |
-+ free(s); |
24206 |
-+ ASSERT_RETURN(env->control_fd >= 0); |
24207 |
-+ |
24208 |
-+ if (!args->busname) { |
24209 |
-+ n = unique_name("test-bus"); |
24210 |
-+ ASSERT_RETURN(n); |
24211 |
-+ } |
24212 |
-+ |
24213 |
-+ ret = kdbus_create_bus(env->control_fd, |
24214 |
-+ args->busname ?: n, |
24215 |
-+ _KDBUS_ATTACH_ALL, &s); |
24216 |
-+ free(n); |
24217 |
-+ ASSERT_RETURN(ret == 0); |
24218 |
-+ |
24219 |
-+ asprintf(&env->buspath, "%s/%s/bus", args->root, s); |
24220 |
-+ free(s); |
24221 |
-+ } |
24222 |
-+ |
24223 |
-+ if (t->flags & TEST_CREATE_CONN) { |
24224 |
-+ env->conn = kdbus_hello(env->buspath, 0, NULL, 0); |
24225 |
-+ ASSERT_RETURN(env->conn); |
24226 |
-+ } |
24227 |
-+ |
24228 |
-+ env->root = args->root; |
24229 |
-+ env->module = args->module; |
24230 |
-+ |
24231 |
-+ return 0; |
24232 |
-+} |
24233 |
-+ |
24234 |
-+void test_unprepare_env(const struct kdbus_test *t, struct kdbus_test_env *env) |
24235 |
-+{ |
24236 |
-+ if (env->conn) { |
24237 |
-+ kdbus_conn_free(env->conn); |
24238 |
-+ env->conn = NULL; |
24239 |
-+ } |
24240 |
-+ |
24241 |
-+ if (env->control_fd >= 0) { |
24242 |
-+ close(env->control_fd); |
24243 |
-+ env->control_fd = -1; |
24244 |
-+ } |
24245 |
-+ |
24246 |
-+ if (env->buspath) { |
24247 |
-+ free(env->buspath); |
24248 |
-+ env->buspath = NULL; |
24249 |
-+ } |
24250 |
-+} |
24251 |
-+ |
24252 |
-+static int test_run(const struct kdbus_test *t, |
24253 |
-+ const struct kdbus_test_args *kdbus_args, |
24254 |
-+ int wait) |
24255 |
-+{ |
24256 |
-+ int ret; |
24257 |
-+ struct kdbus_test_env env = {}; |
24258 |
-+ |
24259 |
-+ ret = test_prepare_env(t, kdbus_args, &env); |
24260 |
-+ if (ret != TEST_OK) |
24261 |
-+ return ret; |
24262 |
-+ |
24263 |
-+ if (wait > 0) { |
24264 |
-+ printf("Sleeping %d seconds before running test ...\n", wait); |
24265 |
-+ sleep(wait); |
24266 |
-+ } |
24267 |
-+ |
24268 |
-+ ret = t->func(&env); |
24269 |
-+ test_unprepare_env(t, &env); |
24270 |
-+ return ret; |
24271 |
-+} |
24272 |
-+ |
24273 |
-+static int test_run_forked(const struct kdbus_test *t, |
24274 |
-+ const struct kdbus_test_args *kdbus_args, |
24275 |
-+ int wait) |
24276 |
-+{ |
24277 |
-+ int ret; |
24278 |
-+ pid_t pid; |
24279 |
-+ |
24280 |
-+ pid = fork(); |
24281 |
-+ if (pid < 0) { |
24282 |
-+ return TEST_ERR; |
24283 |
-+ } else if (pid == 0) { |
24284 |
-+ ret = test_run(t, kdbus_args, wait); |
24285 |
-+ _exit(ret); |
24286 |
-+ } |
24287 |
-+ |
24288 |
-+ pid = waitpid(pid, &ret, 0); |
24289 |
-+ if (pid <= 0) |
24290 |
-+ return TEST_ERR; |
24291 |
-+ else if (!WIFEXITED(ret)) |
24292 |
-+ return TEST_ERR; |
24293 |
-+ else |
24294 |
-+ return WEXITSTATUS(ret); |
24295 |
-+} |
24296 |
-+ |
24297 |
-+static void print_test_result(int ret) |
24298 |
-+{ |
24299 |
-+ switch (ret) { |
24300 |
-+ case TEST_OK: |
24301 |
-+ printf("OK"); |
24302 |
-+ break; |
24303 |
-+ case TEST_SKIP: |
24304 |
-+ printf("SKIPPED"); |
24305 |
-+ break; |
24306 |
-+ case TEST_ERR: |
24307 |
-+ printf("ERROR"); |
24308 |
-+ break; |
24309 |
-+ } |
24310 |
-+} |
24311 |
-+ |
24312 |
-+static int start_all_tests(struct kdbus_test_args *kdbus_args) |
24313 |
-+{ |
24314 |
-+ int ret; |
24315 |
-+ unsigned int fail_cnt = 0; |
24316 |
-+ unsigned int skip_cnt = 0; |
24317 |
-+ unsigned int ok_cnt = 0; |
24318 |
-+ unsigned int i; |
24319 |
-+ |
24320 |
-+ if (kdbus_args->tap_output) { |
24321 |
-+ printf("1..%d\n", N_TESTS); |
24322 |
-+ fflush(stdout); |
24323 |
-+ } |
24324 |
-+ |
24325 |
-+ kdbus_util_verbose = false; |
24326 |
-+ |
24327 |
-+ for (i = 0; i < N_TESTS; i++) { |
24328 |
-+ const struct kdbus_test *t = tests + i; |
24329 |
-+ |
24330 |
-+ if (!kdbus_args->tap_output) { |
24331 |
-+ unsigned int n; |
24332 |
-+ |
24333 |
-+ printf("Testing %s (%s) ", t->desc, t->name); |
24334 |
-+ for (n = 0; n < 60 - strlen(t->desc) - strlen(t->name); n++) |
24335 |
-+ printf("."); |
24336 |
-+ printf(" "); |
24337 |
-+ } |
24338 |
-+ |
24339 |
-+ ret = test_run_forked(t, kdbus_args, 0); |
24340 |
-+ switch (ret) { |
24341 |
-+ case TEST_OK: |
24342 |
-+ ok_cnt++; |
24343 |
-+ break; |
24344 |
-+ case TEST_SKIP: |
24345 |
-+ skip_cnt++; |
24346 |
-+ break; |
24347 |
-+ case TEST_ERR: |
24348 |
-+ fail_cnt++; |
24349 |
-+ break; |
24350 |
-+ } |
24351 |
-+ |
24352 |
-+ if (kdbus_args->tap_output) { |
24353 |
-+ printf("%sok %d - %s%s (%s)\n", |
24354 |
-+ (ret == TEST_ERR) ? "not " : "", i + 1, |
24355 |
-+ (ret == TEST_SKIP) ? "# SKIP " : "", |
24356 |
-+ t->desc, t->name); |
24357 |
-+ fflush(stdout); |
24358 |
-+ } else { |
24359 |
-+ print_test_result(ret); |
24360 |
-+ printf("\n"); |
24361 |
-+ } |
24362 |
-+ } |
24363 |
-+ |
24364 |
-+ if (kdbus_args->tap_output) |
24365 |
-+ printf("Failed %d/%d tests, %.2f%% okay\n", fail_cnt, N_TESTS, |
24366 |
-+ 100.0 - (fail_cnt * 100.0) / ((float) N_TESTS)); |
24367 |
-+ else |
24368 |
-+ printf("\nSUMMARY: %u tests passed, %u skipped, %u failed\n", |
24369 |
-+ ok_cnt, skip_cnt, fail_cnt); |
24370 |
-+ |
24371 |
-+ return fail_cnt > 0 ? TEST_ERR : TEST_OK; |
24372 |
-+} |
24373 |
-+ |
24374 |
-+static int start_one_test(struct kdbus_test_args *kdbus_args) |
24375 |
-+{ |
24376 |
-+ int i, ret; |
24377 |
-+ bool test_found = false; |
24378 |
-+ |
24379 |
-+ for (i = 0; i < N_TESTS; i++) { |
24380 |
-+ const struct kdbus_test *t = tests + i; |
24381 |
-+ |
24382 |
-+ if (strcmp(t->name, kdbus_args->test)) |
24383 |
-+ continue; |
24384 |
-+ |
24385 |
-+ do { |
24386 |
-+ test_found = true; |
24387 |
-+ if (kdbus_args->fork) |
24388 |
-+ ret = test_run_forked(t, kdbus_args, |
24389 |
-+ kdbus_args->wait); |
24390 |
-+ else |
24391 |
-+ ret = test_run(t, kdbus_args, |
24392 |
-+ kdbus_args->wait); |
24393 |
-+ |
24394 |
-+ printf("Testing %s: ", t->desc); |
24395 |
-+ print_test_result(ret); |
24396 |
-+ printf("\n"); |
24397 |
-+ |
24398 |
-+ if (ret != TEST_OK) |
24399 |
-+ break; |
24400 |
-+ } while (kdbus_args->loop); |
24401 |
-+ |
24402 |
-+ return ret; |
24403 |
-+ } |
24404 |
-+ |
24405 |
-+ if (!test_found) { |
24406 |
-+ printf("Unknown test-id '%s'\n", kdbus_args->test); |
24407 |
-+ return TEST_ERR; |
24408 |
-+ } |
24409 |
-+ |
24410 |
-+ return TEST_OK; |
24411 |
-+} |
24412 |
-+ |
24413 |
-+static void usage(const char *argv0) |
24414 |
-+{ |
24415 |
-+ unsigned int i, j; |
24416 |
-+ |
24417 |
-+ printf("Usage: %s [options]\n" |
24418 |
-+ "Options:\n" |
24419 |
-+ "\t-a, --tap Output test results in TAP format\n" |
24420 |
-+ "\t-m, --module <module> Kdbus module name\n" |
24421 |
-+ "\t-x, --loop Run in a loop\n" |
24422 |
-+ "\t-f, --fork Fork before running a test\n" |
24423 |
-+ "\t-h, --help Print this help\n" |
24424 |
-+ "\t-r, --root <root> Toplevel of the kdbus hierarchy\n" |
24425 |
-+ "\t-t, --test <test-id> Run one specific test only, in verbose mode\n" |
24426 |
-+ "\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n" |
24427 |
-+ "\t-w, --wait <secs> Wait <secs> before actually starting test\n" |
24428 |
-+ "\t --mntns New mount namespace\n" |
24429 |
-+ "\t --pidns New PID namespace\n" |
24430 |
-+ "\t --userns New user namespace\n" |
24431 |
-+ "\t --uidmap uid_map UID map for user namespace\n" |
24432 |
-+ "\t --gidmap gid_map GID map for user namespace\n" |
24433 |
-+ "\n", argv0); |
24434 |
-+ |
24435 |
-+ printf("By default, all test are run once, and a summary is printed.\n" |
24436 |
-+ "Available tests for --test:\n\n"); |
24437 |
-+ |
24438 |
-+ for (i = 0; i < N_TESTS; i++) { |
24439 |
-+ const struct kdbus_test *t = tests + i; |
24440 |
-+ |
24441 |
-+ printf("\t%s", t->name); |
24442 |
-+ |
24443 |
-+ for (j = 0; j < 24 - strlen(t->name); j++) |
24444 |
-+ printf(" "); |
24445 |
-+ |
24446 |
-+ printf("Test %s\n", t->desc); |
24447 |
-+ } |
24448 |
-+ |
24449 |
-+ printf("\n"); |
24450 |
-+ printf("Note that some tests may, if run specifically by --test, " |
24451 |
-+ "behave differently, and not terminate by themselves.\n"); |
24452 |
-+ |
24453 |
-+ exit(EXIT_FAILURE); |
24454 |
-+} |
24455 |
-+ |
24456 |
-+void print_kdbus_test_args(struct kdbus_test_args *args) |
24457 |
-+{ |
24458 |
-+ if (args->userns || args->pidns || args->mntns) |
24459 |
-+ printf("# Starting tests in new %s%s%s namespaces%s\n", |
24460 |
-+ args->mntns ? "MOUNT " : "", |
24461 |
-+ args->pidns ? "PID " : "", |
24462 |
-+ args->userns ? "USER " : "", |
24463 |
-+ args->mntns ? ", kdbusfs will be remounted" : ""); |
24464 |
-+ else |
24465 |
-+ printf("# Starting tests in the same namespaces\n"); |
24466 |
-+} |
24467 |
-+ |
24468 |
-+void print_metadata_support(void) |
24469 |
-+{ |
24470 |
-+ bool no_meta_audit, no_meta_cgroups, no_meta_seclabel; |
24471 |
-+ |
24472 |
-+ /* |
24473 |
-+ * KDBUS_ATTACH_CGROUP, KDBUS_ATTACH_AUDIT and |
24474 |
-+ * KDBUS_ATTACH_SECLABEL |
24475 |
-+ */ |
24476 |
-+ no_meta_audit = !config_auditsyscall_is_enabled(); |
24477 |
-+ no_meta_cgroups = !config_cgroups_is_enabled(); |
24478 |
-+ no_meta_seclabel = !config_security_is_enabled(); |
24479 |
-+ |
24480 |
-+ if (no_meta_audit | no_meta_cgroups | no_meta_seclabel) |
24481 |
-+ printf("# Starting tests without %s%s%s metadata support\n", |
24482 |
-+ no_meta_audit ? "AUDIT " : "", |
24483 |
-+ no_meta_cgroups ? "CGROUP " : "", |
24484 |
-+ no_meta_seclabel ? "SECLABEL " : ""); |
24485 |
-+ else |
24486 |
-+ printf("# Starting tests with full metadata support\n"); |
24487 |
-+} |
24488 |
-+ |
24489 |
-+int run_tests(struct kdbus_test_args *kdbus_args) |
24490 |
-+{ |
24491 |
-+ int ret; |
24492 |
-+ static char control[4096]; |
24493 |
-+ |
24494 |
-+ snprintf(control, sizeof(control), "%s/control", kdbus_args->root); |
24495 |
-+ |
24496 |
-+ if (access(control, W_OK) < 0) { |
24497 |
-+ printf("Unable to locate control node at '%s'.\n", |
24498 |
-+ control); |
24499 |
-+ return TEST_ERR; |
24500 |
-+ } |
24501 |
-+ |
24502 |
-+ if (kdbus_args->test) { |
24503 |
-+ ret = start_one_test(kdbus_args); |
24504 |
-+ } else { |
24505 |
-+ do { |
24506 |
-+ ret = start_all_tests(kdbus_args); |
24507 |
-+ if (ret != TEST_OK) |
24508 |
-+ break; |
24509 |
-+ } while (kdbus_args->loop); |
24510 |
-+ } |
24511 |
-+ |
24512 |
-+ return ret; |
24513 |
-+} |
24514 |
-+ |
24515 |
-+static void nop_handler(int sig) {} |
24516 |
-+ |
24517 |
-+static int test_prepare_mounts(struct kdbus_test_args *kdbus_args) |
24518 |
-+{ |
24519 |
-+ int ret; |
24520 |
-+ char kdbusfs[64] = {'\0'}; |
24521 |
-+ |
24522 |
-+ snprintf(kdbusfs, sizeof(kdbusfs), "%sfs", kdbus_args->module); |
24523 |
-+ |
24524 |
-+ /* make current mount slave */ |
24525 |
-+ ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); |
24526 |
-+ if (ret < 0) { |
24527 |
-+ ret = -errno; |
24528 |
-+ printf("error mount() root: %d (%m)\n", ret); |
24529 |
-+ return ret; |
24530 |
-+ } |
24531 |
-+ |
24532 |
-+ /* Remount procfs since we need it in our tests */ |
24533 |
-+ if (kdbus_args->pidns) { |
24534 |
-+ ret = mount("proc", "/proc", "proc", |
24535 |
-+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); |
24536 |
-+ if (ret < 0) { |
24537 |
-+ ret = -errno; |
24538 |
-+ printf("error mount() /proc : %d (%m)\n", ret); |
24539 |
-+ return ret; |
24540 |
-+ } |
24541 |
-+ } |
24542 |
-+ |
24543 |
-+ /* Remount kdbusfs */ |
24544 |
-+ ret = mount(kdbusfs, kdbus_args->root, kdbusfs, |
24545 |
-+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); |
24546 |
-+ if (ret < 0) { |
24547 |
-+ ret = -errno; |
24548 |
-+ printf("error mount() %s :%d (%m)\n", kdbusfs, ret); |
24549 |
-+ return ret; |
24550 |
-+ } |
24551 |
-+ |
24552 |
-+ return 0; |
24553 |
-+} |
24554 |
-+ |
24555 |
-+int run_tests_in_namespaces(struct kdbus_test_args *kdbus_args) |
24556 |
-+{ |
24557 |
-+ int ret; |
24558 |
-+ int efd = -1; |
24559 |
-+ int status; |
24560 |
-+ pid_t pid, rpid; |
24561 |
-+ struct sigaction oldsa; |
24562 |
-+ struct sigaction sa = { |
24563 |
-+ .sa_handler = nop_handler, |
24564 |
-+ .sa_flags = SA_NOCLDSTOP, |
24565 |
-+ }; |
24566 |
-+ |
24567 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
24568 |
-+ if (efd < 0) { |
24569 |
-+ ret = -errno; |
24570 |
-+ printf("eventfd() failed: %d (%m)\n", ret); |
24571 |
-+ return TEST_ERR; |
24572 |
-+ } |
24573 |
-+ |
24574 |
-+ ret = sigaction(SIGCHLD, &sa, &oldsa); |
24575 |
-+ if (ret < 0) { |
24576 |
-+ ret = -errno; |
24577 |
-+ printf("sigaction() failed: %d (%m)\n", ret); |
24578 |
-+ return TEST_ERR; |
24579 |
-+ } |
24580 |
-+ |
24581 |
-+ /* setup namespaces */ |
24582 |
-+ pid = syscall(__NR_clone, SIGCHLD| |
24583 |
-+ (kdbus_args->userns ? CLONE_NEWUSER : 0) | |
24584 |
-+ (kdbus_args->mntns ? CLONE_NEWNS : 0) | |
24585 |
-+ (kdbus_args->pidns ? CLONE_NEWPID : 0), NULL); |
24586 |
-+ if (pid < 0) { |
24587 |
-+ printf("clone() failed: %d (%m)\n", -errno); |
24588 |
-+ return TEST_ERR; |
24589 |
-+ } |
24590 |
-+ |
24591 |
-+ if (pid == 0) { |
24592 |
-+ eventfd_t event_status = 0; |
24593 |
-+ |
24594 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
24595 |
-+ if (ret < 0) { |
24596 |
-+ ret = -errno; |
24597 |
-+ printf("error prctl(): %d (%m)\n", ret); |
24598 |
-+ _exit(TEST_ERR); |
24599 |
-+ } |
24600 |
-+ |
24601 |
-+ /* reset sighandlers of childs */ |
24602 |
-+ ret = sigaction(SIGCHLD, &oldsa, NULL); |
24603 |
-+ if (ret < 0) { |
24604 |
-+ ret = -errno; |
24605 |
-+ printf("sigaction() failed: %d (%m)\n", ret); |
24606 |
-+ _exit(TEST_ERR); |
24607 |
-+ } |
24608 |
-+ |
24609 |
-+ ret = eventfd_read(efd, &event_status); |
24610 |
-+ if (ret < 0 || event_status != 1) { |
24611 |
-+ printf("error eventfd_read()\n"); |
24612 |
-+ _exit(TEST_ERR); |
24613 |
-+ } |
24614 |
-+ |
24615 |
-+ if (kdbus_args->mntns) { |
24616 |
-+ ret = test_prepare_mounts(kdbus_args); |
24617 |
-+ if (ret < 0) { |
24618 |
-+ printf("error preparing mounts\n"); |
24619 |
-+ _exit(TEST_ERR); |
24620 |
-+ } |
24621 |
-+ } |
24622 |
-+ |
24623 |
-+ ret = run_tests(kdbus_args); |
24624 |
-+ _exit(ret); |
24625 |
-+ } |
24626 |
-+ |
24627 |
-+ /* Setup userns mapping */ |
24628 |
-+ if (kdbus_args->userns) { |
24629 |
-+ ret = userns_map_uid_gid(pid, kdbus_args->uid_map, |
24630 |
-+ kdbus_args->gid_map); |
24631 |
-+ if (ret < 0) { |
24632 |
-+ printf("error mapping uid and gid in userns\n"); |
24633 |
-+ eventfd_write(efd, 2); |
24634 |
-+ return TEST_ERR; |
24635 |
-+ } |
24636 |
-+ } |
24637 |
-+ |
24638 |
-+ ret = eventfd_write(efd, 1); |
24639 |
-+ if (ret < 0) { |
24640 |
-+ ret = -errno; |
24641 |
-+ printf("error eventfd_write(): %d (%m)\n", ret); |
24642 |
-+ return TEST_ERR; |
24643 |
-+ } |
24644 |
-+ |
24645 |
-+ rpid = waitpid(pid, &status, 0); |
24646 |
-+ ASSERT_RETURN_VAL(rpid == pid, TEST_ERR); |
24647 |
-+ |
24648 |
-+ close(efd); |
24649 |
-+ |
24650 |
-+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) |
24651 |
-+ return TEST_ERR; |
24652 |
-+ |
24653 |
-+ return TEST_OK; |
24654 |
-+} |
24655 |
-+ |
24656 |
-+int start_tests(struct kdbus_test_args *kdbus_args) |
24657 |
-+{ |
24658 |
-+ int ret; |
24659 |
-+ bool namespaces; |
24660 |
-+ static char fspath[4096]; |
24661 |
-+ |
24662 |
-+ namespaces = (kdbus_args->mntns || kdbus_args->pidns || |
24663 |
-+ kdbus_args->userns); |
24664 |
-+ |
24665 |
-+ /* for pidns we need mntns set */ |
24666 |
-+ if (kdbus_args->pidns && !kdbus_args->mntns) { |
24667 |
-+ printf("Failed: please set both pid and mnt namesapces\n"); |
24668 |
-+ return TEST_ERR; |
24669 |
-+ } |
24670 |
-+ |
24671 |
-+ if (kdbus_args->userns) { |
24672 |
-+ if (!config_user_ns_is_enabled()) { |
24673 |
-+ printf("User namespace not supported\n"); |
24674 |
-+ return TEST_ERR; |
24675 |
-+ } |
24676 |
-+ |
24677 |
-+ if (!kdbus_args->uid_map || !kdbus_args->gid_map) { |
24678 |
-+ printf("Failed: please specify uid or gid mapping\n"); |
24679 |
-+ return TEST_ERR; |
24680 |
-+ } |
24681 |
-+ } |
24682 |
-+ |
24683 |
-+ print_kdbus_test_args(kdbus_args); |
24684 |
-+ print_metadata_support(); |
24685 |
-+ |
24686 |
-+ /* setup kdbus paths */ |
24687 |
-+ if (!kdbus_args->module) |
24688 |
-+ kdbus_args->module = "kdbus"; |
24689 |
-+ |
24690 |
-+ if (!kdbus_args->root) { |
24691 |
-+ snprintf(fspath, sizeof(fspath), "/sys/fs/%s", |
24692 |
-+ kdbus_args->module); |
24693 |
-+ kdbus_args->root = fspath; |
24694 |
-+ } |
24695 |
-+ |
24696 |
-+ /* Start tests */ |
24697 |
-+ if (namespaces) |
24698 |
-+ ret = run_tests_in_namespaces(kdbus_args); |
24699 |
-+ else |
24700 |
-+ ret = run_tests(kdbus_args); |
24701 |
-+ |
24702 |
-+ return ret; |
24703 |
-+} |
24704 |
-+ |
24705 |
-+int main(int argc, char *argv[]) |
24706 |
-+{ |
24707 |
-+ int t, ret = 0; |
24708 |
-+ struct kdbus_test_args *kdbus_args; |
24709 |
-+ enum { |
24710 |
-+ ARG_MNTNS = 0x100, |
24711 |
-+ ARG_PIDNS, |
24712 |
-+ ARG_USERNS, |
24713 |
-+ ARG_UIDMAP, |
24714 |
-+ ARG_GIDMAP, |
24715 |
-+ }; |
24716 |
-+ |
24717 |
-+ kdbus_args = malloc(sizeof(*kdbus_args)); |
24718 |
-+ if (!kdbus_args) { |
24719 |
-+ printf("unable to malloc() kdbus_args\n"); |
24720 |
-+ return EXIT_FAILURE; |
24721 |
-+ } |
24722 |
-+ |
24723 |
-+ memset(kdbus_args, 0, sizeof(*kdbus_args)); |
24724 |
-+ |
24725 |
-+ static const struct option options[] = { |
24726 |
-+ { "loop", no_argument, NULL, 'x' }, |
24727 |
-+ { "help", no_argument, NULL, 'h' }, |
24728 |
-+ { "root", required_argument, NULL, 'r' }, |
24729 |
-+ { "test", required_argument, NULL, 't' }, |
24730 |
-+ { "bus", required_argument, NULL, 'b' }, |
24731 |
-+ { "wait", required_argument, NULL, 'w' }, |
24732 |
-+ { "fork", no_argument, NULL, 'f' }, |
24733 |
-+ { "module", required_argument, NULL, 'm' }, |
24734 |
-+ { "tap", no_argument, NULL, 'a' }, |
24735 |
-+ { "mntns", no_argument, NULL, ARG_MNTNS }, |
24736 |
-+ { "pidns", no_argument, NULL, ARG_PIDNS }, |
24737 |
-+ { "userns", no_argument, NULL, ARG_USERNS }, |
24738 |
-+ { "uidmap", required_argument, NULL, ARG_UIDMAP }, |
24739 |
-+ { "gidmap", required_argument, NULL, ARG_GIDMAP }, |
24740 |
-+ {} |
24741 |
-+ }; |
24742 |
-+ |
24743 |
-+ srand(time(NULL)); |
24744 |
-+ |
24745 |
-+ while ((t = getopt_long(argc, argv, "hxfm:r:t:b:w:a", options, NULL)) >= 0) { |
24746 |
-+ switch (t) { |
24747 |
-+ case 'x': |
24748 |
-+ kdbus_args->loop = 1; |
24749 |
-+ break; |
24750 |
-+ |
24751 |
-+ case 'm': |
24752 |
-+ kdbus_args->module = optarg; |
24753 |
-+ break; |
24754 |
-+ |
24755 |
-+ case 'r': |
24756 |
-+ kdbus_args->root = optarg; |
24757 |
-+ break; |
24758 |
-+ |
24759 |
-+ case 't': |
24760 |
-+ kdbus_args->test = optarg; |
24761 |
-+ break; |
24762 |
-+ |
24763 |
-+ case 'b': |
24764 |
-+ kdbus_args->busname = optarg; |
24765 |
-+ break; |
24766 |
-+ |
24767 |
-+ case 'w': |
24768 |
-+ kdbus_args->wait = strtol(optarg, NULL, 10); |
24769 |
-+ break; |
24770 |
-+ |
24771 |
-+ case 'f': |
24772 |
-+ kdbus_args->fork = 1; |
24773 |
-+ break; |
24774 |
-+ |
24775 |
-+ case 'a': |
24776 |
-+ kdbus_args->tap_output = 1; |
24777 |
-+ break; |
24778 |
-+ |
24779 |
-+ case ARG_MNTNS: |
24780 |
-+ kdbus_args->mntns = true; |
24781 |
-+ break; |
24782 |
-+ |
24783 |
-+ case ARG_PIDNS: |
24784 |
-+ kdbus_args->pidns = true; |
24785 |
-+ break; |
24786 |
-+ |
24787 |
-+ case ARG_USERNS: |
24788 |
-+ kdbus_args->userns = true; |
24789 |
-+ break; |
24790 |
-+ |
24791 |
-+ case ARG_UIDMAP: |
24792 |
-+ kdbus_args->uid_map = optarg; |
24793 |
-+ break; |
24794 |
-+ |
24795 |
-+ case ARG_GIDMAP: |
24796 |
-+ kdbus_args->gid_map = optarg; |
24797 |
-+ break; |
24798 |
-+ |
24799 |
-+ default: |
24800 |
-+ case 'h': |
24801 |
-+ usage(argv[0]); |
24802 |
-+ } |
24803 |
-+ } |
24804 |
-+ |
24805 |
-+ ret = start_tests(kdbus_args); |
24806 |
-+ if (ret == TEST_ERR) |
24807 |
-+ return EXIT_FAILURE; |
24808 |
-+ |
24809 |
-+ free(kdbus_args); |
24810 |
-+ |
24811 |
-+ return 0; |
24812 |
-+} |
24813 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-test.h b/tools/testing/selftests/kdbus/kdbus-test.h |
24814 |
-new file mode 100644 |
24815 |
-index 0000000..ee937f9 |
24816 |
---- /dev/null |
24817 |
-+++ b/tools/testing/selftests/kdbus/kdbus-test.h |
24818 |
-@@ -0,0 +1,84 @@ |
24819 |
-+#ifndef _TEST_KDBUS_H_ |
24820 |
-+#define _TEST_KDBUS_H_ |
24821 |
-+ |
24822 |
-+struct kdbus_test_env { |
24823 |
-+ char *buspath; |
24824 |
-+ const char *root; |
24825 |
-+ const char *module; |
24826 |
-+ int control_fd; |
24827 |
-+ struct kdbus_conn *conn; |
24828 |
-+}; |
24829 |
-+ |
24830 |
-+enum { |
24831 |
-+ TEST_OK, |
24832 |
-+ TEST_SKIP, |
24833 |
-+ TEST_ERR, |
24834 |
-+}; |
24835 |
-+ |
24836 |
-+#define ASSERT_RETURN_VAL(cond, val) \ |
24837 |
-+ if (!(cond)) { \ |
24838 |
-+ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24839 |
-+ #cond, __func__, __FILE__, __LINE__); \ |
24840 |
-+ return val; \ |
24841 |
-+ } |
24842 |
-+ |
24843 |
-+#define ASSERT_EXIT_VAL(cond, val) \ |
24844 |
-+ if (!(cond)) { \ |
24845 |
-+ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24846 |
-+ #cond, __func__, __FILE__, __LINE__); \ |
24847 |
-+ _exit(val); \ |
24848 |
-+ } |
24849 |
-+ |
24850 |
-+#define ASSERT_BREAK(cond) \ |
24851 |
-+ if (!(cond)) { \ |
24852 |
-+ fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ |
24853 |
-+ #cond, __func__, __FILE__, __LINE__); \ |
24854 |
-+ break; \ |
24855 |
-+ } |
24856 |
-+ |
24857 |
-+#define ASSERT_RETURN(cond) \ |
24858 |
-+ ASSERT_RETURN_VAL(cond, TEST_ERR) |
24859 |
-+ |
24860 |
-+#define ASSERT_EXIT(cond) \ |
24861 |
-+ ASSERT_EXIT_VAL(cond, EXIT_FAILURE) |
24862 |
-+ |
24863 |
-+int kdbus_test_activator(struct kdbus_test_env *env); |
24864 |
-+int kdbus_test_benchmark(struct kdbus_test_env *env); |
24865 |
-+int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env); |
24866 |
-+int kdbus_test_benchmark_uds(struct kdbus_test_env *env); |
24867 |
-+int kdbus_test_bus_make(struct kdbus_test_env *env); |
24868 |
-+int kdbus_test_byebye(struct kdbus_test_env *env); |
24869 |
-+int kdbus_test_chat(struct kdbus_test_env *env); |
24870 |
-+int kdbus_test_conn_info(struct kdbus_test_env *env); |
24871 |
-+int kdbus_test_conn_update(struct kdbus_test_env *env); |
24872 |
-+int kdbus_test_daemon(struct kdbus_test_env *env); |
24873 |
-+int kdbus_test_custom_endpoint(struct kdbus_test_env *env); |
24874 |
-+int kdbus_test_fd_passing(struct kdbus_test_env *env); |
24875 |
-+int kdbus_test_free(struct kdbus_test_env *env); |
24876 |
-+int kdbus_test_hello(struct kdbus_test_env *env); |
24877 |
-+int kdbus_test_match_bloom(struct kdbus_test_env *env); |
24878 |
-+int kdbus_test_match_id_add(struct kdbus_test_env *env); |
24879 |
-+int kdbus_test_match_id_remove(struct kdbus_test_env *env); |
24880 |
-+int kdbus_test_match_replace(struct kdbus_test_env *env); |
24881 |
-+int kdbus_test_match_name_add(struct kdbus_test_env *env); |
24882 |
-+int kdbus_test_match_name_change(struct kdbus_test_env *env); |
24883 |
-+int kdbus_test_match_name_remove(struct kdbus_test_env *env); |
24884 |
-+int kdbus_test_message_basic(struct kdbus_test_env *env); |
24885 |
-+int kdbus_test_message_prio(struct kdbus_test_env *env); |
24886 |
-+int kdbus_test_message_quota(struct kdbus_test_env *env); |
24887 |
-+int kdbus_test_memory_access(struct kdbus_test_env *env); |
24888 |
-+int kdbus_test_metadata_ns(struct kdbus_test_env *env); |
24889 |
-+int kdbus_test_monitor(struct kdbus_test_env *env); |
24890 |
-+int kdbus_test_name_basic(struct kdbus_test_env *env); |
24891 |
-+int kdbus_test_name_conflict(struct kdbus_test_env *env); |
24892 |
-+int kdbus_test_name_queue(struct kdbus_test_env *env); |
24893 |
-+int kdbus_test_name_takeover(struct kdbus_test_env *env); |
24894 |
-+int kdbus_test_policy(struct kdbus_test_env *env); |
24895 |
-+int kdbus_test_policy_ns(struct kdbus_test_env *env); |
24896 |
-+int kdbus_test_policy_priv(struct kdbus_test_env *env); |
24897 |
-+int kdbus_test_sync_byebye(struct kdbus_test_env *env); |
24898 |
-+int kdbus_test_sync_reply(struct kdbus_test_env *env); |
24899 |
-+int kdbus_test_timeout(struct kdbus_test_env *env); |
24900 |
-+int kdbus_test_writable_pool(struct kdbus_test_env *env); |
24901 |
-+ |
24902 |
-+#endif /* _TEST_KDBUS_H_ */ |
24903 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c |
24904 |
-new file mode 100644 |
24905 |
-index 0000000..82fa89b |
24906 |
---- /dev/null |
24907 |
-+++ b/tools/testing/selftests/kdbus/kdbus-util.c |
24908 |
-@@ -0,0 +1,1612 @@ |
24909 |
-+/* |
24910 |
-+ * Copyright (C) 2013-2015 Daniel Mack |
24911 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
24912 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
24913 |
-+ * |
24914 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
24915 |
-+ * the terms of the GNU Lesser General Public License as published by the |
24916 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
24917 |
-+ * your option) any later version. |
24918 |
-+ */ |
24919 |
-+ |
24920 |
-+#include <stdio.h> |
24921 |
-+#include <stdarg.h> |
24922 |
-+#include <string.h> |
24923 |
-+#include <time.h> |
24924 |
-+#include <inttypes.h> |
24925 |
-+#include <fcntl.h> |
24926 |
-+#include <stdlib.h> |
24927 |
-+#include <stddef.h> |
24928 |
-+#include <unistd.h> |
24929 |
-+#include <stdint.h> |
24930 |
-+#include <stdbool.h> |
24931 |
-+#include <errno.h> |
24932 |
-+#include <assert.h> |
24933 |
-+#include <poll.h> |
24934 |
-+#include <grp.h> |
24935 |
-+#include <sys/capability.h> |
24936 |
-+#include <sys/mman.h> |
24937 |
-+#include <sys/stat.h> |
24938 |
-+#include <sys/time.h> |
24939 |
-+#include <linux/unistd.h> |
24940 |
-+#include <linux/memfd.h> |
24941 |
-+ |
24942 |
-+#ifndef __NR_memfd_create |
24943 |
-+ #ifdef __x86_64__ |
24944 |
-+ #define __NR_memfd_create 319 |
24945 |
-+ #elif defined __arm__ |
24946 |
-+ #define __NR_memfd_create 385 |
24947 |
-+ #else |
24948 |
-+ #define __NR_memfd_create 356 |
24949 |
-+ #endif |
24950 |
-+#endif |
24951 |
-+ |
24952 |
-+#include "kdbus-api.h" |
24953 |
-+#include "kdbus-util.h" |
24954 |
-+#include "kdbus-enum.h" |
24955 |
-+ |
24956 |
-+#ifndef F_ADD_SEALS |
24957 |
-+#define F_LINUX_SPECIFIC_BASE 1024 |
24958 |
-+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) |
24959 |
-+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) |
24960 |
-+ |
24961 |
-+#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ |
24962 |
-+#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ |
24963 |
-+#define F_SEAL_GROW 0x0004 /* prevent file from growing */ |
24964 |
-+#define F_SEAL_WRITE 0x0008 /* prevent writes */ |
24965 |
-+#endif |
24966 |
-+ |
24967 |
-+int kdbus_util_verbose = true; |
24968 |
-+ |
24969 |
-+int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask) |
24970 |
-+{ |
24971 |
-+ int ret; |
24972 |
-+ FILE *file; |
24973 |
-+ unsigned long long value; |
24974 |
-+ |
24975 |
-+ file = fopen(path, "r"); |
24976 |
-+ if (!file) { |
24977 |
-+ ret = -errno; |
24978 |
-+ kdbus_printf("--- error fopen(): %d (%m)\n", ret); |
24979 |
-+ return ret; |
24980 |
-+ } |
24981 |
-+ |
24982 |
-+ ret = fscanf(file, "%llu", &value); |
24983 |
-+ if (ret != 1) { |
24984 |
-+ if (ferror(file)) |
24985 |
-+ ret = -errno; |
24986 |
-+ else |
24987 |
-+ ret = -EIO; |
24988 |
-+ |
24989 |
-+ kdbus_printf("--- error fscanf(): %d\n", ret); |
24990 |
-+ fclose(file); |
24991 |
-+ return ret; |
24992 |
-+ } |
24993 |
-+ |
24994 |
-+ *mask = (uint64_t)value; |
24995 |
-+ |
24996 |
-+ fclose(file); |
24997 |
-+ |
24998 |
-+ return 0; |
24999 |
-+} |
25000 |
-+ |
25001 |
-+int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask) |
25002 |
-+{ |
25003 |
-+ int ret; |
25004 |
-+ FILE *file; |
25005 |
-+ |
25006 |
-+ file = fopen(path, "w"); |
25007 |
-+ if (!file) { |
25008 |
-+ ret = -errno; |
25009 |
-+ kdbus_printf("--- error open(): %d (%m)\n", ret); |
25010 |
-+ return ret; |
25011 |
-+ } |
25012 |
-+ |
25013 |
-+ ret = fprintf(file, "%llu", (unsigned long long)mask); |
25014 |
-+ if (ret <= 0) { |
25015 |
-+ ret = -EIO; |
25016 |
-+ kdbus_printf("--- error fprintf(): %d\n", ret); |
25017 |
-+ } |
25018 |
-+ |
25019 |
-+ fclose(file); |
25020 |
-+ |
25021 |
-+ return ret > 0 ? 0 : ret; |
25022 |
-+} |
25023 |
-+ |
25024 |
-+int kdbus_create_bus(int control_fd, const char *name, |
25025 |
-+ uint64_t owner_meta, char **path) |
25026 |
-+{ |
25027 |
-+ struct { |
25028 |
-+ struct kdbus_cmd cmd; |
25029 |
-+ |
25030 |
-+ /* bloom size item */ |
25031 |
-+ struct { |
25032 |
-+ uint64_t size; |
25033 |
-+ uint64_t type; |
25034 |
-+ struct kdbus_bloom_parameter bloom; |
25035 |
-+ } bp; |
25036 |
-+ |
25037 |
-+ /* owner metadata items */ |
25038 |
-+ struct { |
25039 |
-+ uint64_t size; |
25040 |
-+ uint64_t type; |
25041 |
-+ uint64_t flags; |
25042 |
-+ } attach; |
25043 |
-+ |
25044 |
-+ /* name item */ |
25045 |
-+ struct { |
25046 |
-+ uint64_t size; |
25047 |
-+ uint64_t type; |
25048 |
-+ char str[64]; |
25049 |
-+ } name; |
25050 |
-+ } bus_make; |
25051 |
-+ int ret; |
25052 |
-+ |
25053 |
-+ memset(&bus_make, 0, sizeof(bus_make)); |
25054 |
-+ bus_make.bp.size = sizeof(bus_make.bp); |
25055 |
-+ bus_make.bp.type = KDBUS_ITEM_BLOOM_PARAMETER; |
25056 |
-+ bus_make.bp.bloom.size = 64; |
25057 |
-+ bus_make.bp.bloom.n_hash = 1; |
25058 |
-+ |
25059 |
-+ snprintf(bus_make.name.str, sizeof(bus_make.name.str), |
25060 |
-+ "%u-%s", getuid(), name); |
25061 |
-+ |
25062 |
-+ bus_make.attach.type = KDBUS_ITEM_ATTACH_FLAGS_SEND; |
25063 |
-+ bus_make.attach.size = sizeof(bus_make.attach); |
25064 |
-+ bus_make.attach.flags = owner_meta; |
25065 |
-+ |
25066 |
-+ bus_make.name.type = KDBUS_ITEM_MAKE_NAME; |
25067 |
-+ bus_make.name.size = KDBUS_ITEM_HEADER_SIZE + |
25068 |
-+ strlen(bus_make.name.str) + 1; |
25069 |
-+ |
25070 |
-+ bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD; |
25071 |
-+ bus_make.cmd.size = sizeof(bus_make.cmd) + |
25072 |
-+ bus_make.bp.size + |
25073 |
-+ bus_make.attach.size + |
25074 |
-+ bus_make.name.size; |
25075 |
-+ |
25076 |
-+ kdbus_printf("Creating bus with name >%s< on control fd %d ...\n", |
25077 |
-+ name, control_fd); |
25078 |
-+ |
25079 |
-+ ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd); |
25080 |
-+ if (ret < 0) { |
25081 |
-+ kdbus_printf("--- error when making bus: %d (%m)\n", ret); |
25082 |
-+ return ret; |
25083 |
-+ } |
25084 |
-+ |
25085 |
-+ if (ret == 0 && path) |
25086 |
-+ *path = strdup(bus_make.name.str); |
25087 |
-+ |
25088 |
-+ return ret; |
25089 |
-+} |
25090 |
-+ |
25091 |
-+struct kdbus_conn * |
25092 |
-+kdbus_hello(const char *path, uint64_t flags, |
25093 |
-+ const struct kdbus_item *item, size_t item_size) |
25094 |
-+{ |
25095 |
-+ struct kdbus_cmd_free cmd_free = {}; |
25096 |
-+ int fd, ret; |
25097 |
-+ struct { |
25098 |
-+ struct kdbus_cmd_hello hello; |
25099 |
-+ |
25100 |
-+ struct { |
25101 |
-+ uint64_t size; |
25102 |
-+ uint64_t type; |
25103 |
-+ char str[16]; |
25104 |
-+ } conn_name; |
25105 |
-+ |
25106 |
-+ uint8_t extra_items[item_size]; |
25107 |
-+ } h; |
25108 |
-+ struct kdbus_conn *conn; |
25109 |
-+ |
25110 |
-+ memset(&h, 0, sizeof(h)); |
25111 |
-+ |
25112 |
-+ if (item_size > 0) |
25113 |
-+ memcpy(h.extra_items, item, item_size); |
25114 |
-+ |
25115 |
-+ kdbus_printf("-- opening bus connection %s\n", path); |
25116 |
-+ fd = open(path, O_RDWR|O_CLOEXEC); |
25117 |
-+ if (fd < 0) { |
25118 |
-+ kdbus_printf("--- error %d (%m)\n", fd); |
25119 |
-+ return NULL; |
25120 |
-+ } |
25121 |
-+ |
25122 |
-+ h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD; |
25123 |
-+ h.hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
25124 |
-+ h.hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
25125 |
-+ h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION; |
25126 |
-+ strcpy(h.conn_name.str, "this-is-my-name"); |
25127 |
-+ h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1; |
25128 |
-+ |
25129 |
-+ h.hello.size = sizeof(h); |
25130 |
-+ h.hello.pool_size = POOL_SIZE; |
25131 |
-+ |
25132 |
-+ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello); |
25133 |
-+ if (ret < 0) { |
25134 |
-+ kdbus_printf("--- error when saying hello: %d (%m)\n", ret); |
25135 |
-+ return NULL; |
25136 |
-+ } |
25137 |
-+ 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", |
25138 |
-+ path, (unsigned long long)h.hello.id, |
25139 |
-+ h.hello.id128[0], h.hello.id128[1], h.hello.id128[2], |
25140 |
-+ h.hello.id128[3], h.hello.id128[4], h.hello.id128[5], |
25141 |
-+ h.hello.id128[6], h.hello.id128[7], h.hello.id128[8], |
25142 |
-+ h.hello.id128[9], h.hello.id128[10], h.hello.id128[11], |
25143 |
-+ h.hello.id128[12], h.hello.id128[13], h.hello.id128[14], |
25144 |
-+ h.hello.id128[15]); |
25145 |
-+ |
25146 |
-+ cmd_free.size = sizeof(cmd_free); |
25147 |
-+ cmd_free.offset = h.hello.offset; |
25148 |
-+ kdbus_cmd_free(fd, &cmd_free); |
25149 |
-+ |
25150 |
-+ conn = malloc(sizeof(*conn)); |
25151 |
-+ if (!conn) { |
25152 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25153 |
-+ return NULL; |
25154 |
-+ } |
25155 |
-+ |
25156 |
-+ conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
25157 |
-+ if (conn->buf == MAP_FAILED) { |
25158 |
-+ free(conn); |
25159 |
-+ close(fd); |
25160 |
-+ kdbus_printf("--- error mmap (%m)\n"); |
25161 |
-+ return NULL; |
25162 |
-+ } |
25163 |
-+ |
25164 |
-+ conn->fd = fd; |
25165 |
-+ conn->id = h.hello.id; |
25166 |
-+ return conn; |
25167 |
-+} |
25168 |
-+ |
25169 |
-+struct kdbus_conn * |
25170 |
-+kdbus_hello_registrar(const char *path, const char *name, |
25171 |
-+ const struct kdbus_policy_access *access, |
25172 |
-+ size_t num_access, uint64_t flags) |
25173 |
-+{ |
25174 |
-+ struct kdbus_item *item, *items; |
25175 |
-+ size_t i, size; |
25176 |
-+ |
25177 |
-+ size = KDBUS_ITEM_SIZE(strlen(name) + 1) + |
25178 |
-+ num_access * KDBUS_ITEM_SIZE(sizeof(*access)); |
25179 |
-+ |
25180 |
-+ items = alloca(size); |
25181 |
-+ |
25182 |
-+ item = items; |
25183 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25184 |
-+ item->type = KDBUS_ITEM_NAME; |
25185 |
-+ strcpy(item->str, name); |
25186 |
-+ item = KDBUS_ITEM_NEXT(item); |
25187 |
-+ |
25188 |
-+ for (i = 0; i < num_access; i++) { |
25189 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
25190 |
-+ sizeof(struct kdbus_policy_access); |
25191 |
-+ item->type = KDBUS_ITEM_POLICY_ACCESS; |
25192 |
-+ |
25193 |
-+ item->policy_access.type = access[i].type; |
25194 |
-+ item->policy_access.access = access[i].access; |
25195 |
-+ item->policy_access.id = access[i].id; |
25196 |
-+ |
25197 |
-+ item = KDBUS_ITEM_NEXT(item); |
25198 |
-+ } |
25199 |
-+ |
25200 |
-+ return kdbus_hello(path, flags, items, size); |
25201 |
-+} |
25202 |
-+ |
25203 |
-+struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, |
25204 |
-+ const struct kdbus_policy_access *access, |
25205 |
-+ size_t num_access) |
25206 |
-+{ |
25207 |
-+ return kdbus_hello_registrar(path, name, access, num_access, |
25208 |
-+ KDBUS_HELLO_ACTIVATOR); |
25209 |
-+} |
25210 |
-+ |
25211 |
-+bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type) |
25212 |
-+{ |
25213 |
-+ const struct kdbus_item *item; |
25214 |
-+ |
25215 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) |
25216 |
-+ if (item->type == type) |
25217 |
-+ return true; |
25218 |
-+ |
25219 |
-+ return false; |
25220 |
-+} |
25221 |
-+ |
25222 |
-+int kdbus_bus_creator_info(struct kdbus_conn *conn, |
25223 |
-+ uint64_t flags, |
25224 |
-+ uint64_t *offset) |
25225 |
-+{ |
25226 |
-+ struct kdbus_cmd_info *cmd; |
25227 |
-+ size_t size = sizeof(*cmd); |
25228 |
-+ int ret; |
25229 |
-+ |
25230 |
-+ cmd = alloca(size); |
25231 |
-+ memset(cmd, 0, size); |
25232 |
-+ cmd->size = size; |
25233 |
-+ cmd->attach_flags = flags; |
25234 |
-+ |
25235 |
-+ ret = kdbus_cmd_bus_creator_info(conn->fd, cmd); |
25236 |
-+ if (ret < 0) { |
25237 |
-+ kdbus_printf("--- error when requesting info: %d (%m)\n", ret); |
25238 |
-+ return ret; |
25239 |
-+ } |
25240 |
-+ |
25241 |
-+ if (offset) |
25242 |
-+ *offset = cmd->offset; |
25243 |
-+ else |
25244 |
-+ kdbus_free(conn, cmd->offset); |
25245 |
-+ |
25246 |
-+ return 0; |
25247 |
-+} |
25248 |
-+ |
25249 |
-+int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, |
25250 |
-+ const char *name, uint64_t flags, |
25251 |
-+ uint64_t *offset) |
25252 |
-+{ |
25253 |
-+ struct kdbus_cmd_info *cmd; |
25254 |
-+ size_t size = sizeof(*cmd); |
25255 |
-+ struct kdbus_info *info; |
25256 |
-+ int ret; |
25257 |
-+ |
25258 |
-+ if (name) |
25259 |
-+ size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25260 |
-+ |
25261 |
-+ cmd = alloca(size); |
25262 |
-+ memset(cmd, 0, size); |
25263 |
-+ cmd->size = size; |
25264 |
-+ cmd->attach_flags = flags; |
25265 |
-+ |
25266 |
-+ if (name) { |
25267 |
-+ cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25268 |
-+ cmd->items[0].type = KDBUS_ITEM_NAME; |
25269 |
-+ strcpy(cmd->items[0].str, name); |
25270 |
-+ } else { |
25271 |
-+ cmd->id = id; |
25272 |
-+ } |
25273 |
-+ |
25274 |
-+ ret = kdbus_cmd_conn_info(conn->fd, cmd); |
25275 |
-+ if (ret < 0) { |
25276 |
-+ kdbus_printf("--- error when requesting info: %d (%m)\n", ret); |
25277 |
-+ return ret; |
25278 |
-+ } |
25279 |
-+ |
25280 |
-+ info = (struct kdbus_info *) (conn->buf + cmd->offset); |
25281 |
-+ if (info->size != cmd->info_size) { |
25282 |
-+ kdbus_printf("%s(): size mismatch: %d != %d\n", __func__, |
25283 |
-+ (int) info->size, (int) cmd->info_size); |
25284 |
-+ return -EIO; |
25285 |
-+ } |
25286 |
-+ |
25287 |
-+ if (offset) |
25288 |
-+ *offset = cmd->offset; |
25289 |
-+ else |
25290 |
-+ kdbus_free(conn, cmd->offset); |
25291 |
-+ |
25292 |
-+ return 0; |
25293 |
-+} |
25294 |
-+ |
25295 |
-+void kdbus_conn_free(struct kdbus_conn *conn) |
25296 |
-+{ |
25297 |
-+ if (!conn) |
25298 |
-+ return; |
25299 |
-+ |
25300 |
-+ if (conn->buf) |
25301 |
-+ munmap(conn->buf, POOL_SIZE); |
25302 |
-+ |
25303 |
-+ if (conn->fd >= 0) |
25304 |
-+ close(conn->fd); |
25305 |
-+ |
25306 |
-+ free(conn); |
25307 |
-+} |
25308 |
-+ |
25309 |
-+int sys_memfd_create(const char *name, __u64 size) |
25310 |
-+{ |
25311 |
-+ int ret, fd; |
25312 |
-+ |
25313 |
-+ fd = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING); |
25314 |
-+ if (fd < 0) |
25315 |
-+ return fd; |
25316 |
-+ |
25317 |
-+ ret = ftruncate(fd, size); |
25318 |
-+ if (ret < 0) { |
25319 |
-+ close(fd); |
25320 |
-+ return ret; |
25321 |
-+ } |
25322 |
-+ |
25323 |
-+ return fd; |
25324 |
-+} |
25325 |
-+ |
25326 |
-+int sys_memfd_seal_set(int fd) |
25327 |
-+{ |
25328 |
-+ return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | |
25329 |
-+ F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); |
25330 |
-+} |
25331 |
-+ |
25332 |
-+off_t sys_memfd_get_size(int fd, off_t *size) |
25333 |
-+{ |
25334 |
-+ struct stat stat; |
25335 |
-+ int ret; |
25336 |
-+ |
25337 |
-+ ret = fstat(fd, &stat); |
25338 |
-+ if (ret < 0) { |
25339 |
-+ kdbus_printf("stat() failed: %m\n"); |
25340 |
-+ return ret; |
25341 |
-+ } |
25342 |
-+ |
25343 |
-+ *size = stat.st_size; |
25344 |
-+ return 0; |
25345 |
-+} |
25346 |
-+ |
25347 |
-+static int __kdbus_msg_send(const struct kdbus_conn *conn, |
25348 |
-+ const char *name, |
25349 |
-+ uint64_t cookie, |
25350 |
-+ uint64_t flags, |
25351 |
-+ uint64_t timeout, |
25352 |
-+ int64_t priority, |
25353 |
-+ uint64_t dst_id, |
25354 |
-+ uint64_t cmd_flags, |
25355 |
-+ int cancel_fd) |
25356 |
-+{ |
25357 |
-+ struct kdbus_cmd_send *cmd = NULL; |
25358 |
-+ struct kdbus_msg *msg = NULL; |
25359 |
-+ const char ref1[1024 * 128 + 3] = "0123456789_0"; |
25360 |
-+ const char ref2[] = "0123456789_1"; |
25361 |
-+ struct kdbus_item *item; |
25362 |
-+ struct timespec now; |
25363 |
-+ uint64_t size; |
25364 |
-+ int memfd = -1; |
25365 |
-+ int ret; |
25366 |
-+ |
25367 |
-+ size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25368 |
-+ |
25369 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
25370 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
25371 |
-+ else { |
25372 |
-+ memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024); |
25373 |
-+ if (memfd < 0) { |
25374 |
-+ kdbus_printf("failed to create memfd: %m\n"); |
25375 |
-+ return memfd; |
25376 |
-+ } |
25377 |
-+ |
25378 |
-+ if (write(memfd, "kdbus memfd 1234567", 19) != 19) { |
25379 |
-+ ret = -errno; |
25380 |
-+ kdbus_printf("writing to memfd failed: %m\n"); |
25381 |
-+ goto out; |
25382 |
-+ } |
25383 |
-+ |
25384 |
-+ ret = sys_memfd_seal_set(memfd); |
25385 |
-+ if (ret < 0) { |
25386 |
-+ ret = -errno; |
25387 |
-+ kdbus_printf("memfd sealing failed: %m\n"); |
25388 |
-+ goto out; |
25389 |
-+ } |
25390 |
-+ |
25391 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
25392 |
-+ } |
25393 |
-+ |
25394 |
-+ if (name) |
25395 |
-+ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
25396 |
-+ |
25397 |
-+ msg = malloc(size); |
25398 |
-+ if (!msg) { |
25399 |
-+ ret = -errno; |
25400 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25401 |
-+ goto out; |
25402 |
-+ } |
25403 |
-+ |
25404 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
25405 |
-+ flags |= KDBUS_MSG_SIGNAL; |
25406 |
-+ |
25407 |
-+ memset(msg, 0, size); |
25408 |
-+ msg->flags = flags; |
25409 |
-+ msg->priority = priority; |
25410 |
-+ msg->size = size; |
25411 |
-+ msg->src_id = conn->id; |
25412 |
-+ msg->dst_id = name ? 0 : dst_id; |
25413 |
-+ msg->cookie = cookie; |
25414 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
25415 |
-+ |
25416 |
-+ if (timeout) { |
25417 |
-+ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); |
25418 |
-+ if (ret < 0) |
25419 |
-+ goto out; |
25420 |
-+ |
25421 |
-+ msg->timeout_ns = now.tv_sec * 1000000000ULL + |
25422 |
-+ now.tv_nsec + timeout; |
25423 |
-+ } |
25424 |
-+ |
25425 |
-+ item = msg->items; |
25426 |
-+ |
25427 |
-+ if (name) { |
25428 |
-+ item->type = KDBUS_ITEM_DST_NAME; |
25429 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
25430 |
-+ strcpy(item->str, name); |
25431 |
-+ item = KDBUS_ITEM_NEXT(item); |
25432 |
-+ } |
25433 |
-+ |
25434 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25435 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25436 |
-+ item->vec.address = (uintptr_t)&ref1; |
25437 |
-+ item->vec.size = sizeof(ref1); |
25438 |
-+ item = KDBUS_ITEM_NEXT(item); |
25439 |
-+ |
25440 |
-+ /* data padding for ref1 */ |
25441 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25442 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25443 |
-+ item->vec.address = (uintptr_t)NULL; |
25444 |
-+ item->vec.size = KDBUS_ALIGN8(sizeof(ref1)) - sizeof(ref1); |
25445 |
-+ item = KDBUS_ITEM_NEXT(item); |
25446 |
-+ |
25447 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25448 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25449 |
-+ item->vec.address = (uintptr_t)&ref2; |
25450 |
-+ item->vec.size = sizeof(ref2); |
25451 |
-+ item = KDBUS_ITEM_NEXT(item); |
25452 |
-+ |
25453 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
25454 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
25455 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
25456 |
-+ item->bloom_filter.generation = 0; |
25457 |
-+ } else { |
25458 |
-+ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
25459 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd); |
25460 |
-+ item->memfd.size = 16; |
25461 |
-+ item->memfd.fd = memfd; |
25462 |
-+ } |
25463 |
-+ item = KDBUS_ITEM_NEXT(item); |
25464 |
-+ |
25465 |
-+ size = sizeof(*cmd); |
25466 |
-+ if (cancel_fd != -1) |
25467 |
-+ size += KDBUS_ITEM_SIZE(sizeof(cancel_fd)); |
25468 |
-+ |
25469 |
-+ cmd = malloc(size); |
25470 |
-+ if (!cmd) { |
25471 |
-+ ret = -errno; |
25472 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25473 |
-+ goto out; |
25474 |
-+ } |
25475 |
-+ |
25476 |
-+ cmd->size = size; |
25477 |
-+ cmd->flags = cmd_flags; |
25478 |
-+ cmd->msg_address = (uintptr_t)msg; |
25479 |
-+ |
25480 |
-+ item = cmd->items; |
25481 |
-+ |
25482 |
-+ if (cancel_fd != -1) { |
25483 |
-+ item->type = KDBUS_ITEM_CANCEL_FD; |
25484 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(cancel_fd); |
25485 |
-+ item->fds[0] = cancel_fd; |
25486 |
-+ item = KDBUS_ITEM_NEXT(item); |
25487 |
-+ } |
25488 |
-+ |
25489 |
-+ ret = kdbus_cmd_send(conn->fd, cmd); |
25490 |
-+ if (ret < 0) { |
25491 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
25492 |
-+ goto out; |
25493 |
-+ } |
25494 |
-+ |
25495 |
-+ if (cmd_flags & KDBUS_SEND_SYNC_REPLY) { |
25496 |
-+ struct kdbus_msg *reply; |
25497 |
-+ |
25498 |
-+ kdbus_printf("SYNC REPLY @offset %llu:\n", cmd->reply.offset); |
25499 |
-+ reply = (struct kdbus_msg *)(conn->buf + cmd->reply.offset); |
25500 |
-+ kdbus_msg_dump(conn, reply); |
25501 |
-+ |
25502 |
-+ kdbus_msg_free(reply); |
25503 |
-+ |
25504 |
-+ ret = kdbus_free(conn, cmd->reply.offset); |
25505 |
-+ if (ret < 0) |
25506 |
-+ goto out; |
25507 |
-+ } |
25508 |
-+ |
25509 |
-+out: |
25510 |
-+ free(msg); |
25511 |
-+ free(cmd); |
25512 |
-+ |
25513 |
-+ if (memfd >= 0) |
25514 |
-+ close(memfd); |
25515 |
-+ |
25516 |
-+ return ret < 0 ? ret : 0; |
25517 |
-+} |
25518 |
-+ |
25519 |
-+int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, |
25520 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
25521 |
-+ int64_t priority, uint64_t dst_id) |
25522 |
-+{ |
25523 |
-+ return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority, |
25524 |
-+ dst_id, 0, -1); |
25525 |
-+} |
25526 |
-+ |
25527 |
-+int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, |
25528 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
25529 |
-+ int64_t priority, uint64_t dst_id, int cancel_fd) |
25530 |
-+{ |
25531 |
-+ return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority, |
25532 |
-+ dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd); |
25533 |
-+} |
25534 |
-+ |
25535 |
-+int kdbus_msg_send_reply(const struct kdbus_conn *conn, |
25536 |
-+ uint64_t reply_cookie, |
25537 |
-+ uint64_t dst_id) |
25538 |
-+{ |
25539 |
-+ struct kdbus_cmd_send cmd = {}; |
25540 |
-+ struct kdbus_msg *msg; |
25541 |
-+ const char ref1[1024 * 128 + 3] = "0123456789_0"; |
25542 |
-+ struct kdbus_item *item; |
25543 |
-+ uint64_t size; |
25544 |
-+ int ret; |
25545 |
-+ |
25546 |
-+ size = sizeof(struct kdbus_msg); |
25547 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
25548 |
-+ |
25549 |
-+ msg = malloc(size); |
25550 |
-+ if (!msg) { |
25551 |
-+ kdbus_printf("unable to malloc()!?\n"); |
25552 |
-+ return -ENOMEM; |
25553 |
-+ } |
25554 |
-+ |
25555 |
-+ memset(msg, 0, size); |
25556 |
-+ msg->size = size; |
25557 |
-+ msg->src_id = conn->id; |
25558 |
-+ msg->dst_id = dst_id; |
25559 |
-+ msg->cookie_reply = reply_cookie; |
25560 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
25561 |
-+ |
25562 |
-+ item = msg->items; |
25563 |
-+ |
25564 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
25565 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
25566 |
-+ item->vec.address = (uintptr_t)&ref1; |
25567 |
-+ item->vec.size = sizeof(ref1); |
25568 |
-+ item = KDBUS_ITEM_NEXT(item); |
25569 |
-+ |
25570 |
-+ cmd.size = sizeof(cmd); |
25571 |
-+ cmd.msg_address = (uintptr_t)msg; |
25572 |
-+ |
25573 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
25574 |
-+ if (ret < 0) |
25575 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
25576 |
-+ |
25577 |
-+ free(msg); |
25578 |
-+ |
25579 |
-+ return ret; |
25580 |
-+} |
25581 |
-+ |
25582 |
-+static char *msg_id(uint64_t id, char *buf) |
25583 |
-+{ |
25584 |
-+ if (id == 0) |
25585 |
-+ return "KERNEL"; |
25586 |
-+ if (id == ~0ULL) |
25587 |
-+ return "BROADCAST"; |
25588 |
-+ sprintf(buf, "%llu", (unsigned long long)id); |
25589 |
-+ return buf; |
25590 |
-+} |
25591 |
-+ |
25592 |
-+int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg) |
25593 |
-+{ |
25594 |
-+ const struct kdbus_item *item = msg->items; |
25595 |
-+ char buf_src[32]; |
25596 |
-+ char buf_dst[32]; |
25597 |
-+ uint64_t timeout = 0; |
25598 |
-+ uint64_t cookie_reply = 0; |
25599 |
-+ int ret = 0; |
25600 |
-+ |
25601 |
-+ if (msg->flags & KDBUS_MSG_EXPECT_REPLY) |
25602 |
-+ timeout = msg->timeout_ns; |
25603 |
-+ else |
25604 |
-+ cookie_reply = msg->cookie_reply; |
25605 |
-+ |
25606 |
-+ kdbus_printf("MESSAGE: %s (%llu bytes) flags=0x%08llx, %s → %s, " |
25607 |
-+ "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n", |
25608 |
-+ enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size, |
25609 |
-+ (unsigned long long)msg->flags, |
25610 |
-+ msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst), |
25611 |
-+ (unsigned long long)msg->cookie, (unsigned long long)timeout, |
25612 |
-+ (unsigned long long)cookie_reply, (long long)msg->priority); |
25613 |
-+ |
25614 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
25615 |
-+ if (item->size < KDBUS_ITEM_HEADER_SIZE) { |
25616 |
-+ kdbus_printf(" +%s (%llu bytes) invalid data record\n", |
25617 |
-+ enum_MSG(item->type), item->size); |
25618 |
-+ ret = -EINVAL; |
25619 |
-+ break; |
25620 |
-+ } |
25621 |
-+ |
25622 |
-+ switch (item->type) { |
25623 |
-+ case KDBUS_ITEM_PAYLOAD_OFF: { |
25624 |
-+ char *s; |
25625 |
-+ |
25626 |
-+ if (item->vec.offset == ~0ULL) |
25627 |
-+ s = "[\\0-bytes]"; |
25628 |
-+ else |
25629 |
-+ s = (char *)msg + item->vec.offset; |
25630 |
-+ |
25631 |
-+ kdbus_printf(" +%s (%llu bytes) off=%llu size=%llu '%s'\n", |
25632 |
-+ enum_MSG(item->type), item->size, |
25633 |
-+ (unsigned long long)item->vec.offset, |
25634 |
-+ (unsigned long long)item->vec.size, s); |
25635 |
-+ break; |
25636 |
-+ } |
25637 |
-+ |
25638 |
-+ case KDBUS_ITEM_FDS: { |
25639 |
-+ int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25640 |
-+ sizeof(int); |
25641 |
-+ |
25642 |
-+ kdbus_printf(" +%s (%llu bytes, %d fds)\n", |
25643 |
-+ enum_MSG(item->type), item->size, n); |
25644 |
-+ |
25645 |
-+ for (i = 0; i < n; i++) |
25646 |
-+ kdbus_printf(" fd[%d] = %d\n", |
25647 |
-+ i, item->fds[i]); |
25648 |
-+ |
25649 |
-+ break; |
25650 |
-+ } |
25651 |
-+ |
25652 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
25653 |
-+ char *buf; |
25654 |
-+ off_t size; |
25655 |
-+ |
25656 |
-+ buf = mmap(NULL, item->memfd.size, PROT_READ, |
25657 |
-+ MAP_PRIVATE, item->memfd.fd, 0); |
25658 |
-+ if (buf == MAP_FAILED) { |
25659 |
-+ kdbus_printf("mmap() fd=%i size=%llu failed: %m\n", |
25660 |
-+ item->memfd.fd, item->memfd.size); |
25661 |
-+ break; |
25662 |
-+ } |
25663 |
-+ |
25664 |
-+ if (sys_memfd_get_size(item->memfd.fd, &size) < 0) { |
25665 |
-+ kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n"); |
25666 |
-+ break; |
25667 |
-+ } |
25668 |
-+ |
25669 |
-+ kdbus_printf(" +%s (%llu bytes) fd=%i size=%llu filesize=%llu '%s'\n", |
25670 |
-+ enum_MSG(item->type), item->size, item->memfd.fd, |
25671 |
-+ (unsigned long long)item->memfd.size, |
25672 |
-+ (unsigned long long)size, buf); |
25673 |
-+ munmap(buf, item->memfd.size); |
25674 |
-+ break; |
25675 |
-+ } |
25676 |
-+ |
25677 |
-+ case KDBUS_ITEM_CREDS: |
25678 |
-+ kdbus_printf(" +%s (%llu bytes) uid=%lld, euid=%lld, suid=%lld, fsuid=%lld, " |
25679 |
-+ "gid=%lld, egid=%lld, sgid=%lld, fsgid=%lld\n", |
25680 |
-+ enum_MSG(item->type), item->size, |
25681 |
-+ item->creds.uid, item->creds.euid, |
25682 |
-+ item->creds.suid, item->creds.fsuid, |
25683 |
-+ item->creds.gid, item->creds.egid, |
25684 |
-+ item->creds.sgid, item->creds.fsgid); |
25685 |
-+ break; |
25686 |
-+ |
25687 |
-+ case KDBUS_ITEM_PIDS: |
25688 |
-+ kdbus_printf(" +%s (%llu bytes) pid=%lld, tid=%lld, ppid=%lld\n", |
25689 |
-+ enum_MSG(item->type), item->size, |
25690 |
-+ item->pids.pid, item->pids.tid, |
25691 |
-+ item->pids.ppid); |
25692 |
-+ break; |
25693 |
-+ |
25694 |
-+ case KDBUS_ITEM_AUXGROUPS: { |
25695 |
-+ int i, n; |
25696 |
-+ |
25697 |
-+ kdbus_printf(" +%s (%llu bytes)\n", |
25698 |
-+ enum_MSG(item->type), item->size); |
25699 |
-+ n = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25700 |
-+ sizeof(uint64_t); |
25701 |
-+ |
25702 |
-+ for (i = 0; i < n; i++) |
25703 |
-+ kdbus_printf(" gid[%d] = %lld\n", |
25704 |
-+ i, item->data64[i]); |
25705 |
-+ break; |
25706 |
-+ } |
25707 |
-+ |
25708 |
-+ case KDBUS_ITEM_NAME: |
25709 |
-+ case KDBUS_ITEM_PID_COMM: |
25710 |
-+ case KDBUS_ITEM_TID_COMM: |
25711 |
-+ case KDBUS_ITEM_EXE: |
25712 |
-+ case KDBUS_ITEM_CGROUP: |
25713 |
-+ case KDBUS_ITEM_SECLABEL: |
25714 |
-+ case KDBUS_ITEM_DST_NAME: |
25715 |
-+ case KDBUS_ITEM_CONN_DESCRIPTION: |
25716 |
-+ kdbus_printf(" +%s (%llu bytes) '%s' (%zu)\n", |
25717 |
-+ enum_MSG(item->type), item->size, |
25718 |
-+ item->str, strlen(item->str)); |
25719 |
-+ break; |
25720 |
-+ |
25721 |
-+ case KDBUS_ITEM_OWNED_NAME: { |
25722 |
-+ kdbus_printf(" +%s (%llu bytes) '%s' (%zu) flags=0x%08llx\n", |
25723 |
-+ enum_MSG(item->type), item->size, |
25724 |
-+ item->name.name, strlen(item->name.name), |
25725 |
-+ item->name.flags); |
25726 |
-+ break; |
25727 |
-+ } |
25728 |
-+ |
25729 |
-+ case KDBUS_ITEM_CMDLINE: { |
25730 |
-+ size_t size = item->size - KDBUS_ITEM_HEADER_SIZE; |
25731 |
-+ const char *str = item->str; |
25732 |
-+ int count = 0; |
25733 |
-+ |
25734 |
-+ kdbus_printf(" +%s (%llu bytes) ", |
25735 |
-+ enum_MSG(item->type), item->size); |
25736 |
-+ while (size) { |
25737 |
-+ kdbus_printf("'%s' ", str); |
25738 |
-+ size -= strlen(str) + 1; |
25739 |
-+ str += strlen(str) + 1; |
25740 |
-+ count++; |
25741 |
-+ } |
25742 |
-+ |
25743 |
-+ kdbus_printf("(%d string%s)\n", |
25744 |
-+ count, (count == 1) ? "" : "s"); |
25745 |
-+ break; |
25746 |
-+ } |
25747 |
-+ |
25748 |
-+ case KDBUS_ITEM_AUDIT: |
25749 |
-+ kdbus_printf(" +%s (%llu bytes) loginuid=%u sessionid=%u\n", |
25750 |
-+ enum_MSG(item->type), item->size, |
25751 |
-+ item->audit.loginuid, item->audit.sessionid); |
25752 |
-+ break; |
25753 |
-+ |
25754 |
-+ case KDBUS_ITEM_CAPS: { |
25755 |
-+ const uint32_t *cap; |
25756 |
-+ int n, i; |
25757 |
-+ |
25758 |
-+ kdbus_printf(" +%s (%llu bytes) len=%llu bytes, last_cap %d\n", |
25759 |
-+ enum_MSG(item->type), item->size, |
25760 |
-+ (unsigned long long)item->size - |
25761 |
-+ KDBUS_ITEM_HEADER_SIZE, |
25762 |
-+ (int) item->caps.last_cap); |
25763 |
-+ |
25764 |
-+ cap = item->caps.caps; |
25765 |
-+ n = (item->size - offsetof(struct kdbus_item, caps.caps)) |
25766 |
-+ / 4 / sizeof(uint32_t); |
25767 |
-+ |
25768 |
-+ kdbus_printf(" CapInh="); |
25769 |
-+ for (i = 0; i < n; i++) |
25770 |
-+ kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]); |
25771 |
-+ |
25772 |
-+ kdbus_printf(" CapPrm="); |
25773 |
-+ for (i = 0; i < n; i++) |
25774 |
-+ kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]); |
25775 |
-+ |
25776 |
-+ kdbus_printf(" CapEff="); |
25777 |
-+ for (i = 0; i < n; i++) |
25778 |
-+ kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]); |
25779 |
-+ |
25780 |
-+ kdbus_printf(" CapBnd="); |
25781 |
-+ for (i = 0; i < n; i++) |
25782 |
-+ kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]); |
25783 |
-+ kdbus_printf("\n"); |
25784 |
-+ break; |
25785 |
-+ } |
25786 |
-+ |
25787 |
-+ case KDBUS_ITEM_TIMESTAMP: |
25788 |
-+ kdbus_printf(" +%s (%llu bytes) seq=%llu realtime=%lluns monotonic=%lluns\n", |
25789 |
-+ enum_MSG(item->type), item->size, |
25790 |
-+ (unsigned long long)item->timestamp.seqnum, |
25791 |
-+ (unsigned long long)item->timestamp.realtime_ns, |
25792 |
-+ (unsigned long long)item->timestamp.monotonic_ns); |
25793 |
-+ break; |
25794 |
-+ |
25795 |
-+ case KDBUS_ITEM_REPLY_TIMEOUT: |
25796 |
-+ kdbus_printf(" +%s (%llu bytes) cookie=%llu\n", |
25797 |
-+ enum_MSG(item->type), item->size, |
25798 |
-+ msg->cookie_reply); |
25799 |
-+ break; |
25800 |
-+ |
25801 |
-+ case KDBUS_ITEM_NAME_ADD: |
25802 |
-+ case KDBUS_ITEM_NAME_REMOVE: |
25803 |
-+ case KDBUS_ITEM_NAME_CHANGE: |
25804 |
-+ kdbus_printf(" +%s (%llu bytes) '%s', old id=%lld, now id=%lld, old_flags=0x%llx new_flags=0x%llx\n", |
25805 |
-+ enum_MSG(item->type), |
25806 |
-+ (unsigned long long) item->size, |
25807 |
-+ item->name_change.name, |
25808 |
-+ item->name_change.old_id.id, |
25809 |
-+ item->name_change.new_id.id, |
25810 |
-+ item->name_change.old_id.flags, |
25811 |
-+ item->name_change.new_id.flags); |
25812 |
-+ break; |
25813 |
-+ |
25814 |
-+ case KDBUS_ITEM_ID_ADD: |
25815 |
-+ case KDBUS_ITEM_ID_REMOVE: |
25816 |
-+ kdbus_printf(" +%s (%llu bytes) id=%llu flags=%llu\n", |
25817 |
-+ enum_MSG(item->type), |
25818 |
-+ (unsigned long long) item->size, |
25819 |
-+ (unsigned long long) item->id_change.id, |
25820 |
-+ (unsigned long long) item->id_change.flags); |
25821 |
-+ break; |
25822 |
-+ |
25823 |
-+ default: |
25824 |
-+ kdbus_printf(" +%s (%llu bytes)\n", |
25825 |
-+ enum_MSG(item->type), item->size); |
25826 |
-+ break; |
25827 |
-+ } |
25828 |
-+ } |
25829 |
-+ |
25830 |
-+ if ((char *)item - ((char *)msg + msg->size) >= 8) { |
25831 |
-+ kdbus_printf("invalid padding at end of message\n"); |
25832 |
-+ ret = -EINVAL; |
25833 |
-+ } |
25834 |
-+ |
25835 |
-+ kdbus_printf("\n"); |
25836 |
-+ |
25837 |
-+ return ret; |
25838 |
-+} |
25839 |
-+ |
25840 |
-+void kdbus_msg_free(struct kdbus_msg *msg) |
25841 |
-+{ |
25842 |
-+ const struct kdbus_item *item; |
25843 |
-+ int nfds, i; |
25844 |
-+ |
25845 |
-+ if (!msg) |
25846 |
-+ return; |
25847 |
-+ |
25848 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
25849 |
-+ switch (item->type) { |
25850 |
-+ /* close all memfds */ |
25851 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: |
25852 |
-+ close(item->memfd.fd); |
25853 |
-+ break; |
25854 |
-+ case KDBUS_ITEM_FDS: |
25855 |
-+ nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
25856 |
-+ sizeof(int); |
25857 |
-+ |
25858 |
-+ for (i = 0; i < nfds; i++) |
25859 |
-+ close(item->fds[i]); |
25860 |
-+ |
25861 |
-+ break; |
25862 |
-+ } |
25863 |
-+ } |
25864 |
-+} |
25865 |
-+ |
25866 |
-+int kdbus_msg_recv(struct kdbus_conn *conn, |
25867 |
-+ struct kdbus_msg **msg_out, |
25868 |
-+ uint64_t *offset) |
25869 |
-+{ |
25870 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
25871 |
-+ struct kdbus_msg *msg; |
25872 |
-+ int ret; |
25873 |
-+ |
25874 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
25875 |
-+ if (ret < 0) |
25876 |
-+ return ret; |
25877 |
-+ |
25878 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
25879 |
-+ ret = kdbus_msg_dump(conn, msg); |
25880 |
-+ if (ret < 0) { |
25881 |
-+ kdbus_msg_free(msg); |
25882 |
-+ return ret; |
25883 |
-+ } |
25884 |
-+ |
25885 |
-+ if (msg_out) { |
25886 |
-+ *msg_out = msg; |
25887 |
-+ |
25888 |
-+ if (offset) |
25889 |
-+ *offset = recv.msg.offset; |
25890 |
-+ } else { |
25891 |
-+ kdbus_msg_free(msg); |
25892 |
-+ |
25893 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
25894 |
-+ if (ret < 0) |
25895 |
-+ return ret; |
25896 |
-+ } |
25897 |
-+ |
25898 |
-+ return 0; |
25899 |
-+} |
25900 |
-+ |
25901 |
-+/* |
25902 |
-+ * Returns: 0 on success, negative errno on failure. |
25903 |
-+ * |
25904 |
-+ * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors. |
25905 |
-+ * We must return the result of kdbus_msg_recv() |
25906 |
-+ */ |
25907 |
-+int kdbus_msg_recv_poll(struct kdbus_conn *conn, |
25908 |
-+ int timeout_ms, |
25909 |
-+ struct kdbus_msg **msg_out, |
25910 |
-+ uint64_t *offset) |
25911 |
-+{ |
25912 |
-+ int ret; |
25913 |
-+ |
25914 |
-+ do { |
25915 |
-+ struct timeval before, after, diff; |
25916 |
-+ struct pollfd fd; |
25917 |
-+ |
25918 |
-+ fd.fd = conn->fd; |
25919 |
-+ fd.events = POLLIN | POLLPRI | POLLHUP; |
25920 |
-+ fd.revents = 0; |
25921 |
-+ |
25922 |
-+ gettimeofday(&before, NULL); |
25923 |
-+ ret = poll(&fd, 1, timeout_ms); |
25924 |
-+ gettimeofday(&after, NULL); |
25925 |
-+ |
25926 |
-+ if (ret == 0) { |
25927 |
-+ ret = -ETIMEDOUT; |
25928 |
-+ break; |
25929 |
-+ } |
25930 |
-+ |
25931 |
-+ if (ret > 0) { |
25932 |
-+ if (fd.revents & POLLIN) |
25933 |
-+ ret = kdbus_msg_recv(conn, msg_out, offset); |
25934 |
-+ |
25935 |
-+ if (fd.revents & (POLLHUP | POLLERR)) |
25936 |
-+ ret = -ECONNRESET; |
25937 |
-+ } |
25938 |
-+ |
25939 |
-+ if (ret == 0 || ret != -EAGAIN) |
25940 |
-+ break; |
25941 |
-+ |
25942 |
-+ timersub(&after, &before, &diff); |
25943 |
-+ timeout_ms -= diff.tv_sec * 1000UL + |
25944 |
-+ diff.tv_usec / 1000UL; |
25945 |
-+ } while (timeout_ms > 0); |
25946 |
-+ |
25947 |
-+ return ret; |
25948 |
-+} |
25949 |
-+ |
25950 |
-+int kdbus_free(const struct kdbus_conn *conn, uint64_t offset) |
25951 |
-+{ |
25952 |
-+ struct kdbus_cmd_free cmd_free = {}; |
25953 |
-+ int ret; |
25954 |
-+ |
25955 |
-+ cmd_free.size = sizeof(cmd_free); |
25956 |
-+ cmd_free.offset = offset; |
25957 |
-+ cmd_free.flags = 0; |
25958 |
-+ |
25959 |
-+ ret = kdbus_cmd_free(conn->fd, &cmd_free); |
25960 |
-+ if (ret < 0) { |
25961 |
-+ kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret); |
25962 |
-+ return ret; |
25963 |
-+ } |
25964 |
-+ |
25965 |
-+ return 0; |
25966 |
-+} |
25967 |
-+ |
25968 |
-+int kdbus_name_acquire(struct kdbus_conn *conn, |
25969 |
-+ const char *name, uint64_t *flags) |
25970 |
-+{ |
25971 |
-+ struct kdbus_cmd *cmd_name; |
25972 |
-+ size_t name_len = strlen(name) + 1; |
25973 |
-+ uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len); |
25974 |
-+ struct kdbus_item *item; |
25975 |
-+ int ret; |
25976 |
-+ |
25977 |
-+ cmd_name = alloca(size); |
25978 |
-+ |
25979 |
-+ memset(cmd_name, 0, size); |
25980 |
-+ |
25981 |
-+ item = cmd_name->items; |
25982 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + name_len; |
25983 |
-+ item->type = KDBUS_ITEM_NAME; |
25984 |
-+ strcpy(item->str, name); |
25985 |
-+ |
25986 |
-+ cmd_name->size = size; |
25987 |
-+ if (flags) |
25988 |
-+ cmd_name->flags = *flags; |
25989 |
-+ |
25990 |
-+ ret = kdbus_cmd_name_acquire(conn->fd, cmd_name); |
25991 |
-+ if (ret < 0) { |
25992 |
-+ kdbus_printf("error aquiring name: %s\n", strerror(-ret)); |
25993 |
-+ return ret; |
25994 |
-+ } |
25995 |
-+ |
25996 |
-+ kdbus_printf("%s(): flags after call: 0x%llx\n", __func__, |
25997 |
-+ cmd_name->return_flags); |
25998 |
-+ |
25999 |
-+ if (flags) |
26000 |
-+ *flags = cmd_name->return_flags; |
26001 |
-+ |
26002 |
-+ return 0; |
26003 |
-+} |
26004 |
-+ |
26005 |
-+int kdbus_name_release(struct kdbus_conn *conn, const char *name) |
26006 |
-+{ |
26007 |
-+ struct kdbus_cmd *cmd_name; |
26008 |
-+ size_t name_len = strlen(name) + 1; |
26009 |
-+ uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len); |
26010 |
-+ struct kdbus_item *item; |
26011 |
-+ int ret; |
26012 |
-+ |
26013 |
-+ cmd_name = alloca(size); |
26014 |
-+ |
26015 |
-+ memset(cmd_name, 0, size); |
26016 |
-+ |
26017 |
-+ item = cmd_name->items; |
26018 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + name_len; |
26019 |
-+ item->type = KDBUS_ITEM_NAME; |
26020 |
-+ strcpy(item->str, name); |
26021 |
-+ |
26022 |
-+ cmd_name->size = size; |
26023 |
-+ |
26024 |
-+ kdbus_printf("conn %lld giving up name '%s'\n", |
26025 |
-+ (unsigned long long) conn->id, name); |
26026 |
-+ |
26027 |
-+ ret = kdbus_cmd_name_release(conn->fd, cmd_name); |
26028 |
-+ if (ret < 0) { |
26029 |
-+ kdbus_printf("error releasing name: %s\n", strerror(-ret)); |
26030 |
-+ return ret; |
26031 |
-+ } |
26032 |
-+ |
26033 |
-+ return 0; |
26034 |
-+} |
26035 |
-+ |
26036 |
-+int kdbus_list(struct kdbus_conn *conn, uint64_t flags) |
26037 |
-+{ |
26038 |
-+ struct kdbus_cmd_list cmd_list = {}; |
26039 |
-+ struct kdbus_info *list, *name; |
26040 |
-+ int ret; |
26041 |
-+ |
26042 |
-+ cmd_list.size = sizeof(cmd_list); |
26043 |
-+ cmd_list.flags = flags; |
26044 |
-+ |
26045 |
-+ ret = kdbus_cmd_list(conn->fd, &cmd_list); |
26046 |
-+ if (ret < 0) { |
26047 |
-+ kdbus_printf("error listing names: %d (%m)\n", ret); |
26048 |
-+ return ret; |
26049 |
-+ } |
26050 |
-+ |
26051 |
-+ kdbus_printf("REGISTRY:\n"); |
26052 |
-+ list = (struct kdbus_info *)(conn->buf + cmd_list.offset); |
26053 |
-+ |
26054 |
-+ KDBUS_FOREACH(name, list, cmd_list.list_size) { |
26055 |
-+ uint64_t flags = 0; |
26056 |
-+ struct kdbus_item *item; |
26057 |
-+ const char *n = "MISSING-NAME"; |
26058 |
-+ |
26059 |
-+ if (name->size == sizeof(struct kdbus_cmd)) |
26060 |
-+ continue; |
26061 |
-+ |
26062 |
-+ KDBUS_ITEM_FOREACH(item, name, items) |
26063 |
-+ if (item->type == KDBUS_ITEM_OWNED_NAME) { |
26064 |
-+ n = item->name.name; |
26065 |
-+ flags = item->name.flags; |
26066 |
-+ |
26067 |
-+ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n", |
26068 |
-+ name->id, |
26069 |
-+ (unsigned long long) flags, |
26070 |
-+ name->flags, n); |
26071 |
-+ } |
26072 |
-+ } |
26073 |
-+ kdbus_printf("\n"); |
26074 |
-+ |
26075 |
-+ ret = kdbus_free(conn, cmd_list.offset); |
26076 |
-+ |
26077 |
-+ return ret; |
26078 |
-+} |
26079 |
-+ |
26080 |
-+int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, |
26081 |
-+ uint64_t attach_flags_send, |
26082 |
-+ uint64_t attach_flags_recv) |
26083 |
-+{ |
26084 |
-+ int ret; |
26085 |
-+ size_t size; |
26086 |
-+ struct kdbus_cmd *update; |
26087 |
-+ struct kdbus_item *item; |
26088 |
-+ |
26089 |
-+ size = sizeof(struct kdbus_cmd); |
26090 |
-+ size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2; |
26091 |
-+ |
26092 |
-+ update = malloc(size); |
26093 |
-+ if (!update) { |
26094 |
-+ kdbus_printf("error malloc: %m\n"); |
26095 |
-+ return -ENOMEM; |
26096 |
-+ } |
26097 |
-+ |
26098 |
-+ memset(update, 0, size); |
26099 |
-+ update->size = size; |
26100 |
-+ |
26101 |
-+ item = update->items; |
26102 |
-+ |
26103 |
-+ item->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; |
26104 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); |
26105 |
-+ item->data64[0] = attach_flags_send; |
26106 |
-+ item = KDBUS_ITEM_NEXT(item); |
26107 |
-+ |
26108 |
-+ item->type = KDBUS_ITEM_ATTACH_FLAGS_RECV; |
26109 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t); |
26110 |
-+ item->data64[0] = attach_flags_recv; |
26111 |
-+ item = KDBUS_ITEM_NEXT(item); |
26112 |
-+ |
26113 |
-+ ret = kdbus_cmd_update(conn->fd, update); |
26114 |
-+ if (ret < 0) |
26115 |
-+ kdbus_printf("error conn update: %d (%m)\n", ret); |
26116 |
-+ |
26117 |
-+ free(update); |
26118 |
-+ |
26119 |
-+ return ret; |
26120 |
-+} |
26121 |
-+ |
26122 |
-+int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, |
26123 |
-+ const struct kdbus_policy_access *access, |
26124 |
-+ size_t num_access) |
26125 |
-+{ |
26126 |
-+ struct kdbus_cmd *update; |
26127 |
-+ struct kdbus_item *item; |
26128 |
-+ size_t i, size; |
26129 |
-+ int ret; |
26130 |
-+ |
26131 |
-+ size = sizeof(struct kdbus_cmd); |
26132 |
-+ size += KDBUS_ITEM_SIZE(strlen(name) + 1); |
26133 |
-+ size += num_access * KDBUS_ITEM_SIZE(sizeof(struct kdbus_policy_access)); |
26134 |
-+ |
26135 |
-+ update = malloc(size); |
26136 |
-+ if (!update) { |
26137 |
-+ kdbus_printf("error malloc: %m\n"); |
26138 |
-+ return -ENOMEM; |
26139 |
-+ } |
26140 |
-+ |
26141 |
-+ memset(update, 0, size); |
26142 |
-+ update->size = size; |
26143 |
-+ |
26144 |
-+ item = update->items; |
26145 |
-+ |
26146 |
-+ item->type = KDBUS_ITEM_NAME; |
26147 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1; |
26148 |
-+ strcpy(item->str, name); |
26149 |
-+ item = KDBUS_ITEM_NEXT(item); |
26150 |
-+ |
26151 |
-+ for (i = 0; i < num_access; i++) { |
26152 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
26153 |
-+ sizeof(struct kdbus_policy_access); |
26154 |
-+ item->type = KDBUS_ITEM_POLICY_ACCESS; |
26155 |
-+ |
26156 |
-+ item->policy_access.type = access[i].type; |
26157 |
-+ item->policy_access.access = access[i].access; |
26158 |
-+ item->policy_access.id = access[i].id; |
26159 |
-+ |
26160 |
-+ item = KDBUS_ITEM_NEXT(item); |
26161 |
-+ } |
26162 |
-+ |
26163 |
-+ ret = kdbus_cmd_update(conn->fd, update); |
26164 |
-+ if (ret < 0) |
26165 |
-+ kdbus_printf("error conn update: %d (%m)\n", ret); |
26166 |
-+ |
26167 |
-+ free(update); |
26168 |
-+ |
26169 |
-+ return ret; |
26170 |
-+} |
26171 |
-+ |
26172 |
-+int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, |
26173 |
-+ uint64_t type, uint64_t id) |
26174 |
-+{ |
26175 |
-+ struct { |
26176 |
-+ struct kdbus_cmd_match cmd; |
26177 |
-+ struct { |
26178 |
-+ uint64_t size; |
26179 |
-+ uint64_t type; |
26180 |
-+ struct kdbus_notify_id_change chg; |
26181 |
-+ } item; |
26182 |
-+ } buf; |
26183 |
-+ int ret; |
26184 |
-+ |
26185 |
-+ memset(&buf, 0, sizeof(buf)); |
26186 |
-+ |
26187 |
-+ buf.cmd.size = sizeof(buf); |
26188 |
-+ buf.cmd.cookie = cookie; |
26189 |
-+ buf.item.size = sizeof(buf.item); |
26190 |
-+ buf.item.type = type; |
26191 |
-+ buf.item.chg.id = id; |
26192 |
-+ |
26193 |
-+ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
26194 |
-+ if (ret < 0) |
26195 |
-+ kdbus_printf("--- error adding conn match: %d (%m)\n", ret); |
26196 |
-+ |
26197 |
-+ return ret; |
26198 |
-+} |
26199 |
-+ |
26200 |
-+int kdbus_add_match_empty(struct kdbus_conn *conn) |
26201 |
-+{ |
26202 |
-+ struct { |
26203 |
-+ struct kdbus_cmd_match cmd; |
26204 |
-+ struct kdbus_item item; |
26205 |
-+ } buf; |
26206 |
-+ int ret; |
26207 |
-+ |
26208 |
-+ memset(&buf, 0, sizeof(buf)); |
26209 |
-+ |
26210 |
-+ buf.item.size = sizeof(uint64_t) * 3; |
26211 |
-+ buf.item.type = KDBUS_ITEM_ID; |
26212 |
-+ buf.item.id = KDBUS_MATCH_ID_ANY; |
26213 |
-+ |
26214 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
26215 |
-+ |
26216 |
-+ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
26217 |
-+ if (ret < 0) |
26218 |
-+ kdbus_printf("--- error adding conn match: %d (%m)\n", ret); |
26219 |
-+ |
26220 |
-+ return ret; |
26221 |
-+} |
26222 |
-+ |
26223 |
-+static int all_ids_are_mapped(const char *path) |
26224 |
-+{ |
26225 |
-+ int ret; |
26226 |
-+ FILE *file; |
26227 |
-+ uint32_t inside_id, length; |
26228 |
-+ |
26229 |
-+ file = fopen(path, "r"); |
26230 |
-+ if (!file) { |
26231 |
-+ ret = -errno; |
26232 |
-+ kdbus_printf("error fopen() %s: %d (%m)\n", |
26233 |
-+ path, ret); |
26234 |
-+ return ret; |
26235 |
-+ } |
26236 |
-+ |
26237 |
-+ ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length); |
26238 |
-+ if (ret != 2) { |
26239 |
-+ if (ferror(file)) |
26240 |
-+ ret = -errno; |
26241 |
-+ else |
26242 |
-+ ret = -EIO; |
26243 |
-+ |
26244 |
-+ kdbus_printf("--- error fscanf(): %d\n", ret); |
26245 |
-+ fclose(file); |
26246 |
-+ return ret; |
26247 |
-+ } |
26248 |
-+ |
26249 |
-+ fclose(file); |
26250 |
-+ |
26251 |
-+ /* |
26252 |
-+ * If length is 4294967295 which means the invalid uid |
26253 |
-+ * (uid_t) -1 then we are able to map all uid/gids |
26254 |
-+ */ |
26255 |
-+ if (inside_id == 0 && length == (uid_t) -1) |
26256 |
-+ return 1; |
26257 |
-+ |
26258 |
-+ return 0; |
26259 |
-+} |
26260 |
-+ |
26261 |
-+int all_uids_gids_are_mapped(void) |
26262 |
-+{ |
26263 |
-+ int ret; |
26264 |
-+ |
26265 |
-+ ret = all_ids_are_mapped("/proc/self/uid_map"); |
26266 |
-+ if (ret <= 0) { |
26267 |
-+ kdbus_printf("--- error not all uids are mapped\n"); |
26268 |
-+ return 0; |
26269 |
-+ } |
26270 |
-+ |
26271 |
-+ ret = all_ids_are_mapped("/proc/self/gid_map"); |
26272 |
-+ if (ret <= 0) { |
26273 |
-+ kdbus_printf("--- error not all gids are mapped\n"); |
26274 |
-+ return 0; |
26275 |
-+ } |
26276 |
-+ |
26277 |
-+ return 1; |
26278 |
-+} |
26279 |
-+ |
26280 |
-+int drop_privileges(uid_t uid, gid_t gid) |
26281 |
-+{ |
26282 |
-+ int ret; |
26283 |
-+ |
26284 |
-+ ret = setgroups(0, NULL); |
26285 |
-+ if (ret < 0) { |
26286 |
-+ ret = -errno; |
26287 |
-+ kdbus_printf("error setgroups: %d (%m)\n", ret); |
26288 |
-+ return ret; |
26289 |
-+ } |
26290 |
-+ |
26291 |
-+ ret = setresgid(gid, gid, gid); |
26292 |
-+ if (ret < 0) { |
26293 |
-+ ret = -errno; |
26294 |
-+ kdbus_printf("error setresgid: %d (%m)\n", ret); |
26295 |
-+ return ret; |
26296 |
-+ } |
26297 |
-+ |
26298 |
-+ ret = setresuid(uid, uid, uid); |
26299 |
-+ if (ret < 0) { |
26300 |
-+ ret = -errno; |
26301 |
-+ kdbus_printf("error setresuid: %d (%m)\n", ret); |
26302 |
-+ return ret; |
26303 |
-+ } |
26304 |
-+ |
26305 |
-+ return ret; |
26306 |
-+} |
26307 |
-+ |
26308 |
-+uint64_t now(clockid_t clock) |
26309 |
-+{ |
26310 |
-+ struct timespec spec; |
26311 |
-+ |
26312 |
-+ clock_gettime(clock, &spec); |
26313 |
-+ return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec; |
26314 |
-+} |
26315 |
-+ |
26316 |
-+char *unique_name(const char *prefix) |
26317 |
-+{ |
26318 |
-+ unsigned int i; |
26319 |
-+ uint64_t u_now; |
26320 |
-+ char n[17]; |
26321 |
-+ char *str; |
26322 |
-+ int r; |
26323 |
-+ |
26324 |
-+ /* |
26325 |
-+ * This returns a random string which is guaranteed to be |
26326 |
-+ * globally unique across all calls to unique_name(). We |
26327 |
-+ * compose the string as: |
26328 |
-+ * <prefix>-<random>-<time> |
26329 |
-+ * With: |
26330 |
-+ * <prefix>: string provided by the caller |
26331 |
-+ * <random>: a random alpha string of 16 characters |
26332 |
-+ * <time>: the current time in micro-seconds since last boot |
26333 |
-+ * |
26334 |
-+ * The <random> part makes the string always look vastly different, |
26335 |
-+ * the <time> part makes sure no two calls return the same string. |
26336 |
-+ */ |
26337 |
-+ |
26338 |
-+ u_now = now(CLOCK_MONOTONIC); |
26339 |
-+ |
26340 |
-+ for (i = 0; i < sizeof(n) - 1; ++i) |
26341 |
-+ n[i] = 'a' + (rand() % ('z' - 'a')); |
26342 |
-+ n[sizeof(n) - 1] = 0; |
26343 |
-+ |
26344 |
-+ r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now); |
26345 |
-+ if (r < 0) |
26346 |
-+ return NULL; |
26347 |
-+ |
26348 |
-+ return str; |
26349 |
-+} |
26350 |
-+ |
26351 |
-+static int do_userns_map_id(pid_t pid, |
26352 |
-+ const char *map_file, |
26353 |
-+ const char *map_id) |
26354 |
-+{ |
26355 |
-+ int ret; |
26356 |
-+ int fd; |
26357 |
-+ char *map; |
26358 |
-+ unsigned int i; |
26359 |
-+ |
26360 |
-+ map = strndupa(map_id, strlen(map_id)); |
26361 |
-+ if (!map) { |
26362 |
-+ ret = -errno; |
26363 |
-+ kdbus_printf("error strndupa %s: %d (%m)\n", |
26364 |
-+ map_file, ret); |
26365 |
-+ return ret; |
26366 |
-+ } |
26367 |
-+ |
26368 |
-+ for (i = 0; i < strlen(map); i++) |
26369 |
-+ if (map[i] == ',') |
26370 |
-+ map[i] = '\n'; |
26371 |
-+ |
26372 |
-+ fd = open(map_file, O_RDWR); |
26373 |
-+ if (fd < 0) { |
26374 |
-+ ret = -errno; |
26375 |
-+ kdbus_printf("error open %s: %d (%m)\n", |
26376 |
-+ map_file, ret); |
26377 |
-+ return ret; |
26378 |
-+ } |
26379 |
-+ |
26380 |
-+ ret = write(fd, map, strlen(map)); |
26381 |
-+ if (ret < 0) { |
26382 |
-+ ret = -errno; |
26383 |
-+ kdbus_printf("error write to %s: %d (%m)\n", |
26384 |
-+ map_file, ret); |
26385 |
-+ goto out; |
26386 |
-+ } |
26387 |
-+ |
26388 |
-+ ret = 0; |
26389 |
-+ |
26390 |
-+out: |
26391 |
-+ close(fd); |
26392 |
-+ return ret; |
26393 |
-+} |
26394 |
-+ |
26395 |
-+int userns_map_uid_gid(pid_t pid, |
26396 |
-+ const char *map_uid, |
26397 |
-+ const char *map_gid) |
26398 |
-+{ |
26399 |
-+ int fd, ret; |
26400 |
-+ char file_id[128] = {'\0'}; |
26401 |
-+ |
26402 |
-+ snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map", |
26403 |
-+ (long) pid); |
26404 |
-+ |
26405 |
-+ ret = do_userns_map_id(pid, file_id, map_uid); |
26406 |
-+ if (ret < 0) |
26407 |
-+ return ret; |
26408 |
-+ |
26409 |
-+ snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups", |
26410 |
-+ (long) pid); |
26411 |
-+ |
26412 |
-+ fd = open(file_id, O_WRONLY); |
26413 |
-+ if (fd >= 0) { |
26414 |
-+ write(fd, "deny\n", 5); |
26415 |
-+ close(fd); |
26416 |
-+ } |
26417 |
-+ |
26418 |
-+ snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map", |
26419 |
-+ (long) pid); |
26420 |
-+ |
26421 |
-+ return do_userns_map_id(pid, file_id, map_gid); |
26422 |
-+} |
26423 |
-+ |
26424 |
-+static int do_cap_get_flag(cap_t caps, cap_value_t cap) |
26425 |
-+{ |
26426 |
-+ int ret; |
26427 |
-+ cap_flag_value_t flag_set; |
26428 |
-+ |
26429 |
-+ ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set); |
26430 |
-+ if (ret < 0) { |
26431 |
-+ ret = -errno; |
26432 |
-+ kdbus_printf("error cap_get_flag(): %d (%m)\n", ret); |
26433 |
-+ return ret; |
26434 |
-+ } |
26435 |
-+ |
26436 |
-+ return (flag_set == CAP_SET); |
26437 |
-+} |
26438 |
-+ |
26439 |
-+/* |
26440 |
-+ * Returns: |
26441 |
-+ * 1 in case all the requested effective capabilities are set. |
26442 |
-+ * 0 in case we do not have the requested capabilities. This value |
26443 |
-+ * will be used to abort tests with TEST_SKIP |
26444 |
-+ * Negative errno on failure. |
26445 |
-+ * |
26446 |
-+ * Terminate args with a negative value. |
26447 |
-+ */ |
26448 |
-+int test_is_capable(int cap, ...) |
26449 |
-+{ |
26450 |
-+ int ret; |
26451 |
-+ va_list ap; |
26452 |
-+ cap_t caps; |
26453 |
-+ |
26454 |
-+ caps = cap_get_proc(); |
26455 |
-+ if (!caps) { |
26456 |
-+ ret = -errno; |
26457 |
-+ kdbus_printf("error cap_get_proc(): %d (%m)\n", ret); |
26458 |
-+ return ret; |
26459 |
-+ } |
26460 |
-+ |
26461 |
-+ ret = do_cap_get_flag(caps, (cap_value_t)cap); |
26462 |
-+ if (ret <= 0) |
26463 |
-+ goto out; |
26464 |
-+ |
26465 |
-+ va_start(ap, cap); |
26466 |
-+ while ((cap = va_arg(ap, int)) > 0) { |
26467 |
-+ ret = do_cap_get_flag(caps, (cap_value_t)cap); |
26468 |
-+ if (ret <= 0) |
26469 |
-+ break; |
26470 |
-+ } |
26471 |
-+ va_end(ap); |
26472 |
-+ |
26473 |
-+out: |
26474 |
-+ cap_free(caps); |
26475 |
-+ return ret; |
26476 |
-+} |
26477 |
-+ |
26478 |
-+int config_user_ns_is_enabled(void) |
26479 |
-+{ |
26480 |
-+ return (access("/proc/self/uid_map", F_OK) == 0); |
26481 |
-+} |
26482 |
-+ |
26483 |
-+int config_auditsyscall_is_enabled(void) |
26484 |
-+{ |
26485 |
-+ return (access("/proc/self/loginuid", F_OK) == 0); |
26486 |
-+} |
26487 |
-+ |
26488 |
-+int config_cgroups_is_enabled(void) |
26489 |
-+{ |
26490 |
-+ return (access("/proc/self/cgroup", F_OK) == 0); |
26491 |
-+} |
26492 |
-+ |
26493 |
-+int config_security_is_enabled(void) |
26494 |
-+{ |
26495 |
-+ int fd; |
26496 |
-+ int ret; |
26497 |
-+ char buf[128]; |
26498 |
-+ |
26499 |
-+ /* CONFIG_SECURITY is disabled */ |
26500 |
-+ if (access("/proc/self/attr/current", F_OK) != 0) |
26501 |
-+ return 0; |
26502 |
-+ |
26503 |
-+ /* |
26504 |
-+ * Now only if read() fails with -EINVAL then we assume |
26505 |
-+ * that SECLABEL and LSM are disabled |
26506 |
-+ */ |
26507 |
-+ fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC); |
26508 |
-+ if (fd < 0) |
26509 |
-+ return 1; |
26510 |
-+ |
26511 |
-+ ret = read(fd, buf, sizeof(buf)); |
26512 |
-+ if (ret == -1 && errno == EINVAL) |
26513 |
-+ ret = 0; |
26514 |
-+ else |
26515 |
-+ ret = 1; |
26516 |
-+ |
26517 |
-+ close(fd); |
26518 |
-+ |
26519 |
-+ return ret; |
26520 |
-+} |
26521 |
-diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h |
26522 |
-new file mode 100644 |
26523 |
-index 0000000..e1e18b9 |
26524 |
---- /dev/null |
26525 |
-+++ b/tools/testing/selftests/kdbus/kdbus-util.h |
26526 |
-@@ -0,0 +1,218 @@ |
26527 |
-+/* |
26528 |
-+ * Copyright (C) 2013-2015 Kay Sievers |
26529 |
-+ * Copyright (C) 2013-2015 Daniel Mack |
26530 |
-+ * |
26531 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
26532 |
-+ * the terms of the GNU Lesser General Public License as published by the |
26533 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
26534 |
-+ * your option) any later version. |
26535 |
-+ */ |
26536 |
-+ |
26537 |
-+#pragma once |
26538 |
-+ |
26539 |
-+#define BIT(X) (1 << (X)) |
26540 |
-+ |
26541 |
-+#include <time.h> |
26542 |
-+#include <stdbool.h> |
26543 |
-+#include <linux/kdbus.h> |
26544 |
-+ |
26545 |
-+#define _STRINGIFY(x) #x |
26546 |
-+#define STRINGIFY(x) _STRINGIFY(x) |
26547 |
-+#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) |
26548 |
-+ |
26549 |
-+#define KDBUS_PTR(addr) ((void *)(uintptr_t)(addr)) |
26550 |
-+ |
26551 |
-+#define KDBUS_ALIGN8(l) (((l) + 7) & ~7) |
26552 |
-+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) |
26553 |
-+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) |
26554 |
-+ |
26555 |
-+#define KDBUS_ITEM_NEXT(item) \ |
26556 |
-+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) |
26557 |
-+#define KDBUS_ITEM_FOREACH(item, head, first) \ |
26558 |
-+ for ((item) = (head)->first; \ |
26559 |
-+ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ |
26560 |
-+ ((uint8_t *)(item) >= (uint8_t *)(head)); \ |
26561 |
-+ (item) = KDBUS_ITEM_NEXT(item)) |
26562 |
-+#define KDBUS_FOREACH(iter, first, _size) \ |
26563 |
-+ for ((iter) = (first); \ |
26564 |
-+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ |
26565 |
-+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \ |
26566 |
-+ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size))) |
26567 |
-+ |
26568 |
-+#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL)) |
26569 |
-+ |
26570 |
-+/* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */ |
26571 |
-+#define KDBUS_ATTACH_ITEMS_TYPE_SUM \ |
26572 |
-+ ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \ |
26573 |
-+ ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2) + \ |
26574 |
-+ (_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR)) |
26575 |
-+ |
26576 |
-+#define POOL_SIZE (16 * 1024LU * 1024LU) |
26577 |
-+ |
26578 |
-+#define UNPRIV_UID 65534 |
26579 |
-+#define UNPRIV_GID 65534 |
26580 |
-+ |
26581 |
-+/* Dump as user of process, useful for user namespace testing */ |
26582 |
-+#define SUID_DUMP_USER 1 |
26583 |
-+ |
26584 |
-+extern int kdbus_util_verbose; |
26585 |
-+ |
26586 |
-+#define kdbus_printf(X...) \ |
26587 |
-+ if (kdbus_util_verbose) \ |
26588 |
-+ printf(X) |
26589 |
-+ |
26590 |
-+#define RUN_UNPRIVILEGED(child_uid, child_gid, _child_, _parent_) ({ \ |
26591 |
-+ pid_t pid, rpid; \ |
26592 |
-+ int ret; \ |
26593 |
-+ \ |
26594 |
-+ pid = fork(); \ |
26595 |
-+ if (pid == 0) { \ |
26596 |
-+ ret = drop_privileges(child_uid, child_gid); \ |
26597 |
-+ ASSERT_EXIT_VAL(ret == 0, ret); \ |
26598 |
-+ \ |
26599 |
-+ _child_; \ |
26600 |
-+ _exit(0); \ |
26601 |
-+ } else if (pid > 0) { \ |
26602 |
-+ _parent_; \ |
26603 |
-+ rpid = waitpid(pid, &ret, 0); \ |
26604 |
-+ ASSERT_RETURN(rpid == pid); \ |
26605 |
-+ ASSERT_RETURN(WIFEXITED(ret)); \ |
26606 |
-+ ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ |
26607 |
-+ ret = TEST_OK; \ |
26608 |
-+ } else { \ |
26609 |
-+ ret = pid; \ |
26610 |
-+ } \ |
26611 |
-+ \ |
26612 |
-+ ret; \ |
26613 |
-+ }) |
26614 |
-+ |
26615 |
-+#define RUN_UNPRIVILEGED_CONN(_var_, _bus_, _code_) \ |
26616 |
-+ RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ \ |
26617 |
-+ struct kdbus_conn *_var_; \ |
26618 |
-+ _var_ = kdbus_hello(_bus_, 0, NULL, 0); \ |
26619 |
-+ ASSERT_EXIT(_var_); \ |
26620 |
-+ _code_; \ |
26621 |
-+ kdbus_conn_free(_var_); \ |
26622 |
-+ }), ({ 0; })) |
26623 |
-+ |
26624 |
-+#define RUN_CLONE_CHILD(clone_ret, flags, _setup_, _child_body_, \ |
26625 |
-+ _parent_setup_, _parent_body_) ({ \ |
26626 |
-+ pid_t pid, rpid; \ |
26627 |
-+ int ret; \ |
26628 |
-+ int efd = -1; \ |
26629 |
-+ \ |
26630 |
-+ _setup_; \ |
26631 |
-+ efd = eventfd(0, EFD_CLOEXEC); \ |
26632 |
-+ ASSERT_RETURN(efd >= 0); \ |
26633 |
-+ *(clone_ret) = 0; \ |
26634 |
-+ pid = syscall(__NR_clone, flags, NULL); \ |
26635 |
-+ if (pid == 0) { \ |
26636 |
-+ eventfd_t event_status = 0; \ |
26637 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); \ |
26638 |
-+ ASSERT_EXIT(ret == 0); \ |
26639 |
-+ ret = eventfd_read(efd, &event_status); \ |
26640 |
-+ if (ret < 0 || event_status != 1) { \ |
26641 |
-+ kdbus_printf("error eventfd_read()\n"); \ |
26642 |
-+ _exit(EXIT_FAILURE); \ |
26643 |
-+ } \ |
26644 |
-+ _child_body_; \ |
26645 |
-+ _exit(0); \ |
26646 |
-+ } else if (pid > 0) { \ |
26647 |
-+ _parent_setup_; \ |
26648 |
-+ ret = eventfd_write(efd, 1); \ |
26649 |
-+ ASSERT_RETURN(ret >= 0); \ |
26650 |
-+ _parent_body_; \ |
26651 |
-+ rpid = waitpid(pid, &ret, 0); \ |
26652 |
-+ ASSERT_RETURN(rpid == pid); \ |
26653 |
-+ ASSERT_RETURN(WIFEXITED(ret)); \ |
26654 |
-+ ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ |
26655 |
-+ ret = TEST_OK; \ |
26656 |
-+ } else { \ |
26657 |
-+ ret = -errno; \ |
26658 |
-+ *(clone_ret) = -errno; \ |
26659 |
-+ } \ |
26660 |
-+ close(efd); \ |
26661 |
-+ ret; \ |
26662 |
-+}) |
26663 |
-+ |
26664 |
-+/* Enums for parent if it should drop privs or not */ |
26665 |
-+enum kdbus_drop_parent { |
26666 |
-+ DO_NOT_DROP, |
26667 |
-+ DROP_SAME_UNPRIV, |
26668 |
-+ DROP_OTHER_UNPRIV, |
26669 |
-+}; |
26670 |
-+ |
26671 |
-+struct kdbus_conn { |
26672 |
-+ int fd; |
26673 |
-+ uint64_t id; |
26674 |
-+ unsigned char *buf; |
26675 |
-+}; |
26676 |
-+ |
26677 |
-+int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask); |
26678 |
-+int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask); |
26679 |
-+ |
26680 |
-+int sys_memfd_create(const char *name, __u64 size); |
26681 |
-+int sys_memfd_seal_set(int fd); |
26682 |
-+off_t sys_memfd_get_size(int fd, off_t *size); |
26683 |
-+ |
26684 |
-+int kdbus_list(struct kdbus_conn *conn, uint64_t flags); |
26685 |
-+int kdbus_name_release(struct kdbus_conn *conn, const char *name); |
26686 |
-+int kdbus_name_acquire(struct kdbus_conn *conn, const char *name, |
26687 |
-+ uint64_t *flags); |
26688 |
-+void kdbus_msg_free(struct kdbus_msg *msg); |
26689 |
-+int kdbus_msg_recv(struct kdbus_conn *conn, |
26690 |
-+ struct kdbus_msg **msg, uint64_t *offset); |
26691 |
-+int kdbus_msg_recv_poll(struct kdbus_conn *conn, int timeout_ms, |
26692 |
-+ struct kdbus_msg **msg_out, uint64_t *offset); |
26693 |
-+int kdbus_free(const struct kdbus_conn *conn, uint64_t offset); |
26694 |
-+int kdbus_msg_dump(const struct kdbus_conn *conn, |
26695 |
-+ const struct kdbus_msg *msg); |
26696 |
-+int kdbus_create_bus(int control_fd, const char *name, |
26697 |
-+ uint64_t owner_meta, char **path); |
26698 |
-+int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, |
26699 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
26700 |
-+ int64_t priority, uint64_t dst_id); |
26701 |
-+int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, |
26702 |
-+ uint64_t cookie, uint64_t flags, uint64_t timeout, |
26703 |
-+ int64_t priority, uint64_t dst_id, int cancel_fd); |
26704 |
-+int kdbus_msg_send_reply(const struct kdbus_conn *conn, |
26705 |
-+ uint64_t reply_cookie, |
26706 |
-+ uint64_t dst_id); |
26707 |
-+struct kdbus_conn *kdbus_hello(const char *path, uint64_t hello_flags, |
26708 |
-+ const struct kdbus_item *item, |
26709 |
-+ size_t item_size); |
26710 |
-+struct kdbus_conn *kdbus_hello_registrar(const char *path, const char *name, |
26711 |
-+ const struct kdbus_policy_access *access, |
26712 |
-+ size_t num_access, uint64_t flags); |
26713 |
-+struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, |
26714 |
-+ const struct kdbus_policy_access *access, |
26715 |
-+ size_t num_access); |
26716 |
-+bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type); |
26717 |
-+int kdbus_bus_creator_info(struct kdbus_conn *conn, |
26718 |
-+ uint64_t flags, |
26719 |
-+ uint64_t *offset); |
26720 |
-+int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, |
26721 |
-+ const char *name, uint64_t flags, uint64_t *offset); |
26722 |
-+void kdbus_conn_free(struct kdbus_conn *conn); |
26723 |
-+int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, |
26724 |
-+ uint64_t attach_flags_send, |
26725 |
-+ uint64_t attach_flags_recv); |
26726 |
-+int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, |
26727 |
-+ const struct kdbus_policy_access *access, |
26728 |
-+ size_t num_access); |
26729 |
-+ |
26730 |
-+int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, |
26731 |
-+ uint64_t type, uint64_t id); |
26732 |
-+int kdbus_add_match_empty(struct kdbus_conn *conn); |
26733 |
-+ |
26734 |
-+int all_uids_gids_are_mapped(void); |
26735 |
-+int drop_privileges(uid_t uid, gid_t gid); |
26736 |
-+uint64_t now(clockid_t clock); |
26737 |
-+char *unique_name(const char *prefix); |
26738 |
-+ |
26739 |
-+int userns_map_uid_gid(pid_t pid, const char *map_uid, const char *map_gid); |
26740 |
-+int test_is_capable(int cap, ...); |
26741 |
-+int config_user_ns_is_enabled(void); |
26742 |
-+int config_auditsyscall_is_enabled(void); |
26743 |
-+int config_cgroups_is_enabled(void); |
26744 |
-+int config_security_is_enabled(void); |
26745 |
-diff --git a/tools/testing/selftests/kdbus/test-activator.c b/tools/testing/selftests/kdbus/test-activator.c |
26746 |
-new file mode 100644 |
26747 |
-index 0000000..3d1b763 |
26748 |
---- /dev/null |
26749 |
-+++ b/tools/testing/selftests/kdbus/test-activator.c |
26750 |
-@@ -0,0 +1,318 @@ |
26751 |
-+#include <stdio.h> |
26752 |
-+#include <string.h> |
26753 |
-+#include <time.h> |
26754 |
-+#include <fcntl.h> |
26755 |
-+#include <stdlib.h> |
26756 |
-+#include <stdbool.h> |
26757 |
-+#include <stddef.h> |
26758 |
-+#include <unistd.h> |
26759 |
-+#include <stdint.h> |
26760 |
-+#include <errno.h> |
26761 |
-+#include <assert.h> |
26762 |
-+#include <poll.h> |
26763 |
-+#include <sys/capability.h> |
26764 |
-+#include <sys/types.h> |
26765 |
-+#include <sys/wait.h> |
26766 |
-+ |
26767 |
-+#include "kdbus-test.h" |
26768 |
-+#include "kdbus-util.h" |
26769 |
-+#include "kdbus-enum.h" |
26770 |
-+ |
26771 |
-+static int kdbus_starter_poll(struct kdbus_conn *conn) |
26772 |
-+{ |
26773 |
-+ int ret; |
26774 |
-+ struct pollfd fd; |
26775 |
-+ |
26776 |
-+ fd.fd = conn->fd; |
26777 |
-+ fd.events = POLLIN | POLLPRI | POLLHUP; |
26778 |
-+ fd.revents = 0; |
26779 |
-+ |
26780 |
-+ ret = poll(&fd, 1, 100); |
26781 |
-+ if (ret == 0) |
26782 |
-+ return -ETIMEDOUT; |
26783 |
-+ else if (ret > 0) { |
26784 |
-+ if (fd.revents & POLLIN) |
26785 |
-+ return 0; |
26786 |
-+ |
26787 |
-+ if (fd.revents & (POLLHUP | POLLERR)) |
26788 |
-+ ret = -ECONNRESET; |
26789 |
-+ } |
26790 |
-+ |
26791 |
-+ return ret; |
26792 |
-+} |
26793 |
-+ |
26794 |
-+/* Ensure that kdbus activator logic is safe */ |
26795 |
-+static int kdbus_priv_activator(struct kdbus_test_env *env) |
26796 |
-+{ |
26797 |
-+ int ret; |
26798 |
-+ struct kdbus_msg *msg = NULL; |
26799 |
-+ uint64_t cookie = 0xdeadbeef; |
26800 |
-+ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
26801 |
-+ struct kdbus_conn *activator; |
26802 |
-+ struct kdbus_conn *service; |
26803 |
-+ struct kdbus_conn *client; |
26804 |
-+ struct kdbus_conn *holder; |
26805 |
-+ struct kdbus_policy_access *access; |
26806 |
-+ |
26807 |
-+ access = (struct kdbus_policy_access[]){ |
26808 |
-+ { |
26809 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
26810 |
-+ .id = getuid(), |
26811 |
-+ .access = KDBUS_POLICY_OWN, |
26812 |
-+ }, |
26813 |
-+ { |
26814 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
26815 |
-+ .id = getuid(), |
26816 |
-+ .access = KDBUS_POLICY_TALK, |
26817 |
-+ }, |
26818 |
-+ }; |
26819 |
-+ |
26820 |
-+ activator = kdbus_hello_activator(env->buspath, "foo.priv.activator", |
26821 |
-+ access, 2); |
26822 |
-+ ASSERT_RETURN(activator); |
26823 |
-+ |
26824 |
-+ service = kdbus_hello(env->buspath, 0, NULL, 0); |
26825 |
-+ ASSERT_RETURN(service); |
26826 |
-+ |
26827 |
-+ client = kdbus_hello(env->buspath, 0, NULL, 0); |
26828 |
-+ ASSERT_RETURN(client); |
26829 |
-+ |
26830 |
-+ /* |
26831 |
-+ * Make sure that other users can't TALK to the activator |
26832 |
-+ */ |
26833 |
-+ |
26834 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26835 |
-+ /* Try to talk using the ID */ |
26836 |
-+ ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0, |
26837 |
-+ 0, activator->id); |
26838 |
-+ ASSERT_EXIT(ret == -ENXIO); |
26839 |
-+ |
26840 |
-+ /* Try to talk to the name */ |
26841 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26842 |
-+ 0xdeadbeef, 0, 0, 0, |
26843 |
-+ KDBUS_DST_ID_NAME); |
26844 |
-+ ASSERT_EXIT(ret == -EPERM); |
26845 |
-+ })); |
26846 |
-+ ASSERT_RETURN(ret >= 0); |
26847 |
-+ |
26848 |
-+ /* |
26849 |
-+ * Make sure that we did not receive anything, so the |
26850 |
-+ * service will not be started automatically |
26851 |
-+ */ |
26852 |
-+ |
26853 |
-+ ret = kdbus_starter_poll(activator); |
26854 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
26855 |
-+ |
26856 |
-+ /* |
26857 |
-+ * Now try to emulate the starter/service logic and |
26858 |
-+ * acquire the name. |
26859 |
-+ */ |
26860 |
-+ |
26861 |
-+ cookie++; |
26862 |
-+ ret = kdbus_msg_send(service, "foo.priv.activator", cookie, |
26863 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26864 |
-+ ASSERT_RETURN(ret == 0); |
26865 |
-+ |
26866 |
-+ ret = kdbus_starter_poll(activator); |
26867 |
-+ ASSERT_RETURN(ret == 0); |
26868 |
-+ |
26869 |
-+ /* Policies are still checked, access denied */ |
26870 |
-+ |
26871 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26872 |
-+ ret = kdbus_name_acquire(unpriv, "foo.priv.activator", |
26873 |
-+ &flags); |
26874 |
-+ ASSERT_RETURN(ret == -EPERM); |
26875 |
-+ })); |
26876 |
-+ ASSERT_RETURN(ret >= 0); |
26877 |
-+ |
26878 |
-+ ret = kdbus_name_acquire(service, "foo.priv.activator", |
26879 |
-+ &flags); |
26880 |
-+ ASSERT_RETURN(ret == 0); |
26881 |
-+ |
26882 |
-+ /* We read our previous starter message */ |
26883 |
-+ |
26884 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26885 |
-+ ASSERT_RETURN(ret == 0); |
26886 |
-+ |
26887 |
-+ /* Try to talk, we still fail */ |
26888 |
-+ |
26889 |
-+ cookie++; |
26890 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26891 |
-+ /* Try to talk to the name */ |
26892 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26893 |
-+ cookie, 0, 0, 0, |
26894 |
-+ KDBUS_DST_ID_NAME); |
26895 |
-+ ASSERT_EXIT(ret == -EPERM); |
26896 |
-+ })); |
26897 |
-+ ASSERT_RETURN(ret >= 0); |
26898 |
-+ |
26899 |
-+ /* Still nothing to read */ |
26900 |
-+ |
26901 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26902 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
26903 |
-+ |
26904 |
-+ /* We receive every thing now */ |
26905 |
-+ |
26906 |
-+ cookie++; |
26907 |
-+ ret = kdbus_msg_send(client, "foo.priv.activator", cookie, |
26908 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26909 |
-+ ASSERT_RETURN(ret == 0); |
26910 |
-+ ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); |
26911 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
26912 |
-+ |
26913 |
-+ kdbus_msg_free(msg); |
26914 |
-+ |
26915 |
-+ /* Policies default to deny TALK now */ |
26916 |
-+ kdbus_conn_free(activator); |
26917 |
-+ |
26918 |
-+ cookie++; |
26919 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26920 |
-+ /* Try to talk to the name */ |
26921 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26922 |
-+ cookie, 0, 0, 0, |
26923 |
-+ KDBUS_DST_ID_NAME); |
26924 |
-+ ASSERT_EXIT(ret == -EPERM); |
26925 |
-+ })); |
26926 |
-+ ASSERT_RETURN(ret >= 0); |
26927 |
-+ |
26928 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26929 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
26930 |
-+ |
26931 |
-+ /* Same user is able to TALK */ |
26932 |
-+ cookie++; |
26933 |
-+ ret = kdbus_msg_send(client, "foo.priv.activator", cookie, |
26934 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
26935 |
-+ ASSERT_RETURN(ret == 0); |
26936 |
-+ ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); |
26937 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
26938 |
-+ |
26939 |
-+ kdbus_msg_free(msg); |
26940 |
-+ |
26941 |
-+ access = (struct kdbus_policy_access []){ |
26942 |
-+ { |
26943 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
26944 |
-+ .id = getuid(), |
26945 |
-+ .access = KDBUS_POLICY_TALK, |
26946 |
-+ }, |
26947 |
-+ }; |
26948 |
-+ |
26949 |
-+ holder = kdbus_hello_registrar(env->buspath, "foo.priv.activator", |
26950 |
-+ access, 1, KDBUS_HELLO_POLICY_HOLDER); |
26951 |
-+ ASSERT_RETURN(holder); |
26952 |
-+ |
26953 |
-+ /* Now we are able to TALK to the name */ |
26954 |
-+ |
26955 |
-+ cookie++; |
26956 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26957 |
-+ /* Try to talk to the name */ |
26958 |
-+ ret = kdbus_msg_send(unpriv, "foo.priv.activator", |
26959 |
-+ cookie, 0, 0, 0, |
26960 |
-+ KDBUS_DST_ID_NAME); |
26961 |
-+ ASSERT_EXIT(ret == 0); |
26962 |
-+ })); |
26963 |
-+ ASSERT_RETURN(ret >= 0); |
26964 |
-+ |
26965 |
-+ ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); |
26966 |
-+ ASSERT_RETURN(ret == 0); |
26967 |
-+ |
26968 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
26969 |
-+ ret = kdbus_name_acquire(unpriv, "foo.priv.activator", |
26970 |
-+ &flags); |
26971 |
-+ ASSERT_RETURN(ret == -EPERM); |
26972 |
-+ })); |
26973 |
-+ ASSERT_RETURN(ret >= 0); |
26974 |
-+ |
26975 |
-+ kdbus_conn_free(service); |
26976 |
-+ kdbus_conn_free(client); |
26977 |
-+ kdbus_conn_free(holder); |
26978 |
-+ |
26979 |
-+ return 0; |
26980 |
-+} |
26981 |
-+ |
26982 |
-+int kdbus_test_activator(struct kdbus_test_env *env) |
26983 |
-+{ |
26984 |
-+ int ret; |
26985 |
-+ struct kdbus_conn *activator; |
26986 |
-+ struct pollfd fds[2]; |
26987 |
-+ bool activator_done = false; |
26988 |
-+ struct kdbus_policy_access access[2]; |
26989 |
-+ |
26990 |
-+ access[0].type = KDBUS_POLICY_ACCESS_USER; |
26991 |
-+ access[0].id = getuid(); |
26992 |
-+ access[0].access = KDBUS_POLICY_OWN; |
26993 |
-+ |
26994 |
-+ access[1].type = KDBUS_POLICY_ACCESS_WORLD; |
26995 |
-+ access[1].access = KDBUS_POLICY_TALK; |
26996 |
-+ |
26997 |
-+ activator = kdbus_hello_activator(env->buspath, "foo.test.activator", |
26998 |
-+ access, 2); |
26999 |
-+ ASSERT_RETURN(activator); |
27000 |
-+ |
27001 |
-+ ret = kdbus_add_match_empty(env->conn); |
27002 |
-+ ASSERT_RETURN(ret == 0); |
27003 |
-+ |
27004 |
-+ ret = kdbus_list(env->conn, KDBUS_LIST_NAMES | |
27005 |
-+ KDBUS_LIST_UNIQUE | |
27006 |
-+ KDBUS_LIST_ACTIVATORS | |
27007 |
-+ KDBUS_LIST_QUEUED); |
27008 |
-+ ASSERT_RETURN(ret == 0); |
27009 |
-+ |
27010 |
-+ ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef, |
27011 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
27012 |
-+ ASSERT_RETURN(ret == 0); |
27013 |
-+ |
27014 |
-+ fds[0].fd = activator->fd; |
27015 |
-+ fds[1].fd = env->conn->fd; |
27016 |
-+ |
27017 |
-+ kdbus_printf("-- entering poll loop ...\n"); |
27018 |
-+ |
27019 |
-+ for (;;) { |
27020 |
-+ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
27021 |
-+ |
27022 |
-+ for (i = 0; i < nfds; i++) { |
27023 |
-+ fds[i].events = POLLIN | POLLPRI; |
27024 |
-+ fds[i].revents = 0; |
27025 |
-+ } |
27026 |
-+ |
27027 |
-+ ret = poll(fds, nfds, 3000); |
27028 |
-+ ASSERT_RETURN(ret >= 0); |
27029 |
-+ |
27030 |
-+ ret = kdbus_list(env->conn, KDBUS_LIST_NAMES); |
27031 |
-+ ASSERT_RETURN(ret == 0); |
27032 |
-+ |
27033 |
-+ if ((fds[0].revents & POLLIN) && !activator_done) { |
27034 |
-+ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
27035 |
-+ |
27036 |
-+ kdbus_printf("Starter was called back!\n"); |
27037 |
-+ |
27038 |
-+ ret = kdbus_name_acquire(env->conn, |
27039 |
-+ "foo.test.activator", &flags); |
27040 |
-+ ASSERT_RETURN(ret == 0); |
27041 |
-+ |
27042 |
-+ activator_done = true; |
27043 |
-+ } |
27044 |
-+ |
27045 |
-+ if (fds[1].revents & POLLIN) { |
27046 |
-+ kdbus_msg_recv(env->conn, NULL, NULL); |
27047 |
-+ break; |
27048 |
-+ } |
27049 |
-+ } |
27050 |
-+ |
27051 |
-+ /* Check if all uids/gids are mapped */ |
27052 |
-+ if (!all_uids_gids_are_mapped()) |
27053 |
-+ return TEST_SKIP; |
27054 |
-+ |
27055 |
-+ /* Check now capabilities, so we run the previous tests */ |
27056 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
27057 |
-+ ASSERT_RETURN(ret >= 0); |
27058 |
-+ |
27059 |
-+ if (!ret) |
27060 |
-+ return TEST_SKIP; |
27061 |
-+ |
27062 |
-+ ret = kdbus_priv_activator(env); |
27063 |
-+ ASSERT_RETURN(ret == 0); |
27064 |
-+ |
27065 |
-+ kdbus_conn_free(activator); |
27066 |
-+ |
27067 |
-+ return TEST_OK; |
27068 |
-+} |
27069 |
-diff --git a/tools/testing/selftests/kdbus/test-benchmark.c b/tools/testing/selftests/kdbus/test-benchmark.c |
27070 |
-new file mode 100644 |
27071 |
-index 0000000..8a9744b |
27072 |
---- /dev/null |
27073 |
-+++ b/tools/testing/selftests/kdbus/test-benchmark.c |
27074 |
-@@ -0,0 +1,451 @@ |
27075 |
-+#include <stdio.h> |
27076 |
-+#include <string.h> |
27077 |
-+#include <time.h> |
27078 |
-+#include <fcntl.h> |
27079 |
-+#include <locale.h> |
27080 |
-+#include <stdlib.h> |
27081 |
-+#include <stddef.h> |
27082 |
-+#include <unistd.h> |
27083 |
-+#include <stdint.h> |
27084 |
-+#include <stdbool.h> |
27085 |
-+#include <errno.h> |
27086 |
-+#include <assert.h> |
27087 |
-+#include <poll.h> |
27088 |
-+#include <sys/time.h> |
27089 |
-+#include <sys/mman.h> |
27090 |
-+#include <sys/socket.h> |
27091 |
-+#include <math.h> |
27092 |
-+ |
27093 |
-+#include "kdbus-api.h" |
27094 |
-+#include "kdbus-test.h" |
27095 |
-+#include "kdbus-util.h" |
27096 |
-+#include "kdbus-enum.h" |
27097 |
-+ |
27098 |
-+#define SERVICE_NAME "foo.bar.echo" |
27099 |
-+ |
27100 |
-+/* |
27101 |
-+ * To have a banchmark comparison with unix socket, set: |
27102 |
-+ * user_memfd = false; |
27103 |
-+ * compare_uds = true; |
27104 |
-+ * attach_none = true; do not attached metadata |
27105 |
-+ */ |
27106 |
-+ |
27107 |
-+static bool use_memfd = true; /* transmit memfd? */ |
27108 |
-+static bool compare_uds = false; /* unix-socket comparison? */ |
27109 |
-+static bool attach_none = false; /* clear attach-flags? */ |
27110 |
-+static char stress_payload[8192]; |
27111 |
-+ |
27112 |
-+struct stats { |
27113 |
-+ uint64_t count; |
27114 |
-+ uint64_t latency_acc; |
27115 |
-+ uint64_t latency_low; |
27116 |
-+ uint64_t latency_high; |
27117 |
-+ uint64_t latency_avg; |
27118 |
-+ uint64_t latency_ssquares; |
27119 |
-+}; |
27120 |
-+ |
27121 |
-+static struct stats stats; |
27122 |
-+ |
27123 |
-+static void reset_stats(void) |
27124 |
-+{ |
27125 |
-+ stats.count = 0; |
27126 |
-+ stats.latency_acc = 0; |
27127 |
-+ stats.latency_low = UINT64_MAX; |
27128 |
-+ stats.latency_high = 0; |
27129 |
-+ stats.latency_avg = 0; |
27130 |
-+ stats.latency_ssquares = 0; |
27131 |
-+} |
27132 |
-+ |
27133 |
-+static void dump_stats(bool is_uds) |
27134 |
-+{ |
27135 |
-+ if (stats.count > 0) { |
27136 |
-+ kdbus_printf("stats %s: %'llu packets processed, latency (nsecs) min/max/avg/dev %'7llu // %'7llu // %'7llu // %'7.f\n", |
27137 |
-+ is_uds ? " (UNIX)" : "(KDBUS)", |
27138 |
-+ (unsigned long long) stats.count, |
27139 |
-+ (unsigned long long) stats.latency_low, |
27140 |
-+ (unsigned long long) stats.latency_high, |
27141 |
-+ (unsigned long long) stats.latency_avg, |
27142 |
-+ sqrt(stats.latency_ssquares / stats.count)); |
27143 |
-+ } else { |
27144 |
-+ kdbus_printf("*** no packets received. bus stuck?\n"); |
27145 |
-+ } |
27146 |
-+} |
27147 |
-+ |
27148 |
-+static void add_stats(uint64_t prev) |
27149 |
-+{ |
27150 |
-+ uint64_t diff, latency_avg_prev; |
27151 |
-+ |
27152 |
-+ diff = now(CLOCK_THREAD_CPUTIME_ID) - prev; |
27153 |
-+ |
27154 |
-+ stats.count++; |
27155 |
-+ stats.latency_acc += diff; |
27156 |
-+ |
27157 |
-+ /* see Welford62 */ |
27158 |
-+ latency_avg_prev = stats.latency_avg; |
27159 |
-+ stats.latency_avg = stats.latency_acc / stats.count; |
27160 |
-+ stats.latency_ssquares += (diff - latency_avg_prev) * (diff - stats.latency_avg); |
27161 |
-+ |
27162 |
-+ if (stats.latency_low > diff) |
27163 |
-+ stats.latency_low = diff; |
27164 |
-+ |
27165 |
-+ if (stats.latency_high < diff) |
27166 |
-+ stats.latency_high = diff; |
27167 |
-+} |
27168 |
-+ |
27169 |
-+static int setup_simple_kdbus_msg(struct kdbus_conn *conn, |
27170 |
-+ uint64_t dst_id, |
27171 |
-+ struct kdbus_msg **msg_out) |
27172 |
-+{ |
27173 |
-+ struct kdbus_msg *msg; |
27174 |
-+ struct kdbus_item *item; |
27175 |
-+ uint64_t size; |
27176 |
-+ |
27177 |
-+ size = sizeof(struct kdbus_msg); |
27178 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
27179 |
-+ |
27180 |
-+ msg = malloc(size); |
27181 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
27182 |
-+ |
27183 |
-+ memset(msg, 0, size); |
27184 |
-+ msg->size = size; |
27185 |
-+ msg->src_id = conn->id; |
27186 |
-+ msg->dst_id = dst_id; |
27187 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
27188 |
-+ |
27189 |
-+ item = msg->items; |
27190 |
-+ |
27191 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
27192 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
27193 |
-+ item->vec.address = (uintptr_t) stress_payload; |
27194 |
-+ item->vec.size = sizeof(stress_payload); |
27195 |
-+ item = KDBUS_ITEM_NEXT(item); |
27196 |
-+ |
27197 |
-+ *msg_out = msg; |
27198 |
-+ |
27199 |
-+ return 0; |
27200 |
-+} |
27201 |
-+ |
27202 |
-+static int setup_memfd_kdbus_msg(struct kdbus_conn *conn, |
27203 |
-+ uint64_t dst_id, |
27204 |
-+ off_t *memfd_item_offset, |
27205 |
-+ struct kdbus_msg **msg_out) |
27206 |
-+{ |
27207 |
-+ struct kdbus_msg *msg; |
27208 |
-+ struct kdbus_item *item; |
27209 |
-+ uint64_t size; |
27210 |
-+ |
27211 |
-+ size = sizeof(struct kdbus_msg); |
27212 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
27213 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
27214 |
-+ |
27215 |
-+ msg = malloc(size); |
27216 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
27217 |
-+ |
27218 |
-+ memset(msg, 0, size); |
27219 |
-+ msg->size = size; |
27220 |
-+ msg->src_id = conn->id; |
27221 |
-+ msg->dst_id = dst_id; |
27222 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
27223 |
-+ |
27224 |
-+ item = msg->items; |
27225 |
-+ |
27226 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
27227 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
27228 |
-+ item->vec.address = (uintptr_t) stress_payload; |
27229 |
-+ item->vec.size = sizeof(stress_payload); |
27230 |
-+ item = KDBUS_ITEM_NEXT(item); |
27231 |
-+ |
27232 |
-+ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
27233 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd); |
27234 |
-+ item->memfd.size = sizeof(uint64_t); |
27235 |
-+ |
27236 |
-+ *memfd_item_offset = (unsigned char *)item - (unsigned char *)msg; |
27237 |
-+ *msg_out = msg; |
27238 |
-+ |
27239 |
-+ return 0; |
27240 |
-+} |
27241 |
-+ |
27242 |
-+static int |
27243 |
-+send_echo_request(struct kdbus_conn *conn, uint64_t dst_id, |
27244 |
-+ void *kdbus_msg, off_t memfd_item_offset) |
27245 |
-+{ |
27246 |
-+ struct kdbus_cmd_send cmd = {}; |
27247 |
-+ int memfd = -1; |
27248 |
-+ int ret; |
27249 |
-+ |
27250 |
-+ if (use_memfd) { |
27251 |
-+ uint64_t now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27252 |
-+ struct kdbus_item *item = memfd_item_offset + kdbus_msg; |
27253 |
-+ memfd = sys_memfd_create("memfd-name", 0); |
27254 |
-+ ASSERT_RETURN_VAL(memfd >= 0, memfd); |
27255 |
-+ |
27256 |
-+ ret = write(memfd, &now_ns, sizeof(now_ns)); |
27257 |
-+ ASSERT_RETURN_VAL(ret == sizeof(now_ns), -EAGAIN); |
27258 |
-+ |
27259 |
-+ ret = sys_memfd_seal_set(memfd); |
27260 |
-+ ASSERT_RETURN_VAL(ret == 0, -errno); |
27261 |
-+ |
27262 |
-+ item->memfd.fd = memfd; |
27263 |
-+ } |
27264 |
-+ |
27265 |
-+ cmd.size = sizeof(cmd); |
27266 |
-+ cmd.msg_address = (uintptr_t)kdbus_msg; |
27267 |
-+ |
27268 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
27269 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
27270 |
-+ |
27271 |
-+ close(memfd); |
27272 |
-+ |
27273 |
-+ return 0; |
27274 |
-+} |
27275 |
-+ |
27276 |
-+static int |
27277 |
-+handle_echo_reply(struct kdbus_conn *conn, uint64_t send_ns) |
27278 |
-+{ |
27279 |
-+ int ret; |
27280 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
27281 |
-+ struct kdbus_msg *msg; |
27282 |
-+ const struct kdbus_item *item; |
27283 |
-+ bool has_memfd = false; |
27284 |
-+ |
27285 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
27286 |
-+ if (ret == -EAGAIN) |
27287 |
-+ return ret; |
27288 |
-+ |
27289 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
27290 |
-+ |
27291 |
-+ if (!use_memfd) |
27292 |
-+ goto out; |
27293 |
-+ |
27294 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
27295 |
-+ |
27296 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
27297 |
-+ switch (item->type) { |
27298 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: { |
27299 |
-+ char *buf; |
27300 |
-+ |
27301 |
-+ buf = mmap(NULL, item->memfd.size, PROT_READ, |
27302 |
-+ MAP_PRIVATE, item->memfd.fd, 0); |
27303 |
-+ ASSERT_RETURN_VAL(buf != MAP_FAILED, -EINVAL); |
27304 |
-+ ASSERT_RETURN_VAL(item->memfd.size == sizeof(uint64_t), |
27305 |
-+ -EINVAL); |
27306 |
-+ |
27307 |
-+ add_stats(*(uint64_t*)buf); |
27308 |
-+ munmap(buf, item->memfd.size); |
27309 |
-+ close(item->memfd.fd); |
27310 |
-+ has_memfd = true; |
27311 |
-+ break; |
27312 |
-+ } |
27313 |
-+ |
27314 |
-+ case KDBUS_ITEM_PAYLOAD_OFF: |
27315 |
-+ /* ignore */ |
27316 |
-+ break; |
27317 |
-+ } |
27318 |
-+ } |
27319 |
-+ |
27320 |
-+out: |
27321 |
-+ if (!has_memfd) |
27322 |
-+ add_stats(send_ns); |
27323 |
-+ |
27324 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
27325 |
-+ ASSERT_RETURN_VAL(ret == 0, -errno); |
27326 |
-+ |
27327 |
-+ return 0; |
27328 |
-+} |
27329 |
-+ |
27330 |
-+static int benchmark(struct kdbus_test_env *env) |
27331 |
-+{ |
27332 |
-+ static char buf[sizeof(stress_payload)]; |
27333 |
-+ struct kdbus_msg *kdbus_msg = NULL; |
27334 |
-+ off_t memfd_cached_offset = 0; |
27335 |
-+ int ret; |
27336 |
-+ struct kdbus_conn *conn_a, *conn_b; |
27337 |
-+ struct pollfd fds[2]; |
27338 |
-+ uint64_t start, send_ns, now_ns, diff; |
27339 |
-+ unsigned int i; |
27340 |
-+ int uds[2]; |
27341 |
-+ |
27342 |
-+ setlocale(LC_ALL, ""); |
27343 |
-+ |
27344 |
-+ for (i = 0; i < sizeof(stress_payload); i++) |
27345 |
-+ stress_payload[i] = i; |
27346 |
-+ |
27347 |
-+ /* setup kdbus pair */ |
27348 |
-+ |
27349 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
27350 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
27351 |
-+ ASSERT_RETURN(conn_a && conn_b); |
27352 |
-+ |
27353 |
-+ ret = kdbus_add_match_empty(conn_a); |
27354 |
-+ ASSERT_RETURN(ret == 0); |
27355 |
-+ |
27356 |
-+ ret = kdbus_add_match_empty(conn_b); |
27357 |
-+ ASSERT_RETURN(ret == 0); |
27358 |
-+ |
27359 |
-+ ret = kdbus_name_acquire(conn_a, SERVICE_NAME, NULL); |
27360 |
-+ ASSERT_RETURN(ret == 0); |
27361 |
-+ |
27362 |
-+ if (attach_none) { |
27363 |
-+ ret = kdbus_conn_update_attach_flags(conn_a, |
27364 |
-+ _KDBUS_ATTACH_ALL, |
27365 |
-+ 0); |
27366 |
-+ ASSERT_RETURN(ret == 0); |
27367 |
-+ } |
27368 |
-+ |
27369 |
-+ /* setup UDS pair */ |
27370 |
-+ |
27371 |
-+ ret = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, uds); |
27372 |
-+ ASSERT_RETURN(ret == 0); |
27373 |
-+ |
27374 |
-+ /* setup a kdbus msg now */ |
27375 |
-+ if (use_memfd) { |
27376 |
-+ ret = setup_memfd_kdbus_msg(conn_b, conn_a->id, |
27377 |
-+ &memfd_cached_offset, |
27378 |
-+ &kdbus_msg); |
27379 |
-+ ASSERT_RETURN(ret == 0); |
27380 |
-+ } else { |
27381 |
-+ ret = setup_simple_kdbus_msg(conn_b, conn_a->id, &kdbus_msg); |
27382 |
-+ ASSERT_RETURN(ret == 0); |
27383 |
-+ } |
27384 |
-+ |
27385 |
-+ /* start benchmark */ |
27386 |
-+ |
27387 |
-+ kdbus_printf("-- entering poll loop ...\n"); |
27388 |
-+ |
27389 |
-+ do { |
27390 |
-+ /* run kdbus benchmark */ |
27391 |
-+ fds[0].fd = conn_a->fd; |
27392 |
-+ fds[1].fd = conn_b->fd; |
27393 |
-+ |
27394 |
-+ /* cancel any pending message */ |
27395 |
-+ handle_echo_reply(conn_a, 0); |
27396 |
-+ |
27397 |
-+ start = now(CLOCK_THREAD_CPUTIME_ID); |
27398 |
-+ reset_stats(); |
27399 |
-+ |
27400 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27401 |
-+ ret = send_echo_request(conn_b, conn_a->id, |
27402 |
-+ kdbus_msg, memfd_cached_offset); |
27403 |
-+ ASSERT_RETURN(ret == 0); |
27404 |
-+ |
27405 |
-+ while (1) { |
27406 |
-+ unsigned int nfds = sizeof(fds) / sizeof(fds[0]); |
27407 |
-+ unsigned int i; |
27408 |
-+ |
27409 |
-+ for (i = 0; i < nfds; i++) { |
27410 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27411 |
-+ fds[i].revents = 0; |
27412 |
-+ } |
27413 |
-+ |
27414 |
-+ ret = poll(fds, nfds, 10); |
27415 |
-+ if (ret < 0) |
27416 |
-+ break; |
27417 |
-+ |
27418 |
-+ if (fds[0].revents & POLLIN) { |
27419 |
-+ ret = handle_echo_reply(conn_a, send_ns); |
27420 |
-+ ASSERT_RETURN(ret == 0); |
27421 |
-+ |
27422 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27423 |
-+ ret = send_echo_request(conn_b, conn_a->id, |
27424 |
-+ kdbus_msg, |
27425 |
-+ memfd_cached_offset); |
27426 |
-+ ASSERT_RETURN(ret == 0); |
27427 |
-+ } |
27428 |
-+ |
27429 |
-+ now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27430 |
-+ diff = now_ns - start; |
27431 |
-+ if (diff > 1000000000ULL) { |
27432 |
-+ start = now_ns; |
27433 |
-+ |
27434 |
-+ dump_stats(false); |
27435 |
-+ break; |
27436 |
-+ } |
27437 |
-+ } |
27438 |
-+ |
27439 |
-+ if (!compare_uds) |
27440 |
-+ continue; |
27441 |
-+ |
27442 |
-+ /* run unix-socket benchmark as comparison */ |
27443 |
-+ |
27444 |
-+ fds[0].fd = uds[0]; |
27445 |
-+ fds[1].fd = uds[1]; |
27446 |
-+ |
27447 |
-+ /* cancel any pendign message */ |
27448 |
-+ read(uds[1], buf, sizeof(buf)); |
27449 |
-+ |
27450 |
-+ start = now(CLOCK_THREAD_CPUTIME_ID); |
27451 |
-+ reset_stats(); |
27452 |
-+ |
27453 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27454 |
-+ ret = write(uds[0], stress_payload, sizeof(stress_payload)); |
27455 |
-+ ASSERT_RETURN(ret == sizeof(stress_payload)); |
27456 |
-+ |
27457 |
-+ while (1) { |
27458 |
-+ unsigned int nfds = sizeof(fds) / sizeof(fds[0]); |
27459 |
-+ unsigned int i; |
27460 |
-+ |
27461 |
-+ for (i = 0; i < nfds; i++) { |
27462 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27463 |
-+ fds[i].revents = 0; |
27464 |
-+ } |
27465 |
-+ |
27466 |
-+ ret = poll(fds, nfds, 10); |
27467 |
-+ if (ret < 0) |
27468 |
-+ break; |
27469 |
-+ |
27470 |
-+ if (fds[1].revents & POLLIN) { |
27471 |
-+ ret = read(uds[1], buf, sizeof(buf)); |
27472 |
-+ ASSERT_RETURN(ret == sizeof(buf)); |
27473 |
-+ |
27474 |
-+ add_stats(send_ns); |
27475 |
-+ |
27476 |
-+ send_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27477 |
-+ ret = write(uds[0], buf, sizeof(buf)); |
27478 |
-+ ASSERT_RETURN(ret == sizeof(buf)); |
27479 |
-+ } |
27480 |
-+ |
27481 |
-+ now_ns = now(CLOCK_THREAD_CPUTIME_ID); |
27482 |
-+ diff = now_ns - start; |
27483 |
-+ if (diff > 1000000000ULL) { |
27484 |
-+ start = now_ns; |
27485 |
-+ |
27486 |
-+ dump_stats(true); |
27487 |
-+ break; |
27488 |
-+ } |
27489 |
-+ } |
27490 |
-+ |
27491 |
-+ } while (kdbus_util_verbose); |
27492 |
-+ |
27493 |
-+ kdbus_printf("-- closing bus connections\n"); |
27494 |
-+ |
27495 |
-+ free(kdbus_msg); |
27496 |
-+ |
27497 |
-+ kdbus_conn_free(conn_a); |
27498 |
-+ kdbus_conn_free(conn_b); |
27499 |
-+ |
27500 |
-+ return (stats.count > 1) ? TEST_OK : TEST_ERR; |
27501 |
-+} |
27502 |
-+ |
27503 |
-+int kdbus_test_benchmark(struct kdbus_test_env *env) |
27504 |
-+{ |
27505 |
-+ use_memfd = true; |
27506 |
-+ attach_none = false; |
27507 |
-+ compare_uds = false; |
27508 |
-+ return benchmark(env); |
27509 |
-+} |
27510 |
-+ |
27511 |
-+int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env) |
27512 |
-+{ |
27513 |
-+ use_memfd = false; |
27514 |
-+ attach_none = false; |
27515 |
-+ compare_uds = false; |
27516 |
-+ return benchmark(env); |
27517 |
-+} |
27518 |
-+ |
27519 |
-+int kdbus_test_benchmark_uds(struct kdbus_test_env *env) |
27520 |
-+{ |
27521 |
-+ use_memfd = false; |
27522 |
-+ attach_none = true; |
27523 |
-+ compare_uds = true; |
27524 |
-+ return benchmark(env); |
27525 |
-+} |
27526 |
-diff --git a/tools/testing/selftests/kdbus/test-bus.c b/tools/testing/selftests/kdbus/test-bus.c |
27527 |
-new file mode 100644 |
27528 |
-index 0000000..762fb30 |
27529 |
---- /dev/null |
27530 |
-+++ b/tools/testing/selftests/kdbus/test-bus.c |
27531 |
-@@ -0,0 +1,175 @@ |
27532 |
-+#include <stdio.h> |
27533 |
-+#include <string.h> |
27534 |
-+#include <fcntl.h> |
27535 |
-+#include <stdlib.h> |
27536 |
-+#include <stddef.h> |
27537 |
-+#include <unistd.h> |
27538 |
-+#include <stdint.h> |
27539 |
-+#include <errno.h> |
27540 |
-+#include <assert.h> |
27541 |
-+#include <limits.h> |
27542 |
-+#include <sys/mman.h> |
27543 |
-+#include <stdbool.h> |
27544 |
-+ |
27545 |
-+#include "kdbus-api.h" |
27546 |
-+#include "kdbus-util.h" |
27547 |
-+#include "kdbus-enum.h" |
27548 |
-+#include "kdbus-test.h" |
27549 |
-+ |
27550 |
-+static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, |
27551 |
-+ uint64_t type) |
27552 |
-+{ |
27553 |
-+ struct kdbus_item *item; |
27554 |
-+ |
27555 |
-+ KDBUS_ITEM_FOREACH(item, info, items) |
27556 |
-+ if (item->type == type) |
27557 |
-+ return item; |
27558 |
-+ |
27559 |
-+ return NULL; |
27560 |
-+} |
27561 |
-+ |
27562 |
-+static int test_bus_creator_info(const char *bus_path) |
27563 |
-+{ |
27564 |
-+ int ret; |
27565 |
-+ uint64_t offset; |
27566 |
-+ struct kdbus_conn *conn; |
27567 |
-+ struct kdbus_info *info; |
27568 |
-+ struct kdbus_item *item; |
27569 |
-+ char *tmp, *busname; |
27570 |
-+ |
27571 |
-+ /* extract the bus-name from @bus_path */ |
27572 |
-+ tmp = strdup(bus_path); |
27573 |
-+ ASSERT_RETURN(tmp); |
27574 |
-+ busname = strrchr(tmp, '/'); |
27575 |
-+ ASSERT_RETURN(busname); |
27576 |
-+ *busname = 0; |
27577 |
-+ busname = strrchr(tmp, '/'); |
27578 |
-+ ASSERT_RETURN(busname); |
27579 |
-+ ++busname; |
27580 |
-+ |
27581 |
-+ conn = kdbus_hello(bus_path, 0, NULL, 0); |
27582 |
-+ ASSERT_RETURN(conn); |
27583 |
-+ |
27584 |
-+ ret = kdbus_bus_creator_info(conn, _KDBUS_ATTACH_ALL, &offset); |
27585 |
-+ ASSERT_RETURN(ret == 0); |
27586 |
-+ |
27587 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
27588 |
-+ |
27589 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_MAKE_NAME); |
27590 |
-+ ASSERT_RETURN(item); |
27591 |
-+ ASSERT_RETURN(!strcmp(item->str, busname)); |
27592 |
-+ |
27593 |
-+ ret = kdbus_free(conn, offset); |
27594 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
27595 |
-+ |
27596 |
-+ free(tmp); |
27597 |
-+ kdbus_conn_free(conn); |
27598 |
-+ return 0; |
27599 |
-+} |
27600 |
-+ |
27601 |
-+int kdbus_test_bus_make(struct kdbus_test_env *env) |
27602 |
-+{ |
27603 |
-+ struct { |
27604 |
-+ struct kdbus_cmd cmd; |
27605 |
-+ |
27606 |
-+ /* bloom size item */ |
27607 |
-+ struct { |
27608 |
-+ uint64_t size; |
27609 |
-+ uint64_t type; |
27610 |
-+ struct kdbus_bloom_parameter bloom; |
27611 |
-+ } bs; |
27612 |
-+ |
27613 |
-+ /* name item */ |
27614 |
-+ uint64_t n_size; |
27615 |
-+ uint64_t n_type; |
27616 |
-+ char name[64]; |
27617 |
-+ } bus_make; |
27618 |
-+ char s[PATH_MAX], *name; |
27619 |
-+ int ret, control_fd2; |
27620 |
-+ uid_t uid; |
27621 |
-+ |
27622 |
-+ name = unique_name(""); |
27623 |
-+ ASSERT_RETURN(name); |
27624 |
-+ |
27625 |
-+ snprintf(s, sizeof(s), "%s/control", env->root); |
27626 |
-+ env->control_fd = open(s, O_RDWR|O_CLOEXEC); |
27627 |
-+ ASSERT_RETURN(env->control_fd >= 0); |
27628 |
-+ |
27629 |
-+ control_fd2 = open(s, O_RDWR|O_CLOEXEC); |
27630 |
-+ ASSERT_RETURN(control_fd2 >= 0); |
27631 |
-+ |
27632 |
-+ memset(&bus_make, 0, sizeof(bus_make)); |
27633 |
-+ |
27634 |
-+ bus_make.bs.size = sizeof(bus_make.bs); |
27635 |
-+ bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER; |
27636 |
-+ bus_make.bs.bloom.size = 64; |
27637 |
-+ bus_make.bs.bloom.n_hash = 1; |
27638 |
-+ |
27639 |
-+ bus_make.n_type = KDBUS_ITEM_MAKE_NAME; |
27640 |
-+ |
27641 |
-+ uid = getuid(); |
27642 |
-+ |
27643 |
-+ /* missing uid prefix */ |
27644 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "foo"); |
27645 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27646 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27647 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27648 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27649 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27650 |
-+ |
27651 |
-+ /* non alphanumeric character */ |
27652 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid); |
27653 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27654 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27655 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27656 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27657 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27658 |
-+ |
27659 |
-+ /* '-' at the end */ |
27660 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid); |
27661 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27662 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27663 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27664 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27665 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27666 |
-+ |
27667 |
-+ /* create a new bus */ |
27668 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-1", uid, name); |
27669 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27670 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27671 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27672 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27673 |
-+ ASSERT_RETURN(ret == 0); |
27674 |
-+ |
27675 |
-+ ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); |
27676 |
-+ ASSERT_RETURN(ret == -EEXIST); |
27677 |
-+ |
27678 |
-+ snprintf(s, sizeof(s), "%s/%u-%s-1/bus", env->root, uid, name); |
27679 |
-+ ASSERT_RETURN(access(s, F_OK) == 0); |
27680 |
-+ |
27681 |
-+ ret = test_bus_creator_info(s); |
27682 |
-+ ASSERT_RETURN(ret == 0); |
27683 |
-+ |
27684 |
-+ /* can't use the same fd for bus make twice, even though a different |
27685 |
-+ * bus name is used |
27686 |
-+ */ |
27687 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); |
27688 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27689 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27690 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27691 |
-+ ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); |
27692 |
-+ ASSERT_RETURN(ret == -EBADFD); |
27693 |
-+ |
27694 |
-+ /* create a new bus, with different fd and different bus name */ |
27695 |
-+ snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); |
27696 |
-+ bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; |
27697 |
-+ bus_make.cmd.size = sizeof(struct kdbus_cmd) + |
27698 |
-+ sizeof(bus_make.bs) + bus_make.n_size; |
27699 |
-+ ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); |
27700 |
-+ ASSERT_RETURN(ret == 0); |
27701 |
-+ |
27702 |
-+ close(control_fd2); |
27703 |
-+ free(name); |
27704 |
-+ |
27705 |
-+ return TEST_OK; |
27706 |
-+} |
27707 |
-diff --git a/tools/testing/selftests/kdbus/test-chat.c b/tools/testing/selftests/kdbus/test-chat.c |
27708 |
-new file mode 100644 |
27709 |
-index 0000000..41e5b53 |
27710 |
---- /dev/null |
27711 |
-+++ b/tools/testing/selftests/kdbus/test-chat.c |
27712 |
-@@ -0,0 +1,124 @@ |
27713 |
-+#include <stdio.h> |
27714 |
-+#include <string.h> |
27715 |
-+#include <time.h> |
27716 |
-+#include <fcntl.h> |
27717 |
-+#include <stdlib.h> |
27718 |
-+#include <stddef.h> |
27719 |
-+#include <unistd.h> |
27720 |
-+#include <stdint.h> |
27721 |
-+#include <errno.h> |
27722 |
-+#include <assert.h> |
27723 |
-+#include <poll.h> |
27724 |
-+#include <stdbool.h> |
27725 |
-+ |
27726 |
-+#include "kdbus-test.h" |
27727 |
-+#include "kdbus-util.h" |
27728 |
-+#include "kdbus-enum.h" |
27729 |
-+ |
27730 |
-+int kdbus_test_chat(struct kdbus_test_env *env) |
27731 |
-+{ |
27732 |
-+ int ret, cookie; |
27733 |
-+ struct kdbus_conn *conn_a, *conn_b; |
27734 |
-+ struct pollfd fds[2]; |
27735 |
-+ uint64_t flags; |
27736 |
-+ int count; |
27737 |
-+ |
27738 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
27739 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
27740 |
-+ ASSERT_RETURN(conn_a && conn_b); |
27741 |
-+ |
27742 |
-+ flags = KDBUS_NAME_ALLOW_REPLACEMENT; |
27743 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.test", &flags); |
27744 |
-+ ASSERT_RETURN(ret == 0); |
27745 |
-+ |
27746 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.baz", NULL); |
27747 |
-+ ASSERT_RETURN(ret == 0); |
27748 |
-+ |
27749 |
-+ flags = KDBUS_NAME_QUEUE; |
27750 |
-+ ret = kdbus_name_acquire(conn_b, "foo.bar.baz", &flags); |
27751 |
-+ ASSERT_RETURN(ret == 0); |
27752 |
-+ |
27753 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL); |
27754 |
-+ ASSERT_RETURN(ret == 0); |
27755 |
-+ |
27756 |
-+ flags = 0; |
27757 |
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.double", &flags); |
27758 |
-+ ASSERT_RETURN(ret == 0); |
27759 |
-+ ASSERT_RETURN(!(flags & KDBUS_NAME_ACQUIRED)); |
27760 |
-+ |
27761 |
-+ ret = kdbus_name_release(conn_a, "foo.bar.double"); |
27762 |
-+ ASSERT_RETURN(ret == 0); |
27763 |
-+ |
27764 |
-+ ret = kdbus_name_release(conn_a, "foo.bar.double"); |
27765 |
-+ ASSERT_RETURN(ret == -ESRCH); |
27766 |
-+ |
27767 |
-+ ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | |
27768 |
-+ KDBUS_LIST_NAMES | |
27769 |
-+ KDBUS_LIST_QUEUED | |
27770 |
-+ KDBUS_LIST_ACTIVATORS); |
27771 |
-+ ASSERT_RETURN(ret == 0); |
27772 |
-+ |
27773 |
-+ ret = kdbus_add_match_empty(conn_a); |
27774 |
-+ ASSERT_RETURN(ret == 0); |
27775 |
-+ |
27776 |
-+ ret = kdbus_add_match_empty(conn_b); |
27777 |
-+ ASSERT_RETURN(ret == 0); |
27778 |
-+ |
27779 |
-+ cookie = 0; |
27780 |
-+ ret = kdbus_msg_send(conn_b, NULL, 0xc0000000 | cookie, 0, 0, 0, |
27781 |
-+ KDBUS_DST_ID_BROADCAST); |
27782 |
-+ ASSERT_RETURN(ret == 0); |
27783 |
-+ |
27784 |
-+ fds[0].fd = conn_a->fd; |
27785 |
-+ fds[1].fd = conn_b->fd; |
27786 |
-+ |
27787 |
-+ kdbus_printf("-- entering poll loop ...\n"); |
27788 |
-+ |
27789 |
-+ for (count = 0;; count++) { |
27790 |
-+ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
27791 |
-+ |
27792 |
-+ for (i = 0; i < nfds; i++) { |
27793 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
27794 |
-+ fds[i].revents = 0; |
27795 |
-+ } |
27796 |
-+ |
27797 |
-+ ret = poll(fds, nfds, 3000); |
27798 |
-+ ASSERT_RETURN(ret >= 0); |
27799 |
-+ |
27800 |
-+ if (fds[0].revents & POLLIN) { |
27801 |
-+ if (count > 2) |
27802 |
-+ kdbus_name_release(conn_a, "foo.bar.baz"); |
27803 |
-+ |
27804 |
-+ ret = kdbus_msg_recv(conn_a, NULL, NULL); |
27805 |
-+ ASSERT_RETURN(ret == 0); |
27806 |
-+ ret = kdbus_msg_send(conn_a, NULL, |
27807 |
-+ 0xc0000000 | cookie++, |
27808 |
-+ 0, 0, 0, conn_b->id); |
27809 |
-+ ASSERT_RETURN(ret == 0); |
27810 |
-+ } |
27811 |
-+ |
27812 |
-+ if (fds[1].revents & POLLIN) { |
27813 |
-+ ret = kdbus_msg_recv(conn_b, NULL, NULL); |
27814 |
-+ ASSERT_RETURN(ret == 0); |
27815 |
-+ ret = kdbus_msg_send(conn_b, NULL, |
27816 |
-+ 0xc0000000 | cookie++, |
27817 |
-+ 0, 0, 0, conn_a->id); |
27818 |
-+ ASSERT_RETURN(ret == 0); |
27819 |
-+ } |
27820 |
-+ |
27821 |
-+ ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | |
27822 |
-+ KDBUS_LIST_NAMES | |
27823 |
-+ KDBUS_LIST_QUEUED | |
27824 |
-+ KDBUS_LIST_ACTIVATORS); |
27825 |
-+ ASSERT_RETURN(ret == 0); |
27826 |
-+ |
27827 |
-+ if (count > 10) |
27828 |
-+ break; |
27829 |
-+ } |
27830 |
-+ |
27831 |
-+ kdbus_printf("-- closing bus connections\n"); |
27832 |
-+ kdbus_conn_free(conn_a); |
27833 |
-+ kdbus_conn_free(conn_b); |
27834 |
-+ |
27835 |
-+ return TEST_OK; |
27836 |
-+} |
27837 |
-diff --git a/tools/testing/selftests/kdbus/test-connection.c b/tools/testing/selftests/kdbus/test-connection.c |
27838 |
-new file mode 100644 |
27839 |
-index 0000000..4688ce8 |
27840 |
---- /dev/null |
27841 |
-+++ b/tools/testing/selftests/kdbus/test-connection.c |
27842 |
-@@ -0,0 +1,597 @@ |
27843 |
-+#include <stdio.h> |
27844 |
-+#include <string.h> |
27845 |
-+#include <fcntl.h> |
27846 |
-+#include <stdlib.h> |
27847 |
-+#include <stddef.h> |
27848 |
-+#include <unistd.h> |
27849 |
-+#include <stdint.h> |
27850 |
-+#include <errno.h> |
27851 |
-+#include <assert.h> |
27852 |
-+#include <limits.h> |
27853 |
-+#include <sys/types.h> |
27854 |
-+#include <sys/capability.h> |
27855 |
-+#include <sys/mman.h> |
27856 |
-+#include <sys/syscall.h> |
27857 |
-+#include <sys/wait.h> |
27858 |
-+#include <stdbool.h> |
27859 |
-+ |
27860 |
-+#include "kdbus-api.h" |
27861 |
-+#include "kdbus-util.h" |
27862 |
-+#include "kdbus-enum.h" |
27863 |
-+#include "kdbus-test.h" |
27864 |
-+ |
27865 |
-+int kdbus_test_hello(struct kdbus_test_env *env) |
27866 |
-+{ |
27867 |
-+ struct kdbus_cmd_free cmd_free = {}; |
27868 |
-+ struct kdbus_cmd_hello hello; |
27869 |
-+ int fd, ret; |
27870 |
-+ |
27871 |
-+ memset(&hello, 0, sizeof(hello)); |
27872 |
-+ |
27873 |
-+ fd = open(env->buspath, O_RDWR|O_CLOEXEC); |
27874 |
-+ ASSERT_RETURN(fd >= 0); |
27875 |
-+ |
27876 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
27877 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27878 |
-+ hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
27879 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
27880 |
-+ hello.pool_size = POOL_SIZE; |
27881 |
-+ |
27882 |
-+ /* an unaligned hello must result in -EFAULT */ |
27883 |
-+ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) ((char *) &hello + 1)); |
27884 |
-+ ASSERT_RETURN(ret == -EFAULT); |
27885 |
-+ |
27886 |
-+ /* a size of 0 must return EMSGSIZE */ |
27887 |
-+ hello.size = 1; |
27888 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
27889 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27890 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27891 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27892 |
-+ |
27893 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
27894 |
-+ |
27895 |
-+ /* check faulty flags */ |
27896 |
-+ hello.flags = 1ULL << 32; |
27897 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27898 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27899 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27900 |
-+ |
27901 |
-+ /* check for faulty pool sizes */ |
27902 |
-+ hello.pool_size = 0; |
27903 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
27904 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27905 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27906 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27907 |
-+ |
27908 |
-+ hello.pool_size = 4097; |
27909 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27910 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27911 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27912 |
-+ |
27913 |
-+ hello.pool_size = POOL_SIZE; |
27914 |
-+ |
27915 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
27916 |
-+ hello.offset = (__u64)-1; |
27917 |
-+ |
27918 |
-+ /* success test */ |
27919 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27920 |
-+ ASSERT_RETURN(ret == 0); |
27921 |
-+ |
27922 |
-+ /* The kernel should have returned some items */ |
27923 |
-+ ASSERT_RETURN(hello.offset != (__u64)-1); |
27924 |
-+ cmd_free.size = sizeof(cmd_free); |
27925 |
-+ cmd_free.offset = hello.offset; |
27926 |
-+ ret = kdbus_cmd_free(fd, &cmd_free); |
27927 |
-+ ASSERT_RETURN(ret >= 0); |
27928 |
-+ |
27929 |
-+ close(fd); |
27930 |
-+ |
27931 |
-+ fd = open(env->buspath, O_RDWR|O_CLOEXEC); |
27932 |
-+ ASSERT_RETURN(fd >= 0); |
27933 |
-+ |
27934 |
-+ /* no ACTIVATOR flag without a name */ |
27935 |
-+ hello.flags = KDBUS_HELLO_ACTIVATOR; |
27936 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
27937 |
-+ ASSERT_RETURN(ret == -EINVAL); |
27938 |
-+ |
27939 |
-+ close(fd); |
27940 |
-+ |
27941 |
-+ return TEST_OK; |
27942 |
-+} |
27943 |
-+ |
27944 |
-+int kdbus_test_byebye(struct kdbus_test_env *env) |
27945 |
-+{ |
27946 |
-+ struct kdbus_conn *conn; |
27947 |
-+ struct kdbus_cmd_recv cmd_recv = { .size = sizeof(cmd_recv) }; |
27948 |
-+ struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; |
27949 |
-+ int ret; |
27950 |
-+ |
27951 |
-+ /* create a 2nd connection */ |
27952 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
27953 |
-+ ASSERT_RETURN(conn != NULL); |
27954 |
-+ |
27955 |
-+ ret = kdbus_add_match_empty(conn); |
27956 |
-+ ASSERT_RETURN(ret == 0); |
27957 |
-+ |
27958 |
-+ ret = kdbus_add_match_empty(env->conn); |
27959 |
-+ ASSERT_RETURN(ret == 0); |
27960 |
-+ |
27961 |
-+ /* send over 1st connection */ |
27962 |
-+ ret = kdbus_msg_send(env->conn, NULL, 0, 0, 0, 0, |
27963 |
-+ KDBUS_DST_ID_BROADCAST); |
27964 |
-+ ASSERT_RETURN(ret == 0); |
27965 |
-+ |
27966 |
-+ /* say byebye on the 2nd, which must fail */ |
27967 |
-+ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
27968 |
-+ ASSERT_RETURN(ret == -EBUSY); |
27969 |
-+ |
27970 |
-+ /* receive the message */ |
27971 |
-+ ret = kdbus_cmd_recv(conn->fd, &cmd_recv); |
27972 |
-+ ASSERT_RETURN(ret == 0); |
27973 |
-+ |
27974 |
-+ ret = kdbus_free(conn, cmd_recv.msg.offset); |
27975 |
-+ ASSERT_RETURN(ret == 0); |
27976 |
-+ |
27977 |
-+ /* and try again */ |
27978 |
-+ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
27979 |
-+ ASSERT_RETURN(ret == 0); |
27980 |
-+ |
27981 |
-+ /* a 2nd try should result in -ECONNRESET */ |
27982 |
-+ ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); |
27983 |
-+ ASSERT_RETURN(ret == -ECONNRESET); |
27984 |
-+ |
27985 |
-+ kdbus_conn_free(conn); |
27986 |
-+ |
27987 |
-+ return TEST_OK; |
27988 |
-+} |
27989 |
-+ |
27990 |
-+/* Get only the first item */ |
27991 |
-+static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, |
27992 |
-+ uint64_t type) |
27993 |
-+{ |
27994 |
-+ struct kdbus_item *item; |
27995 |
-+ |
27996 |
-+ KDBUS_ITEM_FOREACH(item, info, items) |
27997 |
-+ if (item->type == type) |
27998 |
-+ return item; |
27999 |
-+ |
28000 |
-+ return NULL; |
28001 |
-+} |
28002 |
-+ |
28003 |
-+static unsigned int kdbus_count_item(struct kdbus_info *info, |
28004 |
-+ uint64_t type) |
28005 |
-+{ |
28006 |
-+ unsigned int i = 0; |
28007 |
-+ const struct kdbus_item *item; |
28008 |
-+ |
28009 |
-+ KDBUS_ITEM_FOREACH(item, info, items) |
28010 |
-+ if (item->type == type) |
28011 |
-+ i++; |
28012 |
-+ |
28013 |
-+ return i; |
28014 |
-+} |
28015 |
-+ |
28016 |
-+static int kdbus_fuzz_conn_info(struct kdbus_test_env *env, int capable) |
28017 |
-+{ |
28018 |
-+ int ret; |
28019 |
-+ unsigned int cnt = 0; |
28020 |
-+ uint64_t offset = 0; |
28021 |
-+ struct kdbus_info *info; |
28022 |
-+ struct kdbus_conn *conn; |
28023 |
-+ struct kdbus_conn *privileged; |
28024 |
-+ const struct kdbus_item *item; |
28025 |
-+ uint64_t valid_flags = KDBUS_ATTACH_NAMES | |
28026 |
-+ KDBUS_ATTACH_CREDS | |
28027 |
-+ KDBUS_ATTACH_PIDS | |
28028 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION; |
28029 |
-+ |
28030 |
-+ uint64_t invalid_flags = KDBUS_ATTACH_NAMES | |
28031 |
-+ KDBUS_ATTACH_CREDS | |
28032 |
-+ KDBUS_ATTACH_PIDS | |
28033 |
-+ KDBUS_ATTACH_CAPS | |
28034 |
-+ KDBUS_ATTACH_CGROUP | |
28035 |
-+ KDBUS_ATTACH_CONN_DESCRIPTION; |
28036 |
-+ |
28037 |
-+ struct kdbus_creds cached_creds; |
28038 |
-+ uid_t ruid, euid, suid; |
28039 |
-+ gid_t rgid, egid, sgid; |
28040 |
-+ |
28041 |
-+ getresuid(&ruid, &euid, &suid); |
28042 |
-+ getresgid(&rgid, &egid, &sgid); |
28043 |
-+ |
28044 |
-+ cached_creds.uid = ruid; |
28045 |
-+ cached_creds.euid = euid; |
28046 |
-+ cached_creds.suid = suid; |
28047 |
-+ cached_creds.fsuid = ruid; |
28048 |
-+ |
28049 |
-+ cached_creds.gid = rgid; |
28050 |
-+ cached_creds.egid = egid; |
28051 |
-+ cached_creds.sgid = sgid; |
28052 |
-+ cached_creds.fsgid = rgid; |
28053 |
-+ |
28054 |
-+ struct kdbus_pids cached_pids = { |
28055 |
-+ .pid = getpid(), |
28056 |
-+ .tid = syscall(SYS_gettid), |
28057 |
-+ .ppid = getppid(), |
28058 |
-+ }; |
28059 |
-+ |
28060 |
-+ ret = kdbus_conn_info(env->conn, env->conn->id, NULL, |
28061 |
-+ valid_flags, &offset); |
28062 |
-+ ASSERT_RETURN(ret == 0); |
28063 |
-+ |
28064 |
-+ info = (struct kdbus_info *)(env->conn->buf + offset); |
28065 |
-+ ASSERT_RETURN(info->id == env->conn->id); |
28066 |
-+ |
28067 |
-+ /* We do not have any well-known name */ |
28068 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_NAME); |
28069 |
-+ ASSERT_RETURN(item == NULL); |
28070 |
-+ |
28071 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CONN_DESCRIPTION); |
28072 |
-+ if (valid_flags & KDBUS_ATTACH_CONN_DESCRIPTION) { |
28073 |
-+ ASSERT_RETURN(item); |
28074 |
-+ } else { |
28075 |
-+ ASSERT_RETURN(item == NULL); |
28076 |
-+ } |
28077 |
-+ |
28078 |
-+ kdbus_free(env->conn, offset); |
28079 |
-+ |
28080 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28081 |
-+ ASSERT_RETURN(conn); |
28082 |
-+ |
28083 |
-+ privileged = kdbus_hello(env->buspath, 0, NULL, 0); |
28084 |
-+ ASSERT_RETURN(privileged); |
28085 |
-+ |
28086 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28087 |
-+ ASSERT_RETURN(ret == 0); |
28088 |
-+ |
28089 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28090 |
-+ ASSERT_RETURN(info->id == conn->id); |
28091 |
-+ |
28092 |
-+ /* We do not have any well-known name */ |
28093 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_NAME); |
28094 |
-+ ASSERT_RETURN(item == NULL); |
28095 |
-+ |
28096 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); |
28097 |
-+ if (valid_flags & KDBUS_ATTACH_CREDS) { |
28098 |
-+ ASSERT_RETURN(cnt == 1); |
28099 |
-+ |
28100 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28101 |
-+ ASSERT_RETURN(item); |
28102 |
-+ |
28103 |
-+ /* Compare received items with cached creds */ |
28104 |
-+ ASSERT_RETURN(memcmp(&item->creds, &cached_creds, |
28105 |
-+ sizeof(struct kdbus_creds)) == 0); |
28106 |
-+ } else { |
28107 |
-+ ASSERT_RETURN(cnt == 0); |
28108 |
-+ } |
28109 |
-+ |
28110 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28111 |
-+ if (valid_flags & KDBUS_ATTACH_PIDS) { |
28112 |
-+ ASSERT_RETURN(item); |
28113 |
-+ |
28114 |
-+ /* Compare item->pids with cached PIDs */ |
28115 |
-+ ASSERT_RETURN(item->pids.pid == cached_pids.pid && |
28116 |
-+ item->pids.tid == cached_pids.tid && |
28117 |
-+ item->pids.ppid == cached_pids.ppid); |
28118 |
-+ } else { |
28119 |
-+ ASSERT_RETURN(item == NULL); |
28120 |
-+ } |
28121 |
-+ |
28122 |
-+ /* We did not request KDBUS_ITEM_CAPS */ |
28123 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CAPS); |
28124 |
-+ ASSERT_RETURN(item == NULL); |
28125 |
-+ |
28126 |
-+ kdbus_free(conn, offset); |
28127 |
-+ |
28128 |
-+ ret = kdbus_name_acquire(conn, "com.example.a", NULL); |
28129 |
-+ ASSERT_RETURN(ret >= 0); |
28130 |
-+ |
28131 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28132 |
-+ ASSERT_RETURN(ret == 0); |
28133 |
-+ |
28134 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28135 |
-+ ASSERT_RETURN(info->id == conn->id); |
28136 |
-+ |
28137 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); |
28138 |
-+ if (valid_flags & KDBUS_ATTACH_NAMES) { |
28139 |
-+ ASSERT_RETURN(item && !strcmp(item->name.name, "com.example.a")); |
28140 |
-+ } else { |
28141 |
-+ ASSERT_RETURN(item == NULL); |
28142 |
-+ } |
28143 |
-+ |
28144 |
-+ kdbus_free(conn, offset); |
28145 |
-+ |
28146 |
-+ ret = kdbus_conn_info(conn, 0, "com.example.a", valid_flags, &offset); |
28147 |
-+ ASSERT_RETURN(ret == 0); |
28148 |
-+ |
28149 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28150 |
-+ ASSERT_RETURN(info->id == conn->id); |
28151 |
-+ |
28152 |
-+ kdbus_free(conn, offset); |
28153 |
-+ |
28154 |
-+ /* does not have the necessary caps to drop to unprivileged */ |
28155 |
-+ if (!capable) |
28156 |
-+ goto continue_test; |
28157 |
-+ |
28158 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
28159 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, |
28160 |
-+ valid_flags, &offset); |
28161 |
-+ ASSERT_EXIT(ret == 0); |
28162 |
-+ |
28163 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28164 |
-+ ASSERT_EXIT(info->id == conn->id); |
28165 |
-+ |
28166 |
-+ if (valid_flags & KDBUS_ATTACH_NAMES) { |
28167 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); |
28168 |
-+ ASSERT_EXIT(item && |
28169 |
-+ strcmp(item->name.name, |
28170 |
-+ "com.example.a") == 0); |
28171 |
-+ } |
28172 |
-+ |
28173 |
-+ if (valid_flags & KDBUS_ATTACH_CREDS) { |
28174 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28175 |
-+ ASSERT_EXIT(item); |
28176 |
-+ |
28177 |
-+ /* Compare received items with cached creds */ |
28178 |
-+ ASSERT_EXIT(memcmp(&item->creds, &cached_creds, |
28179 |
-+ sizeof(struct kdbus_creds)) == 0); |
28180 |
-+ } |
28181 |
-+ |
28182 |
-+ if (valid_flags & KDBUS_ATTACH_PIDS) { |
28183 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28184 |
-+ ASSERT_EXIT(item); |
28185 |
-+ |
28186 |
-+ /* |
28187 |
-+ * Compare item->pids with cached pids of |
28188 |
-+ * privileged one. |
28189 |
-+ * |
28190 |
-+ * cmd_info will always return cached pids. |
28191 |
-+ */ |
28192 |
-+ ASSERT_EXIT(item->pids.pid == cached_pids.pid && |
28193 |
-+ item->pids.tid == cached_pids.tid); |
28194 |
-+ } |
28195 |
-+ |
28196 |
-+ kdbus_free(conn, offset); |
28197 |
-+ |
28198 |
-+ /* |
28199 |
-+ * Use invalid_flags and make sure that userspace |
28200 |
-+ * do not play with us. |
28201 |
-+ */ |
28202 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, |
28203 |
-+ invalid_flags, &offset); |
28204 |
-+ ASSERT_EXIT(ret == 0); |
28205 |
-+ |
28206 |
-+ /* |
28207 |
-+ * Make sure that we return only one creds item and |
28208 |
-+ * it points to the cached creds. |
28209 |
-+ */ |
28210 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); |
28211 |
-+ if (invalid_flags & KDBUS_ATTACH_CREDS) { |
28212 |
-+ ASSERT_EXIT(cnt == 1); |
28213 |
-+ |
28214 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS); |
28215 |
-+ ASSERT_EXIT(item); |
28216 |
-+ |
28217 |
-+ /* Compare received items with cached creds */ |
28218 |
-+ ASSERT_EXIT(memcmp(&item->creds, &cached_creds, |
28219 |
-+ sizeof(struct kdbus_creds)) == 0); |
28220 |
-+ } else { |
28221 |
-+ ASSERT_EXIT(cnt == 0); |
28222 |
-+ } |
28223 |
-+ |
28224 |
-+ if (invalid_flags & KDBUS_ATTACH_PIDS) { |
28225 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_PIDS); |
28226 |
-+ ASSERT_EXIT(cnt == 1); |
28227 |
-+ |
28228 |
-+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS); |
28229 |
-+ ASSERT_EXIT(item); |
28230 |
-+ |
28231 |
-+ /* Compare item->pids with cached pids */ |
28232 |
-+ ASSERT_EXIT(item->pids.pid == cached_pids.pid && |
28233 |
-+ item->pids.tid == cached_pids.tid); |
28234 |
-+ } |
28235 |
-+ |
28236 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CGROUP); |
28237 |
-+ if (invalid_flags & KDBUS_ATTACH_CGROUP) { |
28238 |
-+ ASSERT_EXIT(cnt == 1); |
28239 |
-+ } else { |
28240 |
-+ ASSERT_EXIT(cnt == 0); |
28241 |
-+ } |
28242 |
-+ |
28243 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_CAPS); |
28244 |
-+ if (invalid_flags & KDBUS_ATTACH_CAPS) { |
28245 |
-+ ASSERT_EXIT(cnt == 1); |
28246 |
-+ } else { |
28247 |
-+ ASSERT_EXIT(cnt == 0); |
28248 |
-+ } |
28249 |
-+ |
28250 |
-+ kdbus_free(conn, offset); |
28251 |
-+ }), |
28252 |
-+ ({ 0; })); |
28253 |
-+ ASSERT_RETURN(ret == 0); |
28254 |
-+ |
28255 |
-+continue_test: |
28256 |
-+ |
28257 |
-+ /* A second name */ |
28258 |
-+ ret = kdbus_name_acquire(conn, "com.example.b", NULL); |
28259 |
-+ ASSERT_RETURN(ret >= 0); |
28260 |
-+ |
28261 |
-+ ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); |
28262 |
-+ ASSERT_RETURN(ret == 0); |
28263 |
-+ |
28264 |
-+ info = (struct kdbus_info *)(conn->buf + offset); |
28265 |
-+ ASSERT_RETURN(info->id == conn->id); |
28266 |
-+ |
28267 |
-+ cnt = kdbus_count_item(info, KDBUS_ITEM_OWNED_NAME); |
28268 |
-+ if (valid_flags & KDBUS_ATTACH_NAMES) { |
28269 |
-+ ASSERT_RETURN(cnt == 2); |
28270 |
-+ } else { |
28271 |
-+ ASSERT_RETURN(cnt == 0); |
28272 |
-+ } |
28273 |
-+ |
28274 |
-+ kdbus_free(conn, offset); |
28275 |
-+ |
28276 |
-+ ASSERT_RETURN(ret == 0); |
28277 |
-+ |
28278 |
-+ return 0; |
28279 |
-+} |
28280 |
-+ |
28281 |
-+int kdbus_test_conn_info(struct kdbus_test_env *env) |
28282 |
-+{ |
28283 |
-+ int ret; |
28284 |
-+ int have_caps; |
28285 |
-+ struct { |
28286 |
-+ struct kdbus_cmd_info cmd_info; |
28287 |
-+ |
28288 |
-+ struct { |
28289 |
-+ uint64_t size; |
28290 |
-+ uint64_t type; |
28291 |
-+ char str[64]; |
28292 |
-+ } name; |
28293 |
-+ } buf; |
28294 |
-+ |
28295 |
-+ buf.cmd_info.size = sizeof(struct kdbus_cmd_info); |
28296 |
-+ buf.cmd_info.flags = 0; |
28297 |
-+ buf.cmd_info.attach_flags = 0; |
28298 |
-+ buf.cmd_info.id = env->conn->id; |
28299 |
-+ |
28300 |
-+ ret = kdbus_conn_info(env->conn, env->conn->id, NULL, 0, NULL); |
28301 |
-+ ASSERT_RETURN(ret == 0); |
28302 |
-+ |
28303 |
-+ /* try to pass a name that is longer than the buffer's size */ |
28304 |
-+ buf.name.size = KDBUS_ITEM_HEADER_SIZE + 1; |
28305 |
-+ buf.name.type = KDBUS_ITEM_NAME; |
28306 |
-+ strcpy(buf.name.str, "foo.bar.bla"); |
28307 |
-+ |
28308 |
-+ buf.cmd_info.id = 0; |
28309 |
-+ buf.cmd_info.size = sizeof(buf.cmd_info) + buf.name.size; |
28310 |
-+ ret = kdbus_cmd_conn_info(env->conn->fd, (struct kdbus_cmd_info *) &buf); |
28311 |
-+ ASSERT_RETURN(ret == -EINVAL); |
28312 |
-+ |
28313 |
-+ /* Pass a non existent name */ |
28314 |
-+ ret = kdbus_conn_info(env->conn, 0, "non.existent.name", 0, NULL); |
28315 |
-+ ASSERT_RETURN(ret == -ESRCH); |
28316 |
-+ |
28317 |
-+ if (!all_uids_gids_are_mapped()) |
28318 |
-+ return TEST_SKIP; |
28319 |
-+ |
28320 |
-+ /* Test for caps here, so we run the previous test */ |
28321 |
-+ have_caps = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
28322 |
-+ ASSERT_RETURN(have_caps >= 0); |
28323 |
-+ |
28324 |
-+ ret = kdbus_fuzz_conn_info(env, have_caps); |
28325 |
-+ ASSERT_RETURN(ret == 0); |
28326 |
-+ |
28327 |
-+ /* Now if we have skipped some tests then let the user know */ |
28328 |
-+ if (!have_caps) |
28329 |
-+ return TEST_SKIP; |
28330 |
-+ |
28331 |
-+ return TEST_OK; |
28332 |
-+} |
28333 |
-+ |
28334 |
-+int kdbus_test_conn_update(struct kdbus_test_env *env) |
28335 |
-+{ |
28336 |
-+ struct kdbus_conn *conn; |
28337 |
-+ struct kdbus_msg *msg; |
28338 |
-+ int found = 0; |
28339 |
-+ int ret; |
28340 |
-+ |
28341 |
-+ /* |
28342 |
-+ * kdbus_hello() sets all attach flags. Receive a message by this |
28343 |
-+ * connection, and make sure a timestamp item (just to pick one) is |
28344 |
-+ * present. |
28345 |
-+ */ |
28346 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
28347 |
-+ ASSERT_RETURN(conn); |
28348 |
-+ |
28349 |
-+ ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); |
28350 |
-+ ASSERT_RETURN(ret == 0); |
28351 |
-+ |
28352 |
-+ ret = kdbus_msg_recv(conn, &msg, NULL); |
28353 |
-+ ASSERT_RETURN(ret == 0); |
28354 |
-+ |
28355 |
-+ found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
28356 |
-+ ASSERT_RETURN(found == 1); |
28357 |
-+ |
28358 |
-+ kdbus_msg_free(msg); |
28359 |
-+ |
28360 |
-+ /* |
28361 |
-+ * Now, modify the attach flags and repeat the action. The item must |
28362 |
-+ * now be missing. |
28363 |
-+ */ |
28364 |
-+ found = 0; |
28365 |
-+ |
28366 |
-+ ret = kdbus_conn_update_attach_flags(conn, |
28367 |
-+ _KDBUS_ATTACH_ALL, |
28368 |
-+ _KDBUS_ATTACH_ALL & |
28369 |
-+ ~KDBUS_ATTACH_TIMESTAMP); |
28370 |
-+ ASSERT_RETURN(ret == 0); |
28371 |
-+ |
28372 |
-+ ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); |
28373 |
-+ ASSERT_RETURN(ret == 0); |
28374 |
-+ |
28375 |
-+ ret = kdbus_msg_recv(conn, &msg, NULL); |
28376 |
-+ ASSERT_RETURN(ret == 0); |
28377 |
-+ |
28378 |
-+ found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
28379 |
-+ ASSERT_RETURN(found == 0); |
28380 |
-+ |
28381 |
-+ /* Provide a bogus attach_flags value */ |
28382 |
-+ ret = kdbus_conn_update_attach_flags(conn, |
28383 |
-+ _KDBUS_ATTACH_ALL + 1, |
28384 |
-+ _KDBUS_ATTACH_ALL); |
28385 |
-+ ASSERT_RETURN(ret == -EINVAL); |
28386 |
-+ |
28387 |
-+ kdbus_msg_free(msg); |
28388 |
-+ |
28389 |
-+ kdbus_conn_free(conn); |
28390 |
-+ |
28391 |
-+ return TEST_OK; |
28392 |
-+} |
28393 |
-+ |
28394 |
-+int kdbus_test_writable_pool(struct kdbus_test_env *env) |
28395 |
-+{ |
28396 |
-+ struct kdbus_cmd_free cmd_free = {}; |
28397 |
-+ struct kdbus_cmd_hello hello; |
28398 |
-+ int fd, ret; |
28399 |
-+ void *map; |
28400 |
-+ |
28401 |
-+ fd = open(env->buspath, O_RDWR | O_CLOEXEC); |
28402 |
-+ ASSERT_RETURN(fd >= 0); |
28403 |
-+ |
28404 |
-+ memset(&hello, 0, sizeof(hello)); |
28405 |
-+ hello.flags = KDBUS_HELLO_ACCEPT_FD; |
28406 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
28407 |
-+ hello.attach_flags_recv = _KDBUS_ATTACH_ALL; |
28408 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
28409 |
-+ hello.pool_size = POOL_SIZE; |
28410 |
-+ hello.offset = (__u64)-1; |
28411 |
-+ |
28412 |
-+ /* success test */ |
28413 |
-+ ret = kdbus_cmd_hello(fd, &hello); |
28414 |
-+ ASSERT_RETURN(ret == 0); |
28415 |
-+ |
28416 |
-+ /* The kernel should have returned some items */ |
28417 |
-+ ASSERT_RETURN(hello.offset != (__u64)-1); |
28418 |
-+ cmd_free.size = sizeof(cmd_free); |
28419 |
-+ cmd_free.offset = hello.offset; |
28420 |
-+ ret = kdbus_cmd_free(fd, &cmd_free); |
28421 |
-+ ASSERT_RETURN(ret >= 0); |
28422 |
-+ |
28423 |
-+ /* pools cannot be mapped writable */ |
28424 |
-+ map = mmap(NULL, POOL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
28425 |
-+ ASSERT_RETURN(map == MAP_FAILED); |
28426 |
-+ |
28427 |
-+ /* pools can always be mapped readable */ |
28428 |
-+ map = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
28429 |
-+ ASSERT_RETURN(map != MAP_FAILED); |
28430 |
-+ |
28431 |
-+ /* make sure we cannot change protection masks to writable */ |
28432 |
-+ ret = mprotect(map, POOL_SIZE, PROT_READ | PROT_WRITE); |
28433 |
-+ ASSERT_RETURN(ret < 0); |
28434 |
-+ |
28435 |
-+ munmap(map, POOL_SIZE); |
28436 |
-+ close(fd); |
28437 |
-+ |
28438 |
-+ return TEST_OK; |
28439 |
-+} |
28440 |
-diff --git a/tools/testing/selftests/kdbus/test-daemon.c b/tools/testing/selftests/kdbus/test-daemon.c |
28441 |
-new file mode 100644 |
28442 |
-index 0000000..8bc2386 |
28443 |
---- /dev/null |
28444 |
-+++ b/tools/testing/selftests/kdbus/test-daemon.c |
28445 |
-@@ -0,0 +1,65 @@ |
28446 |
-+#include <stdio.h> |
28447 |
-+#include <string.h> |
28448 |
-+#include <time.h> |
28449 |
-+#include <fcntl.h> |
28450 |
-+#include <stdlib.h> |
28451 |
-+#include <stddef.h> |
28452 |
-+#include <unistd.h> |
28453 |
-+#include <stdint.h> |
28454 |
-+#include <errno.h> |
28455 |
-+#include <assert.h> |
28456 |
-+#include <poll.h> |
28457 |
-+#include <stdbool.h> |
28458 |
-+ |
28459 |
-+#include "kdbus-test.h" |
28460 |
-+#include "kdbus-util.h" |
28461 |
-+#include "kdbus-enum.h" |
28462 |
-+ |
28463 |
-+int kdbus_test_daemon(struct kdbus_test_env *env) |
28464 |
-+{ |
28465 |
-+ struct pollfd fds[2]; |
28466 |
-+ int count; |
28467 |
-+ int ret; |
28468 |
-+ |
28469 |
-+ /* This test doesn't make any sense in non-interactive mode */ |
28470 |
-+ if (!kdbus_util_verbose) |
28471 |
-+ return TEST_OK; |
28472 |
-+ |
28473 |
-+ printf("Created connection %llu on bus '%s'\n", |
28474 |
-+ (unsigned long long) env->conn->id, env->buspath); |
28475 |
-+ |
28476 |
-+ ret = kdbus_name_acquire(env->conn, "com.example.kdbus-test", NULL); |
28477 |
-+ ASSERT_RETURN(ret == 0); |
28478 |
-+ printf(" Aquired name: com.example.kdbus-test\n"); |
28479 |
-+ |
28480 |
-+ fds[0].fd = env->conn->fd; |
28481 |
-+ fds[1].fd = STDIN_FILENO; |
28482 |
-+ |
28483 |
-+ printf("Monitoring connections:\n"); |
28484 |
-+ |
28485 |
-+ for (count = 0;; count++) { |
28486 |
-+ int i, nfds = sizeof(fds) / sizeof(fds[0]); |
28487 |
-+ |
28488 |
-+ for (i = 0; i < nfds; i++) { |
28489 |
-+ fds[i].events = POLLIN | POLLPRI | POLLHUP; |
28490 |
-+ fds[i].revents = 0; |
28491 |
-+ } |
28492 |
-+ |
28493 |
-+ ret = poll(fds, nfds, -1); |
28494 |
-+ if (ret <= 0) |
28495 |
-+ break; |
28496 |
-+ |
28497 |
-+ if (fds[0].revents & POLLIN) { |
28498 |
-+ ret = kdbus_msg_recv(env->conn, NULL, NULL); |
28499 |
-+ ASSERT_RETURN(ret == 0); |
28500 |
-+ } |
28501 |
-+ |
28502 |
-+ /* stdin */ |
28503 |
-+ if (fds[1].revents & POLLIN) |
28504 |
-+ break; |
28505 |
-+ } |
28506 |
-+ |
28507 |
-+ printf("Closing bus connection\n"); |
28508 |
-+ |
28509 |
-+ return TEST_OK; |
28510 |
-+} |
28511 |
-diff --git a/tools/testing/selftests/kdbus/test-endpoint.c b/tools/testing/selftests/kdbus/test-endpoint.c |
28512 |
-new file mode 100644 |
28513 |
-index 0000000..34a7be4 |
28514 |
---- /dev/null |
28515 |
-+++ b/tools/testing/selftests/kdbus/test-endpoint.c |
28516 |
-@@ -0,0 +1,352 @@ |
28517 |
-+#include <stdio.h> |
28518 |
-+#include <string.h> |
28519 |
-+#include <fcntl.h> |
28520 |
-+#include <stdlib.h> |
28521 |
-+#include <stddef.h> |
28522 |
-+#include <unistd.h> |
28523 |
-+#include <stdint.h> |
28524 |
-+#include <errno.h> |
28525 |
-+#include <assert.h> |
28526 |
-+#include <libgen.h> |
28527 |
-+#include <sys/capability.h> |
28528 |
-+#include <sys/wait.h> |
28529 |
-+#include <stdbool.h> |
28530 |
-+ |
28531 |
-+#include "kdbus-api.h" |
28532 |
-+#include "kdbus-util.h" |
28533 |
-+#include "kdbus-enum.h" |
28534 |
-+#include "kdbus-test.h" |
28535 |
-+ |
28536 |
-+#define KDBUS_SYSNAME_MAX_LEN 63 |
28537 |
-+ |
28538 |
-+static int install_name_add_match(struct kdbus_conn *conn, const char *name) |
28539 |
-+{ |
28540 |
-+ struct { |
28541 |
-+ struct kdbus_cmd_match cmd; |
28542 |
-+ struct { |
28543 |
-+ uint64_t size; |
28544 |
-+ uint64_t type; |
28545 |
-+ struct kdbus_notify_name_change chg; |
28546 |
-+ } item; |
28547 |
-+ char name[64]; |
28548 |
-+ } buf; |
28549 |
-+ int ret; |
28550 |
-+ |
28551 |
-+ /* install the match rule */ |
28552 |
-+ memset(&buf, 0, sizeof(buf)); |
28553 |
-+ buf.item.type = KDBUS_ITEM_NAME_ADD; |
28554 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
28555 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
28556 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
28557 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
28558 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
28559 |
-+ |
28560 |
-+ ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); |
28561 |
-+ if (ret < 0) |
28562 |
-+ return ret; |
28563 |
-+ |
28564 |
-+ return 0; |
28565 |
-+} |
28566 |
-+ |
28567 |
-+static int create_endpoint(const char *buspath, uid_t uid, const char *name, |
28568 |
-+ uint64_t flags) |
28569 |
-+{ |
28570 |
-+ struct { |
28571 |
-+ struct kdbus_cmd cmd; |
28572 |
-+ |
28573 |
-+ /* name item */ |
28574 |
-+ struct { |
28575 |
-+ uint64_t size; |
28576 |
-+ uint64_t type; |
28577 |
-+ /* max should be KDBUS_SYSNAME_MAX_LEN */ |
28578 |
-+ char str[128]; |
28579 |
-+ } name; |
28580 |
-+ } ep_make; |
28581 |
-+ int fd, ret; |
28582 |
-+ |
28583 |
-+ fd = open(buspath, O_RDWR); |
28584 |
-+ if (fd < 0) |
28585 |
-+ return fd; |
28586 |
-+ |
28587 |
-+ memset(&ep_make, 0, sizeof(ep_make)); |
28588 |
-+ |
28589 |
-+ snprintf(ep_make.name.str, |
28590 |
-+ /* Use the KDBUS_SYSNAME_MAX_LEN or sizeof(str) */ |
28591 |
-+ KDBUS_SYSNAME_MAX_LEN > strlen(name) ? |
28592 |
-+ KDBUS_SYSNAME_MAX_LEN : sizeof(ep_make.name.str), |
28593 |
-+ "%u-%s", uid, name); |
28594 |
-+ |
28595 |
-+ ep_make.name.type = KDBUS_ITEM_MAKE_NAME; |
28596 |
-+ ep_make.name.size = KDBUS_ITEM_HEADER_SIZE + |
28597 |
-+ strlen(ep_make.name.str) + 1; |
28598 |
-+ |
28599 |
-+ ep_make.cmd.flags = flags; |
28600 |
-+ ep_make.cmd.size = sizeof(ep_make.cmd) + ep_make.name.size; |
28601 |
-+ |
28602 |
-+ ret = kdbus_cmd_endpoint_make(fd, &ep_make.cmd); |
28603 |
-+ if (ret < 0) { |
28604 |
-+ kdbus_printf("error creating endpoint: %d (%m)\n", ret); |
28605 |
-+ return ret; |
28606 |
-+ } |
28607 |
-+ |
28608 |
-+ return fd; |
28609 |
-+} |
28610 |
-+ |
28611 |
-+static int unpriv_test_custom_ep(const char *buspath) |
28612 |
-+{ |
28613 |
-+ int ret, ep_fd1, ep_fd2; |
28614 |
-+ char *ep1, *ep2, *tmp1, *tmp2; |
28615 |
-+ |
28616 |
-+ tmp1 = strdup(buspath); |
28617 |
-+ tmp2 = strdup(buspath); |
28618 |
-+ ASSERT_RETURN(tmp1 && tmp2); |
28619 |
-+ |
28620 |
-+ ret = asprintf(&ep1, "%s/%u-%s", dirname(tmp1), getuid(), "apps1"); |
28621 |
-+ ASSERT_RETURN(ret >= 0); |
28622 |
-+ |
28623 |
-+ ret = asprintf(&ep2, "%s/%u-%s", dirname(tmp2), getuid(), "apps2"); |
28624 |
-+ ASSERT_RETURN(ret >= 0); |
28625 |
-+ |
28626 |
-+ free(tmp1); |
28627 |
-+ free(tmp2); |
28628 |
-+ |
28629 |
-+ /* endpoint only accessible to current uid */ |
28630 |
-+ ep_fd1 = create_endpoint(buspath, getuid(), "apps1", 0); |
28631 |
-+ ASSERT_RETURN(ep_fd1 >= 0); |
28632 |
-+ |
28633 |
-+ /* endpoint world accessible */ |
28634 |
-+ ep_fd2 = create_endpoint(buspath, getuid(), "apps2", |
28635 |
-+ KDBUS_MAKE_ACCESS_WORLD); |
28636 |
-+ ASSERT_RETURN(ep_fd2 >= 0); |
28637 |
-+ |
28638 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
28639 |
-+ int ep_fd; |
28640 |
-+ struct kdbus_conn *ep_conn; |
28641 |
-+ |
28642 |
-+ /* |
28643 |
-+ * Make sure that we are not able to create custom |
28644 |
-+ * endpoints |
28645 |
-+ */ |
28646 |
-+ ep_fd = create_endpoint(buspath, getuid(), |
28647 |
-+ "unpriv_costum_ep", 0); |
28648 |
-+ ASSERT_EXIT(ep_fd == -EPERM); |
28649 |
-+ |
28650 |
-+ /* |
28651 |
-+ * Endpoint "apps1" only accessible to same users, |
28652 |
-+ * that own the endpoint. Access denied by VFS |
28653 |
-+ */ |
28654 |
-+ ep_conn = kdbus_hello(ep1, 0, NULL, 0); |
28655 |
-+ ASSERT_EXIT(!ep_conn && errno == EACCES); |
28656 |
-+ |
28657 |
-+ /* Endpoint "apps2" world accessible */ |
28658 |
-+ ep_conn = kdbus_hello(ep2, 0, NULL, 0); |
28659 |
-+ ASSERT_EXIT(ep_conn); |
28660 |
-+ |
28661 |
-+ kdbus_conn_free(ep_conn); |
28662 |
-+ |
28663 |
-+ _exit(EXIT_SUCCESS); |
28664 |
-+ }), |
28665 |
-+ ({ 0; })); |
28666 |
-+ ASSERT_RETURN(ret == 0); |
28667 |
-+ |
28668 |
-+ close(ep_fd1); |
28669 |
-+ close(ep_fd2); |
28670 |
-+ free(ep1); |
28671 |
-+ free(ep2); |
28672 |
-+ |
28673 |
-+ return 0; |
28674 |
-+} |
28675 |
-+ |
28676 |
-+static int update_endpoint(int fd, const char *name) |
28677 |
-+{ |
28678 |
-+ int len = strlen(name) + 1; |
28679 |
-+ struct { |
28680 |
-+ struct kdbus_cmd cmd; |
28681 |
-+ |
28682 |
-+ /* name item */ |
28683 |
-+ struct { |
28684 |
-+ uint64_t size; |
28685 |
-+ uint64_t type; |
28686 |
-+ char str[KDBUS_ALIGN8(len)]; |
28687 |
-+ } name; |
28688 |
-+ |
28689 |
-+ struct { |
28690 |
-+ uint64_t size; |
28691 |
-+ uint64_t type; |
28692 |
-+ struct kdbus_policy_access access; |
28693 |
-+ } access; |
28694 |
-+ } ep_update; |
28695 |
-+ int ret; |
28696 |
-+ |
28697 |
-+ memset(&ep_update, 0, sizeof(ep_update)); |
28698 |
-+ |
28699 |
-+ ep_update.name.size = KDBUS_ITEM_HEADER_SIZE + len; |
28700 |
-+ ep_update.name.type = KDBUS_ITEM_NAME; |
28701 |
-+ strncpy(ep_update.name.str, name, sizeof(ep_update.name.str) - 1); |
28702 |
-+ |
28703 |
-+ ep_update.access.size = sizeof(ep_update.access); |
28704 |
-+ ep_update.access.type = KDBUS_ITEM_POLICY_ACCESS; |
28705 |
-+ ep_update.access.access.type = KDBUS_POLICY_ACCESS_WORLD; |
28706 |
-+ ep_update.access.access.access = KDBUS_POLICY_SEE; |
28707 |
-+ |
28708 |
-+ ep_update.cmd.size = sizeof(ep_update); |
28709 |
-+ |
28710 |
-+ ret = kdbus_cmd_endpoint_update(fd, &ep_update.cmd); |
28711 |
-+ if (ret < 0) { |
28712 |
-+ kdbus_printf("error updating endpoint: %d (%m)\n", ret); |
28713 |
-+ return ret; |
28714 |
-+ } |
28715 |
-+ |
28716 |
-+ return 0; |
28717 |
-+} |
28718 |
-+ |
28719 |
-+int kdbus_test_custom_endpoint(struct kdbus_test_env *env) |
28720 |
-+{ |
28721 |
-+ char *ep, *tmp; |
28722 |
-+ int ret, ep_fd; |
28723 |
-+ struct kdbus_msg *msg; |
28724 |
-+ struct kdbus_conn *ep_conn; |
28725 |
-+ struct kdbus_conn *reader; |
28726 |
-+ const char *name = "foo.bar.baz"; |
28727 |
-+ const char *epname = "foo"; |
28728 |
-+ char fake_ep[KDBUS_SYSNAME_MAX_LEN + 1] = {'\0'}; |
28729 |
-+ |
28730 |
-+ memset(fake_ep, 'X', sizeof(fake_ep) - 1); |
28731 |
-+ |
28732 |
-+ /* Try to create a custom endpoint with a long name */ |
28733 |
-+ ret = create_endpoint(env->buspath, getuid(), fake_ep, 0); |
28734 |
-+ ASSERT_RETURN(ret == -ENAMETOOLONG); |
28735 |
-+ |
28736 |
-+ /* Try to create a custom endpoint with a different uid */ |
28737 |
-+ ret = create_endpoint(env->buspath, getuid() + 1, "foobar", 0); |
28738 |
-+ ASSERT_RETURN(ret == -EINVAL); |
28739 |
-+ |
28740 |
-+ /* create a custom endpoint, and open a connection on it */ |
28741 |
-+ ep_fd = create_endpoint(env->buspath, getuid(), "foo", 0); |
28742 |
-+ ASSERT_RETURN(ep_fd >= 0); |
28743 |
-+ |
28744 |
-+ tmp = strdup(env->buspath); |
28745 |
-+ ASSERT_RETURN(tmp); |
28746 |
-+ |
28747 |
-+ ret = asprintf(&ep, "%s/%u-%s", dirname(tmp), getuid(), epname); |
28748 |
-+ free(tmp); |
28749 |
-+ ASSERT_RETURN(ret >= 0); |
28750 |
-+ |
28751 |
-+ /* Register a connection that listen to broadcasts */ |
28752 |
-+ reader = kdbus_hello(ep, 0, NULL, 0); |
28753 |
-+ ASSERT_RETURN(reader); |
28754 |
-+ |
28755 |
-+ /* Register to kernel signals */ |
28756 |
-+ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, |
28757 |
-+ KDBUS_MATCH_ID_ANY); |
28758 |
-+ ASSERT_RETURN(ret == 0); |
28759 |
-+ |
28760 |
-+ ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, |
28761 |
-+ KDBUS_MATCH_ID_ANY); |
28762 |
-+ ASSERT_RETURN(ret == 0); |
28763 |
-+ |
28764 |
-+ ret = install_name_add_match(reader, name); |
28765 |
-+ ASSERT_RETURN(ret == 0); |
28766 |
-+ |
28767 |
-+ /* Monitor connections are not supported on custom endpoints */ |
28768 |
-+ ep_conn = kdbus_hello(ep, KDBUS_HELLO_MONITOR, NULL, 0); |
28769 |
-+ ASSERT_RETURN(!ep_conn && errno == EOPNOTSUPP); |
28770 |
-+ |
28771 |
-+ ep_conn = kdbus_hello(ep, 0, NULL, 0); |
28772 |
-+ ASSERT_RETURN(ep_conn); |
28773 |
-+ |
28774 |
-+ /* Check that the reader got the IdAdd notification */ |
28775 |
-+ ret = kdbus_msg_recv(reader, &msg, NULL); |
28776 |
-+ ASSERT_RETURN(ret == 0); |
28777 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD); |
28778 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == ep_conn->id); |
28779 |
-+ kdbus_msg_free(msg); |
28780 |
-+ |
28781 |
-+ /* |
28782 |
-+ * Add a name add match on the endpoint connection, acquire name from |
28783 |
-+ * the unfiltered connection, and make sure the filtered connection |
28784 |
-+ * did not get the notification on the name owner change. Also, the |
28785 |
-+ * endpoint connection may not be able to call conn_info, neither on |
28786 |
-+ * the name nor on the ID. |
28787 |
-+ */ |
28788 |
-+ ret = install_name_add_match(ep_conn, name); |
28789 |
-+ ASSERT_RETURN(ret == 0); |
28790 |
-+ |
28791 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
28792 |
-+ ASSERT_RETURN(ret == 0); |
28793 |
-+ |
28794 |
-+ ret = kdbus_msg_recv(ep_conn, NULL, NULL); |
28795 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
28796 |
-+ |
28797 |
-+ ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); |
28798 |
-+ ASSERT_RETURN(ret == -ESRCH); |
28799 |
-+ |
28800 |
-+ ret = kdbus_conn_info(ep_conn, 0, "random.crappy.name", 0, NULL); |
28801 |
-+ ASSERT_RETURN(ret == -ESRCH); |
28802 |
-+ |
28803 |
-+ ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); |
28804 |
-+ ASSERT_RETURN(ret == -ENXIO); |
28805 |
-+ |
28806 |
-+ ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL); |
28807 |
-+ ASSERT_RETURN(ret == -ENXIO); |
28808 |
-+ |
28809 |
-+ /* Check that the reader did not receive the name notification */ |
28810 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
28811 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
28812 |
-+ |
28813 |
-+ /* |
28814 |
-+ * Release the name again, update the custom endpoint policy, |
28815 |
-+ * and try again. This time, the connection on the custom endpoint |
28816 |
-+ * should have gotten it. |
28817 |
-+ */ |
28818 |
-+ ret = kdbus_name_release(env->conn, name); |
28819 |
-+ ASSERT_RETURN(ret == 0); |
28820 |
-+ |
28821 |
-+ /* Check that the reader did not receive the name notification */ |
28822 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
28823 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
28824 |
-+ |
28825 |
-+ ret = update_endpoint(ep_fd, name); |
28826 |
-+ ASSERT_RETURN(ret == 0); |
28827 |
-+ |
28828 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
28829 |
-+ ASSERT_RETURN(ret == 0); |
28830 |
-+ |
28831 |
-+ ret = kdbus_msg_recv(ep_conn, &msg, NULL); |
28832 |
-+ ASSERT_RETURN(ret == 0); |
28833 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); |
28834 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); |
28835 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); |
28836 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
28837 |
-+ kdbus_msg_free(msg); |
28838 |
-+ |
28839 |
-+ ret = kdbus_msg_recv(reader, &msg, NULL); |
28840 |
-+ ASSERT_RETURN(ret == 0); |
28841 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
28842 |
-+ |
28843 |
-+ kdbus_msg_free(msg); |
28844 |
-+ |
28845 |
-+ ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); |
28846 |
-+ ASSERT_RETURN(ret == 0); |
28847 |
-+ |
28848 |
-+ ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); |
28849 |
-+ ASSERT_RETURN(ret == 0); |
28850 |
-+ |
28851 |
-+ /* If we have privileges test custom endpoints */ |
28852 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
28853 |
-+ ASSERT_RETURN(ret >= 0); |
28854 |
-+ |
28855 |
-+ /* |
28856 |
-+ * All uids/gids are mapped and we have the necessary caps |
28857 |
-+ */ |
28858 |
-+ if (ret && all_uids_gids_are_mapped()) { |
28859 |
-+ ret = unpriv_test_custom_ep(env->buspath); |
28860 |
-+ ASSERT_RETURN(ret == 0); |
28861 |
-+ } |
28862 |
-+ |
28863 |
-+ kdbus_conn_free(reader); |
28864 |
-+ kdbus_conn_free(ep_conn); |
28865 |
-+ close(ep_fd); |
28866 |
-+ |
28867 |
-+ return TEST_OK; |
28868 |
-+} |
28869 |
-diff --git a/tools/testing/selftests/kdbus/test-fd.c b/tools/testing/selftests/kdbus/test-fd.c |
28870 |
-new file mode 100644 |
28871 |
-index 0000000..2ae0f5a |
28872 |
---- /dev/null |
28873 |
-+++ b/tools/testing/selftests/kdbus/test-fd.c |
28874 |
-@@ -0,0 +1,789 @@ |
28875 |
-+#include <stdio.h> |
28876 |
-+#include <string.h> |
28877 |
-+#include <time.h> |
28878 |
-+#include <fcntl.h> |
28879 |
-+#include <stdlib.h> |
28880 |
-+#include <stdbool.h> |
28881 |
-+#include <stddef.h> |
28882 |
-+#include <unistd.h> |
28883 |
-+#include <stdint.h> |
28884 |
-+#include <errno.h> |
28885 |
-+#include <assert.h> |
28886 |
-+#include <sys/types.h> |
28887 |
-+#include <sys/mman.h> |
28888 |
-+#include <sys/socket.h> |
28889 |
-+#include <sys/wait.h> |
28890 |
-+ |
28891 |
-+#include "kdbus-api.h" |
28892 |
-+#include "kdbus-test.h" |
28893 |
-+#include "kdbus-util.h" |
28894 |
-+#include "kdbus-enum.h" |
28895 |
-+ |
28896 |
-+#define KDBUS_MSG_MAX_ITEMS 128 |
28897 |
-+#define KDBUS_USER_MAX_CONN 256 |
28898 |
-+ |
28899 |
-+/* maximum number of inflight fds in a target queue per user */ |
28900 |
-+#define KDBUS_CONN_MAX_FDS_PER_USER 16 |
28901 |
-+ |
28902 |
-+/* maximum number of memfd items per message */ |
28903 |
-+#define KDBUS_MSG_MAX_MEMFD_ITEMS 16 |
28904 |
-+ |
28905 |
-+static int make_msg_payload_dbus(uint64_t src_id, uint64_t dst_id, |
28906 |
-+ uint64_t msg_size, |
28907 |
-+ struct kdbus_msg **msg_dbus) |
28908 |
-+{ |
28909 |
-+ struct kdbus_msg *msg; |
28910 |
-+ |
28911 |
-+ msg = malloc(msg_size); |
28912 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
28913 |
-+ |
28914 |
-+ memset(msg, 0, msg_size); |
28915 |
-+ msg->size = msg_size; |
28916 |
-+ msg->src_id = src_id; |
28917 |
-+ msg->dst_id = dst_id; |
28918 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
28919 |
-+ |
28920 |
-+ *msg_dbus = msg; |
28921 |
-+ |
28922 |
-+ return 0; |
28923 |
-+} |
28924 |
-+ |
28925 |
-+static void make_item_memfds(struct kdbus_item *item, |
28926 |
-+ int *memfds, size_t memfd_size) |
28927 |
-+{ |
28928 |
-+ size_t i; |
28929 |
-+ |
28930 |
-+ for (i = 0; i < memfd_size; i++) { |
28931 |
-+ item->type = KDBUS_ITEM_PAYLOAD_MEMFD; |
28932 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + |
28933 |
-+ sizeof(struct kdbus_memfd); |
28934 |
-+ item->memfd.fd = memfds[i]; |
28935 |
-+ item->memfd.size = sizeof(uint64_t); /* const size */ |
28936 |
-+ item = KDBUS_ITEM_NEXT(item); |
28937 |
-+ } |
28938 |
-+} |
28939 |
-+ |
28940 |
-+static void make_item_fds(struct kdbus_item *item, |
28941 |
-+ int *fd_array, size_t fd_size) |
28942 |
-+{ |
28943 |
-+ size_t i; |
28944 |
-+ item->type = KDBUS_ITEM_FDS; |
28945 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + (sizeof(int) * fd_size); |
28946 |
-+ |
28947 |
-+ for (i = 0; i < fd_size; i++) |
28948 |
-+ item->fds[i] = fd_array[i]; |
28949 |
-+} |
28950 |
-+ |
28951 |
-+static int memfd_write(const char *name, void *buf, size_t bufsize) |
28952 |
-+{ |
28953 |
-+ ssize_t ret; |
28954 |
-+ int memfd; |
28955 |
-+ |
28956 |
-+ memfd = sys_memfd_create(name, 0); |
28957 |
-+ ASSERT_RETURN_VAL(memfd >= 0, memfd); |
28958 |
-+ |
28959 |
-+ ret = write(memfd, buf, bufsize); |
28960 |
-+ ASSERT_RETURN_VAL(ret == (ssize_t)bufsize, -EAGAIN); |
28961 |
-+ |
28962 |
-+ ret = sys_memfd_seal_set(memfd); |
28963 |
-+ ASSERT_RETURN_VAL(ret == 0, -errno); |
28964 |
-+ |
28965 |
-+ return memfd; |
28966 |
-+} |
28967 |
-+ |
28968 |
-+static int send_memfds(struct kdbus_conn *conn, uint64_t dst_id, |
28969 |
-+ int *memfds_array, size_t memfd_count) |
28970 |
-+{ |
28971 |
-+ struct kdbus_cmd_send cmd = {}; |
28972 |
-+ struct kdbus_item *item; |
28973 |
-+ struct kdbus_msg *msg; |
28974 |
-+ uint64_t size; |
28975 |
-+ int ret; |
28976 |
-+ |
28977 |
-+ size = sizeof(struct kdbus_msg); |
28978 |
-+ size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
28979 |
-+ |
28980 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
28981 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
28982 |
-+ |
28983 |
-+ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
28984 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
28985 |
-+ |
28986 |
-+ item = msg->items; |
28987 |
-+ |
28988 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
28989 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
28990 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
28991 |
-+ item = KDBUS_ITEM_NEXT(item); |
28992 |
-+ |
28993 |
-+ msg->flags |= KDBUS_MSG_SIGNAL; |
28994 |
-+ } |
28995 |
-+ |
28996 |
-+ make_item_memfds(item, memfds_array, memfd_count); |
28997 |
-+ |
28998 |
-+ cmd.size = sizeof(cmd); |
28999 |
-+ cmd.msg_address = (uintptr_t)msg; |
29000 |
-+ |
29001 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
29002 |
-+ if (ret < 0) { |
29003 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
29004 |
-+ return ret; |
29005 |
-+ } |
29006 |
-+ |
29007 |
-+ free(msg); |
29008 |
-+ return 0; |
29009 |
-+} |
29010 |
-+ |
29011 |
-+static int send_fds(struct kdbus_conn *conn, uint64_t dst_id, |
29012 |
-+ int *fd_array, size_t fd_count) |
29013 |
-+{ |
29014 |
-+ struct kdbus_cmd_send cmd = {}; |
29015 |
-+ struct kdbus_item *item; |
29016 |
-+ struct kdbus_msg *msg; |
29017 |
-+ uint64_t size; |
29018 |
-+ int ret; |
29019 |
-+ |
29020 |
-+ size = sizeof(struct kdbus_msg); |
29021 |
-+ size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count); |
29022 |
-+ |
29023 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) |
29024 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29025 |
-+ |
29026 |
-+ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29027 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
29028 |
-+ |
29029 |
-+ item = msg->items; |
29030 |
-+ |
29031 |
-+ if (dst_id == KDBUS_DST_ID_BROADCAST) { |
29032 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
29033 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64; |
29034 |
-+ item = KDBUS_ITEM_NEXT(item); |
29035 |
-+ |
29036 |
-+ msg->flags |= KDBUS_MSG_SIGNAL; |
29037 |
-+ } |
29038 |
-+ |
29039 |
-+ make_item_fds(item, fd_array, fd_count); |
29040 |
-+ |
29041 |
-+ cmd.size = sizeof(cmd); |
29042 |
-+ cmd.msg_address = (uintptr_t)msg; |
29043 |
-+ |
29044 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
29045 |
-+ if (ret < 0) { |
29046 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
29047 |
-+ return ret; |
29048 |
-+ } |
29049 |
-+ |
29050 |
-+ free(msg); |
29051 |
-+ return ret; |
29052 |
-+} |
29053 |
-+ |
29054 |
-+static int send_fds_memfds(struct kdbus_conn *conn, uint64_t dst_id, |
29055 |
-+ int *fds_array, size_t fd_count, |
29056 |
-+ int *memfds_array, size_t memfd_count) |
29057 |
-+{ |
29058 |
-+ struct kdbus_cmd_send cmd = {}; |
29059 |
-+ struct kdbus_item *item; |
29060 |
-+ struct kdbus_msg *msg; |
29061 |
-+ uint64_t size; |
29062 |
-+ int ret; |
29063 |
-+ |
29064 |
-+ size = sizeof(struct kdbus_msg); |
29065 |
-+ size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd)); |
29066 |
-+ size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count); |
29067 |
-+ |
29068 |
-+ ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg); |
29069 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
29070 |
-+ |
29071 |
-+ item = msg->items; |
29072 |
-+ |
29073 |
-+ make_item_fds(item, fds_array, fd_count); |
29074 |
-+ item = KDBUS_ITEM_NEXT(item); |
29075 |
-+ make_item_memfds(item, memfds_array, memfd_count); |
29076 |
-+ |
29077 |
-+ cmd.size = sizeof(cmd); |
29078 |
-+ cmd.msg_address = (uintptr_t)msg; |
29079 |
-+ |
29080 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
29081 |
-+ if (ret < 0) { |
29082 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
29083 |
-+ return ret; |
29084 |
-+ } |
29085 |
-+ |
29086 |
-+ free(msg); |
29087 |
-+ return ret; |
29088 |
-+} |
29089 |
-+ |
29090 |
-+/* Return the number of received fds */ |
29091 |
-+static unsigned int kdbus_item_get_nfds(struct kdbus_msg *msg) |
29092 |
-+{ |
29093 |
-+ unsigned int fds = 0; |
29094 |
-+ const struct kdbus_item *item; |
29095 |
-+ |
29096 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
29097 |
-+ switch (item->type) { |
29098 |
-+ case KDBUS_ITEM_FDS: { |
29099 |
-+ fds += (item->size - KDBUS_ITEM_HEADER_SIZE) / |
29100 |
-+ sizeof(int); |
29101 |
-+ break; |
29102 |
-+ } |
29103 |
-+ |
29104 |
-+ case KDBUS_ITEM_PAYLOAD_MEMFD: |
29105 |
-+ fds++; |
29106 |
-+ break; |
29107 |
-+ |
29108 |
-+ default: |
29109 |
-+ break; |
29110 |
-+ } |
29111 |
-+ } |
29112 |
-+ |
29113 |
-+ return fds; |
29114 |
-+} |
29115 |
-+ |
29116 |
-+static struct kdbus_msg * |
29117 |
-+get_kdbus_msg_with_fd(struct kdbus_conn *conn_src, |
29118 |
-+ uint64_t dst_id, uint64_t cookie, int fd) |
29119 |
-+{ |
29120 |
-+ int ret; |
29121 |
-+ uint64_t size; |
29122 |
-+ struct kdbus_item *item; |
29123 |
-+ struct kdbus_msg *msg; |
29124 |
-+ |
29125 |
-+ size = sizeof(struct kdbus_msg); |
29126 |
-+ if (fd >= 0) |
29127 |
-+ size += KDBUS_ITEM_SIZE(sizeof(int)); |
29128 |
-+ |
29129 |
-+ ret = make_msg_payload_dbus(conn_src->id, dst_id, size, &msg); |
29130 |
-+ ASSERT_RETURN_VAL(ret == 0, NULL); |
29131 |
-+ |
29132 |
-+ msg->cookie = cookie; |
29133 |
-+ |
29134 |
-+ if (fd >= 0) { |
29135 |
-+ item = msg->items; |
29136 |
-+ |
29137 |
-+ make_item_fds(item, (int *)&fd, 1); |
29138 |
-+ } |
29139 |
-+ |
29140 |
-+ return msg; |
29141 |
-+} |
29142 |
-+ |
29143 |
-+static int kdbus_test_no_fds(struct kdbus_test_env *env, |
29144 |
-+ int *fds, int *memfd) |
29145 |
-+{ |
29146 |
-+ pid_t pid; |
29147 |
-+ int ret, status; |
29148 |
-+ uint64_t cookie; |
29149 |
-+ int connfd1, connfd2; |
29150 |
-+ struct kdbus_msg *msg, *msg_sync_reply; |
29151 |
-+ struct kdbus_cmd_hello hello; |
29152 |
-+ struct kdbus_conn *conn_src, *conn_dst, *conn_dummy; |
29153 |
-+ struct kdbus_cmd_send cmd = {}; |
29154 |
-+ struct kdbus_cmd_free cmd_free = {}; |
29155 |
-+ |
29156 |
-+ conn_src = kdbus_hello(env->buspath, 0, NULL, 0); |
29157 |
-+ ASSERT_RETURN(conn_src); |
29158 |
-+ |
29159 |
-+ connfd1 = open(env->buspath, O_RDWR|O_CLOEXEC); |
29160 |
-+ ASSERT_RETURN(connfd1 >= 0); |
29161 |
-+ |
29162 |
-+ connfd2 = open(env->buspath, O_RDWR|O_CLOEXEC); |
29163 |
-+ ASSERT_RETURN(connfd2 >= 0); |
29164 |
-+ |
29165 |
-+ /* |
29166 |
-+ * Create connections without KDBUS_HELLO_ACCEPT_FD |
29167 |
-+ * to test if send fd operations are blocked |
29168 |
-+ */ |
29169 |
-+ conn_dst = malloc(sizeof(*conn_dst)); |
29170 |
-+ ASSERT_RETURN(conn_dst); |
29171 |
-+ |
29172 |
-+ conn_dummy = malloc(sizeof(*conn_dummy)); |
29173 |
-+ ASSERT_RETURN(conn_dummy); |
29174 |
-+ |
29175 |
-+ memset(&hello, 0, sizeof(hello)); |
29176 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
29177 |
-+ hello.pool_size = POOL_SIZE; |
29178 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
29179 |
-+ |
29180 |
-+ ret = kdbus_cmd_hello(connfd1, &hello); |
29181 |
-+ ASSERT_RETURN(ret == 0); |
29182 |
-+ |
29183 |
-+ cmd_free.size = sizeof(cmd_free); |
29184 |
-+ cmd_free.offset = hello.offset; |
29185 |
-+ ret = kdbus_cmd_free(connfd1, &cmd_free); |
29186 |
-+ ASSERT_RETURN(ret >= 0); |
29187 |
-+ |
29188 |
-+ conn_dst->fd = connfd1; |
29189 |
-+ conn_dst->id = hello.id; |
29190 |
-+ |
29191 |
-+ memset(&hello, 0, sizeof(hello)); |
29192 |
-+ hello.size = sizeof(struct kdbus_cmd_hello); |
29193 |
-+ hello.pool_size = POOL_SIZE; |
29194 |
-+ hello.attach_flags_send = _KDBUS_ATTACH_ALL; |
29195 |
-+ |
29196 |
-+ ret = kdbus_cmd_hello(connfd2, &hello); |
29197 |
-+ ASSERT_RETURN(ret == 0); |
29198 |
-+ |
29199 |
-+ cmd_free.size = sizeof(cmd_free); |
29200 |
-+ cmd_free.offset = hello.offset; |
29201 |
-+ ret = kdbus_cmd_free(connfd2, &cmd_free); |
29202 |
-+ ASSERT_RETURN(ret >= 0); |
29203 |
-+ |
29204 |
-+ conn_dummy->fd = connfd2; |
29205 |
-+ conn_dummy->id = hello.id; |
29206 |
-+ |
29207 |
-+ conn_dst->buf = mmap(NULL, POOL_SIZE, PROT_READ, |
29208 |
-+ MAP_SHARED, connfd1, 0); |
29209 |
-+ ASSERT_RETURN(conn_dst->buf != MAP_FAILED); |
29210 |
-+ |
29211 |
-+ conn_dummy->buf = mmap(NULL, POOL_SIZE, PROT_READ, |
29212 |
-+ MAP_SHARED, connfd2, 0); |
29213 |
-+ ASSERT_RETURN(conn_dummy->buf != MAP_FAILED); |
29214 |
-+ |
29215 |
-+ /* |
29216 |
-+ * Send fds to connection that do not accept fd passing |
29217 |
-+ */ |
29218 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29219 |
-+ ASSERT_RETURN(ret == -ECOMM); |
29220 |
-+ |
29221 |
-+ /* |
29222 |
-+ * memfd are kdbus payload |
29223 |
-+ */ |
29224 |
-+ ret = send_memfds(conn_src, conn_dst->id, memfd, 1); |
29225 |
-+ ASSERT_RETURN(ret == 0); |
29226 |
-+ |
29227 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 100, NULL, NULL); |
29228 |
-+ ASSERT_RETURN(ret == 0); |
29229 |
-+ |
29230 |
-+ cookie = time(NULL); |
29231 |
-+ |
29232 |
-+ pid = fork(); |
29233 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
29234 |
-+ |
29235 |
-+ if (pid == 0) { |
29236 |
-+ struct timespec now; |
29237 |
-+ |
29238 |
-+ /* |
29239 |
-+ * A sync send/reply to a connection that do not |
29240 |
-+ * accept fds should fail if it contains an fd |
29241 |
-+ */ |
29242 |
-+ msg_sync_reply = get_kdbus_msg_with_fd(conn_dst, |
29243 |
-+ conn_dummy->id, |
29244 |
-+ cookie, fds[0]); |
29245 |
-+ ASSERT_EXIT(msg_sync_reply); |
29246 |
-+ |
29247 |
-+ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now); |
29248 |
-+ ASSERT_EXIT(ret == 0); |
29249 |
-+ |
29250 |
-+ msg_sync_reply->timeout_ns = now.tv_sec * 1000000000ULL + |
29251 |
-+ now.tv_nsec + 100000000ULL; |
29252 |
-+ msg_sync_reply->flags = KDBUS_MSG_EXPECT_REPLY; |
29253 |
-+ |
29254 |
-+ memset(&cmd, 0, sizeof(cmd)); |
29255 |
-+ cmd.size = sizeof(cmd); |
29256 |
-+ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29257 |
-+ cmd.flags = KDBUS_SEND_SYNC_REPLY; |
29258 |
-+ |
29259 |
-+ ret = kdbus_cmd_send(conn_dst->fd, &cmd); |
29260 |
-+ ASSERT_EXIT(ret == -ECOMM); |
29261 |
-+ |
29262 |
-+ /* |
29263 |
-+ * Now send a normal message, but the sync reply |
29264 |
-+ * will fail since it contains an fd that the |
29265 |
-+ * original sender do not want. |
29266 |
-+ * |
29267 |
-+ * The original sender will fail with -ETIMEDOUT |
29268 |
-+ */ |
29269 |
-+ cookie++; |
29270 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
29271 |
-+ KDBUS_MSG_EXPECT_REPLY, |
29272 |
-+ 5000000000ULL, 0, conn_src->id, -1); |
29273 |
-+ ASSERT_EXIT(ret == -EREMOTEIO); |
29274 |
-+ |
29275 |
-+ cookie++; |
29276 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); |
29277 |
-+ ASSERT_EXIT(ret == 0); |
29278 |
-+ ASSERT_EXIT(msg->cookie == cookie); |
29279 |
-+ |
29280 |
-+ free(msg_sync_reply); |
29281 |
-+ kdbus_msg_free(msg); |
29282 |
-+ |
29283 |
-+ _exit(EXIT_SUCCESS); |
29284 |
-+ } |
29285 |
-+ |
29286 |
-+ ret = kdbus_msg_recv_poll(conn_dummy, 100, NULL, NULL); |
29287 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
29288 |
-+ |
29289 |
-+ cookie++; |
29290 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
29291 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
29292 |
-+ |
29293 |
-+ kdbus_msg_free(msg); |
29294 |
-+ |
29295 |
-+ /* |
29296 |
-+ * Try to reply with a kdbus connection handle, this should |
29297 |
-+ * fail with -EOPNOTSUPP |
29298 |
-+ */ |
29299 |
-+ msg_sync_reply = get_kdbus_msg_with_fd(conn_src, |
29300 |
-+ conn_dst->id, |
29301 |
-+ cookie, conn_dst->fd); |
29302 |
-+ ASSERT_RETURN(msg_sync_reply); |
29303 |
-+ |
29304 |
-+ msg_sync_reply->cookie_reply = cookie; |
29305 |
-+ |
29306 |
-+ memset(&cmd, 0, sizeof(cmd)); |
29307 |
-+ cmd.size = sizeof(cmd); |
29308 |
-+ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29309 |
-+ |
29310 |
-+ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
29311 |
-+ ASSERT_RETURN(ret == -EOPNOTSUPP); |
29312 |
-+ |
29313 |
-+ free(msg_sync_reply); |
29314 |
-+ |
29315 |
-+ /* |
29316 |
-+ * Try to reply with a normal fd, this should fail even |
29317 |
-+ * if the response is a sync reply |
29318 |
-+ * |
29319 |
-+ * From the sender view we fail with -ECOMM |
29320 |
-+ */ |
29321 |
-+ msg_sync_reply = get_kdbus_msg_with_fd(conn_src, |
29322 |
-+ conn_dst->id, |
29323 |
-+ cookie, fds[0]); |
29324 |
-+ ASSERT_RETURN(msg_sync_reply); |
29325 |
-+ |
29326 |
-+ msg_sync_reply->cookie_reply = cookie; |
29327 |
-+ |
29328 |
-+ memset(&cmd, 0, sizeof(cmd)); |
29329 |
-+ cmd.size = sizeof(cmd); |
29330 |
-+ cmd.msg_address = (uintptr_t)msg_sync_reply; |
29331 |
-+ |
29332 |
-+ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
29333 |
-+ ASSERT_RETURN(ret == -ECOMM); |
29334 |
-+ |
29335 |
-+ free(msg_sync_reply); |
29336 |
-+ |
29337 |
-+ /* |
29338 |
-+ * Resend another normal message and check if the queue |
29339 |
-+ * is clear |
29340 |
-+ */ |
29341 |
-+ cookie++; |
29342 |
-+ ret = kdbus_msg_send(conn_src, NULL, cookie, 0, 0, 0, |
29343 |
-+ conn_dst->id); |
29344 |
-+ ASSERT_RETURN(ret == 0); |
29345 |
-+ |
29346 |
-+ ret = waitpid(pid, &status, 0); |
29347 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
29348 |
-+ |
29349 |
-+ kdbus_conn_free(conn_dummy); |
29350 |
-+ kdbus_conn_free(conn_dst); |
29351 |
-+ kdbus_conn_free(conn_src); |
29352 |
-+ |
29353 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
29354 |
-+} |
29355 |
-+ |
29356 |
-+static int kdbus_send_multiple_fds(struct kdbus_conn *conn_src, |
29357 |
-+ struct kdbus_conn *conn_dst) |
29358 |
-+{ |
29359 |
-+ int ret, i; |
29360 |
-+ unsigned int nfds; |
29361 |
-+ int fds[KDBUS_CONN_MAX_FDS_PER_USER + 1]; |
29362 |
-+ int memfds[KDBUS_MSG_MAX_ITEMS + 1]; |
29363 |
-+ struct kdbus_msg *msg; |
29364 |
-+ uint64_t dummy_value; |
29365 |
-+ |
29366 |
-+ dummy_value = time(NULL); |
29367 |
-+ |
29368 |
-+ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) { |
29369 |
-+ fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC); |
29370 |
-+ ASSERT_RETURN_VAL(fds[i] >= 0, -errno); |
29371 |
-+ } |
29372 |
-+ |
29373 |
-+ /* Send KDBUS_CONN_MAX_FDS_PER_USER with one more fd */ |
29374 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, |
29375 |
-+ KDBUS_CONN_MAX_FDS_PER_USER + 1); |
29376 |
-+ ASSERT_RETURN(ret == -EMFILE); |
29377 |
-+ |
29378 |
-+ /* Retry with the correct KDBUS_CONN_MAX_FDS_PER_USER */ |
29379 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, |
29380 |
-+ KDBUS_CONN_MAX_FDS_PER_USER); |
29381 |
-+ ASSERT_RETURN(ret == 0); |
29382 |
-+ |
29383 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29384 |
-+ ASSERT_RETURN(ret == 0); |
29385 |
-+ |
29386 |
-+ /* Check we got the right number of fds */ |
29387 |
-+ nfds = kdbus_item_get_nfds(msg); |
29388 |
-+ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER); |
29389 |
-+ |
29390 |
-+ kdbus_msg_free(msg); |
29391 |
-+ |
29392 |
-+ for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++, dummy_value++) { |
29393 |
-+ memfds[i] = memfd_write("memfd-name", |
29394 |
-+ &dummy_value, |
29395 |
-+ sizeof(dummy_value)); |
29396 |
-+ ASSERT_RETURN_VAL(memfds[i] >= 0, memfds[i]); |
29397 |
-+ } |
29398 |
-+ |
29399 |
-+ /* Send KDBUS_MSG_MAX_ITEMS with one more memfd */ |
29400 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29401 |
-+ memfds, KDBUS_MSG_MAX_ITEMS + 1); |
29402 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29403 |
-+ |
29404 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29405 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1); |
29406 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29407 |
-+ |
29408 |
-+ /* Retry with the correct KDBUS_MSG_MAX_ITEMS */ |
29409 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29410 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29411 |
-+ ASSERT_RETURN(ret == 0); |
29412 |
-+ |
29413 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29414 |
-+ ASSERT_RETURN(ret == 0); |
29415 |
-+ |
29416 |
-+ /* Check we got the right number of fds */ |
29417 |
-+ nfds = kdbus_item_get_nfds(msg); |
29418 |
-+ ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS); |
29419 |
-+ |
29420 |
-+ kdbus_msg_free(msg); |
29421 |
-+ |
29422 |
-+ |
29423 |
-+ /* |
29424 |
-+ * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER+1 fds and |
29425 |
-+ * 10 memfds |
29426 |
-+ */ |
29427 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29428 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER + 1, |
29429 |
-+ memfds, 10); |
29430 |
-+ ASSERT_RETURN(ret == -EMFILE); |
29431 |
-+ |
29432 |
-+ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29433 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
29434 |
-+ |
29435 |
-+ /* |
29436 |
-+ * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER fds and |
29437 |
-+ * (128 - 1) + 1 memfds, all fds take one item, while each |
29438 |
-+ * memfd takes one item |
29439 |
-+ */ |
29440 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29441 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29442 |
-+ memfds, (KDBUS_MSG_MAX_ITEMS - 1) + 1); |
29443 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29444 |
-+ |
29445 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29446 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29447 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1); |
29448 |
-+ ASSERT_RETURN(ret == -E2BIG); |
29449 |
-+ |
29450 |
-+ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29451 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
29452 |
-+ |
29453 |
-+ /* |
29454 |
-+ * Send KDBUS_CONN_MAX_FDS_PER_USER fds + |
29455 |
-+ * KDBUS_MSG_MAX_MEMFD_ITEMS memfds |
29456 |
-+ */ |
29457 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29458 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29459 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29460 |
-+ ASSERT_RETURN(ret == 0); |
29461 |
-+ |
29462 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29463 |
-+ ASSERT_RETURN(ret == 0); |
29464 |
-+ |
29465 |
-+ /* Check we got the right number of fds */ |
29466 |
-+ nfds = kdbus_item_get_nfds(msg); |
29467 |
-+ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER + |
29468 |
-+ KDBUS_MSG_MAX_MEMFD_ITEMS); |
29469 |
-+ |
29470 |
-+ kdbus_msg_free(msg); |
29471 |
-+ |
29472 |
-+ |
29473 |
-+ /* |
29474 |
-+ * Re-send fds + memfds, close them, but do not receive them |
29475 |
-+ * and try to queue more |
29476 |
-+ */ |
29477 |
-+ ret = send_fds_memfds(conn_src, conn_dst->id, |
29478 |
-+ fds, KDBUS_CONN_MAX_FDS_PER_USER, |
29479 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29480 |
-+ ASSERT_RETURN(ret == 0); |
29481 |
-+ |
29482 |
-+ /* close old references and get a new ones */ |
29483 |
-+ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) { |
29484 |
-+ close(fds[i]); |
29485 |
-+ fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC); |
29486 |
-+ ASSERT_RETURN_VAL(fds[i] >= 0, -errno); |
29487 |
-+ } |
29488 |
-+ |
29489 |
-+ /* should fail since we have already fds in the queue */ |
29490 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, |
29491 |
-+ KDBUS_CONN_MAX_FDS_PER_USER); |
29492 |
-+ ASSERT_RETURN(ret == -EMFILE); |
29493 |
-+ |
29494 |
-+ /* This should succeed */ |
29495 |
-+ ret = send_memfds(conn_src, conn_dst->id, |
29496 |
-+ memfds, KDBUS_MSG_MAX_MEMFD_ITEMS); |
29497 |
-+ ASSERT_RETURN(ret == 0); |
29498 |
-+ |
29499 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29500 |
-+ ASSERT_RETURN(ret == 0); |
29501 |
-+ |
29502 |
-+ nfds = kdbus_item_get_nfds(msg); |
29503 |
-+ ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER + |
29504 |
-+ KDBUS_MSG_MAX_MEMFD_ITEMS); |
29505 |
-+ |
29506 |
-+ kdbus_msg_free(msg); |
29507 |
-+ |
29508 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29509 |
-+ ASSERT_RETURN(ret == 0); |
29510 |
-+ |
29511 |
-+ nfds = kdbus_item_get_nfds(msg); |
29512 |
-+ ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS); |
29513 |
-+ |
29514 |
-+ kdbus_msg_free(msg); |
29515 |
-+ |
29516 |
-+ ret = kdbus_msg_recv(conn_dst, NULL, NULL); |
29517 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
29518 |
-+ |
29519 |
-+ for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) |
29520 |
-+ close(fds[i]); |
29521 |
-+ |
29522 |
-+ for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++) |
29523 |
-+ close(memfds[i]); |
29524 |
-+ |
29525 |
-+ return 0; |
29526 |
-+} |
29527 |
-+ |
29528 |
-+int kdbus_test_fd_passing(struct kdbus_test_env *env) |
29529 |
-+{ |
29530 |
-+ struct kdbus_conn *conn_src, *conn_dst; |
29531 |
-+ const char *str = "stackenblocken"; |
29532 |
-+ const struct kdbus_item *item; |
29533 |
-+ struct kdbus_msg *msg; |
29534 |
-+ unsigned int i; |
29535 |
-+ uint64_t now; |
29536 |
-+ int fds_conn[2]; |
29537 |
-+ int sock_pair[2]; |
29538 |
-+ int fds[2]; |
29539 |
-+ int memfd; |
29540 |
-+ int ret; |
29541 |
-+ |
29542 |
-+ now = (uint64_t) time(NULL); |
29543 |
-+ |
29544 |
-+ /* create two connections */ |
29545 |
-+ conn_src = kdbus_hello(env->buspath, 0, NULL, 0); |
29546 |
-+ conn_dst = kdbus_hello(env->buspath, 0, NULL, 0); |
29547 |
-+ ASSERT_RETURN(conn_src && conn_dst); |
29548 |
-+ |
29549 |
-+ fds_conn[0] = conn_src->fd; |
29550 |
-+ fds_conn[1] = conn_dst->fd; |
29551 |
-+ |
29552 |
-+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair); |
29553 |
-+ ASSERT_RETURN(ret == 0); |
29554 |
-+ |
29555 |
-+ /* Setup memfd */ |
29556 |
-+ memfd = memfd_write("memfd-name", &now, sizeof(now)); |
29557 |
-+ ASSERT_RETURN(memfd >= 0); |
29558 |
-+ |
29559 |
-+ /* Setup pipes */ |
29560 |
-+ ret = pipe(fds); |
29561 |
-+ ASSERT_RETURN(ret == 0); |
29562 |
-+ |
29563 |
-+ i = write(fds[1], str, strlen(str)); |
29564 |
-+ ASSERT_RETURN(i == strlen(str)); |
29565 |
-+ |
29566 |
-+ /* |
29567 |
-+ * Try to ass the handle of a connection as message payload. |
29568 |
-+ * This must fail. |
29569 |
-+ */ |
29570 |
-+ ret = send_fds(conn_src, conn_dst->id, fds_conn, 2); |
29571 |
-+ ASSERT_RETURN(ret == -ENOTSUP); |
29572 |
-+ |
29573 |
-+ ret = send_fds(conn_dst, conn_src->id, fds_conn, 2); |
29574 |
-+ ASSERT_RETURN(ret == -ENOTSUP); |
29575 |
-+ |
29576 |
-+ ret = send_fds(conn_src, conn_dst->id, sock_pair, 2); |
29577 |
-+ ASSERT_RETURN(ret == -ENOTSUP); |
29578 |
-+ |
29579 |
-+ /* |
29580 |
-+ * Send fds and memfds to connection that do not accept fds |
29581 |
-+ */ |
29582 |
-+ ret = kdbus_test_no_fds(env, fds, (int *)&memfd); |
29583 |
-+ ASSERT_RETURN(ret == 0); |
29584 |
-+ |
29585 |
-+ /* Try to broadcast file descriptors. This must fail. */ |
29586 |
-+ ret = send_fds(conn_src, KDBUS_DST_ID_BROADCAST, fds, 1); |
29587 |
-+ ASSERT_RETURN(ret == -ENOTUNIQ); |
29588 |
-+ |
29589 |
-+ /* Try to broadcast memfd. This must succeed. */ |
29590 |
-+ ret = send_memfds(conn_src, KDBUS_DST_ID_BROADCAST, (int *)&memfd, 1); |
29591 |
-+ ASSERT_RETURN(ret == 0); |
29592 |
-+ |
29593 |
-+ /* Open code this loop */ |
29594 |
-+loop_send_fds: |
29595 |
-+ |
29596 |
-+ /* |
29597 |
-+ * Send the read end of the pipe and close it. |
29598 |
-+ */ |
29599 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29600 |
-+ ASSERT_RETURN(ret == 0); |
29601 |
-+ close(fds[0]); |
29602 |
-+ |
29603 |
-+ ret = kdbus_msg_recv(conn_dst, &msg, NULL); |
29604 |
-+ ASSERT_RETURN(ret == 0); |
29605 |
-+ |
29606 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) { |
29607 |
-+ if (item->type == KDBUS_ITEM_FDS) { |
29608 |
-+ char tmp[14]; |
29609 |
-+ int nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) / |
29610 |
-+ sizeof(int); |
29611 |
-+ ASSERT_RETURN(nfds == 1); |
29612 |
-+ |
29613 |
-+ i = read(item->fds[0], tmp, sizeof(tmp)); |
29614 |
-+ if (i != 0) { |
29615 |
-+ ASSERT_RETURN(i == sizeof(tmp)); |
29616 |
-+ ASSERT_RETURN(memcmp(tmp, str, sizeof(tmp)) == 0); |
29617 |
-+ |
29618 |
-+ /* Write EOF */ |
29619 |
-+ close(fds[1]); |
29620 |
-+ |
29621 |
-+ /* |
29622 |
-+ * Resend the read end of the pipe, |
29623 |
-+ * the receiver still holds a reference |
29624 |
-+ * to it... |
29625 |
-+ */ |
29626 |
-+ goto loop_send_fds; |
29627 |
-+ } |
29628 |
-+ |
29629 |
-+ /* Got EOF */ |
29630 |
-+ |
29631 |
-+ /* |
29632 |
-+ * Close the last reference to the read end |
29633 |
-+ * of the pipe, other references are |
29634 |
-+ * automatically closed just after send. |
29635 |
-+ */ |
29636 |
-+ close(item->fds[0]); |
29637 |
-+ } |
29638 |
-+ } |
29639 |
-+ |
29640 |
-+ /* |
29641 |
-+ * Try to resend the read end of the pipe. Must fail with |
29642 |
-+ * -EBADF since both the sender and receiver closed their |
29643 |
-+ * references to it. We assume the above since sender and |
29644 |
-+ * receiver are on the same process. |
29645 |
-+ */ |
29646 |
-+ ret = send_fds(conn_src, conn_dst->id, fds, 1); |
29647 |
-+ ASSERT_RETURN(ret == -EBADF); |
29648 |
-+ |
29649 |
-+ /* Then we clear out received any data... */ |
29650 |
-+ kdbus_msg_free(msg); |
29651 |
-+ |
29652 |
-+ ret = kdbus_send_multiple_fds(conn_src, conn_dst); |
29653 |
-+ ASSERT_RETURN(ret == 0); |
29654 |
-+ |
29655 |
-+ close(sock_pair[0]); |
29656 |
-+ close(sock_pair[1]); |
29657 |
-+ close(memfd); |
29658 |
-+ |
29659 |
-+ kdbus_conn_free(conn_src); |
29660 |
-+ kdbus_conn_free(conn_dst); |
29661 |
-+ |
29662 |
-+ return TEST_OK; |
29663 |
-+} |
29664 |
-diff --git a/tools/testing/selftests/kdbus/test-free.c b/tools/testing/selftests/kdbus/test-free.c |
29665 |
-new file mode 100644 |
29666 |
-index 0000000..f666da3 |
29667 |
---- /dev/null |
29668 |
-+++ b/tools/testing/selftests/kdbus/test-free.c |
29669 |
-@@ -0,0 +1,64 @@ |
29670 |
-+#include <stdio.h> |
29671 |
-+#include <string.h> |
29672 |
-+#include <fcntl.h> |
29673 |
-+#include <stdlib.h> |
29674 |
-+#include <stddef.h> |
29675 |
-+#include <unistd.h> |
29676 |
-+#include <stdint.h> |
29677 |
-+#include <errno.h> |
29678 |
-+#include <assert.h> |
29679 |
-+#include <stdbool.h> |
29680 |
-+ |
29681 |
-+#include "kdbus-api.h" |
29682 |
-+#include "kdbus-util.h" |
29683 |
-+#include "kdbus-enum.h" |
29684 |
-+#include "kdbus-test.h" |
29685 |
-+ |
29686 |
-+static int sample_ioctl_call(struct kdbus_test_env *env) |
29687 |
-+{ |
29688 |
-+ int ret; |
29689 |
-+ struct kdbus_cmd_list cmd_list = { |
29690 |
-+ .flags = KDBUS_LIST_QUEUED, |
29691 |
-+ .size = sizeof(cmd_list), |
29692 |
-+ }; |
29693 |
-+ |
29694 |
-+ ret = kdbus_cmd_list(env->conn->fd, &cmd_list); |
29695 |
-+ ASSERT_RETURN(ret == 0); |
29696 |
-+ |
29697 |
-+ /* DON'T FREE THIS SLICE OF MEMORY! */ |
29698 |
-+ |
29699 |
-+ return TEST_OK; |
29700 |
-+} |
29701 |
-+ |
29702 |
-+int kdbus_test_free(struct kdbus_test_env *env) |
29703 |
-+{ |
29704 |
-+ int ret; |
29705 |
-+ struct kdbus_cmd_free cmd_free = {}; |
29706 |
-+ |
29707 |
-+ /* free an unallocated buffer */ |
29708 |
-+ cmd_free.size = sizeof(cmd_free); |
29709 |
-+ cmd_free.flags = 0; |
29710 |
-+ cmd_free.offset = 0; |
29711 |
-+ ret = kdbus_cmd_free(env->conn->fd, &cmd_free); |
29712 |
-+ ASSERT_RETURN(ret == -ENXIO); |
29713 |
-+ |
29714 |
-+ /* free a buffer out of the pool's bounds */ |
29715 |
-+ cmd_free.size = sizeof(cmd_free); |
29716 |
-+ cmd_free.offset = POOL_SIZE + 1; |
29717 |
-+ ret = kdbus_cmd_free(env->conn->fd, &cmd_free); |
29718 |
-+ ASSERT_RETURN(ret == -ENXIO); |
29719 |
-+ |
29720 |
-+ /* |
29721 |
-+ * The user application is responsible for freeing the allocated |
29722 |
-+ * memory with the KDBUS_CMD_FREE ioctl, so let's test what happens |
29723 |
-+ * if we forget about it. |
29724 |
-+ */ |
29725 |
-+ |
29726 |
-+ ret = sample_ioctl_call(env); |
29727 |
-+ ASSERT_RETURN(ret == 0); |
29728 |
-+ |
29729 |
-+ ret = sample_ioctl_call(env); |
29730 |
-+ ASSERT_RETURN(ret == 0); |
29731 |
-+ |
29732 |
-+ return TEST_OK; |
29733 |
-+} |
29734 |
-diff --git a/tools/testing/selftests/kdbus/test-match.c b/tools/testing/selftests/kdbus/test-match.c |
29735 |
-new file mode 100644 |
29736 |
-index 0000000..2360dc1 |
29737 |
---- /dev/null |
29738 |
-+++ b/tools/testing/selftests/kdbus/test-match.c |
29739 |
-@@ -0,0 +1,441 @@ |
29740 |
-+#include <stdio.h> |
29741 |
-+#include <string.h> |
29742 |
-+#include <fcntl.h> |
29743 |
-+#include <stdlib.h> |
29744 |
-+#include <stddef.h> |
29745 |
-+#include <unistd.h> |
29746 |
-+#include <stdint.h> |
29747 |
-+#include <errno.h> |
29748 |
-+#include <assert.h> |
29749 |
-+#include <stdbool.h> |
29750 |
-+ |
29751 |
-+#include "kdbus-api.h" |
29752 |
-+#include "kdbus-util.h" |
29753 |
-+#include "kdbus-enum.h" |
29754 |
-+#include "kdbus-test.h" |
29755 |
-+ |
29756 |
-+int kdbus_test_match_id_add(struct kdbus_test_env *env) |
29757 |
-+{ |
29758 |
-+ struct { |
29759 |
-+ struct kdbus_cmd_match cmd; |
29760 |
-+ struct { |
29761 |
-+ uint64_t size; |
29762 |
-+ uint64_t type; |
29763 |
-+ struct kdbus_notify_id_change chg; |
29764 |
-+ } item; |
29765 |
-+ } buf; |
29766 |
-+ struct kdbus_conn *conn; |
29767 |
-+ struct kdbus_msg *msg; |
29768 |
-+ int ret; |
29769 |
-+ |
29770 |
-+ memset(&buf, 0, sizeof(buf)); |
29771 |
-+ |
29772 |
-+ buf.cmd.size = sizeof(buf); |
29773 |
-+ buf.cmd.cookie = 0xdeafbeefdeaddead; |
29774 |
-+ buf.item.size = sizeof(buf.item); |
29775 |
-+ buf.item.type = KDBUS_ITEM_ID_ADD; |
29776 |
-+ buf.item.chg.id = KDBUS_MATCH_ID_ANY; |
29777 |
-+ |
29778 |
-+ /* match on id add */ |
29779 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29780 |
-+ ASSERT_RETURN(ret == 0); |
29781 |
-+ |
29782 |
-+ /* create 2nd connection */ |
29783 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
29784 |
-+ ASSERT_RETURN(conn != NULL); |
29785 |
-+ |
29786 |
-+ /* 1st connection should have received a notification */ |
29787 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29788 |
-+ ASSERT_RETURN(ret == 0); |
29789 |
-+ |
29790 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD); |
29791 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == conn->id); |
29792 |
-+ |
29793 |
-+ kdbus_conn_free(conn); |
29794 |
-+ |
29795 |
-+ return TEST_OK; |
29796 |
-+} |
29797 |
-+ |
29798 |
-+int kdbus_test_match_id_remove(struct kdbus_test_env *env) |
29799 |
-+{ |
29800 |
-+ struct { |
29801 |
-+ struct kdbus_cmd_match cmd; |
29802 |
-+ struct { |
29803 |
-+ uint64_t size; |
29804 |
-+ uint64_t type; |
29805 |
-+ struct kdbus_notify_id_change chg; |
29806 |
-+ } item; |
29807 |
-+ } buf; |
29808 |
-+ struct kdbus_conn *conn; |
29809 |
-+ struct kdbus_msg *msg; |
29810 |
-+ size_t id; |
29811 |
-+ int ret; |
29812 |
-+ |
29813 |
-+ /* create 2nd connection */ |
29814 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
29815 |
-+ ASSERT_RETURN(conn != NULL); |
29816 |
-+ id = conn->id; |
29817 |
-+ |
29818 |
-+ memset(&buf, 0, sizeof(buf)); |
29819 |
-+ buf.cmd.size = sizeof(buf); |
29820 |
-+ buf.cmd.cookie = 0xdeafbeefdeaddead; |
29821 |
-+ buf.item.size = sizeof(buf.item); |
29822 |
-+ buf.item.type = KDBUS_ITEM_ID_REMOVE; |
29823 |
-+ buf.item.chg.id = id; |
29824 |
-+ |
29825 |
-+ /* register match on 2nd connection */ |
29826 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29827 |
-+ ASSERT_RETURN(ret == 0); |
29828 |
-+ |
29829 |
-+ /* remove 2nd connection again */ |
29830 |
-+ kdbus_conn_free(conn); |
29831 |
-+ |
29832 |
-+ /* 1st connection should have received a notification */ |
29833 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29834 |
-+ ASSERT_RETURN(ret == 0); |
29835 |
-+ |
29836 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE); |
29837 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == id); |
29838 |
-+ |
29839 |
-+ return TEST_OK; |
29840 |
-+} |
29841 |
-+ |
29842 |
-+int kdbus_test_match_replace(struct kdbus_test_env *env) |
29843 |
-+{ |
29844 |
-+ struct { |
29845 |
-+ struct kdbus_cmd_match cmd; |
29846 |
-+ struct { |
29847 |
-+ uint64_t size; |
29848 |
-+ uint64_t type; |
29849 |
-+ struct kdbus_notify_id_change chg; |
29850 |
-+ } item; |
29851 |
-+ } buf; |
29852 |
-+ struct kdbus_conn *conn; |
29853 |
-+ struct kdbus_msg *msg; |
29854 |
-+ size_t id; |
29855 |
-+ int ret; |
29856 |
-+ |
29857 |
-+ /* add a match to id_add */ |
29858 |
-+ ASSERT_RETURN(kdbus_test_match_id_add(env) == TEST_OK); |
29859 |
-+ |
29860 |
-+ /* do a replace of the match from id_add to id_remove */ |
29861 |
-+ memset(&buf, 0, sizeof(buf)); |
29862 |
-+ |
29863 |
-+ buf.cmd.size = sizeof(buf); |
29864 |
-+ buf.cmd.cookie = 0xdeafbeefdeaddead; |
29865 |
-+ buf.cmd.flags = KDBUS_MATCH_REPLACE; |
29866 |
-+ buf.item.size = sizeof(buf.item); |
29867 |
-+ buf.item.type = KDBUS_ITEM_ID_REMOVE; |
29868 |
-+ buf.item.chg.id = KDBUS_MATCH_ID_ANY; |
29869 |
-+ |
29870 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29871 |
-+ |
29872 |
-+ /* create 2nd connection */ |
29873 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
29874 |
-+ ASSERT_RETURN(conn != NULL); |
29875 |
-+ id = conn->id; |
29876 |
-+ |
29877 |
-+ /* 1st connection should _not_ have received a notification */ |
29878 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29879 |
-+ ASSERT_RETURN(ret != 0); |
29880 |
-+ |
29881 |
-+ /* remove 2nd connection */ |
29882 |
-+ kdbus_conn_free(conn); |
29883 |
-+ |
29884 |
-+ /* 1st connection should _now_ have received a notification */ |
29885 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29886 |
-+ ASSERT_RETURN(ret == 0); |
29887 |
-+ |
29888 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE); |
29889 |
-+ ASSERT_RETURN(msg->items[0].id_change.id == id); |
29890 |
-+ |
29891 |
-+ return TEST_OK; |
29892 |
-+} |
29893 |
-+ |
29894 |
-+int kdbus_test_match_name_add(struct kdbus_test_env *env) |
29895 |
-+{ |
29896 |
-+ struct { |
29897 |
-+ struct kdbus_cmd_match cmd; |
29898 |
-+ struct { |
29899 |
-+ uint64_t size; |
29900 |
-+ uint64_t type; |
29901 |
-+ struct kdbus_notify_name_change chg; |
29902 |
-+ } item; |
29903 |
-+ char name[64]; |
29904 |
-+ } buf; |
29905 |
-+ struct kdbus_msg *msg; |
29906 |
-+ char *name; |
29907 |
-+ int ret; |
29908 |
-+ |
29909 |
-+ name = "foo.bla.blaz"; |
29910 |
-+ |
29911 |
-+ /* install the match rule */ |
29912 |
-+ memset(&buf, 0, sizeof(buf)); |
29913 |
-+ buf.item.type = KDBUS_ITEM_NAME_ADD; |
29914 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
29915 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
29916 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
29917 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
29918 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
29919 |
-+ |
29920 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29921 |
-+ ASSERT_RETURN(ret == 0); |
29922 |
-+ |
29923 |
-+ /* acquire the name */ |
29924 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
29925 |
-+ ASSERT_RETURN(ret == 0); |
29926 |
-+ |
29927 |
-+ /* we should have received a notification */ |
29928 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29929 |
-+ ASSERT_RETURN(ret == 0); |
29930 |
-+ |
29931 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); |
29932 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); |
29933 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); |
29934 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
29935 |
-+ |
29936 |
-+ return TEST_OK; |
29937 |
-+} |
29938 |
-+ |
29939 |
-+int kdbus_test_match_name_remove(struct kdbus_test_env *env) |
29940 |
-+{ |
29941 |
-+ struct { |
29942 |
-+ struct kdbus_cmd_match cmd; |
29943 |
-+ struct { |
29944 |
-+ uint64_t size; |
29945 |
-+ uint64_t type; |
29946 |
-+ struct kdbus_notify_name_change chg; |
29947 |
-+ } item; |
29948 |
-+ char name[64]; |
29949 |
-+ } buf; |
29950 |
-+ struct kdbus_msg *msg; |
29951 |
-+ char *name; |
29952 |
-+ int ret; |
29953 |
-+ |
29954 |
-+ name = "foo.bla.blaz"; |
29955 |
-+ |
29956 |
-+ /* acquire the name */ |
29957 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
29958 |
-+ ASSERT_RETURN(ret == 0); |
29959 |
-+ |
29960 |
-+ /* install the match rule */ |
29961 |
-+ memset(&buf, 0, sizeof(buf)); |
29962 |
-+ buf.item.type = KDBUS_ITEM_NAME_REMOVE; |
29963 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
29964 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
29965 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
29966 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
29967 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
29968 |
-+ |
29969 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
29970 |
-+ ASSERT_RETURN(ret == 0); |
29971 |
-+ |
29972 |
-+ /* release the name again */ |
29973 |
-+ kdbus_name_release(env->conn, name); |
29974 |
-+ ASSERT_RETURN(ret == 0); |
29975 |
-+ |
29976 |
-+ /* we should have received a notification */ |
29977 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
29978 |
-+ ASSERT_RETURN(ret == 0); |
29979 |
-+ |
29980 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_REMOVE); |
29981 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id); |
29982 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == 0); |
29983 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
29984 |
-+ |
29985 |
-+ return TEST_OK; |
29986 |
-+} |
29987 |
-+ |
29988 |
-+int kdbus_test_match_name_change(struct kdbus_test_env *env) |
29989 |
-+{ |
29990 |
-+ struct { |
29991 |
-+ struct kdbus_cmd_match cmd; |
29992 |
-+ struct { |
29993 |
-+ uint64_t size; |
29994 |
-+ uint64_t type; |
29995 |
-+ struct kdbus_notify_name_change chg; |
29996 |
-+ } item; |
29997 |
-+ char name[64]; |
29998 |
-+ } buf; |
29999 |
-+ struct kdbus_conn *conn; |
30000 |
-+ struct kdbus_msg *msg; |
30001 |
-+ uint64_t flags; |
30002 |
-+ char *name = "foo.bla.baz"; |
30003 |
-+ int ret; |
30004 |
-+ |
30005 |
-+ /* acquire the name */ |
30006 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
30007 |
-+ ASSERT_RETURN(ret == 0); |
30008 |
-+ |
30009 |
-+ /* install the match rule */ |
30010 |
-+ memset(&buf, 0, sizeof(buf)); |
30011 |
-+ buf.item.type = KDBUS_ITEM_NAME_CHANGE; |
30012 |
-+ buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; |
30013 |
-+ buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; |
30014 |
-+ strncpy(buf.name, name, sizeof(buf.name) - 1); |
30015 |
-+ buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; |
30016 |
-+ buf.cmd.size = sizeof(buf.cmd) + buf.item.size; |
30017 |
-+ |
30018 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30019 |
-+ ASSERT_RETURN(ret == 0); |
30020 |
-+ |
30021 |
-+ /* create a 2nd connection */ |
30022 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30023 |
-+ ASSERT_RETURN(conn != NULL); |
30024 |
-+ |
30025 |
-+ /* allow the new connection to own the same name */ |
30026 |
-+ /* queue the 2nd connection as waiting owner */ |
30027 |
-+ flags = KDBUS_NAME_QUEUE; |
30028 |
-+ ret = kdbus_name_acquire(conn, name, &flags); |
30029 |
-+ ASSERT_RETURN(ret == 0); |
30030 |
-+ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); |
30031 |
-+ |
30032 |
-+ /* release name from 1st connection */ |
30033 |
-+ ret = kdbus_name_release(env->conn, name); |
30034 |
-+ ASSERT_RETURN(ret == 0); |
30035 |
-+ |
30036 |
-+ /* we should have received a notification */ |
30037 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30038 |
-+ ASSERT_RETURN(ret == 0); |
30039 |
-+ |
30040 |
-+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_CHANGE); |
30041 |
-+ ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id); |
30042 |
-+ ASSERT_RETURN(msg->items[0].name_change.new_id.id == conn->id); |
30043 |
-+ ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); |
30044 |
-+ |
30045 |
-+ kdbus_conn_free(conn); |
30046 |
-+ |
30047 |
-+ return TEST_OK; |
30048 |
-+} |
30049 |
-+ |
30050 |
-+static int send_bloom_filter(const struct kdbus_conn *conn, |
30051 |
-+ uint64_t cookie, |
30052 |
-+ const uint8_t *filter, |
30053 |
-+ size_t filter_size, |
30054 |
-+ uint64_t filter_generation) |
30055 |
-+{ |
30056 |
-+ struct kdbus_cmd_send cmd = {}; |
30057 |
-+ struct kdbus_msg *msg; |
30058 |
-+ struct kdbus_item *item; |
30059 |
-+ uint64_t size; |
30060 |
-+ int ret; |
30061 |
-+ |
30062 |
-+ size = sizeof(struct kdbus_msg); |
30063 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + filter_size; |
30064 |
-+ |
30065 |
-+ msg = alloca(size); |
30066 |
-+ |
30067 |
-+ memset(msg, 0, size); |
30068 |
-+ msg->size = size; |
30069 |
-+ msg->src_id = conn->id; |
30070 |
-+ msg->dst_id = KDBUS_DST_ID_BROADCAST; |
30071 |
-+ msg->flags = KDBUS_MSG_SIGNAL; |
30072 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30073 |
-+ msg->cookie = cookie; |
30074 |
-+ |
30075 |
-+ item = msg->items; |
30076 |
-+ item->type = KDBUS_ITEM_BLOOM_FILTER; |
30077 |
-+ item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + |
30078 |
-+ filter_size; |
30079 |
-+ |
30080 |
-+ item->bloom_filter.generation = filter_generation; |
30081 |
-+ memcpy(item->bloom_filter.data, filter, filter_size); |
30082 |
-+ |
30083 |
-+ cmd.size = sizeof(cmd); |
30084 |
-+ cmd.msg_address = (uintptr_t)msg; |
30085 |
-+ |
30086 |
-+ ret = kdbus_cmd_send(conn->fd, &cmd); |
30087 |
-+ if (ret < 0) { |
30088 |
-+ kdbus_printf("error sending message: %d (%m)\n", ret); |
30089 |
-+ return ret; |
30090 |
-+ } |
30091 |
-+ |
30092 |
-+ return 0; |
30093 |
-+} |
30094 |
-+ |
30095 |
-+int kdbus_test_match_bloom(struct kdbus_test_env *env) |
30096 |
-+{ |
30097 |
-+ struct { |
30098 |
-+ struct kdbus_cmd_match cmd; |
30099 |
-+ struct { |
30100 |
-+ uint64_t size; |
30101 |
-+ uint64_t type; |
30102 |
-+ uint8_t data_gen0[64]; |
30103 |
-+ uint8_t data_gen1[64]; |
30104 |
-+ } item; |
30105 |
-+ } buf; |
30106 |
-+ struct kdbus_conn *conn; |
30107 |
-+ struct kdbus_msg *msg; |
30108 |
-+ uint64_t cookie = 0xf000f00f; |
30109 |
-+ uint8_t filter[64]; |
30110 |
-+ int ret; |
30111 |
-+ |
30112 |
-+ /* install the match rule */ |
30113 |
-+ memset(&buf, 0, sizeof(buf)); |
30114 |
-+ buf.cmd.size = sizeof(buf); |
30115 |
-+ |
30116 |
-+ buf.item.size = sizeof(buf.item); |
30117 |
-+ buf.item.type = KDBUS_ITEM_BLOOM_MASK; |
30118 |
-+ buf.item.data_gen0[0] = 0x55; |
30119 |
-+ buf.item.data_gen0[63] = 0x80; |
30120 |
-+ |
30121 |
-+ buf.item.data_gen1[1] = 0xaa; |
30122 |
-+ buf.item.data_gen1[9] = 0x02; |
30123 |
-+ |
30124 |
-+ ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd); |
30125 |
-+ ASSERT_RETURN(ret == 0); |
30126 |
-+ |
30127 |
-+ /* create a 2nd connection */ |
30128 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30129 |
-+ ASSERT_RETURN(conn != NULL); |
30130 |
-+ |
30131 |
-+ /* a message with a 0'ed out filter must not reach the other peer */ |
30132 |
-+ memset(filter, 0, sizeof(filter)); |
30133 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30134 |
-+ ASSERT_RETURN(ret == 0); |
30135 |
-+ |
30136 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30137 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30138 |
-+ |
30139 |
-+ /* now set the filter to the connection's mask and expect success */ |
30140 |
-+ filter[0] = 0x55; |
30141 |
-+ filter[63] = 0x80; |
30142 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30143 |
-+ ASSERT_RETURN(ret == 0); |
30144 |
-+ |
30145 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30146 |
-+ ASSERT_RETURN(ret == 0); |
30147 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30148 |
-+ |
30149 |
-+ /* broaden the filter and try again. this should also succeed. */ |
30150 |
-+ filter[0] = 0xff; |
30151 |
-+ filter[8] = 0xff; |
30152 |
-+ filter[63] = 0xff; |
30153 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0); |
30154 |
-+ ASSERT_RETURN(ret == 0); |
30155 |
-+ |
30156 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30157 |
-+ ASSERT_RETURN(ret == 0); |
30158 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30159 |
-+ |
30160 |
-+ /* the same filter must not match against bloom generation 1 */ |
30161 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1); |
30162 |
-+ ASSERT_RETURN(ret == 0); |
30163 |
-+ |
30164 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30165 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30166 |
-+ |
30167 |
-+ /* set a different filter and try again */ |
30168 |
-+ filter[1] = 0xaa; |
30169 |
-+ filter[9] = 0x02; |
30170 |
-+ ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1); |
30171 |
-+ ASSERT_RETURN(ret == 0); |
30172 |
-+ |
30173 |
-+ ret = kdbus_msg_recv(env->conn, &msg, NULL); |
30174 |
-+ ASSERT_RETURN(ret == 0); |
30175 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30176 |
-+ |
30177 |
-+ kdbus_conn_free(conn); |
30178 |
-+ |
30179 |
-+ return TEST_OK; |
30180 |
-+} |
30181 |
-diff --git a/tools/testing/selftests/kdbus/test-message.c b/tools/testing/selftests/kdbus/test-message.c |
30182 |
-new file mode 100644 |
30183 |
-index 0000000..563dc85 |
30184 |
---- /dev/null |
30185 |
-+++ b/tools/testing/selftests/kdbus/test-message.c |
30186 |
-@@ -0,0 +1,734 @@ |
30187 |
-+#include <stdio.h> |
30188 |
-+#include <string.h> |
30189 |
-+#include <fcntl.h> |
30190 |
-+#include <stdlib.h> |
30191 |
-+#include <stddef.h> |
30192 |
-+#include <unistd.h> |
30193 |
-+#include <stdint.h> |
30194 |
-+#include <errno.h> |
30195 |
-+#include <assert.h> |
30196 |
-+#include <time.h> |
30197 |
-+#include <stdbool.h> |
30198 |
-+#include <sys/eventfd.h> |
30199 |
-+#include <sys/types.h> |
30200 |
-+#include <sys/wait.h> |
30201 |
-+ |
30202 |
-+#include "kdbus-api.h" |
30203 |
-+#include "kdbus-util.h" |
30204 |
-+#include "kdbus-enum.h" |
30205 |
-+#include "kdbus-test.h" |
30206 |
-+ |
30207 |
-+/* maximum number of queued messages from the same individual user */ |
30208 |
-+#define KDBUS_CONN_MAX_MSGS 256 |
30209 |
-+ |
30210 |
-+/* maximum number of queued requests waiting for a reply */ |
30211 |
-+#define KDBUS_CONN_MAX_REQUESTS_PENDING 128 |
30212 |
-+ |
30213 |
-+/* maximum message payload size */ |
30214 |
-+#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE (2 * 1024UL * 1024UL) |
30215 |
-+ |
30216 |
-+int kdbus_test_message_basic(struct kdbus_test_env *env) |
30217 |
-+{ |
30218 |
-+ struct kdbus_conn *conn; |
30219 |
-+ struct kdbus_conn *sender; |
30220 |
-+ struct kdbus_msg *msg; |
30221 |
-+ uint64_t cookie = 0x1234abcd5678eeff; |
30222 |
-+ uint64_t offset; |
30223 |
-+ int ret; |
30224 |
-+ |
30225 |
-+ sender = kdbus_hello(env->buspath, 0, NULL, 0); |
30226 |
-+ ASSERT_RETURN(sender != NULL); |
30227 |
-+ |
30228 |
-+ /* create a 2nd connection */ |
30229 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30230 |
-+ ASSERT_RETURN(conn != NULL); |
30231 |
-+ |
30232 |
-+ ret = kdbus_add_match_empty(conn); |
30233 |
-+ ASSERT_RETURN(ret == 0); |
30234 |
-+ |
30235 |
-+ ret = kdbus_add_match_empty(sender); |
30236 |
-+ ASSERT_RETURN(ret == 0); |
30237 |
-+ |
30238 |
-+ /* send over 1st connection */ |
30239 |
-+ ret = kdbus_msg_send(sender, NULL, cookie, 0, 0, 0, |
30240 |
-+ KDBUS_DST_ID_BROADCAST); |
30241 |
-+ ASSERT_RETURN(ret == 0); |
30242 |
-+ |
30243 |
-+ /* Make sure that we do get our own broadcasts */ |
30244 |
-+ ret = kdbus_msg_recv(sender, &msg, &offset); |
30245 |
-+ ASSERT_RETURN(ret == 0); |
30246 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30247 |
-+ |
30248 |
-+ kdbus_msg_free(msg); |
30249 |
-+ |
30250 |
-+ /* ... and receive on the 2nd */ |
30251 |
-+ ret = kdbus_msg_recv_poll(conn, 100, &msg, &offset); |
30252 |
-+ ASSERT_RETURN(ret == 0); |
30253 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
30254 |
-+ |
30255 |
-+ kdbus_msg_free(msg); |
30256 |
-+ |
30257 |
-+ /* Msgs that expect a reply must have timeout and cookie */ |
30258 |
-+ ret = kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY, |
30259 |
-+ 0, 0, conn->id); |
30260 |
-+ ASSERT_RETURN(ret == -EINVAL); |
30261 |
-+ |
30262 |
-+ /* Faked replies with a valid reply cookie are rejected */ |
30263 |
-+ ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id); |
30264 |
-+ ASSERT_RETURN(ret == -EBADSLT); |
30265 |
-+ |
30266 |
-+ ret = kdbus_free(conn, offset); |
30267 |
-+ ASSERT_RETURN(ret == 0); |
30268 |
-+ |
30269 |
-+ kdbus_conn_free(sender); |
30270 |
-+ kdbus_conn_free(conn); |
30271 |
-+ |
30272 |
-+ return TEST_OK; |
30273 |
-+} |
30274 |
-+ |
30275 |
-+static int msg_recv_prio(struct kdbus_conn *conn, |
30276 |
-+ int64_t requested_prio, |
30277 |
-+ int64_t expected_prio) |
30278 |
-+{ |
30279 |
-+ struct kdbus_cmd_recv recv = { |
30280 |
-+ .size = sizeof(recv), |
30281 |
-+ .flags = KDBUS_RECV_USE_PRIORITY, |
30282 |
-+ .priority = requested_prio, |
30283 |
-+ }; |
30284 |
-+ struct kdbus_msg *msg; |
30285 |
-+ int ret; |
30286 |
-+ |
30287 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30288 |
-+ if (ret < 0) { |
30289 |
-+ kdbus_printf("error receiving message: %d (%m)\n", -errno); |
30290 |
-+ return ret; |
30291 |
-+ } |
30292 |
-+ |
30293 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
30294 |
-+ kdbus_msg_dump(conn, msg); |
30295 |
-+ |
30296 |
-+ if (msg->priority != expected_prio) { |
30297 |
-+ kdbus_printf("expected message prio %lld, got %lld\n", |
30298 |
-+ (unsigned long long) expected_prio, |
30299 |
-+ (unsigned long long) msg->priority); |
30300 |
-+ return -EINVAL; |
30301 |
-+ } |
30302 |
-+ |
30303 |
-+ kdbus_msg_free(msg); |
30304 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
30305 |
-+ if (ret < 0) |
30306 |
-+ return ret; |
30307 |
-+ |
30308 |
-+ return 0; |
30309 |
-+} |
30310 |
-+ |
30311 |
-+int kdbus_test_message_prio(struct kdbus_test_env *env) |
30312 |
-+{ |
30313 |
-+ struct kdbus_conn *a, *b; |
30314 |
-+ uint64_t cookie = 0; |
30315 |
-+ |
30316 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30317 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30318 |
-+ ASSERT_RETURN(a && b); |
30319 |
-+ |
30320 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 25, a->id) == 0); |
30321 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id) == 0); |
30322 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); |
30323 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -35, a->id) == 0); |
30324 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id) == 0); |
30325 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 20, a->id) == 0); |
30326 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -15, a->id) == 0); |
30327 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); |
30328 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id) == 0); |
30329 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); |
30330 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); |
30331 |
-+ ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -10, a->id) == 0); |
30332 |
-+ |
30333 |
-+ ASSERT_RETURN(msg_recv_prio(a, -200, -800) == 0); |
30334 |
-+ ASSERT_RETURN(msg_recv_prio(a, -100, -800) == 0); |
30335 |
-+ ASSERT_RETURN(msg_recv_prio(a, -400, -600) == 0); |
30336 |
-+ ASSERT_RETURN(msg_recv_prio(a, -400, -600) == -EAGAIN); |
30337 |
-+ ASSERT_RETURN(msg_recv_prio(a, 10, -150) == 0); |
30338 |
-+ ASSERT_RETURN(msg_recv_prio(a, 10, -100) == 0); |
30339 |
-+ |
30340 |
-+ kdbus_printf("--- get priority (all)\n"); |
30341 |
-+ ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0); |
30342 |
-+ |
30343 |
-+ kdbus_conn_free(a); |
30344 |
-+ kdbus_conn_free(b); |
30345 |
-+ |
30346 |
-+ return TEST_OK; |
30347 |
-+} |
30348 |
-+ |
30349 |
-+static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env) |
30350 |
-+{ |
30351 |
-+ int ret; |
30352 |
-+ unsigned int i; |
30353 |
-+ struct kdbus_conn *conn; |
30354 |
-+ struct kdbus_conn *reader; |
30355 |
-+ struct kdbus_msg *msg = NULL; |
30356 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
30357 |
-+ |
30358 |
-+ reader = kdbus_hello(env->buspath, 0, NULL, 0); |
30359 |
-+ ASSERT_RETURN(reader); |
30360 |
-+ |
30361 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30362 |
-+ ASSERT_RETURN(conn); |
30363 |
-+ |
30364 |
-+ /* Register for ID signals */ |
30365 |
-+ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, |
30366 |
-+ KDBUS_MATCH_ID_ANY); |
30367 |
-+ ASSERT_RETURN(ret == 0); |
30368 |
-+ |
30369 |
-+ ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, |
30370 |
-+ KDBUS_MATCH_ID_ANY); |
30371 |
-+ ASSERT_RETURN(ret == 0); |
30372 |
-+ |
30373 |
-+ /* Each iteration two notifications: add and remove ID */ |
30374 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) { |
30375 |
-+ struct kdbus_conn *notifier; |
30376 |
-+ |
30377 |
-+ notifier = kdbus_hello(env->buspath, 0, NULL, 0); |
30378 |
-+ ASSERT_RETURN(notifier); |
30379 |
-+ |
30380 |
-+ kdbus_conn_free(notifier); |
30381 |
-+ } |
30382 |
-+ |
30383 |
-+ /* |
30384 |
-+ * Now the reader queue is full with kernel notfications, |
30385 |
-+ * but as a user we still have room to push our messages. |
30386 |
-+ */ |
30387 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id); |
30388 |
-+ ASSERT_RETURN(ret == 0); |
30389 |
-+ |
30390 |
-+ /* More ID kernel notifications that will be lost */ |
30391 |
-+ kdbus_conn_free(conn); |
30392 |
-+ |
30393 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30394 |
-+ ASSERT_RETURN(conn); |
30395 |
-+ |
30396 |
-+ kdbus_conn_free(conn); |
30397 |
-+ |
30398 |
-+ /* |
30399 |
-+ * We lost only 3 packets since only signal msgs are |
30400 |
-+ * accounted. The connection ID add/remove notification |
30401 |
-+ */ |
30402 |
-+ ret = kdbus_cmd_recv(reader->fd, &recv); |
30403 |
-+ ASSERT_RETURN(ret == 0); |
30404 |
-+ ASSERT_RETURN(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS); |
30405 |
-+ ASSERT_RETURN(recv.dropped_msgs == 3); |
30406 |
-+ |
30407 |
-+ msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset); |
30408 |
-+ kdbus_msg_free(msg); |
30409 |
-+ |
30410 |
-+ /* Read our queue */ |
30411 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) { |
30412 |
-+ memset(&recv, 0, sizeof(recv)); |
30413 |
-+ recv.size = sizeof(recv); |
30414 |
-+ |
30415 |
-+ ret = kdbus_cmd_recv(reader->fd, &recv); |
30416 |
-+ ASSERT_RETURN(ret == 0); |
30417 |
-+ ASSERT_RETURN(!(recv.return_flags & |
30418 |
-+ KDBUS_RECV_RETURN_DROPPED_MSGS)); |
30419 |
-+ |
30420 |
-+ msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset); |
30421 |
-+ kdbus_msg_free(msg); |
30422 |
-+ } |
30423 |
-+ |
30424 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
30425 |
-+ ASSERT_RETURN(ret == 0); |
30426 |
-+ |
30427 |
-+ ret = kdbus_msg_recv(reader, NULL, NULL); |
30428 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30429 |
-+ |
30430 |
-+ kdbus_conn_free(reader); |
30431 |
-+ |
30432 |
-+ return 0; |
30433 |
-+} |
30434 |
-+ |
30435 |
-+/* Return the number of message successfully sent */ |
30436 |
-+static int kdbus_fill_conn_queue(struct kdbus_conn *conn_src, |
30437 |
-+ uint64_t dst_id, |
30438 |
-+ unsigned int max_msgs) |
30439 |
-+{ |
30440 |
-+ unsigned int i; |
30441 |
-+ uint64_t cookie = 0; |
30442 |
-+ size_t size; |
30443 |
-+ struct kdbus_cmd_send cmd = {}; |
30444 |
-+ struct kdbus_msg *msg; |
30445 |
-+ int ret; |
30446 |
-+ |
30447 |
-+ size = sizeof(struct kdbus_msg); |
30448 |
-+ msg = malloc(size); |
30449 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30450 |
-+ |
30451 |
-+ memset(msg, 0, size); |
30452 |
-+ msg->size = size; |
30453 |
-+ msg->src_id = conn_src->id; |
30454 |
-+ msg->dst_id = dst_id; |
30455 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30456 |
-+ |
30457 |
-+ cmd.size = sizeof(cmd); |
30458 |
-+ cmd.msg_address = (uintptr_t)msg; |
30459 |
-+ |
30460 |
-+ for (i = 0; i < max_msgs; i++) { |
30461 |
-+ msg->cookie = cookie++; |
30462 |
-+ ret = kdbus_cmd_send(conn_src->fd, &cmd); |
30463 |
-+ if (ret < 0) |
30464 |
-+ break; |
30465 |
-+ } |
30466 |
-+ |
30467 |
-+ free(msg); |
30468 |
-+ |
30469 |
-+ return i; |
30470 |
-+} |
30471 |
-+ |
30472 |
-+static int kdbus_test_activator_quota(struct kdbus_test_env *env) |
30473 |
-+{ |
30474 |
-+ int ret; |
30475 |
-+ unsigned int i; |
30476 |
-+ unsigned int activator_msgs_count = 0; |
30477 |
-+ uint64_t cookie = time(NULL); |
30478 |
-+ struct kdbus_conn *conn; |
30479 |
-+ struct kdbus_conn *sender; |
30480 |
-+ struct kdbus_conn *activator; |
30481 |
-+ struct kdbus_msg *msg; |
30482 |
-+ uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; |
30483 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
30484 |
-+ struct kdbus_policy_access access = { |
30485 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
30486 |
-+ .id = geteuid(), |
30487 |
-+ .access = KDBUS_POLICY_OWN, |
30488 |
-+ }; |
30489 |
-+ |
30490 |
-+ activator = kdbus_hello_activator(env->buspath, "foo.test.activator", |
30491 |
-+ &access, 1); |
30492 |
-+ ASSERT_RETURN(activator); |
30493 |
-+ |
30494 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30495 |
-+ sender = kdbus_hello(env->buspath, 0, NULL, 0); |
30496 |
-+ ASSERT_RETURN(conn || sender); |
30497 |
-+ |
30498 |
-+ ret = kdbus_list(sender, KDBUS_LIST_NAMES | |
30499 |
-+ KDBUS_LIST_UNIQUE | |
30500 |
-+ KDBUS_LIST_ACTIVATORS | |
30501 |
-+ KDBUS_LIST_QUEUED); |
30502 |
-+ ASSERT_RETURN(ret == 0); |
30503 |
-+ |
30504 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30505 |
-+ ret = kdbus_msg_send(sender, "foo.test.activator", |
30506 |
-+ cookie++, 0, 0, 0, |
30507 |
-+ KDBUS_DST_ID_NAME); |
30508 |
-+ if (ret < 0) |
30509 |
-+ break; |
30510 |
-+ activator_msgs_count++; |
30511 |
-+ } |
30512 |
-+ |
30513 |
-+ /* we must have at least sent one message */ |
30514 |
-+ ASSERT_RETURN_VAL(i > 0, -errno); |
30515 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30516 |
-+ |
30517 |
-+ /* Good, activator queue is full now */ |
30518 |
-+ |
30519 |
-+ /* ENXIO on direct send (activators can never be addressed by ID) */ |
30520 |
-+ ret = kdbus_msg_send(conn, NULL, cookie++, 0, 0, 0, activator->id); |
30521 |
-+ ASSERT_RETURN(ret == -ENXIO); |
30522 |
-+ |
30523 |
-+ /* can't queue more */ |
30524 |
-+ ret = kdbus_msg_send(conn, "foo.test.activator", cookie++, |
30525 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
30526 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30527 |
-+ |
30528 |
-+ /* no match installed, so the broadcast will not inc dropped_msgs */ |
30529 |
-+ ret = kdbus_msg_send(sender, NULL, cookie++, 0, 0, 0, |
30530 |
-+ KDBUS_DST_ID_BROADCAST); |
30531 |
-+ ASSERT_RETURN(ret == 0); |
30532 |
-+ |
30533 |
-+ /* Check activator queue */ |
30534 |
-+ ret = kdbus_cmd_recv(activator->fd, &recv); |
30535 |
-+ ASSERT_RETURN(ret == 0); |
30536 |
-+ ASSERT_RETURN(recv.dropped_msgs == 0); |
30537 |
-+ |
30538 |
-+ activator_msgs_count--; |
30539 |
-+ |
30540 |
-+ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30541 |
-+ kdbus_msg_free(msg); |
30542 |
-+ |
30543 |
-+ |
30544 |
-+ /* Stage 1) of test check the pool memory quota */ |
30545 |
-+ |
30546 |
-+ /* Consume the connection pool memory */ |
30547 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30548 |
-+ ret = kdbus_msg_send(sender, NULL, |
30549 |
-+ cookie++, 0, 0, 0, conn->id); |
30550 |
-+ if (ret < 0) |
30551 |
-+ break; |
30552 |
-+ } |
30553 |
-+ |
30554 |
-+ /* consume one message, so later at least one can be moved */ |
30555 |
-+ memset(&recv, 0, sizeof(recv)); |
30556 |
-+ recv.size = sizeof(recv); |
30557 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30558 |
-+ ASSERT_RETURN(ret == 0); |
30559 |
-+ ASSERT_RETURN(recv.dropped_msgs == 0); |
30560 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
30561 |
-+ kdbus_msg_free(msg); |
30562 |
-+ |
30563 |
-+ /* Try to acquire the name now */ |
30564 |
-+ ret = kdbus_name_acquire(conn, "foo.test.activator", &flags); |
30565 |
-+ ASSERT_RETURN(ret == 0); |
30566 |
-+ |
30567 |
-+ /* try to read messages and see if we have lost some */ |
30568 |
-+ memset(&recv, 0, sizeof(recv)); |
30569 |
-+ recv.size = sizeof(recv); |
30570 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30571 |
-+ ASSERT_RETURN(ret == 0); |
30572 |
-+ ASSERT_RETURN(recv.dropped_msgs != 0); |
30573 |
-+ |
30574 |
-+ /* number of dropped msgs < received ones (at least one was moved) */ |
30575 |
-+ ASSERT_RETURN(recv.dropped_msgs < activator_msgs_count); |
30576 |
-+ |
30577 |
-+ /* Deduct the number of dropped msgs from the activator msgs */ |
30578 |
-+ activator_msgs_count -= recv.dropped_msgs; |
30579 |
-+ |
30580 |
-+ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30581 |
-+ kdbus_msg_free(msg); |
30582 |
-+ |
30583 |
-+ /* |
30584 |
-+ * Release the name and hand it back to activator, now |
30585 |
-+ * we should have 'activator_msgs_count' msgs again in |
30586 |
-+ * the activator queue |
30587 |
-+ */ |
30588 |
-+ ret = kdbus_name_release(conn, "foo.test.activator"); |
30589 |
-+ ASSERT_RETURN(ret == 0); |
30590 |
-+ |
30591 |
-+ /* make sure that we got our previous activator msgs */ |
30592 |
-+ ret = kdbus_msg_recv(activator, &msg, NULL); |
30593 |
-+ ASSERT_RETURN(ret == 0); |
30594 |
-+ ASSERT_RETURN(msg->src_id == sender->id); |
30595 |
-+ |
30596 |
-+ activator_msgs_count--; |
30597 |
-+ |
30598 |
-+ kdbus_msg_free(msg); |
30599 |
-+ |
30600 |
-+ |
30601 |
-+ /* Stage 2) of test check max message quota */ |
30602 |
-+ |
30603 |
-+ /* Empty conn queue */ |
30604 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { |
30605 |
-+ ret = kdbus_msg_recv(conn, NULL, NULL); |
30606 |
-+ if (ret == -EAGAIN) |
30607 |
-+ break; |
30608 |
-+ } |
30609 |
-+ |
30610 |
-+ /* fill queue with max msgs quota */ |
30611 |
-+ ret = kdbus_fill_conn_queue(sender, conn->id, KDBUS_CONN_MAX_MSGS); |
30612 |
-+ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
30613 |
-+ |
30614 |
-+ /* This one is lost but it is not accounted */ |
30615 |
-+ ret = kdbus_msg_send(sender, NULL, |
30616 |
-+ cookie++, 0, 0, 0, conn->id); |
30617 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30618 |
-+ |
30619 |
-+ /* Acquire the name again */ |
30620 |
-+ ret = kdbus_name_acquire(conn, "foo.test.activator", &flags); |
30621 |
-+ ASSERT_RETURN(ret == 0); |
30622 |
-+ |
30623 |
-+ memset(&recv, 0, sizeof(recv)); |
30624 |
-+ recv.size = sizeof(recv); |
30625 |
-+ |
30626 |
-+ /* |
30627 |
-+ * Try to read messages and make sure that we have lost all |
30628 |
-+ * the activator messages due to quota checks. Our queue is |
30629 |
-+ * already full. |
30630 |
-+ */ |
30631 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
30632 |
-+ ASSERT_RETURN(ret == 0); |
30633 |
-+ ASSERT_RETURN(recv.dropped_msgs == activator_msgs_count); |
30634 |
-+ |
30635 |
-+ msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset); |
30636 |
-+ kdbus_msg_free(msg); |
30637 |
-+ |
30638 |
-+ kdbus_conn_free(sender); |
30639 |
-+ kdbus_conn_free(conn); |
30640 |
-+ kdbus_conn_free(activator); |
30641 |
-+ |
30642 |
-+ return 0; |
30643 |
-+} |
30644 |
-+ |
30645 |
-+static int kdbus_test_expected_reply_quota(struct kdbus_test_env *env) |
30646 |
-+{ |
30647 |
-+ int ret; |
30648 |
-+ unsigned int i, n; |
30649 |
-+ unsigned int count; |
30650 |
-+ uint64_t cookie = 0x1234abcd5678eeff; |
30651 |
-+ struct kdbus_conn *conn; |
30652 |
-+ struct kdbus_conn *connections[9]; |
30653 |
-+ |
30654 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
30655 |
-+ ASSERT_RETURN(conn); |
30656 |
-+ |
30657 |
-+ for (i = 0; i < 9; i++) { |
30658 |
-+ connections[i] = kdbus_hello(env->buspath, 0, NULL, 0); |
30659 |
-+ ASSERT_RETURN(connections[i]); |
30660 |
-+ } |
30661 |
-+ |
30662 |
-+ count = 0; |
30663 |
-+ /* Send 16 messages to 8 different connections */ |
30664 |
-+ for (i = 0; i < 8; i++) { |
30665 |
-+ for (n = 0; n < 16; n++) { |
30666 |
-+ ret = kdbus_msg_send(conn, NULL, cookie++, |
30667 |
-+ KDBUS_MSG_EXPECT_REPLY, |
30668 |
-+ 100000000ULL, 0, |
30669 |
-+ connections[i]->id); |
30670 |
-+ if (ret < 0) |
30671 |
-+ break; |
30672 |
-+ |
30673 |
-+ count++; |
30674 |
-+ } |
30675 |
-+ } |
30676 |
-+ |
30677 |
-+ /* |
30678 |
-+ * We should have queued at least |
30679 |
-+ * KDBUS_CONN_MAX_REQUESTS_PENDING method call |
30680 |
-+ */ |
30681 |
-+ ASSERT_RETURN(count == KDBUS_CONN_MAX_REQUESTS_PENDING); |
30682 |
-+ |
30683 |
-+ /* |
30684 |
-+ * Now try to send a message to the last connection, |
30685 |
-+ * if we have reached KDBUS_CONN_MAX_REQUESTS_PENDING |
30686 |
-+ * no further requests are allowed |
30687 |
-+ */ |
30688 |
-+ ret = kdbus_msg_send(conn, NULL, cookie++, KDBUS_MSG_EXPECT_REPLY, |
30689 |
-+ 1000000000ULL, 0, connections[8]->id); |
30690 |
-+ ASSERT_RETURN(ret == -EMLINK); |
30691 |
-+ |
30692 |
-+ for (i = 0; i < 9; i++) |
30693 |
-+ kdbus_conn_free(connections[i]); |
30694 |
-+ |
30695 |
-+ kdbus_conn_free(conn); |
30696 |
-+ |
30697 |
-+ return 0; |
30698 |
-+} |
30699 |
-+ |
30700 |
-+int kdbus_test_pool_quota(struct kdbus_test_env *env) |
30701 |
-+{ |
30702 |
-+ struct kdbus_conn *a, *b, *c; |
30703 |
-+ struct kdbus_cmd_send cmd = {}; |
30704 |
-+ struct kdbus_item *item; |
30705 |
-+ struct kdbus_msg *recv_msg; |
30706 |
-+ struct kdbus_msg *msg; |
30707 |
-+ uint64_t cookie = time(NULL); |
30708 |
-+ uint64_t size; |
30709 |
-+ unsigned int i; |
30710 |
-+ char *payload; |
30711 |
-+ int ret; |
30712 |
-+ |
30713 |
-+ /* just a guard */ |
30714 |
-+ if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE || |
30715 |
-+ POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0) |
30716 |
-+ return 0; |
30717 |
-+ |
30718 |
-+ payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char)); |
30719 |
-+ ASSERT_RETURN_VAL(payload, -ENOMEM); |
30720 |
-+ |
30721 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30722 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30723 |
-+ c = kdbus_hello(env->buspath, 0, NULL, 0); |
30724 |
-+ ASSERT_RETURN(a && b && c); |
30725 |
-+ |
30726 |
-+ size = sizeof(struct kdbus_msg); |
30727 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
30728 |
-+ |
30729 |
-+ msg = malloc(size); |
30730 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30731 |
-+ |
30732 |
-+ memset(msg, 0, size); |
30733 |
-+ msg->size = size; |
30734 |
-+ msg->src_id = a->id; |
30735 |
-+ msg->dst_id = c->id; |
30736 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30737 |
-+ |
30738 |
-+ item = msg->items; |
30739 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
30740 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
30741 |
-+ item->vec.address = (uintptr_t)payload; |
30742 |
-+ item->vec.size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE; |
30743 |
-+ item = KDBUS_ITEM_NEXT(item); |
30744 |
-+ |
30745 |
-+ cmd.size = sizeof(cmd); |
30746 |
-+ cmd.msg_address = (uintptr_t)msg; |
30747 |
-+ |
30748 |
-+ /* |
30749 |
-+ * Send 2097248 bytes, a user is only allowed to get 33% of half of |
30750 |
-+ * the free space of the pool, the already used space is |
30751 |
-+ * accounted as free space |
30752 |
-+ */ |
30753 |
-+ size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE; |
30754 |
-+ for (i = size; i < (POOL_SIZE / 2 / 3); i += size) { |
30755 |
-+ msg->cookie = cookie++; |
30756 |
-+ |
30757 |
-+ ret = kdbus_cmd_send(a->fd, &cmd); |
30758 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
30759 |
-+ } |
30760 |
-+ |
30761 |
-+ /* Try to get more than 33% */ |
30762 |
-+ msg->cookie = cookie++; |
30763 |
-+ ret = kdbus_cmd_send(a->fd, &cmd); |
30764 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30765 |
-+ |
30766 |
-+ /* We still can pass small messages */ |
30767 |
-+ ret = kdbus_msg_send(b, NULL, cookie++, 0, 0, 0, c->id); |
30768 |
-+ ASSERT_RETURN(ret == 0); |
30769 |
-+ |
30770 |
-+ for (i = size; i < (POOL_SIZE / 2 / 3); i += size) { |
30771 |
-+ ret = kdbus_msg_recv(c, &recv_msg, NULL); |
30772 |
-+ ASSERT_RETURN(ret == 0); |
30773 |
-+ ASSERT_RETURN(recv_msg->src_id == a->id); |
30774 |
-+ |
30775 |
-+ kdbus_msg_free(recv_msg); |
30776 |
-+ } |
30777 |
-+ |
30778 |
-+ ret = kdbus_msg_recv(c, &recv_msg, NULL); |
30779 |
-+ ASSERT_RETURN(ret == 0); |
30780 |
-+ ASSERT_RETURN(recv_msg->src_id == b->id); |
30781 |
-+ |
30782 |
-+ kdbus_msg_free(recv_msg); |
30783 |
-+ |
30784 |
-+ ret = kdbus_msg_recv(c, NULL, NULL); |
30785 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30786 |
-+ |
30787 |
-+ free(msg); |
30788 |
-+ free(payload); |
30789 |
-+ |
30790 |
-+ kdbus_conn_free(c); |
30791 |
-+ kdbus_conn_free(b); |
30792 |
-+ kdbus_conn_free(a); |
30793 |
-+ |
30794 |
-+ return 0; |
30795 |
-+} |
30796 |
-+ |
30797 |
-+int kdbus_test_message_quota(struct kdbus_test_env *env) |
30798 |
-+{ |
30799 |
-+ struct kdbus_conn *a, *b; |
30800 |
-+ uint64_t cookie = 0; |
30801 |
-+ int ret; |
30802 |
-+ int i; |
30803 |
-+ |
30804 |
-+ ret = kdbus_test_activator_quota(env); |
30805 |
-+ ASSERT_RETURN(ret == 0); |
30806 |
-+ |
30807 |
-+ ret = kdbus_test_notify_kernel_quota(env); |
30808 |
-+ ASSERT_RETURN(ret == 0); |
30809 |
-+ |
30810 |
-+ ret = kdbus_test_pool_quota(env); |
30811 |
-+ ASSERT_RETURN(ret == 0); |
30812 |
-+ |
30813 |
-+ ret = kdbus_test_expected_reply_quota(env); |
30814 |
-+ ASSERT_RETURN(ret == 0); |
30815 |
-+ |
30816 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30817 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30818 |
-+ |
30819 |
-+ ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS); |
30820 |
-+ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
30821 |
-+ |
30822 |
-+ ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id); |
30823 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30824 |
-+ |
30825 |
-+ for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i) { |
30826 |
-+ ret = kdbus_msg_recv(a, NULL, NULL); |
30827 |
-+ ASSERT_RETURN(ret == 0); |
30828 |
-+ } |
30829 |
-+ |
30830 |
-+ ret = kdbus_msg_recv(a, NULL, NULL); |
30831 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
30832 |
-+ |
30833 |
-+ ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1); |
30834 |
-+ ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS); |
30835 |
-+ |
30836 |
-+ ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id); |
30837 |
-+ ASSERT_RETURN(ret == -ENOBUFS); |
30838 |
-+ |
30839 |
-+ kdbus_conn_free(a); |
30840 |
-+ kdbus_conn_free(b); |
30841 |
-+ |
30842 |
-+ return TEST_OK; |
30843 |
-+} |
30844 |
-+ |
30845 |
-+int kdbus_test_memory_access(struct kdbus_test_env *env) |
30846 |
-+{ |
30847 |
-+ struct kdbus_conn *a, *b; |
30848 |
-+ struct kdbus_cmd_send cmd = {}; |
30849 |
-+ struct kdbus_item *item; |
30850 |
-+ struct kdbus_msg *msg; |
30851 |
-+ uint64_t test_addr = 0; |
30852 |
-+ char line[256]; |
30853 |
-+ uint64_t size; |
30854 |
-+ FILE *f; |
30855 |
-+ int ret; |
30856 |
-+ |
30857 |
-+ /* |
30858 |
-+ * Search in /proc/kallsyms for the address of a kernel symbol that |
30859 |
-+ * should always be there, regardless of the config. Use that address |
30860 |
-+ * in a PAYLOAD_VEC item and make sure it's inaccessible. |
30861 |
-+ */ |
30862 |
-+ |
30863 |
-+ f = fopen("/proc/kallsyms", "r"); |
30864 |
-+ if (!f) |
30865 |
-+ return TEST_SKIP; |
30866 |
-+ |
30867 |
-+ while (fgets(line, sizeof(line), f)) { |
30868 |
-+ char *s = line; |
30869 |
-+ |
30870 |
-+ if (!strsep(&s, " ")) |
30871 |
-+ continue; |
30872 |
-+ |
30873 |
-+ if (!strsep(&s, " ")) |
30874 |
-+ continue; |
30875 |
-+ |
30876 |
-+ if (!strncmp(s, "mutex_lock", 10)) { |
30877 |
-+ test_addr = strtoull(line, NULL, 16); |
30878 |
-+ break; |
30879 |
-+ } |
30880 |
-+ } |
30881 |
-+ |
30882 |
-+ fclose(f); |
30883 |
-+ |
30884 |
-+ if (!test_addr) |
30885 |
-+ return TEST_SKIP; |
30886 |
-+ |
30887 |
-+ a = kdbus_hello(env->buspath, 0, NULL, 0); |
30888 |
-+ b = kdbus_hello(env->buspath, 0, NULL, 0); |
30889 |
-+ ASSERT_RETURN(a && b); |
30890 |
-+ |
30891 |
-+ size = sizeof(struct kdbus_msg); |
30892 |
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); |
30893 |
-+ |
30894 |
-+ msg = alloca(size); |
30895 |
-+ ASSERT_RETURN_VAL(msg, -ENOMEM); |
30896 |
-+ |
30897 |
-+ memset(msg, 0, size); |
30898 |
-+ msg->size = size; |
30899 |
-+ msg->src_id = a->id; |
30900 |
-+ msg->dst_id = b->id; |
30901 |
-+ msg->payload_type = KDBUS_PAYLOAD_DBUS; |
30902 |
-+ |
30903 |
-+ item = msg->items; |
30904 |
-+ item->type = KDBUS_ITEM_PAYLOAD_VEC; |
30905 |
-+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec); |
30906 |
-+ item->vec.address = test_addr; |
30907 |
-+ item->vec.size = sizeof(void*); |
30908 |
-+ item = KDBUS_ITEM_NEXT(item); |
30909 |
-+ |
30910 |
-+ cmd.size = sizeof(cmd); |
30911 |
-+ cmd.msg_address = (uintptr_t)msg; |
30912 |
-+ |
30913 |
-+ ret = kdbus_cmd_send(a->fd, &cmd); |
30914 |
-+ ASSERT_RETURN(ret == -EFAULT); |
30915 |
-+ |
30916 |
-+ kdbus_conn_free(b); |
30917 |
-+ kdbus_conn_free(a); |
30918 |
-+ |
30919 |
-+ return 0; |
30920 |
-+} |
30921 |
-diff --git a/tools/testing/selftests/kdbus/test-metadata-ns.c b/tools/testing/selftests/kdbus/test-metadata-ns.c |
30922 |
-new file mode 100644 |
30923 |
-index 0000000..1f6edc0 |
30924 |
---- /dev/null |
30925 |
-+++ b/tools/testing/selftests/kdbus/test-metadata-ns.c |
30926 |
-@@ -0,0 +1,500 @@ |
30927 |
-+/* |
30928 |
-+ * Test metadata in new namespaces. Even if our tests can run |
30929 |
-+ * in a namespaced setup, this test is necessary so we can inspect |
30930 |
-+ * metadata on the same kdbusfs but between multiple namespaces |
30931 |
-+ */ |
30932 |
-+ |
30933 |
-+#include <stdio.h> |
30934 |
-+#include <string.h> |
30935 |
-+#include <sched.h> |
30936 |
-+#include <time.h> |
30937 |
-+#include <fcntl.h> |
30938 |
-+#include <stdlib.h> |
30939 |
-+#include <stddef.h> |
30940 |
-+#include <unistd.h> |
30941 |
-+#include <stdint.h> |
30942 |
-+#include <errno.h> |
30943 |
-+#include <assert.h> |
30944 |
-+#include <signal.h> |
30945 |
-+#include <sys/wait.h> |
30946 |
-+#include <sys/prctl.h> |
30947 |
-+#include <sys/eventfd.h> |
30948 |
-+#include <sys/syscall.h> |
30949 |
-+#include <sys/capability.h> |
30950 |
-+#include <linux/sched.h> |
30951 |
-+ |
30952 |
-+#include "kdbus-test.h" |
30953 |
-+#include "kdbus-util.h" |
30954 |
-+#include "kdbus-enum.h" |
30955 |
-+ |
30956 |
-+static const struct kdbus_creds privileged_creds = {}; |
30957 |
-+ |
30958 |
-+static const struct kdbus_creds unmapped_creds = { |
30959 |
-+ .uid = UNPRIV_UID, |
30960 |
-+ .euid = UNPRIV_UID, |
30961 |
-+ .suid = UNPRIV_UID, |
30962 |
-+ .fsuid = UNPRIV_UID, |
30963 |
-+ .gid = UNPRIV_GID, |
30964 |
-+ .egid = UNPRIV_GID, |
30965 |
-+ .sgid = UNPRIV_GID, |
30966 |
-+ .fsgid = UNPRIV_GID, |
30967 |
-+}; |
30968 |
-+ |
30969 |
-+static const struct kdbus_pids unmapped_pids = {}; |
30970 |
-+ |
30971 |
-+/* Get only the first item */ |
30972 |
-+static struct kdbus_item *kdbus_get_item(struct kdbus_msg *msg, |
30973 |
-+ uint64_t type) |
30974 |
-+{ |
30975 |
-+ struct kdbus_item *item; |
30976 |
-+ |
30977 |
-+ KDBUS_ITEM_FOREACH(item, msg, items) |
30978 |
-+ if (item->type == type) |
30979 |
-+ return item; |
30980 |
-+ |
30981 |
-+ return NULL; |
30982 |
-+} |
30983 |
-+ |
30984 |
-+static int kdbus_match_kdbus_creds(struct kdbus_msg *msg, |
30985 |
-+ const struct kdbus_creds *expected_creds) |
30986 |
-+{ |
30987 |
-+ struct kdbus_item *item; |
30988 |
-+ |
30989 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CREDS); |
30990 |
-+ ASSERT_RETURN(item); |
30991 |
-+ |
30992 |
-+ ASSERT_RETURN(memcmp(&item->creds, expected_creds, |
30993 |
-+ sizeof(struct kdbus_creds)) == 0); |
30994 |
-+ |
30995 |
-+ return 0; |
30996 |
-+} |
30997 |
-+ |
30998 |
-+static int kdbus_match_kdbus_pids(struct kdbus_msg *msg, |
30999 |
-+ const struct kdbus_pids *expected_pids) |
31000 |
-+{ |
31001 |
-+ struct kdbus_item *item; |
31002 |
-+ |
31003 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31004 |
-+ ASSERT_RETURN(item); |
31005 |
-+ |
31006 |
-+ ASSERT_RETURN(memcmp(&item->pids, expected_pids, |
31007 |
-+ sizeof(struct kdbus_pids)) == 0); |
31008 |
-+ |
31009 |
-+ return 0; |
31010 |
-+} |
31011 |
-+ |
31012 |
-+static int __kdbus_clone_userns_test(const char *bus, |
31013 |
-+ struct kdbus_conn *conn, |
31014 |
-+ uint64_t grandpa_pid, |
31015 |
-+ int signal_fd) |
31016 |
-+{ |
31017 |
-+ int clone_ret; |
31018 |
-+ int ret; |
31019 |
-+ struct kdbus_msg *msg = NULL; |
31020 |
-+ const struct kdbus_item *item; |
31021 |
-+ uint64_t cookie = time(NULL) ^ 0xdeadbeef; |
31022 |
-+ struct kdbus_conn *unpriv_conn = NULL; |
31023 |
-+ struct kdbus_pids parent_pids = { |
31024 |
-+ .pid = getppid(), |
31025 |
-+ .tid = getppid(), |
31026 |
-+ .ppid = grandpa_pid, |
31027 |
-+ }; |
31028 |
-+ |
31029 |
-+ ret = drop_privileges(UNPRIV_UID, UNPRIV_GID); |
31030 |
-+ ASSERT_EXIT(ret == 0); |
31031 |
-+ |
31032 |
-+ unpriv_conn = kdbus_hello(bus, 0, NULL, 0); |
31033 |
-+ ASSERT_EXIT(unpriv_conn); |
31034 |
-+ |
31035 |
-+ ret = kdbus_add_match_empty(unpriv_conn); |
31036 |
-+ ASSERT_EXIT(ret == 0); |
31037 |
-+ |
31038 |
-+ /* |
31039 |
-+ * ping privileged connection from this new unprivileged |
31040 |
-+ * one |
31041 |
-+ */ |
31042 |
-+ |
31043 |
-+ ret = kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0, |
31044 |
-+ 0, conn->id); |
31045 |
-+ ASSERT_EXIT(ret == 0); |
31046 |
-+ |
31047 |
-+ /* |
31048 |
-+ * Since we just dropped privileges, the dumpable flag |
31049 |
-+ * was just cleared which makes the /proc/$clone_child/uid_map |
31050 |
-+ * to be owned by root, hence any userns uid mapping will fail |
31051 |
-+ * with -EPERM since the mapping will be done by uid 65534. |
31052 |
-+ * |
31053 |
-+ * To avoid this set the dumpable flag again which makes |
31054 |
-+ * procfs update the /proc/$clone_child/ inodes owner to 65534. |
31055 |
-+ * |
31056 |
-+ * Using this we will be able write to /proc/$clone_child/uid_map |
31057 |
-+ * as uid 65534 and map the uid 65534 to 0 inside the user namespace. |
31058 |
-+ */ |
31059 |
-+ ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER); |
31060 |
-+ ASSERT_EXIT(ret == 0); |
31061 |
-+ |
31062 |
-+ /* Make child privileged in its new userns and run tests */ |
31063 |
-+ |
31064 |
-+ ret = RUN_CLONE_CHILD(&clone_ret, |
31065 |
-+ SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID, |
31066 |
-+ ({ 0; /* Clone setup, nothing */ }), |
31067 |
-+ ({ |
31068 |
-+ eventfd_t event_status = 0; |
31069 |
-+ struct kdbus_conn *userns_conn; |
31070 |
-+ |
31071 |
-+ /* ping connection from the new user namespace */ |
31072 |
-+ userns_conn = kdbus_hello(bus, 0, NULL, 0); |
31073 |
-+ ASSERT_EXIT(userns_conn); |
31074 |
-+ |
31075 |
-+ ret = kdbus_add_match_empty(userns_conn); |
31076 |
-+ ASSERT_EXIT(ret == 0); |
31077 |
-+ |
31078 |
-+ cookie++; |
31079 |
-+ ret = kdbus_msg_send(userns_conn, NULL, cookie, |
31080 |
-+ 0, 0, 0, conn->id); |
31081 |
-+ ASSERT_EXIT(ret == 0); |
31082 |
-+ |
31083 |
-+ /* Parent did send */ |
31084 |
-+ ret = eventfd_read(signal_fd, &event_status); |
31085 |
-+ ASSERT_RETURN(ret >= 0 && event_status == 1); |
31086 |
-+ |
31087 |
-+ /* |
31088 |
-+ * Receive from privileged connection |
31089 |
-+ */ |
31090 |
-+ kdbus_printf("Privileged → unprivileged/privileged " |
31091 |
-+ "in its userns " |
31092 |
-+ "(different userns and pidns):\n"); |
31093 |
-+ ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL); |
31094 |
-+ ASSERT_EXIT(ret == 0); |
31095 |
-+ ASSERT_EXIT(msg->dst_id == userns_conn->id); |
31096 |
-+ |
31097 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31098 |
-+ ASSERT_EXIT(item); |
31099 |
-+ |
31100 |
-+ /* uid/gid not mapped, so we have unpriv cached creds */ |
31101 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31102 |
-+ ASSERT_EXIT(ret == 0); |
31103 |
-+ |
31104 |
-+ /* |
31105 |
-+ * Diffent pid namepsaces. This is the child pidns |
31106 |
-+ * so it should not see its parent kdbus_pids |
31107 |
-+ */ |
31108 |
-+ ret = kdbus_match_kdbus_pids(msg, &unmapped_pids); |
31109 |
-+ ASSERT_EXIT(ret == 0); |
31110 |
-+ |
31111 |
-+ kdbus_msg_free(msg); |
31112 |
-+ |
31113 |
-+ |
31114 |
-+ /* |
31115 |
-+ * Receive broadcast from privileged connection |
31116 |
-+ */ |
31117 |
-+ kdbus_printf("Privileged → unprivileged/privileged " |
31118 |
-+ "in its userns " |
31119 |
-+ "(different userns and pidns):\n"); |
31120 |
-+ ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL); |
31121 |
-+ ASSERT_EXIT(ret == 0); |
31122 |
-+ ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST); |
31123 |
-+ |
31124 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31125 |
-+ ASSERT_EXIT(item); |
31126 |
-+ |
31127 |
-+ /* uid/gid not mapped, so we have unpriv cached creds */ |
31128 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31129 |
-+ ASSERT_EXIT(ret == 0); |
31130 |
-+ |
31131 |
-+ /* |
31132 |
-+ * Diffent pid namepsaces. This is the child pidns |
31133 |
-+ * so it should not see its parent kdbus_pids |
31134 |
-+ */ |
31135 |
-+ ret = kdbus_match_kdbus_pids(msg, &unmapped_pids); |
31136 |
-+ ASSERT_EXIT(ret == 0); |
31137 |
-+ |
31138 |
-+ kdbus_msg_free(msg); |
31139 |
-+ |
31140 |
-+ kdbus_conn_free(userns_conn); |
31141 |
-+ }), |
31142 |
-+ ({ |
31143 |
-+ /* Parent setup map child uid/gid */ |
31144 |
-+ ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"); |
31145 |
-+ ASSERT_EXIT(ret == 0); |
31146 |
-+ }), |
31147 |
-+ ({ 0; })); |
31148 |
-+ /* Unprivileged was not able to create user namespace */ |
31149 |
-+ if (clone_ret == -EPERM) { |
31150 |
-+ kdbus_printf("-- CLONE_NEWUSER TEST Failed for " |
31151 |
-+ "uid: %u\n -- Make sure that your kernel " |
31152 |
-+ "do not allow CLONE_NEWUSER for " |
31153 |
-+ "unprivileged users\n", UNPRIV_UID); |
31154 |
-+ ret = 0; |
31155 |
-+ goto out; |
31156 |
-+ } |
31157 |
-+ |
31158 |
-+ ASSERT_EXIT(ret == 0); |
31159 |
-+ |
31160 |
-+ |
31161 |
-+ /* |
31162 |
-+ * Receive from privileged connection |
31163 |
-+ */ |
31164 |
-+ kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n"); |
31165 |
-+ ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL); |
31166 |
-+ |
31167 |
-+ ASSERT_EXIT(ret == 0); |
31168 |
-+ ASSERT_EXIT(msg->dst_id == unpriv_conn->id); |
31169 |
-+ |
31170 |
-+ /* will get the privileged creds */ |
31171 |
-+ ret = kdbus_match_kdbus_creds(msg, &privileged_creds); |
31172 |
-+ ASSERT_EXIT(ret == 0); |
31173 |
-+ |
31174 |
-+ /* Same pidns so will get the kdbus_pids */ |
31175 |
-+ ret = kdbus_match_kdbus_pids(msg, &parent_pids); |
31176 |
-+ ASSERT_RETURN(ret == 0); |
31177 |
-+ |
31178 |
-+ kdbus_msg_free(msg); |
31179 |
-+ |
31180 |
-+ |
31181 |
-+ /* |
31182 |
-+ * Receive broadcast from privileged connection |
31183 |
-+ */ |
31184 |
-+ kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n"); |
31185 |
-+ ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL); |
31186 |
-+ |
31187 |
-+ ASSERT_EXIT(ret == 0); |
31188 |
-+ ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST); |
31189 |
-+ |
31190 |
-+ /* will get the privileged creds */ |
31191 |
-+ ret = kdbus_match_kdbus_creds(msg, &privileged_creds); |
31192 |
-+ ASSERT_EXIT(ret == 0); |
31193 |
-+ |
31194 |
-+ ret = kdbus_match_kdbus_pids(msg, &parent_pids); |
31195 |
-+ ASSERT_RETURN(ret == 0); |
31196 |
-+ |
31197 |
-+ kdbus_msg_free(msg); |
31198 |
-+ |
31199 |
-+out: |
31200 |
-+ kdbus_conn_free(unpriv_conn); |
31201 |
-+ |
31202 |
-+ return ret; |
31203 |
-+} |
31204 |
-+ |
31205 |
-+static int kdbus_clone_userns_test(const char *bus, |
31206 |
-+ struct kdbus_conn *conn) |
31207 |
-+{ |
31208 |
-+ int ret, status, efd; |
31209 |
-+ pid_t pid, ppid; |
31210 |
-+ uint64_t unpriv_conn_id, userns_conn_id; |
31211 |
-+ struct kdbus_msg *msg; |
31212 |
-+ const struct kdbus_item *item; |
31213 |
-+ struct kdbus_pids expected_pids; |
31214 |
-+ struct kdbus_conn *monitor; |
31215 |
-+ |
31216 |
-+ kdbus_printf("STARTING TEST 'metadata-ns'.\n"); |
31217 |
-+ |
31218 |
-+ monitor = kdbus_hello(bus, KDBUS_HELLO_MONITOR, NULL, 0); |
31219 |
-+ ASSERT_EXIT(monitor); |
31220 |
-+ |
31221 |
-+ /* |
31222 |
-+ * parent will signal to child that is in its |
31223 |
-+ * userns to read its queue |
31224 |
-+ */ |
31225 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
31226 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
31227 |
-+ |
31228 |
-+ ppid = getppid(); |
31229 |
-+ |
31230 |
-+ pid = fork(); |
31231 |
-+ ASSERT_RETURN_VAL(pid >= 0, -errno); |
31232 |
-+ |
31233 |
-+ if (pid == 0) { |
31234 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
31235 |
-+ ASSERT_EXIT_VAL(ret == 0, -errno); |
31236 |
-+ |
31237 |
-+ ret = __kdbus_clone_userns_test(bus, conn, ppid, efd); |
31238 |
-+ _exit(ret); |
31239 |
-+ } |
31240 |
-+ |
31241 |
-+ |
31242 |
-+ /* Phase 1) privileged receives from unprivileged */ |
31243 |
-+ |
31244 |
-+ /* |
31245 |
-+ * Receive from the unprivileged child |
31246 |
-+ */ |
31247 |
-+ kdbus_printf("\nUnprivileged → privileged (same namespaces):\n"); |
31248 |
-+ ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL); |
31249 |
-+ ASSERT_RETURN(ret == 0); |
31250 |
-+ |
31251 |
-+ unpriv_conn_id = msg->src_id; |
31252 |
-+ |
31253 |
-+ /* Unprivileged user */ |
31254 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31255 |
-+ ASSERT_RETURN(ret == 0); |
31256 |
-+ |
31257 |
-+ /* Set the expected creds_pids */ |
31258 |
-+ expected_pids = (struct kdbus_pids) { |
31259 |
-+ .pid = pid, |
31260 |
-+ .tid = pid, |
31261 |
-+ .ppid = getpid(), |
31262 |
-+ }; |
31263 |
-+ ret = kdbus_match_kdbus_pids(msg, &expected_pids); |
31264 |
-+ ASSERT_RETURN(ret == 0); |
31265 |
-+ |
31266 |
-+ kdbus_msg_free(msg); |
31267 |
-+ |
31268 |
-+ |
31269 |
-+ /* |
31270 |
-+ * Receive from the unprivileged that is in his own |
31271 |
-+ * userns and pidns |
31272 |
-+ */ |
31273 |
-+ |
31274 |
-+ kdbus_printf("\nUnprivileged/privileged in its userns → privileged " |
31275 |
-+ "(different userns and pidns)\n"); |
31276 |
-+ ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL); |
31277 |
-+ if (ret == -ETIMEDOUT) |
31278 |
-+ /* perhaps unprivileged userns is not allowed */ |
31279 |
-+ goto wait; |
31280 |
-+ |
31281 |
-+ ASSERT_RETURN(ret == 0); |
31282 |
-+ |
31283 |
-+ userns_conn_id = msg->src_id; |
31284 |
-+ |
31285 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_CAPS); |
31286 |
-+ ASSERT_RETURN(item); |
31287 |
-+ |
31288 |
-+ /* |
31289 |
-+ * Compare received items, creds must be translated into |
31290 |
-+ * the receiver user namespace, so the user is unprivileged |
31291 |
-+ */ |
31292 |
-+ ret = kdbus_match_kdbus_creds(msg, &unmapped_creds); |
31293 |
-+ ASSERT_RETURN(ret == 0); |
31294 |
-+ |
31295 |
-+ /* |
31296 |
-+ * We should have the kdbus_pids since we are the parent |
31297 |
-+ * pidns |
31298 |
-+ */ |
31299 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31300 |
-+ ASSERT_RETURN(item); |
31301 |
-+ |
31302 |
-+ ASSERT_RETURN(memcmp(&item->pids, &unmapped_pids, |
31303 |
-+ sizeof(struct kdbus_pids)) != 0); |
31304 |
-+ |
31305 |
-+ /* |
31306 |
-+ * Parent pid of the unprivileged/privileged in its userns |
31307 |
-+ * is the unprivileged child pid that was forked here. |
31308 |
-+ */ |
31309 |
-+ ASSERT_RETURN((uint64_t)pid == item->pids.ppid); |
31310 |
-+ |
31311 |
-+ kdbus_msg_free(msg); |
31312 |
-+ |
31313 |
-+ |
31314 |
-+ /* Phase 2) Privileged connection sends now 3 packets */ |
31315 |
-+ |
31316 |
-+ /* |
31317 |
-+ * Sending to unprivileged connections a unicast |
31318 |
-+ */ |
31319 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31320 |
-+ 0, unpriv_conn_id); |
31321 |
-+ ASSERT_RETURN(ret == 0); |
31322 |
-+ |
31323 |
-+ /* signal to child that is in its userns */ |
31324 |
-+ ret = eventfd_write(efd, 1); |
31325 |
-+ ASSERT_EXIT(ret == 0); |
31326 |
-+ |
31327 |
-+ /* |
31328 |
-+ * Sending to unprivileged/privilged in its userns |
31329 |
-+ * connections a unicast |
31330 |
-+ */ |
31331 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31332 |
-+ 0, userns_conn_id); |
31333 |
-+ ASSERT_RETURN(ret == 0); |
31334 |
-+ |
31335 |
-+ /* |
31336 |
-+ * Sending to unprivileged connections a broadcast |
31337 |
-+ */ |
31338 |
-+ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, |
31339 |
-+ 0, KDBUS_DST_ID_BROADCAST); |
31340 |
-+ ASSERT_RETURN(ret == 0); |
31341 |
-+ |
31342 |
-+ |
31343 |
-+wait: |
31344 |
-+ ret = waitpid(pid, &status, 0); |
31345 |
-+ ASSERT_RETURN(ret >= 0); |
31346 |
-+ |
31347 |
-+ ASSERT_RETURN(WIFEXITED(status)) |
31348 |
-+ ASSERT_RETURN(!WEXITSTATUS(status)); |
31349 |
-+ |
31350 |
-+ /* Dump monitor queue */ |
31351 |
-+ kdbus_printf("\n\nMonitor queue:\n"); |
31352 |
-+ for (;;) { |
31353 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, NULL); |
31354 |
-+ if (ret < 0) |
31355 |
-+ break; |
31356 |
-+ |
31357 |
-+ if (msg->payload_type == KDBUS_PAYLOAD_DBUS) { |
31358 |
-+ /* |
31359 |
-+ * Parent pidns should see all the |
31360 |
-+ * pids |
31361 |
-+ */ |
31362 |
-+ item = kdbus_get_item(msg, KDBUS_ITEM_PIDS); |
31363 |
-+ ASSERT_RETURN(item); |
31364 |
-+ |
31365 |
-+ ASSERT_RETURN(item->pids.pid != 0 && |
31366 |
-+ item->pids.tid != 0 && |
31367 |
-+ item->pids.ppid != 0); |
31368 |
-+ } |
31369 |
-+ |
31370 |
-+ kdbus_msg_free(msg); |
31371 |
-+ } |
31372 |
-+ |
31373 |
-+ kdbus_conn_free(monitor); |
31374 |
-+ close(efd); |
31375 |
-+ |
31376 |
-+ return 0; |
31377 |
-+} |
31378 |
-+ |
31379 |
-+int kdbus_test_metadata_ns(struct kdbus_test_env *env) |
31380 |
-+{ |
31381 |
-+ int ret; |
31382 |
-+ struct kdbus_conn *holder, *conn; |
31383 |
-+ struct kdbus_policy_access policy_access = { |
31384 |
-+ /* Allow world so we can inspect metadata in namespace */ |
31385 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
31386 |
-+ .id = geteuid(), |
31387 |
-+ .access = KDBUS_POLICY_TALK, |
31388 |
-+ }; |
31389 |
-+ |
31390 |
-+ /* |
31391 |
-+ * We require user-namespaces and all uids/gids |
31392 |
-+ * should be mapped (we can just require the necessary ones) |
31393 |
-+ */ |
31394 |
-+ if (!config_user_ns_is_enabled() || |
31395 |
-+ !all_uids_gids_are_mapped()) |
31396 |
-+ return TEST_SKIP; |
31397 |
-+ |
31398 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, CAP_SYS_ADMIN, -1); |
31399 |
-+ ASSERT_RETURN(ret >= 0); |
31400 |
-+ |
31401 |
-+ /* no enough privileges, SKIP test */ |
31402 |
-+ if (!ret) |
31403 |
-+ return TEST_SKIP; |
31404 |
-+ |
31405 |
-+ holder = kdbus_hello_registrar(env->buspath, "com.example.metadata", |
31406 |
-+ &policy_access, 1, |
31407 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
31408 |
-+ ASSERT_RETURN(holder); |
31409 |
-+ |
31410 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31411 |
-+ ASSERT_RETURN(conn); |
31412 |
-+ |
31413 |
-+ ret = kdbus_add_match_empty(conn); |
31414 |
-+ ASSERT_RETURN(ret == 0); |
31415 |
-+ |
31416 |
-+ ret = kdbus_name_acquire(conn, "com.example.metadata", NULL); |
31417 |
-+ ASSERT_EXIT(ret >= 0); |
31418 |
-+ |
31419 |
-+ ret = kdbus_clone_userns_test(env->buspath, conn); |
31420 |
-+ ASSERT_RETURN(ret == 0); |
31421 |
-+ |
31422 |
-+ kdbus_conn_free(holder); |
31423 |
-+ kdbus_conn_free(conn); |
31424 |
-+ |
31425 |
-+ return TEST_OK; |
31426 |
-+} |
31427 |
-diff --git a/tools/testing/selftests/kdbus/test-monitor.c b/tools/testing/selftests/kdbus/test-monitor.c |
31428 |
-new file mode 100644 |
31429 |
-index 0000000..e00d738 |
31430 |
---- /dev/null |
31431 |
-+++ b/tools/testing/selftests/kdbus/test-monitor.c |
31432 |
-@@ -0,0 +1,176 @@ |
31433 |
-+#include <stdio.h> |
31434 |
-+#include <string.h> |
31435 |
-+#include <time.h> |
31436 |
-+#include <fcntl.h> |
31437 |
-+#include <stdlib.h> |
31438 |
-+#include <stddef.h> |
31439 |
-+#include <unistd.h> |
31440 |
-+#include <stdint.h> |
31441 |
-+#include <stdbool.h> |
31442 |
-+#include <errno.h> |
31443 |
-+#include <assert.h> |
31444 |
-+#include <signal.h> |
31445 |
-+#include <sys/time.h> |
31446 |
-+#include <sys/mman.h> |
31447 |
-+#include <sys/capability.h> |
31448 |
-+#include <sys/wait.h> |
31449 |
-+ |
31450 |
-+#include "kdbus-util.h" |
31451 |
-+#include "kdbus-enum.h" |
31452 |
-+ |
31453 |
-+#include "kdbus-util.h" |
31454 |
-+#include "kdbus-enum.h" |
31455 |
-+#include "kdbus-test.h" |
31456 |
-+ |
31457 |
-+int kdbus_test_monitor(struct kdbus_test_env *env) |
31458 |
-+{ |
31459 |
-+ struct kdbus_conn *monitor, *conn; |
31460 |
-+ unsigned int cookie = 0xdeadbeef; |
31461 |
-+ struct kdbus_msg *msg; |
31462 |
-+ uint64_t offset = 0; |
31463 |
-+ int ret; |
31464 |
-+ |
31465 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31466 |
-+ ASSERT_RETURN(conn); |
31467 |
-+ |
31468 |
-+ /* add matches to make sure the monitor do not trigger an item add or |
31469 |
-+ * remove on connect and disconnect, respectively. |
31470 |
-+ */ |
31471 |
-+ ret = kdbus_add_match_id(conn, 0x1, KDBUS_ITEM_ID_ADD, |
31472 |
-+ KDBUS_MATCH_ID_ANY); |
31473 |
-+ ASSERT_RETURN(ret == 0); |
31474 |
-+ |
31475 |
-+ ret = kdbus_add_match_id(conn, 0x2, KDBUS_ITEM_ID_REMOVE, |
31476 |
-+ KDBUS_MATCH_ID_ANY); |
31477 |
-+ ASSERT_RETURN(ret == 0); |
31478 |
-+ |
31479 |
-+ /* register a monitor */ |
31480 |
-+ monitor = kdbus_hello(env->buspath, KDBUS_HELLO_MONITOR, NULL, 0); |
31481 |
-+ ASSERT_RETURN(monitor); |
31482 |
-+ |
31483 |
-+ /* make sure we did not receive a monitor connect notification */ |
31484 |
-+ ret = kdbus_msg_recv(conn, &msg, &offset); |
31485 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
31486 |
-+ |
31487 |
-+ /* check that a monitor cannot acquire a name */ |
31488 |
-+ ret = kdbus_name_acquire(monitor, "foo.bar.baz", NULL); |
31489 |
-+ ASSERT_RETURN(ret == -EOPNOTSUPP); |
31490 |
-+ |
31491 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, conn->id); |
31492 |
-+ ASSERT_RETURN(ret == 0); |
31493 |
-+ |
31494 |
-+ /* the recipient should have gotten the message */ |
31495 |
-+ ret = kdbus_msg_recv(conn, &msg, &offset); |
31496 |
-+ ASSERT_RETURN(ret == 0); |
31497 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31498 |
-+ kdbus_msg_free(msg); |
31499 |
-+ kdbus_free(conn, offset); |
31500 |
-+ |
31501 |
-+ /* and so should the monitor */ |
31502 |
-+ ret = kdbus_msg_recv(monitor, &msg, &offset); |
31503 |
-+ ASSERT_RETURN(ret == 0); |
31504 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31505 |
-+ |
31506 |
-+ kdbus_msg_free(msg); |
31507 |
-+ kdbus_free(monitor, offset); |
31508 |
-+ |
31509 |
-+ /* Installing matches for monitors must fais must fail */ |
31510 |
-+ ret = kdbus_add_match_empty(monitor); |
31511 |
-+ ASSERT_RETURN(ret == -EOPNOTSUPP); |
31512 |
-+ |
31513 |
-+ cookie++; |
31514 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31515 |
-+ KDBUS_DST_ID_BROADCAST); |
31516 |
-+ ASSERT_RETURN(ret == 0); |
31517 |
-+ |
31518 |
-+ /* The monitor should get the message. */ |
31519 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31520 |
-+ ASSERT_RETURN(ret == 0); |
31521 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31522 |
-+ |
31523 |
-+ kdbus_msg_free(msg); |
31524 |
-+ kdbus_free(monitor, offset); |
31525 |
-+ |
31526 |
-+ /* |
31527 |
-+ * Since we are the only monitor, update the attach flags |
31528 |
-+ * and tell we are not interessted in attach flags recv |
31529 |
-+ */ |
31530 |
-+ |
31531 |
-+ ret = kdbus_conn_update_attach_flags(monitor, |
31532 |
-+ _KDBUS_ATTACH_ALL, |
31533 |
-+ 0); |
31534 |
-+ ASSERT_RETURN(ret == 0); |
31535 |
-+ |
31536 |
-+ cookie++; |
31537 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31538 |
-+ KDBUS_DST_ID_BROADCAST); |
31539 |
-+ ASSERT_RETURN(ret == 0); |
31540 |
-+ |
31541 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31542 |
-+ ASSERT_RETURN(ret == 0); |
31543 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31544 |
-+ |
31545 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
31546 |
-+ ASSERT_RETURN(ret == 0); |
31547 |
-+ |
31548 |
-+ kdbus_msg_free(msg); |
31549 |
-+ kdbus_free(monitor, offset); |
31550 |
-+ |
31551 |
-+ /* |
31552 |
-+ * Now we are interested in KDBUS_ITEM_TIMESTAMP and |
31553 |
-+ * KDBUS_ITEM_CREDS |
31554 |
-+ */ |
31555 |
-+ ret = kdbus_conn_update_attach_flags(monitor, |
31556 |
-+ _KDBUS_ATTACH_ALL, |
31557 |
-+ KDBUS_ATTACH_TIMESTAMP | |
31558 |
-+ KDBUS_ATTACH_CREDS); |
31559 |
-+ ASSERT_RETURN(ret == 0); |
31560 |
-+ |
31561 |
-+ cookie++; |
31562 |
-+ ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, |
31563 |
-+ KDBUS_DST_ID_BROADCAST); |
31564 |
-+ ASSERT_RETURN(ret == 0); |
31565 |
-+ |
31566 |
-+ ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); |
31567 |
-+ ASSERT_RETURN(ret == 0); |
31568 |
-+ ASSERT_RETURN(msg->cookie == cookie); |
31569 |
-+ |
31570 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); |
31571 |
-+ ASSERT_RETURN(ret == 1); |
31572 |
-+ |
31573 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_CREDS); |
31574 |
-+ ASSERT_RETURN(ret == 1); |
31575 |
-+ |
31576 |
-+ /* the KDBUS_ITEM_PID_COMM was not requested */ |
31577 |
-+ ret = kdbus_item_in_message(msg, KDBUS_ITEM_PID_COMM); |
31578 |
-+ ASSERT_RETURN(ret == 0); |
31579 |
-+ |
31580 |
-+ kdbus_msg_free(msg); |
31581 |
-+ kdbus_free(monitor, offset); |
31582 |
-+ |
31583 |
-+ kdbus_conn_free(monitor); |
31584 |
-+ /* make sure we did not receive a monitor disconnect notification */ |
31585 |
-+ ret = kdbus_msg_recv(conn, &msg, &offset); |
31586 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
31587 |
-+ |
31588 |
-+ kdbus_conn_free(conn); |
31589 |
-+ |
31590 |
-+ /* Make sure that monitor as unprivileged is not allowed */ |
31591 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
31592 |
-+ ASSERT_RETURN(ret >= 0); |
31593 |
-+ |
31594 |
-+ if (ret && all_uids_gids_are_mapped()) { |
31595 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
31596 |
-+ monitor = kdbus_hello(env->buspath, |
31597 |
-+ KDBUS_HELLO_MONITOR, |
31598 |
-+ NULL, 0); |
31599 |
-+ ASSERT_EXIT(!monitor && errno == EPERM); |
31600 |
-+ |
31601 |
-+ _exit(EXIT_SUCCESS); |
31602 |
-+ }), |
31603 |
-+ ({ 0; })); |
31604 |
-+ ASSERT_RETURN(ret == 0); |
31605 |
-+ } |
31606 |
-+ |
31607 |
-+ return TEST_OK; |
31608 |
-+} |
31609 |
-diff --git a/tools/testing/selftests/kdbus/test-names.c b/tools/testing/selftests/kdbus/test-names.c |
31610 |
-new file mode 100644 |
31611 |
-index 0000000..e400dc8 |
31612 |
---- /dev/null |
31613 |
-+++ b/tools/testing/selftests/kdbus/test-names.c |
31614 |
-@@ -0,0 +1,272 @@ |
31615 |
-+#include <stdio.h> |
31616 |
-+#include <string.h> |
31617 |
-+#include <time.h> |
31618 |
-+#include <fcntl.h> |
31619 |
-+#include <stdlib.h> |
31620 |
-+#include <stddef.h> |
31621 |
-+#include <unistd.h> |
31622 |
-+#include <stdint.h> |
31623 |
-+#include <errno.h> |
31624 |
-+#include <assert.h> |
31625 |
-+#include <limits.h> |
31626 |
-+#include <getopt.h> |
31627 |
-+#include <stdbool.h> |
31628 |
-+ |
31629 |
-+#include "kdbus-api.h" |
31630 |
-+#include "kdbus-util.h" |
31631 |
-+#include "kdbus-enum.h" |
31632 |
-+#include "kdbus-test.h" |
31633 |
-+ |
31634 |
-+struct test_name { |
31635 |
-+ const char *name; |
31636 |
-+ __u64 owner_id; |
31637 |
-+ __u64 flags; |
31638 |
-+}; |
31639 |
-+ |
31640 |
-+static bool conn_test_names(const struct kdbus_conn *conn, |
31641 |
-+ const struct test_name *tests, |
31642 |
-+ unsigned int n_tests) |
31643 |
-+{ |
31644 |
-+ struct kdbus_cmd_list cmd_list = {}; |
31645 |
-+ struct kdbus_info *name, *list; |
31646 |
-+ unsigned int i; |
31647 |
-+ int ret; |
31648 |
-+ |
31649 |
-+ cmd_list.size = sizeof(cmd_list); |
31650 |
-+ cmd_list.flags = KDBUS_LIST_NAMES | |
31651 |
-+ KDBUS_LIST_ACTIVATORS | |
31652 |
-+ KDBUS_LIST_QUEUED; |
31653 |
-+ |
31654 |
-+ ret = kdbus_cmd_list(conn->fd, &cmd_list); |
31655 |
-+ ASSERT_RETURN(ret == 0); |
31656 |
-+ |
31657 |
-+ list = (struct kdbus_info *)(conn->buf + cmd_list.offset); |
31658 |
-+ |
31659 |
-+ for (i = 0; i < n_tests; i++) { |
31660 |
-+ const struct test_name *t = tests + i; |
31661 |
-+ bool found = false; |
31662 |
-+ |
31663 |
-+ KDBUS_FOREACH(name, list, cmd_list.list_size) { |
31664 |
-+ struct kdbus_item *item; |
31665 |
-+ |
31666 |
-+ KDBUS_ITEM_FOREACH(item, name, items) { |
31667 |
-+ if (item->type != KDBUS_ITEM_OWNED_NAME || |
31668 |
-+ strcmp(item->name.name, t->name) != 0) |
31669 |
-+ continue; |
31670 |
-+ |
31671 |
-+ if (t->owner_id == name->id && |
31672 |
-+ t->flags == item->name.flags) { |
31673 |
-+ found = true; |
31674 |
-+ break; |
31675 |
-+ } |
31676 |
-+ } |
31677 |
-+ } |
31678 |
-+ |
31679 |
-+ if (!found) |
31680 |
-+ return false; |
31681 |
-+ } |
31682 |
-+ |
31683 |
-+ return true; |
31684 |
-+} |
31685 |
-+ |
31686 |
-+static bool conn_is_name_primary_owner(const struct kdbus_conn *conn, |
31687 |
-+ const char *needle) |
31688 |
-+{ |
31689 |
-+ struct test_name t = { |
31690 |
-+ .name = needle, |
31691 |
-+ .owner_id = conn->id, |
31692 |
-+ .flags = KDBUS_NAME_PRIMARY, |
31693 |
-+ }; |
31694 |
-+ |
31695 |
-+ return conn_test_names(conn, &t, 1); |
31696 |
-+} |
31697 |
-+ |
31698 |
-+int kdbus_test_name_basic(struct kdbus_test_env *env) |
31699 |
-+{ |
31700 |
-+ struct kdbus_conn *conn; |
31701 |
-+ char *name, *dot_name, *invalid_name, *wildcard_name; |
31702 |
-+ int ret; |
31703 |
-+ |
31704 |
-+ name = "foo.bla.blaz"; |
31705 |
-+ dot_name = ".bla.blaz"; |
31706 |
-+ invalid_name = "foo"; |
31707 |
-+ wildcard_name = "foo.bla.bl.*"; |
31708 |
-+ |
31709 |
-+ /* create a 2nd connection */ |
31710 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31711 |
-+ ASSERT_RETURN(conn != NULL); |
31712 |
-+ |
31713 |
-+ /* acquire name "foo.bar.xxx" name */ |
31714 |
-+ ret = kdbus_name_acquire(conn, "foo.bar.xxx", NULL); |
31715 |
-+ ASSERT_RETURN(ret == 0); |
31716 |
-+ |
31717 |
-+ /* Name is not valid, must fail */ |
31718 |
-+ ret = kdbus_name_acquire(env->conn, dot_name, NULL); |
31719 |
-+ ASSERT_RETURN(ret == -EINVAL); |
31720 |
-+ |
31721 |
-+ ret = kdbus_name_acquire(env->conn, invalid_name, NULL); |
31722 |
-+ ASSERT_RETURN(ret == -EINVAL); |
31723 |
-+ |
31724 |
-+ ret = kdbus_name_acquire(env->conn, wildcard_name, NULL); |
31725 |
-+ ASSERT_RETURN(ret == -EINVAL); |
31726 |
-+ |
31727 |
-+ /* check that we can acquire a name */ |
31728 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
31729 |
-+ ASSERT_RETURN(ret == 0); |
31730 |
-+ |
31731 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31732 |
-+ ASSERT_RETURN(ret == true); |
31733 |
-+ |
31734 |
-+ /* ... and release it again */ |
31735 |
-+ ret = kdbus_name_release(env->conn, name); |
31736 |
-+ ASSERT_RETURN(ret == 0); |
31737 |
-+ |
31738 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31739 |
-+ ASSERT_RETURN(ret == false); |
31740 |
-+ |
31741 |
-+ /* check that we can't release it again */ |
31742 |
-+ ret = kdbus_name_release(env->conn, name); |
31743 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31744 |
-+ |
31745 |
-+ /* check that we can't release a name that we don't own */ |
31746 |
-+ ret = kdbus_name_release(env->conn, "foo.bar.xxx"); |
31747 |
-+ ASSERT_RETURN(ret == -EADDRINUSE); |
31748 |
-+ |
31749 |
-+ /* Name is not valid, must fail */ |
31750 |
-+ ret = kdbus_name_release(env->conn, dot_name); |
31751 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31752 |
-+ |
31753 |
-+ ret = kdbus_name_release(env->conn, invalid_name); |
31754 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31755 |
-+ |
31756 |
-+ ret = kdbus_name_release(env->conn, wildcard_name); |
31757 |
-+ ASSERT_RETURN(ret == -ESRCH); |
31758 |
-+ |
31759 |
-+ kdbus_conn_free(conn); |
31760 |
-+ |
31761 |
-+ return TEST_OK; |
31762 |
-+} |
31763 |
-+ |
31764 |
-+int kdbus_test_name_conflict(struct kdbus_test_env *env) |
31765 |
-+{ |
31766 |
-+ struct kdbus_conn *conn; |
31767 |
-+ char *name; |
31768 |
-+ int ret; |
31769 |
-+ |
31770 |
-+ name = "foo.bla.blaz"; |
31771 |
-+ |
31772 |
-+ /* create a 2nd connection */ |
31773 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31774 |
-+ ASSERT_RETURN(conn != NULL); |
31775 |
-+ |
31776 |
-+ /* allow the new connection to own the same name */ |
31777 |
-+ /* acquire name from the 1st connection */ |
31778 |
-+ ret = kdbus_name_acquire(env->conn, name, NULL); |
31779 |
-+ ASSERT_RETURN(ret == 0); |
31780 |
-+ |
31781 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31782 |
-+ ASSERT_RETURN(ret == true); |
31783 |
-+ |
31784 |
-+ /* check that we also can't acquire it again from the 2nd connection */ |
31785 |
-+ ret = kdbus_name_acquire(conn, name, NULL); |
31786 |
-+ ASSERT_RETURN(ret == -EEXIST); |
31787 |
-+ |
31788 |
-+ kdbus_conn_free(conn); |
31789 |
-+ |
31790 |
-+ return TEST_OK; |
31791 |
-+} |
31792 |
-+ |
31793 |
-+int kdbus_test_name_queue(struct kdbus_test_env *env) |
31794 |
-+{ |
31795 |
-+ struct kdbus_conn *conn; |
31796 |
-+ struct test_name t[2]; |
31797 |
-+ const char *name; |
31798 |
-+ uint64_t flags; |
31799 |
-+ int ret; |
31800 |
-+ |
31801 |
-+ name = "foo.bla.blaz"; |
31802 |
-+ |
31803 |
-+ flags = 0; |
31804 |
-+ |
31805 |
-+ /* create a 2nd connection */ |
31806 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31807 |
-+ ASSERT_RETURN(conn != NULL); |
31808 |
-+ |
31809 |
-+ /* allow the new connection to own the same name */ |
31810 |
-+ /* acquire name from the 1st connection */ |
31811 |
-+ ret = kdbus_name_acquire(env->conn, name, &flags); |
31812 |
-+ ASSERT_RETURN(ret == 0); |
31813 |
-+ |
31814 |
-+ ret = conn_is_name_primary_owner(env->conn, name); |
31815 |
-+ ASSERT_RETURN(ret == true); |
31816 |
-+ |
31817 |
-+ /* queue the 2nd connection as waiting owner */ |
31818 |
-+ flags = KDBUS_NAME_QUEUE; |
31819 |
-+ ret = kdbus_name_acquire(conn, name, &flags); |
31820 |
-+ ASSERT_RETURN(ret == 0); |
31821 |
-+ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); |
31822 |
-+ |
31823 |
-+ t[0].name = name; |
31824 |
-+ t[0].owner_id = env->conn->id; |
31825 |
-+ t[0].flags = KDBUS_NAME_PRIMARY; |
31826 |
-+ t[1].name = name; |
31827 |
-+ t[1].owner_id = conn->id; |
31828 |
-+ t[1].flags = KDBUS_NAME_QUEUE | KDBUS_NAME_IN_QUEUE; |
31829 |
-+ ret = conn_test_names(conn, t, 2); |
31830 |
-+ ASSERT_RETURN(ret == true); |
31831 |
-+ |
31832 |
-+ /* release name from 1st connection */ |
31833 |
-+ ret = kdbus_name_release(env->conn, name); |
31834 |
-+ ASSERT_RETURN(ret == 0); |
31835 |
-+ |
31836 |
-+ /* now the name should be owned by the 2nd connection */ |
31837 |
-+ t[0].name = name; |
31838 |
-+ t[0].owner_id = conn->id; |
31839 |
-+ t[0].flags = KDBUS_NAME_PRIMARY | KDBUS_NAME_QUEUE; |
31840 |
-+ ret = conn_test_names(conn, t, 1); |
31841 |
-+ ASSERT_RETURN(ret == true); |
31842 |
-+ |
31843 |
-+ kdbus_conn_free(conn); |
31844 |
-+ |
31845 |
-+ return TEST_OK; |
31846 |
-+} |
31847 |
-+ |
31848 |
-+int kdbus_test_name_takeover(struct kdbus_test_env *env) |
31849 |
-+{ |
31850 |
-+ struct kdbus_conn *conn; |
31851 |
-+ struct test_name t; |
31852 |
-+ const char *name; |
31853 |
-+ uint64_t flags; |
31854 |
-+ int ret; |
31855 |
-+ |
31856 |
-+ name = "foo.bla.blaz"; |
31857 |
-+ |
31858 |
-+ flags = KDBUS_NAME_ALLOW_REPLACEMENT; |
31859 |
-+ |
31860 |
-+ /* create a 2nd connection */ |
31861 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
31862 |
-+ ASSERT_RETURN(conn != NULL); |
31863 |
-+ |
31864 |
-+ /* acquire name for 1st connection */ |
31865 |
-+ ret = kdbus_name_acquire(env->conn, name, &flags); |
31866 |
-+ ASSERT_RETURN(ret == 0); |
31867 |
-+ |
31868 |
-+ t.name = name; |
31869 |
-+ t.owner_id = env->conn->id; |
31870 |
-+ t.flags = KDBUS_NAME_ALLOW_REPLACEMENT | KDBUS_NAME_PRIMARY; |
31871 |
-+ ret = conn_test_names(conn, &t, 1); |
31872 |
-+ ASSERT_RETURN(ret == true); |
31873 |
-+ |
31874 |
-+ /* now steal name with 2nd connection */ |
31875 |
-+ flags = KDBUS_NAME_REPLACE_EXISTING; |
31876 |
-+ ret = kdbus_name_acquire(conn, name, &flags); |
31877 |
-+ ASSERT_RETURN(ret == 0); |
31878 |
-+ ASSERT_RETURN(flags & KDBUS_NAME_ACQUIRED); |
31879 |
-+ |
31880 |
-+ ret = conn_is_name_primary_owner(conn, name); |
31881 |
-+ ASSERT_RETURN(ret == true); |
31882 |
-+ |
31883 |
-+ kdbus_conn_free(conn); |
31884 |
-+ |
31885 |
-+ return TEST_OK; |
31886 |
-+} |
31887 |
-diff --git a/tools/testing/selftests/kdbus/test-policy-ns.c b/tools/testing/selftests/kdbus/test-policy-ns.c |
31888 |
-new file mode 100644 |
31889 |
-index 0000000..3437012 |
31890 |
---- /dev/null |
31891 |
-+++ b/tools/testing/selftests/kdbus/test-policy-ns.c |
31892 |
-@@ -0,0 +1,632 @@ |
31893 |
-+/* |
31894 |
-+ * Test metadata and policies in new namespaces. Even if our tests |
31895 |
-+ * can run in a namespaced setup, this test is necessary so we can |
31896 |
-+ * inspect policies on the same kdbusfs but between multiple |
31897 |
-+ * namespaces. |
31898 |
-+ * |
31899 |
-+ * Copyright (C) 2014-2015 Djalal Harouni |
31900 |
-+ * |
31901 |
-+ * kdbus is free software; you can redistribute it and/or modify it under |
31902 |
-+ * the terms of the GNU Lesser General Public License as published by the |
31903 |
-+ * Free Software Foundation; either version 2.1 of the License, or (at |
31904 |
-+ * your option) any later version. |
31905 |
-+ */ |
31906 |
-+ |
31907 |
-+#include <stdio.h> |
31908 |
-+#include <string.h> |
31909 |
-+#include <fcntl.h> |
31910 |
-+#include <pthread.h> |
31911 |
-+#include <sched.h> |
31912 |
-+#include <stdlib.h> |
31913 |
-+#include <stddef.h> |
31914 |
-+#include <stdint.h> |
31915 |
-+#include <stdbool.h> |
31916 |
-+#include <unistd.h> |
31917 |
-+#include <errno.h> |
31918 |
-+#include <signal.h> |
31919 |
-+#include <sys/wait.h> |
31920 |
-+#include <sys/prctl.h> |
31921 |
-+#include <sys/eventfd.h> |
31922 |
-+#include <sys/syscall.h> |
31923 |
-+#include <sys/capability.h> |
31924 |
-+#include <linux/sched.h> |
31925 |
-+ |
31926 |
-+#include "kdbus-test.h" |
31927 |
-+#include "kdbus-util.h" |
31928 |
-+#include "kdbus-enum.h" |
31929 |
-+ |
31930 |
-+#define MAX_CONN 64 |
31931 |
-+#define POLICY_NAME "foo.test.policy-test" |
31932 |
-+ |
31933 |
-+#define KDBUS_CONN_MAX_MSGS_PER_USER 16 |
31934 |
-+ |
31935 |
-+/** |
31936 |
-+ * Note: this test can be used to inspect policy_db->talk_access_hash |
31937 |
-+ * |
31938 |
-+ * The purpose of these tests: |
31939 |
-+ * 1) Check KDBUS_POLICY_TALK |
31940 |
-+ * 2) Check the cache state: kdbus_policy_db->talk_access_hash |
31941 |
-+ * Should be extended |
31942 |
-+ */ |
31943 |
-+ |
31944 |
-+/** |
31945 |
-+ * Check a list of connections against conn_db[0] |
31946 |
-+ * conn_db[0] will own the name "foo.test.policy-test" and the |
31947 |
-+ * policy holder connection for this name will update the policy |
31948 |
-+ * entries, so different use cases can be tested. |
31949 |
-+ */ |
31950 |
-+static struct kdbus_conn **conn_db; |
31951 |
-+ |
31952 |
-+static void *kdbus_recv_echo(void *ptr) |
31953 |
-+{ |
31954 |
-+ int ret; |
31955 |
-+ struct kdbus_conn *conn = ptr; |
31956 |
-+ |
31957 |
-+ ret = kdbus_msg_recv_poll(conn, 200, NULL, NULL); |
31958 |
-+ |
31959 |
-+ return (void *)(long)ret; |
31960 |
-+} |
31961 |
-+ |
31962 |
-+/* Trigger kdbus_policy_set() */ |
31963 |
-+static int kdbus_set_policy_talk(struct kdbus_conn *conn, |
31964 |
-+ const char *name, |
31965 |
-+ uid_t id, unsigned int type) |
31966 |
-+{ |
31967 |
-+ int ret; |
31968 |
-+ struct kdbus_policy_access access = { |
31969 |
-+ .type = type, |
31970 |
-+ .id = id, |
31971 |
-+ .access = KDBUS_POLICY_TALK, |
31972 |
-+ }; |
31973 |
-+ |
31974 |
-+ ret = kdbus_conn_update_policy(conn, name, &access, 1); |
31975 |
-+ ASSERT_RETURN(ret == 0); |
31976 |
-+ |
31977 |
-+ return TEST_OK; |
31978 |
-+} |
31979 |
-+ |
31980 |
-+/* return TEST_OK or TEST_ERR on failure */ |
31981 |
-+static int kdbus_register_same_activator(char *bus, const char *name, |
31982 |
-+ struct kdbus_conn **c) |
31983 |
-+{ |
31984 |
-+ int ret; |
31985 |
-+ struct kdbus_conn *activator; |
31986 |
-+ |
31987 |
-+ activator = kdbus_hello_activator(bus, name, NULL, 0); |
31988 |
-+ if (activator) { |
31989 |
-+ *c = activator; |
31990 |
-+ fprintf(stderr, "--- error was able to register name twice '%s'.\n", |
31991 |
-+ name); |
31992 |
-+ return TEST_ERR; |
31993 |
-+ } |
31994 |
-+ |
31995 |
-+ ret = -errno; |
31996 |
-+ /* -EEXIST means test succeeded */ |
31997 |
-+ if (ret == -EEXIST) |
31998 |
-+ return TEST_OK; |
31999 |
-+ |
32000 |
-+ return TEST_ERR; |
32001 |
-+} |
32002 |
-+ |
32003 |
-+/* return TEST_OK or TEST_ERR on failure */ |
32004 |
-+static int kdbus_register_policy_holder(char *bus, const char *name, |
32005 |
-+ struct kdbus_conn **conn) |
32006 |
-+{ |
32007 |
-+ struct kdbus_conn *c; |
32008 |
-+ struct kdbus_policy_access access[2]; |
32009 |
-+ |
32010 |
-+ access[0].type = KDBUS_POLICY_ACCESS_USER; |
32011 |
-+ access[0].access = KDBUS_POLICY_OWN; |
32012 |
-+ access[0].id = geteuid(); |
32013 |
-+ |
32014 |
-+ access[1].type = KDBUS_POLICY_ACCESS_WORLD; |
32015 |
-+ access[1].access = KDBUS_POLICY_TALK; |
32016 |
-+ access[1].id = geteuid(); |
32017 |
-+ |
32018 |
-+ c = kdbus_hello_registrar(bus, name, access, 2, |
32019 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
32020 |
-+ ASSERT_RETURN(c); |
32021 |
-+ |
32022 |
-+ *conn = c; |
32023 |
-+ |
32024 |
-+ return TEST_OK; |
32025 |
-+} |
32026 |
-+ |
32027 |
-+/** |
32028 |
-+ * Create new threads for receiving from multiple senders, |
32029 |
-+ * The 'conn_db' will be populated by newly created connections. |
32030 |
-+ * Caller should free all allocated connections. |
32031 |
-+ * |
32032 |
-+ * return 0 on success, negative errno on failure. |
32033 |
-+ */ |
32034 |
-+static int kdbus_recv_in_threads(const char *bus, const char *name, |
32035 |
-+ struct kdbus_conn **conn_db) |
32036 |
-+{ |
32037 |
-+ int ret; |
32038 |
-+ bool pool_full = false; |
32039 |
-+ unsigned int sent_packets = 0; |
32040 |
-+ unsigned int lost_packets = 0; |
32041 |
-+ unsigned int i, tid; |
32042 |
-+ unsigned long dst_id; |
32043 |
-+ unsigned long cookie = 1; |
32044 |
-+ unsigned int thread_nr = MAX_CONN - 1; |
32045 |
-+ pthread_t thread_id[MAX_CONN - 1] = {'\0'}; |
32046 |
-+ |
32047 |
-+ dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id; |
32048 |
-+ |
32049 |
-+ for (tid = 0, i = 1; tid < thread_nr; tid++, i++) { |
32050 |
-+ ret = pthread_create(&thread_id[tid], NULL, |
32051 |
-+ kdbus_recv_echo, (void *)conn_db[0]); |
32052 |
-+ if (ret < 0) { |
32053 |
-+ ret = -errno; |
32054 |
-+ kdbus_printf("error pthread_create: %d (%m)\n", |
32055 |
-+ ret); |
32056 |
-+ break; |
32057 |
-+ } |
32058 |
-+ |
32059 |
-+ /* just free before re-using */ |
32060 |
-+ kdbus_conn_free(conn_db[i]); |
32061 |
-+ conn_db[i] = NULL; |
32062 |
-+ |
32063 |
-+ /* We need to create connections here */ |
32064 |
-+ conn_db[i] = kdbus_hello(bus, 0, NULL, 0); |
32065 |
-+ if (!conn_db[i]) { |
32066 |
-+ ret = -errno; |
32067 |
-+ break; |
32068 |
-+ } |
32069 |
-+ |
32070 |
-+ ret = kdbus_add_match_empty(conn_db[i]); |
32071 |
-+ if (ret < 0) |
32072 |
-+ break; |
32073 |
-+ |
32074 |
-+ ret = kdbus_msg_send(conn_db[i], name, cookie++, |
32075 |
-+ 0, 0, 0, dst_id); |
32076 |
-+ if (ret < 0) { |
32077 |
-+ /* |
32078 |
-+ * Receivers are not reading their messages, |
32079 |
-+ * not scheduled ?! |
32080 |
-+ * |
32081 |
-+ * So set the pool full here, perhaps the |
32082 |
-+ * connection pool or queue was full, later |
32083 |
-+ * recheck receivers errors |
32084 |
-+ */ |
32085 |
-+ if (ret == -ENOBUFS || ret == -EXFULL) |
32086 |
-+ pool_full = true; |
32087 |
-+ break; |
32088 |
-+ } |
32089 |
-+ |
32090 |
-+ sent_packets++; |
32091 |
-+ } |
32092 |
-+ |
32093 |
-+ for (tid = 0; tid < thread_nr; tid++) { |
32094 |
-+ int thread_ret = 0; |
32095 |
-+ |
32096 |
-+ if (thread_id[tid]) { |
32097 |
-+ pthread_join(thread_id[tid], (void *)&thread_ret); |
32098 |
-+ if (thread_ret < 0) { |
32099 |
-+ /* Update only if send did not fail */ |
32100 |
-+ if (ret == 0) |
32101 |
-+ ret = thread_ret; |
32102 |
-+ |
32103 |
-+ lost_packets++; |
32104 |
-+ } |
32105 |
-+ } |
32106 |
-+ } |
32107 |
-+ |
32108 |
-+ /* |
32109 |
-+ * When sending if we did fail with -ENOBUFS or -EXFULL |
32110 |
-+ * then we should have set lost_packet and we should at |
32111 |
-+ * least have sent_packets set to KDBUS_CONN_MAX_MSGS_PER_USER |
32112 |
-+ */ |
32113 |
-+ if (pool_full) { |
32114 |
-+ ASSERT_RETURN(lost_packets > 0); |
32115 |
-+ |
32116 |
-+ /* |
32117 |
-+ * We should at least send KDBUS_CONN_MAX_MSGS_PER_USER |
32118 |
-+ * |
32119 |
-+ * For every send operation we create a thread to |
32120 |
-+ * recv the packet, so we keep the queue clean |
32121 |
-+ */ |
32122 |
-+ ASSERT_RETURN(sent_packets >= KDBUS_CONN_MAX_MSGS_PER_USER); |
32123 |
-+ |
32124 |
-+ /* |
32125 |
-+ * Set ret to zero since we only failed due to |
32126 |
-+ * the receiving threads that have not been |
32127 |
-+ * scheduled |
32128 |
-+ */ |
32129 |
-+ ret = 0; |
32130 |
-+ } |
32131 |
-+ |
32132 |
-+ return ret; |
32133 |
-+} |
32134 |
-+ |
32135 |
-+/* Return: TEST_OK or TEST_ERR on failure */ |
32136 |
-+static int kdbus_normal_test(const char *bus, const char *name, |
32137 |
-+ struct kdbus_conn **conn_db) |
32138 |
-+{ |
32139 |
-+ int ret; |
32140 |
-+ |
32141 |
-+ ret = kdbus_recv_in_threads(bus, name, conn_db); |
32142 |
-+ ASSERT_RETURN(ret >= 0); |
32143 |
-+ |
32144 |
-+ return TEST_OK; |
32145 |
-+} |
32146 |
-+ |
32147 |
-+static int kdbus_fork_test_by_id(const char *bus, |
32148 |
-+ struct kdbus_conn **conn_db, |
32149 |
-+ int parent_status, int child_status) |
32150 |
-+{ |
32151 |
-+ int ret; |
32152 |
-+ pid_t pid; |
32153 |
-+ uint64_t cookie = 0x9876ecba; |
32154 |
-+ struct kdbus_msg *msg = NULL; |
32155 |
-+ uint64_t offset = 0; |
32156 |
-+ int status = 0; |
32157 |
-+ |
32158 |
-+ /* |
32159 |
-+ * If the child_status is not EXIT_SUCCESS, then we expect |
32160 |
-+ * that sending from the child will fail, thus receiving |
32161 |
-+ * from parent must error with -ETIMEDOUT, and vice versa. |
32162 |
-+ */ |
32163 |
-+ bool parent_timedout = !!child_status; |
32164 |
-+ bool child_timedout = !!parent_status; |
32165 |
-+ |
32166 |
-+ pid = fork(); |
32167 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
32168 |
-+ |
32169 |
-+ if (pid == 0) { |
32170 |
-+ struct kdbus_conn *conn_src; |
32171 |
-+ |
32172 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32173 |
-+ ASSERT_EXIT(ret == 0); |
32174 |
-+ |
32175 |
-+ ret = drop_privileges(65534, 65534); |
32176 |
-+ ASSERT_EXIT(ret == 0); |
32177 |
-+ |
32178 |
-+ conn_src = kdbus_hello(bus, 0, NULL, 0); |
32179 |
-+ ASSERT_EXIT(conn_src); |
32180 |
-+ |
32181 |
-+ ret = kdbus_add_match_empty(conn_src); |
32182 |
-+ ASSERT_EXIT(ret == 0); |
32183 |
-+ |
32184 |
-+ /* |
32185 |
-+ * child_status is always checked against send |
32186 |
-+ * operations, in case it fails always return |
32187 |
-+ * EXIT_FAILURE. |
32188 |
-+ */ |
32189 |
-+ ret = kdbus_msg_send(conn_src, NULL, cookie, |
32190 |
-+ 0, 0, 0, conn_db[0]->id); |
32191 |
-+ ASSERT_EXIT(ret == child_status); |
32192 |
-+ |
32193 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); |
32194 |
-+ |
32195 |
-+ kdbus_conn_free(conn_src); |
32196 |
-+ |
32197 |
-+ /* |
32198 |
-+ * Child kdbus_msg_recv_poll() should timeout since |
32199 |
-+ * the parent_status was set to a non EXIT_SUCCESS |
32200 |
-+ * value. |
32201 |
-+ */ |
32202 |
-+ if (child_timedout) |
32203 |
-+ _exit(ret == -ETIMEDOUT ? EXIT_SUCCESS : EXIT_FAILURE); |
32204 |
-+ |
32205 |
-+ _exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); |
32206 |
-+ } |
32207 |
-+ |
32208 |
-+ ret = kdbus_msg_recv_poll(conn_db[0], 100, &msg, &offset); |
32209 |
-+ /* |
32210 |
-+ * If parent_timedout is set then this should fail with |
32211 |
-+ * -ETIMEDOUT since the child_status was set to a non |
32212 |
-+ * EXIT_SUCCESS value. Otherwise, assume |
32213 |
-+ * that kdbus_msg_recv_poll() has succeeded. |
32214 |
-+ */ |
32215 |
-+ if (parent_timedout) { |
32216 |
-+ ASSERT_RETURN_VAL(ret == -ETIMEDOUT, TEST_ERR); |
32217 |
-+ |
32218 |
-+ /* timedout no need to continue, we don't have the |
32219 |
-+ * child connection ID, so just terminate. */ |
32220 |
-+ goto out; |
32221 |
-+ } else { |
32222 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32223 |
-+ } |
32224 |
-+ |
32225 |
-+ ret = kdbus_msg_send(conn_db[0], NULL, ++cookie, |
32226 |
-+ 0, 0, 0, msg->src_id); |
32227 |
-+ /* |
32228 |
-+ * parent_status is checked against send operations, |
32229 |
-+ * on failures always return TEST_ERR. |
32230 |
-+ */ |
32231 |
-+ ASSERT_RETURN_VAL(ret == parent_status, TEST_ERR); |
32232 |
-+ |
32233 |
-+ kdbus_msg_free(msg); |
32234 |
-+ kdbus_free(conn_db[0], offset); |
32235 |
-+ |
32236 |
-+out: |
32237 |
-+ ret = waitpid(pid, &status, 0); |
32238 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
32239 |
-+ |
32240 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32241 |
-+} |
32242 |
-+ |
32243 |
-+/* |
32244 |
-+ * Return: TEST_OK, TEST_ERR or TEST_SKIP |
32245 |
-+ * we return TEST_OK only if the children return with the expected |
32246 |
-+ * 'expected_status' that is specified as an argument. |
32247 |
-+ */ |
32248 |
-+static int kdbus_fork_test(const char *bus, const char *name, |
32249 |
-+ struct kdbus_conn **conn_db, int expected_status) |
32250 |
-+{ |
32251 |
-+ pid_t pid; |
32252 |
-+ int ret = 0; |
32253 |
-+ int status = 0; |
32254 |
-+ |
32255 |
-+ pid = fork(); |
32256 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
32257 |
-+ |
32258 |
-+ if (pid == 0) { |
32259 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32260 |
-+ ASSERT_EXIT(ret == 0); |
32261 |
-+ |
32262 |
-+ ret = drop_privileges(65534, 65534); |
32263 |
-+ ASSERT_EXIT(ret == 0); |
32264 |
-+ |
32265 |
-+ ret = kdbus_recv_in_threads(bus, name, conn_db); |
32266 |
-+ _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE); |
32267 |
-+ } |
32268 |
-+ |
32269 |
-+ ret = waitpid(pid, &status, 0); |
32270 |
-+ ASSERT_RETURN(ret >= 0); |
32271 |
-+ |
32272 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32273 |
-+} |
32274 |
-+ |
32275 |
-+/* Return EXIT_SUCCESS, EXIT_FAILURE or negative errno */ |
32276 |
-+static int __kdbus_clone_userns_test(const char *bus, |
32277 |
-+ const char *name, |
32278 |
-+ struct kdbus_conn **conn_db, |
32279 |
-+ int expected_status) |
32280 |
-+{ |
32281 |
-+ int efd; |
32282 |
-+ pid_t pid; |
32283 |
-+ int ret = 0; |
32284 |
-+ unsigned int uid = 65534; |
32285 |
-+ int status; |
32286 |
-+ |
32287 |
-+ ret = drop_privileges(uid, uid); |
32288 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32289 |
-+ |
32290 |
-+ /* |
32291 |
-+ * Since we just dropped privileges, the dumpable flag was just |
32292 |
-+ * cleared which makes the /proc/$clone_child/uid_map to be |
32293 |
-+ * owned by root, hence any userns uid mapping will fail with |
32294 |
-+ * -EPERM since the mapping will be done by uid 65534. |
32295 |
-+ * |
32296 |
-+ * To avoid this set the dumpable flag again which makes procfs |
32297 |
-+ * update the /proc/$clone_child/ inodes owner to 65534. |
32298 |
-+ * |
32299 |
-+ * Using this we will be able write to /proc/$clone_child/uid_map |
32300 |
-+ * as uid 65534 and map the uid 65534 to 0 inside the user |
32301 |
-+ * namespace. |
32302 |
-+ */ |
32303 |
-+ ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER); |
32304 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32305 |
-+ |
32306 |
-+ /* sync parent/child */ |
32307 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
32308 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
32309 |
-+ |
32310 |
-+ pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWUSER, NULL); |
32311 |
-+ if (pid < 0) { |
32312 |
-+ ret = -errno; |
32313 |
-+ kdbus_printf("error clone: %d (%m)\n", ret); |
32314 |
-+ /* |
32315 |
-+ * Normal user not allowed to create userns, |
32316 |
-+ * so nothing to worry about ? |
32317 |
-+ */ |
32318 |
-+ if (ret == -EPERM) { |
32319 |
-+ kdbus_printf("-- CLONE_NEWUSER TEST Failed for uid: %u\n" |
32320 |
-+ "-- Make sure that your kernel do not allow " |
32321 |
-+ "CLONE_NEWUSER for unprivileged users\n" |
32322 |
-+ "-- Upstream Commit: " |
32323 |
-+ "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5eaf563e\n", |
32324 |
-+ uid); |
32325 |
-+ ret = 0; |
32326 |
-+ } |
32327 |
-+ |
32328 |
-+ return ret; |
32329 |
-+ } |
32330 |
-+ |
32331 |
-+ if (pid == 0) { |
32332 |
-+ struct kdbus_conn *conn_src; |
32333 |
-+ eventfd_t event_status = 0; |
32334 |
-+ |
32335 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32336 |
-+ ASSERT_EXIT(ret == 0); |
32337 |
-+ |
32338 |
-+ ret = eventfd_read(efd, &event_status); |
32339 |
-+ ASSERT_EXIT(ret >= 0 && event_status == 1); |
32340 |
-+ |
32341 |
-+ /* ping connection from the new user namespace */ |
32342 |
-+ conn_src = kdbus_hello(bus, 0, NULL, 0); |
32343 |
-+ ASSERT_EXIT(conn_src); |
32344 |
-+ |
32345 |
-+ ret = kdbus_add_match_empty(conn_src); |
32346 |
-+ ASSERT_EXIT(ret == 0); |
32347 |
-+ |
32348 |
-+ ret = kdbus_msg_send(conn_src, name, 0xabcd1234, |
32349 |
-+ 0, 0, 0, KDBUS_DST_ID_NAME); |
32350 |
-+ kdbus_conn_free(conn_src); |
32351 |
-+ |
32352 |
-+ _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE); |
32353 |
-+ } |
32354 |
-+ |
32355 |
-+ ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"); |
32356 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32357 |
-+ |
32358 |
-+ /* Tell child we are ready */ |
32359 |
-+ ret = eventfd_write(efd, 1); |
32360 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
32361 |
-+ |
32362 |
-+ ret = waitpid(pid, &status, 0); |
32363 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
32364 |
-+ |
32365 |
-+ close(efd); |
32366 |
-+ |
32367 |
-+ return status == EXIT_SUCCESS ? TEST_OK : TEST_ERR; |
32368 |
-+} |
32369 |
-+ |
32370 |
-+static int kdbus_clone_userns_test(const char *bus, |
32371 |
-+ const char *name, |
32372 |
-+ struct kdbus_conn **conn_db, |
32373 |
-+ int expected_status) |
32374 |
-+{ |
32375 |
-+ pid_t pid; |
32376 |
-+ int ret = 0; |
32377 |
-+ int status; |
32378 |
-+ |
32379 |
-+ pid = fork(); |
32380 |
-+ ASSERT_RETURN_VAL(pid >= 0, -errno); |
32381 |
-+ |
32382 |
-+ if (pid == 0) { |
32383 |
-+ ret = prctl(PR_SET_PDEATHSIG, SIGKILL); |
32384 |
-+ if (ret < 0) |
32385 |
-+ _exit(EXIT_FAILURE); |
32386 |
-+ |
32387 |
-+ ret = __kdbus_clone_userns_test(bus, name, conn_db, |
32388 |
-+ expected_status); |
32389 |
-+ _exit(ret); |
32390 |
-+ } |
32391 |
-+ |
32392 |
-+ /* |
32393 |
-+ * Receive in the original (root privileged) user namespace, |
32394 |
-+ * must fail with -ETIMEDOUT. |
32395 |
-+ */ |
32396 |
-+ ret = kdbus_msg_recv_poll(conn_db[0], 100, NULL, NULL); |
32397 |
-+ ASSERT_RETURN_VAL(ret == -ETIMEDOUT, ret); |
32398 |
-+ |
32399 |
-+ ret = waitpid(pid, &status, 0); |
32400 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
32401 |
-+ |
32402 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
32403 |
-+} |
32404 |
-+ |
32405 |
-+int kdbus_test_policy_ns(struct kdbus_test_env *env) |
32406 |
-+{ |
32407 |
-+ int i; |
32408 |
-+ int ret; |
32409 |
-+ struct kdbus_conn *activator = NULL; |
32410 |
-+ struct kdbus_conn *policy_holder = NULL; |
32411 |
-+ char *bus = env->buspath; |
32412 |
-+ |
32413 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
32414 |
-+ ASSERT_RETURN(ret >= 0); |
32415 |
-+ |
32416 |
-+ /* no enough privileges, SKIP test */ |
32417 |
-+ if (!ret) |
32418 |
-+ return TEST_SKIP; |
32419 |
-+ |
32420 |
-+ /* we require user-namespaces */ |
32421 |
-+ if (access("/proc/self/uid_map", F_OK) != 0) |
32422 |
-+ return TEST_SKIP; |
32423 |
-+ |
32424 |
-+ /* uids/gids must be mapped */ |
32425 |
-+ if (!all_uids_gids_are_mapped()) |
32426 |
-+ return TEST_SKIP; |
32427 |
-+ |
32428 |
-+ conn_db = calloc(MAX_CONN, sizeof(struct kdbus_conn *)); |
32429 |
-+ ASSERT_RETURN(conn_db); |
32430 |
-+ |
32431 |
-+ memset(conn_db, 0, MAX_CONN * sizeof(struct kdbus_conn *)); |
32432 |
-+ |
32433 |
-+ conn_db[0] = kdbus_hello(bus, 0, NULL, 0); |
32434 |
-+ ASSERT_RETURN(conn_db[0]); |
32435 |
-+ |
32436 |
-+ ret = kdbus_add_match_empty(conn_db[0]); |
32437 |
-+ ASSERT_RETURN(ret == 0); |
32438 |
-+ |
32439 |
-+ ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM); |
32440 |
-+ ASSERT_EXIT(ret == 0); |
32441 |
-+ |
32442 |
-+ ret = kdbus_register_policy_holder(bus, POLICY_NAME, |
32443 |
-+ &policy_holder); |
32444 |
-+ ASSERT_RETURN(ret == 0); |
32445 |
-+ |
32446 |
-+ /* Try to register the same name with an activator */ |
32447 |
-+ ret = kdbus_register_same_activator(bus, POLICY_NAME, |
32448 |
-+ &activator); |
32449 |
-+ ASSERT_RETURN(ret == 0); |
32450 |
-+ |
32451 |
-+ /* Acquire POLICY_NAME */ |
32452 |
-+ ret = kdbus_name_acquire(conn_db[0], POLICY_NAME, NULL); |
32453 |
-+ ASSERT_RETURN(ret == 0); |
32454 |
-+ |
32455 |
-+ ret = kdbus_normal_test(bus, POLICY_NAME, conn_db); |
32456 |
-+ ASSERT_RETURN(ret == 0); |
32457 |
-+ |
32458 |
-+ ret = kdbus_list(conn_db[0], KDBUS_LIST_NAMES | |
32459 |
-+ KDBUS_LIST_UNIQUE | |
32460 |
-+ KDBUS_LIST_ACTIVATORS | |
32461 |
-+ KDBUS_LIST_QUEUED); |
32462 |
-+ ASSERT_RETURN(ret == 0); |
32463 |
-+ |
32464 |
-+ ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, EXIT_SUCCESS); |
32465 |
-+ ASSERT_RETURN(ret == 0); |
32466 |
-+ |
32467 |
-+ /* |
32468 |
-+ * children connections are able to talk to conn_db[0] since |
32469 |
-+ * current POLICY_NAME TALK type is KDBUS_POLICY_ACCESS_WORLD, |
32470 |
-+ * so expect EXIT_SUCCESS when sending from child. However, |
32471 |
-+ * since the child's connection does not own any well-known |
32472 |
-+ * name, The parent connection conn_db[0] should fail with |
32473 |
-+ * -EPERM but since it is a privileged bus user the TALK is |
32474 |
-+ * allowed. |
32475 |
-+ */ |
32476 |
-+ ret = kdbus_fork_test_by_id(bus, conn_db, |
32477 |
-+ EXIT_SUCCESS, EXIT_SUCCESS); |
32478 |
-+ ASSERT_EXIT(ret == 0); |
32479 |
-+ |
32480 |
-+ /* |
32481 |
-+ * Connections that can talk are perhaps being destroyed now. |
32482 |
-+ * Restrict the policy and purge cache entries where the |
32483 |
-+ * conn_db[0] is the destination. |
32484 |
-+ * |
32485 |
-+ * Now only connections with uid == 0 are allowed to talk. |
32486 |
-+ */ |
32487 |
-+ ret = kdbus_set_policy_talk(policy_holder, POLICY_NAME, |
32488 |
-+ geteuid(), KDBUS_POLICY_ACCESS_USER); |
32489 |
-+ ASSERT_RETURN(ret == 0); |
32490 |
-+ |
32491 |
-+ /* |
32492 |
-+ * Testing connections (FORK+DROP) again: |
32493 |
-+ * After setting the policy re-check connections |
32494 |
-+ * we expect the children to fail with -EPERM |
32495 |
-+ */ |
32496 |
-+ ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, -EPERM); |
32497 |
-+ ASSERT_RETURN(ret == 0); |
32498 |
-+ |
32499 |
-+ /* |
32500 |
-+ * Now expect that both parent and child to fail. |
32501 |
-+ * |
32502 |
-+ * Child should fail with -EPERM since we just restricted |
32503 |
-+ * the POLICY_NAME TALK to uid 0 and its uid is 65534. |
32504 |
-+ * |
32505 |
-+ * Since the parent's connection will timeout when receiving |
32506 |
-+ * from the child, we never continue. FWIW just put -EPERM. |
32507 |
-+ */ |
32508 |
-+ ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM); |
32509 |
-+ ASSERT_EXIT(ret == 0); |
32510 |
-+ |
32511 |
-+ /* Check if the name can be reached in a new userns */ |
32512 |
-+ ret = kdbus_clone_userns_test(bus, POLICY_NAME, conn_db, -EPERM); |
32513 |
-+ ASSERT_RETURN(ret == 0); |
32514 |
-+ |
32515 |
-+ for (i = 0; i < MAX_CONN; i++) |
32516 |
-+ kdbus_conn_free(conn_db[i]); |
32517 |
-+ |
32518 |
-+ kdbus_conn_free(activator); |
32519 |
-+ kdbus_conn_free(policy_holder); |
32520 |
-+ |
32521 |
-+ free(conn_db); |
32522 |
-+ |
32523 |
-+ return ret; |
32524 |
-+} |
32525 |
-diff --git a/tools/testing/selftests/kdbus/test-policy-priv.c b/tools/testing/selftests/kdbus/test-policy-priv.c |
32526 |
-new file mode 100644 |
32527 |
-index 0000000..0208638 |
32528 |
---- /dev/null |
32529 |
-+++ b/tools/testing/selftests/kdbus/test-policy-priv.c |
32530 |
-@@ -0,0 +1,1285 @@ |
32531 |
-+#include <errno.h> |
32532 |
-+#include <stdio.h> |
32533 |
-+#include <string.h> |
32534 |
-+#include <fcntl.h> |
32535 |
-+#include <stdlib.h> |
32536 |
-+#include <stdint.h> |
32537 |
-+#include <stdbool.h> |
32538 |
-+#include <unistd.h> |
32539 |
-+#include <time.h> |
32540 |
-+#include <sys/capability.h> |
32541 |
-+#include <sys/eventfd.h> |
32542 |
-+#include <sys/wait.h> |
32543 |
-+ |
32544 |
-+#include "kdbus-test.h" |
32545 |
-+#include "kdbus-util.h" |
32546 |
-+#include "kdbus-enum.h" |
32547 |
-+ |
32548 |
-+static int test_policy_priv_by_id(const char *bus, |
32549 |
-+ struct kdbus_conn *conn_dst, |
32550 |
-+ bool drop_second_user, |
32551 |
-+ int parent_status, |
32552 |
-+ int child_status) |
32553 |
-+{ |
32554 |
-+ int ret = 0; |
32555 |
-+ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32556 |
-+ |
32557 |
-+ ASSERT_RETURN(conn_dst); |
32558 |
-+ |
32559 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, bus, ({ |
32560 |
-+ ret = kdbus_msg_send(unpriv, NULL, |
32561 |
-+ expected_cookie, 0, 0, 0, |
32562 |
-+ conn_dst->id); |
32563 |
-+ ASSERT_EXIT(ret == child_status); |
32564 |
-+ })); |
32565 |
-+ ASSERT_RETURN(ret >= 0); |
32566 |
-+ |
32567 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 300, NULL, NULL); |
32568 |
-+ ASSERT_RETURN(ret == parent_status); |
32569 |
-+ |
32570 |
-+ return 0; |
32571 |
-+} |
32572 |
-+ |
32573 |
-+static int test_policy_priv_by_broadcast(const char *bus, |
32574 |
-+ struct kdbus_conn *conn_dst, |
32575 |
-+ int drop_second_user, |
32576 |
-+ int parent_status, |
32577 |
-+ int child_status) |
32578 |
-+{ |
32579 |
-+ int efd; |
32580 |
-+ int ret = 0; |
32581 |
-+ eventfd_t event_status = 0; |
32582 |
-+ struct kdbus_msg *msg = NULL; |
32583 |
-+ uid_t second_uid = UNPRIV_UID; |
32584 |
-+ gid_t second_gid = UNPRIV_GID; |
32585 |
-+ struct kdbus_conn *child_2 = conn_dst; |
32586 |
-+ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32587 |
-+ |
32588 |
-+ /* Drop to another unprivileged user other than UNPRIV_UID */ |
32589 |
-+ if (drop_second_user == DROP_OTHER_UNPRIV) { |
32590 |
-+ second_uid = UNPRIV_UID - 1; |
32591 |
-+ second_gid = UNPRIV_GID - 1; |
32592 |
-+ } |
32593 |
-+ |
32594 |
-+ /* child will signal parent to send broadcast */ |
32595 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
32596 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
32597 |
-+ |
32598 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
32599 |
-+ struct kdbus_conn *child; |
32600 |
-+ |
32601 |
-+ child = kdbus_hello(bus, 0, NULL, 0); |
32602 |
-+ ASSERT_EXIT(child); |
32603 |
-+ |
32604 |
-+ ret = kdbus_add_match_empty(child); |
32605 |
-+ ASSERT_EXIT(ret == 0); |
32606 |
-+ |
32607 |
-+ /* signal parent */ |
32608 |
-+ ret = eventfd_write(efd, 1); |
32609 |
-+ ASSERT_EXIT(ret == 0); |
32610 |
-+ |
32611 |
-+ /* Use a little bit high time */ |
32612 |
-+ ret = kdbus_msg_recv_poll(child, 500, &msg, NULL); |
32613 |
-+ ASSERT_EXIT(ret == child_status); |
32614 |
-+ |
32615 |
-+ /* |
32616 |
-+ * If we expect the child to get the broadcast |
32617 |
-+ * message, then check the received cookie. |
32618 |
-+ */ |
32619 |
-+ if (ret == 0) { |
32620 |
-+ ASSERT_EXIT(expected_cookie == msg->cookie); |
32621 |
-+ } |
32622 |
-+ |
32623 |
-+ /* Use expected_cookie since 'msg' might be NULL */ |
32624 |
-+ ret = kdbus_msg_send(child, NULL, expected_cookie + 1, |
32625 |
-+ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
32626 |
-+ ASSERT_EXIT(ret == 0); |
32627 |
-+ |
32628 |
-+ kdbus_msg_free(msg); |
32629 |
-+ kdbus_conn_free(child); |
32630 |
-+ }), |
32631 |
-+ ({ |
32632 |
-+ if (drop_second_user == DO_NOT_DROP) { |
32633 |
-+ ASSERT_RETURN(child_2); |
32634 |
-+ |
32635 |
-+ ret = eventfd_read(efd, &event_status); |
32636 |
-+ ASSERT_RETURN(ret >= 0 && event_status == 1); |
32637 |
-+ |
32638 |
-+ ret = kdbus_msg_send(child_2, NULL, |
32639 |
-+ expected_cookie, 0, 0, 0, |
32640 |
-+ KDBUS_DST_ID_BROADCAST); |
32641 |
-+ ASSERT_RETURN(ret == 0); |
32642 |
-+ |
32643 |
-+ /* drop own broadcast */ |
32644 |
-+ ret = kdbus_msg_recv(child_2, &msg, NULL); |
32645 |
-+ ASSERT_RETURN(ret == 0); |
32646 |
-+ ASSERT_RETURN(msg->src_id == child_2->id); |
32647 |
-+ kdbus_msg_free(msg); |
32648 |
-+ |
32649 |
-+ /* Use a little bit high time */ |
32650 |
-+ ret = kdbus_msg_recv_poll(child_2, 1000, |
32651 |
-+ &msg, NULL); |
32652 |
-+ ASSERT_RETURN(ret == parent_status); |
32653 |
-+ |
32654 |
-+ /* |
32655 |
-+ * Check returned cookie in case we expect |
32656 |
-+ * success. |
32657 |
-+ */ |
32658 |
-+ if (ret == 0) { |
32659 |
-+ ASSERT_RETURN(msg->cookie == |
32660 |
-+ expected_cookie + 1); |
32661 |
-+ } |
32662 |
-+ |
32663 |
-+ kdbus_msg_free(msg); |
32664 |
-+ } else { |
32665 |
-+ /* |
32666 |
-+ * Two unprivileged users will try to |
32667 |
-+ * communicate using broadcast. |
32668 |
-+ */ |
32669 |
-+ ret = RUN_UNPRIVILEGED(second_uid, second_gid, ({ |
32670 |
-+ child_2 = kdbus_hello(bus, 0, NULL, 0); |
32671 |
-+ ASSERT_EXIT(child_2); |
32672 |
-+ |
32673 |
-+ ret = kdbus_add_match_empty(child_2); |
32674 |
-+ ASSERT_EXIT(ret == 0); |
32675 |
-+ |
32676 |
-+ ret = eventfd_read(efd, &event_status); |
32677 |
-+ ASSERT_EXIT(ret >= 0 && event_status == 1); |
32678 |
-+ |
32679 |
-+ ret = kdbus_msg_send(child_2, NULL, |
32680 |
-+ expected_cookie, 0, 0, 0, |
32681 |
-+ KDBUS_DST_ID_BROADCAST); |
32682 |
-+ ASSERT_EXIT(ret == 0); |
32683 |
-+ |
32684 |
-+ /* drop own broadcast */ |
32685 |
-+ ret = kdbus_msg_recv(child_2, &msg, NULL); |
32686 |
-+ ASSERT_RETURN(ret == 0); |
32687 |
-+ ASSERT_RETURN(msg->src_id == child_2->id); |
32688 |
-+ kdbus_msg_free(msg); |
32689 |
-+ |
32690 |
-+ /* Use a little bit high time */ |
32691 |
-+ ret = kdbus_msg_recv_poll(child_2, 1000, |
32692 |
-+ &msg, NULL); |
32693 |
-+ ASSERT_EXIT(ret == parent_status); |
32694 |
-+ |
32695 |
-+ /* |
32696 |
-+ * Check returned cookie in case we expect |
32697 |
-+ * success. |
32698 |
-+ */ |
32699 |
-+ if (ret == 0) { |
32700 |
-+ ASSERT_EXIT(msg->cookie == |
32701 |
-+ expected_cookie + 1); |
32702 |
-+ } |
32703 |
-+ |
32704 |
-+ kdbus_msg_free(msg); |
32705 |
-+ kdbus_conn_free(child_2); |
32706 |
-+ }), |
32707 |
-+ ({ 0; })); |
32708 |
-+ ASSERT_RETURN(ret == 0); |
32709 |
-+ } |
32710 |
-+ })); |
32711 |
-+ ASSERT_RETURN(ret == 0); |
32712 |
-+ |
32713 |
-+ close(efd); |
32714 |
-+ |
32715 |
-+ return ret; |
32716 |
-+} |
32717 |
-+ |
32718 |
-+static void nosig(int sig) |
32719 |
-+{ |
32720 |
-+} |
32721 |
-+ |
32722 |
-+static int test_priv_before_policy_upload(struct kdbus_test_env *env) |
32723 |
-+{ |
32724 |
-+ int ret = 0; |
32725 |
-+ struct kdbus_conn *conn; |
32726 |
-+ |
32727 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
32728 |
-+ ASSERT_RETURN(conn); |
32729 |
-+ |
32730 |
-+ /* |
32731 |
-+ * Make sure unprivileged bus user cannot acquire names |
32732 |
-+ * before registring any policy holder. |
32733 |
-+ */ |
32734 |
-+ |
32735 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
32736 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
32737 |
-+ ASSERT_EXIT(ret < 0); |
32738 |
-+ })); |
32739 |
-+ ASSERT_RETURN(ret == 0); |
32740 |
-+ |
32741 |
-+ /* |
32742 |
-+ * Make sure unprivileged bus users cannot talk by default |
32743 |
-+ * to privileged ones, unless a policy holder that allows |
32744 |
-+ * this was uploaded. |
32745 |
-+ */ |
32746 |
-+ |
32747 |
-+ ret = test_policy_priv_by_id(env->buspath, conn, false, |
32748 |
-+ -ETIMEDOUT, -EPERM); |
32749 |
-+ ASSERT_RETURN(ret == 0); |
32750 |
-+ |
32751 |
-+ /* Activate matching for a privileged connection */ |
32752 |
-+ ret = kdbus_add_match_empty(conn); |
32753 |
-+ ASSERT_RETURN(ret == 0); |
32754 |
-+ |
32755 |
-+ /* |
32756 |
-+ * First make sure that BROADCAST with msg flag |
32757 |
-+ * KDBUS_MSG_EXPECT_REPLY will fail with -ENOTUNIQ |
32758 |
-+ */ |
32759 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
32760 |
-+ ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, |
32761 |
-+ KDBUS_MSG_EXPECT_REPLY, |
32762 |
-+ 5000000000ULL, 0, |
32763 |
-+ KDBUS_DST_ID_BROADCAST); |
32764 |
-+ ASSERT_EXIT(ret == -ENOTUNIQ); |
32765 |
-+ })); |
32766 |
-+ ASSERT_RETURN(ret == 0); |
32767 |
-+ |
32768 |
-+ /* |
32769 |
-+ * Test broadcast with a privileged connection. |
32770 |
-+ * |
32771 |
-+ * The first unprivileged receiver should not get the |
32772 |
-+ * broadcast message sent by the privileged connection, |
32773 |
-+ * since there is no a TALK policy that allows the |
32774 |
-+ * unprivileged to TALK to the privileged connection. It |
32775 |
-+ * will fail with -ETIMEDOUT |
32776 |
-+ * |
32777 |
-+ * Then second case: |
32778 |
-+ * The privileged connection should get the broadcast |
32779 |
-+ * message from the unprivileged one. Since the receiver is |
32780 |
-+ * a privileged bus user and it has default TALK access to |
32781 |
-+ * all connections it will receive those. |
32782 |
-+ */ |
32783 |
-+ |
32784 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, conn, |
32785 |
-+ DO_NOT_DROP, |
32786 |
-+ 0, -ETIMEDOUT); |
32787 |
-+ ASSERT_RETURN(ret == 0); |
32788 |
-+ |
32789 |
-+ |
32790 |
-+ /* |
32791 |
-+ * Test broadcast with two unprivileged connections running |
32792 |
-+ * under the same user. |
32793 |
-+ * |
32794 |
-+ * Both connections should succeed. |
32795 |
-+ */ |
32796 |
-+ |
32797 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32798 |
-+ DROP_SAME_UNPRIV, 0, 0); |
32799 |
-+ ASSERT_RETURN(ret == 0); |
32800 |
-+ |
32801 |
-+ /* |
32802 |
-+ * Test broadcast with two unprivileged connections running |
32803 |
-+ * under different users. |
32804 |
-+ * |
32805 |
-+ * Both connections will fail with -ETIMEDOUT. |
32806 |
-+ */ |
32807 |
-+ |
32808 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32809 |
-+ DROP_OTHER_UNPRIV, |
32810 |
-+ -ETIMEDOUT, -ETIMEDOUT); |
32811 |
-+ ASSERT_RETURN(ret == 0); |
32812 |
-+ |
32813 |
-+ kdbus_conn_free(conn); |
32814 |
-+ |
32815 |
-+ return ret; |
32816 |
-+} |
32817 |
-+ |
32818 |
-+static int test_broadcast_after_policy_upload(struct kdbus_test_env *env) |
32819 |
-+{ |
32820 |
-+ int ret; |
32821 |
-+ int efd; |
32822 |
-+ eventfd_t event_status = 0; |
32823 |
-+ struct kdbus_msg *msg = NULL; |
32824 |
-+ struct kdbus_conn *owner_a, *owner_b; |
32825 |
-+ struct kdbus_conn *holder_a, *holder_b; |
32826 |
-+ struct kdbus_policy_access access = {}; |
32827 |
-+ uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef; |
32828 |
-+ |
32829 |
-+ owner_a = kdbus_hello(env->buspath, 0, NULL, 0); |
32830 |
-+ ASSERT_RETURN(owner_a); |
32831 |
-+ |
32832 |
-+ ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL); |
32833 |
-+ ASSERT_EXIT(ret >= 0); |
32834 |
-+ |
32835 |
-+ /* |
32836 |
-+ * Make sure unprivileged bus users cannot talk by default |
32837 |
-+ * to privileged ones, unless a policy holder that allows |
32838 |
-+ * this was uploaded. |
32839 |
-+ */ |
32840 |
-+ |
32841 |
-+ ++expected_cookie; |
32842 |
-+ ret = test_policy_priv_by_id(env->buspath, owner_a, false, |
32843 |
-+ -ETIMEDOUT, -EPERM); |
32844 |
-+ ASSERT_RETURN(ret == 0); |
32845 |
-+ |
32846 |
-+ /* |
32847 |
-+ * Make sure that privileged won't receive broadcasts unless |
32848 |
-+ * it installs a match. It will fail with -ETIMEDOUT |
32849 |
-+ * |
32850 |
-+ * At same time check that the unprivileged connection will |
32851 |
-+ * not receive the broadcast message from the privileged one |
32852 |
-+ * since the privileged one owns a name with a restricted |
32853 |
-+ * policy TALK (actually the TALK policy is still not |
32854 |
-+ * registered so we fail by default), thus the unprivileged |
32855 |
-+ * receiver is not able to TALK to that name. |
32856 |
-+ */ |
32857 |
-+ |
32858 |
-+ /* Activate matching for a privileged connection */ |
32859 |
-+ ret = kdbus_add_match_empty(owner_a); |
32860 |
-+ ASSERT_RETURN(ret == 0); |
32861 |
-+ |
32862 |
-+ /* |
32863 |
-+ * Redo the previous test. The privileged conn owner_a is |
32864 |
-+ * able to TALK to any connection so it will receive the |
32865 |
-+ * broadcast message now. |
32866 |
-+ */ |
32867 |
-+ |
32868 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
32869 |
-+ DO_NOT_DROP, |
32870 |
-+ 0, -ETIMEDOUT); |
32871 |
-+ ASSERT_RETURN(ret == 0); |
32872 |
-+ |
32873 |
-+ /* |
32874 |
-+ * Test that broadcast between two unprivileged users running |
32875 |
-+ * under the same user still succeed. |
32876 |
-+ */ |
32877 |
-+ |
32878 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32879 |
-+ DROP_SAME_UNPRIV, 0, 0); |
32880 |
-+ ASSERT_RETURN(ret == 0); |
32881 |
-+ |
32882 |
-+ /* |
32883 |
-+ * Test broadcast with two unprivileged connections running |
32884 |
-+ * under different users. |
32885 |
-+ * |
32886 |
-+ * Both connections will fail with -ETIMEDOUT. |
32887 |
-+ */ |
32888 |
-+ |
32889 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
32890 |
-+ DROP_OTHER_UNPRIV, |
32891 |
-+ -ETIMEDOUT, -ETIMEDOUT); |
32892 |
-+ ASSERT_RETURN(ret == 0); |
32893 |
-+ |
32894 |
-+ access = (struct kdbus_policy_access){ |
32895 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
32896 |
-+ .id = geteuid(), |
32897 |
-+ .access = KDBUS_POLICY_OWN, |
32898 |
-+ }; |
32899 |
-+ |
32900 |
-+ holder_a = kdbus_hello_registrar(env->buspath, |
32901 |
-+ "com.example.broadcastA", |
32902 |
-+ &access, 1, |
32903 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
32904 |
-+ ASSERT_RETURN(holder_a); |
32905 |
-+ |
32906 |
-+ holder_b = kdbus_hello_registrar(env->buspath, |
32907 |
-+ "com.example.broadcastB", |
32908 |
-+ &access, 1, |
32909 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
32910 |
-+ ASSERT_RETURN(holder_b); |
32911 |
-+ |
32912 |
-+ /* Free connections and their received messages and restart */ |
32913 |
-+ kdbus_conn_free(owner_a); |
32914 |
-+ |
32915 |
-+ owner_a = kdbus_hello(env->buspath, 0, NULL, 0); |
32916 |
-+ ASSERT_RETURN(owner_a); |
32917 |
-+ |
32918 |
-+ /* Activate matching for a privileged connection */ |
32919 |
-+ ret = kdbus_add_match_empty(owner_a); |
32920 |
-+ ASSERT_RETURN(ret == 0); |
32921 |
-+ |
32922 |
-+ ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL); |
32923 |
-+ ASSERT_EXIT(ret >= 0); |
32924 |
-+ |
32925 |
-+ owner_b = kdbus_hello(env->buspath, 0, NULL, 0); |
32926 |
-+ ASSERT_RETURN(owner_b); |
32927 |
-+ |
32928 |
-+ ret = kdbus_name_acquire(owner_b, "com.example.broadcastB", NULL); |
32929 |
-+ ASSERT_EXIT(ret >= 0); |
32930 |
-+ |
32931 |
-+ /* Activate matching for a privileged connection */ |
32932 |
-+ ret = kdbus_add_match_empty(owner_b); |
32933 |
-+ ASSERT_RETURN(ret == 0); |
32934 |
-+ |
32935 |
-+ /* |
32936 |
-+ * Test that even if "com.example.broadcastA" and |
32937 |
-+ * "com.example.broadcastB" do have a TALK access by default |
32938 |
-+ * they are able to signal each other using broadcast due to |
32939 |
-+ * the fact they are privileged connections, they receive |
32940 |
-+ * all broadcasts if the match allows it. |
32941 |
-+ */ |
32942 |
-+ |
32943 |
-+ ++expected_cookie; |
32944 |
-+ ret = kdbus_msg_send(owner_a, NULL, expected_cookie, 0, |
32945 |
-+ 0, 0, KDBUS_DST_ID_BROADCAST); |
32946 |
-+ ASSERT_RETURN(ret == 0); |
32947 |
-+ |
32948 |
-+ ret = kdbus_msg_recv_poll(owner_a, 100, &msg, NULL); |
32949 |
-+ ASSERT_RETURN(ret == 0); |
32950 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
32951 |
-+ |
32952 |
-+ /* Check src ID */ |
32953 |
-+ ASSERT_RETURN(msg->src_id == owner_a->id); |
32954 |
-+ |
32955 |
-+ kdbus_msg_free(msg); |
32956 |
-+ |
32957 |
-+ ret = kdbus_msg_recv_poll(owner_b, 100, &msg, NULL); |
32958 |
-+ ASSERT_RETURN(ret == 0); |
32959 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
32960 |
-+ |
32961 |
-+ /* Check src ID */ |
32962 |
-+ ASSERT_RETURN(msg->src_id == owner_a->id); |
32963 |
-+ |
32964 |
-+ kdbus_msg_free(msg); |
32965 |
-+ |
32966 |
-+ /* Release name "com.example.broadcastB" */ |
32967 |
-+ |
32968 |
-+ ret = kdbus_name_release(owner_b, "com.example.broadcastB"); |
32969 |
-+ ASSERT_EXIT(ret >= 0); |
32970 |
-+ |
32971 |
-+ /* KDBUS_POLICY_OWN for unprivileged connections */ |
32972 |
-+ access = (struct kdbus_policy_access){ |
32973 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
32974 |
-+ .id = geteuid(), |
32975 |
-+ .access = KDBUS_POLICY_OWN, |
32976 |
-+ }; |
32977 |
-+ |
32978 |
-+ /* Update the policy so unprivileged will own the name */ |
32979 |
-+ |
32980 |
-+ ret = kdbus_conn_update_policy(holder_b, |
32981 |
-+ "com.example.broadcastB", |
32982 |
-+ &access, 1); |
32983 |
-+ ASSERT_RETURN(ret == 0); |
32984 |
-+ |
32985 |
-+ /* |
32986 |
-+ * Send broadcasts from an unprivileged connection that |
32987 |
-+ * owns a name "com.example.broadcastB". |
32988 |
-+ * |
32989 |
-+ * We'll have four destinations here: |
32990 |
-+ * |
32991 |
-+ * 1) destination owner_a: privileged connection that owns |
32992 |
-+ * "com.example.broadcastA". It will receive the broadcast |
32993 |
-+ * since it is a privileged has default TALK access to all |
32994 |
-+ * connections, and it is subscribed to the match. |
32995 |
-+ * Will succeed. |
32996 |
-+ * |
32997 |
-+ * owner_b: privileged connection (running under a different |
32998 |
-+ * uid) that do not own names, but with an empty broadcast |
32999 |
-+ * match, so it will receive broadcasts since it has default |
33000 |
-+ * TALK access to all connection. |
33001 |
-+ * |
33002 |
-+ * unpriv_a: unpriv connection that do not own any name. |
33003 |
-+ * It will receive the broadcast since it is running under |
33004 |
-+ * the same user of the one broadcasting and did install |
33005 |
-+ * matches. It should get the message. |
33006 |
-+ * |
33007 |
-+ * unpriv_b: unpriv connection is not interested in broadcast |
33008 |
-+ * messages, so it did not install broadcast matches. Should |
33009 |
-+ * fail with -ETIMEDOUT |
33010 |
-+ */ |
33011 |
-+ |
33012 |
-+ ++expected_cookie; |
33013 |
-+ efd = eventfd(0, EFD_CLOEXEC); |
33014 |
-+ ASSERT_RETURN_VAL(efd >= 0, efd); |
33015 |
-+ |
33016 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ |
33017 |
-+ struct kdbus_conn *unpriv_owner; |
33018 |
-+ struct kdbus_conn *unpriv_a, *unpriv_b; |
33019 |
-+ |
33020 |
-+ unpriv_owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33021 |
-+ ASSERT_EXIT(unpriv_owner); |
33022 |
-+ |
33023 |
-+ unpriv_a = kdbus_hello(env->buspath, 0, NULL, 0); |
33024 |
-+ ASSERT_EXIT(unpriv_a); |
33025 |
-+ |
33026 |
-+ unpriv_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33027 |
-+ ASSERT_EXIT(unpriv_b); |
33028 |
-+ |
33029 |
-+ ret = kdbus_name_acquire(unpriv_owner, |
33030 |
-+ "com.example.broadcastB", |
33031 |
-+ NULL); |
33032 |
-+ ASSERT_EXIT(ret >= 0); |
33033 |
-+ |
33034 |
-+ ret = kdbus_add_match_empty(unpriv_a); |
33035 |
-+ ASSERT_EXIT(ret == 0); |
33036 |
-+ |
33037 |
-+ /* Signal that we are doing broadcasts */ |
33038 |
-+ ret = eventfd_write(efd, 1); |
33039 |
-+ ASSERT_EXIT(ret == 0); |
33040 |
-+ |
33041 |
-+ /* |
33042 |
-+ * Do broadcast from a connection that owns the |
33043 |
-+ * names "com.example.broadcastB". |
33044 |
-+ */ |
33045 |
-+ ret = kdbus_msg_send(unpriv_owner, NULL, |
33046 |
-+ expected_cookie, |
33047 |
-+ 0, 0, 0, |
33048 |
-+ KDBUS_DST_ID_BROADCAST); |
33049 |
-+ ASSERT_EXIT(ret == 0); |
33050 |
-+ |
33051 |
-+ /* |
33052 |
-+ * Unprivileged connection running under the same |
33053 |
-+ * user. It should succeed. |
33054 |
-+ */ |
33055 |
-+ ret = kdbus_msg_recv_poll(unpriv_a, 300, &msg, NULL); |
33056 |
-+ ASSERT_EXIT(ret == 0 && msg->cookie == expected_cookie); |
33057 |
-+ |
33058 |
-+ /* |
33059 |
-+ * Did not install matches, not interested in |
33060 |
-+ * broadcasts |
33061 |
-+ */ |
33062 |
-+ ret = kdbus_msg_recv_poll(unpriv_b, 300, NULL, NULL); |
33063 |
-+ ASSERT_EXIT(ret == -ETIMEDOUT); |
33064 |
-+ }), |
33065 |
-+ ({ |
33066 |
-+ ret = eventfd_read(efd, &event_status); |
33067 |
-+ ASSERT_RETURN(ret >= 0 && event_status == 1); |
33068 |
-+ |
33069 |
-+ /* |
33070 |
-+ * owner_a must fail with -ETIMEDOUT, since it owns |
33071 |
-+ * name "com.example.broadcastA" and its TALK |
33072 |
-+ * access is restriced. |
33073 |
-+ */ |
33074 |
-+ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33075 |
-+ ASSERT_RETURN(ret == 0); |
33076 |
-+ |
33077 |
-+ /* confirm the received cookie */ |
33078 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33079 |
-+ |
33080 |
-+ kdbus_msg_free(msg); |
33081 |
-+ |
33082 |
-+ /* |
33083 |
-+ * owner_b got the broadcast from an unprivileged |
33084 |
-+ * connection. |
33085 |
-+ */ |
33086 |
-+ ret = kdbus_msg_recv_poll(owner_b, 300, &msg, NULL); |
33087 |
-+ ASSERT_RETURN(ret == 0); |
33088 |
-+ |
33089 |
-+ /* confirm the received cookie */ |
33090 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33091 |
-+ |
33092 |
-+ kdbus_msg_free(msg); |
33093 |
-+ |
33094 |
-+ })); |
33095 |
-+ ASSERT_RETURN(ret == 0); |
33096 |
-+ |
33097 |
-+ close(efd); |
33098 |
-+ |
33099 |
-+ /* |
33100 |
-+ * Test broadcast with two unprivileged connections running |
33101 |
-+ * under different users. |
33102 |
-+ * |
33103 |
-+ * Both connections will fail with -ETIMEDOUT. |
33104 |
-+ */ |
33105 |
-+ |
33106 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, NULL, |
33107 |
-+ DROP_OTHER_UNPRIV, |
33108 |
-+ -ETIMEDOUT, -ETIMEDOUT); |
33109 |
-+ ASSERT_RETURN(ret == 0); |
33110 |
-+ |
33111 |
-+ /* Drop received broadcasts by privileged */ |
33112 |
-+ ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL); |
33113 |
-+ ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL); |
33114 |
-+ ASSERT_RETURN(ret == 0); |
33115 |
-+ |
33116 |
-+ ret = kdbus_msg_recv(owner_a, NULL, NULL); |
33117 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
33118 |
-+ |
33119 |
-+ ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL); |
33120 |
-+ ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL); |
33121 |
-+ ASSERT_RETURN(ret == 0); |
33122 |
-+ |
33123 |
-+ ret = kdbus_msg_recv(owner_b, NULL, NULL); |
33124 |
-+ ASSERT_RETURN(ret == -EAGAIN); |
33125 |
-+ |
33126 |
-+ /* |
33127 |
-+ * Perform last tests, allow others to talk to name |
33128 |
-+ * "com.example.broadcastA". So now receiving broadcasts |
33129 |
-+ * from it should succeed since the TALK policy allow it. |
33130 |
-+ */ |
33131 |
-+ |
33132 |
-+ /* KDBUS_POLICY_OWN for unprivileged connections */ |
33133 |
-+ access = (struct kdbus_policy_access){ |
33134 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33135 |
-+ .id = geteuid(), |
33136 |
-+ .access = KDBUS_POLICY_TALK, |
33137 |
-+ }; |
33138 |
-+ |
33139 |
-+ ret = kdbus_conn_update_policy(holder_a, |
33140 |
-+ "com.example.broadcastA", |
33141 |
-+ &access, 1); |
33142 |
-+ ASSERT_RETURN(ret == 0); |
33143 |
-+ |
33144 |
-+ /* |
33145 |
-+ * Unprivileged is able to TALK to "com.example.broadcastA" |
33146 |
-+ * now so it will receive its broadcasts |
33147 |
-+ */ |
33148 |
-+ ret = test_policy_priv_by_broadcast(env->buspath, owner_a, |
33149 |
-+ DO_NOT_DROP, 0, 0); |
33150 |
-+ ASSERT_RETURN(ret == 0); |
33151 |
-+ |
33152 |
-+ ++expected_cookie; |
33153 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33154 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.broadcastB", |
33155 |
-+ NULL); |
33156 |
-+ ASSERT_EXIT(ret >= 0); |
33157 |
-+ ret = kdbus_msg_send(unpriv, NULL, expected_cookie, |
33158 |
-+ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
33159 |
-+ ASSERT_EXIT(ret == 0); |
33160 |
-+ })); |
33161 |
-+ ASSERT_RETURN(ret == 0); |
33162 |
-+ |
33163 |
-+ /* owner_a is privileged it will get the broadcast now. */ |
33164 |
-+ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33165 |
-+ ASSERT_RETURN(ret == 0); |
33166 |
-+ |
33167 |
-+ /* confirm the received cookie */ |
33168 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33169 |
-+ |
33170 |
-+ kdbus_msg_free(msg); |
33171 |
-+ |
33172 |
-+ /* |
33173 |
-+ * owner_a released name "com.example.broadcastA". It should |
33174 |
-+ * receive broadcasts since it is still privileged and has |
33175 |
-+ * the right match. |
33176 |
-+ * |
33177 |
-+ * Unprivileged connection will own a name and will try to |
33178 |
-+ * signal to the privileged connection. |
33179 |
-+ */ |
33180 |
-+ |
33181 |
-+ ret = kdbus_name_release(owner_a, "com.example.broadcastA"); |
33182 |
-+ ASSERT_EXIT(ret >= 0); |
33183 |
-+ |
33184 |
-+ ++expected_cookie; |
33185 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33186 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.broadcastB", |
33187 |
-+ NULL); |
33188 |
-+ ASSERT_EXIT(ret >= 0); |
33189 |
-+ ret = kdbus_msg_send(unpriv, NULL, expected_cookie, |
33190 |
-+ 0, 0, 0, KDBUS_DST_ID_BROADCAST); |
33191 |
-+ ASSERT_EXIT(ret == 0); |
33192 |
-+ })); |
33193 |
-+ ASSERT_RETURN(ret == 0); |
33194 |
-+ |
33195 |
-+ /* owner_a will get the broadcast now. */ |
33196 |
-+ ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL); |
33197 |
-+ ASSERT_RETURN(ret == 0); |
33198 |
-+ |
33199 |
-+ /* confirm the received cookie */ |
33200 |
-+ ASSERT_RETURN(msg->cookie == expected_cookie); |
33201 |
-+ |
33202 |
-+ kdbus_msg_free(msg); |
33203 |
-+ |
33204 |
-+ kdbus_conn_free(owner_a); |
33205 |
-+ kdbus_conn_free(owner_b); |
33206 |
-+ kdbus_conn_free(holder_a); |
33207 |
-+ kdbus_conn_free(holder_b); |
33208 |
-+ |
33209 |
-+ return 0; |
33210 |
-+} |
33211 |
-+ |
33212 |
-+static int test_policy_priv(struct kdbus_test_env *env) |
33213 |
-+{ |
33214 |
-+ struct kdbus_conn *conn_a, *conn_b, *conn, *owner; |
33215 |
-+ struct kdbus_policy_access access, *acc; |
33216 |
-+ sigset_t sset; |
33217 |
-+ size_t num; |
33218 |
-+ int ret; |
33219 |
-+ |
33220 |
-+ /* |
33221 |
-+ * Make sure we have CAP_SETUID/SETGID so we can drop privileges |
33222 |
-+ */ |
33223 |
-+ |
33224 |
-+ ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); |
33225 |
-+ ASSERT_RETURN(ret >= 0); |
33226 |
-+ |
33227 |
-+ if (!ret) |
33228 |
-+ return TEST_SKIP; |
33229 |
-+ |
33230 |
-+ /* make sure that uids and gids are mapped */ |
33231 |
-+ if (!all_uids_gids_are_mapped()) |
33232 |
-+ return TEST_SKIP; |
33233 |
-+ |
33234 |
-+ /* |
33235 |
-+ * Setup: |
33236 |
-+ * conn_a: policy holder for com.example.a |
33237 |
-+ * conn_b: name holder of com.example.b |
33238 |
-+ */ |
33239 |
-+ |
33240 |
-+ signal(SIGUSR1, nosig); |
33241 |
-+ sigemptyset(&sset); |
33242 |
-+ sigaddset(&sset, SIGUSR1); |
33243 |
-+ sigprocmask(SIG_BLOCK, &sset, NULL); |
33244 |
-+ |
33245 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33246 |
-+ ASSERT_RETURN(conn); |
33247 |
-+ |
33248 |
-+ /* |
33249 |
-+ * Before registering any policy holder, make sure that the |
33250 |
-+ * bus is secure by default. This test is necessary, it catches |
33251 |
-+ * several cases where old D-Bus was vulnerable. |
33252 |
-+ */ |
33253 |
-+ |
33254 |
-+ ret = test_priv_before_policy_upload(env); |
33255 |
-+ ASSERT_RETURN(ret == 0); |
33256 |
-+ |
33257 |
-+ /* |
33258 |
-+ * Make sure unprivileged are not able to register policy |
33259 |
-+ * holders |
33260 |
-+ */ |
33261 |
-+ |
33262 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
33263 |
-+ struct kdbus_conn *holder; |
33264 |
-+ |
33265 |
-+ holder = kdbus_hello_registrar(env->buspath, |
33266 |
-+ "com.example.a", NULL, 0, |
33267 |
-+ KDBUS_HELLO_POLICY_HOLDER); |
33268 |
-+ ASSERT_EXIT(holder == NULL && errno == EPERM); |
33269 |
-+ }), |
33270 |
-+ ({ 0; })); |
33271 |
-+ ASSERT_RETURN(ret == 0); |
33272 |
-+ |
33273 |
-+ |
33274 |
-+ /* Register policy holder */ |
33275 |
-+ |
33276 |
-+ conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", |
33277 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33278 |
-+ ASSERT_RETURN(conn_a); |
33279 |
-+ |
33280 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
33281 |
-+ ASSERT_RETURN(conn_b); |
33282 |
-+ |
33283 |
-+ ret = kdbus_name_acquire(conn_b, "com.example.b", NULL); |
33284 |
-+ ASSERT_EXIT(ret >= 0); |
33285 |
-+ |
33286 |
-+ /* |
33287 |
-+ * Make sure bus-owners can always acquire names. |
33288 |
-+ */ |
33289 |
-+ ret = kdbus_name_acquire(conn, "com.example.a", NULL); |
33290 |
-+ ASSERT_EXIT(ret >= 0); |
33291 |
-+ |
33292 |
-+ kdbus_conn_free(conn); |
33293 |
-+ |
33294 |
-+ /* |
33295 |
-+ * Make sure unprivileged users cannot acquire names with default |
33296 |
-+ * policy assigned. |
33297 |
-+ */ |
33298 |
-+ |
33299 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33300 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33301 |
-+ ASSERT_EXIT(ret < 0); |
33302 |
-+ })); |
33303 |
-+ ASSERT_RETURN(ret >= 0); |
33304 |
-+ |
33305 |
-+ /* |
33306 |
-+ * Make sure unprivileged users can acquire names if we make them |
33307 |
-+ * world-accessible. |
33308 |
-+ */ |
33309 |
-+ |
33310 |
-+ access = (struct kdbus_policy_access){ |
33311 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33312 |
-+ .id = 0, |
33313 |
-+ .access = KDBUS_POLICY_OWN, |
33314 |
-+ }; |
33315 |
-+ |
33316 |
-+ /* |
33317 |
-+ * Make sure unprivileged/normal connections are not able |
33318 |
-+ * to update policies |
33319 |
-+ */ |
33320 |
-+ |
33321 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33322 |
-+ ret = kdbus_conn_update_policy(unpriv, "com.example.a", |
33323 |
-+ &access, 1); |
33324 |
-+ ASSERT_EXIT(ret == -EOPNOTSUPP); |
33325 |
-+ })); |
33326 |
-+ ASSERT_RETURN(ret == 0); |
33327 |
-+ |
33328 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33329 |
-+ ASSERT_RETURN(ret == 0); |
33330 |
-+ |
33331 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33332 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33333 |
-+ ASSERT_EXIT(ret >= 0); |
33334 |
-+ })); |
33335 |
-+ ASSERT_RETURN(ret >= 0); |
33336 |
-+ |
33337 |
-+ /* |
33338 |
-+ * Make sure unprivileged users can acquire names if we make them |
33339 |
-+ * gid-accessible. But only if the gid matches. |
33340 |
-+ */ |
33341 |
-+ |
33342 |
-+ access = (struct kdbus_policy_access){ |
33343 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33344 |
-+ .id = UNPRIV_GID, |
33345 |
-+ .access = KDBUS_POLICY_OWN, |
33346 |
-+ }; |
33347 |
-+ |
33348 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33349 |
-+ ASSERT_RETURN(ret == 0); |
33350 |
-+ |
33351 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33352 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33353 |
-+ ASSERT_EXIT(ret >= 0); |
33354 |
-+ })); |
33355 |
-+ ASSERT_RETURN(ret >= 0); |
33356 |
-+ |
33357 |
-+ access = (struct kdbus_policy_access){ |
33358 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33359 |
-+ .id = 1, |
33360 |
-+ .access = KDBUS_POLICY_OWN, |
33361 |
-+ }; |
33362 |
-+ |
33363 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33364 |
-+ ASSERT_RETURN(ret == 0); |
33365 |
-+ |
33366 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33367 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33368 |
-+ ASSERT_EXIT(ret < 0); |
33369 |
-+ })); |
33370 |
-+ ASSERT_RETURN(ret >= 0); |
33371 |
-+ |
33372 |
-+ /* |
33373 |
-+ * Make sure unprivileged users can acquire names if we make them |
33374 |
-+ * uid-accessible. But only if the uid matches. |
33375 |
-+ */ |
33376 |
-+ |
33377 |
-+ access = (struct kdbus_policy_access){ |
33378 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33379 |
-+ .id = UNPRIV_UID, |
33380 |
-+ .access = KDBUS_POLICY_OWN, |
33381 |
-+ }; |
33382 |
-+ |
33383 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33384 |
-+ ASSERT_RETURN(ret == 0); |
33385 |
-+ |
33386 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33387 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33388 |
-+ ASSERT_EXIT(ret >= 0); |
33389 |
-+ })); |
33390 |
-+ ASSERT_RETURN(ret >= 0); |
33391 |
-+ |
33392 |
-+ access = (struct kdbus_policy_access){ |
33393 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33394 |
-+ .id = 1, |
33395 |
-+ .access = KDBUS_POLICY_OWN, |
33396 |
-+ }; |
33397 |
-+ |
33398 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33399 |
-+ ASSERT_RETURN(ret == 0); |
33400 |
-+ |
33401 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33402 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33403 |
-+ ASSERT_EXIT(ret < 0); |
33404 |
-+ })); |
33405 |
-+ ASSERT_RETURN(ret >= 0); |
33406 |
-+ |
33407 |
-+ /* |
33408 |
-+ * Make sure unprivileged users cannot acquire names if no owner-policy |
33409 |
-+ * matches, even if SEE/TALK policies match. |
33410 |
-+ */ |
33411 |
-+ |
33412 |
-+ num = 4; |
33413 |
-+ acc = (struct kdbus_policy_access[]){ |
33414 |
-+ { |
33415 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33416 |
-+ .id = UNPRIV_GID, |
33417 |
-+ .access = KDBUS_POLICY_SEE, |
33418 |
-+ }, |
33419 |
-+ { |
33420 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33421 |
-+ .id = UNPRIV_UID, |
33422 |
-+ .access = KDBUS_POLICY_TALK, |
33423 |
-+ }, |
33424 |
-+ { |
33425 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33426 |
-+ .id = 0, |
33427 |
-+ .access = KDBUS_POLICY_TALK, |
33428 |
-+ }, |
33429 |
-+ { |
33430 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33431 |
-+ .id = 0, |
33432 |
-+ .access = KDBUS_POLICY_SEE, |
33433 |
-+ }, |
33434 |
-+ }; |
33435 |
-+ |
33436 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num); |
33437 |
-+ ASSERT_RETURN(ret == 0); |
33438 |
-+ |
33439 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33440 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33441 |
-+ ASSERT_EXIT(ret < 0); |
33442 |
-+ })); |
33443 |
-+ ASSERT_RETURN(ret >= 0); |
33444 |
-+ |
33445 |
-+ /* |
33446 |
-+ * Make sure unprivileged users can acquire names if the only matching |
33447 |
-+ * policy is somewhere in the middle. |
33448 |
-+ */ |
33449 |
-+ |
33450 |
-+ num = 5; |
33451 |
-+ acc = (struct kdbus_policy_access[]){ |
33452 |
-+ { |
33453 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33454 |
-+ .id = 1, |
33455 |
-+ .access = KDBUS_POLICY_OWN, |
33456 |
-+ }, |
33457 |
-+ { |
33458 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33459 |
-+ .id = 2, |
33460 |
-+ .access = KDBUS_POLICY_OWN, |
33461 |
-+ }, |
33462 |
-+ { |
33463 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33464 |
-+ .id = UNPRIV_UID, |
33465 |
-+ .access = KDBUS_POLICY_OWN, |
33466 |
-+ }, |
33467 |
-+ { |
33468 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33469 |
-+ .id = 3, |
33470 |
-+ .access = KDBUS_POLICY_OWN, |
33471 |
-+ }, |
33472 |
-+ { |
33473 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33474 |
-+ .id = 4, |
33475 |
-+ .access = KDBUS_POLICY_OWN, |
33476 |
-+ }, |
33477 |
-+ }; |
33478 |
-+ |
33479 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num); |
33480 |
-+ ASSERT_RETURN(ret == 0); |
33481 |
-+ |
33482 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33483 |
-+ ret = kdbus_name_acquire(unpriv, "com.example.a", NULL); |
33484 |
-+ ASSERT_EXIT(ret >= 0); |
33485 |
-+ })); |
33486 |
-+ ASSERT_RETURN(ret >= 0); |
33487 |
-+ |
33488 |
-+ /* |
33489 |
-+ * Clear policies |
33490 |
-+ */ |
33491 |
-+ |
33492 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", NULL, 0); |
33493 |
-+ ASSERT_RETURN(ret == 0); |
33494 |
-+ |
33495 |
-+ /* |
33496 |
-+ * Make sure privileged bus users can _always_ talk to others. |
33497 |
-+ */ |
33498 |
-+ |
33499 |
-+ conn = kdbus_hello(env->buspath, 0, NULL, 0); |
33500 |
-+ ASSERT_RETURN(conn); |
33501 |
-+ |
33502 |
-+ ret = kdbus_msg_send(conn, "com.example.b", 0xdeadbeef, 0, 0, 0, 0); |
33503 |
-+ ASSERT_EXIT(ret >= 0); |
33504 |
-+ |
33505 |
-+ ret = kdbus_msg_recv_poll(conn_b, 300, NULL, NULL); |
33506 |
-+ ASSERT_EXIT(ret >= 0); |
33507 |
-+ |
33508 |
-+ kdbus_conn_free(conn); |
33509 |
-+ |
33510 |
-+ /* |
33511 |
-+ * Make sure unprivileged bus users cannot talk by default. |
33512 |
-+ */ |
33513 |
-+ |
33514 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33515 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33516 |
-+ 0, 0); |
33517 |
-+ ASSERT_EXIT(ret == -EPERM); |
33518 |
-+ })); |
33519 |
-+ ASSERT_RETURN(ret >= 0); |
33520 |
-+ |
33521 |
-+ /* |
33522 |
-+ * Make sure unprivileged bus users can talk to equals, even without |
33523 |
-+ * policy. |
33524 |
-+ */ |
33525 |
-+ |
33526 |
-+ access = (struct kdbus_policy_access){ |
33527 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33528 |
-+ .id = UNPRIV_UID, |
33529 |
-+ .access = KDBUS_POLICY_OWN, |
33530 |
-+ }; |
33531 |
-+ |
33532 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.c", &access, 1); |
33533 |
-+ ASSERT_RETURN(ret == 0); |
33534 |
-+ |
33535 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33536 |
-+ struct kdbus_conn *owner; |
33537 |
-+ |
33538 |
-+ owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33539 |
-+ ASSERT_RETURN(owner); |
33540 |
-+ |
33541 |
-+ ret = kdbus_name_acquire(owner, "com.example.c", NULL); |
33542 |
-+ ASSERT_EXIT(ret >= 0); |
33543 |
-+ |
33544 |
-+ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33545 |
-+ 0, 0); |
33546 |
-+ ASSERT_EXIT(ret >= 0); |
33547 |
-+ ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL); |
33548 |
-+ ASSERT_EXIT(ret >= 0); |
33549 |
-+ |
33550 |
-+ kdbus_conn_free(owner); |
33551 |
-+ })); |
33552 |
-+ ASSERT_RETURN(ret >= 0); |
33553 |
-+ |
33554 |
-+ /* |
33555 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33556 |
-+ * suitable UID policy is set. |
33557 |
-+ */ |
33558 |
-+ |
33559 |
-+ access = (struct kdbus_policy_access){ |
33560 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33561 |
-+ .id = UNPRIV_UID, |
33562 |
-+ .access = KDBUS_POLICY_TALK, |
33563 |
-+ }; |
33564 |
-+ |
33565 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33566 |
-+ ASSERT_RETURN(ret == 0); |
33567 |
-+ |
33568 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33569 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33570 |
-+ 0, 0); |
33571 |
-+ ASSERT_EXIT(ret >= 0); |
33572 |
-+ })); |
33573 |
-+ ASSERT_RETURN(ret >= 0); |
33574 |
-+ |
33575 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33576 |
-+ ASSERT_EXIT(ret >= 0); |
33577 |
-+ |
33578 |
-+ /* |
33579 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33580 |
-+ * suitable GID policy is set. |
33581 |
-+ */ |
33582 |
-+ |
33583 |
-+ access = (struct kdbus_policy_access){ |
33584 |
-+ .type = KDBUS_POLICY_ACCESS_GROUP, |
33585 |
-+ .id = UNPRIV_GID, |
33586 |
-+ .access = KDBUS_POLICY_TALK, |
33587 |
-+ }; |
33588 |
-+ |
33589 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33590 |
-+ ASSERT_RETURN(ret == 0); |
33591 |
-+ |
33592 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33593 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33594 |
-+ 0, 0); |
33595 |
-+ ASSERT_EXIT(ret >= 0); |
33596 |
-+ })); |
33597 |
-+ ASSERT_RETURN(ret >= 0); |
33598 |
-+ |
33599 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33600 |
-+ ASSERT_EXIT(ret >= 0); |
33601 |
-+ |
33602 |
-+ /* |
33603 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33604 |
-+ * suitable WORLD policy is set. |
33605 |
-+ */ |
33606 |
-+ |
33607 |
-+ access = (struct kdbus_policy_access){ |
33608 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33609 |
-+ .id = 0, |
33610 |
-+ .access = KDBUS_POLICY_TALK, |
33611 |
-+ }; |
33612 |
-+ |
33613 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33614 |
-+ ASSERT_RETURN(ret == 0); |
33615 |
-+ |
33616 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33617 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33618 |
-+ 0, 0); |
33619 |
-+ ASSERT_EXIT(ret >= 0); |
33620 |
-+ })); |
33621 |
-+ ASSERT_RETURN(ret >= 0); |
33622 |
-+ |
33623 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33624 |
-+ ASSERT_EXIT(ret >= 0); |
33625 |
-+ |
33626 |
-+ /* |
33627 |
-+ * Make sure unprivileged bus users cannot talk to privileged users if |
33628 |
-+ * no suitable policy is set. |
33629 |
-+ */ |
33630 |
-+ |
33631 |
-+ num = 5; |
33632 |
-+ acc = (struct kdbus_policy_access[]){ |
33633 |
-+ { |
33634 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33635 |
-+ .id = 0, |
33636 |
-+ .access = KDBUS_POLICY_OWN, |
33637 |
-+ }, |
33638 |
-+ { |
33639 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33640 |
-+ .id = 1, |
33641 |
-+ .access = KDBUS_POLICY_TALK, |
33642 |
-+ }, |
33643 |
-+ { |
33644 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33645 |
-+ .id = UNPRIV_UID, |
33646 |
-+ .access = KDBUS_POLICY_SEE, |
33647 |
-+ }, |
33648 |
-+ { |
33649 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33650 |
-+ .id = 3, |
33651 |
-+ .access = KDBUS_POLICY_TALK, |
33652 |
-+ }, |
33653 |
-+ { |
33654 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33655 |
-+ .id = 4, |
33656 |
-+ .access = KDBUS_POLICY_TALK, |
33657 |
-+ }, |
33658 |
-+ }; |
33659 |
-+ |
33660 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", acc, num); |
33661 |
-+ ASSERT_RETURN(ret == 0); |
33662 |
-+ |
33663 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33664 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33665 |
-+ 0, 0); |
33666 |
-+ ASSERT_EXIT(ret == -EPERM); |
33667 |
-+ })); |
33668 |
-+ ASSERT_RETURN(ret >= 0); |
33669 |
-+ |
33670 |
-+ /* |
33671 |
-+ * Make sure unprivileged bus users can talk to privileged users if a |
33672 |
-+ * suitable OWN privilege overwrites TALK. |
33673 |
-+ */ |
33674 |
-+ |
33675 |
-+ access = (struct kdbus_policy_access){ |
33676 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33677 |
-+ .id = 0, |
33678 |
-+ .access = KDBUS_POLICY_OWN, |
33679 |
-+ }; |
33680 |
-+ |
33681 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33682 |
-+ ASSERT_RETURN(ret == 0); |
33683 |
-+ |
33684 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33685 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33686 |
-+ 0, 0); |
33687 |
-+ ASSERT_EXIT(ret >= 0); |
33688 |
-+ })); |
33689 |
-+ ASSERT_RETURN(ret >= 0); |
33690 |
-+ |
33691 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33692 |
-+ ASSERT_EXIT(ret >= 0); |
33693 |
-+ |
33694 |
-+ /* |
33695 |
-+ * Make sure the TALK cache is reset correctly when policies are |
33696 |
-+ * updated. |
33697 |
-+ */ |
33698 |
-+ |
33699 |
-+ access = (struct kdbus_policy_access){ |
33700 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33701 |
-+ .id = 0, |
33702 |
-+ .access = KDBUS_POLICY_TALK, |
33703 |
-+ }; |
33704 |
-+ |
33705 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1); |
33706 |
-+ ASSERT_RETURN(ret == 0); |
33707 |
-+ |
33708 |
-+ ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ |
33709 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33710 |
-+ 0, 0); |
33711 |
-+ ASSERT_EXIT(ret >= 0); |
33712 |
-+ |
33713 |
-+ ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL); |
33714 |
-+ ASSERT_EXIT(ret >= 0); |
33715 |
-+ |
33716 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.b", |
33717 |
-+ NULL, 0); |
33718 |
-+ ASSERT_RETURN(ret == 0); |
33719 |
-+ |
33720 |
-+ ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0, |
33721 |
-+ 0, 0); |
33722 |
-+ ASSERT_EXIT(ret == -EPERM); |
33723 |
-+ })); |
33724 |
-+ ASSERT_RETURN(ret >= 0); |
33725 |
-+ |
33726 |
-+ /* |
33727 |
-+ * Make sure the TALK cache is reset correctly when policy holders |
33728 |
-+ * disconnect. |
33729 |
-+ */ |
33730 |
-+ |
33731 |
-+ access = (struct kdbus_policy_access){ |
33732 |
-+ .type = KDBUS_POLICY_ACCESS_WORLD, |
33733 |
-+ .id = 0, |
33734 |
-+ .access = KDBUS_POLICY_OWN, |
33735 |
-+ }; |
33736 |
-+ |
33737 |
-+ conn = kdbus_hello_registrar(env->buspath, "com.example.c", |
33738 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33739 |
-+ ASSERT_RETURN(conn); |
33740 |
-+ |
33741 |
-+ ret = kdbus_conn_update_policy(conn, "com.example.c", &access, 1); |
33742 |
-+ ASSERT_RETURN(ret == 0); |
33743 |
-+ |
33744 |
-+ owner = kdbus_hello(env->buspath, 0, NULL, 0); |
33745 |
-+ ASSERT_RETURN(owner); |
33746 |
-+ |
33747 |
-+ ret = kdbus_name_acquire(owner, "com.example.c", NULL); |
33748 |
-+ ASSERT_RETURN(ret >= 0); |
33749 |
-+ |
33750 |
-+ ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ |
33751 |
-+ struct kdbus_conn *unpriv; |
33752 |
-+ |
33753 |
-+ /* wait for parent to be finished */ |
33754 |
-+ sigemptyset(&sset); |
33755 |
-+ ret = sigsuspend(&sset); |
33756 |
-+ ASSERT_RETURN(ret == -1 && errno == EINTR); |
33757 |
-+ |
33758 |
-+ unpriv = kdbus_hello(env->buspath, 0, NULL, 0); |
33759 |
-+ ASSERT_RETURN(unpriv); |
33760 |
-+ |
33761 |
-+ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33762 |
-+ 0, 0); |
33763 |
-+ ASSERT_EXIT(ret >= 0); |
33764 |
-+ |
33765 |
-+ ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL); |
33766 |
-+ ASSERT_EXIT(ret >= 0); |
33767 |
-+ |
33768 |
-+ /* free policy holder */ |
33769 |
-+ kdbus_conn_free(conn); |
33770 |
-+ |
33771 |
-+ ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0, |
33772 |
-+ 0, 0); |
33773 |
-+ ASSERT_EXIT(ret == -EPERM); |
33774 |
-+ |
33775 |
-+ kdbus_conn_free(unpriv); |
33776 |
-+ }), ({ |
33777 |
-+ /* make sure policy holder is only valid in child */ |
33778 |
-+ kdbus_conn_free(conn); |
33779 |
-+ kill(pid, SIGUSR1); |
33780 |
-+ })); |
33781 |
-+ ASSERT_RETURN(ret >= 0); |
33782 |
-+ |
33783 |
-+ |
33784 |
-+ /* |
33785 |
-+ * The following tests are necessary. |
33786 |
-+ */ |
33787 |
-+ |
33788 |
-+ ret = test_broadcast_after_policy_upload(env); |
33789 |
-+ ASSERT_RETURN(ret == 0); |
33790 |
-+ |
33791 |
-+ kdbus_conn_free(owner); |
33792 |
-+ |
33793 |
-+ /* |
33794 |
-+ * cleanup resources |
33795 |
-+ */ |
33796 |
-+ |
33797 |
-+ kdbus_conn_free(conn_b); |
33798 |
-+ kdbus_conn_free(conn_a); |
33799 |
-+ |
33800 |
-+ return TEST_OK; |
33801 |
-+} |
33802 |
-+ |
33803 |
-+int kdbus_test_policy_priv(struct kdbus_test_env *env) |
33804 |
-+{ |
33805 |
-+ pid_t pid; |
33806 |
-+ int ret; |
33807 |
-+ |
33808 |
-+ /* make sure to exit() if a child returns from fork() */ |
33809 |
-+ pid = getpid(); |
33810 |
-+ ret = test_policy_priv(env); |
33811 |
-+ if (pid != getpid()) |
33812 |
-+ exit(1); |
33813 |
-+ |
33814 |
-+ return ret; |
33815 |
-+} |
33816 |
-diff --git a/tools/testing/selftests/kdbus/test-policy.c b/tools/testing/selftests/kdbus/test-policy.c |
33817 |
-new file mode 100644 |
33818 |
-index 0000000..96d20d5 |
33819 |
---- /dev/null |
33820 |
-+++ b/tools/testing/selftests/kdbus/test-policy.c |
33821 |
-@@ -0,0 +1,80 @@ |
33822 |
-+#include <errno.h> |
33823 |
-+#include <stdio.h> |
33824 |
-+#include <string.h> |
33825 |
-+#include <fcntl.h> |
33826 |
-+#include <stdlib.h> |
33827 |
-+#include <stdint.h> |
33828 |
-+#include <stdbool.h> |
33829 |
-+#include <unistd.h> |
33830 |
-+ |
33831 |
-+#include "kdbus-test.h" |
33832 |
-+#include "kdbus-util.h" |
33833 |
-+#include "kdbus-enum.h" |
33834 |
-+ |
33835 |
-+int kdbus_test_policy(struct kdbus_test_env *env) |
33836 |
-+{ |
33837 |
-+ struct kdbus_conn *conn_a, *conn_b; |
33838 |
-+ struct kdbus_policy_access access; |
33839 |
-+ int ret; |
33840 |
-+ |
33841 |
-+ /* Invalid name */ |
33842 |
-+ conn_a = kdbus_hello_registrar(env->buspath, ".example.a", |
33843 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33844 |
-+ ASSERT_RETURN(conn_a == NULL); |
33845 |
-+ |
33846 |
-+ conn_a = kdbus_hello_registrar(env->buspath, "example", |
33847 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33848 |
-+ ASSERT_RETURN(conn_a == NULL); |
33849 |
-+ |
33850 |
-+ conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", |
33851 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33852 |
-+ ASSERT_RETURN(conn_a); |
33853 |
-+ |
33854 |
-+ conn_b = kdbus_hello_registrar(env->buspath, "com.example.b", |
33855 |
-+ NULL, 0, KDBUS_HELLO_POLICY_HOLDER); |
33856 |
-+ ASSERT_RETURN(conn_b); |
33857 |
-+ |
33858 |
-+ /* |
33859 |
-+ * Verify there cannot be any duplicate entries, except for specific vs. |
33860 |
-+ * wildcard entries. |
33861 |
-+ */ |
33862 |
-+ |
33863 |
-+ access = (struct kdbus_policy_access){ |
33864 |
-+ .type = KDBUS_POLICY_ACCESS_USER, |
33865 |
-+ .id = geteuid(), |
33866 |
-+ .access = KDBUS_POLICY_SEE, |
33867 |
-+ }; |
33868 |
-+ |
33869 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); |
33870 |
-+ ASSERT_RETURN(ret == 0); |
33871 |
-+ |
33872 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); |
33873 |
-+ ASSERT_RETURN(ret == -EEXIST); |
33874 |
-+ |
33875 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.a.*", &access, 1); |
33876 |
-+ ASSERT_RETURN(ret == 0); |
33877 |
-+ |
33878 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.a.*", &access, 1); |
33879 |
-+ ASSERT_RETURN(ret == -EEXIST); |
33880 |
-+ |
33881 |
-+ ret = kdbus_conn_update_policy(conn_a, "com.example.*", &access, 1); |
33882 |
-+ ASSERT_RETURN(ret == 0); |
33883 |
-+ |
33884 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); |
33885 |
-+ ASSERT_RETURN(ret == 0); |
33886 |
-+ |
33887 |
-+ ret = kdbus_conn_update_policy(conn_b, "com.example.*", &access, 1); |
33888 |
-+ ASSERT_RETURN(ret == -EEXIST); |
33889 |
-+ |
33890 |
-+ /* Invalid name */ |
33891 |
-+ ret = kdbus_conn_update_policy(conn_b, ".example.*", &access, 1); |
33892 |
-+ ASSERT_RETURN(ret == -EINVAL); |
33893 |
-+ |
33894 |
-+ ret = kdbus_conn_update_policy(conn_b, "example", &access, 1); |
33895 |
-+ ASSERT_RETURN(ret == -EINVAL); |
33896 |
-+ |
33897 |
-+ kdbus_conn_free(conn_b); |
33898 |
-+ kdbus_conn_free(conn_a); |
33899 |
-+ |
33900 |
-+ return TEST_OK; |
33901 |
-+} |
33902 |
-diff --git a/tools/testing/selftests/kdbus/test-sync.c b/tools/testing/selftests/kdbus/test-sync.c |
33903 |
-new file mode 100644 |
33904 |
-index 0000000..0655a54 |
33905 |
---- /dev/null |
33906 |
-+++ b/tools/testing/selftests/kdbus/test-sync.c |
33907 |
-@@ -0,0 +1,369 @@ |
33908 |
-+#include <stdio.h> |
33909 |
-+#include <string.h> |
33910 |
-+#include <time.h> |
33911 |
-+#include <fcntl.h> |
33912 |
-+#include <stdlib.h> |
33913 |
-+#include <stddef.h> |
33914 |
-+#include <unistd.h> |
33915 |
-+#include <stdint.h> |
33916 |
-+#include <errno.h> |
33917 |
-+#include <assert.h> |
33918 |
-+#include <pthread.h> |
33919 |
-+#include <stdbool.h> |
33920 |
-+#include <signal.h> |
33921 |
-+#include <sys/wait.h> |
33922 |
-+#include <sys/eventfd.h> |
33923 |
-+ |
33924 |
-+#include "kdbus-api.h" |
33925 |
-+#include "kdbus-test.h" |
33926 |
-+#include "kdbus-util.h" |
33927 |
-+#include "kdbus-enum.h" |
33928 |
-+ |
33929 |
-+static struct kdbus_conn *conn_a, *conn_b; |
33930 |
-+static unsigned int cookie = 0xdeadbeef; |
33931 |
-+ |
33932 |
-+static void nop_handler(int sig) {} |
33933 |
-+ |
33934 |
-+static int interrupt_sync(struct kdbus_conn *conn_src, |
33935 |
-+ struct kdbus_conn *conn_dst) |
33936 |
-+{ |
33937 |
-+ pid_t pid; |
33938 |
-+ int ret, status; |
33939 |
-+ struct kdbus_msg *msg = NULL; |
33940 |
-+ struct sigaction sa = { |
33941 |
-+ .sa_handler = nop_handler, |
33942 |
-+ .sa_flags = SA_NOCLDSTOP|SA_RESTART, |
33943 |
-+ }; |
33944 |
-+ |
33945 |
-+ cookie++; |
33946 |
-+ pid = fork(); |
33947 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
33948 |
-+ |
33949 |
-+ if (pid == 0) { |
33950 |
-+ ret = sigaction(SIGINT, &sa, NULL); |
33951 |
-+ ASSERT_EXIT(ret == 0); |
33952 |
-+ |
33953 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
33954 |
-+ KDBUS_MSG_EXPECT_REPLY, |
33955 |
-+ 100000000ULL, 0, conn_src->id, -1); |
33956 |
-+ ASSERT_EXIT(ret == -ETIMEDOUT); |
33957 |
-+ |
33958 |
-+ _exit(EXIT_SUCCESS); |
33959 |
-+ } |
33960 |
-+ |
33961 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
33962 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
33963 |
-+ |
33964 |
-+ kdbus_msg_free(msg); |
33965 |
-+ |
33966 |
-+ ret = kill(pid, SIGINT); |
33967 |
-+ ASSERT_RETURN_VAL(ret == 0, ret); |
33968 |
-+ |
33969 |
-+ ret = waitpid(pid, &status, 0); |
33970 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
33971 |
-+ |
33972 |
-+ if (WIFSIGNALED(status)) |
33973 |
-+ return TEST_ERR; |
33974 |
-+ |
33975 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); |
33976 |
-+ ASSERT_RETURN(ret == -ETIMEDOUT); |
33977 |
-+ |
33978 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
33979 |
-+} |
33980 |
-+ |
33981 |
-+static int close_epipe_sync(const char *bus) |
33982 |
-+{ |
33983 |
-+ pid_t pid; |
33984 |
-+ int ret, status; |
33985 |
-+ struct kdbus_conn *conn_src; |
33986 |
-+ struct kdbus_conn *conn_dst; |
33987 |
-+ struct kdbus_msg *msg = NULL; |
33988 |
-+ |
33989 |
-+ conn_src = kdbus_hello(bus, 0, NULL, 0); |
33990 |
-+ ASSERT_RETURN(conn_src); |
33991 |
-+ |
33992 |
-+ ret = kdbus_add_match_empty(conn_src); |
33993 |
-+ ASSERT_RETURN(ret == 0); |
33994 |
-+ |
33995 |
-+ conn_dst = kdbus_hello(bus, 0, NULL, 0); |
33996 |
-+ ASSERT_RETURN(conn_dst); |
33997 |
-+ |
33998 |
-+ cookie++; |
33999 |
-+ pid = fork(); |
34000 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
34001 |
-+ |
34002 |
-+ if (pid == 0) { |
34003 |
-+ uint64_t dst_id; |
34004 |
-+ |
34005 |
-+ /* close our reference */ |
34006 |
-+ dst_id = conn_dst->id; |
34007 |
-+ kdbus_conn_free(conn_dst); |
34008 |
-+ |
34009 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34010 |
-+ ASSERT_EXIT(ret == 0 && msg->cookie == cookie); |
34011 |
-+ ASSERT_EXIT(msg->src_id == dst_id); |
34012 |
-+ |
34013 |
-+ cookie++; |
34014 |
-+ ret = kdbus_msg_send_sync(conn_src, NULL, cookie, |
34015 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34016 |
-+ 100000000ULL, 0, dst_id, -1); |
34017 |
-+ ASSERT_EXIT(ret == -EPIPE); |
34018 |
-+ |
34019 |
-+ _exit(EXIT_SUCCESS); |
34020 |
-+ } |
34021 |
-+ |
34022 |
-+ ret = kdbus_msg_send(conn_dst, NULL, cookie, 0, 0, 0, |
34023 |
-+ KDBUS_DST_ID_BROADCAST); |
34024 |
-+ ASSERT_RETURN(ret == 0); |
34025 |
-+ |
34026 |
-+ cookie++; |
34027 |
-+ ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); |
34028 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34029 |
-+ |
34030 |
-+ kdbus_msg_free(msg); |
34031 |
-+ |
34032 |
-+ /* destroy connection */ |
34033 |
-+ kdbus_conn_free(conn_dst); |
34034 |
-+ kdbus_conn_free(conn_src); |
34035 |
-+ |
34036 |
-+ ret = waitpid(pid, &status, 0); |
34037 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34038 |
-+ |
34039 |
-+ if (!WIFEXITED(status)) |
34040 |
-+ return TEST_ERR; |
34041 |
-+ |
34042 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34043 |
-+} |
34044 |
-+ |
34045 |
-+static int cancel_fd_sync(struct kdbus_conn *conn_src, |
34046 |
-+ struct kdbus_conn *conn_dst) |
34047 |
-+{ |
34048 |
-+ pid_t pid; |
34049 |
-+ int cancel_fd; |
34050 |
-+ int ret, status; |
34051 |
-+ uint64_t counter = 1; |
34052 |
-+ struct kdbus_msg *msg = NULL; |
34053 |
-+ |
34054 |
-+ cancel_fd = eventfd(0, 0); |
34055 |
-+ ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); |
34056 |
-+ |
34057 |
-+ cookie++; |
34058 |
-+ pid = fork(); |
34059 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
34060 |
-+ |
34061 |
-+ if (pid == 0) { |
34062 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34063 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34064 |
-+ 100000000ULL, 0, conn_src->id, |
34065 |
-+ cancel_fd); |
34066 |
-+ ASSERT_EXIT(ret == -ECANCELED); |
34067 |
-+ |
34068 |
-+ _exit(EXIT_SUCCESS); |
34069 |
-+ } |
34070 |
-+ |
34071 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34072 |
-+ ASSERT_RETURN(ret == 0 && msg->cookie == cookie); |
34073 |
-+ |
34074 |
-+ kdbus_msg_free(msg); |
34075 |
-+ |
34076 |
-+ ret = write(cancel_fd, &counter, sizeof(counter)); |
34077 |
-+ ASSERT_RETURN(ret == sizeof(counter)); |
34078 |
-+ |
34079 |
-+ ret = waitpid(pid, &status, 0); |
34080 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34081 |
-+ |
34082 |
-+ if (WIFSIGNALED(status)) |
34083 |
-+ return TEST_ERR; |
34084 |
-+ |
34085 |
-+ return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; |
34086 |
-+} |
34087 |
-+ |
34088 |
-+static int no_cancel_sync(struct kdbus_conn *conn_src, |
34089 |
-+ struct kdbus_conn *conn_dst) |
34090 |
-+{ |
34091 |
-+ pid_t pid; |
34092 |
-+ int cancel_fd; |
34093 |
-+ int ret, status; |
34094 |
-+ struct kdbus_msg *msg = NULL; |
34095 |
-+ |
34096 |
-+ /* pass eventfd, but never signal it so it shouldn't have any effect */ |
34097 |
-+ |
34098 |
-+ cancel_fd = eventfd(0, 0); |
34099 |
-+ ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); |
34100 |
-+ |
34101 |
-+ cookie++; |
34102 |
-+ pid = fork(); |
34103 |
-+ ASSERT_RETURN_VAL(pid >= 0, pid); |
34104 |
-+ |
34105 |
-+ if (pid == 0) { |
34106 |
-+ ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, |
34107 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34108 |
-+ 100000000ULL, 0, conn_src->id, |
34109 |
-+ cancel_fd); |
34110 |
-+ ASSERT_EXIT(ret == 0); |
34111 |
-+ |
34112 |
-+ _exit(EXIT_SUCCESS); |
34113 |
-+ } |
34114 |
-+ |
34115 |
-+ ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); |
34116 |
-+ ASSERT_RETURN_VAL(ret == 0 && msg->cookie == cookie, -1); |
34117 |
-+ |
34118 |
-+ kdbus_msg_free(msg); |
34119 |
-+ |
34120 |
-+ ret = kdbus_msg_send_reply(conn_src, cookie, conn_dst->id); |
34121 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34122 |
-+ |
34123 |
-+ ret = waitpid(pid, &status, 0); |
34124 |
-+ ASSERT_RETURN_VAL(ret >= 0, ret); |
34125 |
-+ |
34126 |
-+ if (WIFSIGNALED(status)) |
34127 |
-+ return -1; |
34128 |
-+ |
34129 |
-+ return (status == EXIT_SUCCESS) ? 0 : -1; |
34130 |
-+} |
34131 |
-+ |
34132 |
-+static void *run_thread_reply(void *data) |
34133 |
-+{ |
34134 |
-+ int ret; |
34135 |
-+ unsigned long status = TEST_OK; |
34136 |
-+ |
34137 |
-+ ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); |
34138 |
-+ if (ret < 0) |
34139 |
-+ goto exit_thread; |
34140 |
-+ |
34141 |
-+ kdbus_printf("Thread received message, sending reply ...\n"); |
34142 |
-+ |
34143 |
-+ /* using an unknown cookie must fail */ |
34144 |
-+ ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id); |
34145 |
-+ if (ret != -EBADSLT) { |
34146 |
-+ status = TEST_ERR; |
34147 |
-+ goto exit_thread; |
34148 |
-+ } |
34149 |
-+ |
34150 |
-+ ret = kdbus_msg_send_reply(conn_a, cookie, conn_b->id); |
34151 |
-+ if (ret != 0) { |
34152 |
-+ status = TEST_ERR; |
34153 |
-+ goto exit_thread; |
34154 |
-+ } |
34155 |
-+ |
34156 |
-+exit_thread: |
34157 |
-+ pthread_exit(NULL); |
34158 |
-+ return (void *) status; |
34159 |
-+} |
34160 |
-+ |
34161 |
-+int kdbus_test_sync_reply(struct kdbus_test_env *env) |
34162 |
-+{ |
34163 |
-+ unsigned long status; |
34164 |
-+ pthread_t thread; |
34165 |
-+ int ret; |
34166 |
-+ |
34167 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34168 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34169 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34170 |
-+ |
34171 |
-+ pthread_create(&thread, NULL, run_thread_reply, NULL); |
34172 |
-+ |
34173 |
-+ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34174 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34175 |
-+ 5000000000ULL, 0, conn_a->id, -1); |
34176 |
-+ |
34177 |
-+ pthread_join(thread, (void *) &status); |
34178 |
-+ ASSERT_RETURN(status == 0); |
34179 |
-+ ASSERT_RETURN(ret == 0); |
34180 |
-+ |
34181 |
-+ ret = interrupt_sync(conn_a, conn_b); |
34182 |
-+ ASSERT_RETURN(ret == 0); |
34183 |
-+ |
34184 |
-+ ret = close_epipe_sync(env->buspath); |
34185 |
-+ ASSERT_RETURN(ret == 0); |
34186 |
-+ |
34187 |
-+ ret = cancel_fd_sync(conn_a, conn_b); |
34188 |
-+ ASSERT_RETURN(ret == 0); |
34189 |
-+ |
34190 |
-+ ret = no_cancel_sync(conn_a, conn_b); |
34191 |
-+ ASSERT_RETURN(ret == 0); |
34192 |
-+ |
34193 |
-+ kdbus_printf("-- closing bus connections\n"); |
34194 |
-+ |
34195 |
-+ kdbus_conn_free(conn_a); |
34196 |
-+ kdbus_conn_free(conn_b); |
34197 |
-+ |
34198 |
-+ return TEST_OK; |
34199 |
-+} |
34200 |
-+ |
34201 |
-+#define BYEBYE_ME ((void*)0L) |
34202 |
-+#define BYEBYE_THEM ((void*)1L) |
34203 |
-+ |
34204 |
-+static void *run_thread_byebye(void *data) |
34205 |
-+{ |
34206 |
-+ struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; |
34207 |
-+ int ret; |
34208 |
-+ |
34209 |
-+ ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); |
34210 |
-+ if (ret == 0) { |
34211 |
-+ kdbus_printf("Thread received message, invoking BYEBYE ...\n"); |
34212 |
-+ kdbus_msg_recv(conn_a, NULL, NULL); |
34213 |
-+ if (data == BYEBYE_ME) |
34214 |
-+ kdbus_cmd_byebye(conn_b->fd, &cmd_byebye); |
34215 |
-+ else if (data == BYEBYE_THEM) |
34216 |
-+ kdbus_cmd_byebye(conn_a->fd, &cmd_byebye); |
34217 |
-+ } |
34218 |
-+ |
34219 |
-+ pthread_exit(NULL); |
34220 |
-+ return NULL; |
34221 |
-+} |
34222 |
-+ |
34223 |
-+int kdbus_test_sync_byebye(struct kdbus_test_env *env) |
34224 |
-+{ |
34225 |
-+ pthread_t thread; |
34226 |
-+ int ret; |
34227 |
-+ |
34228 |
-+ /* |
34229 |
-+ * This sends a synchronous message to a thread, which waits until it |
34230 |
-+ * received the message and then invokes BYEBYE on the *ORIGINAL* |
34231 |
-+ * connection. That is, on the same connection that synchronously waits |
34232 |
-+ * for an reply. |
34233 |
-+ * This should properly wake the connection up and cause ECONNRESET as |
34234 |
-+ * the connection is disconnected now. |
34235 |
-+ * |
34236 |
-+ * The second time, we do the same but invoke BYEBYE on the *TARGET* |
34237 |
-+ * connection. This should also wake up the synchronous sender as the |
34238 |
-+ * reply cannot be sent by a disconnected target. |
34239 |
-+ */ |
34240 |
-+ |
34241 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34242 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34243 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34244 |
-+ |
34245 |
-+ pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_ME); |
34246 |
-+ |
34247 |
-+ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34248 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34249 |
-+ 5000000000ULL, 0, conn_a->id, -1); |
34250 |
-+ |
34251 |
-+ ASSERT_RETURN(ret == -ECONNRESET); |
34252 |
-+ |
34253 |
-+ pthread_join(thread, NULL); |
34254 |
-+ |
34255 |
-+ kdbus_conn_free(conn_a); |
34256 |
-+ kdbus_conn_free(conn_b); |
34257 |
-+ |
34258 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34259 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34260 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34261 |
-+ |
34262 |
-+ pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_THEM); |
34263 |
-+ |
34264 |
-+ ret = kdbus_msg_send_sync(conn_b, NULL, cookie, |
34265 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34266 |
-+ 5000000000ULL, 0, conn_a->id, -1); |
34267 |
-+ |
34268 |
-+ ASSERT_RETURN(ret == -EPIPE); |
34269 |
-+ |
34270 |
-+ pthread_join(thread, NULL); |
34271 |
-+ |
34272 |
-+ kdbus_conn_free(conn_a); |
34273 |
-+ kdbus_conn_free(conn_b); |
34274 |
-+ |
34275 |
-+ return TEST_OK; |
34276 |
-+} |
34277 |
-diff --git a/tools/testing/selftests/kdbus/test-timeout.c b/tools/testing/selftests/kdbus/test-timeout.c |
34278 |
-new file mode 100644 |
34279 |
-index 0000000..cfd1930 |
34280 |
---- /dev/null |
34281 |
-+++ b/tools/testing/selftests/kdbus/test-timeout.c |
34282 |
-@@ -0,0 +1,99 @@ |
34283 |
-+#include <stdio.h> |
34284 |
-+#include <string.h> |
34285 |
-+#include <time.h> |
34286 |
-+#include <fcntl.h> |
34287 |
-+#include <stdlib.h> |
34288 |
-+#include <stddef.h> |
34289 |
-+#include <unistd.h> |
34290 |
-+#include <stdint.h> |
34291 |
-+#include <errno.h> |
34292 |
-+#include <assert.h> |
34293 |
-+#include <poll.h> |
34294 |
-+#include <stdbool.h> |
34295 |
-+ |
34296 |
-+#include "kdbus-api.h" |
34297 |
-+#include "kdbus-test.h" |
34298 |
-+#include "kdbus-util.h" |
34299 |
-+#include "kdbus-enum.h" |
34300 |
-+ |
34301 |
-+int timeout_msg_recv(struct kdbus_conn *conn, uint64_t *expected) |
34302 |
-+{ |
34303 |
-+ struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; |
34304 |
-+ struct kdbus_msg *msg; |
34305 |
-+ int ret; |
34306 |
-+ |
34307 |
-+ ret = kdbus_cmd_recv(conn->fd, &recv); |
34308 |
-+ if (ret < 0) { |
34309 |
-+ kdbus_printf("error receiving message: %d (%m)\n", ret); |
34310 |
-+ return ret; |
34311 |
-+ } |
34312 |
-+ |
34313 |
-+ msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); |
34314 |
-+ |
34315 |
-+ ASSERT_RETURN_VAL(msg->payload_type == KDBUS_PAYLOAD_KERNEL, -EINVAL); |
34316 |
-+ ASSERT_RETURN_VAL(msg->src_id == KDBUS_SRC_ID_KERNEL, -EINVAL); |
34317 |
-+ ASSERT_RETURN_VAL(msg->dst_id == conn->id, -EINVAL); |
34318 |
-+ |
34319 |
-+ *expected &= ~(1ULL << msg->cookie_reply); |
34320 |
-+ kdbus_printf("Got message timeout for cookie %llu\n", |
34321 |
-+ msg->cookie_reply); |
34322 |
-+ |
34323 |
-+ ret = kdbus_free(conn, recv.msg.offset); |
34324 |
-+ if (ret < 0) |
34325 |
-+ return ret; |
34326 |
-+ |
34327 |
-+ return 0; |
34328 |
-+} |
34329 |
-+ |
34330 |
-+int kdbus_test_timeout(struct kdbus_test_env *env) |
34331 |
-+{ |
34332 |
-+ struct kdbus_conn *conn_a, *conn_b; |
34333 |
-+ struct pollfd fd; |
34334 |
-+ int ret, i, n_msgs = 4; |
34335 |
-+ uint64_t expected = 0; |
34336 |
-+ uint64_t cookie = 0xdeadbeef; |
34337 |
-+ |
34338 |
-+ conn_a = kdbus_hello(env->buspath, 0, NULL, 0); |
34339 |
-+ conn_b = kdbus_hello(env->buspath, 0, NULL, 0); |
34340 |
-+ ASSERT_RETURN(conn_a && conn_b); |
34341 |
-+ |
34342 |
-+ fd.fd = conn_b->fd; |
34343 |
-+ |
34344 |
-+ /* |
34345 |
-+ * send messages that expect a reply (within 100 msec), |
34346 |
-+ * but never answer it. |
34347 |
-+ */ |
34348 |
-+ for (i = 0; i < n_msgs; i++, cookie++) { |
34349 |
-+ kdbus_printf("Sending message with cookie %llu ...\n", |
34350 |
-+ (unsigned long long)cookie); |
34351 |
-+ ASSERT_RETURN(kdbus_msg_send(conn_b, NULL, cookie, |
34352 |
-+ KDBUS_MSG_EXPECT_REPLY, |
34353 |
-+ (i + 1) * 100ULL * 1000000ULL, 0, |
34354 |
-+ conn_a->id) == 0); |
34355 |
-+ expected |= 1ULL << cookie; |
34356 |
-+ } |
34357 |
-+ |
34358 |
-+ for (;;) { |
34359 |
-+ fd.events = POLLIN | POLLPRI | POLLHUP; |
34360 |
-+ fd.revents = 0; |
34361 |
-+ |
34362 |
-+ ret = poll(&fd, 1, (n_msgs + 1) * 100); |
34363 |
-+ if (ret == 0) |
34364 |
-+ kdbus_printf("--- timeout\n"); |
34365 |
-+ if (ret <= 0) |
34366 |
-+ break; |
34367 |
-+ |
34368 |
-+ if (fd.revents & POLLIN) |
34369 |
-+ ASSERT_RETURN(!timeout_msg_recv(conn_b, &expected)); |
34370 |
-+ |
34371 |
-+ if (expected == 0) |
34372 |
-+ break; |
34373 |
-+ } |
34374 |
-+ |
34375 |
-+ ASSERT_RETURN(expected == 0); |
34376 |
-+ |
34377 |
-+ kdbus_conn_free(conn_a); |
34378 |
-+ kdbus_conn_free(conn_b); |
34379 |
-+ |
34380 |
-+ return TEST_OK; |
34381 |
-+} |