Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9cdc903 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

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: default avatarMichael Halcrow <mhalcrow@google.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 88bd6ccd
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -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)) {