Commit ff978b09 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4 crypto: move context consistency check to ext4_file_open()

In the case where the per-file key for the directory is cached, but
root does not have access to the key needed to derive the per-file key
for the files in the directory, we allow the lookup to succeed, so
that lstat(2) and unlink(2) can suceed.  However, if a program tries
to open the file, it will get an ENOKEY error.
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 28b4c263
...@@ -350,6 +350,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) ...@@ -350,6 +350,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
struct vfsmount *mnt = filp->f_path.mnt; struct vfsmount *mnt = filp->f_path.mnt;
struct inode *dir = filp->f_path.dentry->d_parent->d_inode;
struct path path; struct path path;
char buf[64], *cp; char buf[64], *cp;
int ret; int ret;
...@@ -393,6 +394,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp) ...@@ -393,6 +394,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
if (ext4_encryption_info(inode) == NULL) if (ext4_encryption_info(inode) == NULL)
return -ENOKEY; return -ENOKEY;
} }
if (ext4_encrypted_inode(dir) &&
!ext4_is_child_context_consistent_with_parent(dir, inode)) {
ext4_warning(inode->i_sb,
"Inconsistent encryption contexts: %lu/%lu\n",
(unsigned long) dir->i_ino,
(unsigned long) inode->i_ino);
return -EPERM;
}
/* /*
* Set up the jbd2_inode if we are opening the inode for * Set up the jbd2_inode if we are opening the inode for
* writing and the journal is present * writing and the journal is present
......
...@@ -1603,11 +1603,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi ...@@ -1603,11 +1603,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
return ERR_PTR(-EFSCORRUPTED); return ERR_PTR(-EFSCORRUPTED);
} }
if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
S_ISLNK(inode->i_mode)) &&
!ext4_is_child_context_consistent_with_parent(dir, !ext4_is_child_context_consistent_with_parent(dir,
inode)) { inode)) {
int nokey = ext4_encrypted_inode(inode) &&
!ext4_encryption_info(inode);
iput(inode); iput(inode);
if (nokey)
return ERR_PTR(-ENOKEY);
ext4_warning(inode->i_sb, ext4_warning(inode->i_sb,
"Inconsistent encryption contexts: %lu/%lu\n", "Inconsistent encryption contexts: %lu/%lu\n",
(unsigned long) dir->i_ino, (unsigned long) dir->i_ino,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment