eCryptfs changes for 7.1-rc1

The set of eCryptfs changes for the 7.1-rc1 merge window consists of:
 - A fix to avoid unnecessary eCryptfs inode timestamp truncation by
   re-using the lower filesystem's time granularity
 - Various small code cleanups
 - Reorganization of the setattr hook's handling of inode resizing to
   improve style and readability, remove an unnecessary memory allocation
   when shrinking, and to support an upcoming rework of the VFS
   interfaces involved in truncation
 
 The patches have all spent time in linux-next and they do not regress
 the tests in the ecryptfs-utils tree. The inode timestamp fix returns
 the "setattr-flush-dirty" test to passing state.
 
 Signed-off-by: Tyler Hicks <code@tyhicks.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEKvuQkp28KvPJn/fVfL7QslYSS/0FAmnlw5YRHGNvZGVAdHlo
 aWNrcy5jb20ACgkQfL7QslYSS/38Yg//ZTAxtS9P+LkrrDSgFhCBDW2Z6L+y7EFu
 4cYRj37+u2d+V69aWBFcFbKC67WqLwAU9U6RpmUh9cIU6f1N0VU9C8EmGAe/am3W
 oOS2TFwGnVvlTnaChgWEDk0UT6GwzGenHkH+umy+70ryOEq7HydJiynYbyjRqZ5J
 Kea5ppLh23Dh7+fnelbDCYRr9iNld1r5mkqbKRHTpm/3o3ZYRWoytWS5/afkDCmW
 0ewb3xuVjFmlRuc9Lqsl4uC5r7QLQC7d+087OBTSumxvQLXtN4hWI38orpE7LCQV
 h8xNVLZrGSX5LhGSobhSC1Hrab6+S/kcHEqWg2KqUYx/kYHcUOMkLZ3vCGa1FmJ1
 8hsu8lO1vy3waoNLeS11IIAMFd+aG9N7N6s2nWvMNoEFapAkWNXTTuJ0hPK7+XLA
 WEDwYX9tV/NckTQO+/TQb8OYl1bLTzSxG/VP9hWhK7kmXxDpd2xdms/3PZZHPQV+
 IxOC9yBS2w3J6OHfeqhxkU40woJapmcpIum9NtrXg/yEyW7+pIa4ZVWDxaiqiYTS
 BkhxaYFDVHvrtn2dKLWf/Dklj7I6GMvyWFJKOYKIE2tZ8qBokyVhfNwyEDiLt2RA
 QTXNCCZ4B4x1dvDLmKgDrFLy4CHlsKDNM4JtrJs0t4rv8DC6zeGzvRC6YJI+uLYs
 wFhzjenKtac=
 =iUz9
 -----END PGP SIGNATURE-----

Merge tag 'ecryptfs-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs

Pull eCryptfs updates from Tyler Hicks:

 - avoid unnecessary eCryptfs inode timestamp truncation by re-using the
   lower filesystem's time granularity

 - various small code cleanups

 - reorganize the setattr hook inode resizing to improve style and
   readability, remove an unnecessary memory allocation when shrinking,
   and to support an upcoming rework of the VFS interfaces involved in
   truncation

* tag 'ecryptfs-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
  ecryptfs: keep the lower iattr contained in truncate_upper
  ecryptfs: factor out a ecryptfs_iattr_to_lower helper
  ecryptfs: merge ecryptfs_inode_newsize_ok into truncate_upper
  ecryptfs: combine the two ATTR_SIZE blocks in ecryptfs_setattr
  ecryptfs: use ZERO_PAGE instead of allocating zeroed memory in truncate_upper
  ecryptfs: streamline truncate_upper
  ecryptfs: cleanup ecryptfs_setattr
  ecryptfs: Drop TODO comment in ecryptfs_derive_iv
  ecryptfs: Fix typo in ecryptfs_derive_iv function comment
  ecryptfs: Log function name only once in decode_and_decrypt_filename
  ecryptfs: Remove redundant if checks in encrypt_and_encode_filename
  ecryptfs: Fix tag number in encrypt_filename() error message
  ecryptfs: Use struct_size to improve process_response + send_miscdev
  ecryptfs: Replace memcpy + manual NUL termination with strscpy
  ecryptfs: Set s_time_gran to get correct time granularity
This commit is contained in:
Linus Torvalds 2026-04-20 10:54:17 -07:00
commit a5e1c3b609
7 changed files with 150 additions and 181 deletions

View File

@ -72,7 +72,7 @@ static int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
/**
* ecryptfs_derive_iv
* @iv: destination for the derived iv vale
* @iv: destination for the derived iv value
* @crypt_stat: Pointer to crypt_stat struct for the current inode
* @offset: Offset of the extent whose IV we are to derive
*
@ -89,10 +89,6 @@ void ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
ecryptfs_printk(KERN_DEBUG, "root iv:\n");
ecryptfs_dump_hex(crypt_stat->root_iv, crypt_stat->iv_bytes);
}
/* TODO: It is probably secure to just cast the least
* significant bits of the root IV into an unsigned long and
* add the offset to that rather than go through all this
* hashing business. -Halcrow */
memcpy(src, crypt_stat->root_iv, crypt_stat->iv_bytes);
memset((src + crypt_stat->iv_bytes), 0, 16);
snprintf((src + crypt_stat->iv_bytes), 16, "%lld", offset);
@ -1376,9 +1372,9 @@ ecryptfs_encrypt_filename(struct ecryptfs_filename *filename,
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);
ecryptfs_printk(KERN_ERR,
"Error attempting to get packet size for tag 70; rc = [%d]\n",
rc);
filename->encrypted_filename_size = 0;
goto out;
}
@ -1802,8 +1798,9 @@ int ecryptfs_encrypt_and_encode_filename(
filename->filename_size = name_size;
rc = ecryptfs_encrypt_filename(filename, mount_crypt_stat);
if (rc) {
printk(KERN_ERR "%s: Error attempting to encrypt "
"filename; rc = [%d]\n", __func__, rc);
ecryptfs_printk(KERN_ERR,
"Error attempting to encrypt filename; rc = [%d]\n",
rc);
kfree(filename);
goto out;
}
@ -1811,9 +1808,8 @@ int ecryptfs_encrypt_and_encode_filename(
NULL, &encoded_name_no_prefix_size,
filename->encrypted_filename,
filename->encrypted_filename_size);
if (mount_crypt_stat
&& (mount_crypt_stat->flags
& ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))
if (mount_crypt_stat->flags
& ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)
(*encoded_name_size) =
(ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE
+ encoded_name_no_prefix_size);
@ -1828,9 +1824,8 @@ int ecryptfs_encrypt_and_encode_filename(
kfree(filename);
goto out;
}
if (mount_crypt_stat
&& (mount_crypt_stat->flags
& ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) {
if (mount_crypt_stat->flags
& ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK) {
memcpy((*encoded_name),
ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX,
ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE);
@ -1848,9 +1843,9 @@ int ecryptfs_encrypt_and_encode_filename(
rc = -EOPNOTSUPP;
}
if (rc) {
printk(KERN_ERR "%s: Error attempting to encode "
"encrypted filename; rc = [%d]\n", __func__,
rc);
ecryptfs_printk(KERN_ERR,
"Error attempting to encode encrypted filename; rc = [%d]\n",
rc);
kfree((*encoded_name));
(*encoded_name) = NULL;
(*encoded_name_size) = 0;
@ -1925,8 +1920,7 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,
decoded_name_size);
if (rc) {
ecryptfs_printk(KERN_DEBUG,
"%s: Could not parse tag 70 packet from filename\n",
__func__);
"Could not parse tag 70 packet from filename\n");
goto out_free;
}
} else {

View File

@ -7,6 +7,7 @@
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
*/
#include <linux/string.h>
#include "ecryptfs_kernel.h"
/*
@ -33,9 +34,7 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
ECRYPTFS_PERSISTENT_PASSWORD) {
ecryptfs_printk(KERN_DEBUG, " * persistent\n");
}
memcpy(sig, auth_tok->token.password.signature,
ECRYPTFS_SIG_SIZE_HEX);
sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
strscpy(sig, auth_tok->token.password.signature);
ecryptfs_printk(KERN_DEBUG, " * signature = [%s]\n", sig);
}
ecryptfs_printk(KERN_DEBUG, " * session_key.flags = [0x%x]\n",

View File

@ -677,6 +677,20 @@ static const char *ecryptfs_get_link(struct dentry *dentry,
return buf;
}
static void ecryptfs_iattr_to_lower(struct iattr *lower_ia,
const struct iattr *ia)
{
memcpy(lower_ia, ia, sizeof(*lower_ia));
if (ia->ia_valid & ATTR_FILE)
lower_ia->ia_file = ecryptfs_file_to_lower(ia->ia_file);
/*
* If the mode change is for clearing setuid/setgid bits, allow the lower
* file system to interpret this in its own way.
*/
if (lower_ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
lower_ia->ia_valid &= ~ATTR_MODE;
}
/**
* upper_size_to_lower_size
* @crypt_stat: Crypt_stat associated with file
@ -707,127 +721,113 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
}
/**
* truncate_upper
* __ecryptfs_truncate
* @dentry: The ecryptfs layer dentry
* @ia: Address of the ecryptfs inode's attributes
* @lower_ia: Address of the lower inode's attributes
*
* Function to handle truncations modifying the size of the file. Note
* that the file sizes are interpolated. When expanding, we are simply
* writing strings of 0's out. When truncating, we truncate the upper
* inode and update the lower_ia according to the page index
* interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return,
* the caller must use lower_ia in a call to notify_change() to perform
* the truncation of the lower inode.
* Handle truncations modifying the size of the file. Note that the file sizes
* are interpolated. When expanding, we are simply writing strings of 0's out.
* When truncating, we truncate the upper inode and update the lower_ia
* according to the page index interpolations.
*
* Returns zero on success; non-zero otherwise
*/
static int truncate_upper(struct dentry *dentry, struct iattr *ia,
struct iattr *lower_ia)
static int __ecryptfs_truncate(struct dentry *dentry, const struct iattr *ia)
{
int rc = 0;
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
struct inode *inode = d_inode(dentry);
struct ecryptfs_crypt_stat *crypt_stat;
loff_t i_size = i_size_read(inode);
loff_t lower_size_before_truncate;
loff_t lower_size_after_truncate;
struct iattr lower_ia;
size_t num_zeros;
int rc;
if (unlikely((ia->ia_size == i_size))) {
lower_ia->ia_valid &= ~ATTR_SIZE;
ecryptfs_iattr_to_lower(&lower_ia, ia);
if (unlikely((ia->ia_size == i_size)))
return 0;
}
rc = ecryptfs_get_lower_file(dentry, inode);
if (rc)
return rc;
crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
/* Switch on growing or shrinking file */
if (ia->ia_size > i_size) {
char zero[] = { 0x00 };
lower_ia->ia_valid &= ~ATTR_SIZE;
/* Write a single 0 at the last position of the file;
* this triggers code that will fill in 0's throughout
* the intermediate portion of the previous end of the
* file and the new and of the file */
rc = ecryptfs_write(inode, zero,
(ia->ia_size - 1), 1);
} else { /* ia->ia_size < i_size_read(inode) */
/* We're chopping off all the pages down to the page
* in which ia->ia_size is located. Fill in the end of
* that page from (ia->ia_size & ~PAGE_MASK) to
* PAGE_SIZE with zeros. */
size_t num_zeros = (PAGE_SIZE
- (ia->ia_size & ~PAGE_MASK));
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
truncate_setsize(inode, ia->ia_size);
lower_ia->ia_size = ia->ia_size;
lower_ia->ia_valid |= ATTR_SIZE;
goto out;
}
if (num_zeros) {
char *zeros_virt;
zeros_virt = kzalloc(num_zeros, GFP_KERNEL);
if (!zeros_virt) {
rc = -ENOMEM;
goto out;
}
rc = ecryptfs_write(inode, zeros_virt,
ia->ia_size, num_zeros);
kfree(zeros_virt);
if (rc) {
printk(KERN_ERR "Error attempting to zero out "
"the remainder of the end page on "
"reducing truncate; rc = [%d]\n", rc);
goto out;
}
}
truncate_setsize(inode, ia->ia_size);
rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
printk(KERN_ERR "Problem with "
"ecryptfs_write_inode_size_to_metadata; "
"rc = [%d]\n", rc);
goto out;
}
/* We are reducing the size of the ecryptfs file, and need to
* know if we need to reduce the size of the lower file. */
lower_size_before_truncate =
upper_size_to_lower_size(crypt_stat, i_size);
lower_size_after_truncate =
upper_size_to_lower_size(crypt_stat, ia->ia_size);
if (lower_size_after_truncate < lower_size_before_truncate) {
lower_ia->ia_size = lower_size_after_truncate;
lower_ia->ia_valid |= ATTR_SIZE;
} else
lower_ia->ia_valid &= ~ATTR_SIZE;
}
out:
ecryptfs_put_lower_file(inode);
return rc;
}
static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
{
struct ecryptfs_crypt_stat *crypt_stat;
loff_t lower_oldsize, lower_newsize;
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
lower_oldsize = upper_size_to_lower_size(crypt_stat,
i_size_read(inode));
lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
if (lower_newsize > lower_oldsize) {
lower_size_before_truncate =
upper_size_to_lower_size(crypt_stat, i_size);
lower_size_after_truncate =
upper_size_to_lower_size(crypt_stat, ia->ia_size);
if (lower_size_after_truncate > lower_size_before_truncate) {
/*
* The eCryptfs inode and the new *lower* size are mixed here
* because we may not have the lower i_mutex held and/or it may
* not be appropriate to call inode_newsize_ok() with inodes
* from other filesystems.
*/
return inode_newsize_ok(inode, lower_newsize);
rc = inode_newsize_ok(inode, lower_size_after_truncate);
if (rc)
return rc;
}
return 0;
rc = ecryptfs_get_lower_file(dentry, inode);
if (rc)
return rc;
if (ia->ia_size > i_size) {
char zero[] = { 0x00 };
/*
* Write a single 0 at the last position of the file; this
* triggers code that will fill in 0's throughout the
* intermediate portion of the previous end of the file and the
* new end of the file.
*/
rc = ecryptfs_write(inode, zero, ia->ia_size - 1, 1);
goto out;
}
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
truncate_setsize(inode, ia->ia_size);
lower_ia.ia_size = ia->ia_size;
goto set_size;
}
/*
* We're chopping off all the pages down to the page in which
* ia->ia_size is located. Fill in the end of that page from
* (ia->ia_size & ~PAGE_MASK) to PAGE_SIZE with zeros.
*/
num_zeros = PAGE_SIZE - (ia->ia_size & ~PAGE_MASK);
if (num_zeros) {
rc = ecryptfs_write(inode, page_address(ZERO_PAGE(0)),
ia->ia_size, num_zeros);
if (rc) {
pr_err("Error attempting to zero out the remainder of the end page on reducing truncate; rc = [%d]\n",
rc);
goto out;
}
}
truncate_setsize(inode, ia->ia_size);
rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
pr_err("Problem with ecryptfs_write_inode_size_to_metadata; rc = [%d]\n",
rc);
goto out;
}
/*
* We are reducing the size of the ecryptfs file, and need to know if we
* need to reduce the size of the lower file.
*/
if (lower_size_after_truncate >= lower_size_before_truncate)
goto out;
lower_ia.ia_size = lower_size_after_truncate;
set_size:
lower_ia.ia_valid |= ATTR_SIZE;
inode_lock(d_inode(lower_dentry));
rc = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL);
inode_unlock(d_inode(lower_dentry));
out:
ecryptfs_put_lower_file(inode);
return rc;
}
/**
@ -842,24 +842,12 @@ static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
*/
int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
{
struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length };
struct iattr lower_ia = { .ia_valid = 0 };
int rc;
const struct iattr ia = {
.ia_valid = ATTR_SIZE,
.ia_size = new_length,
};
rc = ecryptfs_inode_newsize_ok(d_inode(dentry), new_length);
if (rc)
return rc;
rc = truncate_upper(dentry, &ia, &lower_ia);
if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
inode_lock(d_inode(lower_dentry));
rc = notify_change(&nop_mnt_idmap, lower_dentry,
&lower_ia, NULL);
inode_unlock(d_inode(lower_dentry));
}
return rc;
return __ecryptfs_truncate(dentry, &ia);
}
static int
@ -886,25 +874,22 @@ ecryptfs_permission(struct mnt_idmap *idmap, struct inode *inode,
static int ecryptfs_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, struct iattr *ia)
{
int rc = 0;
struct dentry *lower_dentry;
struct iattr lower_ia;
struct inode *inode;
struct inode *lower_inode;
struct inode *inode = d_inode(dentry);
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
struct ecryptfs_crypt_stat *crypt_stat;
int rc;
crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
ecryptfs_init_crypt_stat(crypt_stat);
inode = d_inode(dentry);
lower_inode = ecryptfs_inode_to_lower(inode);
lower_dentry = ecryptfs_dentry_to_lower(dentry);
mutex_lock(&crypt_stat->cs_mutex);
if (d_is_dir(dentry))
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
else if (d_is_reg(dentry)
&& (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
|| !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) {
else if (d_is_reg(dentry) &&
(!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) ||
!(crypt_stat->flags & ECRYPTFS_KEY_VALID))) {
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
mount_crypt_stat = &ecryptfs_superblock_to_private(
@ -917,8 +902,8 @@ static int ecryptfs_setattr(struct mnt_idmap *idmap,
rc = ecryptfs_read_metadata(dentry);
ecryptfs_put_lower_file(inode);
if (rc) {
if (!(mount_crypt_stat->flags
& ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
if (!(mount_crypt_stat->flags &
ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
printk(KERN_WARNING "Either the lower file "
"is not in a valid eCryptfs format, "
@ -938,31 +923,19 @@ static int ecryptfs_setattr(struct mnt_idmap *idmap,
rc = setattr_prepare(&nop_mnt_idmap, dentry, ia);
if (rc)
goto out;
if (ia->ia_valid & ATTR_SIZE) {
rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
if (rc)
goto out;
rc = __ecryptfs_truncate(dentry, ia);
} else {
struct iattr lower_ia;
ecryptfs_iattr_to_lower(&lower_ia, ia);
inode_lock(d_inode(lower_dentry));
rc = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia,
NULL);
inode_unlock(d_inode(lower_dentry));
}
memcpy(&lower_ia, ia, sizeof(lower_ia));
if (ia->ia_valid & ATTR_FILE)
lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
if (ia->ia_valid & ATTR_SIZE) {
rc = truncate_upper(dentry, ia, &lower_ia);
if (rc < 0)
goto out;
}
/*
* mode change is for clearing setuid/setgid bits. Allow lower fs
* to interpret this in its own way.
*/
if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
lower_ia.ia_valid &= ~ATTR_MODE;
inode_lock(d_inode(lower_dentry));
rc = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL);
inode_unlock(d_inode(lower_dentry));
out:
fsstack_copy_attr_all(inode, lower_inode);
return rc;

View File

@ -2458,8 +2458,7 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)
if (!new_key_sig)
return -ENOMEM;
memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX);
new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
strscpy(new_key_sig->keysig, sig);
/* Caller must hold keysig_list_mutex */
list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list);
@ -2479,9 +2478,8 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
if (!new_auth_tok)
return -ENOMEM;
memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX);
strscpy(new_auth_tok->sig, sig);
new_auth_tok->flags = global_auth_tok_flags;
new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
list_add(&new_auth_tok->mount_crypt_stat_list,
&mount_crypt_stat->global_auth_tok_list);

View File

@ -531,6 +531,7 @@ static int ecryptfs_get_tree(struct fs_context *fc)
s->s_blocksize = path.dentry->d_sb->s_blocksize;
s->s_magic = ECRYPTFS_SUPER_MAGIC;
s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
s->s_time_gran = path.dentry->d_sb->s_time_gran;
rc = -EINVAL;
if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {

View File

@ -6,6 +6,7 @@
* Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
* Tyler Hicks <code@tyhicks.com>
*/
#include <linux/overflow.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/user_namespace.h>
@ -232,7 +233,7 @@ int ecryptfs_process_response(struct ecryptfs_daemon *daemon,
msg_ctx->counter, seq);
goto unlock;
}
msg_size = (sizeof(*msg) + msg->data_len);
msg_size = struct_size(msg, data, msg->data_len);
msg_ctx->msg = kmemdup(msg, msg_size, GFP_KERNEL);
if (!msg_ctx->msg) {
rc = -ENOMEM;

View File

@ -10,6 +10,7 @@
#include <linux/hash.h>
#include <linux/random.h>
#include <linux/miscdevice.h>
#include <linux/overflow.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/wait.h>
@ -148,8 +149,10 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
u16 msg_flags, struct ecryptfs_daemon *daemon)
{
struct ecryptfs_message *msg;
size_t msg_size;
msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL);
msg_size = struct_size(msg, data, data_size);
msg = kmalloc(msg_size, GFP_KERNEL);
if (!msg)
return -ENOMEM;
@ -159,7 +162,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
msg_ctx->msg->data_len = data_size;
msg_ctx->type = msg_type;
memcpy(msg_ctx->msg->data, data, data_size);
msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
msg_ctx->msg_size = msg_size;
list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
mutex_unlock(&msg_ctx->mux);