Re: [PATCH v4 06/24] nbd/client: Simplify cookie vs. index computation

2023-06-12 Thread Eric Blake
On Mon, Jun 12, 2023 at 05:27:19PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> On 08.06.23 16:56, Eric Blake wrote:
> > Our code relies on a sentinel cookie value of zero for deciding when a
> > packet has been handled, as well as relying on array indices between 0
> > and MAX_NBD_REQUESTS-1 for dereferencing purposes.  As long as we can
> > symmetrically convert between two forms, there is no reason to go with
> > the odd choice of using XOR with a random pointer, when we can instead
> > simplify the mappings with a mere offset of 1.
> 
> Should we go further and use (uint64)-1 as a sentinel cookie value, and just 
> use index as a cookie?  Or, using zero cookie in a wire looks too asymmetric?

I thought about that too, but in the end I decided it would require
auditing more lines of code to make sure I was catching all places
where we currently expected a zero sentinel (where some of those uses
are not obvious, because of things like hiding behind g_new0).  And
there is indeed the argument that if data corruption is going to
happen, it's harder to tell if an all-zero field on the wire was
intentional than a non-zero field.

> 
> > 
> > Signed-off-by: Eric Blake 
> 
> Reviewed-by: Vladimir Sementsov-Ogievskiy 

Thanks; for now, I'll just leave this one as-is.


-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v4 06/24] nbd/client: Simplify cookie vs. index computation

2023-06-12 Thread Vladimir Sementsov-Ogievskiy

On 08.06.23 16:56, Eric Blake wrote:

Our code relies on a sentinel cookie value of zero for deciding when a
packet has been handled, as well as relying on array indices between 0
and MAX_NBD_REQUESTS-1 for dereferencing purposes.  As long as we can
symmetrically convert between two forms, there is no reason to go with
the odd choice of using XOR with a random pointer, when we can instead
simplify the mappings with a mere offset of 1.


Should we go further and use (uint64)-1 as a sentinel cookie value, and just 
use index as a cookie?  Or, using zero cookie in a wire looks too asymmetric?



Signed-off-by: Eric Blake 


Reviewed-by: Vladimir Sementsov-Ogievskiy 


---

v4: new patch
---
  block/nbd.c | 16 
  1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index be3c46c6fee..5322e66166c 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -50,8 +50,8 @@
  #define EN_OPTSTR ":exportname="
  #define MAX_NBD_REQUESTS16

-#define COOKIE_TO_INDEX(bs, cookie) ((cookie) ^ (uint64_t)(intptr_t)(bs))
-#define INDEX_TO_COOKIE(bs, index)  ((index)  ^ (uint64_t)(intptr_t)(bs))


That looked like some security trick to hide real indices. But I don't think 
that index of request in a list is a secret information.


+#define COOKIE_TO_INDEX(cookie) ((cookie) - 1)
+#define INDEX_TO_COOKIE(index)  ((index) + 1)



[..]

--
Best regards,
Vladimir




[PATCH v4 06/24] nbd/client: Simplify cookie vs. index computation

2023-06-08 Thread Eric Blake
Our code relies on a sentinel cookie value of zero for deciding when a
packet has been handled, as well as relying on array indices between 0
and MAX_NBD_REQUESTS-1 for dereferencing purposes.  As long as we can
symmetrically convert between two forms, there is no reason to go with
the odd choice of using XOR with a random pointer, when we can instead
simplify the mappings with a mere offset of 1.

Signed-off-by: Eric Blake 
---

v4: new patch
---
 block/nbd.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index be3c46c6fee..5322e66166c 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -50,8 +50,8 @@
 #define EN_OPTSTR ":exportname="
 #define MAX_NBD_REQUESTS16

-#define COOKIE_TO_INDEX(bs, cookie) ((cookie) ^ (uint64_t)(intptr_t)(bs))
-#define INDEX_TO_COOKIE(bs, index)  ((index)  ^ (uint64_t)(intptr_t)(bs))
+#define COOKIE_TO_INDEX(cookie) ((cookie) - 1)
+#define INDEX_TO_COOKIE(index)  ((index) + 1)

 typedef struct {
 Coroutine *coroutine;
@@ -420,7 +420,7 @@ static void coroutine_fn GRAPH_RDLOCK 
nbd_reconnect_attempt(BDRVNBDState *s)
 static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t cookie)
 {
 int ret;
-uint64_t ind = COOKIE_TO_INDEX(s, cookie), ind2;
+uint64_t ind = COOKIE_TO_INDEX(cookie), ind2;
 QEMU_LOCK_GUARD(>receive_mutex);

 while (true) {
@@ -435,7 +435,7 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState 
*s, uint64_t cookie)
  * woken by whoever set s->reply.cookie (or never wait in this
  * yield). So, we should not wake it here.
  */
-ind2 = COOKIE_TO_INDEX(s, s->reply.cookie);
+ind2 = COOKIE_TO_INDEX(s->reply.cookie);
 assert(!s->requests[ind2].receiving);

 s->requests[ind].receiving = true;
@@ -468,7 +468,7 @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState 
*s, uint64_t cookie)
 nbd_channel_error(s, -EINVAL);
 return -EINVAL;
 }
-ind2 = COOKIE_TO_INDEX(s, s->reply.cookie);
+ind2 = COOKIE_TO_INDEX(s->reply.cookie);
 if (ind2 >= MAX_NBD_REQUESTS || !s->requests[ind2].coroutine) {
 nbd_channel_error(s, -EINVAL);
 return -EINVAL;
@@ -519,7 +519,7 @@ nbd_co_send_request(BlockDriverState *bs, NBDRequest 
*request,
 qemu_mutex_unlock(>requests_lock);

 qemu_co_mutex_lock(>send_mutex);
-request->cookie = INDEX_TO_COOKIE(s, i);
+request->cookie = INDEX_TO_COOKIE(i);

 assert(s->ioc);

@@ -832,7 +832,7 @@ static coroutine_fn int nbd_co_do_receive_one_chunk(
 int *request_ret, QEMUIOVector *qiov, void **payload, Error **errp)
 {
 int ret;
-int i = COOKIE_TO_INDEX(s, cookie);
+int i = COOKIE_TO_INDEX(cookie);
 void *local_payload = NULL;
 NBDStructuredReplyChunk *chunk;

@@ -1038,7 +1038,7 @@ static bool coroutine_fn 
nbd_reply_chunk_iter_receive(BDRVNBDState *s,

 break_loop:
 qemu_mutex_lock(>requests_lock);
-s->requests[COOKIE_TO_INDEX(s, cookie)].coroutine = NULL;
+s->requests[COOKIE_TO_INDEX(cookie)].coroutine = NULL;
 s->in_flight--;
 qemu_co_queue_next(>free_sema);
 qemu_mutex_unlock(>requests_lock);
-- 
2.40.1