From c9e77ba2b34e91fe3fe01f6a6cc3e16fd8888fa5 Mon Sep 17 00:00:00 2001 From: zhangxingrong Date: Fri, 16 Aug 2024 11:20:24 +0800 Subject: [PATCH] add some upstream patchs update libnfs.spec. Signed-off-by: zhangxingrong delete backport-Fix-compiler-warnings-and-a-subtle-precedence-error.patch --- ...id-explicit-memset-calls-with-calloc.patch | 435 ++++++++++++++++++ ...ounds-reading-of-v4-READLINK-results.patch | 34 ++ ...-memory-leak-in-nfs4_set_client_name.patch | 21 + libnfs.spec | 11 +- 4 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 backport-Avoid-explicit-memset-calls-with-calloc.patch create mode 100644 backport-Fix-out-of-bounds-reading-of-v4-READLINK-results.patch create mode 100644 backport-libnfs-fix-memory-leak-in-nfs4_set_client_name.patch diff --git a/backport-Avoid-explicit-memset-calls-with-calloc.patch b/backport-Avoid-explicit-memset-calls-with-calloc.patch new file mode 100644 index 0000000..75bda59 --- /dev/null +++ b/backport-Avoid-explicit-memset-calls-with-calloc.patch @@ -0,0 +1,435 @@ +From 5d228d2645510c4f03ce603dbfc6f1054ac78ef4 Mon Sep 17 00:00:00 2001 +From: Volker Lendecke +Date: Mon, 19 Feb 2024 13:56:17 +0100 +Subject: [PATCH] Avoid explicit memset calls with calloc + +--- + lib/nfs_v4.c | 84 ++++++++++++++++++---------------------------------- + 1 file changed, 28 insertions(+), 56 deletions(-) + +diff --git a/lib/nfs_v4.c b/lib/nfs_v4.c +index b1dfab5e..852ee91f 100644 +--- a/lib/nfs_v4.c ++++ b/lib/nfs_v4.c +@@ -274,13 +274,12 @@ init_cb_data_full_path(struct nfs_context *nfs, const char *path) + { + struct nfs4_cb_data *data; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return NULL; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->path = nfs4_resolve_path(nfs, path); +@@ -1516,7 +1515,7 @@ nfs4_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, + + data->filler.func = nfs4_populate_getfh; + data->filler.max_op = 1; +- data->filler.data = malloc(2 * sizeof(uint32_t)); ++ data->filler.data = calloc(2, sizeof(uint32_t)); + if (data->filler.data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "data structure."); +@@ -1524,7 +1523,6 @@ nfs4_mount_3_cb(struct rpc_context *rpc, int status, void *command_data, + free_nfs4_cb_data(data); + return; + } +- memset(data->filler.data, 0, 2 * sizeof(uint32_t)); + + + if (nfs4_lookup_path_async(nfs, data, nfs4_mount_4_cb) < 0) { +@@ -1633,13 +1631,12 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server, + nfs->nfsi->export = new_export; + + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "memory for nfs mount data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -1706,7 +1703,7 @@ int nfs4_chdir_async(struct nfs_context *nfs, const char *path, + data->private_data = private_data; + data->filler.func = nfs4_populate_getattr; + data->filler.max_op = 1; +- data->filler.data = malloc(2 * sizeof(uint32_t)); ++ data->filler.data = calloc(2, sizeof(uint32_t)); + if (data->filler.data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "data structure."); +@@ -1714,7 +1711,6 @@ int nfs4_chdir_async(struct nfs_context *nfs, const char *path, + free_nfs4_cb_data(data); + return -1; + } +- memset(data->filler.data, 0, 2 * sizeof(uint32_t)); + + if (nfs4_lookup_path_async(nfs, data, nfs4_chdir_1_cb) < 0) { + free_nfs4_cb_data(data); +@@ -1776,7 +1772,7 @@ nfs4_stat64_async(struct nfs_context *nfs, const char *path, + data->private_data = private_data; + data->filler.func = nfs4_populate_getattr; + data->filler.max_op = 1; +- data->filler.data = malloc(2 * sizeof(uint32_t)); ++ data->filler.data = calloc(2, sizeof(uint32_t)); + if (data->filler.data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "data structure."); +@@ -1784,7 +1780,6 @@ nfs4_stat64_async(struct nfs_context *nfs, const char *path, + free_nfs4_cb_data(data); + return -1; + } +- memset(data->filler.data, 0, 2 * sizeof(uint32_t)); + + if (nfs4_lookup_path_async(nfs, data, nfs4_xstat64_cb) < 0) { + free_nfs4_cb_data(data); +@@ -2115,7 +2110,7 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data, + } + gresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; + +- fh = malloc(sizeof(*fh)); ++ fh = calloc(1, sizeof(*fh)); + if (fh == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "nfsfh"); +@@ -2123,7 +2118,6 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data, + free_nfs4_cb_data(data); + return; + } +- memset(fh, 0 , sizeof(*fh)); + + data->filler.blob0.val = fh; + data->filler.blob0.free = (blob_free)nfs_free_nfsfh; +@@ -2562,13 +2556,12 @@ nfs4_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -2641,13 +2634,12 @@ nfs4_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -2702,13 +2694,12 @@ nfs4_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + #ifdef HAVE_MULTITHREADING + if (nfs->rpc->multithreading_enabled) { +@@ -2784,13 +2775,12 @@ nfs4_pread_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -2992,13 +2982,12 @@ nfs4_pwrite_async_internal(struct nfs_context *nfs, struct nfsfh *nfsfh, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -3094,13 +3083,12 @@ nfs4_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "cb data"); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -3212,7 +3200,7 @@ nfs4_link_1_cb(struct rpc_context *rpc, int status, void *command_data, + gfhresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; + + /* oldpath fh */ +- fh = malloc(sizeof(*fh)); ++ fh = calloc(1, sizeof(*fh)); + if (fh == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "nfsfh"); +@@ -3220,7 +3208,6 @@ nfs4_link_1_cb(struct rpc_context *rpc, int status, void *command_data, + free_nfs4_cb_data(data); + return; + } +- memset(fh, 0 , sizeof(*fh)); + data->filler.blob0.val = fh; + data->filler.blob0.free = (blob_free)nfs_free_nfsfh; + +@@ -3345,7 +3332,7 @@ nfs4_rename_1_cb(struct rpc_context *rpc, int status, void *command_data, + gfhresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; + + /* newpath fh */ +- fh = malloc(sizeof(*fh)); ++ fh = calloc(1, sizeof(*fh)); + if (fh == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "nfsfh"); +@@ -3353,7 +3340,6 @@ nfs4_rename_1_cb(struct rpc_context *rpc, int status, void *command_data, + free_nfs4_cb_data(data); + return; + } +- memset(fh, 0 , sizeof(*fh)); + data->filler.blob0.val = fh; + data->filler.blob0.free = (blob_free)nfs_free_nfsfh; + +@@ -3728,7 +3714,7 @@ nfs4_opendir_cb(struct rpc_context *rpc, int status, void *command_data, + } + gresok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetfh.GETFH4res_u.resok4; + +- fh = malloc(sizeof(*fh)); ++ fh = calloc(1, sizeof(*fh)); + if (fh == NULL) { + nfs_set_error(nfs, "Out of memory. Failed to allocate " + "nfsfh"); +@@ -3736,7 +3722,6 @@ nfs4_opendir_cb(struct rpc_context *rpc, int status, void *command_data, + free_nfs4_cb_data(data); + return; + } +- memset(fh, 0 , sizeof(*fh)); + + data->filler.blob0.val = fh; + data->filler.blob0.free = (blob_free)nfs_free_nfsfh; +@@ -3796,24 +3781,22 @@ nfs4_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, + data->filler.func = nfs4_populate_readdir; + data->filler.max_op = 2; + +- nfsdir = malloc(sizeof(struct nfsdir)); ++ nfsdir = calloc(1, sizeof(struct nfsdir)); + if (nfsdir == NULL) { + free_nfs4_cb_data(data); + nfs_set_error(nfs, "failed to allocate buffer for nfsdir"); + return -1; + } +- memset(nfsdir, 0, sizeof(struct nfsdir)); + + data->filler.blob1.val = nfsdir; + data->filler.blob1.free = (blob_free)nfs_free_nfsdir; + +- data->filler.blob2.val = malloc(sizeof(uint64_t)); ++ data->filler.blob2.val = calloc(1, sizeof(uint64_t)); + if (data->filler.blob2.val == NULL) { + free_nfs4_cb_data(data); + nfs_set_error(nfs, "failed to allocate buffer for cookie"); + return -1; + } +- memset(data->filler.blob2.val, 0, sizeof(uint64_t)); + data->filler.blob2.free = (blob_free)free; + + if (nfs4_lookup_path_async(nfs, data, nfs4_opendir_cb) < 0) { +@@ -3950,12 +3933,11 @@ nfs4_fsync_async(struct nfs_context *nfs, struct nfsfh *fh, nfs_cb cb, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -3989,18 +3971,17 @@ nfs4_ftruncate_async(struct nfs_context *nfs, struct nfsfh *fh, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; + data->private_data = private_data; + +- data->filler.blob3.val = malloc(12); ++ data->filler.blob3.val = calloc(1, 12); + if (data->filler.blob3.val == NULL) { + nfs_set_error(nfs, "Out of memory"); + free_nfs4_cb_data(data); +@@ -4008,7 +3989,6 @@ nfs4_ftruncate_async(struct nfs_context *nfs, struct nfsfh *fh, + } + data->filler.blob3.free = free; + +- memset(data->filler.blob3.val, 0, 12); + length = nfs_hton64(length); + memcpy(data->filler.blob3.val, &length, sizeof(uint64_t)); + +@@ -4112,12 +4092,11 @@ nfs4_lseek_async(struct nfs_context *nfs, struct nfsfh *fh, int64_t offset, + return 0; + } + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -4214,12 +4193,11 @@ nfs4_lockf_async(struct nfs_context *nfs, struct nfsfh *fh, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -4428,12 +4406,11 @@ nfs4_fcntl_async(struct nfs_context *nfs, struct nfsfh *fh, + nfs_argop4 op[2]; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -4709,12 +4686,11 @@ nfs4_statvfs_async_internal(struct nfs_context *nfs, const char *path, + nfs_argop4 op[2]; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -4830,12 +4806,11 @@ nfs4_fchmod_async(struct nfs_context *nfs, struct nfsfh *fh, int mode, + uint32_t m; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -4880,13 +4855,12 @@ nfs4_create_chown_buffer(struct nfs_context *nfs, struct nfs4_cb_data *data, + int i, l; + uint32_t len; + +- data->filler.blob3.val = malloc(CHOWN_BLOB_SIZE); ++ data->filler.blob3.val = calloc(1, CHOWN_BLOB_SIZE); + if (data->filler.blob3.val == NULL) { + nfs_set_error(nfs, "Out of memory"); + return -1; + } + data->filler.blob3.free = free; +- memset(data->filler.blob3.val, 0, CHOWN_BLOB_SIZE); + + i = 0; + str = data->filler.blob3.val; +@@ -4986,12 +4960,11 @@ nfs4_fchown_async(struct nfs_context *nfs, struct nfsfh *fh, int uid, int gid, + struct nfs4_cb_data *data; + int i; + +- data = malloc(sizeof(*data)); ++ data = calloc(1, sizeof(*data)); + if (data == NULL) { + nfs_set_error(nfs, "Out of memory."); + return -1; + } +- memset(data, 0, sizeof(*data)); + + data->nfs = nfs; + data->cb = cb; +@@ -5183,12 +5156,11 @@ nfs4_utimes_async_internal(struct nfs_context *nfs, const char *path, + } + + data->filler.blob3.len = 2 * (4 + 8 + 4); +- buf = data->filler.blob3.val = malloc(data->filler.blob3.len); ++ buf = data->filler.blob3.val = calloc(1, data->filler.blob3.len); + if (data->filler.blob3.val == NULL) { + nfs_set_error(nfs, "Out of memory"); + return -1; + } +- memset(buf, 0, data->filler.blob3.len); + data->filler.blob3.free = free; + + if (times != NULL) { diff --git a/backport-Fix-out-of-bounds-reading-of-v4-READLINK-results.patch b/backport-Fix-out-of-bounds-reading-of-v4-READLINK-results.patch new file mode 100644 index 0000000..2cf77f2 --- /dev/null +++ b/backport-Fix-out-of-bounds-reading-of-v4-READLINK-results.patch @@ -0,0 +1,34 @@ +From 1918e4d3cb458131e51f1ecdbdd8ac6b2f85214b Mon Sep 17 00:00:00 2001 +From: QRPp +Date: Mon, 8 Jan 2024 06:08:54 +0000 +Subject: [PATCH] Fix out-of-bounds reading of v4 READLINK results + +`nfs4_readlink_cb()`, part of `nfs_readlink_async()` and indirectly +`nfs_readlink()` & `nfs_readlink2()`, presumes the results of v4 READLINK ops +to be always NUL-terminated. That isn't guaranteed, and is rarely the case at +least when a result needs no NUL-padding on the wire toward a typically (or +always?) four byte multiple: the next RAM byte can be NUL only coincidentally. + +Under these conditions, memory is read beyond the end of the op result, at the +very least corrupting the result returned to the caller, or even crashing, +given no NUL byte in all the remainder of the corresponding memory area. + +(Closes #338 by @ma-rom.) +--- + lib/nfs_v4.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/nfs_v4.c b/lib/nfs_v4.c +index 2e0499e3..d6e3ee6f 100644 +--- a/lib/nfs_v4.c ++++ b/lib/nfs_v4.c +@@ -2902,7 +2902,8 @@ nfs4_readlink_cb(struct rpc_context *rpc, int status, void *command_data, + + rlresok = &res->resarray.resarray_val[i].nfs_resop4_u.opreadlink.READLINK4res_u.resok4; + +- target = strdup(rlresok->link.utf8string_val); ++ target = strndup(rlresok->link.utf8string_val, ++ rlresok->link.utf8string_len); + if (target == NULL) { + data->cb(-ENOMEM, nfs, "Failed to allocate memory", + data->private_data); diff --git a/backport-libnfs-fix-memory-leak-in-nfs4_set_client_name.patch b/backport-libnfs-fix-memory-leak-in-nfs4_set_client_name.patch new file mode 100644 index 0000000..562619d --- /dev/null +++ b/backport-libnfs-fix-memory-leak-in-nfs4_set_client_name.patch @@ -0,0 +1,21 @@ +From 95ac08bd55b0f8e61ea275923c3107bbc9d650a7 Mon Sep 17 00:00:00 2001 +From: Max Kellermann +Date: Mon, 13 May 2024 16:57:34 +0200 +Subject: [PATCH] libnfs: fix memory leak in nfs4_set_client_name() + +--- + lib/libnfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/libnfs.c b/lib/libnfs.c +index 6e80dc46..bf922a7b 100755 +--- a/lib/libnfs.c ++++ b/lib/libnfs.c +@@ -647,6 +647,7 @@ nfs_init_context(void) + void + nfs4_set_client_name(struct nfs_context *nfs, const char *client_name) + { ++ free(nfs->nfsi->client_name); + nfs->nfsi->client_name = strdup(client_name); + } + diff --git a/libnfs.spec b/libnfs.spec index be0b731..3aafc38 100644 --- a/libnfs.spec +++ b/libnfs.spec @@ -1,12 +1,16 @@ Name: libnfs Version: 5.0.3 -Release: 1 +Release: 2 Summary: A library for accessing NFS shares over a network License: LGPLv2+ and BSD URL: https://github.com/sahlberg/libnfs Source0: https://github.com/sahlberg/libnfs/archive/refs/tags/%{name}-%{version}.tar.gz +Patch0: backport-Fix-out-of-bounds-reading-of-v4-READLINK-results.patch +Patch1: backport-Avoid-explicit-memset-calls-with-calloc.patch +Patch2: backport-libnfs-fix-memory-leak-in-nfs4_set_client_name.patch + BuildRequires: gcc pkgconfig automake libtool %description @@ -79,6 +83,11 @@ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool %doc README %changelog +* Fri Aug 16 2024 zhangxingrong - 5.0.3-2 +- Fix out-of-bounds reading of v4 READLINK results +- Avoid explicit memset calls with calloc +- libnfs: fix memory leak in nfs4_set_client_name() + * Tue Jul 30 2024 dillon chen - 5.0.3-1 - upgrade to 5.0.3 -- Gitee