Linux v4.2-rc1-33-gd6ac4ffc61ac

This commit is contained in:
Josh Boyer 2015-07-08 10:30:06 -04:00
parent 84bb446543
commit 8be443055e
81 changed files with 40410 additions and 2 deletions

View File

@ -0,0 +1,27 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Thu, 9 Apr 2015 13:08:05 +0300
Subject: [PATCH] Documentation: kdbus: Fix description of
KDBUS_SEND_SYNC_REPLY flag
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Acked-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.message.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml
index 5e7c7a3f537e..90f6596dcc20 100644
--- a/Documentation/kdbus/kdbus.message.xml
+++ b/Documentation/kdbus/kdbus.message.xml
@@ -242,8 +242,8 @@ struct kdbus_cmd_send {
</citerefentry>.
The offset of the reply message in the sender's pool is stored
- in in <varname>offset_reply</varname> when the ioctl has
- returned without error. Hence, there is no need for another
+ in <varname>reply</varname> when the ioctl has returned without
+ error. Hence, there is no need for another
<constant>KDBUS_CMD_RECV</constant> ioctl or anything else to
receive the reply.
</para>

View File

@ -0,0 +1,32 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Thu, 9 Apr 2015 13:08:07 +0300
Subject: [PATCH] Documentation: kdbus: Fix list of KDBUS_CMD_ENDPOINT_UPDATE
errors
Remove EEXIST.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Acked-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.endpoint.xml | 7 -------
1 file changed, 7 deletions(-)
diff --git a/Documentation/kdbus/kdbus.endpoint.xml b/Documentation/kdbus/kdbus.endpoint.xml
index 76e325d4e931..c36aa9781739 100644
--- a/Documentation/kdbus/kdbus.endpoint.xml
+++ b/Documentation/kdbus/kdbus.endpoint.xml
@@ -369,13 +369,6 @@ struct kdbus_cmd {
<constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided.
</para></listitem>
</varlistentry>
-
- <varlistentry>
- <term><constant>EEXIST</constant></term>
- <listitem><para>
- An endpoint of that name already exists.
- </para></listitem>
- </varlistentry>
</variablelist>
</refsect2>
</refsect1>

View File

@ -0,0 +1,279 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Thu, 9 Apr 2015 13:08:04 +0300
Subject: [PATCH] Documentation: kdbus: Fix typos
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Acked-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.bus.xml | 9 ++++-----
Documentation/kdbus/kdbus.connection.xml | 10 ++++------
Documentation/kdbus/kdbus.endpoint.xml | 2 +-
Documentation/kdbus/kdbus.item.xml | 9 ++++-----
Documentation/kdbus/kdbus.match.xml | 14 ++++++++------
Documentation/kdbus/kdbus.message.xml | 11 +++++------
Documentation/kdbus/kdbus.xml | 6 +++---
7 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/Documentation/kdbus/kdbus.bus.xml b/Documentation/kdbus/kdbus.bus.xml
index 4d875e59ac02..4b9a0ac1b351 100644
--- a/Documentation/kdbus/kdbus.bus.xml
+++ b/Documentation/kdbus/kdbus.bus.xml
@@ -28,8 +28,7 @@
<citerefentry>
<refentrytitle>kdbus.message</refentrytitle>
<manvolnum>7</manvolnum>
- </citerefentry>
- ).
+ </citerefentry>).
Each bus is independent, and operations on the bus will not have any
effect on other buses. A bus is a management entity that controls the
addresses of its connections, their policies and message transactions
@@ -42,7 +41,7 @@
<refentrytitle>kdbus.fs</refentrytitle>
<manvolnum>7</manvolnum>
</citerefentry>
- , a bus is presented as a directory. No operations can be performed on
+ a bus is presented as a directory. No operations can be performed on
the bus itself; instead you need to perform the operations on an endpoint
associated with the bus. Endpoints are accessible as files underneath the
bus directory. A default endpoint called <constant>bus</constant> is
@@ -165,8 +164,8 @@ struct kdbus_cmd {
<citerefentry>
<refentrytitle>kdbus.item</refentrytitle>
<manvolnum>7</manvolnum>
- </citerefentry>
- ) are expected for <constant>KDBUS_CMD_BUS_MAKE</constant>.
+ </citerefentry>)
+ are expected for <constant>KDBUS_CMD_BUS_MAKE</constant>.
</para>
<variablelist>
<varlistentry>
diff --git a/Documentation/kdbus/kdbus.connection.xml b/Documentation/kdbus/kdbus.connection.xml
index 09852125b2d4..cefb419f1093 100644
--- a/Documentation/kdbus/kdbus.connection.xml
+++ b/Documentation/kdbus/kdbus.connection.xml
@@ -50,8 +50,7 @@
<citerefentry>
<refentrytitle>kdbus.match</refentrytitle>
<manvolnum>7</manvolnum>
- </citerefentry>
- ).
+ </citerefentry>).
</para>
<para>
Messages synthesized and sent directly by the kernel will carry the
@@ -595,13 +594,13 @@ struct kdbus_cmd_info {
</varlistentry>
<varlistentry>
- <term><varname>flags</varname></term>
+ <term><varname>attach_flags</varname></term>
<listitem><para>
Specifies which metadata items should be attached to the answer. See
<citerefentry>
<refentrytitle>kdbus.message</refentrytitle>
<manvolnum>7</manvolnum>
- </citerefentry>
+ </citerefentry>.
</para></listitem>
</varlistentry>
@@ -986,8 +985,7 @@ struct kdbus_cmd {
<term><varname>items</varname></term>
<listitem>
<para>
- Items to describe the connection details to be updated. The
- following item types are supported.
+ The following item types are supported.
</para>
<variablelist>
<varlistentry>
diff --git a/Documentation/kdbus/kdbus.endpoint.xml b/Documentation/kdbus/kdbus.endpoint.xml
index c36aa9781739..6632485f3e84 100644
--- a/Documentation/kdbus/kdbus.endpoint.xml
+++ b/Documentation/kdbus/kdbus.endpoint.xml
@@ -201,7 +201,7 @@ struct kdbus_cmd {
<para>
To update an existing endpoint, the
<constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> command is used on the file
- descriptor that was used to create the update, using
+ descriptor that was used to create the endpoint, using
<constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. The only relevant detail of
the endpoint that can be updated is the policy. When the command is
employed, the policy of the endpoint is <emphasis>replaced</emphasis>
diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml
index bfe47362097f..09f8b903116f 100644
--- a/Documentation/kdbus/kdbus.item.xml
+++ b/Documentation/kdbus/kdbus.item.xml
@@ -139,7 +139,7 @@ struct kdbus_item {
<term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
<listitem><para>
With this item is attached to any ioctl, programs can
- <emphasis>probe</emphasis> the kernel for known item items.
+ <emphasis>probe</emphasis> the kernel for known item types.
The item carries an array of <type>uint64_t</type> values in
<varname>item.data64</varname>, each set to an item type to
probe. The kernel will reset each member of this array that is
@@ -232,7 +232,6 @@ struct kdbus_memfd {
When received as item attached to a message, the array will
contain the numbers of the installed file descriptors, or
<constant>-1</constant> in case an error occurred.
- file descriptor.
In either case, the number of entries in the array is derived from
the item's total size. See
<citerefentry>
@@ -487,7 +486,7 @@ struct kdbus_pids {
a remote peer is a member of, stored as array of
<type>uint32_t</type> values in <varname>item.data32</varname>.
The array length can be determined by looking at the item's total
- size, subtracting the size of the header and and dividing the
+ size, subtracting the size of the header and dividing the
remainder by <constant>sizeof(uint32_t)</constant>.
</para></listitem>
</varlistentry>
@@ -748,7 +747,7 @@ struct kdbus_notify_name_change {
This item is sent as attachment to a
<emphasis>kernel notification</emphasis>. It informs the receiver
that an expected reply to a message was not received in time.
- The remote peer ID and the message cookie is stored in the message
+ The remote peer ID and the message cookie are stored in the message
header. See
<citerefentry>
<refentrytitle>kdbus.message</refentrytitle>
@@ -765,7 +764,7 @@ struct kdbus_notify_name_change {
<emphasis>kernel notification</emphasis>. It informs the receiver
that a remote connection a reply is expected from was disconnected
before that reply was sent. The remote peer ID and the message
- cookie is stored in the message header. See
+ cookie are stored in the message header. See
<citerefentry>
<refentrytitle>kdbus.message</refentrytitle>
<manvolnum>7</manvolnum>
diff --git a/Documentation/kdbus/kdbus.match.xml b/Documentation/kdbus/kdbus.match.xml
index ef77b64e5890..ae38e04ab4d6 100644
--- a/Documentation/kdbus/kdbus.match.xml
+++ b/Documentation/kdbus/kdbus.match.xml
@@ -55,7 +55,7 @@
possibly along with some other rules to further limit the match.
The kernel will match the signal message's bloom filter against the
- connections bloom mask (simply by &amp;-ing it), and will decide whether
+ connection's bloom mask (simply by &amp;-ing it), and will decide whether
the message should be delivered to a connection.
</para>
<para>
@@ -138,9 +138,9 @@
<title>Generations</title>
<para>
- Uploaded matches may contain multiple masks, which have are as large as
- the bloom size defined by the bus. Each block of a mask is called a
- <emphasis>generation</emphasis>, starting at index 0.
+ Uploaded matches may contain multiple masks, which have to be as large
+ as the bloom filter size defined by the bus. Each block of a mask is
+ called a <emphasis>generation</emphasis>, starting at index 0.
At match time, when a signal is about to be delivered, a bloom mask
generation is passed, which denotes which of the bloom masks the filter
@@ -171,7 +171,8 @@
<title>Adding a match</title>
<para>
To add a match, the <constant>KDBUS_CMD_MATCH_ADD</constant> ioctl is
- used, which takes a struct of the struct described below.
+ used, which takes a <type>struct kdbus_cmd_match</type> as an argument
+ described below.
Note that each of the items attached to this command will internally
create one match <emphasis>rule</emphasis>, and the collection of them,
@@ -266,7 +267,8 @@ struct kdbus_cmd_match {
An item that carries the bloom filter mask to match against
in its data field. The payload size must match the bloom
filter size that was specified when the bus was created.
- See the section below for more information on bloom filters.
+ See the "Bloom filters" section above for more information on
+ bloom filters.
</para>
</listitem>
</varlistentry>
diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml
index 90f6596dcc20..0115d9d50db3 100644
--- a/Documentation/kdbus/kdbus.message.xml
+++ b/Documentation/kdbus/kdbus.message.xml
@@ -344,8 +344,7 @@ struct kdbus_cmd_send {
</variablelist>
<para>
- The fields in this struct are described below.
- The message referenced the <varname>msg_address</varname> above has
+ The message referenced by the <varname>msg_address</varname> above has
the following layout.
</para>
@@ -528,7 +527,7 @@ struct kdbus_msg {
<listitem>
<para>
Actual data records containing the payload. See section
- "Passing of Payload Data".
+ "Message payload".
</para>
</listitem>
</varlistentry>
@@ -707,7 +706,7 @@ struct kdbus_cmd_recv {
<listitem><para>
Whenever a message with <constant>KDBUS_MSG_SIGNAL</constant> is sent
but cannot be queued on a peer (e.g., as it contains FDs but the peer
- does not support FDs, or there is no space left in the peer's pool..)
+ does not support FDs, or there is no space left in the peer's pool)
the 'dropped_msgs' counter of the peer is incremented. On the next
RECV ioctl, the 'dropped_msgs' field is copied into the ioctl struct
and cleared on the peer. If it was non-zero, the
@@ -963,7 +962,7 @@ struct kdbus_msg_info {
<varlistentry>
<term><constant>E2BIG</constant></term>
<listitem><para>
- Too many items
+ Too many items.
</para></listitem>
</varlistentry>
@@ -1172,7 +1171,7 @@ struct kdbus_msg_info {
<varlistentry>
<term><constant>EAGAIN</constant></term>
<listitem><para>
- No message found in the queue
+ No message found in the queue.
</para></listitem>
</varlistentry>
</variablelist>
diff --git a/Documentation/kdbus/kdbus.xml b/Documentation/kdbus/kdbus.xml
index 194abd2e76cc..d8e7400df2af 100644
--- a/Documentation/kdbus/kdbus.xml
+++ b/Documentation/kdbus/kdbus.xml
@@ -379,7 +379,7 @@
<listitem>
<para>
When a message is sent (<constant>KDBUS_CMD_SEND</constant>),
- information about the sending task and the sending connection are
+ information about the sending task and the sending connection is
collected. This metadata will be attached to the message when it
arrives in the receiver's pool. If the connection sending the
message installed faked credentials (see
@@ -514,7 +514,7 @@
To let the kernel know which metadata information to attach as items
to the aforementioned commands, it uses a bitmask. In those, the
following <emphasis>attach flags</emphasis> are currently supported.
- Both the the <varname>attach_flags_recv</varname> and
+ Both the <varname>attach_flags_recv</varname> and
<varname>attach_flags_send</varname> fields of
<type>struct kdbus_cmd_hello</type>, as well as the payload of the
<constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant> and
@@ -924,7 +924,7 @@
<para>
These ioctls, along with the structs they transport, are explained in
- detail in the other documents linked to in the 'see also' section below.
+ detail in the other documents linked to in the "See Also" section below.
</para>
</refsect1>

View File

@ -0,0 +1,31 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Thu, 9 Apr 2015 13:08:06 +0300
Subject: [PATCH] Documentation: kdbus: Update list of ioctls which cause
writing to receiver's pool
Add KDBUS_CMD_BUS_CREATOR_INFO.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Acked-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.pool.xml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/kdbus/kdbus.pool.xml b/Documentation/kdbus/kdbus.pool.xml
index 05fd01902ad4..a9e16f196d39 100644
--- a/Documentation/kdbus/kdbus.pool.xml
+++ b/Documentation/kdbus/kdbus.pool.xml
@@ -66,6 +66,12 @@
... to retrieve information on a connection
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></term>
+ <listitem><para>
+ ... to retrieve information about a connection's bus creator
+ </para></listitem>
+ </varlistentry>
</variablelist>
</para>

View File

@ -0,0 +1,41 @@
From: Daniel Mack <daniel@zonque.org>
Date: Mon, 9 Mar 2015 18:00:46 +0100
Subject: [PATCH] Documentation: kdbus: fix location for generated files
The generated files should reside in Documentation/kdbus, not in the
top-level of the source tree. Also add a .gitignore file and ignore
everything that was built from the XML files.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/.gitignore | 2 ++
Documentation/kdbus/Makefile | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
create mode 100644 Documentation/kdbus/.gitignore
diff --git a/Documentation/kdbus/.gitignore b/Documentation/kdbus/.gitignore
new file mode 100644
index 000000000000..b4a77ccba9b4
--- /dev/null
+++ b/Documentation/kdbus/.gitignore
@@ -0,0 +1,2 @@
+*.7
+*.html
diff --git a/Documentation/kdbus/Makefile b/Documentation/kdbus/Makefile
index cd6b48ee41bf..f6d491251c25 100644
--- a/Documentation/kdbus/Makefile
+++ b/Documentation/kdbus/Makefile
@@ -18,10 +18,10 @@ HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES))
XMLTO_ARGS := -m $(obj)/stylesheet.xsl
%.7: %.xml
- xmlto man $(XMLTO_ARGS) -o . $<
+ xmlto man $(XMLTO_ARGS) -o $(obj) $<
%.html: %.xml
- xmlto html-nochunks $(XMLTO_ARGS) -o . $<
+ xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $<
mandocs: $(MANFILES)

View File

@ -0,0 +1,33 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:01 +0300
Subject: [PATCH] Documentation/kdbus: fix operator precedence issue in
KDBUS_ITEM_NEXT macro
`item' argument in KDBUS_ITEM_NEXT macro example is not enclosed into
parentheses when the cast operator is applied, which leads to improper
type conversion if `item' is supplied as a complex expression, e.g.
KDBUS_ITEM_NEXT(condition ? a : b)
Use parentheses properly to guarantee right precedence.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.item.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml
index 09f8b903116f..b0eeeef995af 100644
--- a/Documentation/kdbus/kdbus.item.xml
+++ b/Documentation/kdbus/kdbus.item.xml
@@ -69,7 +69,7 @@
#define KDBUS_ALIGN8(val) (((val) + 7) & ~7)
#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
#define KDBUS_ITEM_FOREACH(item, head, first) \
for (item = (head)->first; \

View File

@ -0,0 +1,27 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 16 Mar 2015 10:17:11 +0100
Subject: [PATCH] Documentation/kdbus: fix out-of-tree builds
Don't use $(obj) to access source files, but use $(srctree)/$(src)/
instead. This fixes build issues if you use O= with a directory other than
the source directory.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/kdbus/Makefile b/Documentation/kdbus/Makefile
index f6d491251c25..d8e6bf37d53b 100644
--- a/Documentation/kdbus/Makefile
+++ b/Documentation/kdbus/Makefile
@@ -15,7 +15,7 @@ XMLFILES := $(addprefix $(obj)/,$(DOCS))
MANFILES := $(patsubst %.xml, %.7, $(XMLFILES))
HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES))
-XMLTO_ARGS := -m $(obj)/stylesheet.xsl
+XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl
%.7: %.xml
xmlto man $(XMLTO_ARGS) -o $(obj) $<

View File

@ -0,0 +1,28 @@
From: Lukasz Skalski <l.skalski@samsung.com>
Date: Mon, 16 Mar 2015 10:35:08 +0100
Subject: [PATCH] Documentation/kdbus: replace 'reply_cookie' with
'cookie_reply'
The member field is called 'cookie_reply', fix the documentation which
incorrectly used 'reply_cookie'.
Signed-off-by: Lukasz Skalski <l.skalski@samsung.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.message.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml
index c25000dcfbc7..5e7c7a3f537e 100644
--- a/Documentation/kdbus/kdbus.message.xml
+++ b/Documentation/kdbus/kdbus.message.xml
@@ -393,7 +393,7 @@ struct kdbus_msg {
For a message to be accepted as reply, it must be a direct
message to the original sender (not a broadcast and not a
signal message), and its
- <varname>kdbus_msg.reply_cookie</varname> must match the
+ <varname>kdbus_msg.cookie_reply</varname> must match the
previous message's <varname>kdbus_msg.cookie</varname>.
</para><para>
Expected replies also temporarily open the policy of the

View File

@ -0,0 +1,44 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 16 Mar 2015 10:17:12 +0100
Subject: [PATCH] Documentation/kdbus: support quiet builds
Add support for quiet builds, just like Documentation/DocBook/Makefile
supports.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/Makefile | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/Documentation/kdbus/Makefile b/Documentation/kdbus/Makefile
index d8e6bf37d53b..af87641db416 100644
--- a/Documentation/kdbus/Makefile
+++ b/Documentation/kdbus/Makefile
@@ -15,13 +15,23 @@ XMLFILES := $(addprefix $(obj)/,$(DOCS))
MANFILES := $(patsubst %.xml, %.7, $(XMLFILES))
HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES))
-XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl
+XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl --skip-validation
+quiet_cmd_db2man = MAN $@
+ cmd_db2man = xmlto man $(XMLTO_ARGS) -o $(obj) $<
%.7: %.xml
- xmlto man $(XMLTO_ARGS) -o $(obj) $<
+ @(which xmlto > /dev/null 2>&1) || \
+ (echo "*** You need to install xmlto ***"; \
+ exit 1)
+ $(call cmd,db2man)
+quiet_cmd_db2html = HTML $@
+ cmd_db2html = xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $<
%.html: %.xml
- xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $<
+ @(which xmlto > /dev/null 2>&1) || \
+ (echo "*** You need to install xmlto ***"; \
+ exit 1)
+ $(call cmd,db2html)
mandocs: $(MANFILES)

View File

@ -0,0 +1,32 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:02 +0300
Subject: [PATCH] Documentation/kdbus: use parentheses uniformly in
KDBUS_ITEM_FOREACH macro
Enclose all arguments into parentheses to stay consistent across the
whole macro.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/kdbus/kdbus.item.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml
index b0eeeef995af..ee09dfa443b8 100644
--- a/Documentation/kdbus/kdbus.item.xml
+++ b/Documentation/kdbus/kdbus.item.xml
@@ -72,10 +72,10 @@
(typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
#define KDBUS_ITEM_FOREACH(item, head, first) \
- for (item = (head)->first; \
+ for ((item) = (head)->first; \
((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
((uint8_t *)(item) >= (uint8_t *)(head)); \
- item = KDBUS_ITEM_NEXT(item))
+ (item) = KDBUS_ITEM_NEXT(item))
]]></programlisting>
</refsect2>
</refsect1>

View File

@ -67,6 +67,7 @@ CONFIG_NET_NS=y
CONFIG_USER_NS=y CONFIG_USER_NS=y
CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE=y
CONFIG_KDBUS=m
# CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set # CONFIG_PREEMPT is not set

View File

@ -0,0 +1,35 @@
From: Daniel Mack <daniel@zonque.org>
Date: Tue, 24 Mar 2015 19:51:55 +0100
Subject: [PATCH] kdbus: Fix CONFIG_KDBUS help text
Drop a left-over from the times when documentation lived in a
simple text file, which is no longer the case. Mention the
auto-generated man-pages and HTML files instead.
Reported-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Daniel Mack <daniel@zonque.org>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
init/Kconfig | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/init/Kconfig b/init/Kconfig
index 02735f91836e..c4075075295d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -268,10 +268,11 @@ config KDBUS
D-Bus is a system for low-latency, low-overhead, easy to use
interprocess communication (IPC).
- See Documentation/kdbus.txt
+ See the man-pages and HTML files in Documentation/kdbus/
+ that are generated by 'make mandocs' and 'make htmldocs'.
- To compile this driver as a module, choose M here: the
- module will be called kdbus.
+ If you have an ordinary machine, select M here. The module
+ will be called kdbus.
config CROSS_MEMORY_ATTACH
bool "Enable process_vm_readv/writev syscalls"

View File

@ -0,0 +1,106 @@
From: Daniel Mack <daniel@zonque.org>
Date: Thu, 11 Sep 2014 18:48:06 +0200
Subject: [PATCH] kdbus: add Makefile, Kconfig and MAINTAINERS entry
This patch hooks up the build system to actually compile the files
added by previous patches. It also adds an entry to MAINTAINERS to
direct people to Greg KH, David Herrmann, Djalal Harouni and me for
questions and patches.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
MAINTAINERS | 13 +++++++++++++
init/Kconfig | 12 ++++++++++++
ipc/Makefile | 2 +-
ipc/kdbus/Makefile | 22 ++++++++++++++++++++++
4 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 ipc/kdbus/Makefile
diff --git a/MAINTAINERS b/MAINTAINERS
index 8133cefb6b6e..11a76301dde3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5780,6 +5780,19 @@ S: Maintained
F: Documentation/kbuild/kconfig-language.txt
F: scripts/kconfig/
+KDBUS
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+M: Daniel Mack <daniel@zonque.org>
+M: David Herrmann <dh.herrmann@googlemail.com>
+M: Djalal Harouni <tixxdz@opendz.org>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: ipc/kdbus/*
+F: samples/kdbus/*
+F: Documentation/kdbus/*
+F: include/uapi/linux/kdbus.h
+F: tools/testing/selftests/kdbus/
+
KDUMP
M: Vivek Goyal <vgoyal@redhat.com>
M: Haren Myneni <hbabu@us.ibm.com>
diff --git a/init/Kconfig b/init/Kconfig
index 860ca236975f..02735f91836e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -261,6 +261,18 @@ config POSIX_MQUEUE_SYSCTL
depends on SYSCTL
default y
+config KDBUS
+ tristate "kdbus interprocess communication"
+ depends on TMPFS
+ help
+ D-Bus is a system for low-latency, low-overhead, easy to use
+ interprocess communication (IPC).
+
+ See Documentation/kdbus.txt
+
+ To compile this driver as a module, choose M here: the
+ module will be called kdbus.
+
config CROSS_MEMORY_ATTACH
bool "Enable process_vm_readv/writev syscalls"
depends on MMU
diff --git a/ipc/Makefile b/ipc/Makefile
index 86c7300ecdf5..68ec4167d11b 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -9,4 +9,4 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
obj-$(CONFIG_IPC_NS) += namespace.o
obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
-
+obj-$(CONFIG_KDBUS) += kdbus/
diff --git a/ipc/kdbus/Makefile b/ipc/kdbus/Makefile
new file mode 100644
index 000000000000..7ee9271e1449
--- /dev/null
+++ b/ipc/kdbus/Makefile
@@ -0,0 +1,22 @@
+kdbus-y := \
+ bus.o \
+ connection.o \
+ endpoint.o \
+ fs.o \
+ handle.o \
+ item.o \
+ main.o \
+ match.o \
+ message.o \
+ metadata.o \
+ names.o \
+ node.o \
+ notify.o \
+ domain.o \
+ policy.o \
+ pool.o \
+ reply.o \
+ queue.o \
+ util.o
+
+obj-$(CONFIG_KDBUS) += kdbus.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,929 @@
From: Daniel Mack <daniel@zonque.org>
Date: Thu, 11 Sep 2014 18:59:16 +0200
Subject: [PATCH] kdbus: add code for notifications and matches
This patch adds code for matches and notifications.
Notifications are broadcast messages generated by the kernel, which
notify subscribes when connections are created or destroyed, when
well-known-names have been claimed, released or changed ownership,
or when reply messages have timed out.
Matches are used to tell the kernel driver which broadcast messages
a connection is interested in. Matches can either be specific on one
of the kernel-generated notification types, or carry a bloom filter
mask to match against a message from userspace. The latter is a way
to pre-filter messages from other connections in order to mitigate
unnecessary wakeups.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/match.c | 559 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ipc/kdbus/match.h | 35 ++++
ipc/kdbus/notify.c | 248 ++++++++++++++++++++++++
ipc/kdbus/notify.h | 30 +++
4 files changed, 872 insertions(+)
create mode 100644 ipc/kdbus/match.c
create mode 100644 ipc/kdbus/match.h
create mode 100644 ipc/kdbus/notify.c
create mode 100644 ipc/kdbus/notify.h
diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c
new file mode 100644
index 000000000000..30cec1ca819f
--- /dev/null
+++ b/ipc/kdbus/match.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/fs.h>
+#include <linux/hash.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "bus.h"
+#include "connection.h"
+#include "endpoint.h"
+#include "handle.h"
+#include "item.h"
+#include "match.h"
+#include "message.h"
+#include "names.h"
+
+/**
+ * struct kdbus_match_db - message filters
+ * @entries_list: List of matches
+ * @mdb_rwlock: Match data lock
+ * @entries_count: Number of entries in database
+ */
+struct kdbus_match_db {
+ struct list_head entries_list;
+ struct rw_semaphore mdb_rwlock;
+ unsigned int entries_count;
+};
+
+/**
+ * struct kdbus_match_entry - a match database entry
+ * @cookie: User-supplied cookie to lookup the entry
+ * @list_entry: The list entry element for the db list
+ * @rules_list: The list head for tracking rules of this entry
+ */
+struct kdbus_match_entry {
+ u64 cookie;
+ struct list_head list_entry;
+ struct list_head rules_list;
+};
+
+/**
+ * struct kdbus_bloom_mask - mask to match against filter
+ * @generations: Number of generations carried
+ * @data: Array of bloom bit fields
+ */
+struct kdbus_bloom_mask {
+ u64 generations;
+ u64 *data;
+};
+
+/**
+ * struct kdbus_match_rule - a rule appended to a match entry
+ * @type: An item type to match agains
+ * @bloom_mask: Bloom mask to match a message's filter against, used
+ * with KDBUS_ITEM_BLOOM_MASK
+ * @name: Name to match against, used with KDBUS_ITEM_NAME,
+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
+ * @old_id: ID to match against, used with
+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE},
+ * KDBUS_ITEM_ID_REMOVE
+ * @new_id: ID to match against, used with
+ * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE},
+ * KDBUS_ITEM_ID_REMOVE
+ * @src_id: ID to match against, used with KDBUS_ITEM_ID
+ * @rules_entry: Entry in the entry's rules list
+ */
+struct kdbus_match_rule {
+ u64 type;
+ union {
+ struct kdbus_bloom_mask bloom_mask;
+ struct {
+ char *name;
+ u64 old_id;
+ u64 new_id;
+ };
+ u64 src_id;
+ };
+ struct list_head rules_entry;
+};
+
+static void kdbus_match_rule_free(struct kdbus_match_rule *rule)
+{
+ if (!rule)
+ return;
+
+ switch (rule->type) {
+ case KDBUS_ITEM_BLOOM_MASK:
+ kfree(rule->bloom_mask.data);
+ break;
+
+ case KDBUS_ITEM_NAME:
+ case KDBUS_ITEM_NAME_ADD:
+ case KDBUS_ITEM_NAME_REMOVE:
+ case KDBUS_ITEM_NAME_CHANGE:
+ kfree(rule->name);
+ break;
+
+ case KDBUS_ITEM_ID:
+ case KDBUS_ITEM_ID_ADD:
+ case KDBUS_ITEM_ID_REMOVE:
+ break;
+
+ default:
+ BUG();
+ }
+
+ list_del(&rule->rules_entry);
+ kfree(rule);
+}
+
+static void kdbus_match_entry_free(struct kdbus_match_entry *entry)
+{
+ struct kdbus_match_rule *r, *tmp;
+
+ if (!entry)
+ return;
+
+ list_for_each_entry_safe(r, tmp, &entry->rules_list, rules_entry)
+ kdbus_match_rule_free(r);
+
+ list_del(&entry->list_entry);
+ kfree(entry);
+}
+
+/**
+ * kdbus_match_db_free() - free match db resources
+ * @mdb: The match database
+ */
+void kdbus_match_db_free(struct kdbus_match_db *mdb)
+{
+ struct kdbus_match_entry *entry, *tmp;
+
+ if (!mdb)
+ return;
+
+ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
+ kdbus_match_entry_free(entry);
+
+ kfree(mdb);
+}
+
+/**
+ * kdbus_match_db_new() - create a new match database
+ *
+ * Return: a new kdbus_match_db on success, ERR_PTR on failure.
+ */
+struct kdbus_match_db *kdbus_match_db_new(void)
+{
+ struct kdbus_match_db *d;
+
+ d = kzalloc(sizeof(*d), GFP_KERNEL);
+ if (!d)
+ return ERR_PTR(-ENOMEM);
+
+ init_rwsem(&d->mdb_rwlock);
+ INIT_LIST_HEAD(&d->entries_list);
+
+ return d;
+}
+
+static bool kdbus_match_bloom(const struct kdbus_bloom_filter *filter,
+ const struct kdbus_bloom_mask *mask,
+ const struct kdbus_conn *conn)
+{
+ size_t n = conn->ep->bus->bloom.size / sizeof(u64);
+ const u64 *m;
+ size_t i;
+
+ /*
+ * The message's filter carries a generation identifier, the
+ * match's mask possibly carries an array of multiple generations
+ * of the mask. Select the mask with the closest match of the
+ * filter's generation.
+ */
+ m = mask->data + (min(filter->generation, mask->generations - 1) * n);
+
+ /*
+ * The message's filter contains the messages properties,
+ * the match's mask contains the properties to look for in the
+ * message. Check the mask bit field against the filter bit field,
+ * if the message possibly carries the properties the connection
+ * has subscribed to.
+ */
+ for (i = 0; i < n; i++)
+ if ((filter->data[i] & m[i]) != m[i])
+ return false;
+
+ return true;
+}
+
+static bool kdbus_match_rules(const struct kdbus_match_entry *entry,
+ struct kdbus_conn *conn_src,
+ struct kdbus_kmsg *kmsg)
+{
+ struct kdbus_match_rule *r;
+
+ if (conn_src)
+ lockdep_assert_held(&conn_src->ep->bus->name_registry->rwlock);
+
+ /*
+ * Walk all the rules and bail out immediately
+ * if any of them is unsatisfied.
+ */
+
+ list_for_each_entry(r, &entry->rules_list, rules_entry) {
+ if (conn_src) {
+ /* messages from userspace */
+
+ switch (r->type) {
+ case KDBUS_ITEM_BLOOM_MASK:
+ if (!kdbus_match_bloom(kmsg->bloom_filter,
+ &r->bloom_mask,
+ conn_src))
+ return false;
+ break;
+
+ case KDBUS_ITEM_ID:
+ if (r->src_id != conn_src->id &&
+ r->src_id != KDBUS_MATCH_ID_ANY)
+ return false;
+
+ break;
+
+ case KDBUS_ITEM_NAME:
+ if (!kdbus_conn_has_name(conn_src, r->name))
+ return false;
+
+ break;
+
+ default:
+ return false;
+ }
+ } else {
+ /* kernel notifications */
+
+ if (kmsg->notify_type != r->type)
+ return false;
+
+ switch (r->type) {
+ case KDBUS_ITEM_ID_ADD:
+ if (r->new_id != KDBUS_MATCH_ID_ANY &&
+ r->new_id != kmsg->notify_new_id)
+ return false;
+
+ break;
+
+ case KDBUS_ITEM_ID_REMOVE:
+ if (r->old_id != KDBUS_MATCH_ID_ANY &&
+ r->old_id != kmsg->notify_old_id)
+ return false;
+
+ break;
+
+ case KDBUS_ITEM_NAME_ADD:
+ case KDBUS_ITEM_NAME_CHANGE:
+ case KDBUS_ITEM_NAME_REMOVE:
+ if ((r->old_id != KDBUS_MATCH_ID_ANY &&
+ r->old_id != kmsg->notify_old_id) ||
+ (r->new_id != KDBUS_MATCH_ID_ANY &&
+ r->new_id != kmsg->notify_new_id) ||
+ (r->name && kmsg->notify_name &&
+ strcmp(r->name, kmsg->notify_name) != 0))
+ return false;
+
+ break;
+
+ default:
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * kdbus_match_db_match_kmsg() - match a kmsg object agains the database entries
+ * @mdb: The match database
+ * @conn_src: The connection object originating the message
+ * @kmsg: The kmsg to perform the match on
+ *
+ * This function will walk through all the database entries previously uploaded
+ * with kdbus_match_db_add(). As soon as any of them has an all-satisfied rule
+ * set, this function will return true.
+ *
+ * The caller must hold the registry lock of conn_src->ep->bus, in case conn_src
+ * is non-NULL.
+ *
+ * Return: true if there was a matching database entry, false otherwise.
+ */
+bool kdbus_match_db_match_kmsg(struct kdbus_match_db *mdb,
+ struct kdbus_conn *conn_src,
+ struct kdbus_kmsg *kmsg)
+{
+ struct kdbus_match_entry *entry;
+ bool matched = false;
+
+ down_read(&mdb->mdb_rwlock);
+ list_for_each_entry(entry, &mdb->entries_list, list_entry) {
+ matched = kdbus_match_rules(entry, conn_src, kmsg);
+ if (matched)
+ break;
+ }
+ up_read(&mdb->mdb_rwlock);
+
+ return matched;
+}
+
+static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb,
+ u64 cookie)
+{
+ struct kdbus_match_entry *entry, *tmp;
+ bool found = false;
+
+ list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
+ if (entry->cookie == cookie) {
+ kdbus_match_entry_free(entry);
+ --mdb->entries_count;
+ found = true;
+ }
+
+ return found ? 0 : -EBADSLT;
+}
+
+/**
+ * kdbus_cmd_match_add() - handle KDBUS_CMD_MATCH_ADD
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
+ * One call to this function (or one ioctl(KDBUS_CMD_MATCH_ADD), respectively,
+ * adds one new database entry with n rules attached to it. Each rule is
+ * described with an kdbus_item, and an entry is considered matching if all
+ * its rules are satisfied.
+ *
+ * The items attached to a kdbus_cmd_match struct have the following mapping:
+ *
+ * KDBUS_ITEM_BLOOM_MASK: A bloom mask
+ * KDBUS_ITEM_NAME: A connection's source name
+ * KDBUS_ITEM_ID: A connection ID
+ * KDBUS_ITEM_NAME_ADD:
+ * KDBUS_ITEM_NAME_REMOVE:
+ * KDBUS_ITEM_NAME_CHANGE: Well-known name changes, carry
+ * kdbus_notify_name_change
+ * KDBUS_ITEM_ID_ADD:
+ * KDBUS_ITEM_ID_REMOVE: Connection ID changes, carry
+ * kdbus_notify_id_change
+ *
+ * For kdbus_notify_{id,name}_change structs, only the ID and name fields
+ * are looked at when adding an entry. The flags are unused.
+ *
+ * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME and KDBUS_ITEM_ID
+ * are used to match messages from userspace, while the others apply to
+ * kernel-generated notifications.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp)
+{
+ struct kdbus_match_db *mdb = conn->match_db;
+ struct kdbus_match_entry *entry = NULL;
+ struct kdbus_cmd_match *cmd;
+ struct kdbus_item *item;
+ int ret;
+
+ struct kdbus_arg argv[] = {
+ { .type = KDBUS_ITEM_NEGOTIATE },
+ { .type = KDBUS_ITEM_BLOOM_MASK, .multiple = true },
+ { .type = KDBUS_ITEM_NAME, .multiple = true },
+ { .type = KDBUS_ITEM_ID, .multiple = true },
+ { .type = KDBUS_ITEM_NAME_ADD, .multiple = true },
+ { .type = KDBUS_ITEM_NAME_REMOVE, .multiple = true },
+ { .type = KDBUS_ITEM_NAME_CHANGE, .multiple = true },
+ { .type = KDBUS_ITEM_ID_ADD, .multiple = true },
+ { .type = KDBUS_ITEM_ID_REMOVE, .multiple = true },
+ };
+ struct kdbus_args args = {
+ .allowed_flags = KDBUS_FLAG_NEGOTIATE |
+ KDBUS_MATCH_REPLACE,
+ .argv = argv,
+ .argc = ARRAY_SIZE(argv),
+ };
+
+ if (!kdbus_conn_is_ordinary(conn))
+ return -EOPNOTSUPP;
+
+ ret = kdbus_args_parse(&args, argp, &cmd);
+ if (ret != 0)
+ return ret;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ entry->cookie = cmd->cookie;
+ INIT_LIST_HEAD(&entry->list_entry);
+ INIT_LIST_HEAD(&entry->rules_list);
+
+ KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) {
+ struct kdbus_match_rule *rule;
+ size_t size = item->size - offsetof(struct kdbus_item, data);
+
+ rule = kzalloc(sizeof(*rule), GFP_KERNEL);
+ if (!rule) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ rule->type = item->type;
+ INIT_LIST_HEAD(&rule->rules_entry);
+
+ switch (item->type) {
+ case KDBUS_ITEM_BLOOM_MASK: {
+ u64 bsize = conn->ep->bus->bloom.size;
+ u64 generations;
+ u64 remainder;
+
+ generations = div64_u64_rem(size, bsize, &remainder);
+ if (size < bsize || remainder > 0) {
+ ret = -EDOM;
+ break;
+ }
+
+ rule->bloom_mask.data = kmemdup(item->data,
+ size, GFP_KERNEL);
+ if (!rule->bloom_mask.data) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ rule->bloom_mask.generations = generations;
+ break;
+ }
+
+ case KDBUS_ITEM_NAME:
+ if (!kdbus_name_is_valid(item->str, false)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ rule->name = kstrdup(item->str, GFP_KERNEL);
+ if (!rule->name)
+ ret = -ENOMEM;
+
+ break;
+
+ case KDBUS_ITEM_ID:
+ rule->src_id = item->id;
+ break;
+
+ case KDBUS_ITEM_NAME_ADD:
+ case KDBUS_ITEM_NAME_REMOVE:
+ case KDBUS_ITEM_NAME_CHANGE:
+ rule->old_id = item->name_change.old_id.id;
+ rule->new_id = item->name_change.new_id.id;
+
+ if (size > sizeof(struct kdbus_notify_name_change)) {
+ rule->name = kstrdup(item->name_change.name,
+ GFP_KERNEL);
+ if (!rule->name)
+ ret = -ENOMEM;
+ }
+
+ break;
+
+ case KDBUS_ITEM_ID_ADD:
+ case KDBUS_ITEM_ID_REMOVE:
+ if (item->type == KDBUS_ITEM_ID_ADD)
+ rule->new_id = item->id_change.id;
+ else
+ rule->old_id = item->id_change.id;
+
+ break;
+ }
+
+ if (ret < 0) {
+ kdbus_match_rule_free(rule);
+ goto exit;
+ }
+
+ list_add_tail(&rule->rules_entry, &entry->rules_list);
+ }
+
+ down_write(&mdb->mdb_rwlock);
+
+ /* Remove any entry that has the same cookie as the current one. */
+ if (cmd->flags & KDBUS_MATCH_REPLACE)
+ kdbus_match_db_remove_unlocked(mdb, entry->cookie);
+
+ /*
+ * If the above removal caught any entry, there will be room for the
+ * new one.
+ */
+ if (++mdb->entries_count > KDBUS_MATCH_MAX) {
+ --mdb->entries_count;
+ ret = -EMFILE;
+ } else {
+ list_add_tail(&entry->list_entry, &mdb->entries_list);
+ entry = NULL;
+ }
+
+ up_write(&mdb->mdb_rwlock);
+
+exit:
+ kdbus_match_entry_free(entry);
+ return kdbus_args_clear(&args, ret);
+}
+
+/**
+ * kdbus_cmd_match_remove() - handle KDBUS_CMD_MATCH_REMOVE
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp)
+{
+ struct kdbus_cmd_match *cmd;
+ int ret;
+
+ struct kdbus_arg argv[] = {
+ { .type = KDBUS_ITEM_NEGOTIATE },
+ };
+ struct kdbus_args args = {
+ .allowed_flags = KDBUS_FLAG_NEGOTIATE,
+ .argv = argv,
+ .argc = ARRAY_SIZE(argv),
+ };
+
+ if (!kdbus_conn_is_ordinary(conn))
+ return -EOPNOTSUPP;
+
+ ret = kdbus_args_parse(&args, argp, &cmd);
+ if (ret != 0)
+ return ret;
+
+ down_write(&conn->match_db->mdb_rwlock);
+ ret = kdbus_match_db_remove_unlocked(conn->match_db, cmd->cookie);
+ up_write(&conn->match_db->mdb_rwlock);
+
+ return kdbus_args_clear(&args, ret);
+}
diff --git a/ipc/kdbus/match.h b/ipc/kdbus/match.h
new file mode 100644
index 000000000000..ea4292938deb
--- /dev/null
+++ b/ipc/kdbus/match.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __KDBUS_MATCH_H
+#define __KDBUS_MATCH_H
+
+struct kdbus_conn;
+struct kdbus_kmsg;
+struct kdbus_match_db;
+
+struct kdbus_match_db *kdbus_match_db_new(void);
+void kdbus_match_db_free(struct kdbus_match_db *db);
+int kdbus_match_db_add(struct kdbus_conn *conn,
+ struct kdbus_cmd_match *cmd);
+int kdbus_match_db_remove(struct kdbus_conn *conn,
+ struct kdbus_cmd_match *cmd);
+bool kdbus_match_db_match_kmsg(struct kdbus_match_db *db,
+ struct kdbus_conn *conn_src,
+ struct kdbus_kmsg *kmsg);
+
+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp);
+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp);
+
+#endif
diff --git a/ipc/kdbus/notify.c b/ipc/kdbus/notify.c
new file mode 100644
index 000000000000..e4a454222f09
--- /dev/null
+++ b/ipc/kdbus/notify.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include "bus.h"
+#include "connection.h"
+#include "domain.h"
+#include "endpoint.h"
+#include "item.h"
+#include "message.h"
+#include "notify.h"
+
+static inline void kdbus_notify_add_tail(struct kdbus_kmsg *kmsg,
+ struct kdbus_bus *bus)
+{
+ spin_lock(&bus->notify_lock);
+ list_add_tail(&kmsg->notify_entry, &bus->notify_list);
+ spin_unlock(&bus->notify_lock);
+}
+
+static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id,
+ u64 cookie, u64 msg_type)
+{
+ struct kdbus_kmsg *kmsg = NULL;
+
+ WARN_ON(id == 0);
+
+ kmsg = kdbus_kmsg_new(bus, 0);
+ if (IS_ERR(kmsg))
+ return PTR_ERR(kmsg);
+
+ /*
+ * a kernel-generated notification can only contain one
+ * struct kdbus_item, so make a shortcut here for
+ * faster lookup in the match db.
+ */
+ kmsg->notify_type = msg_type;
+ kmsg->msg.flags = KDBUS_MSG_SIGNAL;
+ kmsg->msg.dst_id = id;
+ kmsg->msg.src_id = KDBUS_SRC_ID_KERNEL;
+ kmsg->msg.payload_type = KDBUS_PAYLOAD_KERNEL;
+ kmsg->msg.cookie_reply = cookie;
+ kmsg->msg.items[0].type = msg_type;
+
+ kdbus_notify_add_tail(kmsg, bus);
+
+ return 0;
+}
+
+/**
+ * kdbus_notify_reply_timeout() - queue a timeout reply
+ * @bus: Bus which queues the messages
+ * @id: The destination's connection ID
+ * @cookie: The cookie to set in the reply.
+ *
+ * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie)
+{
+ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT);
+}
+
+/**
+ * kdbus_notify_reply_dead() - queue a 'dead' reply
+ * @bus: Bus which queues the messages
+ * @id: The destination's connection ID
+ * @cookie: The cookie to set in the reply.
+ *
+ * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie)
+{
+ return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD);
+}
+
+/**
+ * kdbus_notify_name_change() - queue a notification about a name owner change
+ * @bus: Bus which queues the messages
+ * @type: The type if the notification; KDBUS_ITEM_NAME_ADD,
+ * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE
+ * @old_id: The id of the connection that used to own the name
+ * @new_id: The id of the new owner connection
+ * @old_flags: The flags to pass in the KDBUS_ITEM flags field for
+ * the old owner
+ * @new_flags: The flags to pass in the KDBUS_ITEM flags field for
+ * the new owner
+ * @name: The name that was removed or assigned to a new owner
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type,
+ u64 old_id, u64 new_id,
+ u64 old_flags, u64 new_flags,
+ const char *name)
+{
+ struct kdbus_kmsg *kmsg = NULL;
+ size_t name_len, extra_size;
+
+ name_len = strlen(name) + 1;
+ extra_size = sizeof(struct kdbus_notify_name_change) + name_len;
+ kmsg = kdbus_kmsg_new(bus, extra_size);
+ if (IS_ERR(kmsg))
+ return PTR_ERR(kmsg);
+
+ kmsg->msg.flags = KDBUS_MSG_SIGNAL;
+ kmsg->msg.dst_id = KDBUS_DST_ID_BROADCAST;
+ kmsg->msg.src_id = KDBUS_SRC_ID_KERNEL;
+ kmsg->msg.payload_type = KDBUS_PAYLOAD_KERNEL;
+ kmsg->notify_type = type;
+ kmsg->notify_old_id = old_id;
+ kmsg->notify_new_id = new_id;
+ kmsg->msg.items[0].type = type;
+ kmsg->msg.items[0].name_change.old_id.id = old_id;
+ kmsg->msg.items[0].name_change.old_id.flags = old_flags;
+ kmsg->msg.items[0].name_change.new_id.id = new_id;
+ kmsg->msg.items[0].name_change.new_id.flags = new_flags;
+ memcpy(kmsg->msg.items[0].name_change.name, name, name_len);
+ kmsg->notify_name = kmsg->msg.items[0].name_change.name;
+
+ kdbus_notify_add_tail(kmsg, bus);
+
+ return 0;
+}
+
+/**
+ * kdbus_notify_id_change() - queue a notification about a unique ID change
+ * @bus: Bus which queues the messages
+ * @type: The type if the notification; KDBUS_ITEM_ID_ADD or
+ * KDBUS_ITEM_ID_REMOVE
+ * @id: The id of the connection that was added or removed
+ * @flags: The flags to pass in the KDBUS_ITEM flags field
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags)
+{
+ struct kdbus_kmsg *kmsg = NULL;
+
+ kmsg = kdbus_kmsg_new(bus, sizeof(struct kdbus_notify_id_change));
+ if (IS_ERR(kmsg))
+ return PTR_ERR(kmsg);
+
+ kmsg->msg.flags = KDBUS_MSG_SIGNAL;
+ kmsg->msg.dst_id = KDBUS_DST_ID_BROADCAST;
+ kmsg->msg.src_id = KDBUS_SRC_ID_KERNEL;
+ kmsg->msg.payload_type = KDBUS_PAYLOAD_KERNEL;
+ kmsg->notify_type = type;
+
+ switch (type) {
+ case KDBUS_ITEM_ID_ADD:
+ kmsg->notify_new_id = id;
+ break;
+
+ case KDBUS_ITEM_ID_REMOVE:
+ kmsg->notify_old_id = id;
+ break;
+
+ default:
+ BUG();
+ }
+
+ kmsg->msg.items[0].type = type;
+ kmsg->msg.items[0].id_change.id = id;
+ kmsg->msg.items[0].id_change.flags = flags;
+
+ kdbus_notify_add_tail(kmsg, bus);
+
+ return 0;
+}
+
+/**
+ * kdbus_notify_flush() - send a list of collected messages
+ * @bus: Bus which queues the messages
+ *
+ * The list is empty after sending the messages.
+ */
+void kdbus_notify_flush(struct kdbus_bus *bus)
+{
+ LIST_HEAD(notify_list);
+ struct kdbus_kmsg *kmsg, *tmp;
+
+ mutex_lock(&bus->notify_flush_lock);
+ down_read(&bus->name_registry->rwlock);
+
+ spin_lock(&bus->notify_lock);
+ list_splice_init(&bus->notify_list, &notify_list);
+ spin_unlock(&bus->notify_lock);
+
+ list_for_each_entry_safe(kmsg, tmp, &notify_list, notify_entry) {
+ kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, NULL,
+ KDBUS_ATTACH_TIMESTAMP);
+
+ if (kmsg->msg.dst_id != KDBUS_DST_ID_BROADCAST) {
+ struct kdbus_conn *conn;
+
+ conn = kdbus_bus_find_conn_by_id(bus, kmsg->msg.dst_id);
+ if (conn) {
+ kdbus_bus_eavesdrop(bus, NULL, kmsg);
+ kdbus_conn_entry_insert(NULL, conn, kmsg, NULL);
+ kdbus_conn_unref(conn);
+ }
+ } else {
+ kdbus_bus_broadcast(bus, NULL, kmsg);
+ }
+
+ list_del(&kmsg->notify_entry);
+ kdbus_kmsg_free(kmsg);
+ }
+
+ up_read(&bus->name_registry->rwlock);
+ mutex_unlock(&bus->notify_flush_lock);
+}
+
+/**
+ * kdbus_notify_free() - free a list of collected messages
+ * @bus: Bus which queues the messages
+ */
+void kdbus_notify_free(struct kdbus_bus *bus)
+{
+ struct kdbus_kmsg *kmsg, *tmp;
+
+ list_for_each_entry_safe(kmsg, tmp, &bus->notify_list, notify_entry) {
+ list_del(&kmsg->notify_entry);
+ kdbus_kmsg_free(kmsg);
+ }
+}
diff --git a/ipc/kdbus/notify.h b/ipc/kdbus/notify.h
new file mode 100644
index 000000000000..03df464cb735
--- /dev/null
+++ b/ipc/kdbus/notify.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __KDBUS_NOTIFY_H
+#define __KDBUS_NOTIFY_H
+
+struct kdbus_bus;
+
+int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags);
+int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie);
+int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie);
+int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type,
+ u64 old_id, u64 new_id,
+ u64 old_flags, u64 new_flags,
+ const char *name);
+void kdbus_notify_flush(struct kdbus_bus *bus);
+void kdbus_notify_free(struct kdbus_bus *bus);
+
+#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,822 @@
From: Daniel Mack <daniel@zonque.org>
Date: Thu, 11 Sep 2014 18:56:41 +0200
Subject: [PATCH] kdbus: add connection pool implementation
A pool for data received from the kernel is installed for every
connection of the bus, and it is used to copy data from the kernel to
userspace clients, for messages and other information.
It is accessed when one of the following ioctls is issued:
* KDBUS_CMD_MSG_RECV, to receive a message
* KDBUS_CMD_NAME_LIST, to dump the name registry
* KDBUS_CMD_CONN_INFO, to retrieve information on a connection
The offsets returned by either one of the aforementioned ioctls
describe offsets inside the pool. Internally, the pool is organized in
slices, that are dynamically allocated on demand. The overall size of
the pool is chosen by the connection when it connects to the bus with
KDBUS_CMD_HELLO.
In order to make the slice available for subsequent calls,
KDBUS_CMD_FREE has to be called on the offset.
To access the memory, the caller is expected to mmap() it to its task.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/pool.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
ipc/kdbus/pool.h | 46 ++++
2 files changed, 774 insertions(+)
create mode 100644 ipc/kdbus/pool.c
create mode 100644 ipc/kdbus/pool.h
diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c
new file mode 100644
index 000000000000..139bb77056b3
--- /dev/null
+++ b/ipc/kdbus/pool.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/aio.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/shmem_fs.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/uio.h>
+
+#include "pool.h"
+#include "util.h"
+
+/**
+ * struct kdbus_pool - the receiver's buffer
+ * @f: The backing shmem file
+ * @size: The size of the file
+ * @accounted_size: Currently accounted memory in bytes
+ * @lock: Pool data lock
+ * @slices: All slices sorted by address
+ * @slices_busy: Tree of allocated slices
+ * @slices_free: Tree of free slices
+ *
+ * The receiver's buffer, managed as a pool of allocated and free
+ * slices containing the queued messages.
+ *
+ * Messages sent with KDBUS_CMD_SEND are copied direcly by the
+ * sending process into the receiver's pool.
+ *
+ * Messages received with KDBUS_CMD_RECV just return the offset
+ * to the data placed in the pool.
+ *
+ * The internally allocated memory needs to be returned by the receiver
+ * with KDBUS_CMD_FREE.
+ */
+struct kdbus_pool {
+ struct file *f;
+ size_t size;
+ size_t accounted_size;
+ struct mutex lock;
+
+ struct list_head slices;
+ struct rb_root slices_busy;
+ struct rb_root slices_free;
+};
+
+/**
+ * struct kdbus_pool_slice - allocated element in kdbus_pool
+ * @pool: Pool this slice belongs to
+ * @off: Offset of slice in the shmem file
+ * @size: Size of slice
+ * @entry: Entry in "all slices" list
+ * @rb_node: Entry in free or busy list
+ * @free: Unused slice
+ * @accounted: Accounted as queue slice
+ * @ref_kernel: Kernel holds a reference
+ * @ref_user: Userspace holds a reference
+ *
+ * The pool has one or more slices, always spanning the entire size of the
+ * pool.
+ *
+ * Every slice is an element in a list sorted by the buffer address, to
+ * provide access to the next neighbor slice.
+ *
+ * Every slice is member in either the busy or the free tree. The free
+ * tree is organized by slice size, the busy tree organized by buffer
+ * offset.
+ */
+struct kdbus_pool_slice {
+ struct kdbus_pool *pool;
+ size_t off;
+ size_t size;
+
+ struct list_head entry;
+ struct rb_node rb_node;
+
+ bool free:1;
+ bool accounted:1;
+ bool ref_kernel:1;
+ bool ref_user:1;
+};
+
+static struct kdbus_pool_slice *kdbus_pool_slice_new(struct kdbus_pool *pool,
+ size_t off, size_t size)
+{
+ struct kdbus_pool_slice *slice;
+
+ slice = kzalloc(sizeof(*slice), GFP_KERNEL);
+ if (!slice)
+ return NULL;
+
+ slice->pool = pool;
+ slice->off = off;
+ slice->size = size;
+ slice->free = true;
+ return slice;
+}
+
+/* insert a slice into the free tree */
+static void kdbus_pool_add_free_slice(struct kdbus_pool *pool,
+ struct kdbus_pool_slice *slice)
+{
+ struct rb_node **n;
+ struct rb_node *pn = NULL;
+
+ n = &pool->slices_free.rb_node;
+ while (*n) {
+ struct kdbus_pool_slice *pslice;
+
+ pn = *n;
+ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node);
+ if (slice->size < pslice->size)
+ n = &pn->rb_left;
+ else
+ n = &pn->rb_right;
+ }
+
+ rb_link_node(&slice->rb_node, pn, n);
+ rb_insert_color(&slice->rb_node, &pool->slices_free);
+}
+
+/* insert a slice into the busy tree */
+static void kdbus_pool_add_busy_slice(struct kdbus_pool *pool,
+ struct kdbus_pool_slice *slice)
+{
+ struct rb_node **n;
+ struct rb_node *pn = NULL;
+
+ n = &pool->slices_busy.rb_node;
+ while (*n) {
+ struct kdbus_pool_slice *pslice;
+
+ pn = *n;
+ pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node);
+ if (slice->off < pslice->off)
+ n = &pn->rb_left;
+ else if (slice->off > pslice->off)
+ n = &pn->rb_right;
+ else
+ BUG();
+ }
+
+ rb_link_node(&slice->rb_node, pn, n);
+ rb_insert_color(&slice->rb_node, &pool->slices_busy);
+}
+
+static struct kdbus_pool_slice *kdbus_pool_find_slice(struct kdbus_pool *pool,
+ size_t off)
+{
+ struct rb_node *n;
+
+ n = pool->slices_busy.rb_node;
+ while (n) {
+ struct kdbus_pool_slice *s;
+
+ s = rb_entry(n, struct kdbus_pool_slice, rb_node);
+ if (off < s->off)
+ n = n->rb_left;
+ else if (off > s->off)
+ n = n->rb_right;
+ else
+ return s;
+ }
+
+ return NULL;
+}
+
+/**
+ * kdbus_pool_slice_alloc() - allocate memory from a pool
+ * @pool: The receiver's pool
+ * @size: The number of bytes to allocate
+ * @accounted: Whether this slice should be accounted for
+ *
+ * The returned slice is used for kdbus_pool_slice_release() to
+ * free the allocated memory. If either @kvec or @iovec is non-NULL, the data
+ * will be copied from kernel or userspace memory into the new slice at
+ * offset 0.
+ *
+ * Return: the allocated slice on success, ERR_PTR on failure.
+ */
+struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
+ size_t size, bool accounted)
+{
+ size_t slice_size = KDBUS_ALIGN8(size);
+ struct rb_node *n, *found = NULL;
+ struct kdbus_pool_slice *s;
+ int ret = 0;
+
+ if (WARN_ON(!size))
+ return ERR_PTR(-EINVAL);
+
+ /* search a free slice with the closest matching size */
+ mutex_lock(&pool->lock);
+ n = pool->slices_free.rb_node;
+ while (n) {
+ s = rb_entry(n, struct kdbus_pool_slice, rb_node);
+ if (slice_size < s->size) {
+ found = n;
+ n = n->rb_left;
+ } else if (slice_size > s->size) {
+ n = n->rb_right;
+ } else {
+ found = n;
+ break;
+ }
+ }
+
+ /* no slice with the minimum size found in the pool */
+ if (!found) {
+ ret = -EXFULL;
+ goto exit_unlock;
+ }
+
+ /* no exact match, use the closest one */
+ if (!n) {
+ struct kdbus_pool_slice *s_new;
+
+ s = rb_entry(found, struct kdbus_pool_slice, rb_node);
+
+ /* split-off the remainder of the size to its own slice */
+ s_new = kdbus_pool_slice_new(pool, s->off + slice_size,
+ s->size - slice_size);
+ if (!s_new) {
+ ret = -ENOMEM;
+ goto exit_unlock;
+ }
+
+ list_add(&s_new->entry, &s->entry);
+ kdbus_pool_add_free_slice(pool, s_new);
+
+ /* adjust our size now that we split-off another slice */
+ s->size = slice_size;
+ }
+
+ /* move slice from free to the busy tree */
+ rb_erase(found, &pool->slices_free);
+ kdbus_pool_add_busy_slice(pool, s);
+
+ WARN_ON(s->ref_kernel || s->ref_user);
+
+ s->ref_kernel = true;
+ s->free = false;
+ s->accounted = accounted;
+ if (accounted)
+ pool->accounted_size += s->size;
+ mutex_unlock(&pool->lock);
+
+ return s;
+
+exit_unlock:
+ mutex_unlock(&pool->lock);
+ return ERR_PTR(ret);
+}
+
+static void __kdbus_pool_slice_release(struct kdbus_pool_slice *slice)
+{
+ struct kdbus_pool *pool = slice->pool;
+
+ /* don't free the slice if either has a reference */
+ if (slice->ref_kernel || slice->ref_user)
+ return;
+
+ if (WARN_ON(slice->free))
+ return;
+
+ rb_erase(&slice->rb_node, &pool->slices_busy);
+
+ /* merge with the next free slice */
+ if (!list_is_last(&slice->entry, &pool->slices)) {
+ struct kdbus_pool_slice *s;
+
+ s = list_entry(slice->entry.next,
+ struct kdbus_pool_slice, entry);
+ if (s->free) {
+ rb_erase(&s->rb_node, &pool->slices_free);
+ list_del(&s->entry);
+ slice->size += s->size;
+ kfree(s);
+ }
+ }
+
+ /* merge with previous free slice */
+ if (pool->slices.next != &slice->entry) {
+ struct kdbus_pool_slice *s;
+
+ s = list_entry(slice->entry.prev,
+ struct kdbus_pool_slice, entry);
+ if (s->free) {
+ rb_erase(&s->rb_node, &pool->slices_free);
+ list_del(&slice->entry);
+ s->size += slice->size;
+ kfree(slice);
+ slice = s;
+ }
+ }
+
+ slice->free = true;
+ kdbus_pool_add_free_slice(pool, slice);
+}
+
+/**
+ * kdbus_pool_slice_release() - drop kernel-reference on allocated slice
+ * @slice: Slice allocated from the pool
+ *
+ * This releases the kernel-reference on the given slice. If the
+ * kernel-reference and the user-reference on a slice are dropped, the slice is
+ * returned to the pool.
+ *
+ * So far, we do not implement full ref-counting on slices. Each, kernel and
+ * user-space can have exactly one reference to a slice. If both are dropped at
+ * the same time, the slice is released.
+ */
+void kdbus_pool_slice_release(struct kdbus_pool_slice *slice)
+{
+ struct kdbus_pool *pool;
+
+ if (!slice)
+ return;
+
+ /* @slice may be freed, so keep local ptr to @pool */
+ pool = slice->pool;
+
+ mutex_lock(&pool->lock);
+ /* kernel must own a ref to @slice to drop it */
+ WARN_ON(!slice->ref_kernel);
+ slice->ref_kernel = false;
+ /* no longer kernel-owned, de-account slice */
+ if (slice->accounted && !WARN_ON(pool->accounted_size < slice->size))
+ pool->accounted_size -= slice->size;
+ __kdbus_pool_slice_release(slice);
+ mutex_unlock(&pool->lock);
+}
+
+/**
+ * kdbus_pool_release_offset() - release a public offset
+ * @pool: pool to operate on
+ * @off: offset to release
+ *
+ * This should be called whenever user-space frees a slice given to them. It
+ * verifies the slice is available and public, and then drops it. It ensures
+ * correct locking and barriers against queues.
+ *
+ * Return: 0 on success, ENXIO if the offset is invalid or not public.
+ */
+int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off)
+{
+ struct kdbus_pool_slice *slice;
+ int ret = 0;
+
+ /* 'pool->size' is used as dummy offset for empty slices */
+ if (off == pool->size)
+ return 0;
+
+ mutex_lock(&pool->lock);
+ slice = kdbus_pool_find_slice(pool, off);
+ if (slice && slice->ref_user) {
+ slice->ref_user = false;
+ __kdbus_pool_slice_release(slice);
+ } else {
+ ret = -ENXIO;
+ }
+ mutex_unlock(&pool->lock);
+
+ return ret;
+}
+
+/**
+ * kdbus_pool_publish_empty() - publish empty slice to user-space
+ * @pool: pool to operate on
+ * @off: output storage for offset, or NULL
+ * @size: output storage for size, or NULL
+ *
+ * This is the same as kdbus_pool_slice_publish(), but uses a dummy slice with
+ * size 0. The returned offset points to the end of the pool and is never
+ * returned on real slices.
+ */
+void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size)
+{
+ if (off)
+ *off = pool->size;
+ if (size)
+ *size = 0;
+}
+
+/**
+ * kdbus_pool_slice_publish() - publish slice to user-space
+ * @slice: The slice
+ * @out_offset: Output storage for offset, or NULL
+ * @out_size: Output storage for size, or NULL
+ *
+ * This prepares a slice to be published to user-space.
+ *
+ * This call combines the following operations:
+ * * the memory region is flushed so the user's memory view is consistent
+ * * the slice is marked as referenced by user-space, so user-space has to
+ * call KDBUS_CMD_FREE to release it
+ * * the offset and size of the slice are written to the given output
+ * arguments, if non-NULL
+ */
+void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice,
+ u64 *out_offset, u64 *out_size)
+{
+ mutex_lock(&slice->pool->lock);
+ /* kernel must own a ref to @slice to gain a user-space ref */
+ WARN_ON(!slice->ref_kernel);
+ slice->ref_user = true;
+ mutex_unlock(&slice->pool->lock);
+
+ if (out_offset)
+ *out_offset = slice->off;
+ if (out_size)
+ *out_size = slice->size;
+}
+
+/**
+ * kdbus_pool_slice_offset() - Get a slice's offset inside the pool
+ * @slice: Slice to return the offset of
+ *
+ * Return: The internal offset @slice inside the pool.
+ */
+off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice)
+{
+ return slice->off;
+}
+
+/**
+ * kdbus_pool_slice_size() - get size of a pool slice
+ * @slice: slice to query
+ *
+ * Return: size of the given slice
+ */
+size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice)
+{
+ return slice->size;
+}
+
+/**
+ * kdbus_pool_new() - create a new pool
+ * @name: Name of the (deleted) file which shows up in
+ * /proc, used for debugging
+ * @size: Maximum size of the pool
+ *
+ * Return: a new kdbus_pool on success, ERR_PTR on failure.
+ */
+struct kdbus_pool *kdbus_pool_new(const char *name, size_t size)
+{
+ struct kdbus_pool_slice *s;
+ struct kdbus_pool *p;
+ struct file *f;
+ char *n = NULL;
+ int ret;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+
+ if (name) {
+ n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name);
+ if (!n) {
+ ret = -ENOMEM;
+ goto exit_free;
+ }
+ }
+
+ f = shmem_file_setup(n ?: KBUILD_MODNAME "-conn", size, 0);
+ kfree(n);
+
+ if (IS_ERR(f)) {
+ ret = PTR_ERR(f);
+ goto exit_free;
+ }
+
+ ret = get_write_access(file_inode(f));
+ if (ret < 0)
+ goto exit_put_shmem;
+
+ /* allocate first slice spanning the entire pool */
+ s = kdbus_pool_slice_new(p, 0, size);
+ if (!s) {
+ ret = -ENOMEM;
+ goto exit_put_write;
+ }
+
+ p->f = f;
+ p->size = size;
+ p->slices_free = RB_ROOT;
+ p->slices_busy = RB_ROOT;
+ mutex_init(&p->lock);
+
+ INIT_LIST_HEAD(&p->slices);
+ list_add(&s->entry, &p->slices);
+
+ kdbus_pool_add_free_slice(p, s);
+ return p;
+
+exit_put_write:
+ put_write_access(file_inode(f));
+exit_put_shmem:
+ fput(f);
+exit_free:
+ kfree(p);
+ return ERR_PTR(ret);
+}
+
+/**
+ * kdbus_pool_free() - destroy pool
+ * @pool: The receiver's pool
+ */
+void kdbus_pool_free(struct kdbus_pool *pool)
+{
+ struct kdbus_pool_slice *s, *tmp;
+
+ if (!pool)
+ return;
+
+ list_for_each_entry_safe(s, tmp, &pool->slices, entry) {
+ list_del(&s->entry);
+ kfree(s);
+ }
+
+ put_write_access(file_inode(pool->f));
+ fput(pool->f);
+ kfree(pool);
+}
+
+/**
+ * kdbus_pool_accounted() - retrieve accounting information
+ * @pool: pool to query
+ * @size: output for overall pool size
+ * @acc: output for currently accounted size
+ *
+ * This returns accounting information of the pool. Note that the data might
+ * change after the function returns, as the pool lock is dropped. You need to
+ * protect the data via other means, if you need reliable accounting.
+ */
+void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc)
+{
+ mutex_lock(&pool->lock);
+ if (size)
+ *size = pool->size;
+ if (acc)
+ *acc = pool->accounted_size;
+ mutex_unlock(&pool->lock);
+}
+
+/**
+ * kdbus_pool_slice_copy_iovec() - copy user memory to a slice
+ * @slice: The slice to write to
+ * @off: Offset in the slice to write to
+ * @iov: iovec array, pointing to data to copy
+ * @iov_len: Number of elements in @iov
+ * @total_len: Total number of bytes described in members of @iov
+ *
+ * User memory referenced by @iov will be copied into @slice at offset @off.
+ *
+ * Return: the numbers of bytes copied, negative errno on failure.
+ */
+ssize_t
+kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, loff_t off,
+ struct iovec *iov, size_t iov_len, size_t total_len)
+{
+ struct iov_iter iter;
+ ssize_t len;
+
+ if (WARN_ON(off + total_len > slice->size))
+ return -EFAULT;
+
+ off += slice->off;
+ iov_iter_init(&iter, WRITE, iov, iov_len, total_len);
+ len = vfs_iter_write(slice->pool->f, &iter, &off);
+
+ return (len >= 0 && len != total_len) ? -EFAULT : len;
+}
+
+/**
+ * kdbus_pool_slice_copy_kvec() - copy kernel memory to a slice
+ * @slice: The slice to write to
+ * @off: Offset in the slice to write to
+ * @kvec: kvec array, pointing to data to copy
+ * @kvec_len: Number of elements in @kvec
+ * @total_len: Total number of bytes described in members of @kvec
+ *
+ * Kernel memory referenced by @kvec will be copied into @slice at offset @off.
+ *
+ * Return: the numbers of bytes copied, negative errno on failure.
+ */
+ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice,
+ loff_t off, struct kvec *kvec,
+ size_t kvec_len, size_t total_len)
+{
+ struct iov_iter iter;
+ mm_segment_t old_fs;
+ ssize_t len;
+
+ if (WARN_ON(off + total_len > slice->size))
+ return -EFAULT;
+
+ off += slice->off;
+ iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len);
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+ len = vfs_iter_write(slice->pool->f, &iter, &off);
+ set_fs(old_fs);
+
+ return (len >= 0 && len != total_len) ? -EFAULT : len;
+}
+
+/**
+ * kdbus_pool_slice_copy() - copy data from one slice into another
+ * @slice_dst: destination slice
+ * @slice_src: source slice
+ *
+ * Return: 0 on success, negative error number on failure.
+ */
+int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
+ const struct kdbus_pool_slice *slice_src)
+{
+ struct file *f_src = slice_src->pool->f;
+ struct file *f_dst = slice_dst->pool->f;
+ struct inode *i_dst = file_inode(f_dst);
+ struct address_space *mapping_dst = f_dst->f_mapping;
+ const struct address_space_operations *aops = mapping_dst->a_ops;
+ unsigned long len = slice_src->size;
+ loff_t off_src = slice_src->off;
+ loff_t off_dst = slice_dst->off;
+ mm_segment_t old_fs;
+ int ret = 0;
+
+ if (WARN_ON(slice_src->size != slice_dst->size) ||
+ WARN_ON(slice_src->free || slice_dst->free))
+ return -EINVAL;
+
+ mutex_lock(&i_dst->i_mutex);
+ old_fs = get_fs();
+ set_fs(get_ds());
+ while (len > 0) {
+ unsigned long page_off;
+ unsigned long copy_len;
+ char __user *kaddr;
+ struct page *page;
+ ssize_t n_read;
+ void *fsdata;
+ long status;
+
+ page_off = off_dst & (PAGE_CACHE_SIZE - 1);
+ copy_len = min_t(unsigned long,
+ PAGE_CACHE_SIZE - page_off, len);
+
+ status = aops->write_begin(f_dst, mapping_dst, off_dst,
+ copy_len, 0, &page, &fsdata);
+ if (unlikely(status < 0)) {
+ ret = status;
+ break;
+ }
+
+ kaddr = (char __force __user *)kmap(page) + page_off;
+ n_read = f_src->f_op->read(f_src, kaddr, copy_len, &off_src);
+ kunmap(page);
+ mark_page_accessed(page);
+ flush_dcache_page(page);
+
+ if (unlikely(n_read != copy_len)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ status = aops->write_end(f_dst, mapping_dst, off_dst,
+ copy_len, copy_len, page, fsdata);
+ if (unlikely(status != copy_len)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ off_dst += copy_len;
+ len -= copy_len;
+ }
+ set_fs(old_fs);
+ mutex_unlock(&i_dst->i_mutex);
+
+ return ret;
+}
+
+/**
+ * kdbus_pool_mmap() - map the pool into the process
+ * @pool: The receiver's pool
+ * @vma: passed by mmap() syscall
+ *
+ * Return: the result of the mmap() call, negative errno on failure.
+ */
+int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma)
+{
+ /* deny write access to the pool */
+ if (vma->vm_flags & VM_WRITE)
+ return -EPERM;
+ vma->vm_flags &= ~VM_MAYWRITE;
+
+ /* do not allow to map more than the size of the file */
+ if ((vma->vm_end - vma->vm_start) > pool->size)
+ return -EFAULT;
+
+ /* replace the connection file with our shmem file */
+ if (vma->vm_file)
+ fput(vma->vm_file);
+ vma->vm_file = get_file(pool->f);
+
+ return pool->f->f_op->mmap(pool->f, vma);
+}
diff --git a/ipc/kdbus/pool.h b/ipc/kdbus/pool.h
new file mode 100644
index 000000000000..a9038213aa4d
--- /dev/null
+++ b/ipc/kdbus/pool.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __KDBUS_POOL_H
+#define __KDBUS_POOL_H
+
+#include <linux/uio.h>
+
+struct kdbus_pool;
+struct kdbus_pool_slice;
+
+struct kdbus_pool *kdbus_pool_new(const char *name, size_t size);
+void kdbus_pool_free(struct kdbus_pool *pool);
+void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc);
+int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma);
+int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off);
+void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size);
+
+struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
+ size_t size, bool accounted);
+void kdbus_pool_slice_release(struct kdbus_pool_slice *slice);
+void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice,
+ u64 *out_offset, u64 *out_size);
+off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice);
+size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice);
+int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
+ const struct kdbus_pool_slice *slice_src);
+ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice,
+ loff_t off, struct kvec *kvec,
+ size_t kvec_count, size_t total_len);
+ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice,
+ loff_t off, struct iovec *iov,
+ size_t iov_count, size_t total_len);
+
+#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,883 @@
From: Daniel Mack <daniel@zonque.org>
Date: Thu, 11 Sep 2014 19:00:00 +0200
Subject: [PATCH] kdbus: add name registry implementation
This patch adds the name registry implementation.
Each bus instantiates a name registry to resolve well-known names
into unique connection IDs for message delivery. The registry will
be queried when a message is sent with kdbus_msg.dst_id set to
KDBUS_DST_ID_NAME, or when a registry dump is requested.
It's important to have this registry implemented in the kernel to
implement lookups and take-overs in a race-free way.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/names.c | 772 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
ipc/kdbus/names.h | 74 ++++++
2 files changed, 846 insertions(+)
create mode 100644 ipc/kdbus/names.c
create mode 100644 ipc/kdbus/names.h
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
new file mode 100644
index 000000000000..657008e1bb37
--- /dev/null
+++ b/ipc/kdbus/names.c
@@ -0,0 +1,772 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/hash.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/uio.h>
+
+#include "bus.h"
+#include "connection.h"
+#include "endpoint.h"
+#include "handle.h"
+#include "item.h"
+#include "names.h"
+#include "notify.h"
+#include "policy.h"
+
+struct kdbus_name_pending {
+ u64 flags;
+ struct kdbus_conn *conn;
+ struct kdbus_name_entry *name;
+ struct list_head conn_entry;
+ struct list_head name_entry;
+};
+
+static int kdbus_name_pending_new(struct kdbus_name_entry *e,
+ struct kdbus_conn *conn, u64 flags)
+{
+ struct kdbus_name_pending *p;
+
+ kdbus_conn_assert_active(conn);
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->flags = flags;
+ p->conn = conn;
+ p->name = e;
+ list_add_tail(&p->conn_entry, &conn->names_queue_list);
+ list_add_tail(&p->name_entry, &e->queue);
+
+ return 0;
+}
+
+static void kdbus_name_pending_free(struct kdbus_name_pending *p)
+{
+ if (!p)
+ return;
+
+ list_del(&p->name_entry);
+ list_del(&p->conn_entry);
+ kfree(p);
+}
+
+static struct kdbus_name_entry *
+kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash, const char *name)
+{
+ struct kdbus_name_entry *e;
+ size_t namelen;
+
+ namelen = strlen(name);
+
+ e = kmalloc(sizeof(*e) + namelen + 1, GFP_KERNEL);
+ if (!e)
+ return ERR_PTR(-ENOMEM);
+
+ e->name_id = ++r->name_seq_last;
+ e->flags = 0;
+ e->conn = NULL;
+ e->activator = NULL;
+ INIT_LIST_HEAD(&e->queue);
+ INIT_LIST_HEAD(&e->conn_entry);
+ hash_add(r->entries_hash, &e->hentry, hash);
+ memcpy(e->name, name, namelen + 1);
+
+ return e;
+}
+
+static void kdbus_name_entry_free(struct kdbus_name_entry *e)
+{
+ if (!e)
+ return;
+
+ WARN_ON(!list_empty(&e->conn_entry));
+ WARN_ON(!list_empty(&e->queue));
+ WARN_ON(e->activator);
+ WARN_ON(e->conn);
+
+ hash_del(&e->hentry);
+ kfree(e);
+}
+
+static void kdbus_name_entry_set_owner(struct kdbus_name_entry *e,
+ struct kdbus_conn *conn, u64 flags)
+{
+ WARN_ON(e->conn);
+
+ e->conn = kdbus_conn_ref(conn);
+ e->flags = flags;
+ atomic_inc(&conn->name_count);
+ list_add_tail(&e->conn_entry, &e->conn->names_list);
+}
+
+static void kdbus_name_entry_remove_owner(struct kdbus_name_entry *e)
+{
+ WARN_ON(!e->conn);
+
+ list_del_init(&e->conn_entry);
+ atomic_dec(&e->conn->name_count);
+ e->flags = 0;
+ e->conn = kdbus_conn_unref(e->conn);
+}
+
+static void kdbus_name_entry_replace_owner(struct kdbus_name_entry *e,
+ struct kdbus_conn *conn, u64 flags)
+{
+ if (WARN_ON(!e->conn) || WARN_ON(conn == e->conn))
+ return;
+
+ kdbus_notify_name_change(conn->ep->bus, KDBUS_ITEM_NAME_CHANGE,
+ e->conn->id, conn->id,
+ e->flags, flags, e->name);
+ kdbus_name_entry_remove_owner(e);
+ kdbus_name_entry_set_owner(e, conn, flags);
+}
+
+/**
+ * kdbus_name_is_valid() - check if a name is valid
+ * @p: The name to check
+ * @allow_wildcard: Whether or not to allow a wildcard name
+ *
+ * A name is valid if all of the following criterias are met:
+ *
+ * - The name has two or more elements separated by a period ('.') character.
+ * - All elements must contain at least one character.
+ * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-"
+ * and must not begin with a digit.
+ * - The name must not exceed KDBUS_NAME_MAX_LEN.
+ * - If @allow_wildcard is true, the name may end on '.*'
+ */
+bool kdbus_name_is_valid(const char *p, bool allow_wildcard)
+{
+ bool dot, found_dot = false;
+ const char *q;
+
+ for (dot = true, q = p; *q; q++) {
+ if (*q == '.') {
+ if (dot)
+ return false;
+
+ found_dot = true;
+ dot = true;
+ } else {
+ bool good;
+
+ good = isalpha(*q) || (!dot && isdigit(*q)) ||
+ *q == '_' || *q == '-' ||
+ (allow_wildcard && dot &&
+ *q == '*' && *(q + 1) == '\0');
+
+ if (!good)
+ return false;
+
+ dot = false;
+ }
+ }
+
+ if (q - p > KDBUS_NAME_MAX_LEN)
+ return false;
+
+ if (dot)
+ return false;
+
+ if (!found_dot)
+ return false;
+
+ return true;
+}
+
+/**
+ * kdbus_name_registry_new() - create a new name registry
+ *
+ * Return: a new kdbus_name_registry on success, ERR_PTR on failure.
+ */
+struct kdbus_name_registry *kdbus_name_registry_new(void)
+{
+ struct kdbus_name_registry *r;
+
+ r = kmalloc(sizeof(*r), GFP_KERNEL);
+ if (!r)
+ return ERR_PTR(-ENOMEM);
+
+ hash_init(r->entries_hash);
+ init_rwsem(&r->rwlock);
+ r->name_seq_last = 0;
+
+ return r;
+}
+
+/**
+ * kdbus_name_registry_free() - drop a name reg's reference
+ * @reg: The name registry, may be %NULL
+ *
+ * Cleanup the name registry's internal structures.
+ */
+void kdbus_name_registry_free(struct kdbus_name_registry *reg)
+{
+ if (!reg)
+ return;
+
+ WARN_ON(!hash_empty(reg->entries_hash));
+ kfree(reg);
+}
+
+static struct kdbus_name_entry *
+kdbus_name_find(struct kdbus_name_registry *reg, u32 hash, const char *name)
+{
+ struct kdbus_name_entry *e;
+
+ lockdep_assert_held(&reg->rwlock);
+
+ hash_for_each_possible(reg->entries_hash, e, hentry, hash)
+ if (strcmp(e->name, name) == 0)
+ return e;
+
+ return NULL;
+}
+
+/**
+ * kdbus_name_lookup_unlocked() - lookup name in registry
+ * @reg: name registry
+ * @name: name to lookup
+ *
+ * This looks up @name in the given name-registry and returns the
+ * kdbus_name_entry object. The caller must hold the registry-lock and must not
+ * access the returned object after releasing the lock.
+ *
+ * Return: Pointer to name-entry, or NULL if not found.
+ */
+struct kdbus_name_entry *
+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name)
+{
+ return kdbus_name_find(reg, kdbus_strhash(name), name);
+}
+
+/**
+ * kdbus_name_acquire() - acquire a name
+ * @reg: The name registry
+ * @conn: The connection to pin this entry to
+ * @name: The name to acquire
+ * @flags: Acquisition flags (KDBUS_NAME_*)
+ * @return_flags: Pointer to return flags for the acquired name
+ * (KDBUS_NAME_*), may be %NULL
+ *
+ * Callers must ensure that @conn is either a privileged bus user or has
+ * sufficient privileges in the policy-db to own the well-known name @name.
+ *
+ * Return: 0 success, negative error number on failure.
+ */
+int kdbus_name_acquire(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn, const char *name,
+ u64 flags, u64 *return_flags)
+{
+ struct kdbus_name_entry *e;
+ u64 rflags = 0;
+ int ret = 0;
+ u32 hash;
+
+ kdbus_conn_assert_active(conn);
+
+ down_write(&reg->rwlock);
+
+ if (!kdbus_conn_policy_own_name(conn, current_cred(), name)) {
+ ret = -EPERM;
+ goto exit_unlock;
+ }
+
+ hash = kdbus_strhash(name);
+ e = kdbus_name_find(reg, hash, name);
+ if (!e) {
+ /* claim new name */
+
+ if (conn->activator_of) {
+ ret = -EINVAL;
+ goto exit_unlock;
+ }
+
+ e = kdbus_name_entry_new(reg, hash, name);
+ if (IS_ERR(e)) {
+ ret = PTR_ERR(e);
+ goto exit_unlock;
+ }
+
+ if (kdbus_conn_is_activator(conn)) {
+ e->activator = kdbus_conn_ref(conn);
+ conn->activator_of = e;
+ }
+
+ kdbus_name_entry_set_owner(e, conn, flags);
+ kdbus_notify_name_change(e->conn->ep->bus, KDBUS_ITEM_NAME_ADD,
+ 0, e->conn->id, 0, e->flags, e->name);
+ } else if (e->conn == conn || e == conn->activator_of) {
+ /* connection already owns that name */
+ ret = -EALREADY;
+ } else if (kdbus_conn_is_activator(conn)) {
+ /* activator claims existing name */
+
+ if (conn->activator_of) {
+ ret = -EINVAL; /* multiple names not allowed */
+ } else if (e->activator) {
+ ret = -EEXIST; /* only one activator per name */
+ } else {
+ e->activator = kdbus_conn_ref(conn);
+ conn->activator_of = e;
+ }
+ } else if (e->flags & KDBUS_NAME_ACTIVATOR) {
+ /* claim name of an activator */
+
+ kdbus_conn_move_messages(conn, e->activator, 0);
+ kdbus_name_entry_replace_owner(e, conn, flags);
+ } else if ((flags & KDBUS_NAME_REPLACE_EXISTING) &&
+ (e->flags & KDBUS_NAME_ALLOW_REPLACEMENT)) {
+ /* claim name of a previous owner */
+
+ if (e->flags & KDBUS_NAME_QUEUE) {
+ /* move owner back to queue if they asked for it */
+ ret = kdbus_name_pending_new(e, e->conn, e->flags);
+ if (ret < 0)
+ goto exit_unlock;
+ }
+
+ kdbus_name_entry_replace_owner(e, conn, flags);
+ } else if (flags & KDBUS_NAME_QUEUE) {
+ /* add to waiting-queue of the name */
+
+ ret = kdbus_name_pending_new(e, conn, flags);
+ if (ret >= 0)
+ /* tell the caller that we queued it */
+ rflags |= KDBUS_NAME_IN_QUEUE;
+ } else {
+ /* the name is busy, return a failure */
+ ret = -EEXIST;
+ }
+
+ if (ret == 0 && return_flags)
+ *return_flags = rflags;
+
+exit_unlock:
+ up_write(&reg->rwlock);
+ kdbus_notify_flush(conn->ep->bus);
+ return ret;
+}
+
+static void kdbus_name_release_unlocked(struct kdbus_name_registry *reg,
+ struct kdbus_name_entry *e)
+{
+ struct kdbus_name_pending *p;
+
+ lockdep_assert_held(&reg->rwlock);
+
+ p = list_first_entry_or_null(&e->queue, struct kdbus_name_pending,
+ name_entry);
+
+ if (p) {
+ /* give it to first active waiter in the queue */
+ kdbus_name_entry_replace_owner(e, p->conn, p->flags);
+ kdbus_name_pending_free(p);
+ } else if (e->activator && e->activator != e->conn) {
+ /* hand it back to an active activator connection */
+ kdbus_conn_move_messages(e->activator, e->conn, e->name_id);
+ kdbus_name_entry_replace_owner(e, e->activator,
+ KDBUS_NAME_ACTIVATOR);
+ } else {
+ /* release the name */
+ kdbus_notify_name_change(e->conn->ep->bus,
+ KDBUS_ITEM_NAME_REMOVE,
+ e->conn->id, 0, e->flags, 0, e->name);
+ kdbus_name_entry_remove_owner(e);
+ kdbus_name_entry_free(e);
+ }
+}
+
+static int kdbus_name_release(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn,
+ const char *name)
+{
+ struct kdbus_name_pending *p;
+ struct kdbus_name_entry *e;
+ int ret = 0;
+
+ down_write(&reg->rwlock);
+ e = kdbus_name_find(reg, kdbus_strhash(name), name);
+ if (!e) {
+ ret = -ESRCH;
+ } else if (e->conn == conn) {
+ kdbus_name_release_unlocked(reg, e);
+ } else {
+ ret = -EADDRINUSE;
+ list_for_each_entry(p, &e->queue, name_entry) {
+ if (p->conn == conn) {
+ kdbus_name_pending_free(p);
+ ret = 0;
+ break;
+ }
+ }
+ }
+ up_write(&reg->rwlock);
+
+ kdbus_notify_flush(conn->ep->bus);
+ return ret;
+}
+
+/**
+ * kdbus_name_release_all() - remove all name entries of a given connection
+ * @reg: name registry
+ * @conn: connection
+ */
+void kdbus_name_release_all(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn)
+{
+ struct kdbus_name_pending *p;
+ struct kdbus_conn *activator = NULL;
+ struct kdbus_name_entry *e;
+
+ down_write(&reg->rwlock);
+
+ if (kdbus_conn_is_activator(conn)) {
+ activator = conn->activator_of->activator;
+ conn->activator_of->activator = NULL;
+ }
+
+ while ((p = list_first_entry_or_null(&conn->names_queue_list,
+ struct kdbus_name_pending,
+ conn_entry)))
+ kdbus_name_pending_free(p);
+ while ((e = list_first_entry_or_null(&conn->names_list,
+ struct kdbus_name_entry,
+ conn_entry)))
+ kdbus_name_release_unlocked(reg, e);
+
+ up_write(&reg->rwlock);
+
+ kdbus_conn_unref(activator);
+ kdbus_notify_flush(conn->ep->bus);
+}
+
+/**
+ * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp)
+{
+ const char *item_name;
+ struct kdbus_cmd *cmd;
+ int ret;
+
+ struct kdbus_arg argv[] = {
+ { .type = KDBUS_ITEM_NEGOTIATE },
+ { .type = KDBUS_ITEM_NAME, .mandatory = true },
+ };
+ struct kdbus_args args = {
+ .allowed_flags = KDBUS_FLAG_NEGOTIATE |
+ KDBUS_NAME_REPLACE_EXISTING |
+ KDBUS_NAME_ALLOW_REPLACEMENT |
+ KDBUS_NAME_QUEUE,
+ .argv = argv,
+ .argc = ARRAY_SIZE(argv),
+ };
+
+ if (!kdbus_conn_is_ordinary(conn))
+ return -EOPNOTSUPP;
+
+ ret = kdbus_args_parse(&args, argp, &cmd);
+ if (ret != 0)
+ return ret;
+
+ item_name = argv[1].item->str;
+ if (!kdbus_name_is_valid(item_name, false)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ /*
+ * Do atomic_inc_return here to reserve our slot, then decrement
+ * it before returning.
+ */
+ if (atomic_inc_return(&conn->name_count) > KDBUS_CONN_MAX_NAMES) {
+ ret = -E2BIG;
+ goto exit_dec;
+ }
+
+ ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name,
+ cmd->flags, &cmd->return_flags);
+ if (ret < 0)
+ goto exit_dec;
+
+exit_dec:
+ atomic_dec(&conn->name_count);
+exit:
+ return kdbus_args_clear(&args, ret);
+}
+
+/**
+ * kdbus_cmd_name_release() - handle KDBUS_CMD_NAME_RELEASE
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp)
+{
+ struct kdbus_cmd *cmd;
+ int ret;
+
+ struct kdbus_arg argv[] = {
+ { .type = KDBUS_ITEM_NEGOTIATE },
+ { .type = KDBUS_ITEM_NAME, .mandatory = true },
+ };
+ struct kdbus_args args = {
+ .allowed_flags = KDBUS_FLAG_NEGOTIATE,
+ .argv = argv,
+ .argc = ARRAY_SIZE(argv),
+ };
+
+ if (!kdbus_conn_is_ordinary(conn))
+ return -EOPNOTSUPP;
+
+ ret = kdbus_args_parse(&args, argp, &cmd);
+ if (ret != 0)
+ return ret;
+
+ ret = kdbus_name_release(conn->ep->bus->name_registry, conn,
+ argv[1].item->str);
+ return kdbus_args_clear(&args, ret);
+}
+
+static int kdbus_list_write(struct kdbus_conn *conn,
+ struct kdbus_conn *c,
+ struct kdbus_pool_slice *slice,
+ size_t *pos,
+ struct kdbus_name_entry *e,
+ bool write)
+{
+ struct kvec kvec[4];
+ size_t cnt = 0;
+ int ret;
+
+ /* info header */
+ struct kdbus_info info = {
+ .size = 0,
+ .id = c->id,
+ .flags = c->flags,
+ };
+
+ /* fake the header of a kdbus_name item */
+ struct {
+ u64 size;
+ u64 type;
+ u64 flags;
+ } h = {};
+
+ if (e && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(),
+ e->name))
+ return 0;
+
+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size);
+
+ /* append name */
+ if (e) {
+ size_t slen = strlen(e->name) + 1;
+
+ h.size = offsetof(struct kdbus_item, name.name) + slen;
+ h.type = KDBUS_ITEM_OWNED_NAME;
+ h.flags = e->flags;
+
+ kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size);
+ kdbus_kvec_set(&kvec[cnt++], e->name, slen, &info.size);
+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size);
+ }
+
+ if (write) {
+ ret = kdbus_pool_slice_copy_kvec(slice, *pos, kvec,
+ cnt, info.size);
+ if (ret < 0)
+ return ret;
+ }
+
+ *pos += info.size;
+ return 0;
+}
+
+static int kdbus_list_all(struct kdbus_conn *conn, u64 flags,
+ struct kdbus_pool_slice *slice,
+ size_t *pos, bool write)
+{
+ struct kdbus_conn *c;
+ size_t p = *pos;
+ int ret, i;
+
+ hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) {
+ bool added = false;
+
+ /* skip monitors */
+ if (kdbus_conn_is_monitor(c))
+ continue;
+
+ /* skip activators */
+ if (!(flags & KDBUS_LIST_ACTIVATORS) &&
+ kdbus_conn_is_activator(c))
+ continue;
+
+ /* all names the connection owns */
+ if (flags & (KDBUS_LIST_NAMES | KDBUS_LIST_ACTIVATORS)) {
+ struct kdbus_name_entry *e;
+
+ list_for_each_entry(e, &c->names_list, conn_entry) {
+ struct kdbus_conn *a = e->activator;
+
+ if ((flags & KDBUS_LIST_ACTIVATORS) &&
+ a && a != c) {
+ ret = kdbus_list_write(conn, a, slice,
+ &p, e, write);
+ if (ret < 0) {
+ mutex_unlock(&c->lock);
+ return ret;
+ }
+
+ added = true;
+ }
+
+ if (flags & KDBUS_LIST_NAMES ||
+ kdbus_conn_is_activator(c)) {
+ ret = kdbus_list_write(conn, c, slice,
+ &p, e, write);
+ if (ret < 0) {
+ mutex_unlock(&c->lock);
+ return ret;
+ }
+
+ added = true;
+ }
+ }
+ }
+
+ /* queue of names the connection is currently waiting for */
+ if (flags & KDBUS_LIST_QUEUED) {
+ struct kdbus_name_pending *q;
+
+ list_for_each_entry(q, &c->names_queue_list,
+ conn_entry) {
+ ret = kdbus_list_write(conn, c, slice, &p,
+ q->name, write);
+ if (ret < 0) {
+ mutex_unlock(&c->lock);
+ return ret;
+ }
+
+ added = true;
+ }
+ }
+
+ /* nothing added so far, just add the unique ID */
+ if (!added && flags & KDBUS_LIST_UNIQUE) {
+ ret = kdbus_list_write(conn, c, slice, &p, NULL, write);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ *pos = p;
+ return 0;
+}
+
+/**
+ * kdbus_cmd_list() - handle KDBUS_CMD_LIST
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp)
+{
+ struct kdbus_name_registry *reg = conn->ep->bus->name_registry;
+ struct kdbus_pool_slice *slice = NULL;
+ struct kdbus_cmd_list *cmd;
+ size_t pos, size;
+ int ret;
+
+ struct kdbus_arg argv[] = {
+ { .type = KDBUS_ITEM_NEGOTIATE },
+ };
+ struct kdbus_args args = {
+ .allowed_flags = KDBUS_FLAG_NEGOTIATE |
+ KDBUS_LIST_UNIQUE |
+ KDBUS_LIST_NAMES |
+ KDBUS_LIST_ACTIVATORS |
+ KDBUS_LIST_QUEUED,
+ .argv = argv,
+ .argc = ARRAY_SIZE(argv),
+ };
+
+ ret = kdbus_args_parse(&args, argp, &cmd);
+ if (ret != 0)
+ return ret;
+
+ /* lock order: domain -> bus -> ep -> names -> conn */
+ down_read(&reg->rwlock);
+ down_read(&conn->ep->bus->conn_rwlock);
+ down_read(&conn->ep->policy_db.entries_rwlock);
+
+ /* size of records */
+ size = 0;
+ ret = kdbus_list_all(conn, cmd->flags, NULL, &size, false);
+ if (ret < 0)
+ goto exit_unlock;
+
+ if (size == 0) {
+ kdbus_pool_publish_empty(conn->pool, &cmd->offset,
+ &cmd->list_size);
+ } else {
+ slice = kdbus_pool_slice_alloc(conn->pool, size, false);
+ if (IS_ERR(slice)) {
+ ret = PTR_ERR(slice);
+ slice = NULL;
+ goto exit_unlock;
+ }
+
+ /* copy the records */
+ pos = 0;
+ ret = kdbus_list_all(conn, cmd->flags, slice, &pos, true);
+ if (ret < 0)
+ goto exit_unlock;
+
+ WARN_ON(pos != size);
+ kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->list_size);
+ }
+
+ if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) ||
+ kdbus_member_set_user(&cmd->list_size, argp,
+ typeof(*cmd), list_size))
+ ret = -EFAULT;
+
+exit_unlock:
+ up_read(&conn->ep->policy_db.entries_rwlock);
+ up_read(&conn->ep->bus->conn_rwlock);
+ up_read(&reg->rwlock);
+ kdbus_pool_slice_release(slice);
+ return kdbus_args_clear(&args, ret);
+}
diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h
new file mode 100644
index 000000000000..3dd2589293e0
--- /dev/null
+++ b/ipc/kdbus/names.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __KDBUS_NAMES_H
+#define __KDBUS_NAMES_H
+
+#include <linux/hashtable.h>
+#include <linux/rwsem.h>
+
+/**
+ * struct kdbus_name_registry - names registered for a bus
+ * @entries_hash: Map of entries
+ * @lock: Registry data lock
+ * @name_seq_last: Last used sequence number to assign to a name entry
+ */
+struct kdbus_name_registry {
+ DECLARE_HASHTABLE(entries_hash, 8);
+ struct rw_semaphore rwlock;
+ u64 name_seq_last;
+};
+
+/**
+ * struct kdbus_name_entry - well-know name entry
+ * @name_id: Sequence number of name entry to be able to uniquely
+ * identify a name over its registration lifetime
+ * @flags: KDBUS_NAME_* flags
+ * @conn: Connection owning the name
+ * @activator: Connection of the activator queuing incoming messages
+ * @queue: List of queued connections
+ * @conn_entry: Entry in connection
+ * @hentry: Entry in registry map
+ * @name: The well-known name
+ */
+struct kdbus_name_entry {
+ u64 name_id;
+ u64 flags;
+ struct kdbus_conn *conn;
+ struct kdbus_conn *activator;
+ struct list_head queue;
+ struct list_head conn_entry;
+ struct hlist_node hentry;
+ char name[];
+};
+
+bool kdbus_name_is_valid(const char *p, bool allow_wildcard);
+
+struct kdbus_name_registry *kdbus_name_registry_new(void);
+void kdbus_name_registry_free(struct kdbus_name_registry *reg);
+
+struct kdbus_name_entry *
+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name);
+
+int kdbus_name_acquire(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn, const char *name,
+ u64 flags, u64 *return_flags);
+void kdbus_name_release_all(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn);
+
+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp);
+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp);
+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp);
+
+#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,585 @@
From: Daniel Mack <daniel@zonque.org>
Date: Thu, 11 Sep 2014 19:00:43 +0200
Subject: [PATCH] kdbus: add policy database implementation
This patch adds the policy database implementation.
A policy database restricts the possibilities of connections to own,
see and talk to well-known names. It can be associated with a bus
(through a policy holder connection) or a custom endpoint.
By default, buses have an empty policy database that is augmented on
demand when a policy holder connection is instantiated.
Policies are set through KDBUS_CMD_HELLO (when creating a policy
holder connection), KDBUS_CMD_CONN_UPDATE (when updating a policy
holder connection), KDBUS_CMD_EP_MAKE (creating a custom endpoint)
or KDBUS_CMD_EP_UPDATE (updating a custom endpoint). In all cases,
the name and policy access information is stored in items of type
KDBUS_ITEM_NAME and KDBUS_ITEM_POLICY_ACCESS.
See kdbus.policy(7) for more details.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/policy.c | 489 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ipc/kdbus/policy.h | 51 ++++++
2 files changed, 540 insertions(+)
create mode 100644 ipc/kdbus/policy.c
create mode 100644 ipc/kdbus/policy.h
diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c
new file mode 100644
index 000000000000..dd7fffaafa84
--- /dev/null
+++ b/ipc/kdbus/policy.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ * Copyright (C) 2014-2015 Djalal Harouni
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/dcache.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "bus.h"
+#include "connection.h"
+#include "domain.h"
+#include "item.h"
+#include "names.h"
+#include "policy.h"
+
+#define KDBUS_POLICY_HASH_SIZE 64
+
+/**
+ * struct kdbus_policy_db_entry_access - a database entry access item
+ * @type: One of KDBUS_POLICY_ACCESS_* types
+ * @access: Access to grant. One of KDBUS_POLICY_*
+ * @uid: For KDBUS_POLICY_ACCESS_USER, the global uid
+ * @gid: For KDBUS_POLICY_ACCESS_GROUP, the global gid
+ * @list: List entry item for the entry's list
+ *
+ * This is the internal version of struct kdbus_policy_db_access.
+ */
+struct kdbus_policy_db_entry_access {
+ u8 type; /* USER, GROUP, WORLD */
+ u8 access; /* OWN, TALK, SEE */
+ union {
+ kuid_t uid; /* global uid */
+ kgid_t gid; /* global gid */
+ };
+ struct list_head list;
+};
+
+/**
+ * struct kdbus_policy_db_entry - a policy database entry
+ * @name: The name to match the policy entry against
+ * @hentry: The hash entry for the database's entries_hash
+ * @access_list: List head for keeping tracks of the entry's
+ * access items.
+ * @owner: The owner of this entry. Can be a kdbus_conn or
+ * a kdbus_ep object.
+ * @wildcard: The name is a wildcard, such as ending on '.*'
+ */
+struct kdbus_policy_db_entry {
+ char *name;
+ struct hlist_node hentry;
+ struct list_head access_list;
+ const void *owner;
+ bool wildcard:1;
+};
+
+static void kdbus_policy_entry_free(struct kdbus_policy_db_entry *e)
+{
+ struct kdbus_policy_db_entry_access *a, *tmp;
+
+ list_for_each_entry_safe(a, tmp, &e->access_list, list) {
+ list_del(&a->list);
+ kfree(a);
+ }
+
+ kfree(e->name);
+ kfree(e);
+}
+
+static unsigned int kdbus_strnhash(const char *str, size_t len)
+{
+ unsigned long hash = init_name_hash();
+
+ while (len--)
+ hash = partial_name_hash(*str++, hash);
+
+ return end_name_hash(hash);
+}
+
+static const struct kdbus_policy_db_entry *
+kdbus_policy_lookup(struct kdbus_policy_db *db, const char *name, u32 hash)
+{
+ struct kdbus_policy_db_entry *e;
+ const char *dot;
+ size_t len;
+
+ /* find exact match */
+ hash_for_each_possible(db->entries_hash, e, hentry, hash)
+ if (strcmp(e->name, name) == 0 && !e->wildcard)
+ return e;
+
+ /* find wildcard match */
+
+ dot = strrchr(name, '.');
+ if (!dot)
+ return NULL;
+
+ len = dot - name;
+ hash = kdbus_strnhash(name, len);
+
+ hash_for_each_possible(db->entries_hash, e, hentry, hash)
+ if (e->wildcard && !strncmp(e->name, name, len) &&
+ !e->name[len])
+ return e;
+
+ return NULL;
+}
+
+/**
+ * kdbus_policy_db_clear - release all memory from a policy db
+ * @db: The policy database
+ */
+void kdbus_policy_db_clear(struct kdbus_policy_db *db)
+{
+ struct kdbus_policy_db_entry *e;
+ struct hlist_node *tmp;
+ unsigned int i;
+
+ /* purge entries */
+ down_write(&db->entries_rwlock);
+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) {
+ hash_del(&e->hentry);
+ kdbus_policy_entry_free(e);
+ }
+ up_write(&db->entries_rwlock);
+}
+
+/**
+ * kdbus_policy_db_init() - initialize a new policy database
+ * @db: The location of the database
+ *
+ * This initializes a new policy-db. The underlying memory must have been
+ * cleared to zero by the caller.
+ */
+void kdbus_policy_db_init(struct kdbus_policy_db *db)
+{
+ hash_init(db->entries_hash);
+ init_rwsem(&db->entries_rwlock);
+}
+
+/**
+ * kdbus_policy_query_unlocked() - Query the policy database
+ * @db: Policy database
+ * @cred: Credentials to test against
+ * @name: Name to query
+ * @hash: Hash value of @name
+ *
+ * Same as kdbus_policy_query() but requires the caller to lock the policy
+ * database against concurrent writes.
+ *
+ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none.
+ */
+int kdbus_policy_query_unlocked(struct kdbus_policy_db *db,
+ const struct cred *cred, const char *name,
+ unsigned int hash)
+{
+ struct kdbus_policy_db_entry_access *a;
+ const struct kdbus_policy_db_entry *e;
+ int i, highest = -EPERM;
+
+ e = kdbus_policy_lookup(db, name, hash);
+ if (!e)
+ return -EPERM;
+
+ list_for_each_entry(a, &e->access_list, list) {
+ if ((int)a->access <= highest)
+ continue;
+
+ switch (a->type) {
+ case KDBUS_POLICY_ACCESS_USER:
+ if (uid_eq(cred->euid, a->uid))
+ highest = a->access;
+ break;
+ case KDBUS_POLICY_ACCESS_GROUP:
+ if (gid_eq(cred->egid, a->gid)) {
+ highest = a->access;
+ break;
+ }
+
+ for (i = 0; i < cred->group_info->ngroups; i++) {
+ kgid_t gid = GROUP_AT(cred->group_info, i);
+
+ if (gid_eq(gid, a->gid)) {
+ highest = a->access;
+ break;
+ }
+ }
+
+ break;
+ case KDBUS_POLICY_ACCESS_WORLD:
+ highest = a->access;
+ break;
+ }
+
+ /* OWN is the highest possible policy */
+ if (highest >= KDBUS_POLICY_OWN)
+ break;
+ }
+
+ return highest;
+}
+
+/**
+ * kdbus_policy_query() - Query the policy database
+ * @db: Policy database
+ * @cred: Credentials to test against
+ * @name: Name to query
+ * @hash: Hash value of @name
+ *
+ * Query the policy database @db for the access rights of @cred to the name
+ * @name. The access rights of @cred are returned, or -EPERM if no access is
+ * granted.
+ *
+ * This call effectively searches for the highest access-right granted to
+ * @cred. The caller should really cache those as policy lookups are rather
+ * expensive.
+ *
+ * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none.
+ */
+int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred,
+ const char *name, unsigned int hash)
+{
+ int ret;
+
+ down_read(&db->entries_rwlock);
+ ret = kdbus_policy_query_unlocked(db, cred, name, hash);
+ up_read(&db->entries_rwlock);
+
+ return ret;
+}
+
+static void __kdbus_policy_remove_owner(struct kdbus_policy_db *db,
+ const void *owner)
+{
+ struct kdbus_policy_db_entry *e;
+ struct hlist_node *tmp;
+ int i;
+
+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry)
+ if (e->owner == owner) {
+ hash_del(&e->hentry);
+ kdbus_policy_entry_free(e);
+ }
+}
+
+/**
+ * kdbus_policy_remove_owner() - remove all entries related to a connection
+ * @db: The policy database
+ * @owner: The connection which items to remove
+ */
+void kdbus_policy_remove_owner(struct kdbus_policy_db *db,
+ const void *owner)
+{
+ down_write(&db->entries_rwlock);
+ __kdbus_policy_remove_owner(db, owner);
+ up_write(&db->entries_rwlock);
+}
+
+/*
+ * Convert user provided policy access to internal kdbus policy
+ * access
+ */
+static struct kdbus_policy_db_entry_access *
+kdbus_policy_make_access(const struct kdbus_policy_access *uaccess)
+{
+ int ret;
+ struct kdbus_policy_db_entry_access *a;
+
+ a = kzalloc(sizeof(*a), GFP_KERNEL);
+ if (!a)
+ return ERR_PTR(-ENOMEM);
+
+ ret = -EINVAL;
+ switch (uaccess->access) {
+ case KDBUS_POLICY_SEE:
+ case KDBUS_POLICY_TALK:
+ case KDBUS_POLICY_OWN:
+ a->access = uaccess->access;
+ break;
+ default:
+ goto err;
+ }
+
+ switch (uaccess->type) {
+ case KDBUS_POLICY_ACCESS_USER:
+ a->uid = make_kuid(current_user_ns(), uaccess->id);
+ if (!uid_valid(a->uid))
+ goto err;
+
+ break;
+ case KDBUS_POLICY_ACCESS_GROUP:
+ a->gid = make_kgid(current_user_ns(), uaccess->id);
+ if (!gid_valid(a->gid))
+ goto err;
+
+ break;
+ case KDBUS_POLICY_ACCESS_WORLD:
+ break;
+ default:
+ goto err;
+ }
+
+ a->type = uaccess->type;
+
+ return a;
+
+err:
+ kfree(a);
+ return ERR_PTR(ret);
+}
+
+/**
+ * kdbus_policy_set() - set a connection's policy rules
+ * @db: The policy database
+ * @items: A list of kdbus_item elements that contain both
+ * names and access rules to set.
+ * @items_size: The total size of the items.
+ * @max_policies: The maximum number of policy entries to allow.
+ * Pass 0 for no limit.
+ * @allow_wildcards: Boolean value whether wildcard entries (such
+ * ending on '.*') should be allowed.
+ * @owner: The owner of the new policy items.
+ *
+ * This function sets a new set of policies for a given owner. The names and
+ * access rules are gathered by walking the list of items passed in as
+ * argument. An item of type KDBUS_ITEM_NAME is expected before any number of
+ * KDBUS_ITEM_POLICY_ACCESS items. If there are more repetitions of this
+ * pattern than denoted in @max_policies, -EINVAL is returned.
+ *
+ * In order to allow atomic replacement of rules, the function first removes
+ * all entries that have been created for the given owner previously.
+ *
+ * Callers to this function must make sur that the owner is a custom
+ * endpoint, or if the endpoint is a default endpoint, then it must be
+ * either a policy holder or an activator.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_policy_set(struct kdbus_policy_db *db,
+ const struct kdbus_item *items,
+ size_t items_size,
+ size_t max_policies,
+ bool allow_wildcards,
+ const void *owner)
+{
+ struct kdbus_policy_db_entry_access *a;
+ struct kdbus_policy_db_entry *e, *p;
+ const struct kdbus_item *item;
+ struct hlist_node *tmp;
+ HLIST_HEAD(entries);
+ HLIST_HEAD(restore);
+ size_t count = 0;
+ int i, ret = 0;
+ u32 hash;
+
+ /* Walk the list of items and look for new policies */
+ e = NULL;
+ KDBUS_ITEMS_FOREACH(item, items, items_size) {
+ switch (item->type) {
+ case KDBUS_ITEM_NAME: {
+ size_t len;
+
+ if (max_policies && ++count > max_policies) {
+ ret = -E2BIG;
+ goto exit;
+ }
+
+ if (!kdbus_name_is_valid(item->str, true)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (!e) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ INIT_LIST_HEAD(&e->access_list);
+ e->owner = owner;
+ hlist_add_head(&e->hentry, &entries);
+
+ e->name = kstrdup(item->str, GFP_KERNEL);
+ if (!e->name) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ /*
+ * If a supplied name ends with an '.*', cut off that
+ * part, only store anything before it, and mark the
+ * entry as wildcard.
+ */
+ len = strlen(e->name);
+ if (len > 2 &&
+ e->name[len - 3] == '.' &&
+ e->name[len - 2] == '*') {
+ if (!allow_wildcards) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ e->name[len - 3] = '\0';
+ e->wildcard = true;
+ }
+
+ break;
+ }
+
+ case KDBUS_ITEM_POLICY_ACCESS:
+ if (!e) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ a = kdbus_policy_make_access(&item->policy_access);
+ if (IS_ERR(a)) {
+ ret = PTR_ERR(a);
+ goto exit;
+ }
+
+ list_add_tail(&a->list, &e->access_list);
+ break;
+ }
+ }
+
+ down_write(&db->entries_rwlock);
+
+ /* remember previous entries to restore in case of failure */
+ hash_for_each_safe(db->entries_hash, i, tmp, e, hentry)
+ if (e->owner == owner) {
+ hash_del(&e->hentry);
+ hlist_add_head(&e->hentry, &restore);
+ }
+
+ hlist_for_each_entry_safe(e, tmp, &entries, hentry) {
+ /* prevent duplicates */
+ hash = kdbus_strhash(e->name);
+ hash_for_each_possible(db->entries_hash, p, hentry, hash)
+ if (strcmp(e->name, p->name) == 0 &&
+ e->wildcard == p->wildcard) {
+ ret = -EEXIST;
+ goto restore;
+ }
+
+ hlist_del(&e->hentry);
+ hash_add(db->entries_hash, &e->hentry, hash);
+ }
+
+restore:
+ /* if we failed, flush all entries we added so far */
+ if (ret < 0)
+ __kdbus_policy_remove_owner(db, owner);
+
+ /* if we failed, restore entries, otherwise release them */
+ hlist_for_each_entry_safe(e, tmp, &restore, hentry) {
+ hlist_del(&e->hentry);
+ if (ret < 0) {
+ hash = kdbus_strhash(e->name);
+ hash_add(db->entries_hash, &e->hentry, hash);
+ } else {
+ kdbus_policy_entry_free(e);
+ }
+ }
+
+ up_write(&db->entries_rwlock);
+
+exit:
+ hlist_for_each_entry_safe(e, tmp, &entries, hentry) {
+ hlist_del(&e->hentry);
+ kdbus_policy_entry_free(e);
+ }
+
+ return ret;
+}
diff --git a/ipc/kdbus/policy.h b/ipc/kdbus/policy.h
new file mode 100644
index 000000000000..15dd7bc12068
--- /dev/null
+++ b/ipc/kdbus/policy.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ * Copyright (C) 2013-2015 Linux Foundation
+ *
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __KDBUS_POLICY_H
+#define __KDBUS_POLICY_H
+
+#include <linux/hashtable.h>
+#include <linux/rwsem.h>
+
+struct kdbus_conn;
+struct kdbus_item;
+
+/**
+ * struct kdbus_policy_db - policy database
+ * @entries_hash: Hashtable of entries
+ * @entries_rwlock: Mutex to protect the database's access entries
+ */
+struct kdbus_policy_db {
+ DECLARE_HASHTABLE(entries_hash, 6);
+ struct rw_semaphore entries_rwlock;
+};
+
+void kdbus_policy_db_init(struct kdbus_policy_db *db);
+void kdbus_policy_db_clear(struct kdbus_policy_db *db);
+
+int kdbus_policy_query_unlocked(struct kdbus_policy_db *db,
+ const struct cred *cred, const char *name,
+ unsigned int hash);
+int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred,
+ const char *name, unsigned int hash);
+
+void kdbus_policy_remove_owner(struct kdbus_policy_db *db,
+ const void *owner);
+int kdbus_policy_set(struct kdbus_policy_db *db,
+ const struct kdbus_item *items,
+ size_t items_size,
+ size_t max_policies,
+ bool allow_wildcards,
+ const void *owner);
+
+#endif

11448
kdbus-add-selftests.patch Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
From: Arnd Bergmann <arnd@arndb.de>
Date: Fri, 10 Apr 2015 13:43:37 +0200
Subject: [PATCH] kdbus: avoid the use of struct timespec
I did a routine check for new users of 'timespec', which we are trying to remove
from the kernel in order to survive y2038. kdbus came up and looks particularly
trivial to clean up.
This changes the three ktime_get_ts() variants used in kdbus to ktime_get_ns(),
which aside from removing timespec also simplifies the code and makes it
slightly more efficient by avoiding a two-way conversion.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/metadata.c | 9 ++-------
ipc/kdbus/reply.c | 4 +---
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index 06e0a54a276a..3adc6c2c2e76 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -678,13 +678,8 @@ struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc)
static void kdbus_meta_conn_collect_timestamp(struct kdbus_meta_conn *mc,
struct kdbus_kmsg *kmsg)
{
- struct timespec ts;
-
- ktime_get_ts(&ts);
- mc->ts.monotonic_ns = timespec_to_ns(&ts);
-
- ktime_get_real_ts(&ts);
- mc->ts.realtime_ns = timespec_to_ns(&ts);
+ mc->ts.monotonic_ns = ktime_get_ns();
+ mc->ts.realtime_ns = ktime_get_real_ns();
if (kmsg)
mc->ts.seqnum = kmsg->seq;
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
index 6b3bd81bbb4d..008dca801627 100644
--- a/ipc/kdbus/reply.c
+++ b/ipc/kdbus/reply.c
@@ -204,11 +204,9 @@ void kdbus_reply_list_scan_work(struct work_struct *work)
container_of(work, struct kdbus_conn, work.work);
struct kdbus_reply *reply, *reply_tmp;
u64 deadline = ~0ULL;
- struct timespec64 ts;
u64 now;
- ktime_get_ts64(&ts);
- now = timespec64_to_ns(&ts);
+ now = ktime_get_ns();
mutex_lock(&conn->lock);
if (!kdbus_conn_active(conn)) {

View File

@ -0,0 +1,36 @@
From: Daniel Mack <daniel@zonque.org>
Date: Tue, 17 Mar 2015 19:48:24 +0100
Subject: [PATCH] kdbus: connection: fix handling of failed fget()
The patch 5fc8dd5c84fc: "kdbus: add connection, queue handling and
message validation code" from Sep 11, 2014, leads to the following
static checker warning:
ipc/kdbus/connection.c:2000 kdbus_cmd_send()
warn: 'cancel_fd' isn't an ERR_PTR
Fix this by checking for NULL pointers returned from fget().
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/connection.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index e554f1a71aa1..ab476fa9ccca 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -1997,9 +1997,8 @@ int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp)
if (argv[1].item) {
cancel_fd = fget(argv[1].item->fds[0]);
- if (IS_ERR(cancel_fd)) {
- ret = PTR_ERR(cancel_fd);
- cancel_fd = NULL;
+ if (!cancel_fd) {
+ ret = -EBADF;
goto exit;
}

View File

@ -0,0 +1,167 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 20 Apr 2015 16:20:59 +0200
Subject: [PATCH] kdbus: copy small ioctl payloads to stack
Right now, we use memdup_user() on all ioctl payloads. However, most of
the time an ioctl payload is pretty small. 512 bytes on stack seem
reasonable (similar to what poll() does) to speed up small ioctl payloads.
Add a command-buffer to kdbus_args and use it instead of kmalloc() for
reasonably small payloads.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/handle.c | 30 ++++++++++++++++++++++++++----
ipc/kdbus/handle.h | 5 +++++
ipc/kdbus/util.c | 45 ---------------------------------------------
ipc/kdbus/util.h | 1 -
4 files changed, 31 insertions(+), 50 deletions(-)
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
index 6230c7ef4347..07527990a051 100644
--- a/ipc/kdbus/handle.c
+++ b/ipc/kdbus/handle.c
@@ -146,11 +146,32 @@ static int kdbus_args_negotiate(struct kdbus_args *args)
int __kdbus_args_parse(struct kdbus_args *args, void __user *argp,
size_t type_size, size_t items_offset, void **out)
{
+ u64 user_size;
int ret, i;
- args->cmd = kdbus_memdup_user(argp, type_size, KDBUS_CMD_MAX_SIZE);
- if (IS_ERR(args->cmd))
- return PTR_ERR(args->cmd);
+ ret = kdbus_copy_from_user(&user_size, argp, sizeof(user_size));
+ if (ret < 0)
+ return ret;
+
+ if (user_size < type_size)
+ return -EINVAL;
+ if (user_size > KDBUS_CMD_MAX_SIZE)
+ return -EMSGSIZE;
+
+ if (user_size <= sizeof(args->cmd_buf)) {
+ if (copy_from_user(args->cmd_buf, argp, user_size))
+ return -EFAULT;
+ args->cmd = (void*)args->cmd_buf;
+ } else {
+ args->cmd = memdup_user(argp, user_size);
+ if (IS_ERR(args->cmd))
+ return PTR_ERR(args->cmd);
+ }
+
+ if (args->cmd->size != user_size) {
+ ret = -EINVAL;
+ goto error;
+ }
args->cmd->return_flags = 0;
args->user = argp;
@@ -207,7 +228,8 @@ int kdbus_args_clear(struct kdbus_args *args, int ret)
if (put_user(args->cmd->return_flags,
&args->user->return_flags))
ret = -EFAULT;
- kfree(args->cmd);
+ if (args->cmd != (void*)args->cmd_buf)
+ kfree(args->cmd);
args->cmd = NULL;
}
diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h
index 93a372d554a2..13c59d975728 100644
--- a/ipc/kdbus/handle.h
+++ b/ipc/kdbus/handle.h
@@ -45,6 +45,7 @@ struct kdbus_arg {
* @argv: array of items this command supports
* @user: set by parser to user-space location of current command
* @cmd: set by parser to kernel copy of command payload
+ * @cmd_buf: 512 bytes inline buf to avoid kmalloc() on small cmds
* @items: points to item array in @cmd
* @items_size: size of @items in bytes
*
@@ -52,6 +53,9 @@ struct kdbus_arg {
* The ioctl handler has to pre-fill the flags and allowed items before passing
* the object to kdbus_args_parse(). The parser will copy the command payload
* into kernel-space and verify the correctness of the data.
+ *
+ * We use a 512 bytes buffer for small command payloads, to be allocated on
+ * stack on syscall entrance.
*/
struct kdbus_args {
u64 allowed_flags;
@@ -60,6 +64,7 @@ struct kdbus_args {
struct kdbus_cmd __user *user;
struct kdbus_cmd *cmd;
+ u8 cmd_buf[512];
struct kdbus_item *items;
size_t items_size;
diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c
index eaa806a27997..72b188330896 100644
--- a/ipc/kdbus/util.c
+++ b/ipc/kdbus/util.c
@@ -50,51 +50,6 @@ int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size)
}
/**
- * kdbus_memdup_user() - copy dynamically sized object from user-space
- * @user_ptr: user-provided source buffer
- * @sz_min: minimum object size
- * @sz_max: maximum object size
- *
- * This copies a dynamically sized object from user-space into kernel-space. We
- * require the object to have a 64bit size field at offset 0. We read it out
- * first, allocate a suitably sized buffer and then copy all data.
- *
- * The @sz_min and @sz_max parameters define possible min and max object sizes
- * so user-space cannot trigger un-bound kernel-space allocations.
- *
- * The same alignment-restrictions as described in kdbus_copy_from_user() apply.
- *
- * Return: pointer to dynamically allocated copy, or ERR_PTR() on failure.
- */
-void *kdbus_memdup_user(void __user *user_ptr, size_t sz_min, size_t sz_max)
-{
- void *ptr;
- u64 size;
- int ret;
-
- ret = kdbus_copy_from_user(&size, user_ptr, sizeof(size));
- if (ret < 0)
- return ERR_PTR(ret);
-
- if (size < sz_min)
- return ERR_PTR(-EINVAL);
-
- if (size > sz_max)
- return ERR_PTR(-EMSGSIZE);
-
- ptr = memdup_user(user_ptr, size);
- if (IS_ERR(ptr))
- return ptr;
-
- if (*(u64 *)ptr != size) {
- kfree(ptr);
- return ERR_PTR(-EINVAL);
- }
-
- return ptr;
-}
-
-/**
* kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name
* @name: user-supplied name to verify
* @user_ns: user-namespace to act in
diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h
index 740b19880985..9fedf8ab41cd 100644
--- a/ipc/kdbus/util.h
+++ b/ipc/kdbus/util.h
@@ -64,7 +64,6 @@ int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns,
int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags);
int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size);
-void *kdbus_memdup_user(void __user *user_ptr, size_t sz_min, size_t sz_max);
struct kvec;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Wed, 22 Apr 2015 19:31:50 +0200
Subject: [PATCH] kdbus: drop obsolete WARN_ON
entry->user is never set to an error-code. Drop the obsolete WARN_ON which
is a leftover from before the quota rework.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/queue.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c
index a449464a3975..25bb3ad66b98 100644
--- a/ipc/kdbus/queue.c
+++ b/ipc/kdbus/queue.c
@@ -637,7 +637,7 @@ int kdbus_queue_entry_move(struct kdbus_queue_entry *e,
lockdep_assert_held(&src->lock);
lockdep_assert_held(&dst->lock);
- if (WARN_ON(IS_ERR(e->user)) || WARN_ON(list_empty(&e->entry)))
+ if (WARN_ON(list_empty(&e->entry)))
return -EINVAL;
if (src == dst)
return 0;

View File

@ -0,0 +1,24 @@
From: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
Date: Fri, 5 Jun 2015 14:37:34 +0200
Subject: [PATCH] kdbus: drop useless goto
Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/names.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
index 5f5d84ea0e8e..d77ee08afeda 100644
--- a/ipc/kdbus/names.c
+++ b/ipc/kdbus/names.c
@@ -514,8 +514,6 @@ int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp)
ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name,
cmd->flags, &cmd->return_flags);
- if (ret < 0)
- goto exit_dec;
exit_dec:
atomic_dec(&conn->name_count);

View File

@ -0,0 +1,36 @@
From: Lucas De Marchi <lucas.demarchi@intel.com>
Date: Tue, 17 Mar 2015 09:21:42 -0300
Subject: [PATCH] kdbus: fix header guard name
UAPI headers have a _UAPI_ as prefix, which is removed during
headers_install. If it's put as a suffix it will not be removed and will
be the only header with UAPI in the header guard macro.
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/uapi/linux/kdbus.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h
index fc1d77dd7c93..2fe0a1c5056c 100644
--- a/include/uapi/linux/kdbus.h
+++ b/include/uapi/linux/kdbus.h
@@ -5,8 +5,8 @@
* your option) any later version.
*/
-#ifndef _KDBUS_UAPI_H_
-#define _KDBUS_UAPI_H_
+#ifndef _UAPI_KDBUS_H_
+#define _UAPI_KDBUS_H_
#include <linux/ioctl.h>
#include <linux/types.h>
@@ -976,4 +976,4 @@ enum kdbus_ioctl_type {
struct kdbus_cmd_match),
};
-#endif /* _KDBUS_UAPI_H_ */
+#endif /* _UAPI_KDBUS_H_ */

View File

@ -0,0 +1,27 @@
From: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
Date: Sun, 15 Mar 2015 13:13:08 +0800
Subject: [PATCH] kdbus: fix minor typo in the walk-through example
s/receveiver/receiver/
Signed-off-by: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/kdbus/kdbus-workers.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c
index d1d8f7a7697b..d331e0186899 100644
--- a/samples/kdbus/kdbus-workers.c
+++ b/samples/kdbus/kdbus-workers.c
@@ -787,8 +787,8 @@ static int child_run(struct child *c)
* The 2nd item contains a vector to memory we want to send. It
* can be content of any type. In our case, we're sending a one-byte
* string only. The memory referenced by this item will be copied into
- * the pool of the receveiver connection, and does not need to be
- * valid after the command is employed.
+ * the pool of the receiver connection, and does not need to be valid
+ * after the command is employed.
*/
item = KDBUS_ITEM_NEXT(item);
item->type = KDBUS_ITEM_PAYLOAD_VEC;

View File

@ -0,0 +1,47 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Tue, 9 Jun 2015 23:59:59 +0300
Subject: [PATCH] kdbus: fix operator precedence issues in item macros
`_i' argument in KDBUS_ITEM_NEXT and KDBUS_ITEMS_END macros is not
enclosed into parentheses when the cast operator is applied, which
leads to improper type conversion if `_i' is supplied as a complex
expression, e.g.
KDBUS_ITEM_NEXT(condition ? a : b)
KDBUS_ITEMS_SIZE macro has similar issue, missing parentheses around
`_h' when using indirection operator.
Use parentheses properly to guarantee right precedence.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/item.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h
index eeefd8beac3b..32909e2e7954 100644
--- a/ipc/kdbus/item.h
+++ b/ipc/kdbus/item.h
@@ -21,8 +21,8 @@
#include "util.h"
/* generic access and iterators over a stream of items */
-#define KDBUS_ITEM_NEXT(_i) (typeof(_i))(((u8 *)_i) + KDBUS_ALIGN8((_i)->size))
-#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*_h), _is))
+#define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size))
+#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is))
#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s))
#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE)
@@ -40,7 +40,7 @@
(u8 *)(_i) >= (u8 *)(_is))
#define KDBUS_ITEMS_END(_i, _is, _s) \
- ((u8 *)_i == ((u8 *)(_is) + KDBUS_ALIGN8(_s)))
+ ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s)))
/**
* struct kdbus_item_header - Describes the fix part of an item

25
kdbus-fix-typo.patch Normal file
View File

@ -0,0 +1,25 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Tue, 26 May 2015 09:29:52 +0200
Subject: [PATCH] kdbus: fix typo
Fix "there" -> "their" typo.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/connection.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index ab476fa9ccca..fb2c6c67c4c1 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -753,7 +753,7 @@ void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u,
*
* kdbus is reliable. That means, we try hard to never lose messages. However,
* memory is limited, so we cannot rely on transmissions to never fail.
- * Therefore, we use quota-limits to let callers know if there unicast message
+ * Therefore, we use quota-limits to let callers know if their unicast message
* cannot be transmitted to a peer. This works fine for unicasts, but for
* broadcasts we cannot make the caller handle the transmission failure.
* Instead, we must let the destination know that it couldn't receive a

View File

@ -0,0 +1,185 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Thu, 23 Apr 2015 10:23:38 +0200
Subject: [PATCH] kdbus: fix up documentation of ioctl handlers
We support feature negotiation on ioctls. As this is not necessarily fully
generic, we indicate this by returning >0 from kdbus_args_parse().
Therefore, all ioctl handlers that forward the return value of
kdbus_args_parse() might also return >0 on negotiation. Which is totally
fine and handled in kdbus_handle_ioctl(). However, the documentation of
the ioctl handlers doesn't reflect that behavior. Fix those up!
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
ipc/kdbus/bus.c | 4 ++--
ipc/kdbus/connection.c | 14 +++++++-------
ipc/kdbus/endpoint.c | 4 ++--
ipc/kdbus/match.c | 4 ++--
ipc/kdbus/names.c | 6 +++---
5 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c
index d5475961b896..bbdf0f2f391e 100644
--- a/ipc/kdbus/bus.c
+++ b/ipc/kdbus/bus.c
@@ -365,7 +365,7 @@ void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
* @domain: domain to operate on
* @argp: command payload
*
- * Return: Newly created bus on success, ERR_PTR on failure.
+ * Return: NULL or newly created bus on success, ERR_PTR on failure.
*/
struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain,
void __user *argp)
@@ -459,7 +459,7 @@ exit:
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp)
{
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index cbfbf3847c24..8ee62fc0bd46 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -1589,7 +1589,7 @@ bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
* @privileged: Whether the caller is privileged
* @argp: Command payload
*
- * Return: Newly created connection on success, ERR_PTR on failure.
+ * Return: NULL or newly created connection on success, ERR_PTR on failure.
*/
struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
void __user *argp)
@@ -1676,7 +1676,7 @@ exit:
*
* The caller must not hold any active reference to @conn or this will deadlock.
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp)
{
@@ -1708,7 +1708,7 @@ int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp)
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
{
@@ -1838,7 +1838,7 @@ exit:
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp)
{
@@ -1935,7 +1935,7 @@ exit:
* @f: file this command was called on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp)
{
@@ -2031,7 +2031,7 @@ exit:
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp)
{
@@ -2154,7 +2154,7 @@ exit:
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp)
{
diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c
index 174d274b113e..9a95a5ea84d7 100644
--- a/ipc/kdbus/endpoint.c
+++ b/ipc/kdbus/endpoint.c
@@ -188,7 +188,7 @@ struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep)
* @bus: bus to operate on
* @argp: command payload
*
- * Return: Newly created endpoint on success, ERR_PTR on failure.
+ * Return: NULL or newly created endpoint on success, ERR_PTR on failure.
*/
struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp)
{
@@ -247,7 +247,7 @@ exit:
* @ep: endpoint to operate on
* @argp: command payload
*
- * Return: Newly created endpoint on success, ERR_PTR on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp)
{
diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c
index 30cec1ca819f..cc083b4211de 100644
--- a/ipc/kdbus/match.c
+++ b/ipc/kdbus/match.c
@@ -368,7 +368,7 @@ static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb,
* are used to match messages from userspace, while the others apply to
* kernel-generated notifications.
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp)
{
@@ -528,7 +528,7 @@ exit:
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp)
{
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
index 657008e1bb37..5f5d84ea0e8e 100644
--- a/ipc/kdbus/names.c
+++ b/ipc/kdbus/names.c
@@ -469,7 +469,7 @@ void kdbus_name_release_all(struct kdbus_name_registry *reg,
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp)
{
@@ -528,7 +528,7 @@ exit:
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp)
{
@@ -699,7 +699,7 @@ static int kdbus_list_all(struct kdbus_conn *conn, u64 flags,
* @conn: connection to operate on
* @argp: command payload
*
- * Return: 0 on success, negative error code on failure.
+ * Return: >=0 on success, negative error code on failure.
*/
int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp)
{

View File

@ -0,0 +1,88 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Tue, 26 May 2015 09:30:14 +0200
Subject: [PATCH] kdbus: forward ID notifications to everyone
Even if you cannot SEE another peer (eg., if you're behind a private
endpoint), the other peer might be able to TALK to you. Therefore, you
might get messages from them. This works mostly fine, with one major
exception, that you cannot track the remote peer. You will not receive ID
notifications for it, thus, you don't get notified when they disconnect.
This is unforunate and breaks sandboxes kdbus peers.
Fix this by forwarding ID notifications to everyone. Note that those
notifications don't carry _any_ useful information, besides the peer ID.
Therefore, even if you should not able to SEE a peer, you will now still
get ID notifications. This does not reveal any additional information on
the remote peer, besides its lifetime. Hence, it should be fine.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/connection.c | 8 +++-----
tools/testing/selftests/kdbus/test-endpoint.c | 13 ++++++++++++-
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index fb2c6c67c4c1..272b991f36f4 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -1588,10 +1588,8 @@ bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
* to a peer if, and only if, that peer can see the name this
* notification is for.
*
- * KDBUS_ITEM_ID_{ADD,REMOVE}: As new peers cannot have names, and all
- * names are dropped before a peer is removed, those notifications
- * cannot be seen on custom endpoints. Thus, we only pass them
- * through on default endpoints.
+ * KDBUS_ITEM_ID_{ADD,REMOVE}: Notifications for ID changes are
+ * broadcast to everyone, to allow tracking peers.
*/
switch (kmsg->notify_type) {
@@ -1603,7 +1601,7 @@ bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
case KDBUS_ITEM_ID_ADD:
case KDBUS_ITEM_ID_REMOVE:
- return !conn->ep->user;
+ return true;
default:
WARN(1, "Invalid type for notification broadcast: %llu\n",
diff --git a/tools/testing/selftests/kdbus/test-endpoint.c b/tools/testing/selftests/kdbus/test-endpoint.c
index dcc6ab91c4e6..34a7be49c482 100644
--- a/tools/testing/selftests/kdbus/test-endpoint.c
+++ b/tools/testing/selftests/kdbus/test-endpoint.c
@@ -255,6 +255,13 @@ int kdbus_test_custom_endpoint(struct kdbus_test_env *env)
ep_conn = kdbus_hello(ep, 0, NULL, 0);
ASSERT_RETURN(ep_conn);
+ /* Check that the reader got the IdAdd notification */
+ ret = kdbus_msg_recv(reader, &msg, NULL);
+ ASSERT_RETURN(ret == 0);
+ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD);
+ ASSERT_RETURN(msg->items[0].id_change.id == ep_conn->id);
+ kdbus_msg_free(msg);
+
/*
* Add a name add match on the endpoint connection, acquire name from
* the unfiltered connection, and make sure the filtered connection
@@ -283,7 +290,7 @@ int kdbus_test_custom_endpoint(struct kdbus_test_env *env)
ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL);
ASSERT_RETURN(ret == -ENXIO);
- /* Check that the reader did not receive anything */
+ /* Check that the reader did not receive the name notification */
ret = kdbus_msg_recv(reader, NULL, NULL);
ASSERT_RETURN(ret == -EAGAIN);
@@ -295,6 +302,10 @@ int kdbus_test_custom_endpoint(struct kdbus_test_env *env)
ret = kdbus_name_release(env->conn, name);
ASSERT_RETURN(ret == 0);
+ /* Check that the reader did not receive the name notification */
+ ret = kdbus_msg_recv(reader, NULL, NULL);
+ ASSERT_RETURN(ret == -EAGAIN);
+
ret = update_endpoint(ep_fd, name);
ASSERT_RETURN(ret == 0);

View File

@ -0,0 +1,27 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Tue, 2 Jun 2015 18:48:50 +0300
Subject: [PATCH] kdbus: kdbus_conn_connect(): use `bus' instead of
`conn->ep->bus'
Local `bus' is already set to `conn->ep->bus'. Use it.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/connection.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index 1bd7bb968f9f..707be050b408 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -432,7 +432,7 @@ static int kdbus_conn_connect(struct kdbus_conn *conn, const char *name)
* directly, and won't cause any notifications.
*/
if (!kdbus_conn_is_monitor(conn)) {
- ret = kdbus_notify_id_change(conn->ep->bus, KDBUS_ITEM_ID_ADD,
+ ret = kdbus_notify_id_change(bus, KDBUS_ITEM_ID_ADD,
conn->id, conn->flags);
if (ret < 0)
goto exit_disconnect;

View File

@ -0,0 +1,31 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Tue, 2 Jun 2015 18:48:49 +0300
Subject: [PATCH] kdbus: kdbus_item_validate(): remove duplicated code
KDBUS_ITEM_PAYLOAD_VEC and KDBUS_ITEM_PAYLOAD_OFF cases use literally
the same code, so merge them.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/item.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c
index 745ad5495096..1ee72c2ad7c3 100644
--- a/ipc/kdbus/item.c
+++ b/ipc/kdbus/item.c
@@ -96,12 +96,6 @@ int kdbus_item_validate(const struct kdbus_item *item)
break;
case KDBUS_ITEM_PAYLOAD_VEC:
- if (payload_size != sizeof(struct kdbus_vec))
- return -EINVAL;
- if (item->vec.size == 0 || item->vec.size > SIZE_MAX)
- return -EINVAL;
- break;
-
case KDBUS_ITEM_PAYLOAD_OFF:
if (payload_size != sizeof(struct kdbus_vec))
return -EINVAL;

View File

@ -0,0 +1,42 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 20:14:56 +0300
Subject: [PATCH] kdbus: kdbus_reply_find(): return on found entry
Return found entry immediately instead of assigning it to additional
variable and breaking the loop. It's simpler to read, the same way is
used in kdbus_conn_has_name(), for example.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/reply.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
index 89d355b44f63..9d823ebee71f 100644
--- a/ipc/kdbus/reply.c
+++ b/ipc/kdbus/reply.c
@@ -171,17 +171,15 @@ struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying,
struct kdbus_conn *reply_dst,
u64 cookie)
{
- struct kdbus_reply *r, *reply = NULL;
+ struct kdbus_reply *r;
list_for_each_entry(r, &reply_dst->reply_list, entry) {
if (r->cookie == cookie &&
- (!replying || r->reply_src == replying)) {
- reply = r;
- break;
- }
+ (!replying || r->reply_src == replying))
+ return r;
}
- return reply;
+ return NULL;
}
/**

View File

@ -0,0 +1,61 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Tue, 26 May 2015 10:01:37 +0200
Subject: [PATCH] kdbus: make metadata on broadcasts reliable
If we cannot collect metadata, this is a serious error. Don't try to
continue sending a message, but immediately bail out and tell the receiver
that we dropped it. Otherwise, the receiver cannot rely on metadata to be
present and might assume it's a faked connection.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/bus.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c
index 9a0ecbc9df2f..d5475961b896 100644
--- a/ipc/kdbus/bus.c
+++ b/ipc/kdbus/bus.c
@@ -293,12 +293,12 @@ void kdbus_bus_broadcast(struct kdbus_bus *bus,
if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src))
continue;
- /*
- * Keep sending messages even if we cannot acquire the
- * requested metadata. It's up to the receiver to drop
- * messages that lack expected metadata.
- */
- kdbus_kmsg_collect_metadata(kmsg, conn_src, conn_dst);
+ ret = kdbus_kmsg_collect_metadata(kmsg, conn_src,
+ conn_dst);
+ if (ret < 0) {
+ kdbus_conn_lost_message(conn_dst);
+ continue;
+ }
} else {
/*
* Check if there is a policy db that prevents the
@@ -344,14 +344,14 @@ void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
down_read(&bus->conn_rwlock);
list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) {
- /*
- * Collect metadata requested by the destination connection.
- * Ignore errors, as receivers need to check metadata
- * availability, anyway. So it's still better to send messages
- * that lack data, than to skip it entirely.
- */
- if (conn_src)
- kdbus_kmsg_collect_metadata(kmsg, conn_src, conn_dst);
+ if (conn_src) {
+ ret = kdbus_kmsg_collect_metadata(kmsg, conn_src,
+ conn_dst);
+ if (ret < 0) {
+ kdbus_conn_lost_message(conn_dst);
+ continue;
+ }
+ }
ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
if (ret < 0)

View File

@ -0,0 +1,67 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 20 Apr 2015 11:13:54 +0200
Subject: [PATCH] kdbus: no need to ref current->mm
If we access current->mm temporarily, there is no need to ref it. It can
only be changed by us, so no-one can race with us.
Avoid ref'ing and unref'ing it just to access some of its fields, similar
to what syscalls in mm/ do.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
ipc/kdbus/metadata.c | 21 +++------------------
1 file changed, 3 insertions(+), 18 deletions(-)
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index a85eac34a5c4..c36b9cc67637 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -282,15 +282,10 @@ static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp)
static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp)
{
- struct mm_struct *mm;
struct file *exe_file;
- mm = get_task_mm(current);
- if (!mm)
- return;
-
rcu_read_lock();
- exe_file = rcu_dereference(mm->exe_file);
+ exe_file = rcu_dereference(current->mm->exe_file);
if (exe_file) {
mp->exe_path = exe_file->f_path;
path_get(&mp->exe_path);
@@ -298,28 +293,18 @@ static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp)
mp->valid |= KDBUS_ATTACH_EXE;
}
rcu_read_unlock();
-
- mmput(mm);
}
static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp)
{
- struct mm_struct *mm;
+ struct mm_struct *mm = current->mm;
char *cmdline;
- mm = get_task_mm(current);
- if (!mm)
- return 0;
-
- if (!mm->arg_end) {
- mmput(mm);
+ if (!mm->arg_end)
return 0;
- }
cmdline = strndup_user((const char __user *)mm->arg_start,
mm->arg_end - mm->arg_start);
- mmput(mm);
-
if (IS_ERR(cmdline))
return PTR_ERR(cmdline);

View File

@ -0,0 +1,50 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 20 Apr 2015 10:53:35 +0200
Subject: [PATCH] kdbus: optimize auxgroup collector
current->creds can only be changed by 'current'. That is, as long as we
only access our own credentials, we can be sure it does not change. Hence,
there is no need to ref cred->group_info if all we do is copy its content.
This avoids touching shared cachelines when collecting auxgroups.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/metadata.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index eeebfef11552..174436f0aa01 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -245,25 +245,23 @@ static void kdbus_meta_proc_collect_pids(struct kdbus_meta_proc *mp)
static int kdbus_meta_proc_collect_auxgroups(struct kdbus_meta_proc *mp)
{
- struct group_info *info;
+ const struct group_info *info;
size_t i;
- info = get_current_groups();
+ /* no need to lock/ref, current creds cannot change */
+ info = current_cred()->group_info;
if (info->ngroups > 0) {
mp->auxgrps = kmalloc_array(info->ngroups, sizeof(kgid_t),
GFP_KERNEL);
- if (!mp->auxgrps) {
- put_group_info(info);
+ if (!mp->auxgrps)
return -ENOMEM;
- }
for (i = 0; i < info->ngroups; i++)
mp->auxgrps[i] = GROUP_AT(info, i);
}
mp->n_auxgrps = info->ngroups;
- put_group_info(info);
mp->valid |= KDBUS_ATTACH_AUXGROUPS;
return 0;

View File

@ -0,0 +1,46 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 20:14:57 +0300
Subject: [PATCH] kdbus: optimize error path in kdbus_reply_new()
Move cleanup code to separate location as it never executes on normal
flow. This removes extra if-block and the need to initialize `ret'.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/reply.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
index 9d823ebee71f..e6791d86ec92 100644
--- a/ipc/kdbus/reply.c
+++ b/ipc/kdbus/reply.c
@@ -37,7 +37,7 @@ struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
bool sync)
{
struct kdbus_reply *r;
- int ret = 0;
+ int ret;
if (atomic_inc_return(&reply_dst->request_count) >
KDBUS_CONN_MAX_REQUESTS_PENDING) {
@@ -64,13 +64,11 @@ struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
r->waiting = true;
}
-exit_dec_request_count:
- if (ret < 0) {
- atomic_dec(&reply_dst->request_count);
- return ERR_PTR(ret);
- }
-
return r;
+
+exit_dec_request_count:
+ atomic_dec(&reply_dst->request_count);
+ return ERR_PTR(ret);
}
static void __kdbus_reply_free(struct kref *kref)

View File

@ -0,0 +1,48 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 20:14:58 +0300
Subject: [PATCH] kdbus: optimize if statements in kdbus_conn_disconnect()
if (r->sync) branch and code after it both call kdbus_reply_unlink().
Rewrite them as if-else to eliminate code duplication and make algorithm
more obvious.
Convert outer if statement to use continue in order to reduce
indentation and make things easier to read.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/connection.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index 707be050b408..9993753d11de 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -559,17 +559,16 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
hash_for_each(bus->conn_hash, i, c, hentry) {
mutex_lock(&c->lock);
list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) {
- if (r->reply_src == conn) {
- if (r->sync) {
- kdbus_sync_reply_wakeup(r, -EPIPE);
- kdbus_reply_unlink(r);
- continue;
- }
+ if (r->reply_src != conn)
+ continue;
+ if (r->sync)
+ kdbus_sync_reply_wakeup(r, -EPIPE);
+ else
/* send a 'connection dead' notification */
kdbus_notify_reply_dead(bus, c->id, r->cookie);
- kdbus_reply_unlink(r);
- }
+
+ kdbus_reply_unlink(r);
}
mutex_unlock(&c->lock);
}

View File

@ -0,0 +1,72 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Tue, 21 Apr 2015 02:12:18 +0300
Subject: [PATCH] kdbus: pool: use __vfs_read()
After commit 5d5d56897530 ("make new_sync_{read,write}() static")
->read() cannot be called directly.
kdbus_pool_slice_copy() leads to oops, which can be reproduced by
launching tools/testing/selftests/kdbus/kdbus-test -t message-quota:
[ 1167.146793] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 1167.147554] IP: [< (null)>] (null)
[ 1167.148670] PGD 3a9dd067 PUD 3a841067 PMD 0
[ 1167.149611] Oops: 0010 [#1] SMP
[ 1167.150088] Modules linked in: nfsv3 nfs kdbus lockd grace sunrpc
[ 1167.150771] CPU: 0 PID: 518 Comm: kdbus-test Not tainted 4.0.0-next-20150420-kdbus #62
[ 1167.150771] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[ 1167.150771] task: ffff88003daed120 ti: ffff88003a800000 task.ti: ffff88003a800000
[ 1167.150771] RIP: 0010:[<0000000000000000>] [< (null)>] (null)
[ 1167.150771] RSP: 0018:ffff88003a803bc0 EFLAGS: 00010286
[ 1167.150771] RAX: ffff8800377fb000 RBX: 00000000000201e8 RCX: ffff88003a803c00
[ 1167.150771] RDX: 0000000000000b40 RSI: ffff8800377fb4c0 RDI: ffff88003d815700
[ 1167.150771] RBP: ffff88003a803c48 R08: ffffffff8139e380 R09: ffff880039d80490
[ 1167.150771] R10: ffff88003a803a90 R11: 00000000000004c0 R12: 00000000002a24c0
[ 1167.150771] R13: 0000000000000b40 R14: ffff88003d815700 R15: ffffffff8139e460
[ 1167.150771] FS: 00007f41dccd4740(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000
[ 1167.150771] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1167.150771] CR2: 0000000000000000 CR3: 000000003ccdf000 CR4: 00000000000007b0
[ 1167.150771] Stack:
[ 1167.150771] ffffffffa0065497 ffff88003a803c10 00007ffffffff000 ffff88003aaa67c0
[ 1167.150771] 00000000000004c0 ffff88003aaa6870 ffff88003ca83300 ffffffffa006537d
[ 1167.150771] 00000000000201e8 ffffea0000ddfec0 ffff88003a803c20 0000000000000018
[ 1167.150771] Call Trace:
[ 1167.150771] [<ffffffffa0065497>] ? kdbus_pool_slice_copy+0x127/0x200 [kdbus]
[ 1167.150771] [<ffffffffa006537d>] ? kdbus_pool_slice_copy+0xd/0x200 [kdbus]
[ 1167.150771] [<ffffffffa006670a>] kdbus_queue_entry_move+0xaa/0x180 [kdbus]
[ 1167.150771] [<ffffffffa0059e64>] kdbus_conn_move_messages+0x1e4/0x2c0 [kdbus]
[ 1167.150771] [<ffffffffa006234e>] kdbus_name_acquire+0x31e/0x390 [kdbus]
[ 1167.150771] [<ffffffffa00625c5>] kdbus_cmd_name_acquire+0x125/0x130 [kdbus]
[ 1167.150771] [<ffffffffa005db5d>] kdbus_handle_ioctl+0x4ed/0x610 [kdbus]
[ 1167.150771] [<ffffffff811040e0>] do_vfs_ioctl+0x2e0/0x4e0
[ 1167.150771] [<ffffffff81389750>] ? preempt_schedule_common+0x1f/0x3f
[ 1167.150771] [<ffffffff8110431c>] SyS_ioctl+0x3c/0x80
[ 1167.150771] [<ffffffff8138c36e>] system_call_fastpath+0x12/0x71
[ 1167.150771] Code: Bad RIP value.
[ 1167.150771] RIP [< (null)>] (null)
[ 1167.150771] RSP <ffff88003a803bc0>
[ 1167.150771] CR2: 0000000000000000
[ 1167.168756] ---[ end trace a676bcfa75db5a96 ]---
Use __vfs_read() instead.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/pool.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c
index 139bb77056b3..45dcdea505f4 100644
--- a/ipc/kdbus/pool.c
+++ b/ipc/kdbus/pool.c
@@ -675,7 +675,7 @@ int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
}
kaddr = (char __force __user *)kmap(page) + page_off;
- n_read = f_src->f_op->read(f_src, kaddr, copy_len, &off_src);
+ n_read = __vfs_read(f_src, kaddr, copy_len, &off_src);
kunmap(page);
mark_page_accessed(page);
flush_dcache_page(page);

View File

@ -0,0 +1,195 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Tue, 26 May 2015 09:59:02 +0200
Subject: [PATCH] kdbus: provide helper to collect metadata
Provide a new helper kdbus_kmsg_collect_metadata() which implements the
common task of collecting proc- and conn-metadata on a kmsg.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/bus.c | 24 +++---------------------
ipc/kdbus/connection.c | 35 ++++-------------------------------
ipc/kdbus/message.c | 24 ++++++++++++++++++++++++
ipc/kdbus/message.h | 2 ++
4 files changed, 33 insertions(+), 52 deletions(-)
diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c
index 9d0679eb59f6..9a0ecbc9df2f 100644
--- a/ipc/kdbus/bus.c
+++ b/ipc/kdbus/bus.c
@@ -285,8 +285,6 @@ void kdbus_bus_broadcast(struct kdbus_bus *bus,
continue;
if (conn_src) {
- u64 attach_flags;
-
/*
* Anyone can send broadcasts, as they have no
* destination. But a receiver needs TALK access to
@@ -295,19 +293,12 @@ void kdbus_bus_broadcast(struct kdbus_bus *bus,
if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src))
continue;
- attach_flags = kdbus_meta_calc_attach_flags(conn_src,
- conn_dst);
-
/*
* Keep sending messages even if we cannot acquire the
* requested metadata. It's up to the receiver to drop
* messages that lack expected metadata.
*/
- if (!conn_src->faked_meta)
- kdbus_meta_proc_collect(kmsg->proc_meta,
- attach_flags);
- kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
- attach_flags);
+ kdbus_kmsg_collect_metadata(kmsg, conn_src, conn_dst);
} else {
/*
* Check if there is a policy db that prevents the
@@ -359,17 +350,8 @@ void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
* availability, anyway. So it's still better to send messages
* that lack data, than to skip it entirely.
*/
- if (conn_src) {
- u64 attach_flags;
-
- attach_flags = kdbus_meta_calc_attach_flags(conn_src,
- conn_dst);
- if (!conn_src->faked_meta)
- kdbus_meta_proc_collect(kmsg->proc_meta,
- attach_flags);
- kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
- attach_flags);
- }
+ if (conn_src)
+ kdbus_kmsg_collect_metadata(kmsg, conn_src, conn_dst);
ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
if (ret < 0)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index 272b991f36f4..cbfbf3847c24 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -1098,7 +1098,6 @@ static int kdbus_conn_reply(struct kdbus_conn *src, struct kdbus_kmsg *kmsg)
struct kdbus_reply *reply, *wake = NULL;
struct kdbus_conn *dst = NULL;
struct kdbus_bus *bus = src->ep->bus;
- u64 attach;
int ret;
if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) ||
@@ -1131,15 +1130,7 @@ static int kdbus_conn_reply(struct kdbus_conn *src, struct kdbus_kmsg *kmsg)
/* attach metadata */
- attach = kdbus_meta_calc_attach_flags(src, dst);
-
- if (!src->faked_meta) {
- ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
- if (ret < 0)
- goto exit;
- }
-
- ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
+ ret = kdbus_kmsg_collect_metadata(kmsg, src, dst);
if (ret < 0)
goto exit;
@@ -1167,7 +1158,6 @@ static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src,
struct kdbus_reply *wait = NULL;
struct kdbus_conn *dst = NULL;
struct kdbus_bus *bus = src->ep->bus;
- u64 attach;
int ret;
if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) ||
@@ -1218,15 +1208,7 @@ static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src,
/* attach metadata */
- attach = kdbus_meta_calc_attach_flags(src, dst);
-
- if (!src->faked_meta) {
- ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
- if (ret < 0)
- goto exit;
- }
-
- ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
+ ret = kdbus_kmsg_collect_metadata(kmsg, src, dst);
if (ret < 0)
goto exit;
@@ -1257,7 +1239,6 @@ static int kdbus_conn_unicast(struct kdbus_conn *src, struct kdbus_kmsg *kmsg)
struct kdbus_conn *dst = NULL;
struct kdbus_bus *bus = src->ep->bus;
bool is_signal = (kmsg->msg.flags & KDBUS_MSG_SIGNAL);
- u64 attach;
int ret = 0;
if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) ||
@@ -1296,16 +1277,8 @@ static int kdbus_conn_unicast(struct kdbus_conn *src, struct kdbus_kmsg *kmsg)
/* attach metadata */
- attach = kdbus_meta_calc_attach_flags(src, dst);
-
- if (!src->faked_meta) {
- ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
- if (ret < 0 && !is_signal)
- goto exit;
- }
-
- ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
- if (ret < 0 && !is_signal)
+ ret = kdbus_kmsg_collect_metadata(kmsg, src, dst);
+ if (ret < 0)
goto exit;
/* send message */
diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c
index 80960756a329..066e816dfdea 100644
--- a/ipc/kdbus/message.c
+++ b/ipc/kdbus/message.c
@@ -614,3 +614,27 @@ exit_free:
kdbus_kmsg_free(m);
return ERR_PTR(ret);
}
+
+/**
+ * kdbus_kmsg_collect_metadata() - collect metadata
+ * @kmsg: message to collect metadata on
+ * @src: source connection of message
+ * @dst: destination connection of message
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_kmsg_collect_metadata(struct kdbus_kmsg *kmsg, struct kdbus_conn *src,
+ struct kdbus_conn *dst)
+{
+ u64 attach;
+ int ret;
+
+ attach = kdbus_meta_calc_attach_flags(src, dst);
+ if (!src->faked_meta) {
+ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
+ if (ret < 0)
+ return ret;
+ }
+
+ return kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
+}
diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h
index af4775850235..cdaa65c4e6ae 100644
--- a/ipc/kdbus/message.h
+++ b/ipc/kdbus/message.h
@@ -129,5 +129,7 @@ struct kdbus_kmsg *kdbus_kmsg_new(struct kdbus_bus *bus, size_t extra_size);
struct kdbus_kmsg *kdbus_kmsg_new_from_cmd(struct kdbus_conn *conn,
struct kdbus_cmd_send *cmd_send);
void kdbus_kmsg_free(struct kdbus_kmsg *kmsg);
+int kdbus_kmsg_collect_metadata(struct kdbus_kmsg *kmsg, struct kdbus_conn *src,
+ struct kdbus_conn *dst);
#endif

View File

@ -0,0 +1,276 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Sat, 18 Apr 2015 12:39:51 +0200
Subject: [PATCH] kdbus: reduce scope of handle locking
A kdbus handle is used to create objects in the kdbus hierarchy. During
open(), we do not have enough information to know how to setup the object.
Therefore, we provide setup ioctls, which allow user-space to pass in
parameters and options how the to-be-created object should behave. Once
setup is done, we allow user-space to use ioctls to operate on that newly
created object.
It is important to notice:
1) Only one setup ioctl can ever be called on a handle. You cannot call
multiple, different setup ioctls on the same handle.
2) A setup ioctl can only be called once, if it succeeded. If it failed,
it must not modify the handle in any way. If it succeeded, no further
setup ioctl can be issued.
3) After a setup ioctl is done, the handle is constant and must not be
modified in any way.
So far, we used a write-lock around all setup ioctls, and a read-lock
around everything else. The handle setup-indicator (the type field) can
only be set under the write-lock. Whenever you access the handle under a
read-lock, you must verify it was set before, otherwise, you must bail out
as the handle was not initialized, yet.
This has the downside that we need a read-lock on all operations on the
handle. For performance reasons, we should avoid that. This patch turns
the rwlock into a mutex and removes the read-side lock from all paths. It
relies on the 3 behaviors described above.
With this patch, the mutex is only taken around setup ioctls. Furthermore,
the setup-indicator (the type field) is only ever set if the mutex is
held. The mutex guarantees that multiple setup ioctls cannot race, and
also, that only one setup ioctl will ever succeed. If a setup ioctl is
called after setup was already finished, we do not touch the handle at all
and immediately fail.
Furthermore, all other operations (non-setup operations) can only be
called once setup is done. Therefore, we must synchronize them with any
racing setup, otherwise, they might access the handle which is currently
modified by setup.
We protect from this race by setting the setup-indicator (the type field)
_last_, and issue a write-barrier before setting it. Once it is set, we
never modify the handle ever again; it is constant from now on until
file-release.
Hence, on the read-side we simply read the type field and issue a
read-barrier afterwards. _Iff_ the type field was not set, yet, we must
not access the handle in any way, but bail out immediately. Setup was not
done, yet. But if the type field was set, the read-barrier pairs with the
write-barrier during setup. All member fields of the handle object are
guaranteed to be accessible by us, as the type-field is always the last
field that is written.
With this in place, we reduce the locking-overhead of all non-setup ioctls
to a read-barrier, instead of a read-side lock. And in combination with
the follow-up that removes the active-refs from kdbus_handle_poll(), we're
now lock-free in ->poll and ->mmap callbacks.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/handle.c | 110 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 83 insertions(+), 27 deletions(-)
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
index 3f5d8085a297..a3e01383a6f6 100644
--- a/ipc/kdbus/handle.c
+++ b/ipc/kdbus/handle.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
@@ -229,7 +230,7 @@ enum kdbus_handle_type {
/**
* struct kdbus_handle - handle to the kdbus system
- * @rwlock: handle lock
+ * @lock: handle lock
* @type: type of this handle (KDBUS_HANDLE_*)
* @bus_owner: bus this handle owns
* @ep_owner: endpoint this handle owns
@@ -237,7 +238,7 @@ enum kdbus_handle_type {
* @privileged: Flag to mark a handle as privileged
*/
struct kdbus_handle {
- struct rw_semaphore rwlock;
+ struct mutex lock;
enum kdbus_handle_type type;
union {
@@ -265,7 +266,7 @@ static int kdbus_handle_open(struct inode *inode, struct file *file)
goto exit;
}
- init_rwsem(&handle->rwlock);
+ mutex_init(&handle->lock);
handle->type = KDBUS_HANDLE_NONE;
if (node->type == KDBUS_NODE_ENDPOINT) {
@@ -355,8 +356,8 @@ static long kdbus_handle_ioctl_control(struct file *file, unsigned int cmd,
break;
}
- handle->type = KDBUS_HANDLE_BUS_OWNER;
handle->bus_owner = bus;
+ ret = KDBUS_HANDLE_BUS_OWNER;
break;
}
@@ -396,8 +397,8 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
break;
}
- handle->type = KDBUS_HANDLE_EP_OWNER;
handle->ep_owner = ep;
+ ret = KDBUS_HANDLE_EP_OWNER;
break;
case KDBUS_CMD_HELLO:
@@ -407,8 +408,8 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
break;
}
- handle->type = KDBUS_HANDLE_CONNECTED;
handle->conn = conn;
+ ret = KDBUS_HANDLE_CONNECTED;
break;
default:
@@ -522,19 +523,41 @@ static long kdbus_handle_ioctl(struct file *file, unsigned int cmd,
case KDBUS_CMD_BUS_MAKE:
case KDBUS_CMD_ENDPOINT_MAKE:
case KDBUS_CMD_HELLO:
- /* bail out early if already typed */
- if (handle->type != KDBUS_HANDLE_NONE)
- break;
-
- down_write(&handle->rwlock);
+ mutex_lock(&handle->lock);
if (handle->type == KDBUS_HANDLE_NONE) {
if (node->type == KDBUS_NODE_CONTROL)
ret = kdbus_handle_ioctl_control(file, cmd,
argp);
else if (node->type == KDBUS_NODE_ENDPOINT)
ret = kdbus_handle_ioctl_ep(file, cmd, argp);
+
+ if (ret > 0) {
+ /*
+ * The data given via open() is not sufficient
+ * to setup a kdbus handle. Hence, we require
+ * the user to perform a setup ioctl. This setup
+ * can only be performed once and defines the
+ * type of the handle. The different setup
+ * ioctls are locked against each other so they
+ * cannot race. Once the handle type is set,
+ * the type-dependent ioctls are enabled. To
+ * improve performance, we don't lock those via
+ * handle->lock. Instead, we issue a
+ * write-barrier before performing the
+ * type-change, which pairs with smp_rmb() in
+ * all handlers that access the type field. This
+ * guarantees the handle is fully setup, if
+ * handle->type is set. If handle->type is
+ * unset, you must not make any assumptions
+ * without taking handle->lock.
+ * Note that handle->type is only set once. It
+ * will never change afterwards.
+ */
+ smp_wmb();
+ handle->type = ret;
+ }
}
- up_write(&handle->rwlock);
+ mutex_unlock(&handle->lock);
break;
case KDBUS_CMD_ENDPOINT_UPDATE:
@@ -549,14 +572,30 @@ static long kdbus_handle_ioctl(struct file *file, unsigned int cmd,
case KDBUS_CMD_MATCH_REMOVE:
case KDBUS_CMD_SEND:
case KDBUS_CMD_RECV:
- case KDBUS_CMD_FREE:
- down_read(&handle->rwlock);
- if (handle->type == KDBUS_HANDLE_EP_OWNER)
+ case KDBUS_CMD_FREE: {
+ enum kdbus_handle_type type;
+
+ /*
+ * This read-barrier pairs with smp_wmb() of the handle setup.
+ * it guarantees the handle is fully written, in case the
+ * type has been set. It allows us to access the handle without
+ * taking handle->lock, given the guarantee that the type is
+ * only ever set once, and stays constant afterwards.
+ * Furthermore, the handle object itself is not modified in any
+ * way after the type is set. That is, the type-field is the
+ * last field that is written on any handle. If it has not been
+ * set, we must not access the handle here.
+ */
+ type = handle->type;
+ smp_rmb();
+
+ if (type == KDBUS_HANDLE_EP_OWNER)
ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp);
- else if (handle->type == KDBUS_HANDLE_CONNECTED)
+ else if (type == KDBUS_HANDLE_CONNECTED)
ret = kdbus_handle_ioctl_connected(file, cmd, argp);
- up_read(&handle->rwlock);
+
break;
+ }
default:
ret = -ENOTTY;
break;
@@ -569,16 +608,23 @@ static unsigned int kdbus_handle_poll(struct file *file,
struct poll_table_struct *wait)
{
struct kdbus_handle *handle = file->private_data;
+ enum kdbus_handle_type type;
unsigned int mask = POLLOUT | POLLWRNORM;
int ret;
+ /*
+ * This pairs with smp_wmb() during handle setup. It guarantees that
+ * _iff_ the handle type is set, handle->conn is valid. Furthermore,
+ * _iff_ the type is set, the handle object is constant and never
+ * changed again. If it's not set, we must not access the handle but
+ * bail out. We also must assume no setup has taken place, yet.
+ */
+ type = handle->type;
+ smp_rmb();
+
/* Only a connected endpoint can read/write data */
- down_read(&handle->rwlock);
- if (handle->type != KDBUS_HANDLE_CONNECTED) {
- up_read(&handle->rwlock);
+ if (type != KDBUS_HANDLE_CONNECTED)
return POLLERR | POLLHUP;
- }
- up_read(&handle->rwlock);
ret = kdbus_conn_acquire(handle->conn);
if (ret < 0)
@@ -598,13 +644,23 @@ static unsigned int kdbus_handle_poll(struct file *file,
static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma)
{
struct kdbus_handle *handle = file->private_data;
+ enum kdbus_handle_type type;
int ret = -EBADFD;
- if (down_read_trylock(&handle->rwlock)) {
- if (handle->type == KDBUS_HANDLE_CONNECTED)
- ret = kdbus_pool_mmap(handle->conn->pool, vma);
- up_read(&handle->rwlock);
- }
+ /*
+ * This pairs with smp_wmb() during handle setup. It guarantees that
+ * _iff_ the handle type is set, handle->conn is valid. Furthermore,
+ * _iff_ the type is set, the handle object is constant and never
+ * changed again. If it's not set, we must not access the handle but
+ * bail out. We also must assume no setup has taken place, yet.
+ */
+ type = handle->type;
+ smp_rmb();
+
+ /* Only connected handles have a pool we can map */
+ if (type == KDBUS_HANDLE_CONNECTED)
+ ret = kdbus_pool_mmap(handle->conn->pool, vma);
+
return ret;
}

View File

@ -0,0 +1,40 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Tue, 2 Jun 2015 18:48:48 +0300
Subject: [PATCH] kdbus: remove redundant code from kdbus_conn_entry_make()
We don't need to check `entry' for error, as in either case it is
returned as is. Return result of kdbus_queue_entry_new() directly.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/connection.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index 8ee62fc0bd46..1bd7bb968f9f 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -775,8 +775,6 @@ kdbus_conn_entry_make(struct kdbus_conn *conn_dst,
const struct kdbus_kmsg *kmsg,
struct kdbus_user *user)
{
- struct kdbus_queue_entry *entry;
-
/* The remote connection was disconnected */
if (!kdbus_conn_active(conn_dst))
return ERR_PTR(-ECONNRESET);
@@ -793,11 +791,7 @@ kdbus_conn_entry_make(struct kdbus_conn *conn_dst,
kmsg->res && kmsg->res->fds_count > 0)
return ERR_PTR(-ECOMM);
- entry = kdbus_queue_entry_new(conn_dst, kmsg, user);
- if (IS_ERR(entry))
- return entry;
-
- return entry;
+ return kdbus_queue_entry_new(conn_dst, kmsg, user);
}
/*

View File

@ -0,0 +1,25 @@
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Date: Thu, 16 Apr 2015 21:07:18 +0800
Subject: [PATCH] kdbus: remove unused linux/version.h include
Remove <linux/version.h> include, it's not needed.
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Acked-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
ipc/kdbus/metadata.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index 3adc6c2c2e76..eeebfef11552 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -29,7 +29,6 @@
#include <linux/uidgid.h>
#include <linux/uio.h>
#include <linux/user_namespace.h>
-#include <linux/version.h>
#include "bus.h"
#include "connection.h"

View File

@ -0,0 +1,23 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Thu, 12 Mar 2015 17:27:31 +0100
Subject: [PATCH] kdbus: samples/kdbus: add -lrt
On older systems -lrt is needed for clock_gettime(). Add it to
HOSTLOADLIBES of kdbus-workers so it builds fine on those systems.
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/kdbus/Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile
index d009025369f4..eee9b9aed632 100644
--- a/samples/kdbus/Makefile
+++ b/samples/kdbus/Makefile
@@ -8,3 +8,4 @@ always := $(hostprogs-y)
HOSTCFLAGS_kdbus-workers.o += \
-I$(objtree)/usr/include/ \
-I$(objtree)/include/uapi/
+HOSTLOADLIBES_kdbus-workers := -lrt

View File

@ -0,0 +1,24 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Wed, 3 Jun 2015 17:53:29 +0200
Subject: [PATCH] kdbus/selftests: add build-dependencies on headers
Make sure the selftests are re-built if one of the local headers changes.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
tools/testing/selftests/kdbus/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile
index 076f9f40566d..7ad587b3c767 100644
--- a/tools/testing/selftests/kdbus/Makefile
+++ b/tools/testing/selftests/kdbus/Makefile
@@ -34,7 +34,7 @@ all: kdbus-test
include ../lib.mk
-%.o: %.c
+%.o: %.c kdbus-enum.h kdbus-test.h kdbus-util.h
$(CC) $(CFLAGS) -c $< -o $@
kdbus-test: $(OBJS)

View File

@ -0,0 +1,63 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Sat, 18 Apr 2015 13:04:42 +0200
Subject: [PATCH] kdbus: skip acquiring an active reference in poll()
During poll(), we currently acquire an active reference to the connection
in question to verify it's still active. If it's not active, anymore, we
return POLLHUP.
This works fine, but requires an atomic_inc() to acquire the active
reference. However, all we need is a guarantee that the connection is
active right now, and a guarantee we're called again once this changes.
This is as simple as adding the waitqueue first, then checking the
active-state afterwards. kdbus_conn_disconnect() guarantees to wake us up
_after_ deactivating the connection, thus providing the required barrier
implicitly (in case someone is actually polling / waiting on the
connection).
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/handle.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
index a3e01383a6f6..6230c7ef4347 100644
--- a/ipc/kdbus/handle.c
+++ b/ipc/kdbus/handle.c
@@ -610,7 +610,6 @@ static unsigned int kdbus_handle_poll(struct file *file,
struct kdbus_handle *handle = file->private_data;
enum kdbus_handle_type type;
unsigned int mask = POLLOUT | POLLWRNORM;
- int ret;
/*
* This pairs with smp_wmb() during handle setup. It guarantees that
@@ -626,18 +625,21 @@ static unsigned int kdbus_handle_poll(struct file *file,
if (type != KDBUS_HANDLE_CONNECTED)
return POLLERR | POLLHUP;
- ret = kdbus_conn_acquire(handle->conn);
- if (ret < 0)
- return POLLERR | POLLHUP;
-
poll_wait(file, &handle->conn->wait, wait);
+ /*
+ * Verify the connection hasn't been deactivated _after_ adding the
+ * wait-queue. This guarantees, that if the connection is deactivated
+ * after we checked it, the waitqueue is signaled and we're called
+ * again.
+ */
+ if (!kdbus_conn_active(handle->conn))
+ return POLLERR | POLLHUP;
+
if (!list_empty(&handle->conn->queue.msg_list) ||
atomic_read(&handle->conn->lost_count) > 0)
mask |= POLLIN | POLLRDNORM;
- kdbus_conn_release(handle->conn);
-
return mask;
}

View File

@ -0,0 +1,55 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Thu, 21 May 2015 20:03:29 +0200
Subject: [PATCH] kdbus: skip mandatory items on negotiation
The kdbus negotiation is used to figure out what items and flags an ioctl
supports. It is highly impractical to pass in mandatory items when all we
do is negotiation. Therefore, allow user-space to skip mandatory items if
KDBUS_FLAG_NEGOTIATE is passed.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/handle.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
index f72dbe513b4a..3f5d8085a297 100644
--- a/ipc/kdbus/handle.c
+++ b/ipc/kdbus/handle.c
@@ -71,10 +71,6 @@ static int kdbus_args_verify(struct kdbus_args *args)
if (!KDBUS_ITEMS_END(item, args->items, args->items_size))
return -EINVAL;
- for (i = 0; i < args->argc; ++i)
- if (args->argv[i].mandatory && !args->argv[i].item)
- return -EINVAL;
-
return 0;
}
@@ -149,7 +145,7 @@ static int kdbus_args_negotiate(struct kdbus_args *args)
int __kdbus_args_parse(struct kdbus_args *args, void __user *argp,
size_t type_size, size_t items_offset, void **out)
{
- int ret;
+ int ret, i;
args->cmd = kdbus_memdup_user(argp, type_size, KDBUS_CMD_MAX_SIZE);
if (IS_ERR(args->cmd))
@@ -173,6 +169,15 @@ int __kdbus_args_parse(struct kdbus_args *args, void __user *argp,
if (ret < 0)
goto error;
+ /* mandatory items must be given (but not on negotiation) */
+ if (!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE)) {
+ for (i = 0; i < args->argc; ++i)
+ if (args->argv[i].mandatory && !args->argv[i].item) {
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
*out = args->cmd;
return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE);

View File

@ -0,0 +1,212 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Wed, 22 Apr 2015 13:14:24 +0200
Subject: [PATCH] kdbus: translate capabilities between namespaces
Right now, we always drop capability-items if we cross user-namespaces.
However, the kernel _does_ support capability translation, as defined in
./security/commoncap.c cap_capable().
This patch adds capability translation support just like cap_capable()
does. This way, a message sent from a task into a child user-namespace of
its own, will retain the capability-item and thus keep the parent
privileged inside of the user-namespace of its children.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
ipc/kdbus/metadata.c | 126 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 84 insertions(+), 42 deletions(-)
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index b908b6314a00..7949c8d3ed64 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -63,8 +63,7 @@
* @root_path: Root-FS path
* @cmdline: Command-line
* @cgroup: Full cgroup path
- * @caps: Capabilities
- * @caps_namespace: User-namespace of @caps
+ * @cred: Credentials
* @seclabel: Seclabel
* @audit_loginuid: Audit login-UID
* @audit_sessionid: Audit session-ID
@@ -104,14 +103,7 @@ struct kdbus_meta_proc {
char *cgroup;
/* KDBUS_ITEM_CAPS */
- struct caps {
- /* binary compatible to kdbus_caps */
- u32 last_cap;
- struct {
- u32 caps[_KERNEL_CAPABILITY_U32S];
- } set[4];
- } caps;
- struct user_namespace *caps_namespace;
+ const struct cred *cred;
/* KDBUS_ITEM_SECLABEL */
char *seclabel;
@@ -149,6 +141,14 @@ struct kdbus_meta_conn {
char *conn_description;
};
+/* fixed size equivalent of "kdbus_caps" */
+struct kdbus_meta_caps {
+ u32 last_cap;
+ struct {
+ u32 caps[_KERNEL_CAPABILITY_U32S];
+ } set[4];
+};
+
/**
* kdbus_meta_proc_new() - Create process metadata object
*
@@ -175,7 +175,8 @@ static void kdbus_meta_proc_free(struct kref *kref)
path_put(&mp->exe_path);
path_put(&mp->root_path);
- put_user_ns(mp->caps_namespace);
+ if (mp->cred)
+ put_cred(mp->cred);
put_pid(mp->ppid);
put_pid(mp->tgid);
put_pid(mp->pid);
@@ -354,25 +355,7 @@ static int kdbus_meta_proc_collect_cgroup(struct kdbus_meta_proc *mp)
static void kdbus_meta_proc_collect_caps(struct kdbus_meta_proc *mp)
{
- const struct cred *c = current_cred();
- int i;
-
- /* ABI: "last_cap" equals /proc/sys/kernel/cap_last_cap */
- mp->caps.last_cap = CAP_LAST_CAP;
- mp->caps_namespace = get_user_ns(current_user_ns());
-
- CAP_FOR_EACH_U32(i) {
- mp->caps.set[0].caps[i] = c->cap_inheritable.cap[i];
- mp->caps.set[1].caps[i] = c->cap_permitted.cap[i];
- mp->caps.set[2].caps[i] = c->cap_effective.cap[i];
- mp->caps.set[3].caps[i] = c->cap_bset.cap[i];
- }
-
- /* clear unused bits */
- for (i = 0; i < 4; i++)
- mp->caps.set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
- CAP_LAST_U32_VALID_MASK;
-
+ mp->cred = get_current_cred();
mp->valid |= KDBUS_ATTACH_CAPS;
}
@@ -880,7 +863,7 @@ int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp,
size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1);
if (mp && (*mask & KDBUS_ATTACH_CAPS))
- size += KDBUS_ITEM_SIZE(sizeof(mp->caps));
+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps));
if (mp && (*mask & KDBUS_ATTACH_SECLABEL))
size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1);
@@ -917,6 +900,69 @@ static int kdbus_meta_push_kvec(struct kvec *kvec,
return 2 + !!kdbus_kvec_pad(kvec++, size);
}
+static void kdbus_meta_export_caps(struct kdbus_meta_caps *out,
+ struct kdbus_meta_proc *mp)
+{
+ struct user_namespace *iter;
+ const struct cred *cred = mp->cred;
+ bool parent = false, owner = false;
+ int i;
+
+ /*
+ * This translates the effective capabilities of 'cred' into the current
+ * user-namespace. If the current user-namespace is a child-namespace of
+ * the user-namespace of 'cred', the mask can be copied verbatim. If
+ * not, the mask is cleared.
+ * There's one exception: If 'cred' is the owner of any user-namespace
+ * in the path between the current user-namespace and the user-namespace
+ * of 'cred', then it has all effective capabilities set. This means,
+ * the user who created a user-namespace always has all effective
+ * capabilities in any child namespaces. Note that this is based on the
+ * uid of the namespace creator, not the task hierarchy.
+ */
+ for (iter = current_user_ns(); iter; iter = iter->parent) {
+ if (iter == cred->user_ns) {
+ parent = true;
+ break;
+ }
+
+ if (iter == &init_user_ns)
+ break;
+
+ if ((iter->parent == cred->user_ns) &&
+ uid_eq(iter->owner, cred->euid)) {
+ owner = true;
+ break;
+ }
+ }
+
+ out->last_cap = CAP_LAST_CAP;
+
+ CAP_FOR_EACH_U32(i) {
+ if (parent) {
+ out->set[0].caps[i] = cred->cap_inheritable.cap[i];
+ out->set[1].caps[i] = cred->cap_permitted.cap[i];
+ out->set[2].caps[i] = cred->cap_effective.cap[i];
+ out->set[3].caps[i] = cred->cap_bset.cap[i];
+ } else if (owner) {
+ out->set[0].caps[i] = 0U;
+ out->set[1].caps[i] = ~0U;
+ out->set[2].caps[i] = ~0U;
+ out->set[3].caps[i] = ~0U;
+ } else {
+ out->set[0].caps[i] = 0U;
+ out->set[1].caps[i] = 0U;
+ out->set[2].caps[i] = 0U;
+ out->set[3].caps[i] = 0U;
+ }
+ }
+
+ /* clear unused bits */
+ for (i = 0; i < 4; i++)
+ out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
+ CAP_LAST_U32_VALID_MASK;
+}
+
/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */
static uid_t kdbus_from_kuid_keep(kuid_t uid)
{
@@ -975,14 +1021,6 @@ int kdbus_meta_export(struct kdbus_meta_proc *mp,
hdr = &item_hdr[0];
- /*
- * TODO: We currently have no sane way of translating a set of caps
- * between different user namespaces. Until that changes, we have
- * to drop such items.
- */
- if (mp && mp->caps_namespace != user_ns)
- mask &= ~KDBUS_ATTACH_CAPS;
-
if (mask == 0) {
*real_size = 0;
return 0;
@@ -1088,10 +1126,14 @@ int kdbus_meta_export(struct kdbus_meta_proc *mp,
KDBUS_ITEM_CGROUP, mp->cgroup,
strlen(mp->cgroup) + 1, &size);
- if (mp && (mask & KDBUS_ATTACH_CAPS))
+ if (mp && (mask & KDBUS_ATTACH_CAPS)) {
+ struct kdbus_meta_caps caps = {};
+
+ kdbus_meta_export_caps(&caps, mp);
cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++,
- KDBUS_ITEM_CAPS, &mp->caps,
- sizeof(mp->caps), &size);
+ KDBUS_ITEM_CAPS, &caps,
+ sizeof(caps), &size);
+ }
if (mp && (mask & KDBUS_ATTACH_SECLABEL))
cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++,

View File

@ -0,0 +1,101 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Sat, 18 Apr 2015 12:00:33 +0200
Subject: [PATCH] kdbus: turn kdbus_node_idr into an ida
We no longer use the node-idr for lookups. We're only interested in unique
ID allocation. Hence, turn the kdbus_node_idr into an ida and drop the now
redundant locking. This is also what kernfs does for ino allocations.
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Daniel Mack <daniel@zonque.org>
---
ipc/kdbus/main.c | 1 +
ipc/kdbus/node.c | 23 +++++------------------
ipc/kdbus/node.h | 2 ++
3 files changed, 8 insertions(+), 18 deletions(-)
diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c
index 785f529d98b7..f8eac78cace6 100644
--- a/ipc/kdbus/main.c
+++ b/ipc/kdbus/main.c
@@ -116,6 +116,7 @@ static void __exit kdbus_exit(void)
{
kdbus_fs_exit();
kobject_put(kdbus_dir);
+ ida_destroy(&kdbus_node_ida);
}
module_init(kdbus_init);
diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c
index 520df00e676a..0d65c65d2bde 100644
--- a/ipc/kdbus/node.c
+++ b/ipc/kdbus/node.c
@@ -178,7 +178,7 @@
* accessed by other callers to properly initialize
* filesystem nodes.
*
- * * node->id: This is an unsigned 32bit integer allocated by an IDR. It is
+ * * node->id: This is an unsigned 32bit integer allocated by an IDA. It is
* always kept as small as possible during allocation and is
* globally unique across all nodes allocated by this module. 0
* is reserved as "not assigned" and is the default.
@@ -233,8 +233,7 @@
#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4)
/* global unique ID mapping for kdbus nodes */
-static DEFINE_IDR(kdbus_node_idr);
-static DECLARE_RWSEM(kdbus_node_idr_lock);
+DEFINE_IDA(kdbus_node_ida);
/**
* kdbus_node_name_hash() - hash a name
@@ -337,15 +336,11 @@ int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
node->hash = kdbus_node_name_hash(name);
}
- down_write(&kdbus_node_idr_lock);
- ret = idr_alloc(&kdbus_node_idr, node, 1, 0, GFP_KERNEL);
- if (ret >= 0)
- node->id = ret;
- up_write(&kdbus_node_idr_lock);
-
+ ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL);
if (ret < 0)
return ret;
+ node->id = ret;
ret = 0;
if (parent) {
@@ -440,16 +435,8 @@ struct kdbus_node *kdbus_node_unref(struct kdbus_node *node)
if (node->free_cb)
node->free_cb(node);
-
- down_write(&kdbus_node_idr_lock);
if (safe.id > 0)
- idr_remove(&kdbus_node_idr, safe.id);
- /* drop caches after last node to not leak memory on unload */
- if (idr_is_empty(&kdbus_node_idr)) {
- idr_destroy(&kdbus_node_idr);
- idr_init(&kdbus_node_idr);
- }
- up_write(&kdbus_node_idr_lock);
+ ida_simple_remove(&kdbus_node_ida, safe.id);
kfree(safe.name);
diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h
index be125ce4fd58..970e02b08e9f 100644
--- a/ipc/kdbus/node.h
+++ b/ipc/kdbus/node.h
@@ -58,6 +58,8 @@ struct kdbus_node {
#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb)
+extern struct ida kdbus_node_ida;
+
void kdbus_node_init(struct kdbus_node *node, unsigned int type);
int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,

View File

@ -0,0 +1,24 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Thu, 9 Apr 2015 13:11:01 +0300
Subject: [PATCH] kdbus: uapi: Fix kernel-doc for enum kdbus_send_flags
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Acked-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/uapi/linux/kdbus.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h
index 2fe0a1c5056c..00a6e142c977 100644
--- a/include/uapi/linux/kdbus.h
+++ b/include/uapi/linux/kdbus.h
@@ -544,7 +544,7 @@ struct kdbus_msg_info {
* reply to this message. The
* KDBUS_CMD_SEND ioctl() will block
* until the reply is received, and
- * offset_reply in struct kdbus_msg will
+ * reply in struct kdbus_cmd_send will
* yield the offset in the sender's pool
* where the reply can be found.
* This flag is only valid if

View File

@ -0,0 +1,28 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Tue, 2 Jun 2015 18:48:47 +0300
Subject: [PATCH] kdbus: update kernel-doc for kdbus_sync_reply_wakeup()
kdbus_sync_reply_wakeup() doesn't remove reply object from connection
reply_list. Update function description.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/reply.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
index 008dca801627..89d355b44f63 100644
--- a/ipc/kdbus/reply.c
+++ b/ipc/kdbus/reply.c
@@ -140,8 +140,7 @@ void kdbus_reply_unlink(struct kdbus_reply *r)
* @reply: The reply object
* @err: Error code to set on the remote side
*
- * Remove the synchronous reply object from its connection reply_list, and
- * wake up remote peer (method origin) with the appropriate synchronous reply
+ * Wake up remote peer (method origin) with the appropriate synchronous reply
* code.
*/
void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err)

View File

@ -0,0 +1,29 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Thu, 4 Jun 2015 13:39:30 +0300
Subject: [PATCH] kdbus: use FIELD_SIZEOF in kdbus_member_set_user macro
sizeof(((_t *)0)->_m) -> FIELD_SIZEOF(_t, _m)
Use conventional macro according to chapter 17 of
Documentation/CodingStyle.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/util.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h
index 9fedf8ab41cd..529716669fe7 100644
--- a/ipc/kdbus/util.h
+++ b/ipc/kdbus/util.h
@@ -40,7 +40,7 @@
({ \
u64 __user *_sz = \
(void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \
- copy_to_user(_sz, _s, sizeof(((_t *)0)->_m)); \
+ copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \
})
/**

View File

@ -0,0 +1,31 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:00 +0300
Subject: [PATCH] kdbus: use parentheses uniformly in KDBUS_ITEMS_FOREACH macro
Enclose all arguments into parentheses to stay consistent across the
whole macro.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
ipc/kdbus/item.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h
index 32909e2e7954..bca63b4e6e80 100644
--- a/ipc/kdbus/item.h
+++ b/ipc/kdbus/item.h
@@ -28,10 +28,10 @@
#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE)
#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \
- for (_i = _is; \
+ for ((_i) = (_is); \
((u8 *)(_i) < (u8 *)(_is) + (_s)) && \
((u8 *)(_i) >= (u8 *)(_is)); \
- _i = KDBUS_ITEM_NEXT(_i))
+ (_i) = KDBUS_ITEM_NEXT(_i))
#define KDBUS_ITEM_VALID(_i, _is, _s) \
((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \

View File

@ -0,0 +1,44 @@
From: Daniel Mack <daniel@zonque.org>
Date: Sat, 18 Apr 2015 12:04:36 +0200
Subject: [PATCH] kdbus: use rcu to access exe file in metadata
Commit 90f31d0ea888 ("mm: rcu-protected get_mm_exe_file()") removed
mm->mmap_sem from mm->exe_file read side. Follow that change in the
kdbus metadata code.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
ipc/kdbus/metadata.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index 7949c8d3ed64..a85eac34a5c4 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -283,19 +283,21 @@ static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp)
static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp)
{
struct mm_struct *mm;
+ struct file *exe_file;
mm = get_task_mm(current);
if (!mm)
return;
- down_read(&mm->mmap_sem);
- if (mm->exe_file) {
- mp->exe_path = mm->exe_file->f_path;
+ rcu_read_lock();
+ exe_file = rcu_dereference(mm->exe_file);
+ if (exe_file) {
+ mp->exe_path = exe_file->f_path;
path_get(&mp->exe_path);
get_fs_root(current->fs, &mp->root_path);
mp->valid |= KDBUS_ATTACH_EXE;
}
- up_read(&mm->mmap_sem);
+ rcu_read_unlock();
mmput(mm);
}

View File

@ -67,7 +67,7 @@ Summary: The Linux kernel
# The rc snapshot level # The rc snapshot level
%define rcrev 1 %define rcrev 1
# The git snapshot level # The git snapshot level
%define gitrev 1 %define gitrev 2
# Set rpm version accordingly # Set rpm version accordingly
%define rpmversion 4.%{upstream_sublevel}.0 %define rpmversion 4.%{upstream_sublevel}.0
%endif %endif
@ -596,6 +596,162 @@ Patch502: firmware-Drop-WARN-from-usermodehelper_read_trylock-.patch
Patch503: drm-i915-turn-off-wc-mmaps.patch Patch503: drm-i915-turn-off-wc-mmaps.patch
Patch504: kdbus-add-documentation.patch
Patch505: kdbus-add-uapi-header-file.patch
Patch506: kdbus-add-driver-skeleton-ioctl-entry-points-and-uti.patch
Patch507: kdbus-add-connection-pool-implementation.patch
Patch508: kdbus-add-connection-queue-handling-and-message-vali.patch
Patch509: kdbus-add-node-and-filesystem-implementation.patch
Patch510: kdbus-add-code-to-gather-metadata.patch
Patch511: kdbus-add-code-for-notifications-and-matches.patch
Patch512: kdbus-add-code-for-buses-domains-and-endpoints.patch
Patch513: kdbus-add-name-registry-implementation.patch
Patch514: kdbus-add-policy-database-implementation.patch
Patch515: kdbus-add-Makefile-Kconfig-and-MAINTAINERS-entry.patch
Patch516: kdbus-add-walk-through-user-space-example.patch
Patch517: kdbus-add-selftests.patch
Patch518: Documentation-kdbus-fix-location-for-generated-files.patch
Patch519: kdbus-samples-kdbus-add-lrt.patch
Patch520: kdbus-fix-minor-typo-in-the-walk-through-example.patch
Patch521: samples-kdbus-drop-wrong-include.patch
Patch522: Documentation-kdbus-fix-out-of-tree-builds.patch
Patch523: Documentation-kdbus-support-quiet-builds.patch
Patch524: selftests-kdbus-fix-gitignore.patch
Patch525: Documentation-kdbus-replace-reply_cookie-with-cookie.patch
Patch526: kdbus-fix-header-guard-name.patch
Patch527: kdbus-connection-fix-handling-of-failed-fget.patch
Patch528: kdbus-Fix-CONFIG_KDBUS-help-text.patch
Patch529: samples-kdbus-build-kdbus-workers-conditionally.patch
Patch530: selftest-kdbus-enable-cross-compilation.patch
Patch531: kdbus-uapi-Fix-kernel-doc-for-enum-kdbus_send_flags.patch
Patch532: Documentation-kdbus-Fix-list-of-KDBUS_CMD_ENDPOINT_U.patch
Patch533: Documentation-kdbus-Update-list-of-ioctls-which-caus.patch
Patch534: Documentation-kdbus-Fix-description-of-KDBUS_SEND_SY.patch
Patch535: Documentation-kdbus-Fix-typos.patch
Patch536: kdbus-avoid-the-use-of-struct-timespec.patch
Patch537: kdbus-pool-use-__vfs_read.patch
Patch538: kdbus-skip-mandatory-items-on-negotiation.patch
Patch539: kdbus-turn-kdbus_node_idr-into-an-ida.patch
Patch540: kdbus-reduce-scope-of-handle-locking.patch
Patch541: kdbus-skip-acquiring-an-active-reference-in-poll.patch
Patch542: kdbus-remove-unused-linux-version.h-include.patch
Patch543: kdbus-optimize-auxgroup-collector.patch
Patch544: kdbus-drop-obsolete-WARN_ON.patch
Patch545: kdbus-copy-small-ioctl-payloads-to-stack.patch
Patch546: kdbus-drop-kdbus_meta_attach_mask-modparam.patch
Patch547: kdbus-fix-typo.patch
Patch548: kdbus-forward-ID-notifications-to-everyone.patch
Patch549: kdbus-provide-helper-to-collect-metadata.patch
Patch550: kdbus-make-metadata-on-broadcasts-reliable.patch
Patch551: samples-kdbus-stub-out-code-for-glibc-2.7.patch
Patch552: kdbus-fix-up-documentation-of-ioctl-handlers.patch
Patch553: kdbus-translate-capabilities-between-namespaces.patch
Patch554: kdbus-selftests-add-build-dependencies-on-headers.patch
Patch555: kdbus-use-rcu-to-access-exe-file-in-metadata.patch
Patch556: kdbus-no-need-to-ref-current-mm.patch
Patch557: selftests-kdbus-install-kdbus-test.patch
Patch558: kdbus-update-kernel-doc-for-kdbus_sync_reply_wakeup.patch
Patch559: kdbus-remove-redundant-code-from-kdbus_conn_entry_ma.patch
Patch560: kdbus-kdbus_item_validate-remove-duplicated-code.patch
Patch561: kdbus-kdbus_conn_connect-use-bus-instead-of-conn-ep-.patch
Patch562: kdbus-use-FIELD_SIZEOF-in-kdbus_member_set_user-macr.patch
Patch563: selftests-kdbus-handle-cap_get_proc-error-properly.patch
Patch564: selftests-kdbus-drop-useless-assignment.patch
Patch565: selftests-kdbus-remove-useless-initializations-from-.patch
Patch566: selftests-kdbus-drop-duplicated-code-from-__kdbus_ms.patch
Patch567: selftests-kdbus-fix-error-paths-in-__kdbus_msg_send.patch
Patch568: kdbus-drop-useless-goto.patch
Patch569: kdbus-fix-operator-precedence-issues-in-item-macros.patch
Patch570: kdbus-use-parentheses-uniformly-in-KDBUS_ITEMS_FOREA.patch
Patch571: Documentation-kdbus-fix-operator-precedence-issue-in.patch
Patch572: Documentation-kdbus-use-parentheses-uniformly-in-KDB.patch
Patch573: selftests-kdbus-fix-trivial-style-issues.patch
Patch574: selftests-kdbus-fix-precedence-issues-in-macros.patch
Patch575: selftests-kdbus-use-parentheses-in-iteration-macros-.patch
Patch576: samples-kdbus-add-whitespace.patch
Patch577: samples-kdbus-fix-operator-precedence-issue-in-KDBUS.patch
Patch578: samples-kdbus-use-parentheses-uniformly-in-KDBUS_FOR.patch
Patch579: kdbus-kdbus_reply_find-return-on-found-entry.patch
Patch580: kdbus-optimize-error-path-in-kdbus_reply_new.patch
Patch581: kdbus-optimize-if-statements-in-kdbus_conn_disconnec.patch
# END OF PATCH DEFINITIONS # END OF PATCH DEFINITIONS
@ -1266,6 +1422,162 @@ ApplyPatch firmware-Drop-WARN-from-usermodehelper_read_trylock-.patch
ApplyPatch drm-i915-turn-off-wc-mmaps.patch ApplyPatch drm-i915-turn-off-wc-mmaps.patch
ApplyPatch kdbus-add-documentation.patch
ApplyPatch kdbus-add-uapi-header-file.patch
ApplyPatch kdbus-add-driver-skeleton-ioctl-entry-points-and-uti.patch
ApplyPatch kdbus-add-connection-pool-implementation.patch
ApplyPatch kdbus-add-connection-queue-handling-and-message-vali.patch
ApplyPatch kdbus-add-node-and-filesystem-implementation.patch
ApplyPatch kdbus-add-code-to-gather-metadata.patch
ApplyPatch kdbus-add-code-for-notifications-and-matches.patch
ApplyPatch kdbus-add-code-for-buses-domains-and-endpoints.patch
ApplyPatch kdbus-add-name-registry-implementation.patch
ApplyPatch kdbus-add-policy-database-implementation.patch
ApplyPatch kdbus-add-Makefile-Kconfig-and-MAINTAINERS-entry.patch
ApplyPatch kdbus-add-walk-through-user-space-example.patch
ApplyPatch kdbus-add-selftests.patch
ApplyPatch Documentation-kdbus-fix-location-for-generated-files.patch
ApplyPatch kdbus-samples-kdbus-add-lrt.patch
ApplyPatch kdbus-fix-minor-typo-in-the-walk-through-example.patch
ApplyPatch samples-kdbus-drop-wrong-include.patch
ApplyPatch Documentation-kdbus-fix-out-of-tree-builds.patch
ApplyPatch Documentation-kdbus-support-quiet-builds.patch
ApplyPatch selftests-kdbus-fix-gitignore.patch
ApplyPatch Documentation-kdbus-replace-reply_cookie-with-cookie.patch
ApplyPatch kdbus-fix-header-guard-name.patch
ApplyPatch kdbus-connection-fix-handling-of-failed-fget.patch
ApplyPatch kdbus-Fix-CONFIG_KDBUS-help-text.patch
ApplyPatch samples-kdbus-build-kdbus-workers-conditionally.patch
ApplyPatch selftest-kdbus-enable-cross-compilation.patch
ApplyPatch kdbus-uapi-Fix-kernel-doc-for-enum-kdbus_send_flags.patch
ApplyPatch Documentation-kdbus-Fix-list-of-KDBUS_CMD_ENDPOINT_U.patch
ApplyPatch Documentation-kdbus-Update-list-of-ioctls-which-caus.patch
ApplyPatch Documentation-kdbus-Fix-description-of-KDBUS_SEND_SY.patch
ApplyPatch Documentation-kdbus-Fix-typos.patch
ApplyPatch kdbus-avoid-the-use-of-struct-timespec.patch
ApplyPatch kdbus-pool-use-__vfs_read.patch
ApplyPatch kdbus-skip-mandatory-items-on-negotiation.patch
ApplyPatch kdbus-turn-kdbus_node_idr-into-an-ida.patch
ApplyPatch kdbus-reduce-scope-of-handle-locking.patch
ApplyPatch kdbus-skip-acquiring-an-active-reference-in-poll.patch
ApplyPatch kdbus-remove-unused-linux-version.h-include.patch
ApplyPatch kdbus-optimize-auxgroup-collector.patch
ApplyPatch kdbus-drop-obsolete-WARN_ON.patch
ApplyPatch kdbus-copy-small-ioctl-payloads-to-stack.patch
ApplyPatch kdbus-drop-kdbus_meta_attach_mask-modparam.patch
ApplyPatch kdbus-fix-typo.patch
ApplyPatch kdbus-forward-ID-notifications-to-everyone.patch
ApplyPatch kdbus-provide-helper-to-collect-metadata.patch
ApplyPatch kdbus-make-metadata-on-broadcasts-reliable.patch
ApplyPatch samples-kdbus-stub-out-code-for-glibc-2.7.patch
ApplyPatch kdbus-fix-up-documentation-of-ioctl-handlers.patch
ApplyPatch kdbus-translate-capabilities-between-namespaces.patch
ApplyPatch kdbus-selftests-add-build-dependencies-on-headers.patch
ApplyPatch kdbus-use-rcu-to-access-exe-file-in-metadata.patch
ApplyPatch kdbus-no-need-to-ref-current-mm.patch
ApplyPatch selftests-kdbus-install-kdbus-test.patch
ApplyPatch kdbus-update-kernel-doc-for-kdbus_sync_reply_wakeup.patch
ApplyPatch kdbus-remove-redundant-code-from-kdbus_conn_entry_ma.patch
ApplyPatch kdbus-kdbus_item_validate-remove-duplicated-code.patch
ApplyPatch kdbus-kdbus_conn_connect-use-bus-instead-of-conn-ep-.patch
ApplyPatch kdbus-use-FIELD_SIZEOF-in-kdbus_member_set_user-macr.patch
ApplyPatch selftests-kdbus-handle-cap_get_proc-error-properly.patch
ApplyPatch selftests-kdbus-drop-useless-assignment.patch
ApplyPatch selftests-kdbus-remove-useless-initializations-from-.patch
ApplyPatch selftests-kdbus-drop-duplicated-code-from-__kdbus_ms.patch
ApplyPatch selftests-kdbus-fix-error-paths-in-__kdbus_msg_send.patch
ApplyPatch kdbus-drop-useless-goto.patch
ApplyPatch kdbus-fix-operator-precedence-issues-in-item-macros.patch
ApplyPatch kdbus-use-parentheses-uniformly-in-KDBUS_ITEMS_FOREA.patch
ApplyPatch Documentation-kdbus-fix-operator-precedence-issue-in.patch
ApplyPatch Documentation-kdbus-use-parentheses-uniformly-in-KDB.patch
ApplyPatch selftests-kdbus-fix-trivial-style-issues.patch
ApplyPatch selftests-kdbus-fix-precedence-issues-in-macros.patch
ApplyPatch selftests-kdbus-use-parentheses-in-iteration-macros-.patch
ApplyPatch samples-kdbus-add-whitespace.patch
ApplyPatch samples-kdbus-fix-operator-precedence-issue-in-KDBUS.patch
ApplyPatch samples-kdbus-use-parentheses-uniformly-in-KDBUS_FOR.patch
ApplyPatch kdbus-kdbus_reply_find-return-on-found-entry.patch
ApplyPatch kdbus-optimize-error-path-in-kdbus_reply_new.patch
ApplyPatch kdbus-optimize-if-statements-in-kdbus_conn_disconnec.patch
# END OF PATCH APPLICATIONS # END OF PATCH APPLICATIONS
@ -2131,6 +2443,12 @@ fi
# #
# #
%changelog %changelog
* Wed Jul 08 2015 Josh Boyer <jwboyer@fedoraproject.org> - 4.2.0-0.rc1.git2.1
- Linux v4.2-rc1-33-gd6ac4ffc61ac
* Tue Jul 07 2015 Josh Boyer <jwboyer@fedoraproject.org>
- Add kdbus
* Tue Jul 07 2015 Josh Boyer <jwboyer@fedoraproject.org> - 4.2.0-0.rc1.git1.1 * Tue Jul 07 2015 Josh Boyer <jwboyer@fedoraproject.org> - 4.2.0-0.rc1.git1.1
- Linux v4.2-rc1-17-gc7e9ad7da219 - Linux v4.2-rc1-17-gc7e9ad7da219
- Reenable debugging options. - Reenable debugging options.

View File

@ -0,0 +1,24 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:06 +0300
Subject: [PATCH] samples/kdbus: add whitespace
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/kdbus/kdbus-api.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h
index 5ed5907c5cb4..2de4d6a8c51e 100644
--- a/samples/kdbus/kdbus-api.h
+++ b/samples/kdbus/kdbus-api.h
@@ -13,7 +13,7 @@
for (iter = (first); \
((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
((uint8_t *)(iter) >= (uint8_t *)(first)); \
- iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
+ iter = (void *)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd)
{

View File

@ -0,0 +1,47 @@
From: Daniel Mack <daniel@zonque.org>
Date: Tue, 31 Mar 2015 15:11:34 +0200
Subject: [PATCH] samples: kdbus: build kdbus-workers conditionally
Give the kdbus sample its own config switch and only build it if it's
explicitly switched on.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Reported-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/Kconfig | 7 +++++++
samples/kdbus/Makefile | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/samples/Kconfig b/samples/Kconfig
index 224ebb46bed5..a4c6b2f8fa85 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -55,6 +55,13 @@ config SAMPLE_KDB
Build an example of how to dynamically add the hello
command to the kdb shell.
+config SAMPLE_KDBUS
+ bool "Build kdbus API example"
+ depends on KDBUS
+ help
+ Build an example of how the kdbus API can be used from
+ userspace.
+
config SAMPLE_RPMSG_CLIENT
tristate "Build rpmsg client sample -- loadable modules only"
depends on RPMSG && m
diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile
index e714602b6260..137f84272099 100644
--- a/samples/kdbus/Makefile
+++ b/samples/kdbus/Makefile
@@ -1,7 +1,7 @@
# kbuild trick to avoid linker error. Can be omitted if a module is built.
obj- := dummy.o
-hostprogs-y += kdbus-workers
+hostprogs-$(CONFIG_SAMPLE_KDBUS) += kdbus-workers
always := $(hostprogs-y)

View File

@ -0,0 +1,32 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 16 Mar 2015 10:17:10 +0100
Subject: [PATCH] samples/kdbus: drop wrong include
There is no reason to use ./include/uapi/ directly from samples. If your
system headers are not up-to-date, you _need_ to run "make
headers-install" (which will install them to ./usr/ in your kernel tree)
before building the examples. Otherwise, you will get warnings and build
failures.
Once ./usr/ is updated with the correct headers, it contains everything we
need, so drop -Iinclude/uapi from the kdbus-workers CFLAGS.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/kdbus/Makefile | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile
index eee9b9aed632..e714602b6260 100644
--- a/samples/kdbus/Makefile
+++ b/samples/kdbus/Makefile
@@ -5,7 +5,5 @@ hostprogs-y += kdbus-workers
always := $(hostprogs-y)
-HOSTCFLAGS_kdbus-workers.o += \
- -I$(objtree)/usr/include/ \
- -I$(objtree)/include/uapi/
+HOSTCFLAGS_kdbus-workers.o += -I$(objtree)/usr/include
HOSTLOADLIBES_kdbus-workers := -lrt

View File

@ -0,0 +1,33 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:07 +0300
Subject: [PATCH] samples/kdbus: fix operator precedence issue in
KDBUS_ITEM_NEXT macro
`item' argument in KDBUS_ITEM_NEXT macro is not enclosed into
parentheses when the cast operator is applied, which leads to improper
type conversion if `item' is supplied as a complex expression, e.g.
KDBUS_ITEM_NEXT(condition ? a : b)
Use parentheses properly to guarantee right precedence.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/kdbus/kdbus-api.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h
index 2de4d6a8c51e..fab873b89d97 100644
--- a/samples/kdbus/kdbus-api.h
+++ b/samples/kdbus/kdbus-api.h
@@ -8,7 +8,7 @@
#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
#define KDBUS_FOREACH(iter, first, _size) \
for (iter = (first); \
((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \

View File

@ -0,0 +1,83 @@
From: Daniel Mack <daniel@zonque.org>
Date: Fri, 3 Apr 2015 12:41:52 +0200
Subject: [PATCH] samples/kdbus: stub out code for glibc < 2.7
Andrew Morton reports the following build error in samples/kdbus on Fedora
Core 6:
samples/kdbus/kdbus-workers.c:73:26: error: sys/signalfd.h: No such file or directory
samples/kdbus/kdbus-workers.c: In function 'master_new':
samples/kdbus/kdbus-workers.c:231: warning: implicit declaration of function 'signalfd'
samples/kdbus/kdbus-workers.c:231: error: 'SFD_CLOEXEC' undeclared (first use in this function)
samples/kdbus/kdbus-workers.c:231: error: (Each undeclared identifier is reported only once
samples/kdbus/kdbus-workers.c:231: error: for each function it appears in.)
samples/kdbus/kdbus-workers.c: In function 'master_handle_signal':
samples/kdbus/kdbus-workers.c:406: error: storage size of 'val' isn't known
samples/kdbus/kdbus-workers.c:406: warning: unused variable 'val'
samples/kdbus/kdbus-workers.c: In function 'child_run':
samples/kdbus/kdbus-workers.c:773: error: 'CLOCK_MONOTONIC_COARSE' undeclared (first use in this function)
samples/kdbus/kdbus-workers.c: In function 'bus_open_connection':
samples/kdbus/kdbus-workers.c:1038: error: 'O_CLOEXEC' undeclared (first use in this function)
samples/kdbus/kdbus-workers.c: In function 'bus_make':
samples/kdbus/kdbus-workers.c:1275: error: 'O_CLOEXEC' undeclared (first use in this function)
Fedora Core 6 was released in 2006, which predates the introduction of
signalfds in the kernel (v2.6.22, 2007).
The example cannot be built without signalfds, and kbuild cannot depend on
specific features of the local libc when building userspace executables, so
we have to work around the issue by checking for specific glibc versions at
compile time and stub the entire thing if it can't be compiled.
Reported-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
samples/kdbus/kdbus-workers.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c
index d331e0186899..c3ba958639f3 100644
--- a/samples/kdbus/kdbus-workers.c
+++ b/samples/kdbus/kdbus-workers.c
@@ -57,6 +57,12 @@
* top-down, but requires some forward-declarations. Just ignore those.
*/
+#include <stdio.h>
+#include <stdlib.h>
+
+/* glibc < 2.7 does not ship sys/signalfd.h */
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -65,8 +71,6 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/poll.h>
@@ -1324,3 +1328,18 @@ static int bus_make(uid_t uid, const char *name)
return fd;
}
+
+#else
+
+#warning "Skipping compilation due to unsupported libc version"
+
+int main(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Compilation of %s was skipped due to unsupported libc.\n",
+ argv[0]);
+
+ return EXIT_FAILURE;
+}
+
+#endif /* libc sanity check */

View File

@ -0,0 +1,32 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:08 +0300
Subject: [PATCH] samples/kdbus: use parentheses uniformly in KDBUS_FOREACH
macro
Enclose all arguments into parentheses to stay consistent across the
whole macro.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
samples/kdbus/kdbus-api.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h
index fab873b89d97..7f3abae18396 100644
--- a/samples/kdbus/kdbus-api.h
+++ b/samples/kdbus/kdbus-api.h
@@ -10,10 +10,10 @@
#define KDBUS_ITEM_NEXT(item) \
(typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
#define KDBUS_FOREACH(iter, first, _size) \
- for (iter = (first); \
+ for ((iter) = (first); \
((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
((uint8_t *)(iter) >= (uint8_t *)(first)); \
- iter = (void *)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
+ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size)))
static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd)
{

View File

@ -0,0 +1,33 @@
From: Tyler Baker <tyler.baker@linaro.org>
Date: Wed, 1 Apr 2015 16:20:16 -0700
Subject: [PATCH] selftest/kdbus: enable cross compilation
Use the CC variable instead of hard coding gcc and include lib.mk.
Signed-off-by: Tyler Baker <tyler.baker@linaro.org>
Acked-by: Shuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/Makefile | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile
index f6cfab26f315..de8242f9b00e 100644
--- a/tools/testing/selftests/kdbus/Makefile
+++ b/tools/testing/selftests/kdbus/Makefile
@@ -33,11 +33,13 @@ OBJS= \
all: kdbus-test
+include ../lib.mk
+
%.o: %.c
- gcc $(CFLAGS) -c $< -o $@
+ $(CC) $(CFLAGS) -c $< -o $@
kdbus-test: $(OBJS)
- gcc $(CFLAGS) $^ $(LDLIBS) -o $@
+ $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@
run_tests:
./kdbus-test --tap

View File

@ -0,0 +1,29 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 19:33:27 +0300
Subject: [PATCH] selftests/kdbus: drop duplicated code from __kdbus_msg_send()
Set value of `size' in one step instead of four.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-util.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
index 5b924531d938..d35ec89cb816 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.c
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
@@ -462,10 +462,7 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
int memfd = -1;
int ret;
- size = sizeof(*msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
+ size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
if (dst_id == KDBUS_DST_ID_BROADCAST)
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;

View File

@ -0,0 +1,33 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 19:33:25 +0300
Subject: [PATCH] selftests/kdbus: drop useless assignment
Assign returned file descriptor directly to `fd', without intermediate
`ret' variable.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-util.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
index 6909fb9b1ce5..5b924531d938 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.c
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
@@ -408,11 +408,9 @@ int sys_memfd_create(const char *name, __u64 size)
{
int ret, fd;
- ret = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
- if (ret < 0)
- return ret;
-
- fd = ret;
+ fd = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
+ if (fd < 0)
+ return fd;
ret = ftruncate(fd, size);
if (ret < 0) {

View File

@ -0,0 +1,110 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 19:33:28 +0300
Subject: [PATCH] selftests/kdbus: fix error paths in __kdbus_msg_send()
Handle errors properly, free allocated resources.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-util.c | 31 ++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
index d35ec89cb816..9fac4b31536d 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.c
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
@@ -452,8 +452,8 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
uint64_t cmd_flags,
int cancel_fd)
{
- struct kdbus_cmd_send *cmd;
- struct kdbus_msg *msg;
+ struct kdbus_cmd_send *cmd = NULL;
+ struct kdbus_msg *msg = NULL;
const char ref1[1024 * 128 + 3] = "0123456789_0";
const char ref2[] = "0123456789_1";
struct kdbus_item *item;
@@ -476,14 +476,14 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
ret = -errno;
kdbus_printf("writing to memfd failed: %m\n");
- return ret;
+ goto out;
}
ret = sys_memfd_seal_set(memfd);
if (ret < 0) {
ret = -errno;
kdbus_printf("memfd sealing failed: %m\n");
- return ret;
+ goto out;
}
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
@@ -496,7 +496,7 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
if (!msg) {
ret = -errno;
kdbus_printf("unable to malloc()!?\n");
- return ret;
+ goto out;
}
if (dst_id == KDBUS_DST_ID_BROADCAST)
@@ -514,7 +514,7 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
if (timeout) {
ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
if (ret < 0)
- return ret;
+ goto out;
msg->timeout_ns = now.tv_sec * 1000000000ULL +
now.tv_nsec + timeout;
@@ -565,6 +565,12 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
cmd = malloc(size);
+ if (!cmd) {
+ ret = -errno;
+ kdbus_printf("unable to malloc()!?\n");
+ goto out;
+ }
+
cmd->size = size;
cmd->flags = cmd_flags;
cmd->msg_address = (uintptr_t)msg;
@@ -579,12 +585,9 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
}
ret = kdbus_cmd_send(conn->fd, cmd);
- if (memfd >= 0)
- close(memfd);
-
if (ret < 0) {
kdbus_printf("error sending message: %d (%m)\n", ret);
- return ret;
+ goto out;
}
if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
@@ -598,13 +601,17 @@ static int __kdbus_msg_send(const struct kdbus_conn *conn,
ret = kdbus_free(conn, cmd->reply.offset);
if (ret < 0)
- return ret;
+ goto out;
}
+out:
free(msg);
free(cmd);
- return 0;
+ if (memfd >= 0)
+ close(memfd);
+
+ return ret < 0 ? ret : 0;
}
int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,

View File

@ -0,0 +1,24 @@
From: David Herrmann <dh.herrmann@gmail.com>
Date: Mon, 16 Mar 2015 10:17:13 +0100
Subject: [PATCH] selftests/kdbus: fix gitignore
Drop unused elements from .gitignore (which are leftovers when
documentation was placed in the same directory).
Add "kdbus-test" to .gitignore, which is the test binary of all kdbus
selftests.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/.gitignore | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kdbus/.gitignore b/tools/testing/selftests/kdbus/.gitignore
index 7b421f76c888..d3ef42f6ada6 100644
--- a/tools/testing/selftests/kdbus/.gitignore
+++ b/tools/testing/selftests/kdbus/.gitignore
@@ -1,3 +1 @@
-*.7
-manpage.*
-*.proc
+kdbus-test

View File

@ -0,0 +1,53 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:04 +0300
Subject: [PATCH] selftests/kdbus: fix precedence issues in macros
`item' argument in KDBUS_ITEM_NEXT macro is not enclosed into
parentheses when the cast operator is applied, which leads to improper
type conversion if `item' is supplied as a complex expression, e.g.
KDBUS_ITEM_NEXT(condition ? a : b)
RUN_CLONE_CHILD macro has similar issue, missing parentheses around
`clone_ret' when using indirection operator.
Use parentheses properly to guarantee right precedence.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-util.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h
index b53b03f0565c..df5721ee8f54 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.h
+++ b/tools/testing/selftests/kdbus/kdbus-util.h
@@ -27,7 +27,7 @@
#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
+ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
#define KDBUS_ITEM_FOREACH(item, head, first) \
for (item = (head)->first; \
((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
@@ -104,7 +104,7 @@ extern int kdbus_util_verbose;
_setup_; \
efd = eventfd(0, EFD_CLOEXEC); \
ASSERT_RETURN(efd >= 0); \
- *clone_ret = 0; \
+ *(clone_ret) = 0; \
pid = syscall(__NR_clone, flags, NULL); \
if (pid == 0) { \
eventfd_t event_status = 0; \
@@ -129,7 +129,7 @@ extern int kdbus_util_verbose;
ret = TEST_OK; \
} else { \
ret = -errno; \
- *clone_ret = -errno; \
+ *(clone_ret) = -errno; \
} \
close(efd); \
ret; \

View File

@ -0,0 +1,98 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:03 +0300
Subject: [PATCH] selftests/kdbus: fix trivial style issues
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-enum.h | 1 +
tools/testing/selftests/kdbus/kdbus-util.c | 2 +-
tools/testing/selftests/kdbus/kdbus-util.h | 21 +++++++++------------
3 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-enum.h b/tools/testing/selftests/kdbus/kdbus-enum.h
index a67cec3512a7..ed28cca26906 100644
--- a/tools/testing/selftests/kdbus/kdbus-enum.h
+++ b/tools/testing/selftests/kdbus/kdbus-enum.h
@@ -6,6 +6,7 @@
* Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*/
+
#pragma once
const char *enum_CMD(long long id);
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
index 9fac4b31536d..29a0cb1aace2 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.c
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
@@ -1355,7 +1355,7 @@ static int all_ids_are_mapped(const char *path)
return 0;
}
-int all_uids_gids_are_mapped()
+int all_uids_gids_are_mapped(void)
{
int ret;
diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h
index 50ff07140bdd..b53b03f0565c 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.h
+++ b/tools/testing/selftests/kdbus/kdbus-util.h
@@ -7,6 +7,7 @@
* Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*/
+
#pragma once
#define BIT(X) (1 << (X))
@@ -30,24 +31,22 @@
#define KDBUS_ITEM_FOREACH(item, head, first) \
for (item = (head)->first; \
((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
- ((uint8_t *)(item) >= (uint8_t *)(head)); \
+ ((uint8_t *)(item) >= (uint8_t *)(head)); \
item = KDBUS_ITEM_NEXT(item))
#define KDBUS_FOREACH(iter, first, _size) \
for (iter = (first); \
((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
((uint8_t *)(iter) >= (uint8_t *)(first)); \
- iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
-
+ iter = (void *)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
-#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL))
+#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL))
/* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */
-#define KDBUS_ATTACH_ITEMS_TYPE_SUM \
- ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \
- ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2 ) + \
+#define KDBUS_ATTACH_ITEMS_TYPE_SUM \
+ ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \
+ ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2) + \
(_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR))
-
#define POOL_SIZE (16 * 1024LU * 1024LU)
#define UNPRIV_UID 65534
@@ -207,14 +206,12 @@ int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
uint64_t type, uint64_t id);
int kdbus_add_match_empty(struct kdbus_conn *conn);
-int all_uids_gids_are_mapped();
+int all_uids_gids_are_mapped(void);
int drop_privileges(uid_t uid, gid_t gid);
uint64_t now(clockid_t clock);
char *unique_name(const char *prefix);
-int userns_map_uid_gid(pid_t pid,
- const char *map_uid,
- const char *map_gid);
+int userns_map_uid_gid(pid_t pid, const char *map_uid, const char *map_gid);
int test_is_capable(int cap, ...);
int config_user_ns_is_enabled(void);
int config_auditsyscall_is_enabled(void);

View File

@ -0,0 +1,26 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 19:33:24 +0300
Subject: [PATCH] selftests/kdbus: handle cap_get_proc() error properly
Fix typo in checking error value of cap_get_proc(): cap -> caps
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
index 4b376ecfdbed..6909fb9b1ce5 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.c
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
@@ -1547,7 +1547,7 @@ int test_is_capable(int cap, ...)
cap_t caps;
caps = cap_get_proc();
- if (!cap) {
+ if (!caps) {
ret = -errno;
kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
return ret;

View File

@ -0,0 +1,27 @@
From: Tyler Baker <tyler.baker@linaro.org>
Date: Tue, 21 Apr 2015 15:50:51 -0700
Subject: [PATCH] selftests/kdbus: install kdbus-test
Set TEST_PROGS so that kdbus-test is installed.
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Tyler Baker <tyler.baker@linaro.org>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile
index 7ad587b3c767..8f36cb5667cc 100644
--- a/tools/testing/selftests/kdbus/Makefile
+++ b/tools/testing/selftests/kdbus/Makefile
@@ -40,6 +40,8 @@ include ../lib.mk
kdbus-test: $(OBJS)
$(CC) $(CFLAGS) $^ $(LDLIBS) -o $@
+TEST_PROGS := kdbus-test
+
run_tests:
./kdbus-test --tap

View File

@ -0,0 +1,40 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 17 Jun 2015 19:33:26 +0300
Subject: [PATCH] selftests/kdbus: remove useless initializations from
kdbus_clone_userns_test()
Do not initialize efd, unpriv_conn_id, userns_conn_id and monitor. These
vars are assigned to values later in code while initial values are never
used.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/test-metadata-ns.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/kdbus/test-metadata-ns.c b/tools/testing/selftests/kdbus/test-metadata-ns.c
index 2cb1d4d2a5be..ccdfae06922b 100644
--- a/tools/testing/selftests/kdbus/test-metadata-ns.c
+++ b/tools/testing/selftests/kdbus/test-metadata-ns.c
@@ -281,16 +281,13 @@ out:
static int kdbus_clone_userns_test(const char *bus,
struct kdbus_conn *conn)
{
- int ret;
- int status;
- int efd = -1;
+ int ret, status, efd;
pid_t pid, ppid;
- uint64_t unpriv_conn_id = 0;
- uint64_t userns_conn_id = 0;
+ uint64_t unpriv_conn_id, userns_conn_id;
struct kdbus_msg *msg;
const struct kdbus_item *item;
struct kdbus_pids expected_pids;
- struct kdbus_conn *monitor = NULL;
+ struct kdbus_conn *monitor;
kdbus_printf("STARTING TEST 'metadata-ns'.\n");

View File

@ -0,0 +1,39 @@
From: Sergei Zviagintsev <sergei@s15v.net>
Date: Wed, 10 Jun 2015 00:00:05 +0300
Subject: [PATCH] selftests/kdbus: use parentheses in iteration macros
uniformly
Enclose all arguments into parentheses in KDBUS_ITEM_FOREACH and
KDBUS_FOREACH macros to stay consistent across the whole macro.
Signed-off-by: Sergei Zviagintsev <sergei@s15v.net>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/kdbus/kdbus-util.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h
index df5721ee8f54..d1a0f1b4d0eb 100644
--- a/tools/testing/selftests/kdbus/kdbus-util.h
+++ b/tools/testing/selftests/kdbus/kdbus-util.h
@@ -29,15 +29,15 @@
#define KDBUS_ITEM_NEXT(item) \
(typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
#define KDBUS_ITEM_FOREACH(item, head, first) \
- for (item = (head)->first; \
+ for ((item) = (head)->first; \
((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
((uint8_t *)(item) >= (uint8_t *)(head)); \
- item = KDBUS_ITEM_NEXT(item))
+ (item) = KDBUS_ITEM_NEXT(item))
#define KDBUS_FOREACH(iter, first, _size) \
- for (iter = (first); \
+ for ((iter) = (first); \
((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
((uint8_t *)(iter) >= (uint8_t *)(first)); \
- iter = (void *)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
+ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size)))
#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL))

View File

@ -1,4 +1,4 @@
fe9dc0f6729f36400ea81aa41d614c37 linux-4.1.tar.xz fe9dc0f6729f36400ea81aa41d614c37 linux-4.1.tar.xz
84e34c2f58901edcc5c840fe9893c02e perf-man-4.1.tar.gz 84e34c2f58901edcc5c840fe9893c02e perf-man-4.1.tar.gz
bfd9e8391b982eedf8037d697ab7c1b6 patch-4.2-rc1.xz bfd9e8391b982eedf8037d697ab7c1b6 patch-4.2-rc1.xz
db7c9450437995d8bb6f2fcc577ac612 patch-4.2-rc1-git1.xz 8909d96e27719907f8126216d6a8b4f5 patch-4.2-rc1-git2.xz