aboutsummaryrefslogtreecommitdiff
path: root/fs/ecryptfs
diff options
context:
space:
mode:
authormerge <null@invalid>2009-01-22 13:55:32 +0000
committerAndy Green <agreen@octopus.localdomain>2009-01-22 13:55:32 +0000
commitaa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 (patch)
treefbb786d0ac6f8a774fd834e9ce951197e60fbffa /fs/ecryptfs
parentf2d78193eae5dccd3d588d2c8ea0866efc368332 (diff)
MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141
pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage: From: merge <null@invalid> MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage: From: merge <null@invalid> MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage: From: Andy Green <andy@openmoko.com> fix-stray-endmenu.patch Signed-off-by: Andy Green <andy@openmoko.com>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r--fs/ecryptfs/crypto.c514
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h108
-rw-r--r--fs/ecryptfs/file.c45
-rw-r--r--fs/ecryptfs/inode.c303
-rw-r--r--fs/ecryptfs/keystore.c682
-rw-r--r--fs/ecryptfs/kthread.c9
-rw-r--r--fs/ecryptfs/main.c129
-rw-r--r--fs/ecryptfs/messaging.c31
-rw-r--r--fs/ecryptfs/miscdev.c45
-rw-r--r--fs/ecryptfs/mmap.c2
10 files changed, 1452 insertions, 416 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 6046239465a..c01e043670e 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -175,8 +175,8 @@ out:
*
* Returns zero on success; non-zero on error.
*/
-static int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
- loff_t offset)
+int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
+ loff_t offset)
{
int rc = 0;
char dst[MD5_DIGEST_SIZE];
@@ -924,6 +924,15 @@ static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED;
+ if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
+ crypt_stat->flags |= ECRYPTFS_ENCRYPT_FILENAMES;
+ if (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)
+ crypt_stat->flags |= ECRYPTFS_ENCFN_USE_MOUNT_FNEK;
+ else if (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCFN_USE_FEK)
+ crypt_stat->flags |= ECRYPTFS_ENCFN_USE_FEK;
+ }
}
static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs(
@@ -1060,7 +1069,8 @@ struct ecryptfs_flag_map_elem {
static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
{0x00000001, ECRYPTFS_ENABLE_HMAC},
{0x00000002, ECRYPTFS_ENCRYPTED},
- {0x00000004, ECRYPTFS_METADATA_IN_XATTR}
+ {0x00000004, ECRYPTFS_METADATA_IN_XATTR},
+ {0x00000008, ECRYPTFS_ENCRYPT_FILENAMES}
};
/**
@@ -1149,19 +1159,20 @@ ecryptfs_cipher_code_str_map[] = {
/**
* ecryptfs_code_for_cipher_string
- * @crypt_stat: The cryptographic context
+ * @cipher_name: The string alias for the cipher
+ * @key_bytes: Length of key in bytes; used for AES code selection
*
* Returns zero on no match, or the cipher code on match
*/
-u8 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat)
+u8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes)
{
int i;
u8 code = 0;
struct ecryptfs_cipher_code_str_map_elem *map =
ecryptfs_cipher_code_str_map;
- if (strcmp(crypt_stat->cipher, "aes") == 0) {
- switch (crypt_stat->key_size) {
+ if (strcmp(cipher_name, "aes") == 0) {
+ switch (key_bytes) {
case 16:
code = RFC2440_CIPHER_AES_128;
break;
@@ -1173,7 +1184,7 @@ u8 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat)
}
} else {
for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++)
- if (strcmp(crypt_stat->cipher, map[i].cipher_str) == 0){
+ if (strcmp(cipher_name, map[i].cipher_str) == 0) {
code = map[i].cipher_code;
break;
}
@@ -1212,6 +1223,8 @@ int ecryptfs_read_and_validate_header_region(char *data,
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
int rc;
+ if (crypt_stat->extent_size == 0)
+ crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,
ecryptfs_inode);
if (rc) {
@@ -1221,7 +1234,6 @@ int ecryptfs_read_and_validate_header_region(char *data,
}
if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
rc = -EINVAL;
- ecryptfs_printk(KERN_DEBUG, "Valid marker not found\n");
}
out:
return rc;
@@ -1628,95 +1640,95 @@ out:
}
/**
- * ecryptfs_encode_filename - converts a plaintext file name to cipher text
- * @crypt_stat: The crypt_stat struct associated with the file anem to encode
- * @name: The plaintext name
- * @length: The length of the plaintext
- * @encoded_name: The encypted name
+ * ecryptfs_encrypt_filename - encrypt filename
*
- * Encrypts and encodes a filename into something that constitutes a
- * valid filename for a filesystem, with printable characters.
+ * CBC-encrypts the filename. We do not want to encrypt the same
+ * filename with the same key and IV, which may happen with hard
+ * links, so we prepend random bits to each filename.
*
- * We assume that we have a properly initialized crypto context,
- * pointed to by crypt_stat->tfm.
- *
- * TODO: Implement filename decoding and decryption here, in place of
- * memcpy. We are keeping the framework around for now to (1)
- * facilitate testing of the components needed to implement filename
- * encryption and (2) to provide a code base from which other
- * developers in the community can easily implement this feature.
- *
- * Returns the length of encoded filename; negative if error
+ * Returns zero on success; non-zero otherwise
*/
-int
-ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
- const char *name, int length, char **encoded_name)
+static int
+ecryptfs_encrypt_filename(struct ecryptfs_filename *filename,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
{
- int error = 0;
+ int rc = 0;
- (*encoded_name) = kmalloc(length + 2, GFP_KERNEL);
- if (!(*encoded_name)) {
- error = -ENOMEM;
+ filename->encrypted_filename = NULL;
+ filename->encrypted_filename_size = 0;
+ if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCFN_USE_MOUNT_FNEK))
+ || (mount_crypt_stat && (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) {
+ size_t packet_size;
+ size_t remaining_bytes;
+
+ rc = ecryptfs_write_tag_70_packet(
+ NULL, NULL,
+ &filename->encrypted_filename_size,
+ mount_crypt_stat, NULL,
+ filename->filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to get packet "
+ "size for tag 72; rc = [%d]\n", __func__,
+ rc);
+ filename->encrypted_filename_size = 0;
+ goto out;
+ }
+ filename->encrypted_filename =
+ kmalloc(filename->encrypted_filename_size, GFP_KERNEL);
+ if (!filename->encrypted_filename) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to kmalloc [%zd] bytes\n", __func__,
+ filename->encrypted_filename_size);
+ rc = -ENOMEM;
+ goto out;
+ }
+ remaining_bytes = filename->encrypted_filename_size;
+ rc = ecryptfs_write_tag_70_packet(filename->encrypted_filename,
+ &remaining_bytes,
+ &packet_size,
+ mount_crypt_stat,
+ filename->filename,
+ filename->filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to generate "
+ "tag 70 packet; rc = [%d]\n", __func__,
+ rc);
+ kfree(filename->encrypted_filename);
+ filename->encrypted_filename = NULL;
+ filename->encrypted_filename_size = 0;
+ goto out;
+ }
+ filename->encrypted_filename_size = packet_size;
+ } else {
+ printk(KERN_ERR "%s: No support for requested filename "
+ "encryption method in this release\n", __func__);
+ rc = -ENOTSUPP;
goto out;
}
- /* TODO: Filename encryption is a scheduled feature for a
- * future version of eCryptfs. This function is here only for
- * the purpose of providing a framework for other developers
- * to easily implement filename encryption. Hint: Replace this
- * memcpy() with a call to encrypt and encode the
- * filename, the set the length accordingly. */
- memcpy((void *)(*encoded_name), (void *)name, length);
- (*encoded_name)[length] = '\0';
- error = length + 1;
out:
- return error;
+ return rc;
}
-/**
- * ecryptfs_decode_filename - converts the cipher text name to plaintext
- * @crypt_stat: The crypt_stat struct associated with the file
- * @name: The filename in cipher text
- * @length: The length of the cipher text name
- * @decrypted_name: The plaintext name
- *
- * Decodes and decrypts the filename.
- *
- * We assume that we have a properly initialized crypto context,
- * pointed to by crypt_stat->tfm.
- *
- * TODO: Implement filename decoding and decryption here, in place of
- * memcpy. We are keeping the framework around for now to (1)
- * facilitate testing of the components needed to implement filename
- * encryption and (2) to provide a code base from which other
- * developers in the community can easily implement this feature.
- *
- * Returns the length of decoded filename; negative if error
- */
-int
-ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
- const char *name, int length, char **decrypted_name)
+static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size,
+ const char *name, size_t name_size)
{
- int error = 0;
+ int rc = 0;
- (*decrypted_name) = kmalloc(length + 2, GFP_KERNEL);
- if (!(*decrypted_name)) {
- error = -ENOMEM;
+ (*copied_name) = kmalloc((name_size + 2), GFP_KERNEL);
+ if (!(*copied_name)) {
+ rc = -ENOMEM;
goto out;
}
- /* TODO: Filename encryption is a scheduled feature for a
- * future version of eCryptfs. This function is here only for
- * the purpose of providing a framework for other developers
- * to easily implement filename encryption. Hint: Replace this
- * memcpy() with a call to decode and decrypt the
- * filename, the set the length accordingly. */
- memcpy((void *)(*decrypted_name), (void *)name, length);
- (*decrypted_name)[length + 1] = '\0'; /* Only for convenience
+ memcpy((void *)(*copied_name), (void *)name, name_size);
+ (*copied_name)[(name_size)] = '\0'; /* Only for convenience
* in printing out the
* string in debug
* messages */
- error = length;
+ (*copied_name_size) = (name_size + 1);
out:
- return error;
+ return rc;
}
/**
@@ -1740,7 +1752,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,
*key_tfm = NULL;
if (*key_size > ECRYPTFS_MAX_KEY_BYTES) {
rc = -EINVAL;
- printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum "
+ printk(KERN_ERR "Requested key size is [%zd] bytes; maximum "
"allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES);
goto out;
}
@@ -1765,7 +1777,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,
get_random_bytes(dummy_key, *key_size);
rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size);
if (rc) {
- printk(KERN_ERR "Error attempting to set key of size [%Zd] for "
+ printk(KERN_ERR "Error attempting to set key of size [%zd] for "
"cipher [%s]; rc = [%d]\n", *key_size, cipher_name, rc);
rc = -EINVAL;
goto out;
@@ -1910,3 +1922,341 @@ out:
mutex_unlock(&key_tfm_list_mutex);
return rc;
}
+
+/* 64 characters forming a 6-bit target field */
+static unsigned char *portable_filename_chars = ("-.0123456789ABCD"
+ "EFGHIJKLMNOPQRST"
+ "UVWXYZabcdefghij"
+ "klmnopqrstuvwxyz");
+
+/* We could either offset on every reverse map or just pad some 0x00's
+ * at the front here */
+static const unsigned char filename_rev_map[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* 47 */
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, /* 55 */
+ 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 63 */
+ 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, /* 71 */
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, /* 79 */
+ 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, /* 87 */
+ 0x23, 0x24, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 95 */
+ 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */
+ 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */
+ 0x3D, 0x3E, 0x3F
+};
+
+/**
+ * ecryptfs_encode_for_filename
+ * @dst: Destination location for encoded filename
+ * @dst_size: Size of the encoded filename in bytes
+ * @src: Source location for the filename to encode
+ * @src_size: Size of the source in bytes
+ */
+void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size,
+ unsigned char *src, size_t src_size)
+{
+ size_t num_blocks;
+ size_t block_num = 0;
+ size_t dst_offset = 0;
+ unsigned char last_block[3];
+
+ if (src_size == 0) {
+ (*dst_size) = 0;
+ goto out;
+ }
+ num_blocks = (src_size / 3);
+ if ((src_size % 3) == 0) {
+ memcpy(last_block, (&src[src_size - 3]), 3);
+ } else {
+ num_blocks++;
+ last_block[2] = 0x00;
+ switch (src_size % 3) {
+ case 1:
+ last_block[0] = src[src_size - 1];
+ last_block[1] = 0x00;
+ break;
+ case 2:
+ last_block[0] = src[src_size - 2];
+ last_block[1] = src[src_size - 1];
+ }
+ }
+ (*dst_size) = (num_blocks * 4);
+ if (!dst)
+ goto out;
+ while (block_num < num_blocks) {
+ unsigned char *src_block;
+ unsigned char dst_block[4];
+
+ if (block_num == (num_blocks - 1))
+ src_block = last_block;
+ else
+ src_block = &src[block_num * 3];
+ dst_block[0] = ((src_block[0] >> 2) & 0x3F);
+ dst_block[1] = (((src_block[0] << 4) & 0x30)
+ | ((src_block[1] >> 4) & 0x0F));
+ dst_block[2] = (((src_block[1] << 2) & 0x3C)
+ | ((src_block[2] >> 6) & 0x03));
+ dst_block[3] = (src_block[2] & 0x3F);
+ dst[dst_offset++] = portable_filename_chars[dst_block[0]];
+ dst[dst_offset++] = portable_filename_chars[dst_block[1]];
+ dst[dst_offset++] = portable_filename_chars[dst_block[2]];
+ dst[dst_offset++] = portable_filename_chars[dst_block[3]];
+ block_num++;
+ }
+out:
+ return;
+}
+
+/**
+ * ecryptfs_decode_from_filename
+ * @dst: If NULL, this function only sets @dst_size and returns. If
+ * non-NULL, this function decodes the encoded octets in @src
+ * into the memory that @dst points to.
+ * @dst_size: Set to the size of the decoded string.
+ * @src: The encoded set of octets to decode.
+ * @src_size: The size of the encoded set of octets to decode.
+ */
+static void
+ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
+ const unsigned char *src, size_t src_size)
+{
+ u8 current_bit_offset = 0;
+ size_t src_byte_offset = 0;
+ size_t dst_byte_offset = 0;
+
+ if (dst == NULL) {
+ /* Not exact; conservatively long. Every block of 4
+ * encoded characters decodes into a block of 3
+ * decoded characters. This segment of code provides
+ * the caller with the maximum amount of allocated
+ * space that @dst will need to point to in a
+ * subsequent call. */
+ (*dst_size) = (((src_size + 1) * 3) / 4);
+ goto out;
+ }
+ while (src_byte_offset < src_size) {
+ unsigned char src_byte =
+ filename_rev_map[(int)src[src_byte_offset]];
+
+ switch (current_bit_offset) {
+ case 0:
+ dst[dst_byte_offset] = (src_byte << 2);
+ current_bit_offset = 6;
+ break;
+ case 6:
+ dst[dst_byte_offset++] |= (src_byte >> 4);
+ dst[dst_byte_offset] = ((src_byte & 0xF)
+ << 4);
+ current_bit_offset = 4;
+ break;
+ case 4:
+ dst[dst_byte_offset++] |= (src_byte >> 2);
+ dst[dst_byte_offset] = (src_byte << 6);
+ current_bit_offset = 2;
+ break;
+ case 2:
+ dst[dst_byte_offset++] |= (src_byte);
+ dst[dst_byte_offset] = 0;
+ current_bit_offset = 0;
+ break;
+ }
+ src_byte_offset++;
+ }
+ (*dst_size) = dst_byte_offset;
+out:
+ return;
+}
+
+/**
+ * ecryptfs_encrypt_and_encode_filename - converts a plaintext file name to cipher text
+ * @crypt_stat: The crypt_stat struct associated with the file anem to encode
+ * @name: The plaintext name
+ * @length: The length of the plaintext
+ * @encoded_name: The encypted name
+ *
+ * Encrypts and encodes a filename into something that constitutes a
+ * valid filename for a filesystem, with printable characters.
+ *
+ * We assume that we have a properly initialized crypto context,
+ * pointed to by crypt_stat->tfm.
+ *
+ * Returns zero on success; non-zero on otherwise
+ */
+int ecryptfs_encrypt_and_encode_filename(
+ char **encoded_name,
+ size_t *encoded_name_size,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ const char *name, size_t name_size)
+{
+ size_t encoded_name_no_prefix_size;
+ int rc = 0;
+
+ (*encoded_name) = NULL;
+ (*encoded_name_size) = 0;
+ if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES))
+ || (mount_crypt_stat && (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) {
+ struct ecryptfs_filename *filename;
+
+ filename = kzalloc(sizeof(*filename), GFP_KERNEL);
+ if (!filename) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to kzalloc [%zd] bytes\n", __func__,
+ sizeof(*filename));
+ rc = -ENOMEM;
+ goto out;
+ }
+ filename->filename = (char *)name;
+ filename->filename_size = name_size;
+ rc = ecryptfs_encrypt_filename(filename, crypt_stat,
+ mount_crypt_stat);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to encrypt "
+ "filename; rc = [%d]\n", __func__, rc);
+ kfree(filename);
+ goto out;
+ }
+ ecryptfs_encode_for_filename(
+ NULL, &encoded_name_no_prefix_size,
+ filename->encrypted_filename,
+ filename->encrypted_filename_size);
+ if ((crypt_stat && (crypt_stat->flags
+ & ECRYPTFS_ENCFN_USE_MOUNT_FNEK))
+ || (mount_crypt_stat
+ && (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)))
+ (*encoded_name_size) =
+ (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE
+ + encoded_name_no_prefix_size);
+ else
+ (*encoded_name_size) =
+ (ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE
+ + encoded_name_no_prefix_size);
+ (*encoded_name) = kmalloc((*encoded_name_size) + 1, GFP_KERNEL);
+ if (!(*encoded_name)) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to kzalloc [%zd] bytes\n", __func__,
+ (*encoded_name_size));
+ rc = -ENOMEM;
+ kfree(filename->encrypted_filename);
+ kfree(filename);
+ goto out;
+ }
+ if ((crypt_stat && (crypt_stat->flags
+ & ECRYPTFS_ENCFN_USE_MOUNT_FNEK))
+ || (mount_crypt_stat
+ && (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) {
+ memcpy((*encoded_name),
+ ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX,
+ ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE);
+ ecryptfs_encode_for_filename(
+ ((*encoded_name)
+ + ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE),
+ &encoded_name_no_prefix_size,
+ filename->encrypted_filename,
+ filename->encrypted_filename_size);
+ (*encoded_name_size) =
+ (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE
+ + encoded_name_no_prefix_size);
+ (*encoded_name)[(*encoded_name_size)] = '\0';
+ (*encoded_name_size)++;
+ } else {
+ rc = -ENOTSUPP;
+ }
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to encode "
+ "encrypted filename; rc = [%d]\n", __func__,
+ rc);
+ kfree((*encoded_name));
+ (*encoded_name) = NULL;
+ (*encoded_name_size) = 0;
+ }
+ kfree(filename->encrypted_filename);
+ kfree(filename);
+ } else {
+ rc = ecryptfs_copy_filename(encoded_name,
+ encoded_name_size,
+ name, name_size);
+ }
+out:
+ return rc;
+}
+
+/**
+ * ecryptfs_decode_and_decrypt_filename - converts the encoded cipher text name to decoded plaintext
+ * @plaintext_name: The plaintext name
+ * @plaintext_name_size: The plaintext name size
+ * @ecryptfs_dir_dentry: eCryptfs directory dentry
+ * @name: The filename in cipher text
+ * @name_size: The cipher text name size
+ *
+ * Decrypts and decodes the filename.
+ *
+ * Returns zero on error; non-zero otherwise
+ */
+int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,
+ size_t *plaintext_name_size,
+ struct dentry *ecryptfs_dir_dentry,
+ const char *name, size_t name_size)
+{
+ char *decoded_name;
+ size_t decoded_name_size;
+ size_t packet_size;
+ int rc = 0;
+
+ if ((name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE)
+ && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX,
+ ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) {
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+ &ecryptfs_superblock_to_private(
+ ecryptfs_dir_dentry->d_sb)->mount_crypt_stat;
+ const char *orig_name = name;
+ size_t orig_name_size = name_size;
+
+ name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
+ name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
+ ecryptfs_decode_from_filename(NULL, &decoded_name_size,
+ name, name_size);
+ decoded_name = kmalloc(decoded_name_size, GFP_KERNEL);
+ if (!decoded_name) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to kmalloc [%zd] bytes\n", __func__,
+ decoded_name_size);
+ rc = -ENOMEM;
+ goto out;
+ }
+ ecryptfs_decode_from_filename(decoded_name, &decoded_name_size,
+ name, name_size);
+ rc = ecryptfs_parse_tag_70_packet(plaintext_name,
+ plaintext_name_size,
+ &packet_size,
+ mount_crypt_stat,
+ decoded_name,
+ decoded_name_size);
+ if (rc) {
+ printk(KERN_INFO "%s: Could not parse tag 70 packet "
+ "from filename; copying through filename "
+ "as-is\n", __func__);
+ rc = ecryptfs_copy_filename(plaintext_name,
+ plaintext_name_size,
+ orig_name, orig_name_size);
+ goto out_free;
+ }
+ } else {
+ rc = ecryptfs_copy_filename(plaintext_name,
+ plaintext_name_size,
+ name, name_size);
+ goto out;
+ }
+out_free:
+ kfree(decoded_name);
+out:
+ return rc;
+}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 3504cf9df35..c11fc95714a 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -51,12 +51,16 @@
#define ECRYPTFS_VERSIONING_XATTR 0x00000010
#define ECRYPTFS_VERSIONING_MULTKEY 0x00000020
#define ECRYPTFS_VERSIONING_DEVMISC 0x00000040
+#define ECRYPTFS_VERSIONING_HMAC 0x00000080
+#define ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION 0x00000100
+#define ECRYPTFS_VERSIONING_GCM 0x00000200
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
| ECRYPTFS_VERSIONING_PUBKEY \
| ECRYPTFS_VERSIONING_XATTR \
| ECRYPTFS_VERSIONING_MULTKEY \
- | ECRYPTFS_VERSIONING_DEVMISC)
+ | ECRYPTFS_VERSIONING_DEVMISC \
+ | ECRYPTFS_VERSIONING_FILENAME_ENCRYPTION)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
#define ECRYPTFS_SALT_SIZE 8
@@ -199,6 +203,7 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_DEFAULT_CIPHER "aes"
#define ECRYPTFS_DEFAULT_KEY_BYTES 16
#define ECRYPTFS_DEFAULT_HASH "md5"
+#define ECRYPTFS_TAG_70_DIGEST ECRYPTFS_DEFAULT_HASH
#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01
#define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
#define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
@@ -206,30 +211,64 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41
#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42
#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43
+#define ECRYPTFS_TAG_70_PACKET_TYPE 0x46 /* FNEK-encrypted filename
+ * as dentry name */
+#define ECRYPTFS_TAG_71_PACKET_TYPE 0x47 /* FNEK-encrypted filename in
+ * metadata */
+#define ECRYPTFS_TAG_72_PACKET_TYPE 0x48 /* FEK-encrypted filename as
+ * dentry name */
+#define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as
+ * metadata */
+/* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >=
+ * ECRYPTFS_MAX_IV_BYTES */
+#define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16
+#define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */
#define MD5_DIGEST_SIZE 16
+#define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE
+#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED."
+#define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23
+#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
+#define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 24
+#define ECRYPTFS_ENCRYPTED_DENTRY_NAME_LEN (18 + 1 + 4 + 1 + 32)
struct ecryptfs_key_sig {
struct list_head crypt_stat_list;
char keysig[ECRYPTFS_SIG_SIZE_HEX];
};
+struct ecryptfs_filename {
+ struct list_head crypt_stat_list;
+#define ECRYPTFS_FILENAME_CONTAINS_DECRYPTED 0x00000001
+ u32 flags;
+ u32 seq_no;
+ char *filename;
+ char *encrypted_filename;
+ size_t filename_size;
+ size_t encrypted_filename_size;
+ char fnek_sig[ECRYPTFS_SIG_SIZE_HEX];
+ char dentry_name[ECRYPTFS_ENCRYPTED_DENTRY_NAME_LEN + 1];
+};
+
/**
* This is the primary struct associated with each encrypted file.
*
* TODO: cache align/pack?
*/
struct ecryptfs_crypt_stat {
-#define ECRYPTFS_STRUCT_INITIALIZED 0x00000001
-#define ECRYPTFS_POLICY_APPLIED 0x00000002
-#define ECRYPTFS_NEW_FILE 0x00000004
-#define ECRYPTFS_ENCRYPTED 0x00000008
-#define ECRYPTFS_SECURITY_WARNING 0x00000010
-#define ECRYPTFS_ENABLE_HMAC 0x00000020
-#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040
-#define ECRYPTFS_KEY_VALID 0x00000080
-#define ECRYPTFS_METADATA_IN_XATTR 0x00000100
-#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200
-#define ECRYPTFS_KEY_SET 0x00000400
+#define ECRYPTFS_STRUCT_INITIALIZED 0x00000001
+#define ECRYPTFS_POLICY_APPLIED 0x00000002
+#define ECRYPTFS_NEW_FILE 0x00000004
+#define ECRYPTFS_ENCRYPTED 0x00000008
+#define ECRYPTFS_SECURITY_WARNING 0x00000010
+#define ECRYPTFS_ENABLE_HMAC 0x00000020
+#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040
+#define ECRYPTFS_KEY_VALID 0x00000080
+#define ECRYPTFS_METADATA_IN_XATTR 0x00000100
+#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200
+#define ECRYPTFS_KEY_SET 0x00000400
+#define ECRYPTFS_ENCRYPT_FILENAMES 0x00000800
+#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00001000
+#define ECRYPTFS_ENCFN_USE_FEK 0x00002000
u32 flags;
unsigned int file_version;
size_t iv_bytes;
@@ -332,13 +371,20 @@ struct ecryptfs_mount_crypt_stat {
#define ECRYPTFS_XATTR_METADATA_ENABLED 0x00000002
#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED 0x00000004
#define ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED 0x00000008
+#define ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES 0x00000010
+#define ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK 0x00000020
+#define ECRYPTFS_GLOBAL_ENCFN_USE_FEK 0x00000040
u32 flags;
struct list_head global_auth_tok_list;
struct mutex global_auth_tok_list_mutex;
size_t num_global_auth_toks;
size_t global_default_cipher_key_size;
+ size_t global_default_fn_cipher_key_bytes;
unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE
+ 1];
+ unsigned char global_default_fn_cipher_name[
+ ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
+ char global_default_fnek_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
};
/* superblock private data. */
@@ -571,13 +617,22 @@ struct ecryptfs_open_req {
int ecryptfs_interpose(struct dentry *hidden_dentry,
struct dentry *this_dentry, struct super_block *sb,
u32 flags);
+int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
+ struct dentry *lower_dentry,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct inode *ecryptfs_dir_inode,
+ struct nameidata *ecryptfs_nd);
+int ecryptfs_decode_and_decrypt_filename(char **decrypted_name,
+ size_t *decrypted_name_size,
+ struct dentry *ecryptfs_dentry,
+ const char *name, size_t name_size);
int ecryptfs_fill_zeros(struct file *file, loff_t new_length);
-int ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
- const char *name, int length,
- char **decrypted_name);
-int ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
- const char *name, int length,
- char **encoded_name);
+int ecryptfs_encrypt_and_encode_filename(
+ char **encoded_name,
+ size_t *encoded_name_size,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ const char *name, size_t name_size);
struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry);
void ecryptfs_dump_hex(char *data, int bytes);
int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
@@ -599,7 +654,7 @@ int ecryptfs_read_and_validate_header_region(char *data,
struct inode *ecryptfs_inode);
int ecryptfs_read_and_validate_xattr_region(char *page_virt,
struct dentry *ecryptfs_dentry);
-u8 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
+u8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes);
int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code);
void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_generate_key_packet_set(char *dest_base,
@@ -691,7 +746,20 @@ int ecryptfs_init_kthread(void);
void ecryptfs_destroy_kthread(void);
int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
- struct vfsmount *lower_mnt);
+ struct vfsmount *lower_mnt,
+ const struct cred *cred);
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
+int
+ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
+ size_t *packet_size,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *filename, size_t filename_size);
+int
+ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
+ size_t *packet_size,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *data, size_t max_packet_size);
+int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
+ loff_t offset);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index eb3dc4c7ac0..9e944057001 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -77,27 +77,27 @@ struct ecryptfs_getdents_callback {
/* Inspired by generic filldir in fs/readdir.c */
static int
-ecryptfs_filldir(void *dirent, const char *name, int namelen, loff_t offset,
- u64 ino, unsigned int d_type)
+ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
{
- struct ecryptfs_crypt_stat *crypt_stat;
struct ecryptfs_getdents_callback *buf =
(struct ecryptfs_getdents_callback *)dirent;
+ size_t name_size;
+ char *name;
int rc;
- int decoded_length;
- char *decoded_name;
- crypt_stat = ecryptfs_dentry_to_private(buf->dentry)->crypt_stat;
buf->filldir_called++;
- decoded_length = ecryptfs_decode_filename(crypt_stat, name, namelen,
- &decoded_name);
- if (decoded_length < 0) {
- rc = decoded_length;
+ rc = ecryptfs_decode_and_decrypt_filename(&name, &name_size,
+ buf->dentry, lower_name,
+ lower_namelen);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to decode and decrypt "
+ "filename [%s]; rc = [%d]\n", __func__, lower_name,
+ rc);
goto out;
}
- rc = buf->filldir(buf->dirent, decoded_name, decoded_length, offset,
- ino, d_type);
- kfree(decoded_name);
+ rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type);
+ kfree(name);
if (rc >= 0)
buf->entries_written++;
out:
@@ -106,8 +106,8 @@ out:
/**
* ecryptfs_readdir
- * @file: The ecryptfs file struct
- * @dirent: Directory entry
+ * @file: The eCryptfs directory file
+ * @dirent: Directory entry handle
* @filldir: The filldir callback function
*/
static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
@@ -275,18 +275,9 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
static int
ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
- struct file *lower_file = ecryptfs_file_to_lower(file);
- struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
- struct inode *lower_inode = lower_dentry->d_inode;
- int rc = -EINVAL;
-
- if (lower_inode->i_fop->fsync) {
- mutex_lock(&lower_inode->i_mutex);
- rc = lower_inode->i_fop->fsync(lower_file, lower_dentry,
- datasync);
- mutex_unlock(&lower_inode->i_mutex);
- }
- return rc;
+ return vfs_fsync(ecryptfs_file_to_lower(file),
+ ecryptfs_dentry_to_lower(dentry),
+ datasync);
}
static int ecryptfs_fasync(int fd, struct file *file, int flag)
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 89209f00f9c..5697899a168 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -52,8 +52,7 @@ static void unlock_dir(struct dentry *dir)
/**
* ecryptfs_create_underlying_file
* @lower_dir_inode: inode of the parent in the lower fs of the new file
- * @lower_dentry: New file's dentry in the lower fs
- * @ecryptfs_dentry: New file's dentry in ecryptfs
+ * @dentry: New file's dentry
* @mode: The mode of the new file
* @nd: nameidata of ecryptfs' parent's dentry & vfsmount
*
@@ -228,8 +227,7 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
{
int rc;
- /* ecryptfs_do_create() calls ecryptfs_interpose(), which opens
- * the crypt_stat->lower_file (persistent file) */
+ /* ecryptfs_do_create() calls ecryptfs_interpose() */
rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode, nd);
if (unlikely(rc)) {
ecryptfs_printk(KERN_WARNING, "Failed to create file in"
@@ -244,141 +242,91 @@ out:
}
/**
- * ecryptfs_lookup
- * @dir: inode
- * @dentry: The dentry
- * @nd: nameidata, may be NULL
- *
- * Find a file on disk. If the file does not exist, then we'll add it to the
- * dentry cache and continue on to read it from the disk.
+ * ecryptfs_lookup_and_interpose_lower - Perform a lookup
*/
-static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
- struct nameidata *nd)
+int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
+ struct dentry *lower_dentry,
+ struct ecryptfs_crypt_stat *crypt_stat,
+ struct inode *ecryptfs_dir_inode,
+ struct nameidata *ecryptfs_nd)
{
- int rc = 0;
struct dentry *lower_dir_dentry;
- struct dentry *lower_dentry;
struct vfsmount *lower_mnt;
- char *encoded_name;
- int encoded_namelen;
- struct ecryptfs_crypt_stat *crypt_stat = NULL;
+ struct inode *lower_inode;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
char *page_virt = NULL;
- struct inode *lower_inode;
u64 file_size;
+ int rc = 0;
- lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent);
- dentry->d_op = &ecryptfs_dops;
- if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, "."))
- || (dentry->d_name.len == 2
- && !strcmp(dentry->d_name.name, ".."))) {
- d_drop(dentry);
- goto out;
- }
- encoded_namelen = ecryptfs_encode_filename(crypt_stat,
- dentry->d_name.name,
- dentry->d_name.len,
- &encoded_name);
- if (encoded_namelen < 0) {
- rc = encoded_namelen;
- d_drop(dentry);
- goto out;
- }
- ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen "
- "= [%d]\n", encoded_name, encoded_namelen);
- lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry,
- encoded_namelen - 1);
- kfree(encoded_name);
- if (IS_ERR(lower_dentry)) {
- ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n");
- rc = PTR_ERR(lower_dentry);
- d_drop(dentry);
- goto out;
- }
- lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
- ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->"
- "d_name.name = [%s]\n", lower_dentry,
- lower_dentry->d_name.name);
+ lower_dir_dentry = lower_dentry->d_parent;
+ lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
+ ecryptfs_dentry->d_parent));
lower_inode = lower_dentry->d_inode;
- fsstack_copy_attr_atime(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_atime(ecryptfs_dir_inode, lower_dir_dentry->d_inode);
BUG_ON(!atomic_read(&lower_dentry->d_count));
- ecryptfs_set_dentry_private(dentry,
+ ecryptfs_set_dentry_private(ecryptfs_dentry,
kmem_cache_alloc(ecryptfs_dentry_info_cache,
GFP_KERNEL));
- if (!ecryptfs_dentry_to_private(dentry)) {
+ if (!ecryptfs_dentry_to_private(ecryptfs_dentry)) {
rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Out of memory whilst attempting "
- "to allocate ecryptfs_dentry_info struct\n");
+ printk(KERN_ERR "%s: Out of memory whilst attempting "
+ "to allocate ecryptfs_dentry_info struct\n",
+ __func__);
goto out_dput;
}
- ecryptfs_set_dentry_lower(dentry, lower_dentry);
- ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt);
+ ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry);
+ ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt);
if (!lower_dentry->d_inode) {
/* We want to add because we couldn't find in lower */
- d_add(dentry, NULL);
+ d_add(ecryptfs_dentry, NULL);
goto out;
}
- rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb,
- ECRYPTFS_INTERPOSE_FLAG_D_ADD);
+ rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
+ ecryptfs_dir_inode->i_sb, 1);
if (rc) {
- ecryptfs_printk(KERN_ERR, "Error interposing\n");
+ printk(KERN_ERR "%s: Error interposing; rc = [%d]\n",
+ __func__, rc);
goto out;
}
- if (S_ISDIR(lower_inode->i_mode)) {
- ecryptfs_printk(KERN_DEBUG, "Is a directory; returning\n");
+ if (S_ISDIR(lower_inode->i_mode))
goto out;
- }
- if (S_ISLNK(lower_inode->i_mode)) {
- ecryptfs_printk(KERN_DEBUG, "Is a symlink; returning\n");
+ if (S_ISLNK(lower_inode->i_mode))
goto out;
- }
- if (special_file(lower_inode->i_mode)) {
- ecryptfs_printk(KERN_DEBUG, "Is a special file; returning\n");
+ if (special_file(lower_inode->i_mode))
goto out;
- }
- if (!nd) {
- ecryptfs_printk(KERN_DEBUG, "We have a NULL nd, just leave"
- "as we *think* we are about to unlink\n");
+ if (!ecryptfs_nd)
goto out;
- }
/* Released in this function */
- page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2,
- GFP_USER);
+ page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2, GFP_USER);
if (!page_virt) {
+ printk(KERN_ERR "%s: Cannot kmem_cache_zalloc() a page\n",
+ __func__);
rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR,
- "Cannot ecryptfs_kmalloc a page\n");
goto out;
}
- crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
- if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
- ecryptfs_set_default_sizes(crypt_stat);
- if (!ecryptfs_inode_to_private(dentry->d_inode)->lower_file) {
- rc = ecryptfs_init_persistent_file(dentry);
+ if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) {
+ rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
if (rc) {
printk(KERN_ERR "%s: Error attempting to initialize "
"the persistent file for the dentry with name "
"[%s]; rc = [%d]\n", __func__,
- dentry->d_name.name, rc);
- goto out;
+ ecryptfs_dentry->d_name.name, rc);
+ goto out_free_kmem;
}
}
rc = ecryptfs_read_and_validate_header_region(page_virt,
- dentry->d_inode);
+ ecryptfs_dentry->d_inode);
if (rc) {
- rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry);
+ rc = ecryptfs_read_and_validate_xattr_region(page_virt,
+ ecryptfs_dentry);
if (rc) {
- printk(KERN_DEBUG "Valid metadata not found in header "
- "region or xattr region; treating file as "
- "unencrypted\n");
rc = 0;
- kmem_cache_free(ecryptfs_header_cache_2, page_virt);
- goto out;
+ goto out_free_kmem;
}
crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
}
mount_crypt_stat = &ecryptfs_superblock_to_private(
- dentry->d_sb)->mount_crypt_stat;
+ ecryptfs_dentry->d_sb)->mount_crypt_stat;
if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
file_size = (crypt_stat->num_header_bytes_at_front
@@ -388,14 +336,103 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
} else {
file_size = get_unaligned_be64(page_virt);
}
- i_size_write(dentry->d_inode, (loff_t)file_size);
+ i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size);
+out_free_kmem:
kmem_cache_free(ecryptfs_header_cache_2, page_virt);
goto out;
-
out_dput:
dput(lower_dentry);
- d_drop(dentry);
+ d_drop(ecryptfs_dentry);
out:
+ return rc;
+}
+
+/**
+ * ecryptfs_lookup
+ * @ecryptfs_dir_inode: The eCryptfs directory inode
+ * @ecryptfs_dentry: The eCryptfs dentry that we are looking up
+ * @ecryptfs_nd: nameidata; may be NULL
+ *
+ * Find a file on disk. If the file does not exist, then we'll add it to the
+ * dentry cache and continue on to read it from the disk.
+ */
+static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
+ struct dentry *ecryptfs_dentry,
+ struct nameidata *ecryptfs_nd)
+{
+ char *encrypted_and_encoded_name = NULL;
+ size_t encrypted_and_encoded_name_size;
+ struct ecryptfs_crypt_stat *crypt_stat = NULL;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
+ struct ecryptfs_inode_info *inode_info;
+ struct dentry *lower_dir_dentry, *lower_dentry;
+ int rc = 0;
+
+ ecryptfs_dentry->d_op = &ecryptfs_dops;
+ if ((ecryptfs_dentry->d_name.len == 1
+ && !strcmp(ecryptfs_dentry->d_name.name, "."))
+ || (ecryptfs_dentry->d_name.len == 2
+ && !strcmp(ecryptfs_dentry->d_name.name, ".."))) {
+ goto out_d_drop;
+ }
+ lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
+ lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name,
+ lower_dir_dentry,
+ ecryptfs_dentry->d_name.len);
+ if (IS_ERR(lower_dentry)) {
+ rc = PTR_ERR(lower_dentry);
+ printk(KERN_ERR "%s: lookup_one_len() returned [%d] on "
+ "lower_dentry = [%s]\n", __func__, rc,
+ ecryptfs_dentry->d_name.name);
+ goto out_d_drop;
+ }
+ if (lower_dentry->d_inode)
+ goto lookup_and_interpose;
+ inode_info = ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
+ if (inode_info) {
+ crypt_stat = &inode_info->crypt_stat;
+ /* TODO: lock for crypt_stat comparison */
+ if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
+ ecryptfs_set_default_sizes(crypt_stat);
+ }
+ if (crypt_stat)
+ mount_crypt_stat = crypt_stat->mount_crypt_stat;
+ else
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ ecryptfs_dentry->d_sb)->mount_crypt_stat;
+ if (!(crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES))
+ && !(mount_crypt_stat && (mount_crypt_stat->flags
+ & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
+ goto lookup_and_interpose;
+ dput(lower_dentry);
+ rc = ecryptfs_encrypt_and_encode_filename(
+ &encrypted_and_encoded_name, &encrypted_and_encoded_name_size,
+ crypt_stat, mount_crypt_stat, ecryptfs_dentry->d_name.name,
+ ecryptfs_dentry->d_name.len);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to encrypt and encode "
+ "filename; rc = [%d]\n", __func__, rc);
+ goto out_d_drop;
+ }
+ lower_dentry = lookup_one_len(encrypted_and_encoded_name,
+ lower_dir_dentry,
+ encrypted_and_encoded_name_size - 1);
+ if (IS_ERR(lower_dentry)) {
+ rc = PTR_ERR(lower_dentry);
+ printk(KERN_ERR "%s: lookup_one_len() returned [%d] on "
+ "lower_dentry = [%s]\n", __func__, rc,
+ encrypted_and_encoded_name);
+ goto out_d_drop;
+ }
+lookup_and_interpose:
+ rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry,
+ crypt_stat, ecryptfs_dir_inode,
+ ecryptfs_nd);
+ goto out;
+out_d_drop:
+ d_drop(ecryptfs_dentry);
+out:
+ kfree(encrypted_and_encoded_name);
return ERR_PTR(rc);
}
@@ -466,19 +503,21 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
struct dentry *lower_dentry;
struct dentry *lower_dir_dentry;
char *encoded_symname;
- int encoded_symlen;
- struct ecryptfs_crypt_stat *crypt_stat = NULL;
+ size_t encoded_symlen;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
dget(lower_dentry);
lower_dir_dentry = lock_parent(lower_dentry);
- encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
- strlen(symname),
- &encoded_symname);
- if (encoded_symlen < 0) {
- rc = encoded_symlen;
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ dir->i_sb)->mount_crypt_stat;
+ rc = ecryptfs_encrypt_and_encode_filename(&encoded_symname,
+ &encoded_symlen,
+ NULL,
+ mount_crypt_stat, symname,
+ strlen(symname));
+ if (rc)
goto out_lock;
- }
rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
encoded_symname);
kfree(encoded_symname);
@@ -602,53 +641,54 @@ out_lock:
}
static int
-ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
+ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{
- int rc;
- struct dentry *lower_dentry;
- char *decoded_name;
char *lower_buf;
- mm_segment_t old_fs;
+ struct dentry *lower_dentry;
struct ecryptfs_crypt_stat *crypt_stat;
+ char *plaintext_name;
+ size_t plaintext_name_size;
+ mm_segment_t old_fs;
+ int rc;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- if (!lower_dentry->d_inode->i_op ||
- !lower_dentry->d_inode->i_op->readlink) {
+ if (!lower_dentry->d_inode->i_op->readlink) {
rc = -EINVAL;
goto out;
}
+ crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
/* Released in this function */
lower_buf = kmalloc(bufsiz, GFP_KERNEL);
if (lower_buf == NULL) {
- ecryptfs_printk(KERN_ERR, "Out of memory\n");
+ printk(KERN_ERR "%s: Out of memory whilst attempting to "
+ "kmalloc [%d] bytes\n", __func__, bufsiz);
rc = -ENOMEM;
goto out;
}
old_fs = get_fs();
set_fs(get_ds());
- ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ "
- "lower_dentry->d_name.name = [%s]\n",
- lower_dentry->d_name.name);
rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
(char __user *)lower_buf,
bufsiz);
set_fs(old_fs);
if (rc >= 0) {
- crypt_stat = NULL;
- rc = ecryptfs_decode_filename(crypt_stat, lower_buf, rc,
- &decoded_name);
- if (rc == -ENOMEM)
+ rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name,
+ &plaintext_name_size,
+ dentry, lower_buf,
+ rc);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to decode and "
+ "decrypt filename; rc = [%d]\n", __func__,
+ rc);
goto out_free_lower_buf;
- if (rc > 0) {
- ecryptfs_printk(KERN_DEBUG, "Copying [%d] bytes "
- "to userspace: [%*s]\n", rc,
- decoded_name);
- if (copy_to_user(buf, decoded_name, rc))
- rc = -EFAULT;
}
- kfree(decoded_name);
- fsstack_copy_attr_atime(dentry->d_inode,
- lower_dentry->d_inode);
+ rc = copy_to_user(buf, plaintext_name, plaintext_name_size);
+ if (rc)
+ rc = -EFAULT;
+ else
+ rc = plaintext_name_size;
+ kfree(plaintext_name);
+ fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
}
out_free_lower_buf:
kfree(lower_buf);
@@ -670,13 +710,12 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
}
old_fs = get_fs();
set_fs(get_ds());
- ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ "
- "dentry->d_name.name = [%s]\n", dentry->d_name.name);
rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
- buf[rc] = '\0';
set_fs(old_fs);
if (rc < 0)
goto out_free;
+ else
+ buf[rc] = '\0';
rc = 0;
nd_set_link(nd, buf);
goto out;
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index e22bc396134..ff539420cc6 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -358,7 +358,7 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
/* verify that everything through the encrypted FEK size is present */
if (message_len < 4) {
rc = -EIO;
- printk(KERN_ERR "%s: message_len is [%Zd]; minimum acceptable "
+ printk(KERN_ERR "%s: message_len is [%zd]; minimum acceptable "
"message length is [%d]\n", __func__, message_len, 4);
goto out;
}
@@ -385,13 +385,13 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
i += data_len;
if (message_len < (i + key_rec->enc_key_size)) {
rc = -EIO;
- printk(KERN_ERR "%s: message_len [%Zd]; max len is [%Zd]\n",
+ printk(KERN_ERR "%s: message_len [%zd]; max len is [%zd]\n",
__func__, message_len, (i + key_rec->enc_key_size));
goto out;
}
if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
rc = -EIO;
- printk(KERN_ERR "%s: Encrypted key_size [%Zd] larger than "
+ printk(KERN_ERR "%s: Encrypted key_size [%zd] larger than "
"the maximum key size [%d]\n", __func__,
key_rec->enc_key_size,
ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
@@ -403,6 +403,580 @@ out:
}
static int
+ecryptfs_find_global_auth_tok_for_sig(
+ struct ecryptfs_global_auth_tok **global_auth_tok,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
+{
+ struct ecryptfs_global_auth_tok *walker;
+ int rc = 0;
+
+ (*global_auth_tok) = NULL;
+ mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ list_for_each_entry(walker,
+ &mount_crypt_stat->global_auth_tok_list,
+ mount_crypt_stat_list) {
+ if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
+ (*global_auth_tok) = walker;
+ goto out;
+ }
+ }
+ rc = -EINVAL;
+out:
+ mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
+ return rc;
+}
+
+/**
+ * ecryptfs_find_auth_tok_for_sig
+ * @auth_tok: Set to the matching auth_tok; NULL if not found
+ * @crypt_stat: inode crypt_stat crypto context
+ * @sig: Sig of auth_tok to find
+ *
+ * For now, this function simply looks at the registered auth_tok's
+ * linked off the mount_crypt_stat, so all the auth_toks that can be
+ * used must be registered at mount time. This function could
+ * potentially try a lot harder to find auth_tok's (e.g., by calling
+ * out to ecryptfsd to dynamically retrieve an auth_tok object) so
+ * that static registration of auth_tok's will no longer be necessary.
+ *
+ * Returns zero on no error; non-zero on error
+ */
+static int
+ecryptfs_find_auth_tok_for_sig(
+ struct ecryptfs_auth_tok **auth_tok,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *sig)
+{
+ struct ecryptfs_global_auth_tok *global_auth_tok;
+ int rc = 0;
+
+ (*auth_tok) = NULL;
+ if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
+ mount_crypt_stat, sig)) {
+ struct key *auth_tok_key;
+
+ rc = ecryptfs_keyring_auth_tok_for_sig(&auth_tok_key, auth_tok,
+ sig);
+ } else
+ (*auth_tok) = global_auth_tok->global_auth_tok;
+ return rc;
+}
+
+/**
+ * write_tag_70_packet can gobble a lot of stack space. We stuff most
+ * of the function's parameters in a kmalloc'd struct to help reduce
+ * eCryptfs' overall stack usage.
+ */
+struct ecryptfs_write_tag_70_packet_silly_stack {
+ u8 cipher_code;
+ size_t max_packet_size;
+ size_t packet_size_len;
+ size_t block_aligned_filename_size;
+ size_t block_size;
+ size_t i;
+ size_t j;
+ size_t num_rand_bytes;
+ struct mutex *tfm_mutex;
+ char *block_aligned_filename;
+ struct ecryptfs_auth_tok *auth_tok;
+ struct scatterlist src_sg;
+ struct scatterlist dst_sg;
+ struct blkcipher_desc desc;
+ char iv[ECRYPTFS_MAX_IV_BYTES];
+ char hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
+ char tmp_hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
+ struct hash_desc hash_desc;
+ struct scatterlist hash_sg;
+};
+
+/**
+ * write_tag_70_packet - Write encrypted filename (EFN) packet against FNEK
+ * @filename: NULL-terminated filename string
+ *
+ * This is the simplest mechanism for achieving filename encryption in
+ * eCryptfs. It encrypts the given filename with the mount-wide
+ * filename encryption key (FNEK) and stores it in a packet to @dest,
+ * which the callee will encode and write directly into the dentry
+ * name.
+ */
+int
+ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
+ size_t *packet_size,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *filename, size_t filename_size)
+{
+ struct ecryptfs_write_tag_70_packet_silly_stack *s;
+ int rc = 0;
+
+ s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (!s) {
+ printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc "
+ "[%zd] bytes of kernel memory\n", __func__, sizeof(*s));
+ goto out;
+ }
+ s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ (*packet_size) = 0;
+ rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(
+ &s->desc.tfm,
+ &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name);
+ if (unlikely(rc)) {
+ printk(KERN_ERR "Internal error whilst attempting to get "
+ "tfm and mutex for cipher name [%s]; rc = [%d]\n",
+ mount_crypt_stat->global_default_fn_cipher_name, rc);
+ goto out;
+ }
+ mutex_lock(s->tfm_mutex);
+ s->block_size = crypto_blkcipher_blocksize(s->desc.tfm);
+ /* Plus one for the \0 separator between the random prefix
+ * and the plaintext filename */
+ s->num_rand_bytes = (ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES + 1);
+ s->block_aligned_filename_size = (s->num_rand_bytes + filename_size);
+ if ((s->block_aligned_filename_size % s->block_size) != 0) {
+ s->num_rand_bytes += (s->block_size
+ - (s->block_aligned_filename_size
+ % s->block_size));
+ s->block_aligned_filename_size = (s->num_rand_bytes
+ + filename_size);
+ }
+ /* Octet 0: Tag 70 identifier
+ * Octets 1-N1: Tag 70 packet size (includes cipher identifier
+ * and block-aligned encrypted filename size)
+ * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE)
+ * Octet N2-N3: Cipher identifier (1 octet)
+ * Octets N3-N4: Block-aligned encrypted filename
+ * - Consists of a minimum number of random characters, a \0
+ * separator, and then the filename */
+ s->max_packet_size = (1 /* Tag 70 identifier */
+ + 3 /* Max Tag 70 packet size */
+ + ECRYPTFS_SIG_SIZE /* FNEK sig */
+ + 1 /* Cipher identifier */
+ + s->block_aligned_filename_size);
+ if (dest == NULL) {
+ (*packet_size) = s->max_packet_size;
+ goto out_unlock;
+ }
+ if (s->max_packet_size > (*remaining_bytes)) {
+ printk(KERN_WARNING "%s: Require [%zd] bytes to write; only "
+ "[%zd] available\n", __func__, s->max_packet_size,
+ (*remaining_bytes));
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+ s->block_aligned_filename = kzalloc(s->block_aligned_filename_size,
+ GFP_KERNEL);
+ if (!s->block_aligned_filename) {
+ printk(KERN_ERR "%s: Out of kernel memory whilst attempting to "
+ "kzalloc [%zd] bytes\n", __func__,
+ s->block_aligned_filename_size);
+ rc = -ENOMEM;
+ goto out_unlock;
+ }
+ s->i = 0;
+ dest[s->i++] = ECRYPTFS_TAG_70_PACKET_TYPE;
+ rc = ecryptfs_write_packet_length(&dest[s->i],
+ (ECRYPTFS_SIG_SIZE
+ + 1 /* Cipher code */
+ + s->block_aligned_filename_size),
+ &s->packet_size_len);
+ if (rc) {
+ printk(KERN_ERR "%s: Error generating tag 70 packet "
+ "header; cannot generate packet length; rc = [%d]\n",
+ __func__, rc);
+ goto out_free_unlock;
+ }
+ s->i += s->packet_size_len;
+ ecryptfs_from_hex(&dest[s->i],
+ mount_crypt_stat->global_default_fnek_sig,
+ ECRYPTFS_SIG_SIZE);
+ s->i += ECRYPTFS_SIG_SIZE;
+ s->cipher_code = ecryptfs_code_for_cipher_string(
+ mount_crypt_stat->global_default_fn_cipher_name,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ if (s->cipher_code == 0) {
+ printk(KERN_WARNING "%s: Unable to generate code for "
+ "cipher [%s] with key bytes [%zd]\n", __func__,
+ mount_crypt_stat->global_default_fn_cipher_name,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ rc = -EINVAL;
+ goto out_free_unlock;
+ }
+ dest[s->i++] = s->cipher_code;
+ rc = ecryptfs_find_auth_tok_for_sig(
+ &s->auth_tok, mount_crypt_stat,
+ mount_crypt_stat->global_default_fnek_sig);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to find auth tok for "
+ "fnek sig [%s]; rc = [%d]\n", __func__,
+ mount_crypt_stat->global_default_fnek_sig, rc);
+ goto out_free_unlock;
+ }
+ /* TODO: Support other key modules than passphrase for
+ * filename encryption */
+ BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD);
+ sg_init_one(
+ &s->hash_sg,
+ (u8 *)s->auth_tok->token.password.session_key_encryption_key,
+ s->auth_tok->token.password.session_key_encryption_key_bytes);
+ s->hash_desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ s->hash_desc.tfm = crypto_alloc_hash(ECRYPTFS_TAG_70_DIGEST, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(s->hash_desc.tfm)) {
+ rc = PTR_ERR(s->hash_desc.tfm);
+ printk(KERN_ERR "%s: Error attempting to "
+ "allocate hash crypto context; rc = [%d]\n",
+ __func__, rc);
+ goto out_free_unlock;
+ }
+ rc = crypto_hash_init(&s->hash_desc);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error initializing crypto hash; rc = [%d]\n",
+ __func__, rc);
+ goto out_release_free_unlock;
+ }
+ rc = crypto_hash_update(
+ &s->hash_desc, &s->hash_sg,
+ s->auth_tok->token.password.session_key_encryption_key_bytes);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error updating crypto hash; rc = [%d]\n",
+ __func__, rc);
+ goto out_release_free_unlock;
+ }
+ rc = crypto_hash_final(&s->hash_desc, s->hash);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error finalizing crypto hash; rc = [%d]\n",
+ __func__, rc);
+ goto out_release_free_unlock;
+ }
+ for (s->j = 0; s->j < (s->num_rand_bytes - 1); s->j++) {
+ s->block_aligned_filename[s->j] =
+ s->hash[(s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)];
+ if ((s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)
+ == (ECRYPTFS_TAG_70_DIGEST_SIZE - 1)) {
+ sg_init_one(&s->hash_sg, (u8 *)s->hash,
+ ECRYPTFS_TAG_70_DIGEST_SIZE);
+ rc = crypto_hash_init(&s->hash_desc);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error initializing crypto hash; "
+ "rc = [%d]\n", __func__, rc);
+ goto out_release_free_unlock;
+ }
+ rc = crypto_hash_update(&s->hash_desc, &s->hash_sg,
+ ECRYPTFS_TAG_70_DIGEST_SIZE);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error updating crypto hash; "
+ "rc = [%d]\n", __func__, rc);
+ goto out_release_free_unlock;
+ }
+ rc = crypto_hash_final(&s->hash_desc, s->tmp_hash);
+ if (rc) {
+ printk(KERN_ERR
+ "%s: Error finalizing crypto hash; "
+ "rc = [%d]\n", __func__, rc);
+ goto out_release_free_unlock;
+ }
+ memcpy(s->hash, s->tmp_hash,
+ ECRYPTFS_TAG_70_DIGEST_SIZE);
+ }
+ if (s->block_aligned_filename[s->j] == '\0')
+ s->block_aligned_filename[s->j] = ECRYPTFS_NON_NULL;
+ }
+ memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,
+ filename_size);
+ rc = virt_to_scatterlist(s->block_aligned_filename,
+ s->block_aligned_filename_size, &s->src_sg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert filename memory to scatterlist; "
+ "expected rc = 1; got rc = [%d]. "
+ "block_aligned_filename_size = [%zd]\n", __func__, rc,
+ s->block_aligned_filename_size);
+ goto out_release_free_unlock;
+ }
+ rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size,
+ &s->dst_sg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert encrypted filename memory to scatterlist; "
+ "expected rc = 1; got rc = [%d]. "
+ "block_aligned_filename_size = [%zd]\n", __func__, rc,
+ s->block_aligned_filename_size);
+ goto out_release_free_unlock;
+ }
+ /* The characters in the first block effectively do the job
+ * of the IV here, so we just use 0's for the IV. Note the
+ * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES
+ * >= ECRYPTFS_MAX_IV_BYTES. */
+ memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES);
+ s->desc.info = s->iv;
+ rc = crypto_blkcipher_setkey(
+ s->desc.tfm,
+ s->auth_tok->token.password.session_key_encryption_key,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ if (rc < 0) {
+ printk(KERN_ERR "%s: Error setting key for crypto context; "
+ "rc = [%d]. s->auth_tok->token.password.session_key_"
+ "encryption_key = [0x%p]; mount_crypt_stat->"
+ "global_default_fn_cipher_key_bytes = [%zd]\n", __func__,
+ rc,
+ s->auth_tok->token.password.session_key_encryption_key,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ goto out_release_free_unlock;
+ }
+ rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
+ s->block_aligned_filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to encrypt filename; "
+ "rc = [%d]\n", __func__, rc);
+ goto out_release_free_unlock;
+ }
+ s->i += s->block_aligned_filename_size;
+ (*packet_size) = s->i;
+ (*remaining_bytes) -= (*packet_size);
+out_release_free_unlock:
+ crypto_free_hash(s->hash_desc.tfm);
+out_free_unlock:
+ memset(s->block_aligned_filename, 0, s->block_aligned_filename_size);
+ kfree(s->block_aligned_filename);
+out_unlock:
+ mutex_unlock(s->tfm_mutex);
+out:
+ kfree(s);
+ return rc;
+}
+
+struct ecryptfs_parse_tag_70_packet_silly_stack {
+ u8 cipher_code;
+ size_t max_packet_size;
+ size_t packet_size_len;
+ size_t parsed_tag_70_packet_size;
+ size_t block_aligned_filename_size;
+ size_t block_size;
+ size_t i;
+ struct mutex *tfm_mutex;
+ char *decrypted_filename;
+ struct ecryptfs_auth_tok *auth_tok;
+ struct scatterlist src_sg;
+ struct scatterlist dst_sg;
+ struct blkcipher_desc desc;
+ char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
+ char iv[ECRYPTFS_MAX_IV_BYTES];
+ char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
+};
+
+/**
+ * parse_tag_70_packet - Parse and process FNEK-encrypted passphrase packet
+ * @filename: This function kmalloc's the memory for the filename
+ * @filename_size: This function sets this to the amount of memory
+ * kmalloc'd for the filename
+ * @packet_size: This function sets this to the the number of octets
+ * in the packet parsed
+ * @mount_crypt_stat: The mount-wide cryptographic context
+ * @data: The memory location containing the start of the tag 70
+ * packet
+ * @max_packet_size: The maximum legal size of the packet to be parsed
+ * from @data
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int
+ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
+ size_t *packet_size,
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+ char *data, size_t max_packet_size)
+{
+ struct ecryptfs_parse_tag_70_packet_silly_stack *s;
+ int rc = 0;
+
+ (*packet_size) = 0;
+ (*filename_size) = 0;
+ (*filename) = NULL;
+ s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (!s) {
+ printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc "
+ "[%zd] bytes of kernel memory\n", __func__, sizeof(*s));
+ goto out;
+ }
+ s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) {
+ printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "
+ "at least [%d]\n", __func__, max_packet_size,
+ (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1));
+ rc = -EINVAL;
+ goto out;
+ }
+ /* Octet 0: Tag 70 identifier
+ * Octets 1-N1: Tag 70 packet size (includes cipher identifier
+ * and block-aligned encrypted filename size)
+ * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE)
+ * Octet N2-N3: Cipher identifier (1 octet)
+ * Octets N3-N4: Block-aligned encrypted filename
+ * - Consists of a minimum number of random numbers, a \0
+ * separator, and then the filename */
+ if (data[(*packet_size)++] != ECRYPTFS_TAG_70_PACKET_TYPE) {
+ printk(KERN_WARNING "%s: Invalid packet tag [0x%.2x]; must be "
+ "tag [0x%.2x]\n", __func__,
+ data[((*packet_size) - 1)], ECRYPTFS_TAG_70_PACKET_TYPE);
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = ecryptfs_parse_packet_length(&data[(*packet_size)],
+ &s->parsed_tag_70_packet_size,
+ &s->packet_size_len);
+ if (rc) {
+ printk(KERN_WARNING "%s: Error parsing packet length; "
+ "rc = [%d]\n", __func__, rc);
+ goto out;
+ }
+ s->block_aligned_filename_size = (s->parsed_tag_70_packet_size
+ - ECRYPTFS_SIG_SIZE - 1);
+ if ((1 + s->packet_size_len + s->parsed_tag_70_packet_size)
+ > max_packet_size) {
+ printk(KERN_WARNING "%s: max_packet_size is [%zd]; real packet "
+ "size is [%zd]\n", __func__, max_packet_size,
+ (1 + s->packet_size_len + 1
+ + s->block_aligned_filename_size));
+ rc = -EINVAL;
+ goto out;
+ }
+ (*packet_size) += s->packet_size_len;
+ ecryptfs_to_hex(s->fnek_sig_hex, &data[(*packet_size)],
+ ECRYPTFS_SIG_SIZE);
+ s->fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX] = '\0';
+ (*packet_size) += ECRYPTFS_SIG_SIZE;
+ s->cipher_code = data[(*packet_size)++];
+ rc = ecryptfs_cipher_code_to_string(s->cipher_string, s->cipher_code);
+ if (rc) {
+ printk(KERN_WARNING "%s: Cipher code [%d] is invalid\n",
+ __func__, s->cipher_code);
+ goto out;
+ }
+ rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm,
+ &s->tfm_mutex,
+ s->cipher_string);
+ if (unlikely(rc)) {
+ printk(KERN_ERR "Internal error whilst attempting to get "
+ "tfm and mutex for cipher name [%s]; rc = [%d]\n",
+ s->cipher_string, rc);
+ goto out;
+ }
+ mutex_lock(s->tfm_mutex);
+ rc = virt_to_scatterlist(&data[(*packet_size)],
+ s->block_aligned_filename_size, &s->src_sg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert encrypted filename memory to scatterlist; "
+ "expected rc = 1; got rc = [%d]. "
+ "block_aligned_filename_size = [%zd]\n", __func__, rc,
+ s->block_aligned_filename_size);
+ goto out_unlock;
+ }
+ (*packet_size) += s->block_aligned_filename_size;
+ s->decrypted_filename = kmalloc(s->block_aligned_filename_size,
+ GFP_KERNEL);
+ if (!s->decrypted_filename) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting to "
+ "kmalloc [%zd] bytes\n", __func__,
+ s->block_aligned_filename_size);
+ rc = -ENOMEM;
+ goto out_unlock;
+ }
+ rc = virt_to_scatterlist(s->decrypted_filename,
+ s->block_aligned_filename_size, &s->dst_sg, 1);
+ if (rc != 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert decrypted filename memory to scatterlist; "
+ "expected rc = 1; got rc = [%d]. "
+ "block_aligned_filename_size = [%zd]\n", __func__, rc,
+ s->block_aligned_filename_size);
+ goto out_free_unlock;
+ }
+ /* The characters in the first block effectively do the job of
+ * the IV here, so we just use 0's for the IV. Note the
+ * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES
+ * >= ECRYPTFS_MAX_IV_BYTES. */
+ memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES);
+ s->desc.info = s->iv;
+ rc = ecryptfs_find_auth_tok_for_sig(&s->auth_tok, mount_crypt_stat,
+ s->fnek_sig_hex);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to find auth tok for "
+ "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex,
+ rc);
+ goto out_free_unlock;
+ }
+ /* TODO: Support other key modules than passphrase for
+ * filename encryption */
+ BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD);
+ rc = crypto_blkcipher_setkey(
+ s->desc.tfm,
+ s->auth_tok->token.password.session_key_encryption_key,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ if (rc < 0) {
+ printk(KERN_ERR "%s: Error setting key for crypto context; "
+ "rc = [%d]. s->auth_tok->token.password.session_key_"
+ "encryption_key = [0x%p]; mount_crypt_stat->"
+ "global_default_fn_cipher_key_bytes = [%zd]\n", __func__,
+ rc,
+ s->auth_tok->token.password.session_key_encryption_key,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ goto out_free_unlock;
+ }
+ rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
+ s->block_aligned_filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to decrypt filename; "
+ "rc = [%d]\n", __func__, rc);
+ goto out_free_unlock;
+ }
+ s->i = 0;
+ while (s->decrypted_filename[s->i] != '\0'
+ && s->i < s->block_aligned_filename_size)
+ s->i++;
+ if (s->i == s->block_aligned_filename_size) {
+ printk(KERN_WARNING "%s: Invalid tag 70 packet; could not "
+ "find valid separator between random characters and "
+ "the filename\n", __func__);
+ rc = -EINVAL;
+ goto out_free_unlock;
+ }
+ s->i++;
+ (*filename_size) = (s->block_aligned_filename_size - s->i);
+ if (!((*filename_size) > 0 && (*filename_size < PATH_MAX))) {
+ printk(KERN_WARNING "%s: Filename size is [%zd], which is "
+ "invalid\n", __func__, (*filename_size));
+ rc = -EINVAL;
+ goto out_free_unlock;
+ }
+ (*filename) = kmalloc(((*filename_size) + 1), GFP_KERNEL);
+ if (!(*filename)) {
+ printk(KERN_ERR "%s: Out of memory whilst attempting to "
+ "kmalloc [%zd] bytes\n", __func__,
+ ((*filename_size) + 1));
+ rc = -ENOMEM;
+ goto out_free_unlock;
+ }
+ memcpy((*filename), &s->decrypted_filename[s->i], (*filename_size));
+ (*filename)[(*filename_size)] = '\0';
+out_free_unlock:
+ kfree(s->decrypted_filename);
+out_unlock:
+ mutex_unlock(s->tfm_mutex);
+out:
+ if (rc) {
+ (*packet_size) = 0;
+ (*filename_size) = 0;
+ (*filename) = NULL;
+ }
+ kfree(s);
+ return rc;
+}
+
+static int
ecryptfs_get_auth_tok_sig(char **sig, struct ecryptfs_auth_tok *auth_tok)
{
int rc = 0;
@@ -897,30 +1471,6 @@ out:
return rc;
}
-static int
-ecryptfs_find_global_auth_tok_for_sig(
- struct ecryptfs_global_auth_tok **global_auth_tok,
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
-{
- struct ecryptfs_global_auth_tok *walker;
- int rc = 0;
-
- (*global_auth_tok) = NULL;
- mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
- list_for_each_entry(walker,
- &mount_crypt_stat->global_auth_tok_list,
- mount_crypt_stat_list) {
- if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
- (*global_auth_tok) = walker;
- goto out;
- }
- }
- rc = -EINVAL;
-out:
- mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
- return rc;
-}
-
/**
* ecryptfs_verify_version
* @version: The version number to confirm
@@ -990,43 +1540,6 @@ out:
}
/**
- * ecryptfs_find_auth_tok_for_sig
- * @auth_tok: Set to the matching auth_tok; NULL if not found
- * @crypt_stat: inode crypt_stat crypto context
- * @sig: Sig of auth_tok to find
- *
- * For now, this function simply looks at the registered auth_tok's
- * linked off the mount_crypt_stat, so all the auth_toks that can be
- * used must be registered at mount time. This function could
- * potentially try a lot harder to find auth_tok's (e.g., by calling
- * out to ecryptfsd to dynamically retrieve an auth_tok object) so
- * that static registration of auth_tok's will no longer be necessary.
- *
- * Returns zero on no error; non-zero on error
- */
-static int
-ecryptfs_find_auth_tok_for_sig(
- struct ecryptfs_auth_tok **auth_tok,
- struct ecryptfs_crypt_stat *crypt_stat, char *sig)
-{
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
- crypt_stat->mount_crypt_stat;
- struct ecryptfs_global_auth_tok *global_auth_tok;
- int rc = 0;
-
- (*auth_tok) = NULL;
- if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
- mount_crypt_stat, sig)) {
- struct key *auth_tok_key;
-
- rc = ecryptfs_keyring_auth_tok_for_sig(&auth_tok_key, auth_tok,
- sig);
- } else
- (*auth_tok) = global_auth_tok->global_auth_tok;
- return rc;
-}
-
-/**
* decrypt_passphrase_encrypted_session_key - Decrypt the session key with the given auth_tok.
* @auth_tok: The passphrase authentication token to use to encrypt the FEK
* @crypt_stat: The cryptographic context
@@ -1037,17 +1550,14 @@ static int
decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
struct ecryptfs_crypt_stat *crypt_stat)
{
- struct scatterlist dst_sg;
- struct scatterlist src_sg;
+ struct scatterlist dst_sg[2];
+ struct scatterlist src_sg[2];
struct mutex *tfm_mutex;
struct blkcipher_desc desc = {
.flags = CRYPTO_TFM_REQ_MAY_SLEEP
};
int rc = 0;
- sg_init_table(&dst_sg, 1);
- sg_init_table(&src_sg, 1);
-
if (unlikely(ecryptfs_verbosity > 0)) {
ecryptfs_printk(
KERN_DEBUG, "Session key encryption key (size [%d]):\n",
@@ -1066,8 +1576,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
}
rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key,
auth_tok->session_key.encrypted_key_size,
- &src_sg, 1);
- if (rc != 1) {
+ src_sg, 2);
+ if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.encrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]. "
@@ -1079,8 +1589,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
auth_tok->session_key.encrypted_key_size;
rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key,
auth_tok->session_key.decrypted_key_size,
- &dst_sg, 1);
- if (rc != 1) {
+ dst_sg, 2);
+ if (rc < 1 || rc > 2) {
printk(KERN_ERR "Internal error whilst attempting to convert "
"auth_tok->session_key.decrypted_key to scatterlist; "
"expected rc = 1; got rc = [%d]\n", rc);
@@ -1096,7 +1606,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
rc = -EINVAL;
goto out;
}
- rc = crypto_blkcipher_decrypt(&desc, &dst_sg, &src_sg,
+ rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg,
auth_tok->session_key.encrypted_key_size);
mutex_unlock(tfm_mutex);
if (unlikely(rc)) {
@@ -1259,7 +1769,8 @@ find_next_matching_auth_tok:
rc = -EINVAL;
goto out_wipe_list;
}
- ecryptfs_find_auth_tok_for_sig(&matching_auth_tok, crypt_stat,
+ ecryptfs_find_auth_tok_for_sig(&matching_auth_tok,
+ crypt_stat->mount_crypt_stat,
candidate_auth_tok_sig);
if (matching_auth_tok) {
found_auth_tok = 1;
@@ -1339,7 +1850,9 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
int rc;
rc = write_tag_66_packet(auth_tok->token.private_key.signature,
- ecryptfs_code_for_cipher_string(crypt_stat),
+ ecryptfs_code_for_cipher_string(
+ crypt_stat->cipher,
+ crypt_stat->key_size),
crypt_stat, &payload, &payload_len);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
@@ -1539,8 +2052,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
size_t i;
size_t encrypted_session_key_valid = 0;
char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
- struct scatterlist dst_sg;
- struct scatterlist src_sg;
+ struct scatterlist dst_sg[2];
+ struct scatterlist src_sg[2];
struct mutex *tfm_mutex = NULL;
u8 cipher_code;
size_t packet_size_length;
@@ -1619,8 +2132,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
ecryptfs_dump_hex(session_key_encryption_key, 16);
}
rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size,
- &src_sg, 1);
- if (rc != 1) {
+ src_sg, 2);
+ if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat session key; expected rc = 1; "
"got rc = [%d]. key_rec->enc_key_size = [%d]\n",
@@ -1629,8 +2142,8 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
goto out;
}
rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size,
- &dst_sg, 1);
- if (rc != 1) {
+ dst_sg, 2);
+ if (rc < 1 || rc > 2) {
ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
"for crypt_stat encrypted session key; "
"expected rc = 1; got rc = [%d]. "
@@ -1651,7 +2164,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,
rc = 0;
ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n",
crypt_stat->key_size);
- rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg,
+ rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg,
(*key_rec).enc_key_size);
mutex_unlock(tfm_mutex);
if (rc) {
@@ -1699,7 +2212,8 @@ encrypted_session_key_set:
dest[(*packet_size)++] = 0x04; /* version 4 */
/* TODO: Break from RFC2440 so that arbitrary ciphers can be
* specified with strings */
- cipher_code = ecryptfs_code_for_cipher_string(crypt_stat);
+ cipher_code = ecryptfs_code_for_cipher_string(crypt_stat->cipher,
+ crypt_stat->key_size);
if (cipher_code == 0) {
ecryptfs_printk(KERN_WARNING, "Unable to generate code for "
"cipher [%s]\n", crypt_stat->cipher);
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index c440c6b58b2..c6d7a4d748a 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -73,7 +73,7 @@ static int ecryptfs_threadfn(void *ignored)
mntget(req->lower_mnt);
(*req->lower_file) = dentry_open(
req->lower_dentry, req->lower_mnt,
- (O_RDWR | O_LARGEFILE));
+ (O_RDWR | O_LARGEFILE), current_cred());
req->flags |= ECRYPTFS_REQ_PROCESSED;
}
wake_up(&req->wait);
@@ -132,7 +132,8 @@ void ecryptfs_destroy_kthread(void)
*/
int ecryptfs_privileged_open(struct file **lower_file,
struct dentry *lower_dentry,
- struct vfsmount *lower_mnt)
+ struct vfsmount *lower_mnt,
+ const struct cred *cred)
{
struct ecryptfs_open_req *req;
int rc = 0;
@@ -143,7 +144,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
dget(lower_dentry);
mntget(lower_mnt);
(*lower_file) = dentry_open(lower_dentry, lower_mnt,
- (O_RDWR | O_LARGEFILE));
+ (O_RDWR | O_LARGEFILE), cred);
if (!IS_ERR(*lower_file))
goto out;
req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
@@ -184,7 +185,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
dget(lower_dentry);
mntget(lower_mnt);
(*lower_file) = dentry_open(lower_dentry, lower_mnt,
- (O_RDONLY | O_LARGEFILE));
+ (O_RDONLY | O_LARGEFILE), cred);
if (IS_ERR(*lower_file)) {
rc = PTR_ERR(*req->lower_file);
(*lower_file) = NULL;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 64d2ba980df..789cf2e1be1 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -115,6 +115,7 @@ void __ecryptfs_printk(const char *fmt, ...)
*/
int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
{
+ const struct cred *cred = current_cred();
struct ecryptfs_inode_info *inode_info =
ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
int rc = 0;
@@ -127,7 +128,7 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
rc = ecryptfs_privileged_open(&inode_info->lower_file,
- lower_dentry, lower_mnt);
+ lower_dentry, lower_mnt, cred);
if (rc || IS_ERR(inode_info->lower_file)) {
printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
@@ -205,7 +206,9 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher,
ecryptfs_opt_ecryptfs_key_bytes,
ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
- ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
+ ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig,
+ ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
+ ecryptfs_opt_err };
static const match_table_t tokens = {
{ecryptfs_opt_sig, "sig=%s"},
@@ -216,6 +219,9 @@ static const match_table_t tokens = {
{ecryptfs_opt_passthrough, "ecryptfs_passthrough"},
{ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"},
{ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"},
+ {ecryptfs_opt_fnek_sig, "ecryptfs_fnek_sig=%s"},
+ {ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"},
+ {ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"},
{ecryptfs_opt_err, NULL}
};
@@ -280,8 +286,11 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
int rc = 0;
int sig_set = 0;
int cipher_name_set = 0;
+ int fn_cipher_name_set = 0;
int cipher_key_bytes;
int cipher_key_bytes_set = 0;
+ int fn_cipher_key_bytes;
+ int fn_cipher_key_bytes_set = 0;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(sb)->mount_crypt_stat;
substring_t args[MAX_OPT_ARGS];
@@ -289,7 +298,12 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
char *sig_src;
char *cipher_name_dst;
char *cipher_name_src;
+ char *fn_cipher_name_dst;
+ char *fn_cipher_name_src;
+ char *fnek_dst;
+ char *fnek_src;
char *cipher_key_bytes_src;
+ char *fn_cipher_key_bytes_src;
if (!options) {
rc = -EINVAL;
@@ -321,10 +335,7 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
global_default_cipher_name;
strncpy(cipher_name_dst, cipher_name_src,
ECRYPTFS_MAX_CIPHER_NAME_SIZE);
- ecryptfs_printk(KERN_DEBUG,
- "The mount_crypt_stat "
- "global_default_cipher_name set to: "
- "[%s]\n", cipher_name_dst);
+ cipher_name_dst[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
cipher_name_set = 1;
break;
case ecryptfs_opt_ecryptfs_key_bytes:
@@ -334,11 +345,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
&cipher_key_bytes_src, 0);
mount_crypt_stat->global_default_cipher_key_size =
cipher_key_bytes;
- ecryptfs_printk(KERN_DEBUG,
- "The mount_crypt_stat "
- "global_default_cipher_key_size "
- "set to: [%d]\n", mount_crypt_stat->
- global_default_cipher_key_size);
cipher_key_bytes_set = 1;
break;
case ecryptfs_opt_passthrough:
@@ -355,11 +361,51 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
mount_crypt_stat->flags |=
ECRYPTFS_ENCRYPTED_VIEW_ENABLED;
break;
+ case ecryptfs_opt_fnek_sig:
+ fnek_src = args[0].from;
+ fnek_dst =
+ mount_crypt_stat->global_default_fnek_sig;
+ strncpy(fnek_dst, fnek_src, ECRYPTFS_SIG_SIZE_HEX);
+ mount_crypt_stat->global_default_fnek_sig[
+ ECRYPTFS_SIG_SIZE_HEX] = '\0';
+ rc = ecryptfs_add_global_auth_tok(
+ mount_crypt_stat,
+ mount_crypt_stat->global_default_fnek_sig);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to register "
+ "global fnek sig [%s]; rc = [%d]\n",
+ mount_crypt_stat->global_default_fnek_sig,
+ rc);
+ goto out;
+ }
+ mount_crypt_stat->flags |=
+ (ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES
+ | ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK);
+ break;
+ case ecryptfs_opt_fn_cipher:
+ fn_cipher_name_src = args[0].from;
+ fn_cipher_name_dst =
+ mount_crypt_stat->global_default_fn_cipher_name;
+ strncpy(fn_cipher_name_dst, fn_cipher_name_src,
+ ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+ mount_crypt_stat->global_default_fn_cipher_name[
+ ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0';
+ fn_cipher_name_set = 1;
+ break;
+ case ecryptfs_opt_fn_cipher_key_bytes:
+ fn_cipher_key_bytes_src = args[0].from;
+ fn_cipher_key_bytes =
+ (int)simple_strtol(fn_cipher_key_bytes_src,
+ &fn_cipher_key_bytes_src, 0);
+ mount_crypt_stat->global_default_fn_cipher_key_bytes =
+ fn_cipher_key_bytes;
+ fn_cipher_key_bytes_set = 1;
+ break;
case ecryptfs_opt_err:
default:
- ecryptfs_printk(KERN_WARNING,
- "eCryptfs: unrecognized option '%s'\n",
- p);
+ printk(KERN_WARNING
+ "%s: eCryptfs: unrecognized option [%s]\n",
+ __func__, p);
}
}
if (!sig_set) {
@@ -373,33 +419,60 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE);
-
strcpy(mount_crypt_stat->global_default_cipher_name,
ECRYPTFS_DEFAULT_CIPHER);
}
- if (!cipher_key_bytes_set) {
+ if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
+ && !fn_cipher_name_set)
+ strcpy(mount_crypt_stat->global_default_fn_cipher_name,
+ mount_crypt_stat->global_default_cipher_name);
+ if (!cipher_key_bytes_set)
mount_crypt_stat->global_default_cipher_key_size = 0;
- }
+ if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
+ && !fn_cipher_key_bytes_set)
+ mount_crypt_stat->global_default_fn_cipher_key_bytes =
+ mount_crypt_stat->global_default_cipher_key_size;
mutex_lock(&key_tfm_list_mutex);
if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
- NULL))
+ NULL)) {
rc = ecryptfs_add_new_key_tfm(
NULL, mount_crypt_stat->global_default_cipher_name,
mount_crypt_stat->global_default_cipher_key_size);
- mutex_unlock(&key_tfm_list_mutex);
- if (rc) {
- printk(KERN_ERR "Error attempting to initialize cipher with "
- "name = [%s] and key size = [%td]; rc = [%d]\n",
- mount_crypt_stat->global_default_cipher_name,
- mount_crypt_stat->global_default_cipher_key_size, rc);
- rc = -EINVAL;
- goto out;
+ if (rc) {
+ printk(KERN_ERR "Error attempting to initialize "
+ "cipher with name = [%s] and key size = [%td]; "
+ "rc = [%d]\n",
+ mount_crypt_stat->global_default_cipher_name,
+ mount_crypt_stat->global_default_cipher_key_size,
+ rc);
+ rc = -EINVAL;
+ mutex_unlock(&key_tfm_list_mutex);
+ goto out;
+ }
}
+ if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
+ && !ecryptfs_tfm_exists(
+ mount_crypt_stat->global_default_fn_cipher_name, NULL)) {
+ rc = ecryptfs_add_new_key_tfm(
+ NULL, mount_crypt_stat->global_default_fn_cipher_name,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to initialize "
+ "cipher with name = [%s] and key size = [%td]; "
+ "rc = [%d]\n",
+ mount_crypt_stat->global_default_fn_cipher_name,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes,
+ rc);
+ rc = -EINVAL;
+ mutex_unlock(&key_tfm_list_mutex);
+ goto out;
+ }
+ }
+ mutex_unlock(&key_tfm_list_mutex);
rc = ecryptfs_init_global_auth_toks(mount_crypt_stat);
- if (rc) {
+ if (rc)
printk(KERN_WARNING "One or more global auth toks could not "
"properly register; rc = [%d]\n", rc);
- }
out:
return rc;
}
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
index c6983978a31..96ef51489e0 100644
--- a/fs/ecryptfs/messaging.c
+++ b/fs/ecryptfs/messaging.c
@@ -193,7 +193,7 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
(*daemon) = kzalloc(sizeof(**daemon), GFP_KERNEL);
if (!(*daemon)) {
rc = -ENOMEM;
- printk(KERN_ERR "%s: Failed to allocate [%Zd] bytes of "
+ printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of "
"GFP_KERNEL memory\n", __func__, sizeof(**daemon));
goto out;
}
@@ -360,7 +360,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
struct ecryptfs_msg_ctx *msg_ctx;
size_t msg_size;
struct nsproxy *nsproxy;
- struct user_namespace *current_user_ns;
+ struct user_namespace *tsk_user_ns;
+ uid_t ctx_euid;
int rc;
if (msg->index >= ecryptfs_message_buf_len) {
@@ -384,9 +385,9 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
mutex_unlock(&ecryptfs_daemon_hash_mux);
goto wake_up;
}
- current_user_ns = nsproxy->user_ns;
- rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid,
- current_user_ns);
+ tsk_user_ns = __task_cred(msg_ctx->task)->user->user_ns;
+ ctx_euid = task_euid(msg_ctx->task);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns);
rcu_read_unlock();
mutex_unlock(&ecryptfs_daemon_hash_mux);
if (rc) {
@@ -394,28 +395,28 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
printk(KERN_WARNING "%s: User [%d] received a "
"message response from process [0x%p] but does "
"not have a registered daemon\n", __func__,
- msg_ctx->task->euid, pid);
+ ctx_euid, pid);
goto wake_up;
}
- if (msg_ctx->task->euid != euid) {
+ if (ctx_euid != euid) {
rc = -EBADMSG;
printk(KERN_WARNING "%s: Received message from user "
"[%d]; expected message from user [%d]\n", __func__,
- euid, msg_ctx->task->euid);
+ euid, ctx_euid);
goto unlock;
}
- if (current_user_ns != user_ns) {
+ if (tsk_user_ns != user_ns) {
rc = -EBADMSG;
printk(KERN_WARNING "%s: Received message from user_ns "
"[0x%p]; expected message from user_ns [0x%p]\n",
- __func__, user_ns, nsproxy->user_ns);
+ __func__, user_ns, tsk_user_ns);
goto unlock;
}
if (daemon->pid != pid) {
rc = -EBADMSG;
printk(KERN_ERR "%s: User [%d] sent a message response "
"from an unrecognized process [0x%p]\n",
- __func__, msg_ctx->task->euid, pid);
+ __func__, ctx_euid, pid);
goto unlock;
}
if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
@@ -434,7 +435,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
if (!msg_ctx->msg) {
rc = -ENOMEM;
- printk(KERN_ERR "%s: Failed to allocate [%Zd] bytes of "
+ printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of "
"GFP_KERNEL memory\n", __func__, msg_size);
goto unlock;
}
@@ -464,14 +465,14 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
struct ecryptfs_msg_ctx **msg_ctx)
{
struct ecryptfs_daemon *daemon;
+ uid_t euid = current_euid();
int rc;
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
- current->nsproxy->user_ns);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
if (rc || !daemon) {
rc = -ENOTCONN;
printk(KERN_ERR "%s: User [%d] does not have a daemon "
- "registered\n", __func__, current->euid);
+ "registered\n", __func__, euid);
goto out;
}
mutex_lock(&ecryptfs_msg_ctx_lists_mux);
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index b484792a099..a67fea655f4 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -42,12 +42,12 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
{
struct ecryptfs_daemon *daemon;
unsigned int mask = 0;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
- current->nsproxy->user_ns);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
BUG_ON(rc || !daemon);
mutex_lock(&daemon->mux);
mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -83,6 +83,7 @@ static int
ecryptfs_miscdev_open(struct inode *inode, struct file *file)
{
struct ecryptfs_daemon *daemon = NULL;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
@@ -93,11 +94,9 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
"count; rc = [%d]\n", __func__, rc);
goto out_unlock_daemon_list;
}
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
- current->nsproxy->user_ns);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
if (rc || !daemon) {
- rc = ecryptfs_spawn_daemon(&daemon, current->euid,
- current->nsproxy->user_ns,
+ rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(),
task_pid(current));
if (rc) {
printk(KERN_ERR "%s: Error attempting to spawn daemon; "
@@ -147,11 +146,11 @@ static int
ecryptfs_miscdev_release(struct inode *inode, struct file *file)
{
struct ecryptfs_daemon *daemon = NULL;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
- current->nsproxy->user_ns);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
BUG_ON(rc || !daemon);
mutex_lock(&daemon->mux);
BUG_ON(daemon->pid != task_pid(current));
@@ -200,7 +199,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
if (!msg_ctx->msg) {
rc = -ENOMEM;
printk(KERN_ERR "%s: Out of memory whilst attempting "
- "to kmalloc(%Zd, GFP_KERNEL)\n", __func__,
+ "to kmalloc(%zd, GFP_KERNEL)\n", __func__,
(sizeof(*msg_ctx->msg) + data_size));
goto out_unlock;
}
@@ -246,12 +245,12 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
char packet_length[3];
size_t i;
size_t total_length;
+ uid_t euid = current_euid();
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */
- rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
- current->nsproxy->user_ns);
+ rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
BUG_ON(rc || !daemon);
mutex_lock(&daemon->mux);
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -290,8 +289,8 @@ check_list:
* message from the queue; try again */
goto check_list;
}
- BUG_ON(current->euid != daemon->euid);
- BUG_ON(current->nsproxy->user_ns != daemon->user_ns);
+ BUG_ON(euid != daemon->euid);
+ BUG_ON(current_user_ns() != daemon->user_ns);
BUG_ON(task_pid(current) != daemon->pid);
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
struct ecryptfs_msg_ctx, daemon_out_list);
@@ -323,7 +322,7 @@ check_list:
if (count < total_length) {
rc = 0;
printk(KERN_WARNING "%s: Only given user buffer of "
- "size [%Zd], but we need [%Zd] to read the "
+ "size [%zd], but we need [%zd] to read the "
"pending message\n", __func__, count, total_length);
goto out_unlock_msg_ctx;
}
@@ -377,7 +376,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size,
if ((sizeof(*msg) + msg->data_len) != data_size) {
printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = "
- "[%Zd]; data_size = [%Zd]. Invalid packet.\n", __func__,
+ "[%zd]; data_size = [%zd]. Invalid packet.\n", __func__,
(sizeof(*msg) + msg->data_len), data_size);
rc = -EINVAL;
goto out;
@@ -414,6 +413,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
size_t packet_size, packet_size_length, i;
ssize_t sz = 0;
char *data;
+ uid_t euid = current_euid();
int rc;
if (count == 0)
@@ -421,7 +421,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
data = kmalloc(count, GFP_KERNEL);
if (!data) {
printk(KERN_ERR "%s: Out of memory whilst attempting to "
- "kmalloc([%Zd], GFP_KERNEL)\n", __func__, count);
+ "kmalloc([%zd], GFP_KERNEL)\n", __func__, count);
goto out;
}
rc = copy_from_user(data, buf, count);
@@ -436,8 +436,8 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
case ECRYPTFS_MSG_RESPONSE:
if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
printk(KERN_WARNING "%s: Minimum acceptable packet "
- "size is [%Zd], but amount of data written is "
- "only [%Zd]. Discarding response packet.\n",
+ "size is [%zd], but amount of data written is "
+ "only [%zd]. Discarding response packet.\n",
__func__,
(1 + 4 + 1 + sizeof(struct ecryptfs_message)),
count);
@@ -455,16 +455,15 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
}
i += packet_size_length;
if ((1 + 4 + packet_size_length + packet_size) != count) {
- printk(KERN_WARNING "%s: (1 + packet_size_length([%Zd])"
- " + packet_size([%Zd]))([%Zd]) != "
- "count([%Zd]). Invalid packet format.\n",
+ printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
+ " + packet_size([%zd]))([%zd]) != "
+ "count([%zd]). Invalid packet format.\n",
__func__, packet_size_length, packet_size,
(1 + packet_size_length + packet_size), count);
goto out_free;
}
rc = ecryptfs_miscdev_response(&data[i], packet_size,
- current->euid,
- current->nsproxy->user_ns,
+ euid, current_user_ns(),
task_pid(current), seq);
if (rc)
printk(KERN_WARNING "%s: Failed to deliver miscdev "
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 04d7b3fa1ac..46cec2b6979 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -288,7 +288,7 @@ static int ecryptfs_write_begin(struct file *file,
loff_t prev_page_end_size;
int rc = 0;
- page = __grab_cache_page(mapping, index);
+ page = grab_cache_page_write_begin(mapping, index, flags);
if (!page)
return -ENOMEM;
*pagep = page;