diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-20 14:17:24 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-20 14:17:24 -0800 |
commit | f57b620a89ad2eee2e25218b5cb2bee0ad1e2e7d (patch) | |
tree | 074c708cca22d7cc5d8524bd89299e51dd4b8540 /fs | |
parent | 1d51b4b1d3f2db0d6d144175e31a84e472fbd99a (diff) | |
parent | e58725d51fa8da9133f3f1c54170aa2e43056b91 (diff) |
Merge tag 'upstream-4.20-rc7' of git://git.infradead.org/linux-ubifs
Pull UBI/UBIFS fixes from Richard Weinberger:
- Kconfig dependency fixes for our new auth feature
- Fix for selecting the right compressor when creating a fs
- Bugfix for a bug in UBIFS's O_TMPFILE implementation
- Refcounting fixes for UBI
* tag 'upstream-4.20-rc7' of git://git.infradead.org/linux-ubifs:
ubifs: Handle re-linking of inodes correctly while recovery
ubi: Do not drop UBI device reference before using
ubi: Put MTD device after it is not used
ubifs: Fix default compression selection in ubifs
ubifs: Fix memory leak on error condition
ubifs: auth: Add CONFIG_KEYS dependency
ubifs: CONFIG_UBIFS_FS_AUTHENTICATION should depend on UBIFS_FS
ubifs: replay: Fix high stack usage
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ubifs/Kconfig | 16 | ||||
-rw-r--r-- | fs/ubifs/lpt.c | 12 | ||||
-rw-r--r-- | fs/ubifs/replay.c | 72 | ||||
-rw-r--r-- | fs/ubifs/sb.c | 13 |
4 files changed, 87 insertions, 26 deletions
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index 529856fbccd0..bc1e082d921d 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig @@ -12,9 +12,10 @@ config UBIFS_FS help UBIFS is a file system for flash devices which works on top of UBI. +if UBIFS_FS + config UBIFS_FS_ADVANCED_COMPR bool "Advanced compression options" - depends on UBIFS_FS help This option allows to explicitly choose which compressions, if any, are enabled in UBIFS. Removing compressors means inability to read @@ -24,7 +25,6 @@ config UBIFS_FS_ADVANCED_COMPR config UBIFS_FS_LZO bool "LZO compression support" if UBIFS_FS_ADVANCED_COMPR - depends on UBIFS_FS default y help LZO compressor is generally faster than zlib but compresses worse. @@ -32,14 +32,12 @@ config UBIFS_FS_LZO config UBIFS_FS_ZLIB bool "ZLIB compression support" if UBIFS_FS_ADVANCED_COMPR - depends on UBIFS_FS default y help Zlib compresses better than LZO but it is slower. Say 'Y' if unsure. config UBIFS_ATIME_SUPPORT - bool "Access time support" if UBIFS_FS - depends on UBIFS_FS + bool "Access time support" default n help Originally UBIFS did not support atime, because it looked like a bad idea due @@ -54,7 +52,6 @@ config UBIFS_ATIME_SUPPORT config UBIFS_FS_XATTR bool "UBIFS XATTR support" - depends on UBIFS_FS default y help Saying Y here includes support for extended attributes (xattrs). @@ -65,7 +62,7 @@ config UBIFS_FS_XATTR config UBIFS_FS_ENCRYPTION bool "UBIFS Encryption" - depends on UBIFS_FS && UBIFS_FS_XATTR && BLOCK + depends on UBIFS_FS_XATTR && BLOCK select FS_ENCRYPTION default n help @@ -76,7 +73,7 @@ config UBIFS_FS_ENCRYPTION config UBIFS_FS_SECURITY bool "UBIFS Security Labels" - depends on UBIFS_FS && UBIFS_FS_XATTR + depends on UBIFS_FS_XATTR default y help Security labels provide an access control facility to support Linux @@ -89,6 +86,7 @@ config UBIFS_FS_SECURITY config UBIFS_FS_AUTHENTICATION bool "UBIFS authentication support" + depends on KEYS select CRYPTO_HMAC help Enable authentication support for UBIFS. This feature offers protection @@ -96,3 +94,5 @@ config UBIFS_FS_AUTHENTICATION If you say yes here you should also select a hashing algorithm such as sha256, these are not selected automatically since there are many different options. + +endif # UBIFS_FS diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index d1d5e96350dd..b0c5f06128b5 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -1675,6 +1675,12 @@ int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash) if (!ubifs_authenticated(c)) return 0; + if (!c->nroot) { + err = ubifs_read_nnode(c, NULL, 0); + if (err) + return err; + } + desc = ubifs_hash_get_desc(c); if (IS_ERR(desc)) return PTR_ERR(desc); @@ -1685,12 +1691,6 @@ int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash) goto out; } - if (!c->nroot) { - err = ubifs_read_nnode(c, NULL, 0); - if (err) - return err; - } - cnode = (struct ubifs_cnode *)c->nroot; while (cnode) { diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 75f961c4c044..0a0e65c07c6d 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -213,6 +213,38 @@ static int trun_remove_range(struct ubifs_info *c, struct replay_entry *r) } /** + * inode_still_linked - check whether inode in question will be re-linked. + * @c: UBIFS file-system description object + * @rino: replay entry to test + * + * O_TMPFILE files can be re-linked, this means link count goes from 0 to 1. + * This case needs special care, otherwise all references to the inode will + * be removed upon the first replay entry of an inode with link count 0 + * is found. + */ +static bool inode_still_linked(struct ubifs_info *c, struct replay_entry *rino) +{ + struct replay_entry *r; + + ubifs_assert(c, rino->deletion); + ubifs_assert(c, key_type(c, &rino->key) == UBIFS_INO_KEY); + + /* + * Find the most recent entry for the inode behind @rino and check + * whether it is a deletion. + */ + list_for_each_entry_reverse(r, &c->replay_list, list) { + ubifs_assert(c, r->sqnum >= rino->sqnum); + if (key_inum(c, &r->key) == key_inum(c, &rino->key)) + return r->deletion == 0; + + } + + ubifs_assert(c, 0); + return false; +} + +/** * apply_replay_entry - apply a replay entry to the TNC. * @c: UBIFS file-system description object * @r: replay entry to apply @@ -239,6 +271,11 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r) { ino_t inum = key_inum(c, &r->key); + if (inode_still_linked(c, r)) { + err = 0; + break; + } + err = ubifs_tnc_remove_ino(c, inum); break; } @@ -533,6 +570,28 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud) return data == 0xFFFFFFFF; } +/* authenticate_sleb_hash and authenticate_sleb_hmac are split out for stack usage */ +static int authenticate_sleb_hash(struct ubifs_info *c, struct shash_desc *log_hash, u8 *hash) +{ + SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm); + + hash_desc->tfm = c->hash_tfm; + hash_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + ubifs_shash_copy_state(c, log_hash, hash_desc); + return crypto_shash_final(hash_desc, hash); +} + +static int authenticate_sleb_hmac(struct ubifs_info *c, u8 *hash, u8 *hmac) +{ + SHASH_DESC_ON_STACK(hmac_desc, c->hmac_tfm); + + hmac_desc->tfm = c->hmac_tfm; + hmac_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + return crypto_shash_digest(hmac_desc, hash, c->hash_len, hmac); +} + /** * authenticate_sleb - authenticate one scan LEB * @c: UBIFS file-system description object @@ -574,21 +633,12 @@ static int authenticate_sleb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, if (snod->type == UBIFS_AUTH_NODE) { struct ubifs_auth_node *auth = snod->node; - SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm); - SHASH_DESC_ON_STACK(hmac_desc, c->hmac_tfm); - - hash_desc->tfm = c->hash_tfm; - hash_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - ubifs_shash_copy_state(c, log_hash, hash_desc); - err = crypto_shash_final(hash_desc, hash); + err = authenticate_sleb_hash(c, log_hash, hash); if (err) goto out; - hmac_desc->tfm = c->hmac_tfm; - hmac_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - err = crypto_shash_digest(hmac_desc, hash, c->hash_len, - hmac); + err = authenticate_sleb_hmac(c, hash, hmac); if (err) goto out; diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 75a69dd26d6e..3da90c951c23 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -63,6 +63,17 @@ /* Default time granularity in nanoseconds */ #define DEFAULT_TIME_GRAN 1000000000 +static int get_default_compressor(struct ubifs_info *c) +{ + if (ubifs_compr_present(c, UBIFS_COMPR_LZO)) + return UBIFS_COMPR_LZO; + + if (ubifs_compr_present(c, UBIFS_COMPR_ZLIB)) + return UBIFS_COMPR_ZLIB; + + return UBIFS_COMPR_NONE; +} + /** * create_default_filesystem - format empty UBI volume. * @c: UBIFS file-system description object @@ -207,7 +218,7 @@ static int create_default_filesystem(struct ubifs_info *c) if (c->mount_opts.override_compr) sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); else - sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO); + sup->default_compr = cpu_to_le16(get_default_compressor(c)); generate_random_uuid(sup->uuid); |