Skip to content

Commit 42d54ec

Browse files
committed
nbd: Use uint64_t instead of char[8] for cookie
Type-punning *(uint64_t*)(char[8]) is unsafe if the pointer is not aligned per the requirements of the hardware (x86_64 has 1-byte alignment, but other hardware exists that will give a SIGBUS). In practice, it didn't matter - 'struct nbd_request' was already 64-bit aligned for 'from' (even before the recent change in commit 739f712 to pack it), and 'struct nbd_reply' being packed means the compiler emits code to deal with 1-byte alignment despite hardware. But since the cookie is already opaque on the server side, we might as well treat it as an 8-byte integer instead of a character array, with no visible semantic changes to the client. This patch does NOT perform endian swapping on the value. As long as we are consistent (no swap when reading from the client, no swap when writing back to the client), the client sees the same value. If we were to log the cookie at any point in our local handling, then it would be nice to obey the spec that all NBD values sent over the wire are in network byte order (big-endian), so that what we log appears as a 64-bit value with endianness matching whatever wireshark or the client might be logging as well. But since we aren't logging the cookie, skipping the byte-swaps doesn't hurt. Signed-off-by: Eric Blake <[email protected]> Message-Id: <[email protected]>
1 parent e6efa7c commit 42d54ec

File tree

5 files changed

+27
-30
lines changed

5 files changed

+27
-30
lines changed

nbd-server.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,7 +1274,7 @@ int rawexpwrite_fully(off_t a, char *buf, size_t len, CLIENT *client, int fua) {
12741274
static void setup_reply(struct nbd_reply* rep, struct nbd_request* req) {
12751275
rep->magic = htonl(NBD_REPLY_MAGIC);
12761276
rep->error = 0;
1277-
memcpy(&(rep->cookie), &(req->cookie), sizeof(req->cookie));
1277+
rep->cookie = req->cookie;
12781278
}
12791279

12801280
static void log_reply(CLIENT *client, struct nbd_reply *prply) {
@@ -1298,7 +1298,7 @@ void send_structured_chunk(CLIENT *client, struct nbd_request *req, uint16_t fla
12981298
rep.magic = htonl(NBD_STRUCTURED_REPLY_MAGIC);
12991299
rep.flags = htons(flags);
13001300
rep.type = htons(type);
1301-
memcpy(&(rep.cookie), req->cookie, sizeof(rep.cookie));
1301+
rep.cookie = req->cookie;
13021302
rep.paylen = htonl(length);
13031303
pthread_mutex_lock(&(client->lock));
13041304
socket_write(client, &rep, sizeof rep);
@@ -1315,7 +1315,7 @@ void send_structured_chunk_v(CLIENT *client, struct nbd_request *req, uint16_t f
13151315
rep.magic = htonl(NBD_STRUCTURED_REPLY_MAGIC);
13161316
rep.flags = htons(flags);
13171317
rep.type = htons(type);
1318-
memcpy(&(rep.cookie), req->cookie, sizeof(rep.cookie));
1318+
rep.cookie = req->cookie;
13191319
rep.paylen = htonl(length);
13201320
va_start(ap, bufcount);
13211321
pthread_mutex_lock(&(client->lock));
@@ -2223,7 +2223,7 @@ static void setup_transactionlog(CLIENT *client) {
22232223

22242224
req.magic = htonl(NBD_TRACELOG_MAGIC);
22252225
req.type = htonl(NBD_TRACELOG_SET_DATALOG);
2226-
memset(req.cookie, 0, sizeof(req.cookie));
2226+
req.cookie = 0;
22272227
req.from = htonll(NBD_TRACELOG_FROM_MAGIC);
22282228
req.len = htonl(TRUE);
22292229

nbd-trdump.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ int main(int argc, char**argv) {
7070
switch (magic) {
7171
case NBD_REQUEST_MAGIC:
7272
doread(readfd, sizeof(magic)+(char *)(&req), sizeof(struct nbd_request)-sizeof(magic));
73-
cookie = ntohll(*((long long int *)(req.cookie)));
73+
cookie = ntohll(req.cookie);
7474
offset = ntohll(req.from);
7575
len = ntohl(req.len);
7676
command = ntohl(req.type);
@@ -99,7 +99,7 @@ int main(int argc, char**argv) {
9999
break;
100100
case NBD_REPLY_MAGIC:
101101
doread(readfd, sizeof(magic)+(char *)(&rep), sizeof(struct nbd_reply)-sizeof(magic));
102-
cookie = ntohll(*((long long int *)(rep.cookie)));
102+
cookie = ntohll(rep.cookie);
103103
error = ntohl(rep.error);
104104

105105
printf("< H=%016llx E=0x%08x\n",
@@ -109,7 +109,7 @@ int main(int argc, char**argv) {
109109

110110
case NBD_TRACELOG_MAGIC:
111111
doread(readfd, sizeof(magic)+(char *)(&req), sizeof(struct nbd_request)-sizeof(magic));
112-
cookie = ntohll(*((long long int *)(req.cookie)));
112+
cookie = ntohll(req.cookie);
113113
offset = ntohll(req.from);
114114
len = ntohl(req.len);
115115
command = ntohl(req.type);

nbd-trplay.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ int main_loop(int logfd, int imagefd) {
163163
switch (magic) {
164164
case NBD_REQUEST_MAGIC:
165165
doread(logfd, sizeof(magic)+(char *)(&req), sizeof(struct nbd_request)-sizeof(magic));
166-
cookie = ntohll(*((long long int *)(req.cookie)));
166+
cookie = ntohll(req.cookie);
167167
offset = ntohll(req.from);
168168
len = ntohl(req.len);
169169
command = ntohl(req.type);
@@ -185,7 +185,7 @@ int main_loop(int logfd, int imagefd) {
185185

186186
case NBD_REPLY_MAGIC:
187187
doread(logfd, sizeof(magic)+(char *)(&rep), sizeof(struct nbd_reply)-sizeof(magic));
188-
cookie = ntohll(*((long long int *)(rep.cookie)));
188+
cookie = ntohll(rep.cookie);
189189
error = ntohl(rep.error);
190190

191191
if (g_verbose >= VERBOSE_NORMAL) {
@@ -197,7 +197,7 @@ int main_loop(int logfd, int imagefd) {
197197

198198
case NBD_TRACELOG_MAGIC:
199199
doread(logfd, sizeof(magic)+(char *)(&req), sizeof(struct nbd_request)-sizeof(magic));
200-
cookie = ntohll(*((long long int *)(req.cookie)));
200+
cookie = ntohll(req.cookie);
201201
offset = ntohll(req.from);
202202
len = ntohl(req.len);
203203
command = ntohl(req.type);

nbd.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ enum {
9090
struct nbd_request {
9191
uint32_t magic;
9292
uint32_t type; /* == READ || == WRITE */
93-
char cookie[8];
93+
uint64_t cookie;
9494
uint64_t from;
9595
uint32_t len;
9696
} __attribute__ ((packed));
@@ -102,7 +102,7 @@ struct nbd_request {
102102
struct nbd_reply {
103103
uint32_t magic;
104104
uint32_t error; /* 0 = ok, else error */
105-
char cookie[8]; /* cookie you got from request */
105+
uint64_t cookie; /* cookie you got from request */
106106
} __attribute__ ((packed));
107107

108108
/*

tests/run/nbd-tester-client.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ typedef enum {
7474

7575
struct reqcontext {
7676
uint64_t seq;
77-
char origcookie[8];
77+
uint64_t origcookie;
7878
struct nbd_request req;
7979
struct reqcontext *next;
8080
struct reqcontext *prev;
@@ -680,7 +680,7 @@ int close_connection(int sock, CLOSE_TYPE type)
680680
case CONNECTION_CLOSE_PROPERLY:
681681
req.magic = htonl(NBD_REQUEST_MAGIC);
682682
req.type = htonl(NBD_CMD_DISC);
683-
memcpy(&(req.cookie), &(counter), sizeof(counter));
683+
req.cookie = htonll(counter);
684684
counter++;
685685
req.from = 0;
686686
req.len = 0;
@@ -720,8 +720,8 @@ int read_packet_check_header(int sock, size_t datasize, long long int curcookie)
720720
"Received package with incorrect reply_magic. Index of sent packages is %lld (0x%llX), received cookie is %lld (0x%llX). Received magic 0x%lX, expected 0x%lX",
721721
(long long int)curcookie,
722722
(long long unsigned int)curcookie,
723-
(long long int)*((u64 *) rep.cookie),
724-
(long long unsigned int)*((u64 *) rep.cookie),
723+
(long long int)rep.cookie,
724+
(long long unsigned int)rep.cookie,
725725
(long unsigned int)rep.magic,
726726
(long unsigned int)NBD_REPLY_MAGIC);
727727
retval = -1;
@@ -731,8 +731,8 @@ int read_packet_check_header(int sock, size_t datasize, long long int curcookie)
731731
snprintf(errstr, errstr_len,
732732
"Received error from server: %ld (0x%lX). Cookie is %lld (0x%llX).",
733733
(long int)rep.error, (long unsigned int)rep.error,
734-
(long long int)(*((u64 *) rep.cookie)),
735-
(long long unsigned int)*((u64 *) rep.cookie));
734+
(long long int)rep.cookie,
735+
(long long unsigned int)rep.cookie);
736736
retval = -2;
737737
goto end;
738738
}
@@ -767,7 +767,7 @@ int oversize_test(char *name, int sock, char close_sock, int testflags)
767767
req.magic = htonl(NBD_REQUEST_MAGIC);
768768
req.type = htonl(NBD_CMD_READ);
769769
req.len = htonl(1024 * 1024);
770-
memcpy(&(req.cookie), &i, sizeof(i));
770+
req.cookie = htonll(i);
771771
req.from = htonll(i);
772772
WRITE_ALL_ERR_RT(sock, &req, sizeof(req), err, -1,
773773
"Could not write request: %s", strerror(errno));
@@ -971,7 +971,7 @@ int throughput_test(char *name, int sock, char close_sock, int testflags)
971971
if (sendfua)
972972
req.type =
973973
htonl(NBD_CMD_WRITE | NBD_CMD_FLAG_FUA);
974-
memcpy(&(req.cookie), &i, sizeof(i));
974+
req.cookie = htonll(i);
975975
req.from = htonll(i);
976976
if (write_all(sock, &req, sizeof(req)) < 0) {
977977
retval = -1;
@@ -987,7 +987,7 @@ int throughput_test(char *name, int sock, char close_sock, int testflags)
987987
if (sendflush) {
988988
long long int j = i ^ (1LL << 63);
989989
req.type = htonl(NBD_CMD_FLUSH);
990-
memcpy(&(req.cookie), &j, sizeof(j));
990+
req.cookie = htonll(j);
991991
req.from = 0;
992992
req.len = 0;
993993
if (write_all(sock, &req, sizeof(req)) < 0) {
@@ -1334,7 +1334,7 @@ int integrity_test(char *name, int sock, char close_sock, int testflags)
13341334
"Could not read transaction log: %s",
13351335
strerror(errno));
13361336
prc->req.magic = htonl(NBD_REQUEST_MAGIC);
1337-
memcpy(prc->origcookie, prc->req.cookie, 8);
1337+
prc->origcookie = htonll(prc->req.cookie);
13381338
prc->seq = seq++;
13391339
if ((ntohl(prc->req.type) &
13401340
NBD_CMD_MASK_COMMAND) == NBD_CMD_DISC) {
@@ -1439,9 +1439,8 @@ int integrity_test(char *name, int sock, char close_sock, int testflags)
14391439

14401440
dumpcommand("Sending command", prc->req.type);
14411441
/* we rewrite the cookie as they otherwise may not be unique */
1442-
*((uint64_t *) (prc->req.cookie)) =
1443-
getrandomcookie(cookiehash);
1444-
g_hash_table_insert(cookiehash, prc->req.cookie,
1442+
prc->req.cookie = getrandomcookie(cookiehash);
1443+
g_hash_table_insert(cookiehash, &prc->req.cookie,
14451444
prc);
14461445
addbuffer(&txbuf, &(prc->req),
14471446
sizeof(struct nbd_request));
@@ -1538,20 +1537,18 @@ int integrity_test(char *name, int sock, char close_sock, int testflags)
15381537
}
15391538

15401539
uint64_t cookie;
1541-
memcpy(&cookie, rep.cookie, 8);
1540+
cookie = rep.cookie;
15421541
prc = g_hash_table_lookup(cookiehash, &cookie);
15431542
if (!prc) {
15441543
snprintf(errstr, errstr_len,
15451544
"Unrecognised cookie in reply: 0x%llX",
1546-
*(long long unsigned int *)(rep.
1547-
cookie));
1545+
(long long unsigned int)rep.cookie);
15481546
goto err_open;
15491547
}
15501548
if (!g_hash_table_remove(cookiehash, &cookie)) {
15511549
snprintf(errstr, errstr_len,
15521550
"Could not remove cookie from hash: 0x%llX",
1553-
*(long long unsigned int *)(rep.
1554-
cookie));
1551+
(long long unsigned int)rep.cookie);
15551552
goto err_open;
15561553
}
15571554

0 commit comments

Comments
 (0)