Skip to content

Commit a318423

Browse files
committed
Merge tag 'upstream-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs
Pull UBIFS updates from Richard Weinberger: - Support for zstd compression - Support for offline signed filesystems - Various fixes for regressions * tag 'upstream-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs: ubifs: Don't leak orphans on memory during commit ubifs: Check link count of inodes when killing orphans. ubifs: Add support for zstd compression. ubifs: support offline signed images ubifs: remove unnecessary check in ubifs_log_start_commit ubifs: Fix typo of output in get_cs_sqnum ubifs: Simplify redundant code ubifs: Correctly use tnc_next() in search_dh_cookie()
2 parents f2772a0 + 8009ce9 commit a318423

File tree

12 files changed

+338
-92
lines changed

12 files changed

+338
-92
lines changed

fs/ubifs/Kconfig

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ config UBIFS_FS
66
select CRYPTO if UBIFS_FS_ADVANCED_COMPR
77
select CRYPTO if UBIFS_FS_LZO
88
select CRYPTO if UBIFS_FS_ZLIB
9+
select CRYPTO if UBIFS_FS_ZSTD
910
select CRYPTO_LZO if UBIFS_FS_LZO
1011
select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
12+
select CRYPTO_ZSTD if UBIFS_FS_ZSTD
1113
select CRYPTO_HASH_INFO
1214
select UBIFS_FS_XATTR if FS_ENCRYPTION
1315
depends on MTD_UBI
@@ -38,6 +40,14 @@ config UBIFS_FS_ZLIB
3840
help
3941
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
4042

43+
config UBIFS_FS_ZSTD
44+
bool "ZSTD compression support" if UBIFS_FS_ADVANCED_COMPR
45+
depends on UBIFS_FS
46+
default y
47+
help
48+
ZSTD compresses is a big win in speed over Zlib and
49+
in compression ratio over LZO. Say 'Y' if unsure.
50+
4151
config UBIFS_ATIME_SUPPORT
4252
bool "Access time support"
4353
default n
@@ -77,8 +87,9 @@ config UBIFS_FS_SECURITY
7787

7888
config UBIFS_FS_AUTHENTICATION
7989
bool "UBIFS authentication support"
80-
depends on KEYS
90+
select KEYS
8191
select CRYPTO_HMAC
92+
select SYSTEM_DATA_VERIFICATION
8293
help
8394
Enable authentication support for UBIFS. This feature offers protection
8495
against offline changes for both data and metadata of the filesystem.

fs/ubifs/auth.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
*/
1111

1212
#include <linux/crypto.h>
13+
#include <linux/verification.h>
1314
#include <crypto/hash.h>
1415
#include <crypto/sha.h>
1516
#include <crypto/algapi.h>
1617
#include <keys/user-type.h>
18+
#include <keys/asymmetric-type.h>
1719

1820
#include "ubifs.h"
1921

@@ -198,6 +200,77 @@ int __ubifs_node_check_hash(const struct ubifs_info *c, const void *node,
198200
return 0;
199201
}
200202

203+
/**
204+
* ubifs_sb_verify_signature - verify the signature of a superblock
205+
* @c: UBIFS file-system description object
206+
* @sup: The superblock node
207+
*
208+
* To support offline signed images the superblock can be signed with a
209+
* PKCS#7 signature. The signature is placed directly behind the superblock
210+
* node in an ubifs_sig_node.
211+
*
212+
* Returns 0 when the signature can be successfully verified or a negative
213+
* error code if not.
214+
*/
215+
int ubifs_sb_verify_signature(struct ubifs_info *c,
216+
const struct ubifs_sb_node *sup)
217+
{
218+
int err;
219+
struct ubifs_scan_leb *sleb;
220+
struct ubifs_scan_node *snod;
221+
const struct ubifs_sig_node *signode;
222+
223+
sleb = ubifs_scan(c, UBIFS_SB_LNUM, UBIFS_SB_NODE_SZ, c->sbuf, 0);
224+
if (IS_ERR(sleb)) {
225+
err = PTR_ERR(sleb);
226+
return err;
227+
}
228+
229+
if (sleb->nodes_cnt == 0) {
230+
ubifs_err(c, "Unable to find signature node");
231+
err = -EINVAL;
232+
goto out_destroy;
233+
}
234+
235+
snod = list_first_entry(&sleb->nodes, struct ubifs_scan_node, list);
236+
237+
if (snod->type != UBIFS_SIG_NODE) {
238+
ubifs_err(c, "Signature node is of wrong type");
239+
err = -EINVAL;
240+
goto out_destroy;
241+
}
242+
243+
signode = snod->node;
244+
245+
if (le32_to_cpu(signode->len) > snod->len + sizeof(struct ubifs_sig_node)) {
246+
ubifs_err(c, "invalid signature len %d", le32_to_cpu(signode->len));
247+
err = -EINVAL;
248+
goto out_destroy;
249+
}
250+
251+
if (le32_to_cpu(signode->type) != UBIFS_SIGNATURE_TYPE_PKCS7) {
252+
ubifs_err(c, "Signature type %d is not supported\n",
253+
le32_to_cpu(signode->type));
254+
err = -EINVAL;
255+
goto out_destroy;
256+
}
257+
258+
err = verify_pkcs7_signature(sup, sizeof(struct ubifs_sb_node),
259+
signode->sig, le32_to_cpu(signode->len),
260+
NULL, VERIFYING_UNSPECIFIED_SIGNATURE,
261+
NULL, NULL);
262+
263+
if (err)
264+
ubifs_err(c, "Failed to verify signature");
265+
else
266+
ubifs_msg(c, "Successfully verified super block signature");
267+
268+
out_destroy:
269+
ubifs_scan_destroy(sleb);
270+
271+
return err;
272+
}
273+
201274
/**
202275
* ubifs_init_authentication - initialize UBIFS authentication support
203276
* @c: UBIFS file-system description object
@@ -478,3 +551,16 @@ int ubifs_hmac_wkm(struct ubifs_info *c, u8 *hmac)
478551
return err;
479552
return 0;
480553
}
554+
555+
/*
556+
* ubifs_hmac_zero - test if a HMAC is zero
557+
* @c: UBIFS file-system description object
558+
* @hmac: the HMAC to test
559+
*
560+
* This function tests if a HMAC is zero and returns true if it is
561+
* and false otherwise.
562+
*/
563+
bool ubifs_hmac_zero(struct ubifs_info *c, const u8 *hmac)
564+
{
565+
return !memchr_inv(hmac, 0, c->hmac_desc_len);
566+
}

fs/ubifs/compress.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,24 @@ static struct ubifs_compressor zlib_compr = {
5959
};
6060
#endif
6161

62+
#ifdef CONFIG_UBIFS_FS_ZSTD
63+
static DEFINE_MUTEX(zstd_enc_mutex);
64+
static DEFINE_MUTEX(zstd_dec_mutex);
65+
66+
static struct ubifs_compressor zstd_compr = {
67+
.compr_type = UBIFS_COMPR_ZSTD,
68+
.comp_mutex = &zstd_enc_mutex,
69+
.decomp_mutex = &zstd_dec_mutex,
70+
.name = "zstd",
71+
.capi_name = "zstd",
72+
};
73+
#else
74+
static struct ubifs_compressor zstd_compr = {
75+
.compr_type = UBIFS_COMPR_ZSTD,
76+
.name = "zstd",
77+
};
78+
#endif
79+
6280
/* All UBIFS compressors */
6381
struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
6482

@@ -216,13 +234,19 @@ int __init ubifs_compressors_init(void)
216234
if (err)
217235
return err;
218236

219-
err = compr_init(&zlib_compr);
237+
err = compr_init(&zstd_compr);
220238
if (err)
221239
goto out_lzo;
222240

241+
err = compr_init(&zlib_compr);
242+
if (err)
243+
goto out_zstd;
244+
223245
ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
224246
return 0;
225247

248+
out_zstd:
249+
compr_exit(&zstd_compr);
226250
out_lzo:
227251
compr_exit(&lzo_compr);
228252
return err;
@@ -235,4 +259,5 @@ void ubifs_compressors_exit(void)
235259
{
236260
compr_exit(&lzo_compr);
237261
compr_exit(&zlib_compr);
262+
compr_exit(&zstd_compr);
238263
}

fs/ubifs/log.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,10 +438,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
438438
*ltail_lnum = c->lhead_lnum;
439439

440440
c->lhead_offs += len;
441-
if (c->lhead_offs == c->leb_size) {
442-
c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum);
443-
c->lhead_offs = 0;
444-
}
441+
ubifs_assert(c, c->lhead_offs < c->leb_size);
445442

446443
remove_buds(c);
447444

fs/ubifs/master.c

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,39 @@ int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2)
4848
return 0;
4949
}
5050

51+
/* mst_node_check_hash - Check hash of a master node
52+
* @c: UBIFS file-system description object
53+
* @mst: The master node
54+
* @expected: The expected hash of the master node
55+
*
56+
* This checks the hash of a master node against a given expected hash.
57+
* Note that we have two master nodes on a UBIFS image which have different
58+
* sequence numbers and consequently different CRCs. To be able to match
59+
* both master nodes we exclude the common node header containing the sequence
60+
* number and CRC from the hash.
61+
*
62+
* Returns 0 if the hashes are equal, a negative error code otherwise.
63+
*/
64+
static int mst_node_check_hash(const struct ubifs_info *c,
65+
const struct ubifs_mst_node *mst,
66+
const u8 *expected)
67+
{
68+
u8 calc[UBIFS_MAX_HASH_LEN];
69+
const void *node = mst;
70+
71+
SHASH_DESC_ON_STACK(shash, c->hash_tfm);
72+
73+
shash->tfm = c->hash_tfm;
74+
75+
crypto_shash_digest(shash, node + sizeof(struct ubifs_ch),
76+
UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch), calc);
77+
78+
if (ubifs_check_hash(c, expected, calc))
79+
return -EPERM;
80+
81+
return 0;
82+
}
83+
5184
/**
5285
* scan_for_master - search the valid master node.
5386
* @c: UBIFS file-system description object
@@ -102,14 +135,22 @@ static int scan_for_master(struct ubifs_info *c)
102135
if (!ubifs_authenticated(c))
103136
return 0;
104137

105-
err = ubifs_node_verify_hmac(c, c->mst_node,
106-
sizeof(struct ubifs_mst_node),
107-
offsetof(struct ubifs_mst_node, hmac));
108-
if (err) {
109-
ubifs_err(c, "Failed to verify master node HMAC");
110-
return -EPERM;
138+
if (ubifs_hmac_zero(c, c->mst_node->hmac)) {
139+
err = mst_node_check_hash(c, c->mst_node,
140+
c->sup_node->hash_mst);
141+
if (err)
142+
ubifs_err(c, "Failed to verify master node hash");
143+
} else {
144+
err = ubifs_node_verify_hmac(c, c->mst_node,
145+
sizeof(struct ubifs_mst_node),
146+
offsetof(struct ubifs_mst_node, hmac));
147+
if (err)
148+
ubifs_err(c, "Failed to verify master node HMAC");
111149
}
112150

151+
if (err)
152+
return -EPERM;
153+
113154
return 0;
114155

115156
out:

0 commit comments

Comments
 (0)