diff options
author | Richard Weinberger <richard@nod.at> | 2016-10-20 10:47:56 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-12-12 17:07:38 -0500 |
commit | d475a507457b5cafa428871a473d0dcc828c5f68 (patch) | |
tree | 7f6608195cfc421e6d3d7975cc8b916a55e4a914 | |
parent | 6a5e98ab7d8665d2faddbd91a8a2bf9addb79aff (diff) |
ubifs: Add skeleton for fscrypto
This is the first building block to provide file level
encryption on UBIFS.
Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r-- | fs/ubifs/Kconfig | 11 | ||||
-rw-r--r-- | fs/ubifs/Makefile | 1 | ||||
-rw-r--r-- | fs/ubifs/crypto.c | 46 | ||||
-rw-r--r-- | fs/ubifs/dir.c | 28 | ||||
-rw-r--r-- | fs/ubifs/ioctl.c | 35 | ||||
-rw-r--r-- | fs/ubifs/super.c | 10 | ||||
-rw-r--r-- | fs/ubifs/ubifs-media.h | 2 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 37 | ||||
-rw-r--r-- | fs/ubifs/xattr.c | 10 |
9 files changed, 178 insertions, 2 deletions
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index 7ff7712f284e..0a908ae7af13 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig | |||
@@ -50,3 +50,14 @@ config UBIFS_ATIME_SUPPORT | |||
50 | strictatime is the "heavy", relatime is "lighter", etc. | 50 | strictatime is the "heavy", relatime is "lighter", etc. |
51 | 51 | ||
52 | If unsure, say 'N' | 52 | If unsure, say 'N' |
53 | |||
54 | config UBIFS_FS_ENCRYPTION | ||
55 | bool "UBIFS Encryption" | ||
56 | depends on UBIFS_FS | ||
57 | select FS_ENCRYPTION | ||
58 | default n | ||
59 | help | ||
60 | Enable encryption of UBIFS files and directories. This | ||
61 | feature is similar to ecryptfs, but it is more memory | ||
62 | efficient since it avoids caching the encrypted and | ||
63 | decrypted pages in the page cache. | ||
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile index c54a24360f85..6f3251c2bf08 100644 --- a/fs/ubifs/Makefile +++ b/fs/ubifs/Makefile | |||
@@ -5,3 +5,4 @@ ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o | |||
5 | ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o | 5 | ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o |
6 | ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o | 6 | ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o |
7 | ubifs-y += misc.o | 7 | ubifs-y += misc.o |
8 | ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o | ||
diff --git a/fs/ubifs/crypto.c b/fs/ubifs/crypto.c new file mode 100644 index 000000000000..12a0072bddd3 --- /dev/null +++ b/fs/ubifs/crypto.c | |||
@@ -0,0 +1,46 @@ | |||
1 | #include "ubifs.h" | ||
2 | |||
3 | static int ubifs_crypt_get_context(struct inode *inode, void *ctx, size_t len) | ||
4 | { | ||
5 | return ubifs_xattr_get(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT, | ||
6 | ctx, len); | ||
7 | } | ||
8 | |||
9 | static int ubifs_crypt_set_context(struct inode *inode, const void *ctx, | ||
10 | size_t len, void *fs_data) | ||
11 | { | ||
12 | return ubifs_xattr_set(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT, | ||
13 | ctx, len, 0); | ||
14 | } | ||
15 | |||
16 | static bool ubifs_crypt_empty_dir(struct inode *inode) | ||
17 | { | ||
18 | return ubifs_check_dir_empty(inode) == 0; | ||
19 | } | ||
20 | |||
21 | static unsigned int ubifs_crypt_max_namelen(struct inode *inode) | ||
22 | { | ||
23 | if (S_ISLNK(inode->i_mode)) | ||
24 | return UBIFS_MAX_INO_DATA; | ||
25 | else | ||
26 | return UBIFS_MAX_NLEN; | ||
27 | } | ||
28 | |||
29 | static int ubifs_key_prefix(struct inode *inode, u8 **key) | ||
30 | { | ||
31 | static char prefix[] = "ubifs:"; | ||
32 | |||
33 | *key = prefix; | ||
34 | |||
35 | return sizeof(prefix) - 1; | ||
36 | } | ||
37 | |||
38 | struct fscrypt_operations ubifs_crypt_operations = { | ||
39 | .flags = FS_CFLG_INPLACE_ENCRYPTION, | ||
40 | .get_context = ubifs_crypt_get_context, | ||
41 | .set_context = ubifs_crypt_set_context, | ||
42 | .is_encrypted = ubifs_crypt_is_encrypted, | ||
43 | .empty_dir = ubifs_crypt_empty_dir, | ||
44 | .max_namelen = ubifs_crypt_max_namelen, | ||
45 | .key_prefix = ubifs_key_prefix, | ||
46 | }; | ||
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 14a226d47f4c..2315cb864c39 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -85,11 +85,26 @@ static int inherit_flags(const struct inode *dir, umode_t mode) | |||
85 | * initializes it. Returns new inode in case of success and an error code in | 85 | * initializes it. Returns new inode in case of success and an error code in |
86 | * case of failure. | 86 | * case of failure. |
87 | */ | 87 | */ |
88 | struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, | 88 | struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, |
89 | umode_t mode) | 89 | umode_t mode) |
90 | { | 90 | { |
91 | int err; | ||
91 | struct inode *inode; | 92 | struct inode *inode; |
92 | struct ubifs_inode *ui; | 93 | struct ubifs_inode *ui; |
94 | bool encrypted = false; | ||
95 | |||
96 | if (ubifs_crypt_is_encrypted(dir)) { | ||
97 | err = fscrypt_get_encryption_info(dir); | ||
98 | if (err) { | ||
99 | ubifs_err(c, "fscrypt_get_encryption_info failed: %i", err); | ||
100 | return ERR_PTR(err); | ||
101 | } | ||
102 | |||
103 | if (!fscrypt_has_encryption_key(dir)) | ||
104 | return ERR_PTR(-EPERM); | ||
105 | |||
106 | encrypted = true; | ||
107 | } | ||
93 | 108 | ||
94 | inode = new_inode(c->vfs_sb); | 109 | inode = new_inode(c->vfs_sb); |
95 | ui = ubifs_inode(inode); | 110 | ui = ubifs_inode(inode); |
@@ -165,6 +180,17 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, | |||
165 | */ | 180 | */ |
166 | ui->creat_sqnum = ++c->max_sqnum; | 181 | ui->creat_sqnum = ++c->max_sqnum; |
167 | spin_unlock(&c->cnt_lock); | 182 | spin_unlock(&c->cnt_lock); |
183 | |||
184 | if (encrypted) { | ||
185 | err = fscrypt_inherit_context(dir, inode, &encrypted, true); | ||
186 | if (err) { | ||
187 | ubifs_err(c, "fscrypt_inherit_context failed: %i", err); | ||
188 | make_bad_inode(inode); | ||
189 | iput(inode); | ||
190 | return ERR_PTR(err); | ||
191 | } | ||
192 | } | ||
193 | |||
168 | return inode; | 194 | return inode; |
169 | } | 195 | } |
170 | 196 | ||
diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 3c7b29de0ca7..6bb5b35050de 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c | |||
@@ -181,6 +181,41 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
181 | mnt_drop_write_file(file); | 181 | mnt_drop_write_file(file); |
182 | return err; | 182 | return err; |
183 | } | 183 | } |
184 | case FS_IOC_SET_ENCRYPTION_POLICY: { | ||
185 | #ifdef CONFIG_UBIFS_FS_ENCRYPTION | ||
186 | struct fscrypt_policy policy; | ||
187 | |||
188 | if (copy_from_user(&policy, | ||
189 | (struct fscrypt_policy __user *)arg, | ||
190 | sizeof(policy))) | ||
191 | return -EFAULT; | ||
192 | |||
193 | err = fscrypt_process_policy(file, &policy); | ||
194 | |||
195 | return err; | ||
196 | #else | ||
197 | return -EOPNOTSUPP; | ||
198 | #endif | ||
199 | } | ||
200 | case FS_IOC_GET_ENCRYPTION_POLICY: { | ||
201 | #ifdef CONFIG_UBIFS_FS_ENCRYPTION | ||
202 | struct fscrypt_policy policy; | ||
203 | |||
204 | if (!ubifs_crypt_is_encrypted(inode)) | ||
205 | return -ENOENT; | ||
206 | |||
207 | err = fscrypt_get_policy(inode, &policy); | ||
208 | if (err) | ||
209 | return err; | ||
210 | |||
211 | if (copy_to_user((void __user *)arg, &policy, sizeof(policy))) | ||
212 | return -EFAULT; | ||
213 | |||
214 | return 0; | ||
215 | #else | ||
216 | return -EOPNOTSUPP; | ||
217 | #endif | ||
218 | } | ||
184 | 219 | ||
185 | default: | 220 | default: |
186 | return -ENOTTY; | 221 | return -ENOTTY; |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 4ec051089186..e85d5a47aeac 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -380,6 +380,9 @@ out: | |||
380 | } | 380 | } |
381 | done: | 381 | done: |
382 | clear_inode(inode); | 382 | clear_inode(inode); |
383 | #ifdef CONFIG_UBIFS_FS_ENCRYPTION | ||
384 | fscrypt_put_encryption_info(inode, NULL); | ||
385 | #endif | ||
383 | } | 386 | } |
384 | 387 | ||
385 | static void ubifs_dirty_inode(struct inode *inode, int flags) | 388 | static void ubifs_dirty_inode(struct inode *inode, int flags) |
@@ -1995,6 +1998,12 @@ static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) | |||
1995 | return c; | 1998 | return c; |
1996 | } | 1999 | } |
1997 | 2000 | ||
2001 | #ifndef CONFIG_UBIFS_FS_ENCRYPTION | ||
2002 | struct fscrypt_operations ubifs_crypt_operations = { | ||
2003 | .is_encrypted = ubifs_crypt_is_encrypted, | ||
2004 | }; | ||
2005 | #endif | ||
2006 | |||
1998 | static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | 2007 | static int ubifs_fill_super(struct super_block *sb, void *data, int silent) |
1999 | { | 2008 | { |
2000 | struct ubifs_info *c = sb->s_fs_info; | 2009 | struct ubifs_info *c = sb->s_fs_info; |
@@ -2041,6 +2050,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
2041 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; | 2050 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; |
2042 | sb->s_op = &ubifs_super_operations; | 2051 | sb->s_op = &ubifs_super_operations; |
2043 | sb->s_xattr = ubifs_xattr_handlers; | 2052 | sb->s_xattr = ubifs_xattr_handlers; |
2053 | sb->s_cop = &ubifs_crypt_operations; | ||
2044 | 2054 | ||
2045 | mutex_lock(&c->umount_mutex); | 2055 | mutex_lock(&c->umount_mutex); |
2046 | err = mount_ubifs(c); | 2056 | err = mount_ubifs(c); |
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index d47e9569b3de..aa302b11aec8 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h | |||
@@ -316,6 +316,7 @@ enum { | |||
316 | * UBIFS_APPEND_FL: writes to the inode may only append data | 316 | * UBIFS_APPEND_FL: writes to the inode may only append data |
317 | * UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous | 317 | * UBIFS_DIRSYNC_FL: I/O on this directory inode has to be synchronous |
318 | * UBIFS_XATTR_FL: this inode is the inode for an extended attribute value | 318 | * UBIFS_XATTR_FL: this inode is the inode for an extended attribute value |
319 | * UBIFS_CRYPT_FL: use encryption for this inode | ||
319 | * | 320 | * |
320 | * Note, these are on-flash flags which correspond to ioctl flags | 321 | * Note, these are on-flash flags which correspond to ioctl flags |
321 | * (@FS_COMPR_FL, etc). They have the same values now, but generally, do not | 322 | * (@FS_COMPR_FL, etc). They have the same values now, but generally, do not |
@@ -328,6 +329,7 @@ enum { | |||
328 | UBIFS_APPEND_FL = 0x08, | 329 | UBIFS_APPEND_FL = 0x08, |
329 | UBIFS_DIRSYNC_FL = 0x10, | 330 | UBIFS_DIRSYNC_FL = 0x10, |
330 | UBIFS_XATTR_FL = 0x20, | 331 | UBIFS_XATTR_FL = 0x20, |
332 | UBIFS_CRYPT_FL = 0x40, | ||
331 | }; | 333 | }; |
332 | 334 | ||
333 | /* Inode flag bits used by UBIFS */ | 335 | /* Inode flag bits used by UBIFS */ |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 0f8a3ec6a7fe..27a85015e3ff 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/backing-dev.h> | 38 | #include <linux/backing-dev.h> |
39 | #include <linux/security.h> | 39 | #include <linux/security.h> |
40 | #include <linux/xattr.h> | 40 | #include <linux/xattr.h> |
41 | #include <linux/fscrypto.h> | ||
41 | #include "ubifs-media.h" | 42 | #include "ubifs-media.h" |
42 | 43 | ||
43 | /* Version of this UBIFS implementation */ | 44 | /* Version of this UBIFS implementation */ |
@@ -1724,7 +1725,7 @@ int ubifs_update_time(struct inode *inode, struct timespec *time, int flags); | |||
1724 | #endif | 1725 | #endif |
1725 | 1726 | ||
1726 | /* dir.c */ | 1727 | /* dir.c */ |
1727 | struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, | 1728 | struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, |
1728 | umode_t mode); | 1729 | umode_t mode); |
1729 | int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1730 | int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1730 | struct kstat *stat); | 1731 | struct kstat *stat); |
@@ -1773,10 +1774,44 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf, int in_len, | |||
1773 | int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len, | 1774 | int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len, |
1774 | void *out, int *out_len, int compr_type); | 1775 | void *out, int *out_len, int compr_type); |
1775 | 1776 | ||
1777 | extern struct fscrypt_operations ubifs_crypt_operations; | ||
1778 | |||
1776 | #include "debug.h" | 1779 | #include "debug.h" |
1777 | #include "misc.h" | 1780 | #include "misc.h" |
1778 | #include "key.h" | 1781 | #include "key.h" |
1779 | 1782 | ||
1783 | #ifndef CONFIG_UBIFS_FS_ENCRYPTION | ||
1784 | #define fscrypt_set_d_op(i) | ||
1785 | #define fscrypt_get_ctx fscrypt_notsupp_get_ctx | ||
1786 | #define fscrypt_release_ctx fscrypt_notsupp_release_ctx | ||
1787 | #define fscrypt_encrypt_page fscrypt_notsupp_encrypt_page | ||
1788 | #define fscrypt_decrypt_page fscrypt_notsupp_decrypt_page | ||
1789 | #define fscrypt_decrypt_bio_pages fscrypt_notsupp_decrypt_bio_pages | ||
1790 | #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page | ||
1791 | #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page | ||
1792 | #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range | ||
1793 | #define fscrypt_process_policy fscrypt_notsupp_process_policy | ||
1794 | #define fscrypt_get_policy fscrypt_notsupp_get_policy | ||
1795 | #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context | ||
1796 | #define fscrypt_inherit_context fscrypt_notsupp_inherit_context | ||
1797 | #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info | ||
1798 | #define fscrypt_put_encryption_info fscrypt_notsupp_put_encryption_info | ||
1799 | #define fscrypt_setup_filename fscrypt_notsupp_setup_filename | ||
1800 | #define fscrypt_free_filename fscrypt_notsupp_free_filename | ||
1801 | #define fscrypt_fname_encrypted_size fscrypt_notsupp_fname_encrypted_size | ||
1802 | #define fscrypt_fname_alloc_buffer fscrypt_notsupp_fname_alloc_buffer | ||
1803 | #define fscrypt_fname_free_buffer fscrypt_notsupp_fname_free_buffer | ||
1804 | #define fscrypt_fname_disk_to_usr fscrypt_notsupp_fname_disk_to_usr | ||
1805 | #define fscrypt_fname_usr_to_disk fscrypt_notsupp_fname_usr_to_disk | ||
1806 | #endif | ||
1807 | |||
1808 | static inline bool ubifs_crypt_is_encrypted(struct inode *inode) | ||
1809 | { | ||
1810 | struct ubifs_inode *ui = ubifs_inode(inode); | ||
1811 | |||
1812 | return ui->flags & UBIFS_CRYPT_FL; | ||
1813 | } | ||
1814 | |||
1780 | /* Normal UBIFS messages */ | 1815 | /* Normal UBIFS messages */ |
1781 | __printf(2, 3) | 1816 | __printf(2, 3) |
1782 | void ubifs_msg(const struct ubifs_info *c, const char *fmt, ...); | 1817 | void ubifs_msg(const struct ubifs_info *c, const char *fmt, ...); |
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index 2d09dbeecd58..95a16028bbdb 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c | |||
@@ -158,6 +158,15 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, | |||
158 | host_ui->xattr_size += CALC_XATTR_BYTES(size); | 158 | host_ui->xattr_size += CALC_XATTR_BYTES(size); |
159 | host_ui->xattr_names += nm->len; | 159 | host_ui->xattr_names += nm->len; |
160 | 160 | ||
161 | /* | ||
162 | * We handle UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT here because we | ||
163 | * have to set the UBIFS_CRYPT_FL flag on the host inode. | ||
164 | * To avoid multiple updates of the same inode in the same operation, | ||
165 | * let's do it here. | ||
166 | */ | ||
167 | if (strcmp(nm->name, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) | ||
168 | host_ui->flags |= UBIFS_CRYPT_FL; | ||
169 | |||
161 | err = ubifs_jnl_update(c, host, nm, inode, 0, 1); | 170 | err = ubifs_jnl_update(c, host, nm, inode, 0, 1); |
162 | if (err) | 171 | if (err) |
163 | goto out_cancel; | 172 | goto out_cancel; |
@@ -173,6 +182,7 @@ out_cancel: | |||
173 | host_ui->xattr_size -= CALC_DENT_SIZE(nm->len); | 182 | host_ui->xattr_size -= CALC_DENT_SIZE(nm->len); |
174 | host_ui->xattr_size -= CALC_XATTR_BYTES(size); | 183 | host_ui->xattr_size -= CALC_XATTR_BYTES(size); |
175 | host_ui->xattr_names -= nm->len; | 184 | host_ui->xattr_names -= nm->len; |
185 | host_ui->flags &= ~UBIFS_CRYPT_FL; | ||
176 | mutex_unlock(&host_ui->ui_mutex); | 186 | mutex_unlock(&host_ui->ui_mutex); |
177 | out_free: | 187 | out_free: |
178 | make_bad_inode(inode); | 188 | make_bad_inode(inode); |