aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorYichong Chen <chenyichong@uniontech.com>2026-07-15 13:20:04 +0800
committerTyler Hicks <code@tyhicks.com>2026-07-20 22:11:14 -0500
commit2602b79c5b3e2f6fce12e38a670f8e3fda4e46a2 (patch)
tree57f16185628fc2496316f15444b8ab3e671604fe
parentecryptfs: hold msg ctx list lock when cleaning daemon queue (diff)
ecryptfs: pass packet set buffer size to parser
ecryptfs_parse_packet_set() receives a pointer into the file header, but it calculates the remaining packet buffer size from PAGE_SIZE - 8. For version 1 headers the packet set starts later in the header, so this can overstate the available buffer. Pass the actual packet set buffer length from the caller and calculate per-packet limits from the remaining bytes in that buffer. Recompute the remaining length after consuming a tag 3 packet before parsing the following tag 11 packet. Fixes: 237fead61998 ("[PATCH] ecryptfs: fs/Makefile and fs/Kconfig") Cc: <stable@vger.kernel.org> Signed-off-by: Yichong Chen <chenyichong@uniontech.com> Signed-off-by: Tyler Hicks <code@tyhicks.com>
-rw-r--r--fs/ecryptfs/crypto.c2
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h3
-rw-r--r--fs/ecryptfs/keystore.c23
3 files changed, 23 insertions, 5 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 74b02b55e3f6..e67119b6029c 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1197,7 +1197,7 @@ static int ecryptfs_read_headers_virt(char *page_virt,
} else
set_default_header_data(crypt_stat);
rc = ecryptfs_parse_packet_set(crypt_stat, (page_virt + offset),
- ecryptfs_dentry);
+ PAGE_SIZE - offset, ecryptfs_dentry);
out:
return rc;
}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index f4f56a92bd56..7d2488a10b17 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -580,7 +580,8 @@ int ecryptfs_generate_key_packet_set(char *dest_base,
size_t *len, size_t max);
int
ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
- unsigned char *src, struct dentry *ecryptfs_dentry);
+ unsigned char *src, size_t src_size,
+ struct dentry *ecryptfs_dentry);
int ecryptfs_truncate(struct dentry *dentry, loff_t new_length);
ssize_t
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index e200ab0eba16..6402c0cdb7f4 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1714,6 +1714,7 @@ out:
* ecryptfs_parse_packet_set
* @crypt_stat: The cryptographic context
* @src: Virtual address of region of memory containing the packets
+ * @src_size: Size of the packet set buffer
* @ecryptfs_dentry: The eCryptfs dentry associated with the packet set
*
* Get crypt_stat to have the file's session key if the requisite key
@@ -1724,7 +1725,7 @@ out:
* conditions.
*/
int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
- unsigned char *src,
+ unsigned char *src, size_t src_size,
struct dentry *ecryptfs_dentry)
{
size_t i = 0;
@@ -1746,7 +1747,11 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
* added the our &auth_tok_list */
next_packet_is_auth_tok_packet = 1;
while (next_packet_is_auth_tok_packet) {
- size_t max_packet_size = ((PAGE_SIZE - 8) - i);
+ size_t max_packet_size;
+
+ if (i >= src_size)
+ break;
+ max_packet_size = src_size - i;
switch (src[i]) {
case ECRYPTFS_TAG_3_PACKET_TYPE:
@@ -1761,12 +1766,16 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
goto out_wipe_list;
}
i += packet_size;
+ if (i > src_size) {
+ rc = -EIO;
+ goto out_wipe_list;
+ }
rc = parse_tag_11_packet((unsigned char *)&src[i],
sig_tmp_space,
ECRYPTFS_SIG_SIZE,
&tag_11_contents_size,
&tag_11_packet_size,
- max_packet_size);
+ src_size - i);
if (rc) {
ecryptfs_printk(KERN_ERR, "No valid "
"(ecryptfs-specific) literal "
@@ -1778,6 +1787,10 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
goto out_wipe_list;
}
i += tag_11_packet_size;
+ if (i > src_size) {
+ rc = -EIO;
+ goto out_wipe_list;
+ }
if (ECRYPTFS_SIG_SIZE != tag_11_contents_size) {
ecryptfs_printk(KERN_ERR, "Expected "
"signature of size [%d]; "
@@ -1803,6 +1816,10 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
goto out_wipe_list;
}
i += packet_size;
+ if (i > src_size) {
+ rc = -EIO;
+ goto out_wipe_list;
+ }
crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
break;
case ECRYPTFS_TAG_11_PACKET_TYPE: