RISE-2009003 Linux eCryptfs parse_tag_3_packet Encrypted Key Buffer Overflow Vulnerability http://risesecurity.org/advisories/RISE-2009003.txt Published: July 28, 2009 Updated: July 28, 2009 INTRODUCTION There exists a vulnerability within a function of Linux eCryptfs (Enterprise Cryptographic Filesystem), which when properly exploited can lead to compromise of the vulnerable system. This vulnerability was confirmed by us in the Linux kernel version 2.6.30.3. Linux kernel versions 2.6.19 and later have eCryptfs support and may be also affected. DETAILS eCryptfs is a POSIX-compliant enterprise-class stacked cryptographic filesystem for Linux. It is derived from Erez Zadok's Cryptfs, implemented through the FiST framework for generating stacked filesystems. eCryptfs extends Cryptfs to provide advanced key management and policy features. eCryptfs stores cryptographic metadata in the header of each file written, so that encrypted files can be copied between hosts; the file will be decryptable with the proper key, and there is no need to keep track of any additional information aside from what is already in the encrypted file itself. Think of eCryptfs as a sort of ``gnupgfs.'' The parse_tag_3_packet function of eCryptfs in-kernel key management code does not check if the tag 3 packet contains a encrypted key size larger than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES, before copying the encrypted key to the new_auth_tok structure, resulting in a kernel heap-based buffer overflow vulnerability. fs/ecryptfs/keystore.c -- static int parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *data, struct list_head *auth_tok_list, struct ecryptfs_auth_tok **new_auth_tok, size_t *packet_size, size_t max_packet_size) { size_t body_size; struct ecryptfs_auth_tok_list_item *auth_tok_list_item; size_t length_size; int rc = 0; ... /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or * at end of function upon failure */ auth_tok_list_item = kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); if (!auth_tok_list_item) { printk(KERN_ERR "Unable to allocate memory\n"); rc = -ENOMEM; goto out; } (*new_auth_tok) = &auth_tok_list_item->auth_tok; rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size, &length_size); if (rc) { printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n", rc); goto out_free; } ... (*new_auth_tok)->session_key.encrypted_key_size = (body_size - (ECRYPTFS_SALT_SIZE + 5)); if (unlikely(data[(*packet_size)++] != 0x04)) { printk(KERN_WARNING "Unknown version number [%d]\n", data[(*packet_size) - 1]); rc = -EINVAL; goto out_free; } ... /* Friendly reminder: * (*new_auth_tok)->session_key.encrypted_key_size = * (body_size - (ECRYPTFS_SALT_SIZE + 5)); */ memcpy((*new_auth_tok)->session_key.encrypted_key, &data[(*packet_size)], (*new_auth_tok)->session_key.encrypted_key_size); (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; ... -- VENDOR A patch for this vulnerability was sent to the Linux kernel mailing list by Ramon de Carvalho Valle and Tyler Hicks . CREDITS This vulnerability was discovered by Ramon de Carvalho Valle . DISCLAIMER The authors reserve the right not to be responsible for the topicality, correctness, completeness or quality of the information provided in this document. Liability claims regarding damage caused by the use of any information provided, including any kind of information which is incomplete or incorrect, will therefore be rejected.