| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | 
|---|
| 1 | 2 | /* | 
|---|
| 2 | 3 | *   Copyright (C) International Business Machines Corp., 2000-2004 | 
|---|
| 3 | 4 | *   Portions Copyright (C) Tino Reichardt, 2012 | 
|---|
| 4 |  | - * | 
|---|
| 5 |  | - *   This program is free software;  you can redistribute it and/or modify | 
|---|
| 6 |  | - *   it under the terms of the GNU General Public License as published by | 
|---|
| 7 |  | - *   the Free Software Foundation; either version 2 of the License, or | 
|---|
| 8 |  | - *   (at your option) any later version. | 
|---|
| 9 |  | - * | 
|---|
| 10 |  | - *   This program is distributed in the hope that it will be useful, | 
|---|
| 11 |  | - *   but WITHOUT ANY WARRANTY;  without even the implied warranty of | 
|---|
| 12 |  | - *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See | 
|---|
| 13 |  | - *   the GNU General Public License for more details. | 
|---|
| 14 |  | - * | 
|---|
| 15 |  | - *   You should have received a copy of the GNU General Public License | 
|---|
| 16 |  | - *   along with this program;  if not, write to the Free Software | 
|---|
| 17 |  | - *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
|---|
| 18 | 5 | */ | 
|---|
| 19 | 6 |  | 
|---|
| 20 | 7 | #include <linux/fs.h> | 
|---|
| .. | .. | 
|---|
| 161 | 148 | *	0	- success | 
|---|
| 162 | 149 | *	-ENOMEM	- insufficient memory | 
|---|
| 163 | 150 | *	-EIO	- i/o error | 
|---|
|  | 151 | + *	-EINVAL - wrong bmap data | 
|---|
| 164 | 152 | */ | 
|---|
| 165 | 153 | int dbMount(struct inode *ipbmap) | 
|---|
| 166 | 154 | { | 
|---|
| 167 | 155 | struct bmap *bmp; | 
|---|
| 168 | 156 | struct dbmap_disk *dbmp_le; | 
|---|
| 169 | 157 | struct metapage *mp; | 
|---|
| 170 |  | -	int i; | 
|---|
|  | 158 | +	int i, err; | 
|---|
| 171 | 159 |  | 
|---|
| 172 | 160 | /* | 
|---|
| 173 | 161 | * allocate/initialize the in-memory bmap descriptor | 
|---|
| .. | .. | 
|---|
| 182 | 170 | BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage, | 
|---|
| 183 | 171 | PSIZE, 0); | 
|---|
| 184 | 172 | if (mp == NULL) { | 
|---|
| 185 |  | -		kfree(bmp); | 
|---|
| 186 |  | -		return -EIO; | 
|---|
|  | 173 | +		err = -EIO; | 
|---|
|  | 174 | +		goto err_kfree_bmp; | 
|---|
| 187 | 175 | } | 
|---|
| 188 | 176 |  | 
|---|
| 189 | 177 | /* copy the on-disk bmap descriptor to its in-memory version. */ | 
|---|
| 190 | 178 | dbmp_le = (struct dbmap_disk *) mp->data; | 
|---|
| 191 | 179 | bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize); | 
|---|
| 192 | 180 | bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree); | 
|---|
|  | 181 | + | 
|---|
| 193 | 182 | bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage); | 
|---|
|  | 183 | +	if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) { | 
|---|
|  | 184 | +		err = -EINVAL; | 
|---|
|  | 185 | +		goto err_release_metapage; | 
|---|
|  | 186 | +	} | 
|---|
|  | 187 | + | 
|---|
| 194 | 188 | bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); | 
|---|
|  | 189 | +	if (!bmp->db_numag) { | 
|---|
|  | 190 | +		err = -EINVAL; | 
|---|
|  | 191 | +		goto err_release_metapage; | 
|---|
|  | 192 | +	} | 
|---|
|  | 193 | + | 
|---|
| 195 | 194 | bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel); | 
|---|
| 196 | 195 | bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag); | 
|---|
| 197 | 196 | bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref); | 
|---|
| .. | .. | 
|---|
| 200 | 199 | bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth); | 
|---|
| 201 | 200 | bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart); | 
|---|
| 202 | 201 | bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size); | 
|---|
|  | 202 | +	if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG || | 
|---|
|  | 203 | +	    bmp->db_agl2size < 0) { | 
|---|
|  | 204 | +		err = -EINVAL; | 
|---|
|  | 205 | +		goto err_release_metapage; | 
|---|
|  | 206 | +	} | 
|---|
|  | 207 | + | 
|---|
|  | 208 | +	if (((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) { | 
|---|
|  | 209 | +		err = -EINVAL; | 
|---|
|  | 210 | +		goto err_release_metapage; | 
|---|
|  | 211 | +	} | 
|---|
|  | 212 | + | 
|---|
| 203 | 213 | for (i = 0; i < MAXAG; i++) | 
|---|
| 204 | 214 | bmp->db_agfree[i] = le64_to_cpu(dbmp_le->dn_agfree[i]); | 
|---|
| 205 | 215 | bmp->db_agsize = le64_to_cpu(dbmp_le->dn_agsize); | 
|---|
| .. | .. | 
|---|
| 220 | 230 | BMAP_LOCK_INIT(bmp); | 
|---|
| 221 | 231 |  | 
|---|
| 222 | 232 | return (0); | 
|---|
|  | 233 | + | 
|---|
|  | 234 | +err_release_metapage: | 
|---|
|  | 235 | +	release_metapage(mp); | 
|---|
|  | 236 | +err_kfree_bmp: | 
|---|
|  | 237 | +	kfree(bmp); | 
|---|
|  | 238 | +	return err; | 
|---|
| 223 | 239 | } | 
|---|
| 224 | 240 |  | 
|---|
| 225 | 241 |  | 
|---|
| .. | .. | 
|---|
| 253 | 269 |  | 
|---|
| 254 | 270 | /* free the memory for the in-memory bmap. */ | 
|---|
| 255 | 271 | kfree(bmp); | 
|---|
|  | 272 | +	JFS_SBI(ipbmap->i_sb)->bmap = NULL; | 
|---|
| 256 | 273 |  | 
|---|
| 257 | 274 | return (0); | 
|---|
| 258 | 275 | } | 
|---|
| .. | .. | 
|---|
| 391 | 408 | } | 
|---|
| 392 | 409 |  | 
|---|
| 393 | 410 | /* write the last buffer. */ | 
|---|
| 394 |  | -	write_metapage(mp); | 
|---|
|  | 411 | +	if (mp) | 
|---|
|  | 412 | +		write_metapage(mp); | 
|---|
| 395 | 413 |  | 
|---|
| 396 | 414 | IREAD_UNLOCK(ipbmap); | 
|---|
| 397 | 415 |  | 
|---|
| .. | .. | 
|---|
| 2009 | 2027 | */ | 
|---|
| 2010 | 2028 | if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx)) | 
|---|
| 2011 | 2029 | return -ENOSPC; | 
|---|
|  | 2030 | + | 
|---|
|  | 2031 | +	if (leafidx < 0) | 
|---|
|  | 2032 | +		return -EIO; | 
|---|
| 2012 | 2033 |  | 
|---|
| 2013 | 2034 | /* determine the block number within the file system corresponding | 
|---|
| 2014 | 2035 | * to the leaf at which free space was found. | 
|---|
| .. | .. | 
|---|
| 4040 | 4061 | */ | 
|---|
| 4041 | 4062 | #define MAXL0PAGES	(1 + LPERCTL) | 
|---|
| 4042 | 4063 | #define MAXL1PAGES	(1 + LPERCTL * MAXL0PAGES) | 
|---|
| 4043 |  | -#define MAXL2PAGES	(1 + LPERCTL * MAXL1PAGES) | 
|---|
| 4044 | 4064 |  | 
|---|
| 4045 | 4065 | /* | 
|---|
| 4046 | 4066 | * convert number of map pages to the zero origin top dmapctl level | 
|---|