aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2015-04-12 00:55:08 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-04-12 00:55:08 -0400
commitd9cdc903318171571f1cd1e5737fd0cab94186be (patch)
tree5baa3a2fbd4a544fcf7ac7e5546b4b6a2ea25587 /fs/ext4/namei.c
parent88bd6ccdcdd638faa11e9746affc21d5f2fe2acf (diff)
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>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 0dbd2d2937f7..acd79198b800 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1416,6 +1416,18 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
1416 ino); 1416 ino);
1417 return ERR_PTR(-EIO); 1417 return ERR_PTR(-EIO);
1418 } 1418 }
1419 if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
1420 (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
1421 S_ISLNK(inode->i_mode)) &&
1422 !ext4_is_child_context_consistent_with_parent(dir,
1423 inode)) {
1424 iput(inode);
1425 ext4_warning(inode->i_sb,
1426 "Inconsistent encryption contexts: %lu/%lu\n",
1427 (unsigned long) dir->i_ino,
1428 (unsigned long) inode->i_ino);
1429 return ERR_PTR(-EPERM);
1430 }
1419 } 1431 }
1420 return d_splice_alias(inode, dentry); 1432 return d_splice_alias(inode, dentry);
1421} 1433}
@@ -2944,7 +2956,9 @@ static int ext4_link(struct dentry *old_dentry,
2944 2956
2945 if (inode->i_nlink >= EXT4_LINK_MAX) 2957 if (inode->i_nlink >= EXT4_LINK_MAX)
2946 return -EMLINK; 2958 return -EMLINK;
2947 2959 if (ext4_encrypted_inode(dir) &&
2960 !ext4_is_child_context_consistent_with_parent(dir, inode))
2961 return -EPERM;
2948 dquot_initialize(dir); 2962 dquot_initialize(dir);
2949 2963
2950retry: 2964retry:
@@ -3245,6 +3259,14 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3245 if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) 3259 if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino)
3246 goto end_rename; 3260 goto end_rename;
3247 3261
3262 if ((old.dir != new.dir) &&
3263 ext4_encrypted_inode(new.dir) &&
3264 !ext4_is_child_context_consistent_with_parent(new.dir,
3265 old.inode)) {
3266 retval = -EPERM;
3267 goto end_rename;
3268 }
3269
3248 new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, 3270 new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
3249 &new.de, &new.inlined); 3271 &new.de, &new.inlined);
3250 if (IS_ERR(new.bh)) { 3272 if (IS_ERR(new.bh)) {