cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tnc_misc.c (12997B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * This file is part of UBIFS.
      4 *
      5 * Copyright (C) 2006-2008 Nokia Corporation.
      6 *
      7 * Authors: Adrian Hunter
      8 *          Artem Bityutskiy (Битюцкий Артём)
      9 */
     10
     11/*
     12 * This file contains miscelanious TNC-related functions shared betweend
     13 * different files. This file does not form any logically separate TNC
     14 * sub-system. The file was created because there is a lot of TNC code and
     15 * putting it all in one file would make that file too big and unreadable.
     16 */
     17
     18#include "ubifs.h"
     19
     20/**
     21 * ubifs_tnc_levelorder_next - next TNC tree element in levelorder traversal.
     22 * @c: UBIFS file-system description object
     23 * @zr: root of the subtree to traverse
     24 * @znode: previous znode
     25 *
     26 * This function implements levelorder TNC traversal. The LNC is ignored.
     27 * Returns the next element or %NULL if @znode is already the last one.
     28 */
     29struct ubifs_znode *ubifs_tnc_levelorder_next(const struct ubifs_info *c,
     30					      struct ubifs_znode *zr,
     31					      struct ubifs_znode *znode)
     32{
     33	int level, iip, level_search = 0;
     34	struct ubifs_znode *zn;
     35
     36	ubifs_assert(c, zr);
     37
     38	if (unlikely(!znode))
     39		return zr;
     40
     41	if (unlikely(znode == zr)) {
     42		if (znode->level == 0)
     43			return NULL;
     44		return ubifs_tnc_find_child(zr, 0);
     45	}
     46
     47	level = znode->level;
     48
     49	iip = znode->iip;
     50	while (1) {
     51		ubifs_assert(c, znode->level <= zr->level);
     52
     53		/*
     54		 * First walk up until there is a znode with next branch to
     55		 * look at.
     56		 */
     57		while (znode->parent != zr && iip >= znode->parent->child_cnt) {
     58			znode = znode->parent;
     59			iip = znode->iip;
     60		}
     61
     62		if (unlikely(znode->parent == zr &&
     63			     iip >= znode->parent->child_cnt)) {
     64			/* This level is done, switch to the lower one */
     65			level -= 1;
     66			if (level_search || level < 0)
     67				/*
     68				 * We were already looking for znode at lower
     69				 * level ('level_search'). As we are here
     70				 * again, it just does not exist. Or all levels
     71				 * were finished ('level < 0').
     72				 */
     73				return NULL;
     74
     75			level_search = 1;
     76			iip = -1;
     77			znode = ubifs_tnc_find_child(zr, 0);
     78			ubifs_assert(c, znode);
     79		}
     80
     81		/* Switch to the next index */
     82		zn = ubifs_tnc_find_child(znode->parent, iip + 1);
     83		if (!zn) {
     84			/* No more children to look at, we have walk up */
     85			iip = znode->parent->child_cnt;
     86			continue;
     87		}
     88
     89		/* Walk back down to the level we came from ('level') */
     90		while (zn->level != level) {
     91			znode = zn;
     92			zn = ubifs_tnc_find_child(zn, 0);
     93			if (!zn) {
     94				/*
     95				 * This path is not too deep so it does not
     96				 * reach 'level'. Try next path.
     97				 */
     98				iip = znode->iip;
     99				break;
    100			}
    101		}
    102
    103		if (zn) {
    104			ubifs_assert(c, zn->level >= 0);
    105			return zn;
    106		}
    107	}
    108}
    109
    110/**
    111 * ubifs_search_zbranch - search znode branch.
    112 * @c: UBIFS file-system description object
    113 * @znode: znode to search in
    114 * @key: key to search for
    115 * @n: znode branch slot number is returned here
    116 *
    117 * This is a helper function which search branch with key @key in @znode using
    118 * binary search. The result of the search may be:
    119 *   o exact match, then %1 is returned, and the slot number of the branch is
    120 *     stored in @n;
    121 *   o no exact match, then %0 is returned and the slot number of the left
    122 *     closest branch is returned in @n; the slot if all keys in this znode are
    123 *     greater than @key, then %-1 is returned in @n.
    124 */
    125int ubifs_search_zbranch(const struct ubifs_info *c,
    126			 const struct ubifs_znode *znode,
    127			 const union ubifs_key *key, int *n)
    128{
    129	int beg = 0, end = znode->child_cnt, mid;
    130	int cmp;
    131	const struct ubifs_zbranch *zbr = &znode->zbranch[0];
    132
    133	ubifs_assert(c, end > beg);
    134
    135	while (end > beg) {
    136		mid = (beg + end) >> 1;
    137		cmp = keys_cmp(c, key, &zbr[mid].key);
    138		if (cmp > 0)
    139			beg = mid + 1;
    140		else if (cmp < 0)
    141			end = mid;
    142		else {
    143			*n = mid;
    144			return 1;
    145		}
    146	}
    147
    148	*n = end - 1;
    149
    150	/* The insert point is after *n */
    151	ubifs_assert(c, *n >= -1 && *n < znode->child_cnt);
    152	if (*n == -1)
    153		ubifs_assert(c, keys_cmp(c, key, &zbr[0].key) < 0);
    154	else
    155		ubifs_assert(c, keys_cmp(c, key, &zbr[*n].key) > 0);
    156	if (*n + 1 < znode->child_cnt)
    157		ubifs_assert(c, keys_cmp(c, key, &zbr[*n + 1].key) < 0);
    158
    159	return 0;
    160}
    161
    162/**
    163 * ubifs_tnc_postorder_first - find first znode to do postorder tree traversal.
    164 * @znode: znode to start at (root of the sub-tree to traverse)
    165 *
    166 * Find the lowest leftmost znode in a subtree of the TNC tree. The LNC is
    167 * ignored.
    168 */
    169struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode)
    170{
    171	if (unlikely(!znode))
    172		return NULL;
    173
    174	while (znode->level > 0) {
    175		struct ubifs_znode *child;
    176
    177		child = ubifs_tnc_find_child(znode, 0);
    178		if (!child)
    179			return znode;
    180		znode = child;
    181	}
    182
    183	return znode;
    184}
    185
    186/**
    187 * ubifs_tnc_postorder_next - next TNC tree element in postorder traversal.
    188 * @c: UBIFS file-system description object
    189 * @znode: previous znode
    190 *
    191 * This function implements postorder TNC traversal. The LNC is ignored.
    192 * Returns the next element or %NULL if @znode is already the last one.
    193 */
    194struct ubifs_znode *ubifs_tnc_postorder_next(const struct ubifs_info *c,
    195					     struct ubifs_znode *znode)
    196{
    197	struct ubifs_znode *zn;
    198
    199	ubifs_assert(c, znode);
    200	if (unlikely(!znode->parent))
    201		return NULL;
    202
    203	/* Switch to the next index in the parent */
    204	zn = ubifs_tnc_find_child(znode->parent, znode->iip + 1);
    205	if (!zn)
    206		/* This is in fact the last child, return parent */
    207		return znode->parent;
    208
    209	/* Go to the first znode in this new subtree */
    210	return ubifs_tnc_postorder_first(zn);
    211}
    212
    213/**
    214 * ubifs_destroy_tnc_subtree - destroy all znodes connected to a subtree.
    215 * @c: UBIFS file-system description object
    216 * @znode: znode defining subtree to destroy
    217 *
    218 * This function destroys subtree of the TNC tree. Returns number of clean
    219 * znodes in the subtree.
    220 */
    221long ubifs_destroy_tnc_subtree(const struct ubifs_info *c,
    222			       struct ubifs_znode *znode)
    223{
    224	struct ubifs_znode *zn = ubifs_tnc_postorder_first(znode);
    225	long clean_freed = 0;
    226	int n;
    227
    228	ubifs_assert(c, zn);
    229	while (1) {
    230		for (n = 0; n < zn->child_cnt; n++) {
    231			if (!zn->zbranch[n].znode)
    232				continue;
    233
    234			if (zn->level > 0 &&
    235			    !ubifs_zn_dirty(zn->zbranch[n].znode))
    236				clean_freed += 1;
    237
    238			cond_resched();
    239			kfree(zn->zbranch[n].znode);
    240		}
    241
    242		if (zn == znode) {
    243			if (!ubifs_zn_dirty(zn))
    244				clean_freed += 1;
    245			kfree(zn);
    246			return clean_freed;
    247		}
    248
    249		zn = ubifs_tnc_postorder_next(c, zn);
    250	}
    251}
    252
    253/**
    254 * read_znode - read an indexing node from flash and fill znode.
    255 * @c: UBIFS file-system description object
    256 * @zzbr: the zbranch describing the node to read
    257 * @znode: znode to read to
    258 *
    259 * This function reads an indexing node from the flash media and fills znode
    260 * with the read data. Returns zero in case of success and a negative error
    261 * code in case of failure. The read indexing node is validated and if anything
    262 * is wrong with it, this function prints complaint messages and returns
    263 * %-EINVAL.
    264 */
    265static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr,
    266		      struct ubifs_znode *znode)
    267{
    268	int lnum = zzbr->lnum;
    269	int offs = zzbr->offs;
    270	int len = zzbr->len;
    271	int i, err, type, cmp;
    272	struct ubifs_idx_node *idx;
    273
    274	idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
    275	if (!idx)
    276		return -ENOMEM;
    277
    278	err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
    279	if (err < 0) {
    280		kfree(idx);
    281		return err;
    282	}
    283
    284	err = ubifs_node_check_hash(c, idx, zzbr->hash);
    285	if (err) {
    286		ubifs_bad_hash(c, idx, zzbr->hash, lnum, offs);
    287		kfree(idx);
    288		return err;
    289	}
    290
    291	znode->child_cnt = le16_to_cpu(idx->child_cnt);
    292	znode->level = le16_to_cpu(idx->level);
    293
    294	dbg_tnc("LEB %d:%d, level %d, %d branch",
    295		lnum, offs, znode->level, znode->child_cnt);
    296
    297	if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
    298		ubifs_err(c, "current fanout %d, branch count %d",
    299			  c->fanout, znode->child_cnt);
    300		ubifs_err(c, "max levels %d, znode level %d",
    301			  UBIFS_MAX_LEVELS, znode->level);
    302		err = 1;
    303		goto out_dump;
    304	}
    305
    306	for (i = 0; i < znode->child_cnt; i++) {
    307		struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
    308		struct ubifs_zbranch *zbr = &znode->zbranch[i];
    309
    310		key_read(c, &br->key, &zbr->key);
    311		zbr->lnum = le32_to_cpu(br->lnum);
    312		zbr->offs = le32_to_cpu(br->offs);
    313		zbr->len  = le32_to_cpu(br->len);
    314		ubifs_copy_hash(c, ubifs_branch_hash(c, br), zbr->hash);
    315		zbr->znode = NULL;
    316
    317		/* Validate branch */
    318
    319		if (zbr->lnum < c->main_first ||
    320		    zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
    321		    zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
    322			ubifs_err(c, "bad branch %d", i);
    323			err = 2;
    324			goto out_dump;
    325		}
    326
    327		switch (key_type(c, &zbr->key)) {
    328		case UBIFS_INO_KEY:
    329		case UBIFS_DATA_KEY:
    330		case UBIFS_DENT_KEY:
    331		case UBIFS_XENT_KEY:
    332			break;
    333		default:
    334			ubifs_err(c, "bad key type at slot %d: %d",
    335				  i, key_type(c, &zbr->key));
    336			err = 3;
    337			goto out_dump;
    338		}
    339
    340		if (znode->level)
    341			continue;
    342
    343		type = key_type(c, &zbr->key);
    344		if (c->ranges[type].max_len == 0) {
    345			if (zbr->len != c->ranges[type].len) {
    346				ubifs_err(c, "bad target node (type %d) length (%d)",
    347					  type, zbr->len);
    348				ubifs_err(c, "have to be %d", c->ranges[type].len);
    349				err = 4;
    350				goto out_dump;
    351			}
    352		} else if (zbr->len < c->ranges[type].min_len ||
    353			   zbr->len > c->ranges[type].max_len) {
    354			ubifs_err(c, "bad target node (type %d) length (%d)",
    355				  type, zbr->len);
    356			ubifs_err(c, "have to be in range of %d-%d",
    357				  c->ranges[type].min_len,
    358				  c->ranges[type].max_len);
    359			err = 5;
    360			goto out_dump;
    361		}
    362	}
    363
    364	/*
    365	 * Ensure that the next key is greater or equivalent to the
    366	 * previous one.
    367	 */
    368	for (i = 0; i < znode->child_cnt - 1; i++) {
    369		const union ubifs_key *key1, *key2;
    370
    371		key1 = &znode->zbranch[i].key;
    372		key2 = &znode->zbranch[i + 1].key;
    373
    374		cmp = keys_cmp(c, key1, key2);
    375		if (cmp > 0) {
    376			ubifs_err(c, "bad key order (keys %d and %d)", i, i + 1);
    377			err = 6;
    378			goto out_dump;
    379		} else if (cmp == 0 && !is_hash_key(c, key1)) {
    380			/* These can only be keys with colliding hash */
    381			ubifs_err(c, "keys %d and %d are not hashed but equivalent",
    382				  i, i + 1);
    383			err = 7;
    384			goto out_dump;
    385		}
    386	}
    387
    388	kfree(idx);
    389	return 0;
    390
    391out_dump:
    392	ubifs_err(c, "bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
    393	ubifs_dump_node(c, idx, c->max_idx_node_sz);
    394	kfree(idx);
    395	return -EINVAL;
    396}
    397
    398/**
    399 * ubifs_load_znode - load znode to TNC cache.
    400 * @c: UBIFS file-system description object
    401 * @zbr: znode branch
    402 * @parent: znode's parent
    403 * @iip: index in parent
    404 *
    405 * This function loads znode pointed to by @zbr into the TNC cache and
    406 * returns pointer to it in case of success and a negative error code in case
    407 * of failure.
    408 */
    409struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
    410				     struct ubifs_zbranch *zbr,
    411				     struct ubifs_znode *parent, int iip)
    412{
    413	int err;
    414	struct ubifs_znode *znode;
    415
    416	ubifs_assert(c, !zbr->znode);
    417	/*
    418	 * A slab cache is not presently used for znodes because the znode size
    419	 * depends on the fanout which is stored in the superblock.
    420	 */
    421	znode = kzalloc(c->max_znode_sz, GFP_NOFS);
    422	if (!znode)
    423		return ERR_PTR(-ENOMEM);
    424
    425	err = read_znode(c, zbr, znode);
    426	if (err)
    427		goto out;
    428
    429	atomic_long_inc(&c->clean_zn_cnt);
    430
    431	/*
    432	 * Increment the global clean znode counter as well. It is OK that
    433	 * global and per-FS clean znode counters may be inconsistent for some
    434	 * short time (because we might be preempted at this point), the global
    435	 * one is only used in shrinker.
    436	 */
    437	atomic_long_inc(&ubifs_clean_zn_cnt);
    438
    439	zbr->znode = znode;
    440	znode->parent = parent;
    441	znode->time = ktime_get_seconds();
    442	znode->iip = iip;
    443
    444	return znode;
    445
    446out:
    447	kfree(znode);
    448	return ERR_PTR(err);
    449}
    450
    451/**
    452 * ubifs_tnc_read_node - read a leaf node from the flash media.
    453 * @c: UBIFS file-system description object
    454 * @zbr: key and position of the node
    455 * @node: node is returned here
    456 *
    457 * This function reads a node defined by @zbr from the flash media. Returns
    458 * zero in case of success or a negative error code in case of failure.
    459 */
    460int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
    461			void *node)
    462{
    463	union ubifs_key key1, *key = &zbr->key;
    464	int err, type = key_type(c, key);
    465	struct ubifs_wbuf *wbuf;
    466
    467	/*
    468	 * 'zbr' has to point to on-flash node. The node may sit in a bud and
    469	 * may even be in a write buffer, so we have to take care about this.
    470	 */
    471	wbuf = ubifs_get_wbuf(c, zbr->lnum);
    472	if (wbuf)
    473		err = ubifs_read_node_wbuf(wbuf, node, type, zbr->len,
    474					   zbr->lnum, zbr->offs);
    475	else
    476		err = ubifs_read_node(c, node, type, zbr->len, zbr->lnum,
    477				      zbr->offs);
    478
    479	if (err) {
    480		dbg_tnck(key, "key ");
    481		return err;
    482	}
    483
    484	/* Make sure the key of the read node is correct */
    485	key_read(c, node + UBIFS_KEY_OFFSET, &key1);
    486	if (!keys_eq(c, key, &key1)) {
    487		ubifs_err(c, "bad key in node at LEB %d:%d",
    488			  zbr->lnum, zbr->offs);
    489		dbg_tnck(key, "looked for key ");
    490		dbg_tnck(&key1, "but found node's key ");
    491		ubifs_dump_node(c, node, zbr->len);
    492		return -EINVAL;
    493	}
    494
    495	err = ubifs_node_check_hash(c, node, zbr->hash);
    496	if (err) {
    497		ubifs_bad_hash(c, node, zbr->hash, zbr->lnum, zbr->offs);
    498		return err;
    499	}
    500
    501	return 0;
    502}