@@ -1635,6 +1635,131 @@ struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum)
1635
1635
return & pnode -> lprops [iip ];
1636
1636
}
1637
1637
1638
+ /**
1639
+ * ubifs_lpt_calc_hash - Calculate hash of the LPT pnodes
1640
+ * @c: UBIFS file-system description object
1641
+ * @hash: the returned hash of the LPT pnodes
1642
+ *
1643
+ * This function iterates over the LPT pnodes and creates a hash over them.
1644
+ * Returns 0 for success or a negative error code otherwise.
1645
+ */
1646
+ int ubifs_lpt_calc_hash (struct ubifs_info * c , u8 * hash )
1647
+ {
1648
+ struct ubifs_nnode * nnode , * nn ;
1649
+ struct ubifs_cnode * cnode ;
1650
+ struct shash_desc * desc ;
1651
+ int iip = 0 , i ;
1652
+ int bufsiz = max_t (int , c -> nnode_sz , c -> pnode_sz );
1653
+ void * buf ;
1654
+ int err ;
1655
+
1656
+ if (!ubifs_authenticated (c ))
1657
+ return 0 ;
1658
+
1659
+ desc = ubifs_hash_get_desc (c );
1660
+ if (IS_ERR (desc ))
1661
+ return PTR_ERR (desc );
1662
+
1663
+ buf = kmalloc (bufsiz , GFP_NOFS );
1664
+ if (!buf ) {
1665
+ err = - ENOMEM ;
1666
+ goto out ;
1667
+ }
1668
+
1669
+ if (!c -> nroot ) {
1670
+ err = ubifs_read_nnode (c , NULL , 0 );
1671
+ if (err )
1672
+ return err ;
1673
+ }
1674
+
1675
+ cnode = (struct ubifs_cnode * )c -> nroot ;
1676
+
1677
+ while (cnode ) {
1678
+ nnode = cnode -> parent ;
1679
+ nn = (struct ubifs_nnode * )cnode ;
1680
+ if (cnode -> level > 1 ) {
1681
+ while (iip < UBIFS_LPT_FANOUT ) {
1682
+ if (nn -> nbranch [iip ].lnum == 0 ) {
1683
+ /* Go right */
1684
+ iip ++ ;
1685
+ continue ;
1686
+ }
1687
+
1688
+ nnode = ubifs_get_nnode (c , nn , iip );
1689
+ if (IS_ERR (nnode )) {
1690
+ err = PTR_ERR (nnode );
1691
+ goto out ;
1692
+ }
1693
+
1694
+ /* Go down */
1695
+ iip = 0 ;
1696
+ cnode = (struct ubifs_cnode * )nnode ;
1697
+ break ;
1698
+ }
1699
+ if (iip < UBIFS_LPT_FANOUT )
1700
+ continue ;
1701
+ } else {
1702
+ struct ubifs_pnode * pnode ;
1703
+
1704
+ for (i = 0 ; i < UBIFS_LPT_FANOUT ; i ++ ) {
1705
+ if (nn -> nbranch [i ].lnum == 0 )
1706
+ continue ;
1707
+ pnode = ubifs_get_pnode (c , nn , i );
1708
+ if (IS_ERR (pnode )) {
1709
+ err = PTR_ERR (pnode );
1710
+ goto out ;
1711
+ }
1712
+
1713
+ ubifs_pack_pnode (c , buf , pnode );
1714
+ err = ubifs_shash_update (c , desc , buf ,
1715
+ c -> pnode_sz );
1716
+ if (err )
1717
+ goto out ;
1718
+ }
1719
+ }
1720
+ /* Go up and to the right */
1721
+ iip = cnode -> iip + 1 ;
1722
+ cnode = (struct ubifs_cnode * )nnode ;
1723
+ }
1724
+
1725
+ err = ubifs_shash_final (c , desc , hash );
1726
+ out :
1727
+ kfree (desc );
1728
+ kfree (buf );
1729
+
1730
+ return err ;
1731
+ }
1732
+
1733
+ /**
1734
+ * lpt_check_hash - check the hash of the LPT.
1735
+ * @c: UBIFS file-system description object
1736
+ *
1737
+ * This function calculates a hash over all pnodes in the LPT and compares it with
1738
+ * the hash stored in the master node. Returns %0 on success and a negative error
1739
+ * code on failure.
1740
+ */
1741
+ static int lpt_check_hash (struct ubifs_info * c )
1742
+ {
1743
+ int err ;
1744
+ u8 hash [UBIFS_HASH_ARR_SZ ];
1745
+
1746
+ if (!ubifs_authenticated (c ))
1747
+ return 0 ;
1748
+
1749
+ err = ubifs_lpt_calc_hash (c , hash );
1750
+ if (err )
1751
+ return err ;
1752
+
1753
+ if (ubifs_check_hash (c , c -> mst_node -> hash_lpt , hash )) {
1754
+ err = - EPERM ;
1755
+ ubifs_err (c , "Failed to authenticate LPT" );
1756
+ } else {
1757
+ err = 0 ;
1758
+ }
1759
+
1760
+ return err ;
1761
+ }
1762
+
1638
1763
/**
1639
1764
* lpt_init_rd - initialize the LPT for reading.
1640
1765
* @c: UBIFS file-system description object
@@ -1676,6 +1801,10 @@ static int lpt_init_rd(struct ubifs_info *c)
1676
1801
if (err )
1677
1802
return err ;
1678
1803
1804
+ err = lpt_check_hash (c );
1805
+ if (err )
1806
+ return err ;
1807
+
1679
1808
dbg_lp ("space_bits %d" , c -> space_bits );
1680
1809
dbg_lp ("lpt_lnum_bits %d" , c -> lpt_lnum_bits );
1681
1810
dbg_lp ("lpt_offs_bits %d" , c -> lpt_offs_bits );
0 commit comments