From 4df9a546c52b4e96fbf1f35010ba14a4f3bc076e Mon Sep 17 00:00:00 2001 From: Dmitry Ashkadov Date: Thu, 30 Jun 2022 11:52:15 +0300 Subject: [PATCH] Use get_unaligned_be*() to avoid UB In most cases using strict aliasing is undefined behaviour. Obviously cdb is supposed to be an array of bytes and accessing any CDB field using strict aliasing leads to misaligned read which may cause even a crash. Signed-off-by: Dmitry Ashkadov --- api.c | 14 +++++++------- be_byteshift.h | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/api.c b/api.c index d55da0a8..6ffbcd1f 100644 --- a/api.c +++ b/api.c @@ -67,14 +67,14 @@ uint64_t tcmu_cdb_get_lba(uint8_t *cdb) switch (tcmu_cdb_get_length(cdb)) { case 6: - val = be16toh(*((uint16_t *)&cdb[2])); + val = get_unaligned_be16(&cdb[2]); return ((cdb[1] & 0x1f) << 16) | val; case 10: - return be32toh(*((u_int32_t *)&cdb[2])); + return get_unaligned_be32(&cdb[2]); case 12: - return be32toh(*((u_int32_t *)&cdb[2])); + return get_unaligned_be32(&cdb[2]); case 16: - return be64toh(*((u_int64_t *)&cdb[2])); + return get_unaligned_be64(&cdb[2]); default: assert(0); return 0; /* not reached */ @@ -87,11 +87,11 @@ uint32_t tcmu_cdb_get_xfer_length(uint8_t *cdb) case 6: return cdb[4]; case 10: - return be16toh(*((uint16_t *)&cdb[7])); + return get_unaligned_be16(&cdb[7]); case 12: - return be32toh(*((u_int32_t *)&cdb[6])); + return get_unaligned_be32(&cdb[6]); case 16: - return be32toh(*((u_int32_t *)&cdb[10])); + return get_unaligned_be32(&cdb[10]); default: assert(0); return 0; /* not reached */ diff --git a/be_byteshift.h b/be_byteshift.h index 96650688..98054d3b 100644 --- a/be_byteshift.h +++ b/be_byteshift.h @@ -9,6 +9,11 @@ #ifndef _TCMU_BE_BYTESHIFT_H #define _TCMU_BE_BYTESHIFT_H +#include +#include +#include + + static inline void __put_unaligned_be32(uint32_t val, uint8_t *p) { *p++ = val >> 24; @@ -48,9 +53,22 @@ static inline uint32_t __get_unaligned_be32(const uint8_t *p) return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; } -static inline uint16_t get_unaligned_be32(const void *p) +static inline uint32_t get_unaligned_be32(const void *p) { return __get_unaligned_be32(p); } +static inline uint64_t get_unaligned_be64(const void *p) +{ + uint64_t val; + memcpy(&val, p, sizeof(val)); + return be64toh(val); +} + +static inline void put_unaligned_be64(uint64_t val, void *p) +{ + val = htobe64(val); + memcpy(p, &val, sizeof(val)); +} + #endif