diff --git a/libnvme-1.7-stack_smashing_1.patch b/libnvme-1.7-stack_smashing_1.patch new file mode 100644 index 0000000..057d74f --- /dev/null +++ b/libnvme-1.7-stack_smashing_1.patch @@ -0,0 +1,55 @@ +From a2b8e52e46cfd888ac5a48d8ce632bd70a5caa93 Mon Sep 17 00:00:00 2001 +From: Tomas Bzatek +Date: Tue, 10 Oct 2023 18:16:24 +0200 +Subject: [PATCH] util: Introduce alloc helper with alignment support + +Similar to nvme-cli an alloc helper is needed for a couple +of ioctls sent out during tree scan. + +Signed-off-by: Tomas Bzatek +--- + src/nvme/private.h | 2 ++ + src/nvme/util.c | 13 +++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/src/nvme/private.h b/src/nvme/private.h +index 6fb9784a..ee9d738b 100644 +--- a/src/nvme/private.h ++++ b/src/nvme/private.h +@@ -182,6 +182,8 @@ nvme_ctrl_t __nvme_lookup_ctrl(nvme_subsystem_t s, const char *transport, + const char *host_iface, const char *trsvcid, + const char *subsysnqn, nvme_ctrl_t p); + ++void *__nvme_alloc(size_t len); ++ + #if (LOG_FUNCNAME == 1) + #define __nvme_log_func __func__ + #else +diff --git a/src/nvme/util.c b/src/nvme/util.c +index 8fe094d5..20679685 100644 +--- a/src/nvme/util.c ++++ b/src/nvme/util.c +@@ -7,6 +7,7 @@ + * Chaitanya Kulkarni + */ + ++#include + #include + #include + #include +@@ -1058,3 +1059,15 @@ bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const cha + } + + #endif /* HAVE_NETDB */ ++ ++void *__nvme_alloc(size_t len) ++{ ++ size_t _len = round_up(len, 0x1000); ++ void *p; ++ ++ if (posix_memalign((void *)&p, getpagesize(), _len)) ++ return NULL; ++ ++ memset(p, 0, _len); ++ return p; ++} diff --git a/libnvme-1.7-stack_smashing_2.patch b/libnvme-1.7-stack_smashing_2.patch new file mode 100644 index 0000000..74d0a2a --- /dev/null +++ b/libnvme-1.7-stack_smashing_2.patch @@ -0,0 +1,62 @@ +From 68c6ffb11d40a427fc1fd70ac2ac97fd01952913 Mon Sep 17 00:00:00 2001 +From: Tomas Bzatek +Date: Tue, 10 Oct 2023 18:18:38 +0200 +Subject: [PATCH] tree: Allocate aligned payloads for ns scan + +libnvme is actually doing some namespace identification +during tree scan, leading to stack smash on some systems. + +Signed-off-by: Tomas Bzatek +--- + src/nvme/tree.c | 29 ++++++++++++++++++----------- + 1 file changed, 18 insertions(+), 11 deletions(-) + +diff --git a/src/nvme/tree.c b/src/nvme/tree.c +index 00cf96f7..5636aa18 100644 +--- a/src/nvme/tree.c ++++ b/src/nvme/tree.c +@@ -2404,26 +2404,33 @@ static void nvme_ns_parse_descriptors(struct nvme_ns *n, + + static int nvme_ns_init(struct nvme_ns *n) + { +- struct nvme_id_ns ns = { }; +- uint8_t buffer[NVME_IDENTIFY_DATA_SIZE] = { }; +- struct nvme_ns_id_desc *descs = (void *)buffer; ++ struct nvme_id_ns *ns; ++ struct nvme_ns_id_desc *descs; + uint8_t flbas; + int ret; + +- ret = nvme_ns_identify(n, &ns); +- if (ret) ++ ns = __nvme_alloc(sizeof(*ns)); ++ if (!ns) ++ return 0; ++ ret = nvme_ns_identify(n, ns); ++ if (ret) { ++ free(ns); + return ret; ++ } + +- nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &flbas); +- n->lba_shift = ns.lbaf[flbas].ds; ++ nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); ++ n->lba_shift = ns->lbaf[flbas].ds; + n->lba_size = 1 << n->lba_shift; +- n->lba_count = le64_to_cpu(ns.nsze); +- n->lba_util = le64_to_cpu(ns.nuse); +- n->meta_size = le16_to_cpu(ns.lbaf[flbas].ms); ++ n->lba_count = le64_to_cpu(ns->nsze); ++ n->lba_util = le64_to_cpu(ns->nuse); ++ n->meta_size = le16_to_cpu(ns->lbaf[flbas].ms); + +- if (!nvme_ns_identify_descs(n, descs)) ++ descs = __nvme_alloc(NVME_IDENTIFY_DATA_SIZE); ++ if (descs && !nvme_ns_identify_descs(n, descs)) + nvme_ns_parse_descriptors(n, descs); + ++ free(ns); ++ free(descs); + return 0; + } + diff --git a/libnvme-1.7-stack_smashing_3.patch b/libnvme-1.7-stack_smashing_3.patch new file mode 100644 index 0000000..beb7822 --- /dev/null +++ b/libnvme-1.7-stack_smashing_3.patch @@ -0,0 +1,119 @@ +From 3bf6e153a1c02b1c684ac3f5949cd32dec5f46c9 Mon Sep 17 00:00:00 2001 +From: Tomas Bzatek +Date: Thu, 12 Oct 2023 18:42:34 +0200 +Subject: [PATCH] linux: Allocate aligned payloads for id_ctrl and id_ns calls + +Signed-off-by: Tomas Bzatek +--- + src/nvme/linux.c | 61 ++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 43 insertions(+), 18 deletions(-) + +diff --git a/src/nvme/linux.c b/src/nvme/linux.c +index adbc4cdb..66be9eb8 100644 +--- a/src/nvme/linux.c ++++ b/src/nvme/linux.c +@@ -124,28 +124,37 @@ int nvme_fw_download_seq(int fd, __u32 size, __u32 xfer, __u32 offset, + + int nvme_get_telemetry_max(int fd, enum nvme_telemetry_da *da, size_t *data_tx) + { +- struct nvme_id_ctrl id_ctrl; +- int err = nvme_identify_ctrl(fd, &id_ctrl); ++ struct nvme_id_ctrl *id_ctrl; ++ int err; + +- if (err) ++ id_ctrl = __nvme_alloc(sizeof(*id_ctrl)); ++ if (!id_ctrl) { ++ errno = ENOMEM; ++ return -1; ++ } ++ err = nvme_identify_ctrl(fd, id_ctrl); ++ if (err) { ++ free(id_ctrl); + return err; ++ } + + if (data_tx) { +- *data_tx = id_ctrl.mdts; +- if (id_ctrl.mdts) { ++ *data_tx = id_ctrl->mdts; ++ if (id_ctrl->mdts) { + /* assuming CAP.MPSMIN is zero minimum Memory Page Size is at least + * 4096 bytes + */ +- *data_tx = (1 << id_ctrl.mdts) * 4096; ++ *data_tx = (1 << id_ctrl->mdts) * 4096; + } + } + if (da) { +- if (id_ctrl.lpa & 0x8) ++ if (id_ctrl->lpa & 0x8) + *da = NVME_TELEMETRY_DA_3; +- if (id_ctrl.lpa & 0x40) ++ if (id_ctrl->lpa & 0x40) + *da = NVME_TELEMETRY_DA_4; + + } ++ free(id_ctrl); + return err; + } + +@@ -376,32 +385,48 @@ int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, + + int nvme_get_ana_log_len(int fd, size_t *analen) + { +- struct nvme_id_ctrl ctrl; ++ struct nvme_id_ctrl *ctrl; + int ret; + +- ret = nvme_identify_ctrl(fd, &ctrl); +- if (ret) ++ ctrl = __nvme_alloc(sizeof(*ctrl)); ++ if (!ctrl) { ++ errno = ENOMEM; ++ return -1; ++ } ++ ret = nvme_identify_ctrl(fd, ctrl); ++ if (ret) { ++ free(ctrl); + return ret; ++ } + + *analen = sizeof(struct nvme_ana_log) + +- le32_to_cpu(ctrl.nanagrpid) * sizeof(struct nvme_ana_group_desc) + +- le32_to_cpu(ctrl.mnan) * sizeof(__le32); ++ le32_to_cpu(ctrl->nanagrpid) * sizeof(struct nvme_ana_group_desc) + ++ le32_to_cpu(ctrl->mnan) * sizeof(__le32); ++ free(ctrl); + return 0; + } + + int nvme_get_logical_block_size(int fd, __u32 nsid, int *blksize) + { +- struct nvme_id_ns ns; ++ struct nvme_id_ns *ns; + __u8 flbas; + int ret; + +- ret = nvme_identify_ns(fd, nsid, &ns); +- if (ret) ++ ns = __nvme_alloc(sizeof(*ns)); ++ if (!ns) { ++ errno = ENOMEM; ++ return -1; ++ } ++ ret = nvme_identify_ns(fd, nsid, ns); ++ if (ret) { ++ free(ns); + return ret; ++ } + +- nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &flbas); +- *blksize = 1 << ns.lbaf[flbas].ds; ++ nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); ++ *blksize = 1 << ns->lbaf[flbas].ds; + ++ free(ns); + return 0; + } + diff --git a/libnvme-1.7-stack_smashing_4.patch b/libnvme-1.7-stack_smashing_4.patch new file mode 100644 index 0000000..d208a19 --- /dev/null +++ b/libnvme-1.7-stack_smashing_4.patch @@ -0,0 +1,77 @@ +From da8c28e5e220be4742442114252d136097056928 Mon Sep 17 00:00:00 2001 +From: Tomas Bzatek +Date: Thu, 12 Oct 2023 18:43:16 +0200 +Subject: [PATCH] fabrics: Allocate aligned payloads for id_ctrl and discovery + log calls + +Signed-off-by: Tomas Bzatek +--- + src/nvme/fabrics.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c +index 21fb2920..2e48ac86 100644 +--- a/src/nvme/fabrics.c ++++ b/src/nvme/fabrics.c +@@ -1073,7 +1073,7 @@ static struct nvmf_discovery_log *nvme_discovery_log(nvme_ctrl_t c, + size = sizeof(struct nvmf_discovery_log); + + free(log); +- log = calloc(1, size); ++ log = __nvme_alloc(size); + if (!log) { + nvme_msg(r, LOG_ERR, + "could not allocate memory for discovery log header\n"); +@@ -1105,7 +1105,7 @@ static struct nvmf_discovery_log *nvme_discovery_log(nvme_ctrl_t c, + sizeof(struct nvmf_disc_log_entry) * numrec; + + free(log); +- log = calloc(1, size); ++ log = __nvme_alloc(size); + if (!log) { + nvme_msg(r, LOG_ERR, + "could not alloc memory for discovery log page\n"); +@@ -1709,26 +1709,35 @@ static const char *dctype_str[] = { + */ + static int nvme_fetch_cntrltype_dctype_from_id(nvme_ctrl_t c) + { +- struct nvme_id_ctrl id = { 0 }; ++ struct nvme_id_ctrl *id; + int ret; + +- ret = nvme_ctrl_identify(c, &id); +- if (ret) ++ id = __nvme_alloc(sizeof(*id)); ++ if (!id) { ++ errno = ENOMEM; ++ return -1; ++ } ++ ++ ret = nvme_ctrl_identify(c, id); ++ if (ret) { ++ free(id); + return ret; ++ } + + if (!c->cntrltype) { +- if (id.cntrltype > NVME_CTRL_CNTRLTYPE_ADMIN || !cntrltype_str[id.cntrltype]) ++ if (id->cntrltype > NVME_CTRL_CNTRLTYPE_ADMIN || !cntrltype_str[id->cntrltype]) + c->cntrltype = strdup("reserved"); + else +- c->cntrltype = strdup(cntrltype_str[id.cntrltype]); ++ c->cntrltype = strdup(cntrltype_str[id->cntrltype]); + } + +- if (!c->dctype) { +- if (id.dctype > NVME_CTRL_DCTYPE_CDC || !dctype_str[id.dctype]) ++ if (!c->dctype) { ++ if (id->dctype > NVME_CTRL_DCTYPE_CDC || !dctype_str[id->dctype]) + c->dctype = strdup("reserved"); + else +- c->dctype = strdup(dctype_str[id.dctype]); ++ c->dctype = strdup(dctype_str[id->dctype]); + } ++ free(id); + return 0; + } + diff --git a/libnvme.spec b/libnvme.spec index 9e26178..1d6d613 100644 --- a/libnvme.spec +++ b/libnvme.spec @@ -4,11 +4,16 @@ Name: libnvme Summary: Linux-native nvme device management library Version: 1.6 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPL-2.1-or-later URL: https://github.com/linux-nvme/libnvme Source0: %{url}/archive/v%{version_no_tilde}/%{name}-%{version_no_tilde}.tar.gz +Patch0: libnvme-1.7-stack_smashing_1.patch +Patch1: libnvme-1.7-stack_smashing_2.patch +Patch2: libnvme-1.7-stack_smashing_3.patch +Patch3: libnvme-1.7-stack_smashing_4.patch + BuildRequires: gcc gcc-c++ BuildRequires: swig BuildRequires: python3-devel @@ -97,6 +102,9 @@ mv %{buildroot}/usr/*.rst %{buildroot}%{_pkgdocdir}/ %{python3_sitearch}/libnvme/* %changelog +* Tue Oct 24 2023 Tomas Bzatek - 1.6-2 +- Backport stack smashing fixes (#2245707) + * Fri Sep 29 2023 Tomas Bzatek - 1.6-1 - Upstream v1.6 release