Skip to content

Commit 5fa48a0

Browse files
committed
libbtrfs: fix potentially unaligned access
Same fix a previous commit, unaligned access on strict alignment hosts could produce wrong results (reported on send/receive and arm5). As libbtrfs has own copy of the code fix it here too, replacing leXX_to_cpu with get_unaligned_leXX where appropriate. This means any access to raw buffers that get cast to a structure. Issue: #770 Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 09a5fe6 commit 5fa48a0

File tree

2 files changed

+12
-11
lines changed

2 files changed

+12
-11
lines changed

libbtrfs/ctree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,7 +1615,7 @@ void write_extent_buffer(struct extent_buffer *eb, const void *src,
16151615
static inline u##bits btrfs_##name(const struct extent_buffer *eb) \
16161616
{ \
16171617
const struct btrfs_header *h = (struct btrfs_header *)eb->data; \
1618-
return le##bits##_to_cpu(h->member); \
1618+
return get_unaligned_le##bits(&h->member); \
16191619
} \
16201620
static inline void btrfs_set_##name(struct extent_buffer *eb, \
16211621
u##bits val) \
@@ -1643,7 +1643,7 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
16431643
#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
16441644
static inline u##bits btrfs_##name(const type *s) \
16451645
{ \
1646-
return le##bits##_to_cpu(s->member); \
1646+
return get_unaligned_le##bits(&s->member); \
16471647
} \
16481648
static inline void btrfs_set_##name(type *s, u##bits val) \
16491649
{ \

libbtrfs/send-stream.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,10 @@ static int read_cmd(struct btrfs_send_stream *sctx)
119119
goto out;
120120
}
121121

122+
/* No data alignment is guaranteed. */
122123
sctx->cmd_hdr = (struct btrfs_cmd_header *)sctx->read_buf;
123-
cmd = le16_to_cpu(sctx->cmd_hdr->cmd);
124-
cmd_len = le32_to_cpu(sctx->cmd_hdr->len);
124+
cmd = get_unaligned_le16(&sctx->cmd_hdr->cmd);
125+
cmd_len = get_unaligned_le32(&sctx->cmd_hdr->len);
125126

126127
if (cmd_len + sizeof(*sctx->cmd_hdr) >= sizeof(sctx->read_buf)) {
127128
ret = -EINVAL;
@@ -140,8 +141,8 @@ static int read_cmd(struct btrfs_send_stream *sctx)
140141
goto out;
141142
}
142143

143-
crc = le32_to_cpu(sctx->cmd_hdr->crc);
144-
sctx->cmd_hdr->crc = 0;
144+
crc = get_unaligned_le32(&sctx->cmd_hdr->crc);
145+
put_unaligned_le32(0, &sctx->cmd_hdr->crc);
145146

146147
crc2 = crc32c(0, (unsigned char*)sctx->read_buf,
147148
sizeof(*sctx->cmd_hdr) + cmd_len);
@@ -159,8 +160,8 @@ static int read_cmd(struct btrfs_send_stream *sctx)
159160
u16 tlv_len;
160161

161162
tlv_hdr = (struct btrfs_tlv_header *)data;
162-
tlv_type = le16_to_cpu(tlv_hdr->tlv_type);
163-
tlv_len = le16_to_cpu(tlv_hdr->tlv_len);
163+
tlv_type = get_unaligned_le16(&tlv_hdr->tlv_type);
164+
tlv_len = get_unaligned_le16(&tlv_hdr->tlv_len);
164165

165166
if (tlv_type == 0 || tlv_type > BTRFS_SEND_A_MAX) {
166167
fprintf(stderr,
@@ -203,7 +204,7 @@ static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *l
203204
goto out;
204205
}
205206

206-
*len = le16_to_cpu(hdr->tlv_len);
207+
*len = get_unaligned_le16(&hdr->tlv_len);
207208
*data = hdr + 1;
208209

209210
ret = 0;
@@ -282,8 +283,8 @@ static int tlv_get_timespec(struct btrfs_send_stream *sctx,
282283
TLV_GET(sctx, attr, (void**)&bts, &len);
283284
TLV_CHECK_LEN(sizeof(*bts), len);
284285

285-
ts->tv_sec = le64_to_cpu(bts->sec);
286-
ts->tv_nsec = le32_to_cpu(bts->nsec);
286+
ts->tv_sec = get_unaligned_le64(&bts->sec);
287+
ts->tv_nsec = get_unaligned_le32(&bts->nsec);
287288
ret = 0;
288289

289290
tlv_get_failed:

0 commit comments

Comments
 (0)