aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@google.com>2015-04-12 01:09:03 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-04-12 01:09:03 -0400
commit1f3862b5575b138e83080232706e37ee24b8093e (patch)
tree633ea79c868c96823445e2386ab68e978f3b5136 /fs
parentb30984864406ad01b72eee486add103e9cb3526f (diff)
ext4 crypto: filename encryption modifications
Modifies htree_dirblock_to_tree, dx_make_map, ext4_match search_dir, and ext4_find_dest_de to support fname crypto. Filename encryption feature is not yet enabled at this patch. Signed-off-by: Uday Savagaonkar <savagaon@google.com> Signed-off-by: Ildar Muslukhov <ildarm@google.com> Signed-off-by: Michael Halcrow <mhalcrow@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/namei.c248
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);
255static void dx_release(struct dx_frame *frames); 255static void dx_release(struct dx_frame *frames);
256static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, 256static 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[]);
258static void dx_sort_map(struct dx_map_entry *map, unsigned count); 259static void dx_sort_map(struct dx_map_entry *map, unsigned count);
259static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, 260static 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 }
1051errout:
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 */
1141static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, 1189static 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 */
1212static inline int ext4_match (int len, const char * const name, 1279static 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 */
1225int search_dir(struct buffer_head *bh, 1310int 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;
1376return_result:
1377 ext4_put_fname_crypto_ctx(&ctx);
1378 ext4_fname_crypto_free_buffer(&fname_crypto_str);
1379 return res;
1263} 1380}
1264 1381
1265static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block, 1382static 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 }
1915return_result:
1916 ext4_put_fname_crypto_ctx(&ctx);
1917 ext4_fname_crypto_free_buffer(&fname_crypto_str);
1918 return res;
1759} 1919}
1760 1920
1761int ext4_insert_dentry(struct inode *dir, 1921int ext4_insert_dentry(struct inode *dir,