Message ID | 20230608135653.2918540-7-eblake@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | qemu patches for 64-bit NBD extensions | expand |
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 <eblake@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> > --- > > 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_REQUESTS 16 > > -#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) > [..]
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 <eblake@redhat.com> > > Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Thanks; for now, I'll just leave this one as-is.
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_REQUESTS 16 -#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(&s->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(&s->requests_lock); qemu_co_mutex_lock(&s->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(&s->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(&s->free_sema); qemu_mutex_unlock(&s->requests_lock);
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 <eblake@redhat.com> --- v4: new patch --- block/nbd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)