diff options
| -rw-r--r-- | fs/ext4/namei.c | 248 |
1 files changed, 204 insertions, 44 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 85add9a9e1cd..4c84db862891 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -253,8 +253,9 @@ static struct dx_frame *dx_probe(const struct qstr *d_name, | |||
| 253 | struct dx_hash_info *hinfo, | 253 | struct dx_hash_info *hinfo, |
| 254 | struct dx_frame *frame); | 254 | struct dx_frame *frame); |
| 255 | static void dx_release(struct dx_frame *frames); | 255 | static void dx_release(struct dx_frame *frames); |
| 256 | static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, | 256 | static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, |
| 257 | struct dx_hash_info *hinfo, struct dx_map_entry map[]); | 257 | unsigned blocksize, struct dx_hash_info *hinfo, |
| 258 | struct dx_map_entry map[]); | ||
| 258 | static void dx_sort_map(struct dx_map_entry *map, unsigned count); | 259 | static void dx_sort_map(struct dx_map_entry *map, unsigned count); |
| 259 | static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, | 260 | static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, |
| 260 | struct dx_map_entry *offsets, int count, unsigned blocksize); | 261 | struct dx_map_entry *offsets, int count, unsigned blocksize); |
| @@ -968,7 +969,8 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
| 968 | struct buffer_head *bh; | 969 | struct buffer_head *bh; |
| 969 | struct ext4_dir_entry_2 *de, *top; | 970 | struct ext4_dir_entry_2 *de, *top; |
| 970 | int err = 0, count = 0; | 971 | int err = 0, count = 0; |
| 971 | struct ext4_str tmp_str; | 972 | struct ext4_fname_crypto_ctx *ctx = NULL; |
| 973 | struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}, tmp_str; | ||
| 972 | 974 | ||
| 973 | dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", | 975 | dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", |
| 974 | (unsigned long)block)); | 976 | (unsigned long)block)); |
| @@ -980,6 +982,24 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
| 980 | top = (struct ext4_dir_entry_2 *) ((char *) de + | 982 | top = (struct ext4_dir_entry_2 *) ((char *) de + |
| 981 | dir->i_sb->s_blocksize - | 983 | dir->i_sb->s_blocksize - |
| 982 | EXT4_DIR_REC_LEN(0)); | 984 | EXT4_DIR_REC_LEN(0)); |
| 985 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 986 | /* Check if the directory is encrypted */ | ||
| 987 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
| 988 | if (IS_ERR(ctx)) { | ||
| 989 | err = PTR_ERR(ctx); | ||
| 990 | brelse(bh); | ||
| 991 | return err; | ||
| 992 | } | ||
| 993 | if (ctx != NULL) { | ||
| 994 | err = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN, | ||
| 995 | &fname_crypto_str); | ||
| 996 | if (err < 0) { | ||
| 997 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 998 | brelse(bh); | ||
| 999 | return err; | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | #endif | ||
| 983 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { | 1003 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { |
| 984 | if (ext4_check_dir_entry(dir, NULL, de, bh, | 1004 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
| 985 | bh->b_data, bh->b_size, | 1005 | bh->b_data, bh->b_size, |
| @@ -988,24 +1008,52 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
| 988 | /* silently ignore the rest of the block */ | 1008 | /* silently ignore the rest of the block */ |
| 989 | break; | 1009 | break; |
| 990 | } | 1010 | } |
| 1011 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1012 | err = ext4_fname_disk_to_hash(ctx, de, hinfo); | ||
| 1013 | if (err < 0) { | ||
| 1014 | count = err; | ||
| 1015 | goto errout; | ||
| 1016 | } | ||
| 1017 | #else | ||
| 991 | ext4fs_dirhash(de->name, de->name_len, hinfo); | 1018 | ext4fs_dirhash(de->name, de->name_len, hinfo); |
| 1019 | #endif | ||
| 992 | if ((hinfo->hash < start_hash) || | 1020 | if ((hinfo->hash < start_hash) || |
| 993 | ((hinfo->hash == start_hash) && | 1021 | ((hinfo->hash == start_hash) && |
| 994 | (hinfo->minor_hash < start_minor_hash))) | 1022 | (hinfo->minor_hash < start_minor_hash))) |
| 995 | continue; | 1023 | continue; |
| 996 | if (de->inode == 0) | 1024 | if (de->inode == 0) |
| 997 | continue; | 1025 | continue; |
| 998 | tmp_str.name = de->name; | 1026 | if (ctx == NULL) { |
| 999 | tmp_str.len = de->name_len; | 1027 | /* Directory is not encrypted */ |
| 1000 | err = ext4_htree_store_dirent(dir_file, | 1028 | tmp_str.name = de->name; |
| 1001 | hinfo->hash, hinfo->minor_hash, de, &tmp_str); | 1029 | tmp_str.len = de->name_len; |
| 1030 | err = ext4_htree_store_dirent(dir_file, | ||
| 1031 | hinfo->hash, hinfo->minor_hash, de, | ||
| 1032 | &tmp_str); | ||
| 1033 | } else { | ||
| 1034 | /* Directory is encrypted */ | ||
| 1035 | err = ext4_fname_disk_to_usr(ctx, de, | ||
| 1036 | &fname_crypto_str); | ||
| 1037 | if (err < 0) { | ||
| 1038 | count = err; | ||
| 1039 | goto errout; | ||
| 1040 | } | ||
| 1041 | err = ext4_htree_store_dirent(dir_file, | ||
| 1042 | hinfo->hash, hinfo->minor_hash, de, | ||
| 1043 | &fname_crypto_str); | ||
| 1044 | } | ||
| 1002 | if (err != 0) { | 1045 | if (err != 0) { |
| 1003 | brelse(bh); | 1046 | count = err; |
| 1004 | return err; | 1047 | goto errout; |
| 1005 | } | 1048 | } |
| 1006 | count++; | 1049 | count++; |
| 1007 | } | 1050 | } |
| 1051 | errout: | ||
| 1008 | brelse(bh); | 1052 | brelse(bh); |
| 1053 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1054 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1055 | ext4_fname_crypto_free_buffer(&fname_crypto_str); | ||
| 1056 | #endif | ||
| 1009 | return count; | 1057 | return count; |
| 1010 | } | 1058 | } |
| 1011 | 1059 | ||
| @@ -1138,17 +1186,33 @@ static inline int search_dirblock(struct buffer_head *bh, | |||
| 1138 | * Create map of hash values, offsets, and sizes, stored at end of block. | 1186 | * Create map of hash values, offsets, and sizes, stored at end of block. |
| 1139 | * Returns number of entries mapped. | 1187 | * Returns number of entries mapped. |
| 1140 | */ | 1188 | */ |
| 1141 | static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, | 1189 | static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, |
| 1142 | struct dx_hash_info *hinfo, | 1190 | unsigned blocksize, struct dx_hash_info *hinfo, |
| 1143 | struct dx_map_entry *map_tail) | 1191 | struct dx_map_entry *map_tail) |
| 1144 | { | 1192 | { |
| 1145 | int count = 0; | 1193 | int count = 0; |
| 1146 | char *base = (char *) de; | 1194 | char *base = (char *) de; |
| 1147 | struct dx_hash_info h = *hinfo; | 1195 | struct dx_hash_info h = *hinfo; |
| 1196 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1197 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
| 1198 | int err; | ||
| 1199 | |||
| 1200 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
| 1201 | if (IS_ERR(ctx)) | ||
| 1202 | return PTR_ERR(ctx); | ||
| 1203 | #endif | ||
| 1148 | 1204 | ||
| 1149 | while ((char *) de < base + blocksize) { | 1205 | while ((char *) de < base + blocksize) { |
| 1150 | if (de->name_len && de->inode) { | 1206 | if (de->name_len && de->inode) { |
| 1207 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1208 | err = ext4_fname_disk_to_hash(ctx, de, &h); | ||
| 1209 | if (err < 0) { | ||
| 1210 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1211 | return err; | ||
| 1212 | } | ||
| 1213 | #else | ||
| 1151 | ext4fs_dirhash(de->name, de->name_len, &h); | 1214 | ext4fs_dirhash(de->name, de->name_len, &h); |
| 1215 | #endif | ||
| 1152 | map_tail--; | 1216 | map_tail--; |
| 1153 | map_tail->hash = h.hash; | 1217 | map_tail->hash = h.hash; |
| 1154 | map_tail->offs = ((char *) de - base)>>2; | 1218 | map_tail->offs = ((char *) de - base)>>2; |
| @@ -1159,6 +1223,9 @@ static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, | |||
| 1159 | /* XXX: do we need to check rec_len == 0 case? -Chris */ | 1223 | /* XXX: do we need to check rec_len == 0 case? -Chris */ |
| 1160 | de = ext4_next_entry(de, blocksize); | 1224 | de = ext4_next_entry(de, blocksize); |
| 1161 | } | 1225 | } |
| 1226 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1227 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1228 | #endif | ||
| 1162 | return count; | 1229 | return count; |
| 1163 | } | 1230 | } |
| 1164 | 1231 | ||
| @@ -1209,57 +1276,107 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block) | |||
| 1209 | * `len <= EXT4_NAME_LEN' is guaranteed by caller. | 1276 | * `len <= EXT4_NAME_LEN' is guaranteed by caller. |
| 1210 | * `de != NULL' is guaranteed by caller. | 1277 | * `de != NULL' is guaranteed by caller. |
| 1211 | */ | 1278 | */ |
| 1212 | static inline int ext4_match (int len, const char * const name, | 1279 | static inline int ext4_match(struct ext4_fname_crypto_ctx *ctx, |
| 1213 | struct ext4_dir_entry_2 * de) | 1280 | struct ext4_str *fname_crypto_str, |
| 1281 | int len, const char * const name, | ||
| 1282 | struct ext4_dir_entry_2 *de) | ||
| 1214 | { | 1283 | { |
| 1215 | if (len != de->name_len) | 1284 | int res; |
| 1216 | return 0; | 1285 | |
| 1217 | if (!de->inode) | 1286 | if (!de->inode) |
| 1218 | return 0; | 1287 | return 0; |
| 1219 | return !memcmp(name, de->name, len); | 1288 | |
| 1289 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1290 | if (ctx) { | ||
| 1291 | /* Directory is encrypted */ | ||
| 1292 | res = ext4_fname_disk_to_usr(ctx, de, fname_crypto_str); | ||
| 1293 | if (res < 0) | ||
| 1294 | return res; | ||
| 1295 | if (len != res) | ||
| 1296 | return 0; | ||
| 1297 | res = memcmp(name, fname_crypto_str->name, len); | ||
| 1298 | return (res == 0) ? 1 : 0; | ||
| 1299 | } | ||
| 1300 | #endif | ||
| 1301 | if (len != de->name_len) | ||
| 1302 | return 0; | ||
| 1303 | res = memcmp(name, de->name, len); | ||
| 1304 | return (res == 0) ? 1 : 0; | ||
| 1220 | } | 1305 | } |
| 1221 | 1306 | ||
| 1222 | /* | 1307 | /* |
| 1223 | * Returns 0 if not found, -1 on failure, and 1 on success | 1308 | * Returns 0 if not found, -1 on failure, and 1 on success |
| 1224 | */ | 1309 | */ |
| 1225 | int search_dir(struct buffer_head *bh, | 1310 | int search_dir(struct buffer_head *bh, char *search_buf, int buf_size, |
| 1226 | char *search_buf, | 1311 | struct inode *dir, const struct qstr *d_name, |
| 1227 | int buf_size, | 1312 | unsigned int offset, struct ext4_dir_entry_2 **res_dir) |
| 1228 | struct inode *dir, | ||
| 1229 | const struct qstr *d_name, | ||
| 1230 | unsigned int offset, | ||
| 1231 | struct ext4_dir_entry_2 **res_dir) | ||
| 1232 | { | 1313 | { |
| 1233 | struct ext4_dir_entry_2 * de; | 1314 | struct ext4_dir_entry_2 * de; |
| 1234 | char * dlimit; | 1315 | char * dlimit; |
| 1235 | int de_len; | 1316 | int de_len; |
| 1236 | const char *name = d_name->name; | 1317 | const char *name = d_name->name; |
| 1237 | int namelen = d_name->len; | 1318 | int namelen = d_name->len; |
| 1319 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
| 1320 | struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; | ||
| 1321 | int res; | ||
| 1322 | |||
| 1323 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
| 1324 | if (IS_ERR(ctx)) | ||
| 1325 | return -1; | ||
| 1326 | |||
| 1327 | if (ctx != NULL) { | ||
| 1328 | /* Allocate buffer to hold maximum name length */ | ||
| 1329 | res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN, | ||
| 1330 | &fname_crypto_str); | ||
| 1331 | if (res < 0) { | ||
| 1332 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1333 | return -1; | ||
| 1334 | } | ||
| 1335 | } | ||
| 1238 | 1336 | ||
| 1239 | de = (struct ext4_dir_entry_2 *)search_buf; | 1337 | de = (struct ext4_dir_entry_2 *)search_buf; |
| 1240 | dlimit = search_buf + buf_size; | 1338 | dlimit = search_buf + buf_size; |
| 1241 | while ((char *) de < dlimit) { | 1339 | while ((char *) de < dlimit) { |
| 1242 | /* this code is executed quadratically often */ | 1340 | /* this code is executed quadratically often */ |
| 1243 | /* do minimal checking `by hand' */ | 1341 | /* do minimal checking `by hand' */ |
| 1342 | if ((char *) de + de->name_len <= dlimit) { | ||
| 1343 | res = ext4_match(ctx, &fname_crypto_str, namelen, | ||
| 1344 | name, de); | ||
| 1345 | if (res < 0) { | ||
| 1346 | res = -1; | ||
| 1347 | goto return_result; | ||
| 1348 | } | ||
| 1349 | if (res > 0) { | ||
| 1350 | /* found a match - just to be sure, do | ||
| 1351 | * a full check */ | ||
| 1352 | if (ext4_check_dir_entry(dir, NULL, de, bh, | ||
| 1353 | bh->b_data, | ||
| 1354 | bh->b_size, offset)) { | ||
| 1355 | res = -1; | ||
| 1356 | goto return_result; | ||
| 1357 | } | ||
| 1358 | *res_dir = de; | ||
| 1359 | res = 1; | ||
| 1360 | goto return_result; | ||
| 1361 | } | ||
| 1244 | 1362 | ||
| 1245 | if ((char *) de + namelen <= dlimit && | ||
| 1246 | ext4_match (namelen, name, de)) { | ||
| 1247 | /* found a match - just to be sure, do a full check */ | ||
| 1248 | if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, | ||
| 1249 | bh->b_size, offset)) | ||
| 1250 | return -1; | ||
| 1251 | *res_dir = de; | ||
| 1252 | return 1; | ||
| 1253 | } | 1363 | } |
| 1254 | /* prevent looping on a bad block */ | 1364 | /* prevent looping on a bad block */ |
| 1255 | de_len = ext4_rec_len_from_disk(de->rec_len, | 1365 | de_len = ext4_rec_len_from_disk(de->rec_len, |
| 1256 | dir->i_sb->s_blocksize); | 1366 | dir->i_sb->s_blocksize); |
| 1257 | if (de_len <= 0) | 1367 | if (de_len <= 0) { |
| 1258 | return -1; | 1368 | res = -1; |
| 1369 | goto return_result; | ||
| 1370 | } | ||
| 1259 | offset += de_len; | 1371 | offset += de_len; |
| 1260 | de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); | 1372 | de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); |
| 1261 | } | 1373 | } |
| 1262 | return 0; | 1374 | |
| 1375 | res = 0; | ||
| 1376 | return_result: | ||
| 1377 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1378 | ext4_fname_crypto_free_buffer(&fname_crypto_str); | ||
| 1379 | return res; | ||
| 1263 | } | 1380 | } |
| 1264 | 1381 | ||
| 1265 | static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block, | 1382 | static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block, |
| @@ -1448,6 +1565,9 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q | |||
| 1448 | ext4_lblk_t block; | 1565 | ext4_lblk_t block; |
| 1449 | int retval; | 1566 | int retval; |
| 1450 | 1567 | ||
| 1568 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | ||
| 1569 | *res_dir = NULL; | ||
| 1570 | #endif | ||
| 1451 | frame = dx_probe(d_name, dir, &hinfo, frames); | 1571 | frame = dx_probe(d_name, dir, &hinfo, frames); |
| 1452 | if (IS_ERR(frame)) | 1572 | if (IS_ERR(frame)) |
| 1453 | return (struct buffer_head *) frame; | 1573 | return (struct buffer_head *) frame; |
| @@ -1656,7 +1776,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
| 1656 | 1776 | ||
| 1657 | /* create map in the end of data2 block */ | 1777 | /* create map in the end of data2 block */ |
| 1658 | map = (struct dx_map_entry *) (data2 + blocksize); | 1778 | map = (struct dx_map_entry *) (data2 + blocksize); |
| 1659 | count = dx_make_map((struct ext4_dir_entry_2 *) data1, | 1779 | count = dx_make_map(dir, (struct ext4_dir_entry_2 *) data1, |
| 1660 | blocksize, hinfo, map); | 1780 | blocksize, hinfo, map); |
| 1661 | map -= count; | 1781 | map -= count; |
| 1662 | dx_sort_map(map, count); | 1782 | dx_sort_map(map, count); |
| @@ -1679,7 +1799,8 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
| 1679 | hash2, split, count-split)); | 1799 | hash2, split, count-split)); |
| 1680 | 1800 | ||
| 1681 | /* Fancy dance to stay within two buffers */ | 1801 | /* Fancy dance to stay within two buffers */ |
| 1682 | de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize); | 1802 | de2 = dx_move_dirents(data1, data2, map + split, count - split, |
| 1803 | blocksize); | ||
| 1683 | de = dx_pack_dirents(data1, blocksize); | 1804 | de = dx_pack_dirents(data1, blocksize); |
| 1684 | de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) - | 1805 | de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) - |
| 1685 | (char *) de, | 1806 | (char *) de, |
| @@ -1735,15 +1856,48 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, | |||
| 1735 | int nlen, rlen; | 1856 | int nlen, rlen; |
| 1736 | unsigned int offset = 0; | 1857 | unsigned int offset = 0; |
| 1737 | char *top; | 1858 | char *top; |
| 1859 | struct ext4_fname_crypto_ctx *ctx = NULL; | ||
| 1860 | struct ext4_str fname_crypto_str = {.name = NULL, .len = 0}; | ||
| 1861 | int res; | ||
| 1862 | |||
| 1863 | ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN); | ||
| 1864 | if (IS_ERR(ctx)) | ||
| 1865 | return -1; | ||
| 1866 | |||
| 1867 | if (ctx != NULL) { | ||
| 1868 | /* Calculate record length needed to store the entry */ | ||
| 1869 | res = ext4_fname_crypto_namelen_on_disk(ctx, namelen); | ||
| 1870 | if (res < 0) { | ||
| 1871 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1872 | return res; | ||
| 1873 | } | ||
| 1874 | reclen = EXT4_DIR_REC_LEN(res); | ||
| 1875 | |||
| 1876 | /* Allocate buffer to hold maximum name length */ | ||
| 1877 | res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN, | ||
| 1878 | &fname_crypto_str); | ||
| 1879 | if (res < 0) { | ||
| 1880 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1881 | return -1; | ||
| 1882 | } | ||
| 1883 | } | ||
| 1738 | 1884 | ||
| 1739 | de = (struct ext4_dir_entry_2 *)buf; | 1885 | de = (struct ext4_dir_entry_2 *)buf; |
| 1740 | top = buf + buf_size - reclen; | 1886 | top = buf + buf_size - reclen; |
| 1741 | while ((char *) de <= top) { | 1887 | while ((char *) de <= top) { |
| 1742 | if (ext4_check_dir_entry(dir, NULL, de, bh, | 1888 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
| 1743 | buf, buf_size, offset)) | 1889 | buf, buf_size, offset)) { |
| 1744 | return -EIO; | 1890 | res = -EIO; |
| 1745 | if (ext4_match(namelen, name, de)) | 1891 | goto return_result; |
| 1746 | return -EEXIST; | 1892 | } |
| 1893 | /* Provide crypto context and crypto buffer to ext4 match */ | ||
| 1894 | res = ext4_match(ctx, &fname_crypto_str, namelen, name, de); | ||
| 1895 | if (res < 0) | ||
| 1896 | goto return_result; | ||
| 1897 | if (res > 0) { | ||
| 1898 | res = -EEXIST; | ||
| 1899 | goto return_result; | ||
| 1900 | } | ||
| 1747 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 1901 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
| 1748 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); | 1902 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); |
| 1749 | if ((de->inode ? rlen - nlen : rlen) >= reclen) | 1903 | if ((de->inode ? rlen - nlen : rlen) >= reclen) |
| @@ -1751,11 +1905,17 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, | |||
| 1751 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); | 1905 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); |
| 1752 | offset += rlen; | 1906 | offset += rlen; |
| 1753 | } | 1907 | } |
| 1754 | if ((char *) de > top) | ||
| 1755 | return -ENOSPC; | ||
| 1756 | 1908 | ||
| 1757 | *dest_de = de; | 1909 | if ((char *) de > top) |
| 1758 | return 0; | 1910 | res = -ENOSPC; |
| 1911 | else { | ||
| 1912 | *dest_de = de; | ||
| 1913 | res = 0; | ||
| 1914 | } | ||
| 1915 | return_result: | ||
| 1916 | ext4_put_fname_crypto_ctx(&ctx); | ||
| 1917 | ext4_fname_crypto_free_buffer(&fname_crypto_str); | ||
| 1918 | return res; | ||
| 1759 | } | 1919 | } |
| 1760 | 1920 | ||
| 1761 | int ext4_insert_dentry(struct inode *dir, | 1921 | int ext4_insert_dentry(struct inode *dir, |
