Blob Blame History Raw
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);