| .. | .. | 
|---|
 | 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 |  | - * This program is free software; you can redistribute it and/or modify it  | 
|---|
| 7 |  | - * under the terms of the GNU General Public License version 2 as published by  | 
|---|
| 8 |  | - * the Free Software Foundation.  | 
|---|
| 9 |  | - *  | 
|---|
| 10 |  | - * This program is distributed in the hope that it will be useful, but WITHOUT  | 
|---|
| 11 |  | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  | 
|---|
| 12 |  | - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  | 
|---|
| 13 |  | - * more details.  | 
|---|
| 14 |  | - *  | 
|---|
| 15 |  | - * You should have received a copy of the GNU General Public License along with  | 
|---|
| 16 |  | - * this program; if not, write to the Free Software Foundation, Inc., 51  | 
|---|
| 17 |  | - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  | 
|---|
| 18 | 6 |   * | 
|---|
| 19 | 7 |   * Authors: Artem Bityutskiy (Битюцкий Артём) | 
|---|
| 20 | 8 |   *          Adrian Hunter | 
|---|
| .. | .. | 
|---|
| 93 | 81 |  	int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first; | 
|---|
| 94 | 82 |  	int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0; | 
|---|
| 95 | 83 |  	int min_leb_cnt = UBIFS_MIN_LEB_CNT; | 
|---|
 | 84 | +	int idx_node_size;  | 
|---|
| 96 | 85 |  	long long tmp64, main_bytes; | 
|---|
| 97 | 86 |  	__le64 tmp_le64; | 
|---|
| 98 |  | -	__le32 tmp_le32;  | 
|---|
| 99 | 87 |  	struct timespec64 ts; | 
|---|
 | 88 | +	u8 hash[UBIFS_HASH_ARR_SZ];  | 
|---|
 | 89 | +	u8 hash_lpt[UBIFS_HASH_ARR_SZ];  | 
|---|
| 100 | 90 |   | 
|---|
| 101 | 91 |  	/* Some functions called from here depend on the @c->key_len filed */ | 
|---|
| 102 | 92 |  	c->key_len = UBIFS_SK_LEN; | 
|---|
| .. | .. | 
|---|
| 158 | 148 |  	c->lsave_cnt = DEFAULT_LSAVE_CNT; | 
|---|
| 159 | 149 |  	c->max_leb_cnt = c->leb_cnt; | 
|---|
| 160 | 150 |  	err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs, | 
|---|
| 161 |  | -				    &big_lpt);  | 
|---|
 | 151 | +				    &big_lpt, hash_lpt);  | 
|---|
| 162 | 152 |  	if (err) | 
|---|
| 163 | 153 |  		return err; | 
|---|
| 164 | 154 |   | 
|---|
| .. | .. | 
|---|
| 167 | 157 |   | 
|---|
| 168 | 158 |  	main_first = c->leb_cnt - main_lebs; | 
|---|
| 169 | 159 |   | 
|---|
 | 160 | +	sup = kzalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_KERNEL);  | 
|---|
 | 161 | +	mst = kzalloc(c->mst_node_alsz, GFP_KERNEL);  | 
|---|
 | 162 | +	idx_node_size = ubifs_idx_node_sz(c, 1);  | 
|---|
 | 163 | +	idx = kzalloc(ALIGN(idx_node_size, c->min_io_size), GFP_KERNEL);  | 
|---|
 | 164 | +	ino = kzalloc(ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size), GFP_KERNEL);  | 
|---|
 | 165 | +	cs = kzalloc(ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size), GFP_KERNEL);  | 
|---|
 | 166 | +  | 
|---|
 | 167 | +	if (!sup || !mst || !idx || !ino || !cs) {  | 
|---|
 | 168 | +		err = -ENOMEM;  | 
|---|
 | 169 | +		goto out;  | 
|---|
 | 170 | +	}  | 
|---|
 | 171 | +  | 
|---|
| 170 | 172 |  	/* Create default superblock */ | 
|---|
| 171 |  | -	tmp = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);  | 
|---|
| 172 |  | -	sup = kzalloc(tmp, GFP_KERNEL);  | 
|---|
| 173 |  | -	if (!sup)  | 
|---|
| 174 |  | -		return -ENOMEM;  | 
|---|
| 175 | 173 |   | 
|---|
| 176 | 174 |  	tmp64 = (long long)max_buds * c->leb_size; | 
|---|
| 177 | 175 |  	if (big_lpt) | 
|---|
| 178 | 176 |  		sup_flags |= UBIFS_FLG_BIGLPT; | 
|---|
| 179 |  | -	sup_flags |= UBIFS_FLG_DOUBLE_HASH;  | 
|---|
 | 177 | +	if (ubifs_default_version > 4)  | 
|---|
 | 178 | +		sup_flags |= UBIFS_FLG_DOUBLE_HASH;  | 
|---|
 | 179 | +  | 
|---|
 | 180 | +	if (ubifs_authenticated(c)) {  | 
|---|
 | 181 | +		sup_flags |= UBIFS_FLG_AUTHENTICATION;  | 
|---|
 | 182 | +		sup->hash_algo = cpu_to_le16(c->auth_hash_algo);  | 
|---|
 | 183 | +		err = ubifs_hmac_wkm(c, sup->hmac_wkm);  | 
|---|
 | 184 | +		if (err)  | 
|---|
 | 185 | +			goto out;  | 
|---|
 | 186 | +	} else {  | 
|---|
 | 187 | +		sup->hash_algo = cpu_to_le16(0xffff);  | 
|---|
 | 188 | +	}  | 
|---|
| 180 | 189 |   | 
|---|
| 181 | 190 |  	sup->ch.node_type  = UBIFS_SB_NODE; | 
|---|
| 182 | 191 |  	sup->key_hash      = UBIFS_KEY_HASH_R5; | 
|---|
| .. | .. | 
|---|
| 192 | 201 |  	sup->jhead_cnt     = cpu_to_le32(DEFAULT_JHEADS_CNT); | 
|---|
| 193 | 202 |  	sup->fanout        = cpu_to_le32(DEFAULT_FANOUT); | 
|---|
| 194 | 203 |  	sup->lsave_cnt     = cpu_to_le32(c->lsave_cnt); | 
|---|
| 195 |  | -	sup->fmt_version   = cpu_to_le32(UBIFS_FORMAT_VERSION);  | 
|---|
 | 204 | +	sup->fmt_version   = cpu_to_le32(ubifs_default_version);  | 
|---|
| 196 | 205 |  	sup->time_gran     = cpu_to_le32(DEFAULT_TIME_GRAN); | 
|---|
| 197 | 206 |  	if (c->mount_opts.override_compr) | 
|---|
| 198 | 207 |  		sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); | 
|---|
| .. | .. | 
|---|
| 208 | 217 |  	sup->rp_size = cpu_to_le64(tmp64); | 
|---|
| 209 | 218 |  	sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION); | 
|---|
| 210 | 219 |   | 
|---|
| 211 |  | -	err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0);  | 
|---|
| 212 |  | -	kfree(sup);  | 
|---|
| 213 |  | -	if (err)  | 
|---|
| 214 |  | -		return err;  | 
|---|
| 215 |  | -  | 
|---|
| 216 | 220 |  	dbg_gen("default superblock created at LEB 0:0"); | 
|---|
| 217 | 221 |   | 
|---|
| 218 | 222 |  	/* Create default master node */ | 
|---|
| 219 |  | -	mst = kzalloc(c->mst_node_alsz, GFP_KERNEL);  | 
|---|
| 220 |  | -	if (!mst)  | 
|---|
| 221 |  | -		return -ENOMEM;  | 
|---|
| 222 | 223 |   | 
|---|
| 223 | 224 |  	mst->ch.node_type = UBIFS_MST_NODE; | 
|---|
| 224 | 225 |  	mst->log_lnum     = cpu_to_le32(UBIFS_LOG_LNUM); | 
|---|
| .. | .. | 
|---|
| 244 | 245 |  	mst->empty_lebs   = cpu_to_le32(main_lebs - 2); | 
|---|
| 245 | 246 |  	mst->idx_lebs     = cpu_to_le32(1); | 
|---|
| 246 | 247 |  	mst->leb_cnt      = cpu_to_le32(c->leb_cnt); | 
|---|
 | 248 | +	ubifs_copy_hash(c, hash_lpt, mst->hash_lpt);  | 
|---|
| 247 | 249 |   | 
|---|
| 248 | 250 |  	/* Calculate lprops statistics */ | 
|---|
| 249 | 251 |  	tmp64 = main_bytes; | 
|---|
| .. | .. | 
|---|
| 264 | 266 |   | 
|---|
| 265 | 267 |  	mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); | 
|---|
| 266 | 268 |   | 
|---|
| 267 |  | -	err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0);  | 
|---|
| 268 |  | -	if (err) {  | 
|---|
| 269 |  | -		kfree(mst);  | 
|---|
| 270 |  | -		return err;  | 
|---|
| 271 |  | -	}  | 
|---|
| 272 |  | -	err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1,  | 
|---|
| 273 |  | -			       0);  | 
|---|
| 274 |  | -	kfree(mst);  | 
|---|
| 275 |  | -	if (err)  | 
|---|
| 276 |  | -		return err;  | 
|---|
| 277 |  | -  | 
|---|
| 278 | 269 |  	dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM); | 
|---|
| 279 | 270 |   | 
|---|
| 280 | 271 |  	/* Create the root indexing node */ | 
|---|
| 281 |  | -	tmp = ubifs_idx_node_sz(c, 1);  | 
|---|
| 282 |  | -	idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL);  | 
|---|
| 283 |  | -	if (!idx)  | 
|---|
| 284 |  | -		return -ENOMEM;  | 
|---|
| 285 | 272 |   | 
|---|
| 286 | 273 |  	c->key_fmt = UBIFS_SIMPLE_KEY_FMT; | 
|---|
| 287 | 274 |  	c->key_hash = key_r5_hash; | 
|---|
| .. | .. | 
|---|
| 293 | 280 |  	key_write_idx(c, &key, &br->key); | 
|---|
| 294 | 281 |  	br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB); | 
|---|
| 295 | 282 |  	br->len  = cpu_to_le32(UBIFS_INO_NODE_SZ); | 
|---|
| 296 |  | -	err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0);  | 
|---|
| 297 |  | -	kfree(idx);  | 
|---|
| 298 |  | -	if (err)  | 
|---|
| 299 |  | -		return err;  | 
|---|
| 300 | 283 |   | 
|---|
| 301 | 284 |  	dbg_gen("default root indexing node created LEB %d:0", | 
|---|
| 302 | 285 |  		main_first + DEFAULT_IDX_LEB); | 
|---|
| 303 | 286 |   | 
|---|
| 304 | 287 |  	/* Create default root inode */ | 
|---|
| 305 |  | -	tmp = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size);  | 
|---|
| 306 |  | -	ino = kzalloc(tmp, GFP_KERNEL);  | 
|---|
| 307 |  | -	if (!ino)  | 
|---|
| 308 |  | -		return -ENOMEM;  | 
|---|
| 309 | 288 |   | 
|---|
| 310 | 289 |  	ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO); | 
|---|
| 311 | 290 |  	ino->ch.node_type = UBIFS_INO_NODE; | 
|---|
| 312 | 291 |  	ino->creat_sqnum = cpu_to_le64(++c->max_sqnum); | 
|---|
| 313 | 292 |  	ino->nlink = cpu_to_le32(2); | 
|---|
| 314 | 293 |   | 
|---|
| 315 |  | -	ktime_get_real_ts64(&ts);  | 
|---|
| 316 |  | -	ts = timespec64_trunc(ts, DEFAULT_TIME_GRAN);  | 
|---|
 | 294 | +	ktime_get_coarse_real_ts64(&ts);  | 
|---|
| 317 | 295 |  	tmp_le64 = cpu_to_le64(ts.tv_sec); | 
|---|
| 318 | 296 |  	ino->atime_sec   = tmp_le64; | 
|---|
| 319 | 297 |  	ino->ctime_sec   = tmp_le64; | 
|---|
| 320 | 298 |  	ino->mtime_sec   = tmp_le64; | 
|---|
| 321 |  | -	tmp_le32 = cpu_to_le32(ts.tv_nsec);  | 
|---|
| 322 |  | -	ino->atime_nsec  = tmp_le32;  | 
|---|
| 323 |  | -	ino->ctime_nsec  = tmp_le32;  | 
|---|
| 324 |  | -	ino->mtime_nsec  = tmp_le32;  | 
|---|
 | 299 | +	ino->atime_nsec  = 0;  | 
|---|
 | 300 | +	ino->ctime_nsec  = 0;  | 
|---|
 | 301 | +	ino->mtime_nsec  = 0;  | 
|---|
| 325 | 302 |  	ino->mode = cpu_to_le32(S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); | 
|---|
| 326 | 303 |  	ino->size = cpu_to_le64(UBIFS_INO_NODE_SZ); | 
|---|
| 327 | 304 |   | 
|---|
| 328 | 305 |  	/* Set compression enabled by default */ | 
|---|
| 329 | 306 |  	ino->flags = cpu_to_le32(UBIFS_COMPR_FL); | 
|---|
| 330 |  | -  | 
|---|
| 331 |  | -	err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ,  | 
|---|
| 332 |  | -			       main_first + DEFAULT_DATA_LEB, 0);  | 
|---|
| 333 |  | -	kfree(ino);  | 
|---|
| 334 |  | -	if (err)  | 
|---|
| 335 |  | -		return err;  | 
|---|
| 336 | 307 |   | 
|---|
| 337 | 308 |  	dbg_gen("root inode created at LEB %d:0", | 
|---|
| 338 | 309 |  		main_first + DEFAULT_DATA_LEB); | 
|---|
| .. | .. | 
|---|
| 342 | 313 |  	 * always the case during normal file-system operation. Write a fake | 
|---|
| 343 | 314 |  	 * commit start node to the log. | 
|---|
| 344 | 315 |  	 */ | 
|---|
| 345 |  | -	tmp = ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size);  | 
|---|
| 346 |  | -	cs = kzalloc(tmp, GFP_KERNEL);  | 
|---|
| 347 |  | -	if (!cs)  | 
|---|
| 348 |  | -		return -ENOMEM;  | 
|---|
| 349 | 316 |   | 
|---|
| 350 | 317 |  	cs->ch.node_type = UBIFS_CS_NODE; | 
|---|
| 351 |  | -	err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);  | 
|---|
| 352 |  | -	kfree(cs);  | 
|---|
 | 318 | +  | 
|---|
 | 319 | +	err = ubifs_write_node_hmac(c, sup, UBIFS_SB_NODE_SZ, 0, 0,  | 
|---|
 | 320 | +				    offsetof(struct ubifs_sb_node, hmac));  | 
|---|
| 353 | 321 |  	if (err) | 
|---|
| 354 |  | -		return err;  | 
|---|
 | 322 | +		goto out;  | 
|---|
 | 323 | +  | 
|---|
 | 324 | +	err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ,  | 
|---|
 | 325 | +			       main_first + DEFAULT_DATA_LEB, 0);  | 
|---|
 | 326 | +	if (err)  | 
|---|
 | 327 | +		goto out;  | 
|---|
 | 328 | +  | 
|---|
 | 329 | +	ubifs_node_calc_hash(c, ino, hash);  | 
|---|
 | 330 | +	ubifs_copy_hash(c, hash, ubifs_branch_hash(c, br));  | 
|---|
 | 331 | +  | 
|---|
 | 332 | +	err = ubifs_write_node(c, idx, idx_node_size, main_first + DEFAULT_IDX_LEB, 0);  | 
|---|
 | 333 | +	if (err)  | 
|---|
 | 334 | +		goto out;  | 
|---|
 | 335 | +  | 
|---|
 | 336 | +	ubifs_node_calc_hash(c, idx, hash);  | 
|---|
 | 337 | +	ubifs_copy_hash(c, hash, mst->hash_root_idx);  | 
|---|
 | 338 | +  | 
|---|
 | 339 | +	err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0,  | 
|---|
 | 340 | +		offsetof(struct ubifs_mst_node, hmac));  | 
|---|
 | 341 | +	if (err)  | 
|---|
 | 342 | +		goto out;  | 
|---|
 | 343 | +  | 
|---|
 | 344 | +	err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1,  | 
|---|
 | 345 | +			       0, offsetof(struct ubifs_mst_node, hmac));  | 
|---|
 | 346 | +	if (err)  | 
|---|
 | 347 | +		goto out;  | 
|---|
 | 348 | +  | 
|---|
 | 349 | +	err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);  | 
|---|
 | 350 | +	if (err)  | 
|---|
 | 351 | +		goto out;  | 
|---|
| 355 | 352 |   | 
|---|
| 356 | 353 |  	ubifs_msg(c, "default file-system created"); | 
|---|
| 357 |  | -	return 0;  | 
|---|
 | 354 | +  | 
|---|
 | 355 | +	err = 0;  | 
|---|
 | 356 | +out:  | 
|---|
 | 357 | +	kfree(sup);  | 
|---|
 | 358 | +	kfree(mst);  | 
|---|
 | 359 | +	kfree(idx);  | 
|---|
 | 360 | +	kfree(ino);  | 
|---|
 | 361 | +	kfree(cs);  | 
|---|
 | 362 | +  | 
|---|
 | 363 | +	return err;  | 
|---|
| 358 | 364 |  } | 
|---|
| 359 | 365 |   | 
|---|
| 360 | 366 |  /** | 
|---|
| .. | .. | 
|---|
| 509 | 515 |   * code. Note, the user of this function is responsible of kfree()'ing the | 
|---|
| 510 | 516 |   * returned superblock buffer. | 
|---|
| 511 | 517 |   */ | 
|---|
| 512 |  | -struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)  | 
|---|
 | 518 | +static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)  | 
|---|
| 513 | 519 |  { | 
|---|
| 514 | 520 |  	struct ubifs_sb_node *sup; | 
|---|
| 515 | 521 |  	int err; | 
|---|
| .. | .. | 
|---|
| 528 | 534 |  	return sup; | 
|---|
| 529 | 535 |  } | 
|---|
| 530 | 536 |   | 
|---|
 | 537 | +static int authenticate_sb_node(struct ubifs_info *c,  | 
|---|
 | 538 | +				const struct ubifs_sb_node *sup)  | 
|---|
 | 539 | +{  | 
|---|
 | 540 | +	unsigned int sup_flags = le32_to_cpu(sup->flags);  | 
|---|
 | 541 | +	u8 hmac_wkm[UBIFS_HMAC_ARR_SZ];  | 
|---|
 | 542 | +	int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION);  | 
|---|
 | 543 | +	int hash_algo;  | 
|---|
 | 544 | +	int err;  | 
|---|
 | 545 | +  | 
|---|
 | 546 | +	if (c->authenticated && !authenticated) {  | 
|---|
 | 547 | +		ubifs_err(c, "authenticated FS forced, but found FS without authentication");  | 
|---|
 | 548 | +		return -EINVAL;  | 
|---|
 | 549 | +	}  | 
|---|
 | 550 | +  | 
|---|
 | 551 | +	if (!c->authenticated && authenticated) {  | 
|---|
 | 552 | +		ubifs_err(c, "authenticated FS found, but no key given");  | 
|---|
 | 553 | +		return -EINVAL;  | 
|---|
 | 554 | +	}  | 
|---|
 | 555 | +  | 
|---|
 | 556 | +	ubifs_msg(c, "Mounting in %sauthenticated mode",  | 
|---|
 | 557 | +		  c->authenticated ? "" : "un");  | 
|---|
 | 558 | +  | 
|---|
 | 559 | +	if (!c->authenticated)  | 
|---|
 | 560 | +		return 0;  | 
|---|
 | 561 | +  | 
|---|
 | 562 | +	if (!IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION))  | 
|---|
 | 563 | +		return -EOPNOTSUPP;  | 
|---|
 | 564 | +  | 
|---|
 | 565 | +	hash_algo = le16_to_cpu(sup->hash_algo);  | 
|---|
 | 566 | +	if (hash_algo >= HASH_ALGO__LAST) {  | 
|---|
 | 567 | +		ubifs_err(c, "superblock uses unknown hash algo %d",  | 
|---|
 | 568 | +			  hash_algo);  | 
|---|
 | 569 | +		return -EINVAL;  | 
|---|
 | 570 | +	}  | 
|---|
 | 571 | +  | 
|---|
 | 572 | +	if (strcmp(hash_algo_name[hash_algo], c->auth_hash_name)) {  | 
|---|
 | 573 | +		ubifs_err(c, "This filesystem uses %s for hashing,"  | 
|---|
 | 574 | +			     " but %s is specified", hash_algo_name[hash_algo],  | 
|---|
 | 575 | +			     c->auth_hash_name);  | 
|---|
 | 576 | +		return -EINVAL;  | 
|---|
 | 577 | +	}  | 
|---|
 | 578 | +  | 
|---|
 | 579 | +	/*  | 
|---|
 | 580 | +	 * The super block node can either be authenticated by a HMAC or  | 
|---|
 | 581 | +	 * by a signature in a ubifs_sig_node directly following the  | 
|---|
 | 582 | +	 * super block node to support offline image creation.  | 
|---|
 | 583 | +	 */  | 
|---|
 | 584 | +	if (ubifs_hmac_zero(c, sup->hmac)) {  | 
|---|
 | 585 | +		err = ubifs_sb_verify_signature(c, sup);  | 
|---|
 | 586 | +	} else {  | 
|---|
 | 587 | +		err = ubifs_hmac_wkm(c, hmac_wkm);  | 
|---|
 | 588 | +		if (err)  | 
|---|
 | 589 | +			return err;  | 
|---|
 | 590 | +		if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) {  | 
|---|
 | 591 | +			ubifs_err(c, "provided key does not fit");  | 
|---|
 | 592 | +			return -ENOKEY;  | 
|---|
 | 593 | +		}  | 
|---|
 | 594 | +		err = ubifs_node_verify_hmac(c, sup, sizeof(*sup),  | 
|---|
 | 595 | +					     offsetof(struct ubifs_sb_node,  | 
|---|
 | 596 | +						      hmac));  | 
|---|
 | 597 | +	}  | 
|---|
 | 598 | +  | 
|---|
 | 599 | +	if (err)  | 
|---|
 | 600 | +		ubifs_err(c, "Failed to authenticate superblock: %d", err);  | 
|---|
 | 601 | +  | 
|---|
 | 602 | +	return err;  | 
|---|
 | 603 | +}  | 
|---|
 | 604 | +  | 
|---|
| 531 | 605 |  /** | 
|---|
| 532 | 606 |   * ubifs_write_sb_node - write superblock node. | 
|---|
| 533 | 607 |   * @c: UBIFS file-system description object | 
|---|
| .. | .. | 
|---|
| 538 | 612 |  int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) | 
|---|
| 539 | 613 |  { | 
|---|
| 540 | 614 |  	int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); | 
|---|
 | 615 | +	int err;  | 
|---|
| 541 | 616 |   | 
|---|
| 542 |  | -	ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);  | 
|---|
 | 617 | +	err = ubifs_prepare_node_hmac(c, sup, UBIFS_SB_NODE_SZ,  | 
|---|
 | 618 | +				      offsetof(struct ubifs_sb_node, hmac), 1);  | 
|---|
 | 619 | +	if (err)  | 
|---|
 | 620 | +		return err;  | 
|---|
 | 621 | +  | 
|---|
| 543 | 622 |  	return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len); | 
|---|
| 544 | 623 |  } | 
|---|
| 545 | 624 |   | 
|---|
| .. | .. | 
|---|
| 565 | 644 |  	sup = ubifs_read_sb_node(c); | 
|---|
| 566 | 645 |  	if (IS_ERR(sup)) | 
|---|
| 567 | 646 |  		return PTR_ERR(sup); | 
|---|
 | 647 | +  | 
|---|
 | 648 | +	c->sup_node = sup;  | 
|---|
| 568 | 649 |   | 
|---|
| 569 | 650 |  	c->fmt_version = le32_to_cpu(sup->fmt_version); | 
|---|
| 570 | 651 |  	c->ro_compat_version = le32_to_cpu(sup->ro_compat_version); | 
|---|
| .. | .. | 
|---|
| 614 | 695 |  		c->key_hash = key_test_hash; | 
|---|
| 615 | 696 |  		c->key_hash_type = UBIFS_KEY_HASH_TEST; | 
|---|
| 616 | 697 |  		break; | 
|---|
| 617 |  | -	};  | 
|---|
 | 698 | +	}  | 
|---|
| 618 | 699 |   | 
|---|
| 619 | 700 |  	c->key_fmt = sup->key_fmt; | 
|---|
| 620 | 701 |   | 
|---|
| .. | .. | 
|---|
| 651 | 732 |  	c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH); | 
|---|
| 652 | 733 |  	c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION); | 
|---|
| 653 | 734 |   | 
|---|
 | 735 | +	err = authenticate_sb_node(c, sup);  | 
|---|
 | 736 | +	if (err)  | 
|---|
 | 737 | +		goto out;  | 
|---|
 | 738 | +  | 
|---|
| 654 | 739 |  	if ((sup_flags & ~UBIFS_FLG_MASK) != 0) { | 
|---|
| 655 | 740 |  		ubifs_err(c, "Unknown feature flags found: %#x", | 
|---|
| 656 | 741 |  			  sup_flags & ~UBIFS_FLG_MASK); | 
|---|
| .. | .. | 
|---|
| 658 | 743 |  		goto out; | 
|---|
| 659 | 744 |  	} | 
|---|
| 660 | 745 |   | 
|---|
| 661 |  | -#ifndef CONFIG_FS_ENCRYPTION  | 
|---|
| 662 |  | -	if (c->encrypted) {  | 
|---|
 | 746 | +	if (!IS_ENABLED(CONFIG_FS_ENCRYPTION) && c->encrypted) {  | 
|---|
| 663 | 747 |  		ubifs_err(c, "file system contains encrypted files but UBIFS" | 
|---|
| 664 | 748 |  			     " was built without crypto support."); | 
|---|
| 665 | 749 |  		err = -EINVAL; | 
|---|
| 666 | 750 |  		goto out; | 
|---|
| 667 | 751 |  	} | 
|---|
| 668 |  | -#endif  | 
|---|
| 669 | 752 |   | 
|---|
| 670 | 753 |  	/* Automatically increase file system size to the maximum size */ | 
|---|
| 671 |  | -	c->old_leb_cnt = c->leb_cnt;  | 
|---|
| 672 | 754 |  	if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) { | 
|---|
 | 755 | +		int old_leb_cnt = c->leb_cnt;  | 
|---|
 | 756 | +  | 
|---|
| 673 | 757 |  		c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size); | 
|---|
| 674 |  | -		if (c->ro_mount)  | 
|---|
| 675 |  | -			dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",  | 
|---|
| 676 |  | -				c->old_leb_cnt,	c->leb_cnt);  | 
|---|
| 677 |  | -		else {  | 
|---|
| 678 |  | -			dbg_mnt("Auto resizing (sb) from %d LEBs to %d LEBs",  | 
|---|
| 679 |  | -				c->old_leb_cnt, c->leb_cnt);  | 
|---|
| 680 |  | -			sup->leb_cnt = cpu_to_le32(c->leb_cnt);  | 
|---|
| 681 |  | -			err = ubifs_write_sb_node(c, sup);  | 
|---|
| 682 |  | -			if (err)  | 
|---|
| 683 |  | -				goto out;  | 
|---|
| 684 |  | -			c->old_leb_cnt = c->leb_cnt;  | 
|---|
| 685 |  | -		}  | 
|---|
 | 758 | +		sup->leb_cnt = cpu_to_le32(c->leb_cnt);  | 
|---|
 | 759 | +  | 
|---|
 | 760 | +		c->superblock_need_write = 1;  | 
|---|
 | 761 | +  | 
|---|
 | 762 | +		dbg_mnt("Auto resizing from %d LEBs to %d LEBs",  | 
|---|
 | 763 | +			old_leb_cnt, c->leb_cnt);  | 
|---|
| 686 | 764 |  	} | 
|---|
| 687 | 765 |   | 
|---|
| 688 | 766 |  	c->log_bytes = (long long)c->log_lebs * c->leb_size; | 
|---|
| .. | .. | 
|---|
| 697 | 775 |   | 
|---|
| 698 | 776 |  	err = validate_sb(c, sup); | 
|---|
| 699 | 777 |  out: | 
|---|
| 700 |  | -	kfree(sup);  | 
|---|
| 701 | 778 |  	return err; | 
|---|
| 702 | 779 |  } | 
|---|
| 703 | 780 |   | 
|---|
| .. | .. | 
|---|
| 826 | 903 |  int ubifs_fixup_free_space(struct ubifs_info *c) | 
|---|
| 827 | 904 |  { | 
|---|
| 828 | 905 |  	int err; | 
|---|
| 829 |  | -	struct ubifs_sb_node *sup;  | 
|---|
 | 906 | +	struct ubifs_sb_node *sup = c->sup_node;  | 
|---|
| 830 | 907 |   | 
|---|
| 831 | 908 |  	ubifs_assert(c, c->space_fixup); | 
|---|
| 832 | 909 |  	ubifs_assert(c, !c->ro_mount); | 
|---|
| .. | .. | 
|---|
| 837 | 914 |  	if (err) | 
|---|
| 838 | 915 |  		return err; | 
|---|
| 839 | 916 |   | 
|---|
| 840 |  | -	sup = ubifs_read_sb_node(c);  | 
|---|
| 841 |  | -	if (IS_ERR(sup))  | 
|---|
| 842 |  | -		return PTR_ERR(sup);  | 
|---|
| 843 |  | -  | 
|---|
| 844 | 917 |  	/* Free-space fixup is no longer required */ | 
|---|
| 845 | 918 |  	c->space_fixup = 0; | 
|---|
| 846 | 919 |  	sup->flags &= cpu_to_le32(~UBIFS_FLG_SPACE_FIXUP); | 
|---|
| 847 | 920 |   | 
|---|
| 848 |  | -	err = ubifs_write_sb_node(c, sup);  | 
|---|
| 849 |  | -	kfree(sup);  | 
|---|
| 850 |  | -	if (err)  | 
|---|
| 851 |  | -		return err;  | 
|---|
 | 921 | +	c->superblock_need_write = 1;  | 
|---|
| 852 | 922 |   | 
|---|
| 853 | 923 |  	ubifs_msg(c, "free space fixup complete"); | 
|---|
| 854 | 924 |  	return err; | 
|---|
| .. | .. | 
|---|
| 857 | 927 |  int ubifs_enable_encryption(struct ubifs_info *c) | 
|---|
| 858 | 928 |  { | 
|---|
| 859 | 929 |  	int err; | 
|---|
| 860 |  | -	struct ubifs_sb_node *sup;  | 
|---|
 | 930 | +	struct ubifs_sb_node *sup = c->sup_node;  | 
|---|
 | 931 | +  | 
|---|
 | 932 | +	if (!IS_ENABLED(CONFIG_FS_ENCRYPTION))  | 
|---|
 | 933 | +		return -EOPNOTSUPP;  | 
|---|
| 861 | 934 |   | 
|---|
| 862 | 935 |  	if (c->encrypted) | 
|---|
| 863 | 936 |  		return 0; | 
|---|
| .. | .. | 
|---|
| 870 | 943 |  		return -EINVAL; | 
|---|
| 871 | 944 |  	} | 
|---|
| 872 | 945 |   | 
|---|
| 873 |  | -	sup = ubifs_read_sb_node(c);  | 
|---|
| 874 |  | -	if (IS_ERR(sup))  | 
|---|
| 875 |  | -		return PTR_ERR(sup);  | 
|---|
| 876 |  | -  | 
|---|
| 877 | 946 |  	sup->flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION); | 
|---|
| 878 | 947 |   | 
|---|
| 879 | 948 |  	err = ubifs_write_sb_node(c, sup); | 
|---|
| 880 | 949 |  	if (!err) | 
|---|
| 881 | 950 |  		c->encrypted = 1; | 
|---|
| 882 |  | -	kfree(sup);  | 
|---|
| 883 | 951 |   | 
|---|
| 884 | 952 |  	return err; | 
|---|
| 885 | 953 |  } | 
|---|