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>
This commit is contained in:
parent
09a5fe669f
commit
5fa48a03c5
|
@ -1615,7 +1615,7 @@ void write_extent_buffer(struct extent_buffer *eb, const void *src,
|
|||
static inline u##bits btrfs_##name(const struct extent_buffer *eb) \
|
||||
{ \
|
||||
const struct btrfs_header *h = (struct btrfs_header *)eb->data; \
|
||||
return le##bits##_to_cpu(h->member); \
|
||||
return get_unaligned_le##bits(&h->member); \
|
||||
} \
|
||||
static inline void btrfs_set_##name(struct extent_buffer *eb, \
|
||||
u##bits val) \
|
||||
|
@ -1643,7 +1643,7 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
|
|||
#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
|
||||
static inline u##bits btrfs_##name(const type *s) \
|
||||
{ \
|
||||
return le##bits##_to_cpu(s->member); \
|
||||
return get_unaligned_le##bits(&s->member); \
|
||||
} \
|
||||
static inline void btrfs_set_##name(type *s, u##bits val) \
|
||||
{ \
|
||||
|
|
|
@ -119,9 +119,10 @@ static int read_cmd(struct btrfs_send_stream *sctx)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* No data alignment is guaranteed. */
|
||||
sctx->cmd_hdr = (struct btrfs_cmd_header *)sctx->read_buf;
|
||||
cmd = le16_to_cpu(sctx->cmd_hdr->cmd);
|
||||
cmd_len = le32_to_cpu(sctx->cmd_hdr->len);
|
||||
cmd = get_unaligned_le16(&sctx->cmd_hdr->cmd);
|
||||
cmd_len = get_unaligned_le32(&sctx->cmd_hdr->len);
|
||||
|
||||
if (cmd_len + sizeof(*sctx->cmd_hdr) >= sizeof(sctx->read_buf)) {
|
||||
ret = -EINVAL;
|
||||
|
@ -140,8 +141,8 @@ static int read_cmd(struct btrfs_send_stream *sctx)
|
|||
goto out;
|
||||
}
|
||||
|
||||
crc = le32_to_cpu(sctx->cmd_hdr->crc);
|
||||
sctx->cmd_hdr->crc = 0;
|
||||
crc = get_unaligned_le32(&sctx->cmd_hdr->crc);
|
||||
put_unaligned_le32(0, &sctx->cmd_hdr->crc);
|
||||
|
||||
crc2 = crc32c(0, (unsigned char*)sctx->read_buf,
|
||||
sizeof(*sctx->cmd_hdr) + cmd_len);
|
||||
|
@ -159,8 +160,8 @@ static int read_cmd(struct btrfs_send_stream *sctx)
|
|||
u16 tlv_len;
|
||||
|
||||
tlv_hdr = (struct btrfs_tlv_header *)data;
|
||||
tlv_type = le16_to_cpu(tlv_hdr->tlv_type);
|
||||
tlv_len = le16_to_cpu(tlv_hdr->tlv_len);
|
||||
tlv_type = get_unaligned_le16(&tlv_hdr->tlv_type);
|
||||
tlv_len = get_unaligned_le16(&tlv_hdr->tlv_len);
|
||||
|
||||
if (tlv_type == 0 || tlv_type > BTRFS_SEND_A_MAX) {
|
||||
fprintf(stderr,
|
||||
|
@ -203,7 +204,7 @@ static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *l
|
|||
goto out;
|
||||
}
|
||||
|
||||
*len = le16_to_cpu(hdr->tlv_len);
|
||||
*len = get_unaligned_le16(&hdr->tlv_len);
|
||||
*data = hdr + 1;
|
||||
|
||||
ret = 0;
|
||||
|
@ -282,8 +283,8 @@ static int tlv_get_timespec(struct btrfs_send_stream *sctx,
|
|||
TLV_GET(sctx, attr, (void**)&bts, &len);
|
||||
TLV_CHECK_LEN(sizeof(*bts), len);
|
||||
|
||||
ts->tv_sec = le64_to_cpu(bts->sec);
|
||||
ts->tv_nsec = le32_to_cpu(bts->nsec);
|
||||
ts->tv_sec = get_unaligned_le64(&bts->sec);
|
||||
ts->tv_nsec = get_unaligned_le32(&bts->nsec);
|
||||
ret = 0;
|
||||
|
||||
tlv_get_failed:
|
||||
|
|
Loading…
Reference in New Issue