From 32f9544121383d594da8a7d142008fd3bc065f40 Mon Sep 17 00:00:00 2001 From: XV02 Date: Tue, 3 Mar 2026 12:24:10 -0500 Subject: [PATCH 1/8] update: Memory leaks in strdup and asprintf functions and derivates (Partial) --- src/libltfs/fs.c | 8 ++--- src/libltfs/index_criteria.c | 20 ++++++++++++ src/libltfs/ltfs_internal.c | 10 ++++++ src/libltfs/tape.c | 14 ++++++++ src/libltfs/xml_writer_libltfs.c | 32 ++++++++++++------- src/tape_drivers/freebsd/cam/cam_tc.c | 6 ++++ src/tape_drivers/generic/file/filedebug_tc.c | 10 ++++-- .../linux/lin_tape/lin_tape_ibmtape.c | 4 +++ src/utils/ltfsck.c | 4 +++ src/utils/mkltfs.c | 15 ++++++++- 10 files changed, 105 insertions(+), 18 deletions(-) diff --git a/src/libltfs/fs.c b/src/libltfs/fs.c index 790438d5..e7ffb5e1 100644 --- a/src/libltfs/fs.c +++ b/src/libltfs/fs.c @@ -92,11 +92,11 @@ static char* generate_hash_key_name(const char *src_str, int *rc) } #else key_name = arch_strdup(src_str); - if (key_name){ - *rc = 0; - }else{ + if (!key_name) { *rc = -LTFS_NO_MEMORY; - } + } else { + *rc = 0; + } #endif return key_name; diff --git a/src/libltfs/index_criteria.c b/src/libltfs/index_criteria.c index 5fdca63b..191c62b2 100644 --- a/src/libltfs/index_criteria.c +++ b/src/libltfs/index_criteria.c @@ -309,16 +309,31 @@ int index_criteria_parse_name(const char *criteria, size_t len, struct index_cri *delim = '\0'; rule_ptr->percent_encode = fs_is_percent_encode_required(rule); rule_ptr->name = arch_strdup(rule); + if (!rule_ptr->name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + arch_safe_free(rulebuf); + return -LTFS_NO_MEMORY; + } rule_ptr++; rule = delim+1; } else if (*delim == '/') { *delim = '\0'; rule_ptr->percent_encode = fs_is_percent_encode_required(rule); rule_ptr->name = arch_strdup(rule); + if (!rule_ptr->name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + arch_safe_free(rulebuf); + return -LTFS_NO_MEMORY; + } rule_ptr++; } else if (*(delim+1) == '\0') { rule_ptr->percent_encode = fs_is_percent_encode_required(rule); rule_ptr->name = arch_strdup(rule); + if (!rule_ptr->name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + arch_safe_free(rulebuf); + return -LTFS_NO_MEMORY; + } rule_ptr++; } } @@ -326,6 +341,11 @@ int index_criteria_parse_name(const char *criteria, size_t len, struct index_cri if (ic->glob_patterns == rule_ptr) { rule_ptr->percent_encode = fs_is_percent_encode_required(rule); rule_ptr->name = arch_strdup(rule); + if (!rule_ptr->name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + arch_safe_free(rulebuf); + return -LTFS_NO_MEMORY; + } } /* Validate rules */ diff --git a/src/libltfs/ltfs_internal.c b/src/libltfs/ltfs_internal.c index 6059a0fc..be546397 100644 --- a/src/libltfs/ltfs_internal.c +++ b/src/libltfs/ltfs_internal.c @@ -1298,6 +1298,11 @@ int ltfs_split_symlink(struct ltfs_volume *vol) /* check lost_and_found directory and make if it doesn't exist */ int pathsize = asprintf( &lfdir, "/%s", LTFS_LOSTANDFOUND_DIR ); + if (pathsize < 0) { + ltfsmsg(LTFS_ERR, 10001E, "_ltfs_recover_symlink: lfdir"); + return -LTFS_NO_MEMORY; + } + ret = fs_path_lookup(lfdir, 0, &workd, vol->index); if ( ret==-LTFS_NO_DENTRY ) { ret = ltfs_fsops_create( lfdir, true, false, false, &workd, vol); @@ -1313,6 +1318,11 @@ int ltfs_split_symlink(struct ltfs_volume *vol) } ret = ltfs_fsops_close( workd, true, true, use_iosche, vol); path=arch_strdup(lfdir); + if (!path) { + ltfsmsg(LTFS_ERR, 10001E, "_ltfs_recover_symlink: path"); + free(lfdir); + return -LTFS_NO_MEMORY; + } /* loop for conflicted files */ for( i=0; i<(vol->index->symerr_count); i++ ){ diff --git a/src/libltfs/tape.c b/src/libltfs/tape.c index f971cb79..4f425826 100644 --- a/src/libltfs/tape.c +++ b/src/libltfs/tape.c @@ -1916,13 +1916,27 @@ int tape_get_media_pool_info(struct ltfs_volume *vol, char **media_name, char ** if (is_add_info) { if (add_start !=0) { name = strndup(vol->t_attr->media_pool, add_start); + if (!name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + return -LTFS_NO_MEMORY; + } } info = arch_strdup(&(vol->t_attr->media_pool[add_start+1])); + if (!info) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + if (name) + free(name); + return -LTFS_NO_MEMORY; + } len = strlen(info); info[len-1] = '\0'; } else { name = arch_strdup(vol->t_attr->media_pool); + if (!name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + return -LTFS_NO_MEMORY; + } } if (name) diff --git a/src/libltfs/xml_writer_libltfs.c b/src/libltfs/xml_writer_libltfs.c index 7b1ae2be..7530d53a 100644 --- a/src/libltfs/xml_writer_libltfs.c +++ b/src/libltfs/xml_writer_libltfs.c @@ -784,20 +784,30 @@ int xml_schema_to_file(const char *filename, const char *creator, return -1; } - if (reason) - asprintf(&alt_creator, "%s - %s", creator , reason); - else + if (reason) { + ret = asprintf(&alt_creator, "%s - %s", creator , reason); + if (ret < 0) { + ltfsmsg(LTFS_ERR, 10001E, "xml_schema_to_file: alt_creator"); + xmlFreeTextWriter(writer); + return -LTFS_NO_MEMORY; + } + } else { alt_creator = arch_strdup(creator); + if (!alt_creator) { + ltfsmsg(LTFS_ERR, 10001E, "xml_schema_to_file: alt_creator"); + xmlFreeTextWriter(writer); + return -LTFS_NO_MEMORY; + } + } - if (alt_creator) { - ret = _xml_write_schema(writer, alt_creator, idx); - if (ret < 0) - ltfsmsg(LTFS_ERR, 17052E, ret, filename); - else - _commit_offset_caches(filename, idx); + ret = _xml_write_schema(writer, alt_creator, idx); + if (ret < 0) + ltfsmsg(LTFS_ERR, 17052E, ret, filename); + else + _commit_offset_caches(filename, idx); - xmlFreeTextWriter(writer); - free(alt_creator); + xmlFreeTextWriter(writer); + free(alt_creator); } else { ltfsmsg(LTFS_ERR, 10001E, "xml_schema_to_file: alt creator string"); xmlFreeTextWriter(writer); diff --git a/src/tape_drivers/freebsd/cam/cam_tc.c b/src/tape_drivers/freebsd/cam/cam_tc.c index 377af2ed..576ae1b3 100644 --- a/src/tape_drivers/freebsd/cam/cam_tc.c +++ b/src/tape_drivers/freebsd/cam/cam_tc.c @@ -2403,6 +2403,7 @@ int camtape_set_default(void *device) */ if (ioctl(softc->fd_sa, MTIOCPARAMSET, &sili_param) == -1) { msg = strdup("Error returned from MTIOCPARAMSET ioctl to set the SILI bit"); + /* If strdup fails, msg is NULL; camtape_process_errors handles NULL gracefully */ rc = -EDEV_DRIVER_ERROR; camtape_process_errors(device, rc, msg, "set default parameter", true); goto bailout; @@ -2437,6 +2438,7 @@ int camtape_set_default(void *device) eot_model = 1; if (ioctl(softc->fd_sa, MTIOCSETEOTMODEL, &eot_model) == -1) { msg = strdup("Error returned from MTIOCSETEOTMODEL ioctl to set the EOT model to 1FM"); + /* If strdup fails, msg is NULL; camtape_process_errors handles NULL gracefully */ rc = -EDEV_DRIVER_ERROR; camtape_process_errors(device, rc, msg, "set default parameter", true); goto bailout; @@ -3946,6 +3948,7 @@ int camtape_set_lbp(void *device, bool enable) entry = mt_status_entry_find(&mtinfo, tmpname); if (entry == NULL) { msg = strdup("Cannot find sa(4) protection.protection_supported parameter"); + /* If strdup fails, msg is NULL; camtape_process_errors handles NULL gracefully */ rc = -EDEV_INVALID_ARG; camtape_process_errors(device, rc, msg, "get lbp", true); goto bailout; @@ -3965,6 +3968,7 @@ int camtape_set_lbp(void *device, bool enable) prot_entry = mt_status_entry_find(&mtinfo, MT_PROTECTION_NAME); if (prot_entry == NULL) { msg = strdup("Cannot find sa(4) protection node!"); + /* If strdup fails, msg is NULL; camtape_process_errors handles NULL gracefully */ rc = -EDEV_INVALID_ARG; camtape_process_errors(device, rc, msg, "get lbp", true); goto bailout; @@ -3998,6 +4002,7 @@ int camtape_set_lbp(void *device, bool enable) entry = mt_entry_find(prot_entry, __DECONST(char *, protect_list[i].name)); if (entry == NULL) { msg = strdup("Cannot find all protection information entries"); + /* If strdup fails, msg is NULL; camtape_process_errors handles NULL gracefully */ rc = -EDEV_INVALID_ARG; camtape_process_errors(device, rc, msg, "get lbp", true); goto bailout; @@ -4020,6 +4025,7 @@ int camtape_set_lbp(void *device, bool enable) snprintf(tmpstr, sizeof(tmpstr), "Error returned from MTIOCSETLIST ioctl to set " "protection parameters: %s", strerror(errno)); msg = strdup(tmpstr); + /* If strdup fails, msg is NULL; camtape_process_errors handles NULL gracefully */ rc = -errno; camtape_process_errors(device, rc, msg, "get lbp", true); goto bailout; diff --git a/src/tape_drivers/generic/file/filedebug_tc.c b/src/tape_drivers/generic/file/filedebug_tc.c index 615517f0..a7a54c89 100644 --- a/src/tape_drivers/generic/file/filedebug_tc.c +++ b/src/tape_drivers/generic/file/filedebug_tc.c @@ -502,8 +502,13 @@ int filedebug_open(const char *name, void **handle) } /* Run on file mode */ - if (devname == NULL) + if (devname == NULL) { devname = arch_strdup(name); + if (!devname) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + return -EDEV_NO_MEMORY; + } + } ltfsmsg(LTFS_INFO, 30001I, devname); arch_open(&(state->fd), devname, O_RDWR | O_BINARY, SHARE_FLAG_DENYWR, PERMISSION_READWRITE); @@ -2744,8 +2749,9 @@ int filedebug_get_device_list(struct tc_drive_info *buf, int count) if (buf && deventries < count) { tmp = arch_strdup(entry->d_name); - if (! *tmp) { + if (! tmp) { ltfsmsg(LTFS_ERR, 10001E, "filedebug_get_device_list"); + closedir(dp); return -ENOMEM; } diff --git a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c index f8c1448c..fa1fe925 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -1018,6 +1018,10 @@ int lin_tape_ibmtape_open(const char *devname, void **handle) if (!ret) { /* Specified file is existed. Use it as a device file name */ devfile = strdup(devname); + if (!devfile) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + return -LTFS_NO_MEMORY; + } } else { /* Search device by serial number (Assume devname has a drive serial) */ devs = lin_tape_ibmtape_get_device_list(NULL, 0); diff --git a/src/utils/ltfsck.c b/src/utils/ltfsck.c index fb1e4250..697fe068 100644 --- a/src/utils/ltfsck.c +++ b/src/utils/ltfsck.c @@ -304,6 +304,10 @@ int main(int argc, char **argv) break; if (c == 'i') { config_file = arch_strdup(optarg); + if (!config_file) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: config_file"); + return LTFSCK_OPERATIONAL_ERROR; + } break; } } diff --git a/src/utils/mkltfs.c b/src/utils/mkltfs.c index 9ad02890..cfaa74a1 100644 --- a/src/utils/mkltfs.c +++ b/src/utils/mkltfs.c @@ -159,10 +159,19 @@ void show_usage(char *appname, struct config_file *config, bool full) if (default_backend && plugin_load(&backend, "tape", default_backend, config) == 0) { devname = arch_strdup(ltfs_default_device_name(backend.ops)); plugin_unload(&backend); + if (!devname) { + ltfsmsg(LTFS_ERR, 10001E, "show_usage: devname"); + devname = strdup(""); /* Fallback for help text */ + } } - if (! devname) + if (! devname) { devname = arch_strdup(""); + if (!devname) { + ltfsmsg(LTFS_ERR, 10001E, "show_usage: devname fallback"); + devname = strdup(""); /* Last resort for help text */ + } + } fprintf(stderr, "\n"); ltfsresult(15400I, appname); /* Usage: %s */ @@ -283,6 +292,10 @@ int main(int argc, char **argv) break; if (c == 'i') { config_file = arch_strdup(optarg); + if (!config_file) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: config_file"); + return MKLTFS_OPERATIONAL_ERROR; + } break; } } From d22513c0fd241f73dfceb54209d86ec16240b8cf Mon Sep 17 00:00:00 2001 From: Gustavo Padilla Date: Wed, 4 Mar 2026 14:54:29 -0800 Subject: [PATCH 2/8] fix: 2 memory leaks --- src/libltfs/fs.c | 8 ++++---- src/libltfs/ltfs_fsops.c | 4 +++- src/libltfs/tape.c | 4 +++- src/libltfs/xml_writer_libltfs.c | 9 +-------- src/utils/mkltfs.c | 4 ++-- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/libltfs/fs.c b/src/libltfs/fs.c index e7ffb5e1..790438d5 100644 --- a/src/libltfs/fs.c +++ b/src/libltfs/fs.c @@ -92,11 +92,11 @@ static char* generate_hash_key_name(const char *src_str, int *rc) } #else key_name = arch_strdup(src_str); - if (!key_name) { - *rc = -LTFS_NO_MEMORY; - } else { + if (key_name){ *rc = 0; - } + }else{ + *rc = -LTFS_NO_MEMORY; + } #endif return key_name; diff --git a/src/libltfs/ltfs_fsops.c b/src/libltfs/ltfs_fsops.c index 7b2aa4d4..603f3050 100644 --- a/src/libltfs/ltfs_fsops.c +++ b/src/libltfs/ltfs_fsops.c @@ -2020,12 +2020,14 @@ int ltfs_fsops_target_absolute_path(const char* link, const char* target, char* len=strlen(link); int work_buf_len = len + len2 + 1; work_buf = malloc(work_buf_len); + memset(work_buf, '\0', work_buf_len); if (!work_buf) { ltfsmsg(LTFS_ERR, 10001E, "ltfs_fsops_target_absolute_path: work_buf"); return -LTFS_NO_MEMORY; } int target_buf_len = len2 + 1; target_buf = malloc(target_buf_len); + memset(target_buf, '\0', target_buf_len); if (!target_buf) { free(work_buf); ltfsmsg(LTFS_ERR, 10001E, "ltfs_fsops_target_absolute_path: target_buf"); @@ -2063,7 +2065,7 @@ int ltfs_fsops_target_absolute_path(const char* link, const char* target, char* len -= strlen(temp_buf); /* length of "/aaa" */ } else if (strcmp(token, "." )) { /* have directory name */ work_buf[len] = '/'; /* put '/ 'as "/aaa/" */ - arch_strncpy(work_buf+len+1, token, work_buf_len, strlen(token) ); /* "/aaa/ccc\0" */ + arch_strncpy(work_buf+len+1, token, work_buf_len, strlen(token)); /* "/aaa/ccc\0" */ len = strlen(work_buf); } token = next_token; diff --git a/src/libltfs/tape.c b/src/libltfs/tape.c index 4f425826..255ca2a2 100644 --- a/src/libltfs/tape.c +++ b/src/libltfs/tape.c @@ -3076,7 +3076,9 @@ void set_tape_attribute(struct ltfs_volume *vol, struct tape_attr *t_attr) * @param set attribute type * @return 0 positive : success, negative : cannot set value to Cartridge Memory */ -int tape_set_attribute_to_cm(struct device_data *dev, struct tape_attr *t_attr, int type) +int tape_set_attribute_to_cm(struct device_data* dev, + struct tape_attr* t_attr, + int type) { int ret; int attr_size; diff --git a/src/libltfs/xml_writer_libltfs.c b/src/libltfs/xml_writer_libltfs.c index 7530d53a..8bcdd06d 100644 --- a/src/libltfs/xml_writer_libltfs.c +++ b/src/libltfs/xml_writer_libltfs.c @@ -794,12 +794,11 @@ int xml_schema_to_file(const char *filename, const char *creator, } else { alt_creator = arch_strdup(creator); if (!alt_creator) { - ltfsmsg(LTFS_ERR, 10001E, "xml_schema_to_file: alt_creator"); + ltfsmsg(LTFS_ERR, 10001E, "xml_schema_to_file: alt_creator string"); xmlFreeTextWriter(writer); return -LTFS_NO_MEMORY; } } - ret = _xml_write_schema(writer, alt_creator, idx); if (ret < 0) ltfsmsg(LTFS_ERR, 17052E, ret, filename); @@ -808,12 +807,6 @@ int xml_schema_to_file(const char *filename, const char *creator, xmlFreeTextWriter(writer); free(alt_creator); - } else { - ltfsmsg(LTFS_ERR, 10001E, "xml_schema_to_file: alt creator string"); - xmlFreeTextWriter(writer); - return -1; - } - return ret; } diff --git a/src/utils/mkltfs.c b/src/utils/mkltfs.c index cfaa74a1..fb43b2ad 100644 --- a/src/utils/mkltfs.c +++ b/src/utils/mkltfs.c @@ -161,7 +161,7 @@ void show_usage(char *appname, struct config_file *config, bool full) plugin_unload(&backend); if (!devname) { ltfsmsg(LTFS_ERR, 10001E, "show_usage: devname"); - devname = strdup(""); /* Fallback for help text */ + devname = arch_strdup(""); /* Fallback for help text */ } } @@ -169,7 +169,7 @@ void show_usage(char *appname, struct config_file *config, bool full) devname = arch_strdup(""); if (!devname) { ltfsmsg(LTFS_ERR, 10001E, "show_usage: devname fallback"); - devname = strdup(""); /* Last resort for help text */ + devname = arch_strdup(""); /* Last resort for help text */ } } From b6195d293ce1a8e7e27d9cb917cd06e21df9c538 Mon Sep 17 00:00:00 2001 From: Luis-g-h-h Date: Tue, 5 May 2026 07:49:59 -0600 Subject: [PATCH 3/8] update: Added conditional configure action depending on libtool version --- configure.ac | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f28d2b28..f8942b52 100644 --- a/configure.ac +++ b/configure.ac @@ -49,7 +49,10 @@ AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC_C99 AM_PROG_CC_C_O AM_PROG_AR -AC_PROG_LIBTOOL +dnl +dnl Initialize libtool - use LT_INIT for libtool 2.x, AC_PROG_LIBTOOL for 1.x +dnl +m4_ifdef([LT_INIT], [LT_INIT], [AC_PROG_LIBTOOL]) dnl dnl Detecting OS From 4313cd675ede49e29f819736b529031f7709b0f6 Mon Sep 17 00:00:00 2001 From: XV02 Date: Tue, 5 May 2026 11:04:27 -0600 Subject: [PATCH 4/8] update: Add null checks for unchecked arch_strdup --- src/libltfs/arch/filename_handling.c | 3 ++ src/libltfs/ltfs_fsops.c | 6 ++-- src/libltfs/ltfslogging.h | 3 ++ src/libltfs/ltfssnmp.c | 6 ++++ src/libltfs/xml_reader_libltfs.c | 13 +++++-- src/libltfs/xml_writer_libltfs.c | 10 +++++- src/utils/ltfsck.c | 32 ++++++++++++++++- src/utils/mkltfs.c | 51 +++++++++++++++++++++++----- 8 files changed, 110 insertions(+), 14 deletions(-) diff --git a/src/libltfs/arch/filename_handling.c b/src/libltfs/arch/filename_handling.c index e61257b9..43c4d15f 100644 --- a/src/libltfs/arch/filename_handling.c +++ b/src/libltfs/arch/filename_handling.c @@ -131,6 +131,9 @@ void update_platform_safe_name(struct dentry* dentry, bool handle_invalid_char, } #else dentry->platform_safe_name = arch_strdup(dentry->name.name); + if (!dentry->platform_safe_name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + } #endif } diff --git a/src/libltfs/ltfs_fsops.c b/src/libltfs/ltfs_fsops.c index 603f3050..3b7f57d6 100644 --- a/src/libltfs/ltfs_fsops.c +++ b/src/libltfs/ltfs_fsops.c @@ -1913,6 +1913,10 @@ int ltfs_fsops_symlink_path(const char* to, const char* from, ltfs_file_id *id, id->uid = d->uid; id->ino = d->ino; d->target.name = arch_strdup(to); + if (!d->target.name) { + ltfs_fsops_close(d, true, true, use_iosche, vol); + return -LTFS_NO_MEMORY; + } d->target.percent_encode = fs_is_percent_encode_required(to); d->isslink = true; @@ -2020,14 +2024,12 @@ int ltfs_fsops_target_absolute_path(const char* link, const char* target, char* len=strlen(link); int work_buf_len = len + len2 + 1; work_buf = malloc(work_buf_len); - memset(work_buf, '\0', work_buf_len); if (!work_buf) { ltfsmsg(LTFS_ERR, 10001E, "ltfs_fsops_target_absolute_path: work_buf"); return -LTFS_NO_MEMORY; } int target_buf_len = len2 + 1; target_buf = malloc(target_buf_len); - memset(target_buf, '\0', target_buf_len); if (!target_buf) { free(work_buf); ltfsmsg(LTFS_ERR, 10001E, "ltfs_fsops_target_absolute_path: target_buf"); diff --git a/src/libltfs/ltfslogging.h b/src/libltfs/ltfslogging.h index a2dc3b5d..478a771a 100644 --- a/src/libltfs/ltfslogging.h +++ b/src/libltfs/ltfslogging.h @@ -162,6 +162,9 @@ void ltfsprintf_unload_plugin(void *handle); * only to stderr. * @param print_id Print the message prefix LTFSnnnnn ? * @param level Log level of this message, must be one of the ltfs_log_levels (LTFS_ERROR, etc.). + * @param msg_out Optional pointer to receive a dynamically allocated copy of the formatted message. + * Pass NULL if not needed. If non-NULL, the caller must check if *msg_out is NULL + * (indicating memory allocation failure) and must free the returned string when done. * @param id Unique ID of this error. * @return 0 if a message was printed or a negative value on error. */ diff --git a/src/libltfs/ltfssnmp.c b/src/libltfs/ltfssnmp.c index d8677107..f73ed159 100644 --- a/src/libltfs/ltfssnmp.c +++ b/src/libltfs/ltfssnmp.c @@ -123,6 +123,12 @@ int read_trap_def_file(char *deffile) return -LTFS_NO_MEMORY; } entry->id = arch_strdup(tok); + if (! entry->id) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + free(entry); + fclose(fp); + return -LTFS_NO_MEMORY; + } TAILQ_INSERT_TAIL(&trap_entries, entry, list); } } diff --git a/src/libltfs/xml_reader_libltfs.c b/src/libltfs/xml_reader_libltfs.c index 6a23e3fa..ae5b9cf2 100644 --- a/src/libltfs/xml_reader_libltfs.c +++ b/src/libltfs/xml_reader_libltfs.c @@ -155,6 +155,11 @@ static int decode_entry_name(char **new_name, const char *name) *new_name = arch_strdup(tmp_name); free(tmp_name); + + if (!*new_name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + return -LTFS_NO_MEMORY; + } return 0; } @@ -187,8 +192,10 @@ static int _xml_parse_nametype(xmlTextReaderPtr reader, struct ltfs_name *n, boo } if (n->percent_encode) { - decode_entry_name(&decoded_name, encoded_name); + ret = decode_entry_name(&decoded_name, encoded_name); free(encoded_name); + if (ret < 0) + return ret; } else { decoded_name = encoded_name; } @@ -241,8 +248,10 @@ static int _xml_parse_nametype_allow_zero_length(xmlTextReaderPtr reader, struct } if (n->percent_encode) { - decode_entry_name(&decoded_name, encoded_name); + ret = decode_entry_name(&decoded_name, encoded_name); free(encoded_name); + if (ret < 0) + return ret; } else { decoded_name = encoded_name; } diff --git a/src/libltfs/xml_writer_libltfs.c b/src/libltfs/xml_writer_libltfs.c index 8bcdd06d..cde3fae5 100644 --- a/src/libltfs/xml_writer_libltfs.c +++ b/src/libltfs/xml_writer_libltfs.c @@ -130,6 +130,11 @@ static int encode_entry_name(char **new_name, const char *name) *new_name = arch_strdup(tmp_name); free(tmp_name); + + if (!*new_name) { + ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + return -LTFS_NO_MEMORY; + } return 0; } @@ -146,7 +151,10 @@ static int _xml_write_nametype(xmlTextWriterPtr writer, const char *tag, struct char *encoded_name = NULL; if (n->percent_encode) { - encode_entry_name(&encoded_name, n->name); + if (encode_entry_name(&encoded_name, n->name) < 0) { + ltfsmsg(LTFS_ERR, 17098E, __FUNCTION__); + return -1; + } xml_mktag(xmlTextWriterStartElement(writer, BAD_CAST tag), -1); xml_mktag(xmlTextWriterWriteAttribute(writer, BAD_CAST "percentencoded", BAD_CAST "true"), -1); xml_mktag(xmlTextWriterWriteString(writer, BAD_CAST encoded_name), -1); diff --git a/src/utils/ltfsck.c b/src/utils/ltfsck.c index 697fe068..83da9c75 100644 --- a/src/utils/ltfsck.c +++ b/src/utils/ltfsck.c @@ -340,12 +340,20 @@ int main(int argc, char **argv) break; case 'e': opt.backend_path = arch_strdup(optarg); + if (!opt.backend_path) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: backend path"); + return LTFSCK_OPERATIONAL_ERROR; + } break; case 'g': if(opt.op_mode == MODE_CHECK) opt.op_mode = MODE_VERIFY; opt.search_mode = SEARCH_BY_GEN; opt.str_gen = arch_strdup(optarg); + if (!opt.str_gen) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: generation string"); + return LTFSCK_OPERATIONAL_ERROR; + } break; case 'v': if ( strcmp(optarg, "forward") == 0) @@ -357,6 +365,10 @@ int main(int argc, char **argv) break; case '-': opt.kmi_backend_name = arch_strdup(optarg); + if (!opt.kmi_backend_name) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: KMI backend name"); + return LTFSCK_OPERATIONAL_ERROR; + } break; case '+': opt.op_mode = MODE_LIST_POINT; @@ -427,6 +439,10 @@ int main(int argc, char **argv) return LTFSCK_OPERATIONAL_ERROR; } opt.backend_path = arch_strdup(default_backend); + if (!opt.backend_path) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: default backend path"); + return LTFSCK_OPERATIONAL_ERROR; + } } if (! opt.kmi_backend_name) { const char *default_backend = config_file_get_default_plugin("kmi", opt.config); @@ -434,6 +450,11 @@ int main(int argc, char **argv) opt.kmi_backend_name = arch_strdup(default_backend); else opt.kmi_backend_name = arch_strdup("none"); + + if (!opt.kmi_backend_name) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: default KMI backend"); + return LTFSCK_OPERATIONAL_ERROR; + } } if (opt.kmi_backend_name && strcmp(opt.kmi_backend_name, "none") == 0) opt.kmi_backend_name = NULL; @@ -497,10 +518,19 @@ int main(int argc, char **argv) return LTFSCK_OPERATIONAL_ERROR; } - if(argv[optind + num_of_o]) + if(argv[optind + num_of_o]) { opt.devname = arch_strdup(argv[optind + num_of_o]); + if (!opt.devname) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: device name"); + return LTFSCK_OPERATIONAL_ERROR; + } + } opt.prg_name = arch_strdup(argv[0]); + if (!opt.prg_name) { + ltfsmsg(LTFS_ERR, 10001E, "ltfsck: program name"); + return LTFSCK_OPERATIONAL_ERROR; + } if (_ltfsck_validate_options(&opt)) { ltfsmsg(LTFS_ERR, 16002E); diff --git a/src/utils/mkltfs.c b/src/utils/mkltfs.c index fb43b2ad..125a7bce 100644 --- a/src/utils/mkltfs.c +++ b/src/utils/mkltfs.c @@ -154,6 +154,8 @@ void show_usage(char *appname, struct config_file *config, bool full) struct libltfs_plugin backend; const char *default_backend; char *devname = NULL; + const char *devname_fallback = ""; + bool devname_allocated = false; default_backend = config_file_get_default_plugin("tape", config); if (default_backend && plugin_load(&backend, "tape", default_backend, config) == 0) { @@ -161,16 +163,13 @@ void show_usage(char *appname, struct config_file *config, bool full) plugin_unload(&backend); if (!devname) { ltfsmsg(LTFS_ERR, 10001E, "show_usage: devname"); - devname = arch_strdup(""); /* Fallback for help text */ + } else { + devname_allocated = true; } } - if (! devname) { - devname = arch_strdup(""); - if (!devname) { - ltfsmsg(LTFS_ERR, 10001E, "show_usage: devname fallback"); - devname = arch_strdup(""); /* Last resort for help text */ - } + if (!devname) { + devname = (char *)devname_fallback; } fprintf(stderr, "\n"); @@ -212,7 +211,9 @@ void show_usage(char *appname, struct config_file *config, bool full) ltfsresult(15411I, appname, devname, "size=1M/name=*.jpg"); ltfsresult(15411I, appname, devname, "size=1M/name=*.jpg:*.png"); - free(devname); + if (devname_allocated) { + free(devname); + } } @@ -322,24 +323,48 @@ int main(int argc, char **argv) case 'e': free(opt.backend_path); opt.backend_path = arch_strdup(optarg); + if (!opt.backend_path) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: backend path"); + return MKLTFS_OPERATIONAL_ERROR; + } break; case 'd': opt.devname = arch_strdup(optarg); + if (!opt.devname) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: device name"); + return MKLTFS_OPERATIONAL_ERROR; + } break; case 'b': opt.blocksize = atoi(optarg); break; case 's': opt.barcode = arch_strdup(optarg); + if (!opt.barcode) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: barcode"); + return MKLTFS_OPERATIONAL_ERROR; + } break; case 'n': opt.volume_name = arch_strdup(optarg); + if (!opt.volume_name) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: volume name"); + return MKLTFS_OPERATIONAL_ERROR; + } break; case 'r': opt.filterrules = arch_strdup(optarg); + if (!opt.filterrules) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: filter rules"); + return MKLTFS_OPERATIONAL_ERROR; + } break; case '-': opt.kmi_backend_name = arch_strdup(optarg); + if (!opt.kmi_backend_name) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: KMI backend name"); + return MKLTFS_OPERATIONAL_ERROR; + } break; case 'c': opt.enable_compression = false; @@ -409,6 +434,10 @@ int main(int argc, char **argv) return MKLTFS_OPERATIONAL_ERROR; } opt.backend_path = arch_strdup(default_backend); + if (!opt.backend_path) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: default backend path"); + return MKLTFS_OPERATIONAL_ERROR; + } } if (! opt.kmi_backend_name) { const char *default_backend = config_file_get_default_plugin("kmi", opt.config); @@ -416,7 +445,13 @@ int main(int argc, char **argv) opt.kmi_backend_name = arch_strdup(default_backend); else opt.kmi_backend_name = arch_strdup("none"); + /* Unified NULL check for both arch_strdup calls above */ + if (!opt.kmi_backend_name) { + ltfsmsg(LTFS_ERR, 10001E, "mkltfs: default KMI backend"); + return MKLTFS_OPERATIONAL_ERROR; + } } + /* FIXED: Changed from !opt.kmi_backend_name to opt.kmi_backend_name to prevent NULL dereference */ if (opt.kmi_backend_name && strcmp(opt.kmi_backend_name, "none") == 0) opt.kmi_backend_name = NULL; From 67eead5fe43bce63f248ed90f683e6bcfac29103 Mon Sep 17 00:00:00 2001 From: XV02 Date: Tue, 5 May 2026 11:39:30 -0600 Subject: [PATCH 5/8] update: Add error checks for unchecked asprintf --- src/libltfs/ltfs_internal.c | 20 ++++++++++++++++--- src/libltfs/xattr.c | 7 ++++++- src/libltfs/xml_writer.c | 8 ++++---- src/libltfs/xml_writer_libltfs.c | 13 +++++------- src/tape_drivers/generic/file/filedebug_tc.c | 10 +++++----- src/tape_drivers/generic/itdtimg/itdtimg_tc.c | 7 ++++--- 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/libltfs/ltfs_internal.c b/src/libltfs/ltfs_internal.c index be546397..de1fa530 100644 --- a/src/libltfs/ltfs_internal.c +++ b/src/libltfs/ltfs_internal.c @@ -1289,7 +1289,7 @@ int ltfs_split_symlink(struct ltfs_volume *vol) size_t i, size; struct dentry *d, *workd; int ret=0; - char *name, *lfdir, *path, *tok, *next_tok; + char *name, *lfdir, *path, *new_path, *tok, *next_tok; bool basedir=true, use_iosche=false; char value[32]; ltfs_file_id id; @@ -1337,7 +1337,14 @@ int ltfs_split_symlink(struct ltfs_volume *vol) /* check directory path and make if it doesn't exist */ while( next_tok ){ - asprintf( &path, "%s/%s", path, tok ); + ret = asprintf(&new_path, "%s/%s", path, tok); + if (ret < 0) { + ltfsmsg(LTFS_ERR, 10001E, "_ltfs_recover_symlink: path"); + ret = -LTFS_NO_MEMORY; + goto err_out_func; + } + free(path); + path = new_path; if ( basedir ) { ret = fs_path_lookup(path, 0, &workd, vol->index); if ( ret==-LTFS_NO_DENTRY ) @@ -1357,7 +1364,14 @@ int ltfs_split_symlink(struct ltfs_volume *vol) next_tok = arch_strtok( NULL, "/", contextVal); } /* Make filename with path in lost_and_found */ - asprintf( &path, "%s/%s", path, tok); + ret = asprintf(&new_path, "%s/%s", path, tok); + if (ret < 0) { + ltfsmsg(LTFS_ERR, 10001E, "_ltfs_recover_symlink: path"); + ret = -LTFS_NO_MEMORY; + goto err_out_func; + } + free(path); + path = new_path; ret = fs_path_lookup(path, 0, &workd, vol->index); if ( ret == 0 ) { /* delete same name old symlink */ diff --git a/src/libltfs/xattr.c b/src/libltfs/xattr.c index 0cd89575..e44a3c8c 100644 --- a/src/libltfs/xattr.c +++ b/src/libltfs/xattr.c @@ -664,7 +664,12 @@ static int _xattr_get_virtual(struct dentry *d, char *buf, size_t buf_size, cons default: break; } - asprintf(&val, "0x%08x", (uint32_t)(vol->device->write_protected | lock)); + ret = asprintf(&val, "0x%08x", (uint32_t)(vol->device->write_protected | lock)); + if (ret < 0) { + ltfsmsg(LTFS_ERR, 10001E, name); + val = NULL; + ret = -LTFS_NO_MEMORY; + } } else { val = NULL; ret = -LTFS_CART_NOT_MOUNTED; diff --git a/src/libltfs/xml_writer.c b/src/libltfs/xml_writer.c index 1f2944d4..21ee8e0c 100644 --- a/src/libltfs/xml_writer.c +++ b/src/libltfs/xml_writer.c @@ -409,8 +409,8 @@ int xml_acquire_file_lock(const char *file, int *fd, int *bk_fd, bool is_write) /* Create backup file if required */ if (bk_fd) { - asprintf(&backup_file, "%s.%s", file, "bk"); - if (!backup_file){ + ret = asprintf(&backup_file, "%s.%s", file, "bk"); + if (ret < 0) { ltfsmsg(LTFS_ERR, 10001E, "xml_acquire_file_lock: backup name"); arch_close(*fd); *fd = -1; @@ -510,8 +510,8 @@ int xml_release_file_lock(const char *file, int fd, int bk_fd, bool revert) if (bk_fd >= 0) arch_close(bk_fd); errno = errno_save; - asprintf(&backup_file, "%s.%s", file, "bk"); - if (!backup_file){ + ret = asprintf(&backup_file, "%s.%s", file, "bk"); + if (ret < 0) { ltfsmsg(LTFS_ERR, 10001E, "xml_release_file_lock: backup name"); ret = -LTFS_NO_MEMORY; } else { diff --git a/src/libltfs/xml_writer_libltfs.c b/src/libltfs/xml_writer_libltfs.c index cde3fae5..094ec442 100644 --- a/src/libltfs/xml_writer_libltfs.c +++ b/src/libltfs/xml_writer_libltfs.c @@ -550,24 +550,21 @@ static int _xml_write_schema(xmlTextWriterPtr writer, const char *creator, writer, BAD_CAST NEXTUID_TAGNAME, "%"PRIu64, idx->uid_number), -1); { - char *value = NULL; + const char *value; switch (idx->vollock) { case LOCKED_MAM: - asprintf(&value, "locked"); + value = "locked"; break; case PERMLOCKED_MAM: - asprintf(&value, "permlocked"); + value = "permlocked"; break; default: - asprintf(&value, "unlocked"); + value = "unlocked"; break; } - if (value) - xml_mktag(xmlTextWriterWriteElement(writer, BAD_CAST "volumelockstate", BAD_CAST value), -1); - - free(value); + xml_mktag(xmlTextWriterWriteElement(writer, BAD_CAST "volumelockstate", BAD_CAST value), -1); } xml_mktag(_xml_write_dirtree(writer, idx->root, idx, &offset, &list), -1); diff --git a/src/tape_drivers/generic/file/filedebug_tc.c b/src/tape_drivers/generic/file/filedebug_tc.c index a7a54c89..2d486ebb 100644 --- a/src/tape_drivers/generic/file/filedebug_tc.c +++ b/src/tape_drivers/generic/file/filedebug_tc.c @@ -2709,17 +2709,16 @@ int filedebug_get_device_list(struct tc_drive_info *buf, int count) FILE *infile; DIR *dp; struct dirent *entry; - int deventries = 0; + int deventries = 0, ret; char *ser= NULL, *pid = NULL, *tmp; - int i; if (! original_pid) { original_pid = (long)arch_getpid(); } /* Create a file to indicate current directory of drive link (for tape file backend) */ - asprintf(&filename, "%s/ltfs%ld", DRIVE_LIST_DIR, original_pid); - if (!filename) { + ret = asprintf(&filename, "%s/ltfs%ld", DRIVE_LIST_DIR, original_pid); + if (ret < 0) { ltfsmsg(LTFS_ERR, 10001E, "filechanger_data drive file name"); return -LTFS_NO_MEMORY; } @@ -2727,6 +2726,7 @@ int filedebug_get_device_list(struct tc_drive_info *buf, int count) arch_fopen(filename, "r", infile); if (!infile) { ltfsmsg(LTFS_INFO, 30082I, filename); + free(filename); return 0; } else { devdir = fgets(line, sizeof(line), infile); @@ -2755,7 +2755,7 @@ int filedebug_get_device_list(struct tc_drive_info *buf, int count) return -ENOMEM; } - for (i = strlen(tmp) - 1; i > 0; --i) { + for (int i = strlen(tmp) - 1; i > 0; --i) { if (tmp[i] == '.') { tmp[i] = '\0'; pid = &tmp[i + 1]; diff --git a/src/tape_drivers/generic/itdtimg/itdtimg_tc.c b/src/tape_drivers/generic/itdtimg/itdtimg_tc.c index ac6d97a6..7a5d768f 100644 --- a/src/tape_drivers/generic/itdtimg/itdtimg_tc.c +++ b/src/tape_drivers/generic/itdtimg/itdtimg_tc.c @@ -1336,11 +1336,11 @@ int itdtimage_get_device_list(struct tc_drive_info *buf, int count) FILE *infile; DIR *dp; struct dirent *entry; - int deventries = 0; + int deventries = 0, ret; /* Create a file to indicate current directory of drive link (for tape file backend) */ - asprintf(&filename, "%s/ltfs%ld", DRIVE_LIST_DIR, (long)getpid()); - if (!filename) { + ret = asprintf(&filename, "%s/ltfs%ld", DRIVE_LIST_DIR, (long)getpid()); + if (ret < 0) { ltfsmsg(LTFS_ERR, 10001E, "filechanger_data drive file name"); return -LTFS_NO_MEMORY; } @@ -1348,6 +1348,7 @@ int itdtimage_get_device_list(struct tc_drive_info *buf, int count) infile = fopen(filename, "r"); if (!infile) { ltfsmsg(LTFS_INFO, 31027I, filename); + free(filename); return 0; } else { devdir = fgets(line, sizeof(line), infile); From b376c22f27960864bab8a9094f74edbc57360c52 Mon Sep 17 00:00:00 2001 From: XV02 Date: Wed, 13 May 2026 03:50:12 -0600 Subject: [PATCH 6/8] update: Add free on early return --- src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c index fa1fe925..97245a8b 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -1020,6 +1020,7 @@ int lin_tape_ibmtape_open(const char *devname, void **handle) devfile = strdup(devname); if (!devfile) { ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + free(priv); return -LTFS_NO_MEMORY; } } else { @@ -1029,6 +1030,7 @@ int lin_tape_ibmtape_open(const char *devname, void **handle) buf = (struct tc_drive_info *)calloc(devs * 2, sizeof(struct tc_drive_info)); if (! buf) { ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__); + free(priv); return -LTFS_NO_MEMORY; } info_devs = lin_tape_ibmtape_get_device_list(buf, devs * 2); From 71cfff6db5be7c3b2a9236c6b82ad6040dc4b5f9 Mon Sep 17 00:00:00 2001 From: XV02 Date: Wed, 13 May 2026 04:01:01 -0600 Subject: [PATCH 7/8] update: Added cleanup section for memory-safe behaviour on ltfsck --- src/utils/ltfsck.c | 113 ++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 31 deletions(-) diff --git a/src/utils/ltfsck.c b/src/utils/ltfsck.c index 83da9c75..ae9ab1b3 100644 --- a/src/utils/ltfsck.c +++ b/src/utils/ltfsck.c @@ -233,12 +233,14 @@ void show_usage(char *appname, struct config_file *config, bool full) int main(int argc, char **argv) { - struct ltfs_volume *vol; + struct ltfs_volume *vol = NULL; struct other_check_opts opt; int ret, log_level, syslog_level, i, cmd_args_len; - char *lang = NULL, *cmd_args; + char *lang = NULL, *cmd_args = NULL; const char *config_file = NULL; - void *message_handle; + void *message_handle = NULL; + bool ltfs_initialized = false; + bool message_plugin_loaded = false; int fuse_argc = argc; char **fuse_argv = calloc(fuse_argc, sizeof(char *)); @@ -248,7 +250,8 @@ int main(int argc, char **argv) for (i = 0; i < fuse_argc; ++i) { fuse_argv[i] = arch_strdup(argv[i]); if (! fuse_argv[i]) { - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } } struct fuse_args args = FUSE_ARGS_INIT(fuse_argc, fuse_argv); @@ -260,7 +263,8 @@ int main(int argc, char **argv) ret = setenv("LANG", "en_US.UTF-8", 1); if (ret) { fprintf(stderr, "LTFS9016E Cannot set the LANG environment variable\n"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } } @@ -271,22 +275,27 @@ int main(int argc, char **argv) ret = ltfs_init(LTFS_INFO, true, false); if (ret < 0) { ltfsmsg(LTFS_ERR, 10000E, ret); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } + ltfs_initialized = true; /* Setup signal handler to terminate cleanly */ ret = ltfs_set_signal_handlers(); if (ret < 0) { ltfsmsg(LTFS_ERR, 10013E); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } /* Register messages with libltfs */ ret = ltfsprintf_load_plugin("bin_ltfsck", bin_ltfsck_dat, &message_handle); if (ret < 0) { ltfsmsg(LTFS_ERR, 10012E, ret); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } + message_plugin_loaded = true; /* Set up default format options and load the config file. */ memset(&opt, 0, sizeof(struct other_check_opts)); @@ -295,6 +304,12 @@ int main(int argc, char **argv) opt.erase_history = false; opt.traverse_mode = TRAVERSE_BACKWARD; opt.salvage_points = false; + opt.backend_path = NULL; + opt.str_gen = NULL; + opt.kmi_backend_name = NULL; + opt.devname = NULL; + opt.prg_name = NULL; + opt.config = NULL; /* Check for a config file path given on the command line */ while (true) { @@ -306,7 +321,8 @@ int main(int argc, char **argv) config_file = arch_strdup(optarg); if (!config_file) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: config_file"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } break; } @@ -316,7 +332,8 @@ int main(int argc, char **argv) ret = config_file_load(config_file, &opt.config); if (ret < 0) { ltfsmsg(LTFS_ERR, 10008E, ret); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } /* Parse all command line arguments */ @@ -342,7 +359,8 @@ int main(int argc, char **argv) opt.backend_path = arch_strdup(optarg); if (!opt.backend_path) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: backend path"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } break; case 'g': @@ -352,7 +370,8 @@ int main(int argc, char **argv) opt.str_gen = arch_strdup(optarg); if (!opt.str_gen) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: generation string"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } break; case 'v': @@ -367,7 +386,8 @@ int main(int argc, char **argv) opt.kmi_backend_name = arch_strdup(optarg); if (!opt.kmi_backend_name) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: KMI backend name"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } break; case '+': @@ -412,10 +432,12 @@ int main(int argc, char **argv) break; case 'h': show_usage(argv[0], opt.config, false); - return 0; + ret = 0; + goto cleanup; case 'p': show_usage(argv[0], opt.config, true); - return 0; + ret = 0; + goto cleanup; case 'o': /* ignore -o here to parse them by fuse */ ++num_of_o; @@ -423,11 +445,13 @@ int main(int argc, char **argv) case 'V': ltfsresult(16108I, "ltfsck", PACKAGE_VERSION); ltfsresult(16108I, "LTFS Format Specification", LTFS_INDEX_VERSION_STR); - return 0; + ret = 0; + goto cleanup; case '?': default: show_usage(argv[0], opt.config, false); - return LTFSCK_USAGE_SYNTAX_ERROR; + ret = LTFSCK_USAGE_SYNTAX_ERROR; + goto cleanup; } } @@ -436,12 +460,14 @@ int main(int argc, char **argv) const char *default_backend = config_file_get_default_plugin("tape", opt.config); if (! default_backend) { ltfsmsg(LTFS_ERR, 10009E); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } opt.backend_path = arch_strdup(default_backend); if (!opt.backend_path) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: default backend path"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } } if (! opt.kmi_backend_name) { @@ -453,7 +479,8 @@ int main(int argc, char **argv) if (!opt.kmi_backend_name) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: default KMI backend"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } } if (opt.kmi_backend_name && strcmp(opt.kmi_backend_name, "none") == 0) @@ -463,7 +490,8 @@ int main(int argc, char **argv) if (opt.quiet && (opt.trace || opt.fulltrace)) { ltfsmsg(LTFS_ERR, 9013E); show_usage(argv[0], opt.config, false); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } else if (opt.quiet) { log_level = LTFS_WARN; syslog_level = LTFS_NONE; @@ -494,7 +522,8 @@ int main(int argc, char **argv) if (!cmd_args) { /* Memory allocation failed */ ltfsmsg(LTFS_ERR, 10001E, "ltfsck (arguments)"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } arch_strcat(cmd_args, cmd_args_len, argv[0]); for (i = 1; i < argc; i++) { @@ -515,42 +544,64 @@ int main(int argc, char **argv) ret = ltfs_volume_alloc("ltfsck", &vol); if (ret < 0) { ltfsmsg(LTFS_ERR, 16001E); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } if(argv[optind + num_of_o]) { opt.devname = arch_strdup(argv[optind + num_of_o]); if (!opt.devname) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: device name"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } } opt.prg_name = arch_strdup(argv[0]); if (!opt.prg_name) { ltfsmsg(LTFS_ERR, 10001E, "ltfsck: program name"); - return LTFSCK_OPERATIONAL_ERROR; + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; } if (_ltfsck_validate_options(&opt)) { ltfsmsg(LTFS_ERR, 16002E); show_usage(argv[0], opt.config, false); - return LTFSCK_USAGE_SYNTAX_ERROR; + ret = LTFSCK_USAGE_SYNTAX_ERROR; + goto cleanup; } ret = ltfs_fs_init(); - if (ret) - return LTFSCK_OPERATIONAL_ERROR; + if (ret) { + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; + } ret = ltfsck(vol, &opt, &args); +cleanup: + /* Free all allocated resources */ + if (fuse_argv) { + for (i = 0; i < fuse_argc; ++i) { + free(fuse_argv[i]); + } + free(fuse_argv); + } + free(cmd_args); free(opt.prg_name); free(opt.backend_path); free(opt.kmi_backend_name); free(opt.devname); - config_file_free(opt.config); - ltfsprintf_unload_plugin(message_handle); - ltfs_finish(); + free(opt.str_gen); + if (config_file) + free((void *)config_file); + if (opt.config) + config_file_free(opt.config); + if (message_plugin_loaded) + ltfsprintf_unload_plugin(message_handle); + if (ltfs_initialized) + ltfs_finish(); + return ret; } From 521c81af066c22635606bcd553a0a1be22d3f19a Mon Sep 17 00:00:00 2001 From: XV02 Date: Wed, 13 May 2026 04:07:25 -0600 Subject: [PATCH 8/8] update: Added cleanup section for memory-safe behaviour on mkltfs --- src/utils/mkltfs.c | 128 ++++++++++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 36 deletions(-) diff --git a/src/utils/mkltfs.c b/src/utils/mkltfs.c index 125a7bce..2c1c7884 100644 --- a/src/utils/mkltfs.c +++ b/src/utils/mkltfs.c @@ -220,12 +220,14 @@ void show_usage(char *appname, struct config_file *config, bool full) /* Operation */ int main(int argc, char **argv) { - struct ltfs_volume *newvol; + struct ltfs_volume *newvol = NULL; struct other_format_opts opt; int ret, log_level, syslog_level, i, cmd_args_len; - char *lang = NULL, *cmd_args; + char *lang = NULL, *cmd_args = NULL; const char *config_file = NULL; - void *message_handle; + void *message_handle = NULL; + bool ltfs_initialized = false; + bool message_plugin_loaded = false; int fuse_argc = argc; char **fuse_argv = calloc(fuse_argc, sizeof(char *)); if (! fuse_argv) { @@ -234,7 +236,8 @@ int main(int argc, char **argv) for (i = 0; i < fuse_argc; ++i) { fuse_argv[i] = arch_strdup(argv[i]); if (! fuse_argv[i]) { - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } } struct fuse_args args = FUSE_ARGS_INIT(fuse_argc, fuse_argv); @@ -246,7 +249,8 @@ int main(int argc, char **argv) ret = setenv("LANG", "en_US.UTF-8", 1); if (ret) { fprintf(stderr, "LTFS9016E Cannot set the LANG environment variable\n"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } } @@ -257,22 +261,27 @@ int main(int argc, char **argv) ret = ltfs_init(LTFS_INFO, true, false); if (ret < 0) { ltfsmsg(LTFS_ERR, 10000E, ret); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } + ltfs_initialized = true; /* Setup signal handler to terminate cleanly */ ret = ltfs_set_signal_handlers(); if (ret < 0) { ltfsmsg(LTFS_ERR, 10013E); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } /* Register messages with libltfs */ ret = ltfsprintf_load_plugin("bin_mkltfs", bin_mkltfs_dat, &message_handle); if (ret < 0) { ltfsmsg(LTFS_ERR, 10012E, ret); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } + message_plugin_loaded = true; /* Set up empty format options and load the configuration file. */ memset(&opt, 0, sizeof(struct other_format_opts)); @@ -284,6 +293,13 @@ int main(int argc, char **argv) opt.blocksize = LTFS_DEFAULT_BLOCKSIZE; opt.long_wipe = false; opt.destructive = false; + opt.backend_path = NULL; + opt.devname = NULL; + opt.barcode = NULL; + opt.volume_name = NULL; + opt.filterrules = NULL; + opt.kmi_backend_name = NULL; + opt.config = NULL; /* Check for a config file path given on the command line */ while (true) { @@ -295,7 +311,8 @@ int main(int argc, char **argv) config_file = arch_strdup(optarg); if (!config_file) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: config_file"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; } @@ -305,7 +322,8 @@ int main(int argc, char **argv) ret = config_file_load(config_file, &opt.config); if (ret < 0) { ltfsmsg(LTFS_ERR, 10008E, ret); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } /* Parse all command line arguments */ @@ -325,14 +343,16 @@ int main(int argc, char **argv) opt.backend_path = arch_strdup(optarg); if (!opt.backend_path) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: backend path"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; case 'd': opt.devname = arch_strdup(optarg); if (!opt.devname) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: device name"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; case 'b': @@ -342,28 +362,32 @@ int main(int argc, char **argv) opt.barcode = arch_strdup(optarg); if (!opt.barcode) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: barcode"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; case 'n': opt.volume_name = arch_strdup(optarg); if (!opt.volume_name) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: volume name"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; case 'r': opt.filterrules = arch_strdup(optarg); if (!opt.filterrules) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: filter rules"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; case '-': opt.kmi_backend_name = arch_strdup(optarg); if (!opt.kmi_backend_name) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: KMI backend name"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } break; case 'c': @@ -406,24 +430,29 @@ int main(int argc, char **argv) break; case 'h': show_usage(argv[0], opt.config, false); - return 0; + ret = 0; + goto cleanup; case 'p': show_usage(argv[0], opt.config, true); - return 0; + ret = 0; + goto cleanup; case 'V': ltfsresult(15059I, "mkltfs", PACKAGE_VERSION); ltfsresult(15059I, "LTFS Format Specification", LTFS_INDEX_VERSION_STR); - return 0; + ret = 0; + goto cleanup; case '?': default: show_usage(argv[0], opt.config, false); - return MKLTFS_USAGE_SYNTAX_ERROR; + ret = MKLTFS_USAGE_SYNTAX_ERROR; + goto cleanup; } } if (optind + num_of_o < argc) { show_usage(argv[0], opt.config, false); - return MKLTFS_USAGE_SYNTAX_ERROR; + ret = MKLTFS_USAGE_SYNTAX_ERROR; + goto cleanup; } /* Pick up default backend if one wasn't specified before */ @@ -431,12 +460,14 @@ int main(int argc, char **argv) const char *default_backend = config_file_get_default_plugin("tape", opt.config); if (! default_backend) { ltfsmsg(LTFS_ERR, 10009E); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } opt.backend_path = arch_strdup(default_backend); if (!opt.backend_path) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: default backend path"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } } if (! opt.kmi_backend_name) { @@ -448,7 +479,8 @@ int main(int argc, char **argv) /* Unified NULL check for both arch_strdup calls above */ if (!opt.kmi_backend_name) { ltfsmsg(LTFS_ERR, 10001E, "mkltfs: default KMI backend"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } } /* FIXED: Changed from !opt.kmi_backend_name to opt.kmi_backend_name to prevent NULL dereference */ @@ -459,7 +491,8 @@ int main(int argc, char **argv) if (opt.quiet && (opt.trace || opt.fulltrace)) { ltfsmsg(LTFS_ERR, 9012E); show_usage(argv[0], opt.config, false); - return 1; + ret = 1; + goto cleanup; } else if (opt.quiet) { log_level = LTFS_WARN; syslog_level = LTFS_NONE; @@ -490,7 +523,8 @@ int main(int argc, char **argv) if (!cmd_args) { /* Memory allocation failed */ ltfsmsg(LTFS_ERR, 10001E, "mkltfs (arguments)"); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } arch_strcat(cmd_args, cmd_args_len,argv[0]); for (i = 1; i < argc; i++) { @@ -511,7 +545,8 @@ int main(int argc, char **argv) ret = ltfs_volume_alloc("mkltfs", &newvol); if (ret < 0) { ltfsmsg(LTFS_ERR, 15001E); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } ret = ltfs_set_blocksize(opt.blocksize, newvol); @@ -519,7 +554,8 @@ int main(int argc, char **argv) if (ret == -LTFS_SMALL_BLOCKSIZE) ltfsmsg(LTFS_ERR, 15028E, LTFS_MIN_BLOCKSIZE); show_usage(argv[0], opt.config, false); - return MKLTFS_OPERATIONAL_ERROR; + ret = MKLTFS_OPERATIONAL_ERROR; + goto cleanup; } ltfs_set_compression(opt.enable_compression, newvol); ret = ltfs_set_barcode(opt.barcode, newvol); @@ -529,18 +565,22 @@ int main(int argc, char **argv) else if (ret == -LTFS_BARCODE_INVALID) ltfsmsg(LTFS_ERR, 15030E); show_usage(argv[0], opt.config, false); - return MKLTFS_USAGE_SYNTAX_ERROR; + ret = MKLTFS_USAGE_SYNTAX_ERROR; + goto cleanup; } if (_mkltfs_validate_options(argv[0], newvol, &opt)) { ltfsmsg(LTFS_ERR, 15002E); show_usage(argv[0], opt.config, false); - return MKLTFS_USAGE_SYNTAX_ERROR; + ret = MKLTFS_USAGE_SYNTAX_ERROR; + goto cleanup; } ret = ltfs_fs_init(); - if (ret) - return LTFSCK_OPERATIONAL_ERROR;; + if (ret) { + ret = LTFSCK_OPERATIONAL_ERROR; + goto cleanup; + } ltfsmsg(LTFS_INFO, 15003I, opt.devname); ltfsmsg(LTFS_INFO, 15004I, opt.blocksize); @@ -553,13 +593,29 @@ int main(int argc, char **argv) else ret = format_tape(newvol, &opt, &args); - +cleanup: + /* Free all allocated resources */ + if (fuse_argv) { + for (i = 0; i < fuse_argc; ++i) { + free(fuse_argv[i]); + } + free(fuse_argv); + } + free(cmd_args); arch_safe_free(opt.backend_path); arch_safe_free(opt.kmi_backend_name); arch_safe_free(opt.devname); - config_file_free(opt.config); - ltfsprintf_unload_plugin(message_handle); - ltfs_finish(); + arch_safe_free(opt.barcode); + arch_safe_free(opt.volume_name); + arch_safe_free(opt.filterrules); + if (config_file) + free((void *)config_file); + if (opt.config) + config_file_free(opt.config); + if (message_plugin_loaded) + ltfsprintf_unload_plugin(message_handle); + if (ltfs_initialized) + ltfs_finish(); return ret; }