| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0-only  | 
|---|
| 1 | 2 |  /* | 
|---|
| 2 | 3 |   * This file is part of UBIFS. | 
|---|
| 3 | 4 |   * | 
|---|
| 4 | 5 |   * Copyright (C) 2006-2008 Nokia Corporation. | 
|---|
| 5 | 6 |   * Copyright (C) 2006, 2007 University of Szeged, Hungary | 
|---|
| 6 |  | - *  | 
|---|
| 7 |  | - * This program is free software; you can redistribute it and/or modify it  | 
|---|
| 8 |  | - * under the terms of the GNU General Public License version 2 as published by  | 
|---|
| 9 |  | - * the Free Software Foundation.  | 
|---|
| 10 |  | - *  | 
|---|
| 11 |  | - * This program is distributed in the hope that it will be useful, but WITHOUT  | 
|---|
| 12 |  | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  | 
|---|
| 13 |  | - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  | 
|---|
| 14 |  | - * more details.  | 
|---|
| 15 |  | - *  | 
|---|
| 16 |  | - * You should have received a copy of the GNU General Public License along with  | 
|---|
| 17 |  | - * this program; if not, write to the Free Software Foundation, Inc., 51  | 
|---|
| 18 |  | - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  | 
|---|
| 19 | 7 |   * | 
|---|
| 20 | 8 |   * Authors: Artem Bityutskiy (Битюцкий Артём) | 
|---|
| 21 | 9 |   *          Adrian Hunter | 
|---|
| .. | .. | 
|---|
| 377 | 365 |  	return sqnum; | 
|---|
| 378 | 366 |  } | 
|---|
| 379 | 367 |   | 
|---|
 | 368 | +void ubifs_init_node(struct ubifs_info *c, void *node, int len, int pad)  | 
|---|
 | 369 | +{  | 
|---|
 | 370 | +	struct ubifs_ch *ch = node;  | 
|---|
 | 371 | +	unsigned long long sqnum = next_sqnum(c);  | 
|---|
 | 372 | +  | 
|---|
 | 373 | +	ubifs_assert(c, len >= UBIFS_CH_SZ);  | 
|---|
 | 374 | +  | 
|---|
 | 375 | +	ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);  | 
|---|
 | 376 | +	ch->len = cpu_to_le32(len);  | 
|---|
 | 377 | +	ch->group_type = UBIFS_NO_NODE_GROUP;  | 
|---|
 | 378 | +	ch->sqnum = cpu_to_le64(sqnum);  | 
|---|
 | 379 | +	ch->padding[0] = ch->padding[1] = 0;  | 
|---|
 | 380 | +  | 
|---|
 | 381 | +	if (pad) {  | 
|---|
 | 382 | +		len = ALIGN(len, 8);  | 
|---|
 | 383 | +		pad = ALIGN(len, c->min_io_size) - len;  | 
|---|
 | 384 | +		ubifs_pad(c, node + len, pad);  | 
|---|
 | 385 | +	}  | 
|---|
 | 386 | +}  | 
|---|
 | 387 | +  | 
|---|
 | 388 | +void ubifs_crc_node(struct ubifs_info *c, void *node, int len)  | 
|---|
 | 389 | +{  | 
|---|
 | 390 | +	struct ubifs_ch *ch = node;  | 
|---|
 | 391 | +	uint32_t crc;  | 
|---|
 | 392 | +  | 
|---|
 | 393 | +	crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);  | 
|---|
 | 394 | +	ch->crc = cpu_to_le32(crc);  | 
|---|
 | 395 | +}  | 
|---|
 | 396 | +  | 
|---|
 | 397 | +/**  | 
|---|
 | 398 | + * ubifs_prepare_node_hmac - prepare node to be written to flash.  | 
|---|
 | 399 | + * @c: UBIFS file-system description object  | 
|---|
 | 400 | + * @node: the node to pad  | 
|---|
 | 401 | + * @len: node length  | 
|---|
 | 402 | + * @hmac_offs: offset of the HMAC in the node  | 
|---|
 | 403 | + * @pad: if the buffer has to be padded  | 
|---|
 | 404 | + *  | 
|---|
 | 405 | + * This function prepares node at @node to be written to the media - it  | 
|---|
 | 406 | + * calculates node CRC, fills the common header, and adds proper padding up to  | 
|---|
 | 407 | + * the next minimum I/O unit if @pad is not zero. if @hmac_offs is positive then  | 
|---|
 | 408 | + * a HMAC is inserted into the node at the given offset.  | 
|---|
 | 409 | + *  | 
|---|
 | 410 | + * This function returns 0 for success or a negative error code otherwise.  | 
|---|
 | 411 | + */  | 
|---|
 | 412 | +int ubifs_prepare_node_hmac(struct ubifs_info *c, void *node, int len,  | 
|---|
 | 413 | +			    int hmac_offs, int pad)  | 
|---|
 | 414 | +{  | 
|---|
 | 415 | +	int err;  | 
|---|
 | 416 | +  | 
|---|
 | 417 | +	ubifs_init_node(c, node, len, pad);  | 
|---|
 | 418 | +  | 
|---|
 | 419 | +	if (hmac_offs > 0) {  | 
|---|
 | 420 | +		err = ubifs_node_insert_hmac(c, node, len, hmac_offs);  | 
|---|
 | 421 | +		if (err)  | 
|---|
 | 422 | +			return err;  | 
|---|
 | 423 | +	}  | 
|---|
 | 424 | +  | 
|---|
 | 425 | +	ubifs_crc_node(c, node, len);  | 
|---|
 | 426 | +  | 
|---|
 | 427 | +	return 0;  | 
|---|
 | 428 | +}  | 
|---|
 | 429 | +  | 
|---|
| 380 | 430 |  /** | 
|---|
| 381 | 431 |   * ubifs_prepare_node - prepare node to be written to flash. | 
|---|
| 382 | 432 |   * @c: UBIFS file-system description object | 
|---|
| .. | .. | 
|---|
| 390 | 440 |   */ | 
|---|
| 391 | 441 |  void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad) | 
|---|
| 392 | 442 |  { | 
|---|
| 393 |  | -	uint32_t crc;  | 
|---|
| 394 |  | -	struct ubifs_ch *ch = node;  | 
|---|
| 395 |  | -	unsigned long long sqnum = next_sqnum(c);  | 
|---|
| 396 |  | -  | 
|---|
| 397 |  | -	ubifs_assert(c, len >= UBIFS_CH_SZ);  | 
|---|
| 398 |  | -  | 
|---|
| 399 |  | -	ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);  | 
|---|
| 400 |  | -	ch->len = cpu_to_le32(len);  | 
|---|
| 401 |  | -	ch->group_type = UBIFS_NO_NODE_GROUP;  | 
|---|
| 402 |  | -	ch->sqnum = cpu_to_le64(sqnum);  | 
|---|
| 403 |  | -	ch->padding[0] = ch->padding[1] = 0;  | 
|---|
| 404 |  | -	crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);  | 
|---|
| 405 |  | -	ch->crc = cpu_to_le32(crc);  | 
|---|
| 406 |  | -  | 
|---|
| 407 |  | -	if (pad) {  | 
|---|
| 408 |  | -		len = ALIGN(len, 8);  | 
|---|
| 409 |  | -		pad = ALIGN(len, c->min_io_size) - len;  | 
|---|
| 410 |  | -		ubifs_pad(c, node + len, pad);  | 
|---|
| 411 |  | -	}  | 
|---|
 | 443 | +	/*  | 
|---|
 | 444 | +	 * Deliberately ignore return value since this function can only fail  | 
|---|
 | 445 | +	 * when a hmac offset is given.  | 
|---|
 | 446 | +	 */  | 
|---|
 | 447 | +	ubifs_prepare_node_hmac(c, node, len, 0, pad);  | 
|---|
| 412 | 448 |  } | 
|---|
| 413 | 449 |   | 
|---|
| 414 | 450 |  /** | 
|---|
| .. | .. | 
|---|
| 810 | 846 |  	 */ | 
|---|
| 811 | 847 |  	n = aligned_len >> c->max_write_shift; | 
|---|
| 812 | 848 |  	if (n) { | 
|---|
| 813 |  | -		n <<= c->max_write_shift;  | 
|---|
 | 849 | +		int m = n - 1;  | 
|---|
 | 850 | +  | 
|---|
| 814 | 851 |  		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, | 
|---|
| 815 | 852 |  		       wbuf->offs); | 
|---|
| 816 |  | -		err = ubifs_leb_write(c, wbuf->lnum, buf + written,  | 
|---|
| 817 |  | -				      wbuf->offs, n);  | 
|---|
 | 853 | +  | 
|---|
 | 854 | +		if (m) {  | 
|---|
 | 855 | +			/* '(n-1)<<c->max_write_shift < len' is always true. */  | 
|---|
 | 856 | +			m <<= c->max_write_shift;  | 
|---|
 | 857 | +			err = ubifs_leb_write(c, wbuf->lnum, buf + written,  | 
|---|
 | 858 | +					      wbuf->offs, m);  | 
|---|
 | 859 | +			if (err)  | 
|---|
 | 860 | +				goto out;  | 
|---|
 | 861 | +			wbuf->offs += m;  | 
|---|
 | 862 | +			aligned_len -= m;  | 
|---|
 | 863 | +			len -= m;  | 
|---|
 | 864 | +			written += m;  | 
|---|
 | 865 | +		}  | 
|---|
 | 866 | +  | 
|---|
 | 867 | +		/*  | 
|---|
 | 868 | +		 * The non-written len of buf may be less than 'n' because  | 
|---|
 | 869 | +		 * parameter 'len' is not 8 bytes aligned, so here we read  | 
|---|
 | 870 | +		 * min(len, n) bytes from buf.  | 
|---|
 | 871 | +		 */  | 
|---|
 | 872 | +		n = 1 << c->max_write_shift;  | 
|---|
 | 873 | +		memcpy(wbuf->buf, buf + written, min(len, n));  | 
|---|
 | 874 | +		if (n > len) {  | 
|---|
 | 875 | +			ubifs_assert(c, n - len < 8);  | 
|---|
 | 876 | +			ubifs_pad(c, wbuf->buf + len, n - len);  | 
|---|
 | 877 | +		}  | 
|---|
 | 878 | +  | 
|---|
 | 879 | +		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, n);  | 
|---|
| 818 | 880 |  		if (err) | 
|---|
| 819 | 881 |  			goto out; | 
|---|
| 820 | 882 |  		wbuf->offs += n; | 
|---|
| 821 | 883 |  		aligned_len -= n; | 
|---|
| 822 |  | -		len -= n;  | 
|---|
 | 884 | +		len -= min(len, n);  | 
|---|
| 823 | 885 |  		written += n; | 
|---|
| 824 | 886 |  	} | 
|---|
| 825 | 887 |   | 
|---|
| .. | .. | 
|---|
| 870 | 932 |  } | 
|---|
| 871 | 933 |   | 
|---|
| 872 | 934 |  /** | 
|---|
 | 935 | + * ubifs_write_node_hmac - write node to the media.  | 
|---|
 | 936 | + * @c: UBIFS file-system description object  | 
|---|
 | 937 | + * @buf: the node to write  | 
|---|
 | 938 | + * @len: node length  | 
|---|
 | 939 | + * @lnum: logical eraseblock number  | 
|---|
 | 940 | + * @offs: offset within the logical eraseblock  | 
|---|
 | 941 | + * @hmac_offs: offset of the HMAC within the node  | 
|---|
 | 942 | + *  | 
|---|
 | 943 | + * This function automatically fills node magic number, assigns sequence  | 
|---|
 | 944 | + * number, and calculates node CRC checksum. The length of the @buf buffer has  | 
|---|
 | 945 | + * to be aligned to the minimal I/O unit size. This function automatically  | 
|---|
 | 946 | + * appends padding node and padding bytes if needed. Returns zero in case of  | 
|---|
 | 947 | + * success and a negative error code in case of failure.  | 
|---|
 | 948 | + */  | 
|---|
 | 949 | +int ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum,  | 
|---|
 | 950 | +			  int offs, int hmac_offs)  | 
|---|
 | 951 | +{  | 
|---|
 | 952 | +	int err, buf_len = ALIGN(len, c->min_io_size);  | 
|---|
 | 953 | +  | 
|---|
 | 954 | +	dbg_io("LEB %d:%d, %s, length %d (aligned %d)",  | 
|---|
 | 955 | +	       lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len,  | 
|---|
 | 956 | +	       buf_len);  | 
|---|
 | 957 | +	ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);  | 
|---|
 | 958 | +	ubifs_assert(c, offs % c->min_io_size == 0 && offs < c->leb_size);  | 
|---|
 | 959 | +	ubifs_assert(c, !c->ro_media && !c->ro_mount);  | 
|---|
 | 960 | +	ubifs_assert(c, !c->space_fixup);  | 
|---|
 | 961 | +  | 
|---|
 | 962 | +	if (c->ro_error)  | 
|---|
 | 963 | +		return -EROFS;  | 
|---|
 | 964 | +  | 
|---|
 | 965 | +	err = ubifs_prepare_node_hmac(c, buf, len, hmac_offs, 1);  | 
|---|
 | 966 | +	if (err)  | 
|---|
 | 967 | +		return err;  | 
|---|
 | 968 | +  | 
|---|
 | 969 | +	err = ubifs_leb_write(c, lnum, buf, offs, buf_len);  | 
|---|
 | 970 | +	if (err)  | 
|---|
 | 971 | +		ubifs_dump_node(c, buf);  | 
|---|
 | 972 | +  | 
|---|
 | 973 | +	return err;  | 
|---|
 | 974 | +}  | 
|---|
 | 975 | +  | 
|---|
 | 976 | +/**  | 
|---|
| 873 | 977 |   * ubifs_write_node - write node to the media. | 
|---|
| 874 | 978 |   * @c: UBIFS file-system description object | 
|---|
| 875 | 979 |   * @buf: the node to write | 
|---|
| .. | .. | 
|---|
| 886 | 990 |  int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | 
|---|
| 887 | 991 |  		     int offs) | 
|---|
| 888 | 992 |  { | 
|---|
| 889 |  | -	int err, buf_len = ALIGN(len, c->min_io_size);  | 
|---|
| 890 |  | -  | 
|---|
| 891 |  | -	dbg_io("LEB %d:%d, %s, length %d (aligned %d)",  | 
|---|
| 892 |  | -	       lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len,  | 
|---|
| 893 |  | -	       buf_len);  | 
|---|
| 894 |  | -	ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);  | 
|---|
| 895 |  | -	ubifs_assert(c, offs % c->min_io_size == 0 && offs < c->leb_size);  | 
|---|
| 896 |  | -	ubifs_assert(c, !c->ro_media && !c->ro_mount);  | 
|---|
| 897 |  | -	ubifs_assert(c, !c->space_fixup);  | 
|---|
| 898 |  | -  | 
|---|
| 899 |  | -	if (c->ro_error)  | 
|---|
| 900 |  | -		return -EROFS;  | 
|---|
| 901 |  | -  | 
|---|
| 902 |  | -	ubifs_prepare_node(c, buf, len, 1);  | 
|---|
| 903 |  | -	err = ubifs_leb_write(c, lnum, buf, offs, buf_len);  | 
|---|
| 904 |  | -	if (err)  | 
|---|
| 905 |  | -		ubifs_dump_node(c, buf);  | 
|---|
| 906 |  | -  | 
|---|
| 907 |  | -	return err;  | 
|---|
 | 993 | +	return ubifs_write_node_hmac(c, buf, len, lnum, offs, -1);  | 
|---|
| 908 | 994 |  } | 
|---|
| 909 | 995 |   | 
|---|
| 910 | 996 |  /** | 
|---|