aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ecryptfs/inode.c
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>2009-03-20 03:23:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-22 14:20:43 -0400
commit2aac0cf88681bfa092f731553bc7fbd23516be73 (patch)
treeb723cbe9c67b0cafa9081690d03b4ecec038d9f6 /fs/ecryptfs/inode.c
parent8faece5f906725c10e7a1f6caf84452abadbdc7b (diff)
eCryptfs: NULL crypt_stat dereference during lookup
If ecryptfs_encrypted_view or ecryptfs_xattr_metadata were being specified as mount options, a NULL pointer dereference of crypt_stat was possible during lookup. This patch moves the crypt_stat assignment into ecryptfs_lookup_and_interpose_lower(), ensuring that crypt_stat will not be NULL before we attempt to dereference it. Thanks to Dan Carpenter and his static analysis tool, smatch, for finding this bug. Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com> Acked-by: Dustin Kirkland <kirkland@canonical.com> Cc: Dan Carpenter <error27@gmail.com> Cc: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ecryptfs/inode.c')
-rw-r--r--fs/ecryptfs/inode.c32
1 files changed, 12 insertions, 20 deletions
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 5697899a168d..55b3145b8072 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -246,7 +246,6 @@ out:
246 */ 246 */
247int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, 247int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
248 struct dentry *lower_dentry, 248 struct dentry *lower_dentry,
249 struct ecryptfs_crypt_stat *crypt_stat,
250 struct inode *ecryptfs_dir_inode, 249 struct inode *ecryptfs_dir_inode,
251 struct nameidata *ecryptfs_nd) 250 struct nameidata *ecryptfs_nd)
252{ 251{
@@ -254,6 +253,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
254 struct vfsmount *lower_mnt; 253 struct vfsmount *lower_mnt;
255 struct inode *lower_inode; 254 struct inode *lower_inode;
256 struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 255 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
256 struct ecryptfs_crypt_stat *crypt_stat;
257 char *page_virt = NULL; 257 char *page_virt = NULL;
258 u64 file_size; 258 u64 file_size;
259 int rc = 0; 259 int rc = 0;
@@ -314,6 +314,11 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
314 goto out_free_kmem; 314 goto out_free_kmem;
315 } 315 }
316 } 316 }
317 crypt_stat = &ecryptfs_inode_to_private(
318 ecryptfs_dentry->d_inode)->crypt_stat;
319 /* TODO: lock for crypt_stat comparison */
320 if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
321 ecryptfs_set_default_sizes(crypt_stat);
317 rc = ecryptfs_read_and_validate_header_region(page_virt, 322 rc = ecryptfs_read_and_validate_header_region(page_virt,
318 ecryptfs_dentry->d_inode); 323 ecryptfs_dentry->d_inode);
319 if (rc) { 324 if (rc) {
@@ -362,9 +367,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
362{ 367{
363 char *encrypted_and_encoded_name = NULL; 368 char *encrypted_and_encoded_name = NULL;
364 size_t encrypted_and_encoded_name_size; 369 size_t encrypted_and_encoded_name_size;
365 struct ecryptfs_crypt_stat *crypt_stat = NULL;
366 struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL; 370 struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
367 struct ecryptfs_inode_info *inode_info;
368 struct dentry *lower_dir_dentry, *lower_dentry; 371 struct dentry *lower_dir_dentry, *lower_dentry;
369 int rc = 0; 372 int rc = 0;
370 373
@@ -388,26 +391,15 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
388 } 391 }
389 if (lower_dentry->d_inode) 392 if (lower_dentry->d_inode)
390 goto lookup_and_interpose; 393 goto lookup_and_interpose;
391 inode_info = ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); 394 mount_crypt_stat = &ecryptfs_superblock_to_private(
392 if (inode_info) { 395 ecryptfs_dentry->d_sb)->mount_crypt_stat;
393 crypt_stat = &inode_info->crypt_stat; 396 if (!(mount_crypt_stat
394 /* TODO: lock for crypt_stat comparison */ 397 && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
395 if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
396 ecryptfs_set_default_sizes(crypt_stat);
397 }
398 if (crypt_stat)
399 mount_crypt_stat = crypt_stat->mount_crypt_stat;
400 else
401 mount_crypt_stat = &ecryptfs_superblock_to_private(
402 ecryptfs_dentry->d_sb)->mount_crypt_stat;
403 if (!(crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES))
404 && !(mount_crypt_stat && (mount_crypt_stat->flags
405 & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)))
406 goto lookup_and_interpose; 398 goto lookup_and_interpose;
407 dput(lower_dentry); 399 dput(lower_dentry);
408 rc = ecryptfs_encrypt_and_encode_filename( 400 rc = ecryptfs_encrypt_and_encode_filename(
409 &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, 401 &encrypted_and_encoded_name, &encrypted_and_encoded_name_size,
410 crypt_stat, mount_crypt_stat, ecryptfs_dentry->d_name.name, 402 NULL, mount_crypt_stat, ecryptfs_dentry->d_name.name,
411 ecryptfs_dentry->d_name.len); 403 ecryptfs_dentry->d_name.len);
412 if (rc) { 404 if (rc) {
413 printk(KERN_ERR "%s: Error attempting to encrypt and encode " 405 printk(KERN_ERR "%s: Error attempting to encrypt and encode "
@@ -426,7 +418,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
426 } 418 }
427lookup_and_interpose: 419lookup_and_interpose:
428 rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry, 420 rc = ecryptfs_lookup_and_interpose_lower(ecryptfs_dentry, lower_dentry,
429 crypt_stat, ecryptfs_dir_inode, 421 ecryptfs_dir_inode,
430 ecryptfs_nd); 422 ecryptfs_nd);
431 goto out; 423 goto out;
432out_d_drop: 424out_d_drop: