Commit 725ffdb5cbcc4b8a9726a68cc6ae0713266ba5a9
Committed by
Tom Rini
1 parent
265edc03d5
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
fs/fat: fix fatbuf leak
A new fatbuf was allocated by get_fs_info() (called by fat_itr_root()), but not freed, resulting in eventually running out of memory. Spotted by running 'ls -r' in a large FAT filesystem from Shell.efi. fatbuf is mainly used to cache FAT entry lookups (get_fatent()).. possibly once fat_write.c it can move into the iterator to simplify this. Signed-off-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Łukasz Majewski <lukma@denx.de>
Showing 1 changed file with 16 additions and 7 deletions Side-by-side Diff
fs/fat/fat.c
... | ... | @@ -1042,6 +1042,7 @@ |
1042 | 1042 | return 0; |
1043 | 1043 | |
1044 | 1044 | ret = fat_itr_resolve(itr, filename, TYPE_ANY); |
1045 | + free(fsdata.fatbuf); | |
1045 | 1046 | return ret == 0; |
1046 | 1047 | } |
1047 | 1048 | |
1048 | 1049 | |
1049 | 1050 | |
1050 | 1051 | |
... | ... | @@ -1061,17 +1062,19 @@ |
1061 | 1062 | * Directories don't have size, but fs_size() is not |
1062 | 1063 | * expected to fail if passed a directory path: |
1063 | 1064 | */ |
1065 | + free(fsdata.fatbuf); | |
1064 | 1066 | fat_itr_root(itr, &fsdata); |
1065 | 1067 | if (!fat_itr_resolve(itr, filename, TYPE_DIR)) { |
1066 | 1068 | *size = 0; |
1067 | - return 0; | |
1069 | + ret = 0; | |
1068 | 1070 | } |
1069 | - return ret; | |
1071 | + goto out; | |
1070 | 1072 | } |
1071 | 1073 | |
1072 | 1074 | *size = FAT2CPU32(itr->dent->size); |
1073 | - | |
1074 | - return 0; | |
1075 | +out: | |
1076 | + free(fsdata.fatbuf); | |
1077 | + return ret; | |
1075 | 1078 | } |
1076 | 1079 | |
1077 | 1080 | int file_fat_read_at(const char *filename, loff_t pos, void *buffer, |
1078 | 1081 | |
... | ... | @@ -1087,10 +1090,14 @@ |
1087 | 1090 | |
1088 | 1091 | ret = fat_itr_resolve(itr, filename, TYPE_FILE); |
1089 | 1092 | if (ret) |
1090 | - return ret; | |
1093 | + goto out; | |
1091 | 1094 | |
1092 | 1095 | printf("reading %s\n", filename); |
1093 | - return get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread); | |
1096 | + ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread); | |
1097 | + | |
1098 | +out: | |
1099 | + free(fsdata.fatbuf); | |
1100 | + return ret; | |
1094 | 1101 | } |
1095 | 1102 | |
1096 | 1103 | int file_fat_read(const char *filename, void *buffer, int maxsize) |
... | ... | @@ -1126,7 +1133,7 @@ |
1126 | 1133 | |
1127 | 1134 | int fat_opendir(const char *filename, struct fs_dir_stream **dirsp) |
1128 | 1135 | { |
1129 | - fat_dir *dir = malloc(sizeof(*dir)); | |
1136 | + fat_dir *dir = calloc(1, sizeof(*dir)); | |
1130 | 1137 | int ret; |
1131 | 1138 | |
1132 | 1139 | if (!dir) |
... | ... | @@ -1144,6 +1151,7 @@ |
1144 | 1151 | return 0; |
1145 | 1152 | |
1146 | 1153 | fail: |
1154 | + free(dir->fsdata.fatbuf); | |
1147 | 1155 | free(dir); |
1148 | 1156 | return ret; |
1149 | 1157 | } |
... | ... | @@ -1174,6 +1182,7 @@ |
1174 | 1182 | void fat_closedir(struct fs_dir_stream *dirs) |
1175 | 1183 | { |
1176 | 1184 | fat_dir *dir = (fat_dir *)dirs; |
1185 | + free(dir->fsdata.fatbuf); | |
1177 | 1186 | free(dir); |
1178 | 1187 | } |
1179 | 1188 |