Fixes for proper ioctl handling and an untriggerable buffer overflow

- The eCryptfs ioctl handling functions should only pass known-good ioctl
   commands to the lower filesystem
 - A static checker found a potential buffer overflow. Upon inspection, it is
   not triggerable due to input validation performed on the mount parameters.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCgAGBQJU94JWAAoJENaSAD2qAscK5z0P/3rrZv7w4rWnPeLfzddRCSpt
 QMCPGGXE2fo3nP9w6e7HirAQKg474CFdmNXbNzAKR08irQNRM9lMMEkUp8B9kwXN
 8Ms+lHPVuTZuBPXkqtpG/p47kAJdc1d9QePa0iU5PPp5GcdI/knPR/Md42NxUd4y
 kqMdgK7brO/y16i5aCC40CG2x+OPc5I8Xz/9MT9fm9+NTRzOxFhbLxis5LKUrQgj
 SnzkXn4Z1jsLt3y8OCFhrP9n9sHrKmcHpxBExa7GziADbIcw+nv/ugQy8Dvi8sHK
 zzO1G21uUlZXfMoWdv+DbwgU6subaT/D6NjcyVEhZ0ziYQDdMMOVvqDUFzwIV9W7
 WiIV2fYLxYlZHSv318BlYTT6XiDVveINUcLI2107cw4pBwMYUt9QY3QoKLQ7027o
 HhdX4Ys6chzwggWU0CRRI7W45/LTF0KeJ3g06tAsYVV6GFGoJAnZe7olHA6X7nGE
 s8rXzpT5zZqdcz7Y5ln5NtrzWBER91iBUDivafw6y7b0rqj6o+fEUk4vXNdsyuzZ
 y5Qn5dus1ImPLwtCAsfqZMjUUnNtOaBPd52k0sHIkRoY6W7GlXZNOjXA7ki+X5tX
 Jq4tm0n3fkInEhjJDQ/sxtPa+TcZGgcoyc3qNsX80Lob7QpaTvBczKFgBadNnMnK
 TKJEvJQuLIlAq3Lw5DGL
 =4fdp
 -----END PGP SIGNATURE-----

Merge tag 'ecryptfs-4.0-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs

Pull eCryptfs fixes from Tyler Hicks:
 "Fixes for proper ioctl handling and an untriggerable buffer overflow

   - The eCryptfs ioctl handling functions should only pass known-good
     ioctl commands to the lower filesystem

   - A static checker found a potential buffer overflow.  Upon
     inspection, it is not triggerable due to input validation performed
     on the mount parameters"

* tag 'ecryptfs-4.0-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
  eCryptfs: don't pass fs-specific ioctl commands through
  eCryptfs: ensure copy to crypt_stat->cipher does not overrun
This commit is contained in:
Linus Torvalds 2015-03-04 14:19:48 -08:00
commit 8a001af4bb
4 changed files with 34 additions and 8 deletions

View File

@ -124,7 +124,7 @@ ecryptfs_get_key_payload_data(struct key *key)
} }
#define ECRYPTFS_MAX_KEYSET_SIZE 1024 #define ECRYPTFS_MAX_KEYSET_SIZE 1024
#define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32 #define ECRYPTFS_MAX_CIPHER_NAME_SIZE 31
#define ECRYPTFS_MAX_NUM_ENC_KEYS 64 #define ECRYPTFS_MAX_NUM_ENC_KEYS 64
#define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */ #define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */
#define ECRYPTFS_SALT_BYTES 2 #define ECRYPTFS_SALT_BYTES 2
@ -237,7 +237,7 @@ struct ecryptfs_crypt_stat {
struct crypto_ablkcipher *tfm; struct crypto_ablkcipher *tfm;
struct crypto_hash *hash_tfm; /* Crypto context for generating struct crypto_hash *hash_tfm; /* Crypto context for generating
* the initialization vectors */ * the initialization vectors */
unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; unsigned char key[ECRYPTFS_MAX_KEY_BYTES];
unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES];
struct list_head keysig_list; struct list_head keysig_list;

View File

@ -303,9 +303,22 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct file *lower_file = ecryptfs_file_to_lower(file); struct file *lower_file = ecryptfs_file_to_lower(file);
long rc = -ENOTTY; long rc = -ENOTTY;
if (lower_file->f_op->unlocked_ioctl) if (!lower_file->f_op->unlocked_ioctl)
return rc;
switch (cmd) {
case FITRIM:
case FS_IOC_GETFLAGS:
case FS_IOC_SETFLAGS:
case FS_IOC_GETVERSION:
case FS_IOC_SETVERSION:
rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
return rc; fsstack_copy_attr_all(file_inode(file), file_inode(lower_file));
return rc;
default:
return rc;
}
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
@ -315,9 +328,22 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct file *lower_file = ecryptfs_file_to_lower(file); struct file *lower_file = ecryptfs_file_to_lower(file);
long rc = -ENOIOCTLCMD; long rc = -ENOIOCTLCMD;
if (lower_file->f_op->compat_ioctl) if (!lower_file->f_op->compat_ioctl)
return rc;
switch (cmd) {
case FITRIM:
case FS_IOC32_GETFLAGS:
case FS_IOC32_SETFLAGS:
case FS_IOC32_GETVERSION:
case FS_IOC32_SETVERSION:
rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
return rc; fsstack_copy_attr_all(file_inode(file), file_inode(lower_file));
return rc;
default:
return rc;
}
} }
#endif #endif

View File

@ -891,7 +891,7 @@ struct ecryptfs_parse_tag_70_packet_silly_stack {
struct blkcipher_desc desc; struct blkcipher_desc desc;
char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
char iv[ECRYPTFS_MAX_IV_BYTES]; char iv[ECRYPTFS_MAX_IV_BYTES];
char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
}; };
/** /**

View File

@ -407,7 +407,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
if (!cipher_name_set) { if (!cipher_name_set) {
int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER); int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE); BUG_ON(cipher_name_len > ECRYPTFS_MAX_CIPHER_NAME_SIZE);
strcpy(mount_crypt_stat->global_default_cipher_name, strcpy(mount_crypt_stat->global_default_cipher_name,
ECRYPTFS_DEFAULT_CIPHER); ECRYPTFS_DEFAULT_CIPHER);
} }