Clean up whitespace and fixed a bug in the context inheritance error path
[ext4-patch-queue.git] / encryption-validate-context-consistency
blob0c2fb5c70f63bd5e3c4c45fcbd8f8bb4c2200d2b
1 ext4 crypto: enforce context consistency
3 Enforce the following inheritance policy:
5 1) An unencrypted directory may contain encrypted or unencrypted files
6 or directories.
8 2) All files or directories in a directory must be protected using the
9 same key as their containing directory.
11 As a result, assuming the following setup:
13 mke2fs -t ext4 -Fq -O encrypt /dev/vdc
14 mount -t ext4 /dev/vdc /vdc
15 mkdir /vdc/a /vdc/b /vdc/c
16 echo foo | e4crypt add_key /vdc/a
17 echo bar | e4crypt add_key /vdc/b
18 for i in a b c ; do cp /etc/motd /vdc/$i/motd-$i ; done
20 Then we will see the following results:
22 cd /vdc
23 mv a b                  # will fail; /vdc/a and /vdc/b have different keys
24 mv b/motd-b a           # will fail, see above
25 ln a/motd-a b           # will fail, see above
26 mv c a                  # will fail; all inodes in an encrypted directory
27                         #       must be encrypted
28 ln c/motd-c b           # will fail, see above
29 mv a/motd-a c           # will succeed
30 mv c/motd-a a           # will succeed
32 Signed-off-by: Michael Halcrow <mhalcrow@google.com>
33 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
34 ---
35  fs/ext4/namei.c | 24 +++++++++++++++++++++++-
36  1 file changed, 23 insertions(+), 1 deletion(-)
38 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
39 index 2fb55fd..9939db9 100644
40 --- a/fs/ext4/namei.c
41 +++ b/fs/ext4/namei.c
42 @@ -1417,6 +1417,18 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
43                                          ino);
44                         return ERR_PTR(-EIO);
45                 }
46 +               if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
47 +                   (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
48 +                    S_ISLNK(inode->i_mode)) &&
49 +                   !ext4_is_child_context_consistent_with_parent(dir,
50 +                                                                 inode)) {
51 +                       iput(inode);
52 +                       ext4_warning(inode->i_sb,
53 +                                    "Inconsistent encryption contexts: %lu/%lu\n",
54 +                                    (unsigned long) dir->i_ino,
55 +                                    (unsigned long) inode->i_ino);
56 +                       return ERR_PTR(-EPERM);
57 +               }
58         }
59         return d_splice_alias(inode, dentry);
60  }
61 @@ -2937,7 +2949,9 @@ static int ext4_link(struct dentry *old_dentry,
63         if (inode->i_nlink >= EXT4_LINK_MAX)
64                 return -EMLINK;
66 +       if (ext4_encrypted_inode(dir) &&
67 +           !ext4_is_child_context_consistent_with_parent(dir, inode))
68 +               return -EPERM;
69         dquot_initialize(dir);
71  retry:
72 @@ -3238,6 +3252,14 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
73         if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino)
74                 goto end_rename;
76 +       if ((old.dir != new.dir) &&
77 +           ext4_encrypted_inode(new.dir) &&
78 +           !ext4_is_child_context_consistent_with_parent(new.dir,
79 +                                                         old.inode)) {
80 +               retval = -EPERM;
81 +               goto end_rename;
82 +       }
84         new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
85                                  &new.de, &new.inlined);
86         if (IS_ERR(new.bh)) {