aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ubifs/journal.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-09-07 08:36:36 -0400
committerRichard Weinberger <richard@nod.at>2018-10-23 07:48:39 -0400
commit6a98bc4614de8fac8c6d520a6b20b194e23c9936 (patch)
tree768d9f175e5f658f1d38481f3ecdd9fb18ffdbef /fs/ubifs/journal.c
parent16a26b20d2afd0cf063816725b45b12e78d5bb31 (diff)
ubifs: Add authentication nodes to journal
Nodes that are written to flash can only be authenticated through the index after the next commit. When a journal replay is necessary the nodes are not yet referenced by the index and thus can't be authenticated. This patch overcomes this situation by creating a hash over all nodes beginning from the commit start node over the reference node(s) and the buds themselves. From time to time we insert authentication nodes. Authentication nodes contain a HMAC from the current hash state, so that they can be used to authenticate a journal replay up to the point where the authentication node is. The hash is continued afterwards so that theoretically we would only have to check the HMAC of the last authentication node we find. Overall we get this picture: ,,,,,,,, ,......,........................................... ,. CS , hash1.----. hash2.----. ,. | , . |hmac . |hmac ,. v , . v . v ,.REF#0,-> bud -> bud -> bud.-> auth -> bud -> bud.-> auth ... ,..|...,........................................... , | , , | ,,,,,,,,,,,,,,, . | hash3,----. , | , |hmac , v , v , REF#1 -> bud -> bud,-> auth ... ,,,|,,,,,,,,,,,,,,,,,, v REF#2 -> ... | V ... Note how hash3 covers CS, REF#0 and REF#1 so that it is not possible to exchange or skip any reference nodes. Unlike the picture suggests the auth nodes themselves are not hashed. With this it is possible for an offline attacker to cut each journal head or to drop the last reference node(s), but not to skip any journal heads or to reorder any operations. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'fs/ubifs/journal.c')
-rw-r--r--fs/ubifs/journal.c124
1 files changed, 107 insertions, 17 deletions
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 7c12bdfa9a7a..729dc76c83df 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -90,6 +90,12 @@ static inline void zero_trun_node_unused(struct ubifs_trun_node *trun)
90 memset(trun->padding, 0, 12); 90 memset(trun->padding, 0, 12);
91} 91}
92 92
93static void ubifs_add_auth_dirt(struct ubifs_info *c, int lnum)
94{
95 if (ubifs_authenticated(c))
96 ubifs_add_dirt(c, lnum, ubifs_auth_node_sz(c));
97}
98
93/** 99/**
94 * reserve_space - reserve space in the journal. 100 * reserve_space - reserve space in the journal.
95 * @c: UBIFS file-system description object 101 * @c: UBIFS file-system description object
@@ -228,6 +234,35 @@ out_return:
228 return err; 234 return err;
229} 235}
230 236
237static int ubifs_hash_nodes(struct ubifs_info *c, void *node,
238 int len, struct shash_desc *hash)
239{
240 int auth_node_size = ubifs_auth_node_sz(c);
241 int err;
242
243 while (1) {
244 const struct ubifs_ch *ch = node;
245 int nodelen = le32_to_cpu(ch->len);
246
247 ubifs_assert(c, len >= auth_node_size);
248
249 if (len == auth_node_size)
250 break;
251
252 ubifs_assert(c, len > nodelen);
253 ubifs_assert(c, ch->magic == cpu_to_le32(UBIFS_NODE_MAGIC));
254
255 err = ubifs_shash_update(c, hash, (void *)node, nodelen);
256 if (err)
257 return err;
258
259 node += ALIGN(nodelen, 8);
260 len -= ALIGN(nodelen, 8);
261 }
262
263 return ubifs_prepare_auth_node(c, node, hash);
264}
265
231/** 266/**
232 * write_head - write data to a journal head. 267 * write_head - write data to a journal head.
233 * @c: UBIFS file-system description object 268 * @c: UBIFS file-system description object
@@ -255,6 +290,12 @@ static int write_head(struct ubifs_info *c, int jhead, void *buf, int len,
255 dbg_jnl("jhead %s, LEB %d:%d, len %d", 290 dbg_jnl("jhead %s, LEB %d:%d, len %d",
256 dbg_jhead(jhead), *lnum, *offs, len); 291 dbg_jhead(jhead), *lnum, *offs, len);
257 292
293 if (ubifs_authenticated(c)) {
294 err = ubifs_hash_nodes(c, buf, len, c->jheads[jhead].log_hash);
295 if (err)
296 return err;
297 }
298
258 err = ubifs_wbuf_write_nolock(wbuf, buf, len); 299 err = ubifs_wbuf_write_nolock(wbuf, buf, len);
259 if (err) 300 if (err)
260 return err; 301 return err;
@@ -543,7 +584,10 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
543 584
544 len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ; 585 len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;
545 /* Make sure to also account for extended attributes */ 586 /* Make sure to also account for extended attributes */
546 len += host_ui->data_len; 587 if (ubifs_authenticated(c))
588 len += ALIGN(host_ui->data_len, 8) + ubifs_auth_node_sz(c);
589 else
590 len += host_ui->data_len;
547 591
548 dent = kzalloc(len, GFP_NOFS); 592 dent = kzalloc(len, GFP_NOFS);
549 if (!dent) 593 if (!dent)
@@ -611,6 +655,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
611 } 655 }
612 release_head(c, BASEHD); 656 release_head(c, BASEHD);
613 kfree(dent); 657 kfree(dent);
658 ubifs_add_auth_dirt(c, lnum);
614 659
615 if (deletion) { 660 if (deletion) {
616 if (nm->hash) 661 if (nm->hash)
@@ -690,8 +735,9 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
690 const union ubifs_key *key, const void *buf, int len) 735 const union ubifs_key *key, const void *buf, int len)
691{ 736{
692 struct ubifs_data_node *data; 737 struct ubifs_data_node *data;
693 int err, lnum, offs, compr_type, out_len, compr_len; 738 int err, lnum, offs, compr_type, out_len, compr_len, auth_len;
694 int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1; 739 int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
740 int write_len;
695 struct ubifs_inode *ui = ubifs_inode(inode); 741 struct ubifs_inode *ui = ubifs_inode(inode);
696 bool encrypted = ubifs_crypt_is_encrypted(inode); 742 bool encrypted = ubifs_crypt_is_encrypted(inode);
697 u8 hash[UBIFS_HASH_ARR_SZ]; 743 u8 hash[UBIFS_HASH_ARR_SZ];
@@ -703,7 +749,9 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
703 if (encrypted) 749 if (encrypted)
704 dlen += UBIFS_CIPHER_BLOCK_SIZE; 750 dlen += UBIFS_CIPHER_BLOCK_SIZE;
705 751
706 data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN); 752 auth_len = ubifs_auth_node_sz(c);
753
754 data = kmalloc(dlen + auth_len, GFP_NOFS | __GFP_NOWARN);
707 if (!data) { 755 if (!data) {
708 /* 756 /*
709 * Fall-back to the write reserve buffer. Note, we might be 757 * Fall-back to the write reserve buffer. Note, we might be
@@ -742,15 +790,20 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
742 } 790 }
743 791
744 dlen = UBIFS_DATA_NODE_SZ + out_len; 792 dlen = UBIFS_DATA_NODE_SZ + out_len;
793 if (ubifs_authenticated(c))
794 write_len = ALIGN(dlen, 8) + auth_len;
795 else
796 write_len = dlen;
797
745 data->compr_type = cpu_to_le16(compr_type); 798 data->compr_type = cpu_to_le16(compr_type);
746 799
747 /* Make reservation before allocating sequence numbers */ 800 /* Make reservation before allocating sequence numbers */
748 err = make_reservation(c, DATAHD, dlen); 801 err = make_reservation(c, DATAHD, write_len);
749 if (err) 802 if (err)
750 goto out_free; 803 goto out_free;
751 804
752 ubifs_prepare_node(c, data, dlen, 0); 805 ubifs_prepare_node(c, data, dlen, 0);
753 err = write_head(c, DATAHD, data, dlen, &lnum, &offs, 0); 806 err = write_head(c, DATAHD, data, write_len, &lnum, &offs, 0);
754 if (err) 807 if (err)
755 goto out_release; 808 goto out_release;
756 809
@@ -761,6 +814,8 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
761 ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf, key_inum(c, key)); 814 ubifs_wbuf_add_ino_nolock(&c->jheads[DATAHD].wbuf, key_inum(c, key));
762 release_head(c, DATAHD); 815 release_head(c, DATAHD);
763 816
817 ubifs_add_auth_dirt(c, lnum);
818
764 err = ubifs_tnc_add(c, key, lnum, offs, dlen, hash); 819 err = ubifs_tnc_add(c, key, lnum, offs, dlen, hash);
765 if (err) 820 if (err)
766 goto out_ro; 821 goto out_ro;
@@ -799,7 +854,8 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
799 int err, lnum, offs; 854 int err, lnum, offs;
800 struct ubifs_ino_node *ino; 855 struct ubifs_ino_node *ino;
801 struct ubifs_inode *ui = ubifs_inode(inode); 856 struct ubifs_inode *ui = ubifs_inode(inode);
802 int sync = 0, len = UBIFS_INO_NODE_SZ, last_reference = !inode->i_nlink; 857 int sync = 0, write_len, ilen = UBIFS_INO_NODE_SZ;
858 int last_reference = !inode->i_nlink;
803 u8 hash[UBIFS_HASH_ARR_SZ]; 859 u8 hash[UBIFS_HASH_ARR_SZ];
804 860
805 dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink); 861 dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink);
@@ -809,15 +865,21 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
809 * need to synchronize the write-buffer either. 865 * need to synchronize the write-buffer either.
810 */ 866 */
811 if (!last_reference) { 867 if (!last_reference) {
812 len += ui->data_len; 868 ilen += ui->data_len;
813 sync = IS_SYNC(inode); 869 sync = IS_SYNC(inode);
814 } 870 }
815 ino = kmalloc(len, GFP_NOFS); 871
872 if (ubifs_authenticated(c))
873 write_len = ALIGN(ilen, 8) + ubifs_auth_node_sz(c);
874 else
875 write_len = ilen;
876
877 ino = kmalloc(write_len, GFP_NOFS);
816 if (!ino) 878 if (!ino)
817 return -ENOMEM; 879 return -ENOMEM;
818 880
819 /* Make reservation before allocating sequence numbers */ 881 /* Make reservation before allocating sequence numbers */
820 err = make_reservation(c, BASEHD, len); 882 err = make_reservation(c, BASEHD, write_len);
821 if (err) 883 if (err)
822 goto out_free; 884 goto out_free;
823 885
@@ -826,7 +888,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
826 if (err) 888 if (err)
827 goto out_release; 889 goto out_release;
828 890
829 err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); 891 err = write_head(c, BASEHD, ino, write_len, &lnum, &offs, sync);
830 if (err) 892 if (err)
831 goto out_release; 893 goto out_release;
832 if (!sync) 894 if (!sync)
@@ -834,17 +896,19 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
834 inode->i_ino); 896 inode->i_ino);
835 release_head(c, BASEHD); 897 release_head(c, BASEHD);
836 898
899 ubifs_add_auth_dirt(c, lnum);
900
837 if (last_reference) { 901 if (last_reference) {
838 err = ubifs_tnc_remove_ino(c, inode->i_ino); 902 err = ubifs_tnc_remove_ino(c, inode->i_ino);
839 if (err) 903 if (err)
840 goto out_ro; 904 goto out_ro;
841 ubifs_delete_orphan(c, inode->i_ino); 905 ubifs_delete_orphan(c, inode->i_ino);
842 err = ubifs_add_dirt(c, lnum, len); 906 err = ubifs_add_dirt(c, lnum, ilen);
843 } else { 907 } else {
844 union ubifs_key key; 908 union ubifs_key key;
845 909
846 ino_key_init(c, &key, inode->i_ino); 910 ino_key_init(c, &key, inode->i_ino);
847 err = ubifs_tnc_add(c, &key, lnum, offs, len, hash); 911 err = ubifs_tnc_add(c, &key, lnum, offs, ilen, hash);
848 } 912 }
849 if (err) 913 if (err)
850 goto out_ro; 914 goto out_ro;
@@ -973,6 +1037,8 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
973 if (twoparents) 1037 if (twoparents)
974 len += plen; 1038 len += plen;
975 1039
1040 len += ubifs_auth_node_sz(c);
1041
976 dent1 = kzalloc(len, GFP_NOFS); 1042 dent1 = kzalloc(len, GFP_NOFS);
977 if (!dent1) 1043 if (!dent1)
978 return -ENOMEM; 1044 return -ENOMEM;
@@ -1042,6 +1108,8 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
1042 } 1108 }
1043 release_head(c, BASEHD); 1109 release_head(c, BASEHD);
1044 1110
1111 ubifs_add_auth_dirt(c, lnum);
1112
1045 dent_key_init(c, &key, snd_dir->i_ino, snd_nm); 1113 dent_key_init(c, &key, snd_dir->i_ino, snd_nm);
1046 err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, hash_dent1, snd_nm); 1114 err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, hash_dent1, snd_nm);
1047 if (err) 1115 if (err)
@@ -1143,6 +1211,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
1143 len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8); 1211 len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
1144 if (move) 1212 if (move)
1145 len += plen; 1213 len += plen;
1214
1215 len += ubifs_auth_node_sz(c);
1216
1146 dent = kzalloc(len, GFP_NOFS); 1217 dent = kzalloc(len, GFP_NOFS);
1147 if (!dent) 1218 if (!dent)
1148 return -ENOMEM; 1219 return -ENOMEM;
@@ -1240,6 +1311,8 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
1240 } 1311 }
1241 release_head(c, BASEHD); 1312 release_head(c, BASEHD);
1242 1313
1314 ubifs_add_auth_dirt(c, lnum);
1315
1243 dent_key_init(c, &key, new_dir->i_ino, new_nm); 1316 dent_key_init(c, &key, new_dir->i_ino, new_nm);
1244 err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, hash_dent1, new_nm); 1317 err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, hash_dent1, new_nm);
1245 if (err) 1318 if (err)
@@ -1411,6 +1484,9 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
1411 1484
1412 sz = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ + 1485 sz = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ +
1413 UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR; 1486 UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR;
1487
1488 sz += ubifs_auth_node_sz(c);
1489
1414 ino = kmalloc(sz, GFP_NOFS); 1490 ino = kmalloc(sz, GFP_NOFS);
1415 if (!ino) 1491 if (!ino)
1416 return -ENOMEM; 1492 return -ENOMEM;
@@ -1456,8 +1532,12 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
1456 1532
1457 /* Must make reservation before allocating sequence numbers */ 1533 /* Must make reservation before allocating sequence numbers */
1458 len = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ; 1534 len = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ;
1459 if (dlen) 1535
1536 if (ubifs_authenticated(c))
1537 len += ALIGN(dlen, 8) + ubifs_auth_node_sz(c);
1538 else
1460 len += dlen; 1539 len += dlen;
1540
1461 err = make_reservation(c, BASEHD, len); 1541 err = make_reservation(c, BASEHD, len);
1462 if (err) 1542 if (err)
1463 goto out_free; 1543 goto out_free;
@@ -1482,6 +1562,8 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
1482 ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum); 1562 ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, inum);
1483 release_head(c, BASEHD); 1563 release_head(c, BASEHD);
1484 1564
1565 ubifs_add_auth_dirt(c, lnum);
1566
1485 if (dlen) { 1567 if (dlen) {
1486 sz = offs + UBIFS_INO_NODE_SZ + UBIFS_TRUN_NODE_SZ; 1568 sz = offs + UBIFS_INO_NODE_SZ + UBIFS_TRUN_NODE_SZ;
1487 err = ubifs_tnc_add(c, &key, lnum, sz, dlen, hash_dn); 1569 err = ubifs_tnc_add(c, &key, lnum, sz, dlen, hash_dn);
@@ -1545,7 +1627,7 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
1545 const struct inode *inode, 1627 const struct inode *inode,
1546 const struct fscrypt_name *nm) 1628 const struct fscrypt_name *nm)
1547{ 1629{
1548 int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen; 1630 int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen, write_len;
1549 struct ubifs_dent_node *xent; 1631 struct ubifs_dent_node *xent;
1550 struct ubifs_ino_node *ino; 1632 struct ubifs_ino_node *ino;
1551 union ubifs_key xent_key, key1, key2; 1633 union ubifs_key xent_key, key1, key2;
@@ -1565,12 +1647,14 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
1565 hlen = host_ui->data_len + UBIFS_INO_NODE_SZ; 1647 hlen = host_ui->data_len + UBIFS_INO_NODE_SZ;
1566 len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8); 1648 len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);
1567 1649
1568 xent = kzalloc(len, GFP_NOFS); 1650 write_len = len + ubifs_auth_node_sz(c);
1651
1652 xent = kzalloc(write_len, GFP_NOFS);
1569 if (!xent) 1653 if (!xent)
1570 return -ENOMEM; 1654 return -ENOMEM;
1571 1655
1572 /* Make reservation before allocating sequence numbers */ 1656 /* Make reservation before allocating sequence numbers */
1573 err = make_reservation(c, BASEHD, len); 1657 err = make_reservation(c, BASEHD, write_len);
1574 if (err) { 1658 if (err) {
1575 kfree(xent); 1659 kfree(xent);
1576 return err; 1660 return err;
@@ -1595,10 +1679,12 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
1595 if (err) 1679 if (err)
1596 goto out_release; 1680 goto out_release;
1597 1681
1598 err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync); 1682 err = write_head(c, BASEHD, xent, write_len, &lnum, &xent_offs, sync);
1599 if (!sync && !err) 1683 if (!sync && !err)
1600 ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino); 1684 ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf, host->i_ino);
1601 release_head(c, BASEHD); 1685 release_head(c, BASEHD);
1686
1687 ubifs_add_auth_dirt(c, lnum);
1602 kfree(xent); 1688 kfree(xent);
1603 if (err) 1689 if (err)
1604 goto out_ro; 1690 goto out_ro;
@@ -1680,6 +1766,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
1680 aligned_len1 = ALIGN(len1, 8); 1766 aligned_len1 = ALIGN(len1, 8);
1681 aligned_len = aligned_len1 + ALIGN(len2, 8); 1767 aligned_len = aligned_len1 + ALIGN(len2, 8);
1682 1768
1769 aligned_len += ubifs_auth_node_sz(c);
1770
1683 ino = kzalloc(aligned_len, GFP_NOFS); 1771 ino = kzalloc(aligned_len, GFP_NOFS);
1684 if (!ino) 1772 if (!ino)
1685 return -ENOMEM; 1773 return -ENOMEM;
@@ -1709,6 +1797,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
1709 if (err) 1797 if (err)
1710 goto out_ro; 1798 goto out_ro;
1711 1799
1800 ubifs_add_auth_dirt(c, lnum);
1801
1712 ino_key_init(c, &key, host->i_ino); 1802 ino_key_init(c, &key, host->i_ino);
1713 err = ubifs_tnc_add(c, &key, lnum, offs, len1, hash_host); 1803 err = ubifs_tnc_add(c, &key, lnum, offs, len1, hash_host);
1714 if (err) 1804 if (err)