diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-02-12 03:53:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:36 -0500 |
commit | dd2a3b7ad98f8482cae481cad89dfed5eee48365 (patch) | |
tree | 986c09754176ea4c6e8308c6e2cdbf3fc0658a0b /fs/ecryptfs | |
parent | 17398957aa0a05ef62535060b41d103590dcc533 (diff) |
[PATCH] eCryptfs: Generalize metadata read/write
Generalize the metadata reading and writing mechanisms, with two targets for
now: metadata in file header and metadata in the user.ecryptfs xattr of the
lower file.
[akpm@osdl.org: printk warning fix]
[bunk@stusta.de: make some needlessly global code static]
Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/crypto.c | 234 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 51 | ||||
-rw-r--r-- | fs/ecryptfs/file.c | 27 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 61 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 7 | ||||
-rw-r--r-- | fs/ecryptfs/messaging.c | 18 | ||||
-rw-r--r-- | fs/ecryptfs/mmap.c | 96 |
7 files changed, 348 insertions, 146 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 6d85aabb0179..96fa40a48b4f 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompson <mcthomps@us.ibm.com> | 8 | * Michael C. Thompson <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -863,7 +863,10 @@ void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) | |||
863 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; | 863 | ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; |
864 | } else | 864 | } else |
865 | crypt_stat->header_extent_size = PAGE_CACHE_SIZE; | 865 | crypt_stat->header_extent_size = PAGE_CACHE_SIZE; |
866 | crypt_stat->num_header_extents_at_front = 1; | 866 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
867 | crypt_stat->num_header_extents_at_front = 0; | ||
868 | else | ||
869 | crypt_stat->num_header_extents_at_front = 1; | ||
867 | } | 870 | } |
868 | 871 | ||
869 | /** | 872 | /** |
@@ -1021,7 +1024,7 @@ int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) | |||
1021 | * | 1024 | * |
1022 | * Returns one if marker found; zero if not found | 1025 | * Returns one if marker found; zero if not found |
1023 | */ | 1026 | */ |
1024 | int contains_ecryptfs_marker(char *data) | 1027 | static int contains_ecryptfs_marker(char *data) |
1025 | { | 1028 | { |
1026 | u32 m_1, m_2; | 1029 | u32 m_1, m_2; |
1027 | 1030 | ||
@@ -1047,7 +1050,8 @@ struct ecryptfs_flag_map_elem { | |||
1047 | /* Add support for additional flags by adding elements here. */ | 1050 | /* Add support for additional flags by adding elements here. */ |
1048 | static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { | 1051 | static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { |
1049 | {0x00000001, ECRYPTFS_ENABLE_HMAC}, | 1052 | {0x00000001, ECRYPTFS_ENABLE_HMAC}, |
1050 | {0x00000002, ECRYPTFS_ENCRYPTED} | 1053 | {0x00000002, ECRYPTFS_ENCRYPTED}, |
1054 | {0x00000004, ECRYPTFS_METADATA_IN_XATTR} | ||
1051 | }; | 1055 | }; |
1052 | 1056 | ||
1053 | /** | 1057 | /** |
@@ -1207,8 +1211,8 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) | |||
1207 | * | 1211 | * |
1208 | * Returns zero on success; non-zero otherwise | 1212 | * Returns zero on success; non-zero otherwise |
1209 | */ | 1213 | */ |
1210 | int ecryptfs_read_header_region(char *data, struct dentry *dentry, | 1214 | static int ecryptfs_read_header_region(char *data, struct dentry *dentry, |
1211 | struct vfsmount *mnt) | 1215 | struct vfsmount *mnt) |
1212 | { | 1216 | { |
1213 | struct file *lower_file; | 1217 | struct file *lower_file; |
1214 | mm_segment_t oldfs; | 1218 | mm_segment_t oldfs; |
@@ -1237,6 +1241,21 @@ out: | |||
1237 | return rc; | 1241 | return rc; |
1238 | } | 1242 | } |
1239 | 1243 | ||
1244 | int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, | ||
1245 | struct vfsmount *mnt) | ||
1246 | { | ||
1247 | int rc; | ||
1248 | |||
1249 | rc = ecryptfs_read_header_region(data, dentry, mnt); | ||
1250 | if (rc) | ||
1251 | goto out; | ||
1252 | if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) | ||
1253 | rc = -EINVAL; | ||
1254 | out: | ||
1255 | return rc; | ||
1256 | } | ||
1257 | |||
1258 | |||
1240 | static void | 1259 | static void |
1241 | write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat, | 1260 | write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat, |
1242 | size_t *written) | 1261 | size_t *written) |
@@ -1288,9 +1307,9 @@ struct kmem_cache *ecryptfs_header_cache_2; | |||
1288 | * | 1307 | * |
1289 | * Returns zero on success | 1308 | * Returns zero on success |
1290 | */ | 1309 | */ |
1291 | int ecryptfs_write_headers_virt(char *page_virt, | 1310 | static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, |
1292 | struct ecryptfs_crypt_stat *crypt_stat, | 1311 | struct ecryptfs_crypt_stat *crypt_stat, |
1293 | struct dentry *ecryptfs_dentry) | 1312 | struct dentry *ecryptfs_dentry) |
1294 | { | 1313 | { |
1295 | int rc; | 1314 | int rc; |
1296 | size_t written; | 1315 | size_t written; |
@@ -1309,11 +1328,53 @@ int ecryptfs_write_headers_virt(char *page_virt, | |||
1309 | if (rc) | 1328 | if (rc) |
1310 | ecryptfs_printk(KERN_WARNING, "Error generating key packet " | 1329 | ecryptfs_printk(KERN_WARNING, "Error generating key packet " |
1311 | "set; rc = [%d]\n", rc); | 1330 | "set; rc = [%d]\n", rc); |
1331 | if (size) { | ||
1332 | offset += written; | ||
1333 | *size = offset; | ||
1334 | } | ||
1335 | return rc; | ||
1336 | } | ||
1337 | |||
1338 | static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat, | ||
1339 | struct file *lower_file, | ||
1340 | char *page_virt) | ||
1341 | { | ||
1342 | mm_segment_t oldfs; | ||
1343 | int current_header_page; | ||
1344 | int header_pages; | ||
1345 | |||
1346 | lower_file->f_pos = 0; | ||
1347 | oldfs = get_fs(); | ||
1348 | set_fs(get_ds()); | ||
1349 | lower_file->f_op->write(lower_file, (char __user *)page_virt, | ||
1350 | PAGE_CACHE_SIZE, &lower_file->f_pos); | ||
1351 | header_pages = ((crypt_stat->header_extent_size | ||
1352 | * crypt_stat->num_header_extents_at_front) | ||
1353 | / PAGE_CACHE_SIZE); | ||
1354 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
1355 | current_header_page = 1; | ||
1356 | while (current_header_page < header_pages) { | ||
1357 | lower_file->f_op->write(lower_file, (char __user *)page_virt, | ||
1358 | PAGE_CACHE_SIZE, &lower_file->f_pos); | ||
1359 | current_header_page++; | ||
1360 | } | ||
1361 | set_fs(oldfs); | ||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, | ||
1366 | struct ecryptfs_crypt_stat *crypt_stat, | ||
1367 | char *page_virt, size_t size) | ||
1368 | { | ||
1369 | int rc; | ||
1370 | |||
1371 | rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt, | ||
1372 | size, 0); | ||
1312 | return rc; | 1373 | return rc; |
1313 | } | 1374 | } |
1314 | 1375 | ||
1315 | /** | 1376 | /** |
1316 | * ecryptfs_write_headers | 1377 | * ecryptfs_write_metadata |
1317 | * @lower_file: The lower file struct, which was returned from dentry_open | 1378 | * @lower_file: The lower file struct, which was returned from dentry_open |
1318 | * | 1379 | * |
1319 | * Write the file headers out. This will likely involve a userspace | 1380 | * Write the file headers out. This will likely involve a userspace |
@@ -1324,14 +1385,12 @@ int ecryptfs_write_headers_virt(char *page_virt, | |||
1324 | * | 1385 | * |
1325 | * Returns zero on success; non-zero on error | 1386 | * Returns zero on success; non-zero on error |
1326 | */ | 1387 | */ |
1327 | int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, | 1388 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, |
1328 | struct file *lower_file) | 1389 | struct file *lower_file) |
1329 | { | 1390 | { |
1330 | mm_segment_t oldfs; | ||
1331 | struct ecryptfs_crypt_stat *crypt_stat; | 1391 | struct ecryptfs_crypt_stat *crypt_stat; |
1332 | char *page_virt; | 1392 | char *page_virt; |
1333 | int current_header_page; | 1393 | size_t size; |
1334 | int header_pages; | ||
1335 | int rc = 0; | 1394 | int rc = 0; |
1336 | 1395 | ||
1337 | crypt_stat = &ecryptfs_inode_to_private( | 1396 | crypt_stat = &ecryptfs_inode_to_private( |
@@ -1358,48 +1417,36 @@ int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, | |||
1358 | rc = -ENOMEM; | 1417 | rc = -ENOMEM; |
1359 | goto out; | 1418 | goto out; |
1360 | } | 1419 | } |
1361 | 1420 | rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat, | |
1362 | rc = ecryptfs_write_headers_virt(page_virt, crypt_stat, | 1421 | ecryptfs_dentry); |
1363 | ecryptfs_dentry); | ||
1364 | if (unlikely(rc)) { | 1422 | if (unlikely(rc)) { |
1365 | ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n"); | 1423 | ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n"); |
1366 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 1424 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
1367 | goto out_free; | 1425 | goto out_free; |
1368 | } | 1426 | } |
1369 | ecryptfs_printk(KERN_DEBUG, | 1427 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) |
1370 | "Writing key packet set to underlying file\n"); | 1428 | rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, |
1371 | lower_file->f_pos = 0; | 1429 | crypt_stat, page_virt, |
1372 | oldfs = get_fs(); | 1430 | size); |
1373 | set_fs(get_ds()); | 1431 | else |
1374 | ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->" | 1432 | rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file, |
1375 | "write() w/ header page; lower_file->f_pos = " | 1433 | page_virt); |
1376 | "[0x%.16x]\n", lower_file->f_pos); | 1434 | if (rc) { |
1377 | lower_file->f_op->write(lower_file, (char __user *)page_virt, | 1435 | printk(KERN_ERR "Error writing metadata out to lower file; " |
1378 | PAGE_CACHE_SIZE, &lower_file->f_pos); | 1436 | "rc = [%d]\n", rc); |
1379 | header_pages = ((crypt_stat->header_extent_size | 1437 | goto out_free; |
1380 | * crypt_stat->num_header_extents_at_front) | ||
1381 | / PAGE_CACHE_SIZE); | ||
1382 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
1383 | current_header_page = 1; | ||
1384 | while (current_header_page < header_pages) { | ||
1385 | ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->" | ||
1386 | "write() w/ zero'd page; lower_file->f_pos = " | ||
1387 | "[0x%.16x]\n", lower_file->f_pos); | ||
1388 | lower_file->f_op->write(lower_file, (char __user *)page_virt, | ||
1389 | PAGE_CACHE_SIZE, &lower_file->f_pos); | ||
1390 | current_header_page++; | ||
1391 | } | 1438 | } |
1392 | set_fs(oldfs); | ||
1393 | ecryptfs_printk(KERN_DEBUG, | ||
1394 | "Done writing key packet set to underlying file.\n"); | ||
1395 | out_free: | 1439 | out_free: |
1396 | kmem_cache_free(ecryptfs_header_cache_0, page_virt); | 1440 | kmem_cache_free(ecryptfs_header_cache_0, page_virt); |
1397 | out: | 1441 | out: |
1398 | return rc; | 1442 | return rc; |
1399 | } | 1443 | } |
1400 | 1444 | ||
1445 | #define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0 | ||
1446 | #define ECRYPTFS_VALIDATE_HEADER_SIZE 1 | ||
1401 | static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, | 1447 | static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, |
1402 | char *virt, int *bytes_read) | 1448 | char *virt, int *bytes_read, |
1449 | int validate_header_size) | ||
1403 | { | 1450 | { |
1404 | int rc = 0; | 1451 | int rc = 0; |
1405 | u32 header_extent_size; | 1452 | u32 header_extent_size; |
@@ -1414,9 +1461,10 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, | |||
1414 | crypt_stat->num_header_extents_at_front = | 1461 | crypt_stat->num_header_extents_at_front = |
1415 | (int)num_header_extents_at_front; | 1462 | (int)num_header_extents_at_front; |
1416 | (*bytes_read) = 6; | 1463 | (*bytes_read) = 6; |
1417 | if ((crypt_stat->header_extent_size | 1464 | if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) |
1418 | * crypt_stat->num_header_extents_at_front) | 1465 | && ((crypt_stat->header_extent_size |
1419 | < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { | 1466 | * crypt_stat->num_header_extents_at_front) |
1467 | < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { | ||
1420 | rc = -EINVAL; | 1468 | rc = -EINVAL; |
1421 | ecryptfs_printk(KERN_WARNING, "Invalid header extent size: " | 1469 | ecryptfs_printk(KERN_WARNING, "Invalid header extent size: " |
1422 | "[%d]\n", crypt_stat->header_extent_size); | 1470 | "[%d]\n", crypt_stat->header_extent_size); |
@@ -1447,7 +1495,8 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) | |||
1447 | */ | 1495 | */ |
1448 | static int ecryptfs_read_headers_virt(char *page_virt, | 1496 | static int ecryptfs_read_headers_virt(char *page_virt, |
1449 | struct ecryptfs_crypt_stat *crypt_stat, | 1497 | struct ecryptfs_crypt_stat *crypt_stat, |
1450 | struct dentry *ecryptfs_dentry) | 1498 | struct dentry *ecryptfs_dentry, |
1499 | int validate_header_size) | ||
1451 | { | 1500 | { |
1452 | int rc = 0; | 1501 | int rc = 0; |
1453 | int offset; | 1502 | int offset; |
@@ -1481,7 +1530,7 @@ static int ecryptfs_read_headers_virt(char *page_virt, | |||
1481 | offset += bytes_read; | 1530 | offset += bytes_read; |
1482 | if (crypt_stat->file_version >= 1) { | 1531 | if (crypt_stat->file_version >= 1) { |
1483 | rc = parse_header_metadata(crypt_stat, (page_virt + offset), | 1532 | rc = parse_header_metadata(crypt_stat, (page_virt + offset), |
1484 | &bytes_read); | 1533 | &bytes_read, validate_header_size); |
1485 | if (rc) { | 1534 | if (rc) { |
1486 | ecryptfs_printk(KERN_WARNING, "Error reading header " | 1535 | ecryptfs_printk(KERN_WARNING, "Error reading header " |
1487 | "metadata; rc = [%d]\n", rc); | 1536 | "metadata; rc = [%d]\n", rc); |
@@ -1496,12 +1545,60 @@ out: | |||
1496 | } | 1545 | } |
1497 | 1546 | ||
1498 | /** | 1547 | /** |
1499 | * ecryptfs_read_headers | 1548 | * ecryptfs_read_xattr_region |
1549 | * | ||
1550 | * Attempts to read the crypto metadata from the extended attribute | ||
1551 | * region of the lower file. | ||
1552 | */ | ||
1553 | int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry) | ||
1554 | { | ||
1555 | ssize_t size; | ||
1556 | int rc = 0; | ||
1557 | |||
1558 | size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, | ||
1559 | page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); | ||
1560 | if (size < 0) { | ||
1561 | printk(KERN_DEBUG "Error attempting to read the [%s] " | ||
1562 | "xattr from the lower file; return value = [%zd]\n", | ||
1563 | ECRYPTFS_XATTR_NAME, size); | ||
1564 | rc = -EINVAL; | ||
1565 | goto out; | ||
1566 | } | ||
1567 | out: | ||
1568 | return rc; | ||
1569 | } | ||
1570 | |||
1571 | int ecryptfs_read_and_validate_xattr_region(char *page_virt, | ||
1572 | struct dentry *ecryptfs_dentry) | ||
1573 | { | ||
1574 | int rc; | ||
1575 | |||
1576 | rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry); | ||
1577 | if (rc) | ||
1578 | goto out; | ||
1579 | if (!contains_ecryptfs_marker(page_virt + ECRYPTFS_FILE_SIZE_BYTES)) { | ||
1580 | printk(KERN_WARNING "Valid data found in [%s] xattr, but " | ||
1581 | "the marker is invalid\n", ECRYPTFS_XATTR_NAME); | ||
1582 | rc = -EINVAL; | ||
1583 | } | ||
1584 | out: | ||
1585 | return rc; | ||
1586 | } | ||
1587 | |||
1588 | /** | ||
1589 | * ecryptfs_read_metadata | ||
1590 | * | ||
1591 | * Common entry point for reading file metadata. From here, we could | ||
1592 | * retrieve the header information from the header region of the file, | ||
1593 | * the xattr region of the file, or some other repostory that is | ||
1594 | * stored separately from the file itself. The current implementation | ||
1595 | * supports retrieving the metadata information from the file contents | ||
1596 | * and from the xattr region. | ||
1500 | * | 1597 | * |
1501 | * Returns zero if valid headers found and parsed; non-zero otherwise | 1598 | * Returns zero if valid headers found and parsed; non-zero otherwise |
1502 | */ | 1599 | */ |
1503 | int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | 1600 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, |
1504 | struct file *lower_file) | 1601 | struct file *lower_file) |
1505 | { | 1602 | { |
1506 | int rc = 0; | 1603 | int rc = 0; |
1507 | char *page_virt = NULL; | 1604 | char *page_virt = NULL; |
@@ -1530,11 +1627,36 @@ int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | |||
1530 | goto out; | 1627 | goto out; |
1531 | } | 1628 | } |
1532 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, | 1629 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, |
1533 | ecryptfs_dentry); | 1630 | ecryptfs_dentry, |
1631 | ECRYPTFS_VALIDATE_HEADER_SIZE); | ||
1534 | if (rc) { | 1632 | if (rc) { |
1535 | ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not " | 1633 | rc = ecryptfs_read_xattr_region(page_virt, |
1536 | "found\n"); | 1634 | ecryptfs_dentry); |
1537 | rc = -EINVAL; | 1635 | if (rc) { |
1636 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | ||
1637 | "file header region or xattr region\n"); | ||
1638 | rc = -EINVAL; | ||
1639 | goto out; | ||
1640 | } | ||
1641 | rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, | ||
1642 | ecryptfs_dentry, | ||
1643 | ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); | ||
1644 | if (rc) { | ||
1645 | printk(KERN_DEBUG "Valid eCryptfs headers not found in " | ||
1646 | "file xattr region either\n"); | ||
1647 | rc = -EINVAL; | ||
1648 | } | ||
1649 | if (crypt_stat->mount_crypt_stat->flags | ||
1650 | & ECRYPTFS_XATTR_METADATA_ENABLED) { | ||
1651 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | ||
1652 | } else { | ||
1653 | printk(KERN_WARNING "Attempt to access file with " | ||
1654 | "crypto metadata only in the extended attribute " | ||
1655 | "region, but eCryptfs was mounted without " | ||
1656 | "xattr support enabled. eCryptfs will not treat " | ||
1657 | "this like an encrypted file.\n"); | ||
1658 | rc = -EINVAL; | ||
1659 | } | ||
1538 | } | 1660 | } |
1539 | out: | 1661 | out: |
1540 | if (page_virt) { | 1662 | if (page_virt) { |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 7bbd6e6e2743..020abcd16f0e 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 1997-2003 Erez Zadok | 5 | * Copyright (C) 1997-2003 Erez Zadok |
6 | * Copyright (C) 2001-2003 Stony Brook University | 6 | * Copyright (C) 2001-2003 Stony Brook University |
7 | * Copyright (C) 2004-2006 International Business Machines Corp. | 7 | * Copyright (C) 2004-2007 International Business Machines Corp. |
8 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 8 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
9 | * Trevor S. Highland <trevor.highland@gmail.com> | 9 | * Trevor S. Highland <trevor.highland@gmail.com> |
10 | * Tyler Hicks <tyhicks@ou.edu> | 10 | * Tyler Hicks <tyhicks@ou.edu> |
@@ -50,8 +50,8 @@ | |||
50 | #define ECRYPTFS_VERSIONING_XATTR 0x00000010 | 50 | #define ECRYPTFS_VERSIONING_XATTR 0x00000010 |
51 | #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ | 51 | #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ |
52 | | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ | 52 | | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ |
53 | | ECRYPTFS_VERSIONING_PUBKEY) | 53 | | ECRYPTFS_VERSIONING_PUBKEY \ |
54 | 54 | | ECRYPTFS_VERSIONING_XATTR) | |
55 | #define ECRYPTFS_MAX_PASSWORD_LENGTH 64 | 55 | #define ECRYPTFS_MAX_PASSWORD_LENGTH 64 |
56 | #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH | 56 | #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH |
57 | #define ECRYPTFS_SALT_SIZE 8 | 57 | #define ECRYPTFS_SALT_SIZE 8 |
@@ -83,6 +83,7 @@ | |||
83 | #define ECRYPTFS_TRANSPORT_CONNECTOR 1 | 83 | #define ECRYPTFS_TRANSPORT_CONNECTOR 1 |
84 | #define ECRYPTFS_TRANSPORT_RELAYFS 2 | 84 | #define ECRYPTFS_TRANSPORT_RELAYFS 2 |
85 | #define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK | 85 | #define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK |
86 | #define ECRYPTFS_XATTR_NAME "user.ecryptfs" | ||
86 | 87 | ||
87 | #define RFC2440_CIPHER_DES3_EDE 0x02 | 88 | #define RFC2440_CIPHER_DES3_EDE 0x02 |
88 | #define RFC2440_CIPHER_CAST_5 0x03 | 89 | #define RFC2440_CIPHER_CAST_5 0x03 |
@@ -327,18 +328,6 @@ struct ecryptfs_msg_ctx { | |||
327 | struct mutex mux; | 328 | struct mutex mux; |
328 | }; | 329 | }; |
329 | 330 | ||
330 | extern struct list_head ecryptfs_msg_ctx_free_list; | ||
331 | extern struct list_head ecryptfs_msg_ctx_alloc_list; | ||
332 | extern struct mutex ecryptfs_msg_ctx_lists_mux; | ||
333 | |||
334 | #define ecryptfs_uid_hash(uid) \ | ||
335 | hash_long((unsigned long)uid, ecryptfs_hash_buckets) | ||
336 | extern struct hlist_head *ecryptfs_daemon_id_hash; | ||
337 | extern struct mutex ecryptfs_daemon_id_hash_mux; | ||
338 | extern int ecryptfs_hash_buckets; | ||
339 | |||
340 | extern unsigned int ecryptfs_msg_counter; | ||
341 | extern struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | ||
342 | extern unsigned int ecryptfs_transport; | 331 | extern unsigned int ecryptfs_transport; |
343 | 332 | ||
344 | struct ecryptfs_daemon_id { | 333 | struct ecryptfs_daemon_id { |
@@ -479,6 +468,7 @@ extern struct kmem_cache *ecryptfs_sb_info_cache; | |||
479 | extern struct kmem_cache *ecryptfs_header_cache_0; | 468 | extern struct kmem_cache *ecryptfs_header_cache_0; |
480 | extern struct kmem_cache *ecryptfs_header_cache_1; | 469 | extern struct kmem_cache *ecryptfs_header_cache_1; |
481 | extern struct kmem_cache *ecryptfs_header_cache_2; | 470 | extern struct kmem_cache *ecryptfs_header_cache_2; |
471 | extern struct kmem_cache *ecryptfs_xattr_cache; | ||
482 | extern struct kmem_cache *ecryptfs_lower_page_cache; | 472 | extern struct kmem_cache *ecryptfs_lower_page_cache; |
483 | 473 | ||
484 | int ecryptfs_interpose(struct dentry *hidden_dentry, | 474 | int ecryptfs_interpose(struct dentry *hidden_dentry, |
@@ -505,9 +495,13 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); | |||
505 | int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, | 495 | int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, |
506 | char *cipher_name, | 496 | char *cipher_name, |
507 | char *chaining_modifier); | 497 | char *chaining_modifier); |
508 | int ecryptfs_write_inode_size_to_header(struct file *lower_file, | 498 | #define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0 |
509 | struct inode *lower_inode, | 499 | #define ECRYPTFS_LOWER_I_MUTEX_HELD 1 |
510 | struct inode *inode); | 500 | int ecryptfs_write_inode_size_to_metadata(struct file *lower_file, |
501 | struct inode *lower_inode, | ||
502 | struct inode *inode, | ||
503 | struct dentry *ecryptfs_dentry, | ||
504 | int lower_i_mutex_held); | ||
511 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | 505 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, |
512 | struct file *lower_file, | 506 | struct file *lower_file, |
513 | unsigned long lower_page_index, int byte_offset, | 507 | unsigned long lower_page_index, int byte_offset, |
@@ -529,17 +523,15 @@ int ecryptfs_writepage_and_release_lower_page(struct page *lower_page, | |||
529 | struct writeback_control *wbc); | 523 | struct writeback_control *wbc); |
530 | int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx); | 524 | int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx); |
531 | int ecryptfs_decrypt_page(struct file *file, struct page *page); | 525 | int ecryptfs_decrypt_page(struct file *file, struct page *page); |
532 | int ecryptfs_write_headers(struct dentry *ecryptfs_dentry, | 526 | int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, |
527 | struct file *lower_file); | ||
528 | int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry, | ||
533 | struct file *lower_file); | 529 | struct file *lower_file); |
534 | int ecryptfs_write_headers_virt(char *page_virt, | ||
535 | struct ecryptfs_crypt_stat *crypt_stat, | ||
536 | struct dentry *ecryptfs_dentry); | ||
537 | int ecryptfs_read_headers(struct dentry *ecryptfs_dentry, | ||
538 | struct file *lower_file); | ||
539 | int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); | 530 | int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); |
540 | int contains_ecryptfs_marker(char *data); | 531 | int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry, |
541 | int ecryptfs_read_header_region(char *data, struct dentry *dentry, | 532 | struct vfsmount *mnt); |
542 | struct vfsmount *mnt); | 533 | int ecryptfs_read_and_validate_xattr_region(char *page_virt, |
534 | struct dentry *ecryptfs_dentry); | ||
543 | u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat); | 535 | u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat); |
544 | int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code); | 536 | int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code); |
545 | void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat); | 537 | void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat); |
@@ -562,6 +554,11 @@ int ecryptfs_open_lower_file(struct file **lower_file, | |||
562 | struct dentry *lower_dentry, | 554 | struct dentry *lower_dentry, |
563 | struct vfsmount *lower_mnt, int flags); | 555 | struct vfsmount *lower_mnt, int flags); |
564 | int ecryptfs_close_lower_file(struct file *lower_file); | 556 | int ecryptfs_close_lower_file(struct file *lower_file); |
557 | ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, | ||
558 | size_t size); | ||
559 | int | ||
560 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | ||
561 | size_t size, int flags); | ||
565 | 562 | ||
566 | int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid); | 563 | int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid); |
567 | int ecryptfs_process_quit(uid_t uid, pid_t pid); | 564 | int ecryptfs_process_quit(uid_t uid, pid_t pid); |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 779c3477d93c..f22c3a73485c 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com> |
8 | * Michael C. Thompson <mcthomps@us.ibm.com> | 8 | * Michael C. Thompson <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -293,26 +293,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
293 | goto out; | 293 | goto out; |
294 | } | 294 | } |
295 | mutex_lock(&crypt_stat->cs_mutex); | 295 | mutex_lock(&crypt_stat->cs_mutex); |
296 | if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) { | 296 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, |
297 | if (!(mount_crypt_stat->flags | 297 | ECRYPTFS_POLICY_APPLIED) |
298 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { | 298 | || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, |
299 | rc = -EIO; | 299 | ECRYPTFS_KEY_VALID)) { |
300 | printk(KERN_WARNING "Attempt to read file that is " | 300 | rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file); |
301 | "not in a valid eCryptfs format, and plaintext " | ||
302 | "passthrough mode is not enabled; returning " | ||
303 | "-EIO\n"); | ||
304 | mutex_unlock(&crypt_stat->cs_mutex); | ||
305 | goto out_puts; | ||
306 | } | ||
307 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | ||
308 | rc = 0; | ||
309 | mutex_unlock(&crypt_stat->cs_mutex); | ||
310 | goto out; | ||
311 | } else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | ||
312 | ECRYPTFS_POLICY_APPLIED) | ||
313 | || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, | ||
314 | ECRYPTFS_KEY_VALID)) { | ||
315 | rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file); | ||
316 | if (rc) { | 301 | if (rc) { |
317 | ecryptfs_printk(KERN_DEBUG, | 302 | ecryptfs_printk(KERN_DEBUG, |
318 | "Valid headers not found\n"); | 303 | "Valid headers not found\n"); |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index d4f02f3e18d7..6b45b2908f17 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2004 Erez Zadok | 4 | * Copyright (C) 1997-2004 Erez Zadok |
5 | * Copyright (C) 2001-2004 Stony Brook University | 5 | * Copyright (C) 2001-2004 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompsion <mcthomps@us.ibm.com> | 8 | * Michael C. Thompsion <mcthomps@us.ibm.com> |
9 | * | 9 | * |
@@ -169,7 +169,9 @@ static int grow_file(struct dentry *ecryptfs_dentry, struct file *lower_file, | |||
169 | goto out; | 169 | goto out; |
170 | } | 170 | } |
171 | i_size_write(inode, 0); | 171 | i_size_write(inode, 0); |
172 | ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); | 172 | ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode, |
173 | ecryptfs_dentry, | ||
174 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); | ||
173 | ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags, | 175 | ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags, |
174 | ECRYPTFS_NEW_FILE); | 176 | ECRYPTFS_NEW_FILE); |
175 | out: | 177 | out: |
@@ -225,7 +227,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
225 | "context\n"); | 227 | "context\n"); |
226 | goto out_fput; | 228 | goto out_fput; |
227 | } | 229 | } |
228 | rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file); | 230 | rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file); |
229 | if (rc) { | 231 | if (rc) { |
230 | ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); | 232 | ecryptfs_printk(KERN_DEBUG, "Error writing headers\n"); |
231 | goto out_fput; | 233 | goto out_fput; |
@@ -362,32 +364,33 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, | |||
362 | } | 364 | } |
363 | /* Released in this function */ | 365 | /* Released in this function */ |
364 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, | 366 | page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, |
365 | GFP_USER); | 367 | GFP_USER); |
366 | if (!page_virt) { | 368 | if (!page_virt) { |
367 | rc = -ENOMEM; | 369 | rc = -ENOMEM; |
368 | ecryptfs_printk(KERN_ERR, | 370 | ecryptfs_printk(KERN_ERR, |
369 | "Cannot ecryptfs_kmalloc a page\n"); | 371 | "Cannot ecryptfs_kmalloc a page\n"); |
370 | goto out_dput; | 372 | goto out_dput; |
371 | } | 373 | } |
372 | |||
373 | rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); | ||
374 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 374 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
375 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) | 375 | if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) |
376 | ecryptfs_set_default_sizes(crypt_stat); | 376 | ecryptfs_set_default_sizes(crypt_stat); |
377 | rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry, | ||
378 | nd->mnt); | ||
377 | if (rc) { | 379 | if (rc) { |
378 | rc = 0; | 380 | rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry); |
379 | ecryptfs_printk(KERN_WARNING, "Error reading header region;" | 381 | if (rc) { |
380 | " assuming unencrypted\n"); | 382 | printk(KERN_DEBUG "Valid metadata not found in header " |
381 | } else { | 383 | "region or xattr region; treating file as " |
382 | if (!contains_ecryptfs_marker(page_virt | 384 | "unencrypted\n"); |
383 | + ECRYPTFS_FILE_SIZE_BYTES)) { | 385 | rc = 0; |
384 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 386 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
385 | goto out; | 387 | goto out; |
386 | } | 388 | } |
387 | memcpy(&file_size, page_virt, sizeof(file_size)); | 389 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; |
388 | file_size = be64_to_cpu(file_size); | ||
389 | i_size_write(dentry->d_inode, (loff_t)file_size); | ||
390 | } | 390 | } |
391 | memcpy(&file_size, page_virt, sizeof(file_size)); | ||
392 | file_size = be64_to_cpu(file_size); | ||
393 | i_size_write(dentry->d_inode, (loff_t)file_size); | ||
391 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 394 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
392 | goto out; | 395 | goto out; |
393 | 396 | ||
@@ -781,20 +784,26 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
781 | goto out_fput; | 784 | goto out_fput; |
782 | } | 785 | } |
783 | i_size_write(inode, new_length); | 786 | i_size_write(inode, new_length); |
784 | rc = ecryptfs_write_inode_size_to_header(lower_file, | 787 | rc = ecryptfs_write_inode_size_to_metadata( |
785 | lower_dentry->d_inode, | 788 | lower_file, lower_dentry->d_inode, inode, dentry, |
786 | inode); | 789 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
787 | if (rc) { | 790 | if (rc) { |
788 | ecryptfs_printk(KERN_ERR, | 791 | printk(KERN_ERR "Problem with " |
789 | "Problem with ecryptfs_write" | 792 | "ecryptfs_write_inode_size_to_metadata; " |
790 | "_inode_size\n"); | 793 | "rc = [%d]\n", rc); |
791 | goto out_fput; | 794 | goto out_fput; |
792 | } | 795 | } |
793 | } else { /* new_length < i_size_read(inode) */ | 796 | } else { /* new_length < i_size_read(inode) */ |
794 | vmtruncate(inode, new_length); | 797 | vmtruncate(inode, new_length); |
795 | ecryptfs_write_inode_size_to_header(lower_file, | 798 | rc = ecryptfs_write_inode_size_to_metadata( |
796 | lower_dentry->d_inode, | 799 | lower_file, lower_dentry->d_inode, inode, dentry, |
797 | inode); | 800 | ECRYPTFS_LOWER_I_MUTEX_NOT_HELD); |
801 | if (rc) { | ||
802 | printk(KERN_ERR "Problem with " | ||
803 | "ecryptfs_write_inode_size_to_metadata; " | ||
804 | "rc = [%d]\n", rc); | ||
805 | goto out_fput; | ||
806 | } | ||
798 | /* We are reducing the size of the ecryptfs file, and need to | 807 | /* We are reducing the size of the ecryptfs file, and need to |
799 | * know if we need to reduce the size of the lower file. */ | 808 | * know if we need to reduce the size of the lower file. */ |
800 | lower_size_before_truncate = | 809 | lower_size_before_truncate = |
@@ -881,7 +890,7 @@ out: | |||
881 | return rc; | 890 | return rc; |
882 | } | 891 | } |
883 | 892 | ||
884 | static int | 893 | int |
885 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 894 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
886 | size_t size, int flags) | 895 | size_t size, int flags) |
887 | { | 896 | { |
@@ -901,7 +910,7 @@ out: | |||
901 | return rc; | 910 | return rc; |
902 | } | 911 | } |
903 | 912 | ||
904 | static ssize_t | 913 | ssize_t |
905 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, | 914 | ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value, |
906 | size_t size) | 915 | size_t size) |
907 | { | 916 | { |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index a3efdccbbcc8..26fe405a5763 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997-2003 Erez Zadok | 4 | * Copyright (C) 1997-2003 Erez Zadok |
5 | * Copyright (C) 2001-2003 Stony Brook University | 5 | * Copyright (C) 2001-2003 Stony Brook University |
6 | * Copyright (C) 2004-2006 International Business Machines Corp. | 6 | * Copyright (C) 2004-2007 International Business Machines Corp. |
7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 7 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
8 | * Michael C. Thompson <mcthomps@us.ibm.com> | 8 | * Michael C. Thompson <mcthomps@us.ibm.com> |
9 | * Tyler Hicks <tyhicks@ou.edu> | 9 | * Tyler Hicks <tyhicks@ou.edu> |
@@ -642,6 +642,11 @@ static struct ecryptfs_cache_info { | |||
642 | .size = PAGE_CACHE_SIZE, | 642 | .size = PAGE_CACHE_SIZE, |
643 | }, | 643 | }, |
644 | { | 644 | { |
645 | .cache = &ecryptfs_xattr_cache, | ||
646 | .name = "ecryptfs_xattr_cache", | ||
647 | .size = PAGE_CACHE_SIZE, | ||
648 | }, | ||
649 | { | ||
645 | .cache = &ecryptfs_lower_page_cache, | 650 | .cache = &ecryptfs_lower_page_cache, |
646 | .name = "ecryptfs_lower_page_cache", | 651 | .name = "ecryptfs_lower_page_cache", |
647 | .size = PAGE_CACHE_SIZE, | 652 | .size = PAGE_CACHE_SIZE, |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index e8ba6278ad2c..47d7e7b611f7 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -22,16 +22,18 @@ | |||
22 | 22 | ||
23 | #include "ecryptfs_kernel.h" | 23 | #include "ecryptfs_kernel.h" |
24 | 24 | ||
25 | LIST_HEAD(ecryptfs_msg_ctx_free_list); | 25 | static LIST_HEAD(ecryptfs_msg_ctx_free_list); |
26 | LIST_HEAD(ecryptfs_msg_ctx_alloc_list); | 26 | static LIST_HEAD(ecryptfs_msg_ctx_alloc_list); |
27 | struct mutex ecryptfs_msg_ctx_lists_mux; | 27 | static struct mutex ecryptfs_msg_ctx_lists_mux; |
28 | 28 | ||
29 | struct hlist_head *ecryptfs_daemon_id_hash; | 29 | static struct hlist_head *ecryptfs_daemon_id_hash; |
30 | struct mutex ecryptfs_daemon_id_hash_mux; | 30 | static struct mutex ecryptfs_daemon_id_hash_mux; |
31 | int ecryptfs_hash_buckets; | 31 | static int ecryptfs_hash_buckets; |
32 | #define ecryptfs_uid_hash(uid) \ | ||
33 | hash_long((unsigned long)uid, ecryptfs_hash_buckets) | ||
32 | 34 | ||
33 | unsigned int ecryptfs_msg_counter; | 35 | static unsigned int ecryptfs_msg_counter; |
34 | struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | 36 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; |
35 | 37 | ||
36 | /** | 38 | /** |
37 | * ecryptfs_acquire_free_msg_ctx | 39 | * ecryptfs_acquire_free_msg_ctx |
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 0af3aa3b4b3e..ba3650d03c48 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Copyright (C) 1997-2003 Erez Zadok | 7 | * Copyright (C) 1997-2003 Erez Zadok |
8 | * Copyright (C) 2001-2003 Stony Brook University | 8 | * Copyright (C) 2001-2003 Stony Brook University |
9 | * Copyright (C) 2004-2006 International Business Machines Corp. | 9 | * Copyright (C) 2004-2007 International Business Machines Corp. |
10 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> | 10 | * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
@@ -308,6 +308,9 @@ out: | |||
308 | return rc; | 308 | return rc; |
309 | } | 309 | } |
310 | 310 | ||
311 | /** | ||
312 | * Called with lower inode mutex held. | ||
313 | */ | ||
311 | static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) | 314 | static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) |
312 | { | 315 | { |
313 | struct inode *inode = page->mapping->host; | 316 | struct inode *inode = page->mapping->host; |
@@ -407,10 +410,9 @@ static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page) | |||
407 | * | 410 | * |
408 | * Returns zero on success; non-zero on error. | 411 | * Returns zero on success; non-zero on error. |
409 | */ | 412 | */ |
410 | int | 413 | static int ecryptfs_write_inode_size_to_header(struct file *lower_file, |
411 | ecryptfs_write_inode_size_to_header(struct file *lower_file, | 414 | struct inode *lower_inode, |
412 | struct inode *lower_inode, | 415 | struct inode *inode) |
413 | struct inode *inode) | ||
414 | { | 416 | { |
415 | int rc = 0; | 417 | int rc = 0; |
416 | struct page *header_page; | 418 | struct page *header_page; |
@@ -442,6 +444,80 @@ out: | |||
442 | return rc; | 444 | return rc; |
443 | } | 445 | } |
444 | 446 | ||
447 | static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode, | ||
448 | struct inode *inode, | ||
449 | struct dentry *ecryptfs_dentry, | ||
450 | int lower_i_mutex_held) | ||
451 | { | ||
452 | ssize_t size; | ||
453 | void *xattr_virt; | ||
454 | struct dentry *lower_dentry; | ||
455 | u64 file_size; | ||
456 | int rc; | ||
457 | |||
458 | xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); | ||
459 | if (!xattr_virt) { | ||
460 | printk(KERN_ERR "Out of memory whilst attempting to write " | ||
461 | "inode size to xattr\n"); | ||
462 | rc = -ENOMEM; | ||
463 | goto out; | ||
464 | } | ||
465 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | ||
466 | if (!lower_dentry->d_inode->i_op->getxattr) { | ||
467 | printk(KERN_WARNING | ||
468 | "No support for setting xattr in lower filesystem\n"); | ||
469 | rc = -ENOSYS; | ||
470 | kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); | ||
471 | goto out; | ||
472 | } | ||
473 | if (!lower_i_mutex_held) | ||
474 | mutex_lock(&lower_dentry->d_inode->i_mutex); | ||
475 | size = lower_dentry->d_inode->i_op->getxattr(lower_dentry, | ||
476 | ECRYPTFS_XATTR_NAME, | ||
477 | xattr_virt, | ||
478 | PAGE_CACHE_SIZE); | ||
479 | if (!lower_i_mutex_held) | ||
480 | mutex_unlock(&lower_dentry->d_inode->i_mutex); | ||
481 | if (size < 0) | ||
482 | size = 8; | ||
483 | file_size = (u64)i_size_read(inode); | ||
484 | file_size = cpu_to_be64(file_size); | ||
485 | memcpy(xattr_virt, &file_size, sizeof(u64)); | ||
486 | if (!lower_i_mutex_held) | ||
487 | mutex_lock(&lower_dentry->d_inode->i_mutex); | ||
488 | rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry, | ||
489 | ECRYPTFS_XATTR_NAME, | ||
490 | xattr_virt, size, 0); | ||
491 | if (!lower_i_mutex_held) | ||
492 | mutex_unlock(&lower_dentry->d_inode->i_mutex); | ||
493 | if (rc) | ||
494 | printk(KERN_ERR "Error whilst attempting to write inode size " | ||
495 | "to lower file xattr; rc = [%d]\n", rc); | ||
496 | kmem_cache_free(ecryptfs_xattr_cache, xattr_virt); | ||
497 | out: | ||
498 | return rc; | ||
499 | } | ||
500 | |||
501 | int | ||
502 | ecryptfs_write_inode_size_to_metadata(struct file *lower_file, | ||
503 | struct inode *lower_inode, | ||
504 | struct inode *inode, | ||
505 | struct dentry *ecryptfs_dentry, | ||
506 | int lower_i_mutex_held) | ||
507 | { | ||
508 | struct ecryptfs_crypt_stat *crypt_stat; | ||
509 | |||
510 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | ||
511 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
512 | return ecryptfs_write_inode_size_to_xattr(lower_inode, inode, | ||
513 | ecryptfs_dentry, | ||
514 | lower_i_mutex_held); | ||
515 | else | ||
516 | return ecryptfs_write_inode_size_to_header(lower_file, | ||
517 | lower_inode, | ||
518 | inode); | ||
519 | } | ||
520 | |||
445 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | 521 | int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, |
446 | struct file *lower_file, | 522 | struct file *lower_file, |
447 | unsigned long lower_page_index, int byte_offset, | 523 | unsigned long lower_page_index, int byte_offset, |
@@ -528,6 +604,8 @@ out: | |||
528 | return rc; | 604 | return rc; |
529 | } | 605 | } |
530 | 606 | ||
607 | struct kmem_cache *ecryptfs_xattr_cache; | ||
608 | |||
531 | /** | 609 | /** |
532 | * ecryptfs_commit_write | 610 | * ecryptfs_commit_write |
533 | * @file: The eCryptfs file object | 611 | * @file: The eCryptfs file object |
@@ -581,7 +659,6 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
581 | "index [0x%.16x])\n", page->index); | 659 | "index [0x%.16x])\n", page->index); |
582 | goto out; | 660 | goto out; |
583 | } | 661 | } |
584 | rc = 0; | ||
585 | inode->i_blocks = lower_inode->i_blocks; | 662 | inode->i_blocks = lower_inode->i_blocks; |
586 | pos = (page->index << PAGE_CACHE_SHIFT) + to; | 663 | pos = (page->index << PAGE_CACHE_SHIFT) + to; |
587 | if (pos > i_size_read(inode)) { | 664 | if (pos > i_size_read(inode)) { |
@@ -589,7 +666,12 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
589 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " | 666 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " |
590 | "[0x%.16x]\n", i_size_read(inode)); | 667 | "[0x%.16x]\n", i_size_read(inode)); |
591 | } | 668 | } |
592 | ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode); | 669 | rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, |
670 | inode, file->f_dentry, | ||
671 | ECRYPTFS_LOWER_I_MUTEX_HELD); | ||
672 | if (rc) | ||
673 | printk(KERN_ERR "Error writing inode size to metadata; " | ||
674 | "rc = [%d]\n", rc); | ||
593 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | 675 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; |
594 | mark_inode_dirty_sync(inode); | 676 | mark_inode_dirty_sync(inode); |
595 | out: | 677 | out: |