ext4 crypto: enforce context consistency
Enforce the following inheritance policy: 1) An unencrypted directory may contain encrypted or unencrypted files or directories. 2) All files or directories in a directory must be protected using the same key as their containing directory. As a result, assuming the following setup: mke2fs -t ext4 -Fq -O encrypt /dev/vdc mount -t ext4 /dev/vdc /vdc mkdir /vdc/a /vdc/b /vdc/c echo foo | e4crypt add_key /vdc/a echo bar | e4crypt add_key /vdc/b for i in a b c ; do cp /etc/motd /vdc/$i/motd-$i ; done Then we will see the following results: cd /vdc mv a b # will fail; /vdc/a and /vdc/b have different keys mv b/motd-b a # will fail, see above ln a/motd-a b # will fail, see above mv c a # will fail; all inodes in an encrypted directory # must be encrypted ln c/motd-c b # will fail, see above mv a/motd-a c # will succeed mv c/motd-a a # will succeed Signed-off-by: Michael Halcrow <mhalcrow@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
88bd6ccdcd
commit
d9cdc90331
1 changed files with 23 additions and 1 deletions
|
@ -1416,6 +1416,18 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
|
|||
ino);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
|
||||
(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
|
||||
S_ISLNK(inode->i_mode)) &&
|
||||
!ext4_is_child_context_consistent_with_parent(dir,
|
||||
inode)) {
|
||||
iput(inode);
|
||||
ext4_warning(inode->i_sb,
|
||||
"Inconsistent encryption contexts: %lu/%lu\n",
|
||||
(unsigned long) dir->i_ino,
|
||||
(unsigned long) inode->i_ino);
|
||||
return ERR_PTR(-EPERM);
|
||||
}
|
||||
}
|
||||
return d_splice_alias(inode, dentry);
|
||||
}
|
||||
|
@ -2944,7 +2956,9 @@ static int ext4_link(struct dentry *old_dentry,
|
|||
|
||||
if (inode->i_nlink >= EXT4_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
if (ext4_encrypted_inode(dir) &&
|
||||
!ext4_is_child_context_consistent_with_parent(dir, inode))
|
||||
return -EPERM;
|
||||
dquot_initialize(dir);
|
||||
|
||||
retry:
|
||||
|
@ -3245,6 +3259,14 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino)
|
||||
goto end_rename;
|
||||
|
||||
if ((old.dir != new.dir) &&
|
||||
ext4_encrypted_inode(new.dir) &&
|
||||
!ext4_is_child_context_consistent_with_parent(new.dir,
|
||||
old.inode)) {
|
||||
retval = -EPERM;
|
||||
goto end_rename;
|
||||
}
|
||||
|
||||
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
|
||||
&new.de, &new.inlined);
|
||||
if (IS_ERR(new.bh)) {
|
||||
|
|
Loading…
Reference in a new issue