Skip to content

Commit 7799953

Browse files
ubifs: Implement encrypt/decrypt for all IO
Signed-off-by: Richard Weinberger <[email protected]> Signed-off-by: David Gstir <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent 1ee7787 commit 7799953

File tree

5 files changed

+152
-28
lines changed

5 files changed

+152
-28
lines changed

fs/ubifs/crypto.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,57 @@ static int ubifs_key_prefix(struct inode *inode, u8 **key)
3535
return sizeof(prefix) - 1;
3636
}
3737

38+
int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn,
39+
unsigned int in_len, unsigned int *out_len, int block)
40+
{
41+
struct ubifs_info *c = inode->i_sb->s_fs_info;
42+
void *p = &dn->data;
43+
struct page *ret;
44+
unsigned int pad_len = round_up(in_len, UBIFS_CIPHER_BLOCK_SIZE);
45+
46+
ubifs_assert(pad_len <= *out_len);
47+
dn->compr_size = cpu_to_le16(in_len);
48+
49+
/* pad to full block cipher length */
50+
if (pad_len != in_len)
51+
memset(p + in_len, 0, pad_len - in_len);
52+
53+
ret = fscrypt_encrypt_page(inode, virt_to_page(&dn->data), pad_len,
54+
offset_in_page(&dn->data), block, GFP_NOFS);
55+
if (IS_ERR(ret)) {
56+
ubifs_err(c, "fscrypt_encrypt_page failed: %ld", PTR_ERR(ret));
57+
return PTR_ERR(ret);
58+
}
59+
*out_len = pad_len;
60+
61+
return 0;
62+
}
63+
64+
int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
65+
unsigned int *out_len, int block)
66+
{
67+
struct ubifs_info *c = inode->i_sb->s_fs_info;
68+
int err;
69+
unsigned int clen = le16_to_cpu(dn->compr_size);
70+
unsigned int dlen = *out_len;
71+
72+
if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || clen > dlen) {
73+
ubifs_err(c, "bad compr_size: %i", clen);
74+
return -EINVAL;
75+
}
76+
77+
ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
78+
err = fscrypt_decrypt_page(inode, virt_to_page(&dn->data), dlen,
79+
offset_in_page(&dn->data), block);
80+
if (err) {
81+
ubifs_err(c, "fscrypt_decrypt_page failed: %i", err);
82+
return err;
83+
}
84+
*out_len = clen;
85+
86+
return 0;
87+
}
88+
3889
struct fscrypt_operations ubifs_crypt_operations = {
3990
.flags = FS_CFLG_INPLACE_ENCRYPTION,
4091
.get_context = ubifs_crypt_get_context,

fs/ubifs/file.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
7878
goto dump;
7979

8080
dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
81+
82+
if (ubifs_crypt_is_encrypted(inode)) {
83+
err = ubifs_decrypt(inode, dn, &dlen, block);
84+
if (err)
85+
goto dump;
86+
}
87+
8188
out_len = UBIFS_BLOCK_SIZE;
8289
err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
8390
le16_to_cpu(dn->compr_type));
@@ -650,6 +657,13 @@ static int populate_page(struct ubifs_info *c, struct page *page,
650657

651658
dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
652659
out_len = UBIFS_BLOCK_SIZE;
660+
661+
if (ubifs_crypt_is_encrypted(inode)) {
662+
err = ubifs_decrypt(inode, dn, &dlen, page_block);
663+
if (err)
664+
goto out_err;
665+
}
666+
653667
err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
654668
le16_to_cpu(dn->compr_type));
655669
if (err || len != out_len)

fs/ubifs/journal.c

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -688,14 +688,18 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
688688
const union ubifs_key *key, const void *buf, int len)
689689
{
690690
struct ubifs_data_node *data;
691-
int err, lnum, offs, compr_type, out_len;
691+
int err, lnum, offs, compr_type, out_len, compr_len;
692692
int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
693693
struct ubifs_inode *ui = ubifs_inode(inode);
694+
bool encrypted = ubifs_crypt_is_encrypted(inode);
694695

695696
dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
696697
(unsigned long)key_inum(c, key), key_block(c, key), len);
697698
ubifs_assert(len <= UBIFS_BLOCK_SIZE);
698699

700+
if (encrypted)
701+
dlen += UBIFS_CIPHER_BLOCK_SIZE;
702+
699703
data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
700704
if (!data) {
701705
/*
@@ -720,9 +724,18 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
720724
else
721725
compr_type = ui->compr_type;
722726

723-
out_len = dlen - UBIFS_DATA_NODE_SZ;
724-
ubifs_compress(c, buf, len, &data->data, &out_len, &compr_type);
725-
ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
727+
out_len = compr_len = dlen - UBIFS_DATA_NODE_SZ;
728+
ubifs_compress(c, buf, len, &data->data, &compr_len, &compr_type);
729+
ubifs_assert(compr_len <= UBIFS_BLOCK_SIZE);
730+
731+
if (encrypted) {
732+
err = ubifs_encrypt(inode, data, compr_len, &out_len, key_block(c, key));
733+
if (err)
734+
goto out_free;
735+
736+
} else {
737+
data->compr_size = 0;
738+
}
726739

727740
dlen = UBIFS_DATA_NODE_SZ + out_len;
728741
data->compr_type = cpu_to_le16(compr_type);
@@ -1241,31 +1254,55 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
12411254
}
12421255

12431256
/**
1244-
* recomp_data_node - re-compress a truncated data node.
1257+
* truncate_data_node - re-compress/encrypt a truncated data node.
1258+
* @c: UBIFS file-system description object
1259+
* @inode: inode which referes to the data node
1260+
* @block: data block number
12451261
* @dn: data node to re-compress
12461262
* @new_len: new length
12471263
*
12481264
* This function is used when an inode is truncated and the last data node of
1249-
* the inode has to be re-compressed and re-written.
1265+
* the inode has to be re-compressed/encrypted and re-written.
12501266
*/
1251-
static int recomp_data_node(const struct ubifs_info *c,
1252-
struct ubifs_data_node *dn, int *new_len)
1267+
static int truncate_data_node(const struct ubifs_info *c, const struct inode *inode,
1268+
unsigned int block, struct ubifs_data_node *dn,
1269+
int *new_len)
12531270
{
12541271
void *buf;
1255-
int err, len, compr_type, out_len;
1272+
int err, dlen, compr_type, out_len, old_dlen;
12561273

12571274
out_len = le32_to_cpu(dn->size);
12581275
buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS);
12591276
if (!buf)
12601277
return -ENOMEM;
12611278

1262-
len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
1279+
dlen = old_dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
12631280
compr_type = le16_to_cpu(dn->compr_type);
1264-
err = ubifs_decompress(c, &dn->data, len, buf, &out_len, compr_type);
1265-
if (err)
1266-
goto out;
12671281

1268-
ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type);
1282+
if (ubifs_crypt_is_encrypted(inode)) {
1283+
err = ubifs_decrypt(inode, dn, &dlen, block);
1284+
if (err)
1285+
goto out;
1286+
}
1287+
1288+
if (compr_type != UBIFS_COMPR_NONE) {
1289+
err = ubifs_decompress(c, &dn->data, dlen, buf, &out_len, compr_type);
1290+
if (err)
1291+
goto out;
1292+
1293+
ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type);
1294+
}
1295+
1296+
if (ubifs_crypt_is_encrypted(inode)) {
1297+
err = ubifs_encrypt(inode, dn, out_len, &old_dlen, block);
1298+
if (err)
1299+
goto out;
1300+
1301+
out_len = old_dlen;
1302+
} else {
1303+
dn->compr_size = 0;
1304+
}
1305+
12691306
ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
12701307
dn->compr_type = cpu_to_le16(compr_type);
12711308
dn->size = cpu_to_le32(*new_len);
@@ -1337,16 +1374,9 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
13371374
if (le32_to_cpu(dn->size) <= dlen)
13381375
dlen = 0; /* Nothing to do */
13391376
else {
1340-
int compr_type = le16_to_cpu(dn->compr_type);
1341-
1342-
if (compr_type != UBIFS_COMPR_NONE) {
1343-
err = recomp_data_node(c, dn, &dlen);
1344-
if (err)
1345-
goto out_free;
1346-
} else {
1347-
dn->size = cpu_to_le32(dlen);
1348-
dlen += UBIFS_DATA_NODE_SZ;
1349-
}
1377+
err = truncate_data_node(c, inode, blk, dn, &dlen);
1378+
if (err)
1379+
goto out_free;
13501380
}
13511381
}
13521382
}

fs/ubifs/super.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,8 @@ static int mount_ubifs(struct ubifs_info *c)
12101210
bu_init(c);
12111211

12121212
if (!c->ro_mount) {
1213-
c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ,
1213+
c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ + \
1214+
UBIFS_CIPHER_BLOCK_SIZE,
12141215
GFP_KERNEL);
12151216
if (!c->write_reserve_buf)
12161217
goto out_free;
@@ -1623,7 +1624,8 @@ static int ubifs_remount_rw(struct ubifs_info *c)
16231624
goto out;
16241625
}
16251626

1626-
c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ, GFP_KERNEL);
1627+
c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ + \
1628+
UBIFS_CIPHER_BLOCK_SIZE, GFP_KERNEL);
16271629
if (!c->write_reserve_buf) {
16281630
err = -ENOMEM;
16291631
goto out;

fs/ubifs/ubifs.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@
135135
*/
136136
#define WORST_COMPR_FACTOR 2
137137

138+
#ifdef CONFIG_UBIFS_FS_ENCRYPTION
139+
#define UBIFS_CIPHER_BLOCK_SIZE FS_CRYPTO_BLOCK_SIZE
140+
#else
141+
#define UBIFS_CIPHER_BLOCK_SIZE 0
142+
#endif
143+
138144
/*
139145
* How much memory is needed for a buffer where we compress a data node.
140146
*/
@@ -1774,8 +1780,6 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf, int in_len,
17741780
int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
17751781
void *out, int *out_len, int compr_type);
17761782

1777-
extern struct fscrypt_operations ubifs_crypt_operations;
1778-
17791783
#include "debug.h"
17801784
#include "misc.h"
17811785
#include "key.h"
@@ -1803,8 +1807,31 @@ extern struct fscrypt_operations ubifs_crypt_operations;
18031807
#define fscrypt_fname_free_buffer fscrypt_notsupp_fname_free_buffer
18041808
#define fscrypt_fname_disk_to_usr fscrypt_notsupp_fname_disk_to_usr
18051809
#define fscrypt_fname_usr_to_disk fscrypt_notsupp_fname_usr_to_disk
1810+
static inline int ubifs_encrypt(const struct inode *inode,
1811+
struct ubifs_data_node *dn,
1812+
unsigned int in_len, unsigned int *out_len,
1813+
int block)
1814+
{
1815+
ubifs_assert(0);
1816+
return -EOPNOTSUPP;
1817+
}
1818+
static inline int ubifs_decrypt(const struct inode *inode,
1819+
struct ubifs_data_node *dn,
1820+
unsigned int *out_len, int block)
1821+
{
1822+
ubifs_assert(0);
1823+
return -EOPNOTSUPP;
1824+
}
1825+
#else
1826+
/* crypto.c */
1827+
int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn,
1828+
unsigned int in_len, unsigned int *out_len, int block);
1829+
int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
1830+
unsigned int *out_len, int block);
18061831
#endif
18071832

1833+
extern struct fscrypt_operations ubifs_crypt_operations;
1834+
18081835
static inline bool __ubifs_crypt_is_encrypted(struct inode *inode)
18091836
{
18101837
struct ubifs_inode *ui = ubifs_inode(inode);

0 commit comments

Comments
 (0)