From 8791ff3dabaad123006cb97b041b05ff79e320e0 Mon Sep 17 00:00:00 2001 From: Manoharan Vijaya Raghavan Date: Sun, 11 Aug 2019 17:07:24 +0530 Subject: [PATCH] ipq807x: fat: Fix overflow issue As per FAT spec, the number of sectors can be more than clusters, as clusters starts from databegin. So check cluster overflow against total clusters. The FAT at present in u-boot lacks a lot, such as support for long file names, subdir etc. The mini dump was using more than 8 character name, changed that one too. Change-Id: Icfae6d955dd93432b3d33d7c0b9a724382d87185 Signed-off-by: Manoharan Vijaya Raghavan --- board/qca/arm/common/crashdump.c | 2 +- fs/fat/fat_write.c | 30 ++++++++++++++++++------------ include/fat.h | 1 + 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/board/qca/arm/common/crashdump.c b/board/qca/arm/common/crashdump.c index caa56ef445..927415ae2a 100644 --- a/board/qca/arm/common/crashdump.c +++ b/board/qca/arm/common/crashdump.c @@ -373,7 +373,7 @@ static int dump_wlan_segments(struct dumpinfo_t *dumpinfo, int indx) if (cur_type == QCA_WDT_LOG_DUMP_TYPE_WLAN_MOD_INFO) { snprintf(wlan_segment_name, sizeof(wlan_segment_name), - "MODULE_INFO.txt"); + "MOD_INFO.txt"); wlan_tlv_size = *(uint32_t *)(uintptr_t)tlv_info.size; } else { snprintf(wlan_segment_name, diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index d087f6ca9e..56ee76760e 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -806,21 +806,25 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) { __u32 startsect, sect_num, offset; + __u32 total_clusters = 0; - if (clustnum > 0) { - startsect = mydata->data_begin + - clustnum * mydata->clust_size; - } else { + total_clusters = ((total_sector - mydata->rootdir_sect - + mydata->rootdir_size) / + mydata->clust_size) - 3; + + /* the last sectors could be orphaned and not belong to any cluster */ + if (clustnum >= total_clusters) { + return -1; + } else if (!clustnum) { startsect = mydata->rootdir_sect; + sect_num = div_u64_rem(size, mydata->sect_size, &offset); + + if (offset != 0) + sect_num++; + if (startsect + sect_num > total_sector) + return -1; } - sect_num = div_u64_rem(size, mydata->sect_size, &offset); - - if (offset != 0) - sect_num++; - - if (startsect + sect_num > total_sector) - return -1; return 0; } @@ -1003,8 +1007,9 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, if (mydata->fatsize == 32) { mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size * 2); + mydata->rootdir_size = 0; } else { - int rootdir_size; + __u16 rootdir_size; rootdir_size = ((bs.dir_entries[1] * (int)256 + bs.dir_entries[0]) * @@ -1013,6 +1018,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, mydata->data_begin = mydata->rootdir_sect + rootdir_size - (mydata->clust_size * 2); + mydata->rootdir_size = rootdir_size; } mydata->fatbufnum = -1; diff --git a/include/fat.h b/include/fat.h index 3038bd7e4f..6016b55019 100644 --- a/include/fat.h +++ b/include/fat.h @@ -174,6 +174,7 @@ typedef struct { __u16 clust_size; /* Size of clusters in sectors */ int data_begin; /* The sector of the first cluster, can be negative */ int fatbufnum; /* Used by get_fatent, init to -1 */ + __u16 rootdir_size; /* total sectors in rootdir */ } fsdata; typedef int (file_detectfs_func)(void);