From nobody Mon May 30 22:07:27 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 890D81B56071 for ; Mon, 30 May 2022 22:07:41 +0000 (UTC) (envelope-from wlosh@bsdimp.com) Received: from mail-vs1-xe32.google.com (mail-vs1-xe32.google.com [IPv6:2607:f8b0:4864:20::e32]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "GTS CA 1D4" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4LBqK74V5xz4VJn for ; Mon, 30 May 2022 22:07:39 +0000 (UTC) (envelope-from wlosh@bsdimp.com) Received: by mail-vs1-xe32.google.com with SMTP id c62so11906607vsc.10 for ; Mon, 30 May 2022 15:07:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bsdimp-com.20210112.gappssmtp.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=i4AGMLttwPHe8j4Bhf0ZjnsPjjLW+o4TKg7G4sERqtA=; b=BpmnGWD5qP5+SBrhhmAnZBFlpLiuknZTL4uJPAKnnQWh3p6mZufAxa6j9g9r2nxh9r NKf3TFxf1DCjr6h7FJvUcSm5Ei5IMRHM6/4DV07as6MXpX3Yt5huDC7sLauRvQeSRw+k cQAXJOso1KaYjHCsl4JjPK/+CmyamlrLjtKee9xLrFBpdESg7Sbd2wWw9gcvpjCSa0ft fpLUmbp4Ea/cRWPSmMulNKvhdPERizwkR8NwFsuiyMYOjbLM7Pg7RWbEKtCpmifOU78S 6RdsgaqUd3e5NcQC7pgnX+chCjL2qGMgVUBdwLDFCtEXh/vGErXq1ce9xdciBvM880oR DSTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=i4AGMLttwPHe8j4Bhf0ZjnsPjjLW+o4TKg7G4sERqtA=; b=HROGC0gdw4o86HsRmrvs0i1sz+fVFxcQn4KLVoYLZf8lk/m5TMrXf9UPQMF1BPv3TF ExAj98rcF9Sz3/PAkQJGqEShPbO+R7RQTcJtYdPfnGMOsj4DhC0UAaYny/q0LVmKSlRV 7X1eUs1j1+UrsHwz7iP0VbQsrUfVR5X2DD3cPQB20fRfeTx3rVoYytHiNwRRsAAtPTlU UWSiUKAjLw7nDrhkKVZ51gkS6W0ju5n8vyAXgT7Fa7ZPpSLX8bydwPM/2148dc3oiZwj UeBgN12yCi5Vq6m3yRC3/xlvz6eiTIPDRo/9AYKpXDhbs6YlSj4kGZIx2emob3UI9aMF ejvA== X-Gm-Message-State: AOAM530dFttJtsuvHJ9T+xG2iiAu4AIZ0LVHee855PemBbpNgPBOzoTo gKHbI4d1ZaQORF6E6BxzFNY92twZZY14m1mhMLruOA== X-Google-Smtp-Source: ABdhPJxgbpJJ16QMpv3I8z2liMb1iAjpDTSvWi3cxu2B0t36qUWCxfxgwSwW/ipORPaX/XmR8QaVlBRbDdbTEWlwxP4= X-Received: by 2002:a05:6102:c0b:b0:339:8566:2028 with SMTP id x11-20020a0561020c0b00b0033985662028mr9239275vss.38.1653948458536; Mon, 30 May 2022 15:07:38 -0700 (PDT) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 References: <202205271922.24RJMOJ2039923@gitrepo.freebsd.org> <20220530215552.EE5432C@slippy.cwsent.com> In-Reply-To: <20220530215552.EE5432C@slippy.cwsent.com> From: Warner Losh Date: Mon, 30 May 2022 16:07:27 -0600 Message-ID: Subject: Re: git: 076002f24d35 - main - Do comprehensive UFS/FFS superblock integrity checks when reading a superblock. To: Cy Schubert Cc: Kirk McKusick , src-committers , "" , dev-commits-src-main@freebsd.org, David Wolfskill , Toomas Soome Content-Type: multipart/alternative; boundary="00000000000059353005e041e22c" X-Rspamd-Queue-Id: 4LBqK74V5xz4VJn X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org; dkim=pass header.d=bsdimp-com.20210112.gappssmtp.com header.s=20210112 header.b=BpmnGWD5; dmarc=none; spf=none (mx1.freebsd.org: domain of wlosh@bsdimp.com has no SPF policy when checking 2607:f8b0:4864:20::e32) smtp.mailfrom=wlosh@bsdimp.com X-Spamd-Result: default: False [-2.99 / 15.00]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; RCVD_COUNT_TWO(0.00)[2]; R_DKIM_ALLOW(-0.20)[bsdimp-com.20210112.gappssmtp.com:s=20210112]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; MIME_GOOD(-0.10)[multipart/alternative,text/plain]; PREVIOUSLY_DELIVERED(0.00)[dev-commits-src-all@freebsd.org]; DMARC_NA(0.00)[bsdimp.com]; TO_MATCH_ENVRCPT_SOME(0.00)[]; DKIM_TRACE(0.00)[bsdimp-com.20210112.gappssmtp.com:+]; NEURAL_HAM_SHORT(-0.99)[-0.992]; RCPT_COUNT_SEVEN(0.00)[7]; RCVD_IN_DNSWL_NONE(0.00)[2607:f8b0:4864:20::e32:from]; MLMMJ_DEST(0.00)[dev-commits-src-all]; FORGED_SENDER(0.30)[imp@bsdimp.com,wlosh@bsdimp.com]; R_SPF_NA(0.00)[no SPF record]; MIME_TRACE(0.00)[0:+,1:+,2:~]; ASN(0.00)[asn:15169, ipnet:2607:f8b0::/32, country:US]; FROM_NEQ_ENVFROM(0.00)[imp@bsdimp.com,wlosh@bsdimp.com]; RCVD_TLS_ALL(0.00)[]; FREEMAIL_CC(0.00)[freebsd.org,catwhisker.org,me.com] X-ThisMailContainsUnwantedMimeParts: N --00000000000059353005e041e22c Content-Type: text/plain; charset="UTF-8" David Woofskill also reported this... Warner On Mon, May 30, 2022, 3:56 PM Cy Schubert wrote: > In message <202205271922.24RJMOJ2039923@gitrepo.freebsd.org>, Kirk > McKusick > wri > tes: > > The branch main has been updated by mckusick: > > > > URL: > https://cgit.FreeBSD.org/src/commit/?id=076002f24d35962f0d21f44bfddd34ee > > 4d7f015d > > > > commit 076002f24d35962f0d21f44bfddd34ee4d7f015d > > Author: Kirk McKusick > > AuthorDate: 2022-05-27 19:21:11 +0000 > > Commit: Kirk McKusick > > CommitDate: 2022-05-27 19:22:07 +0000 > > > > Do comprehensive UFS/FFS superblock integrity checks when reading a > super > > block. > > > > Historically only minimal checks were made of a superblock when it > > was read in as it was assumed that fsck would have been run to > > correct any errors before attempting to use the filesystem. Recently > > several bug reports have been submitted reporting kernel panics > > that can be triggered by deliberately corrupting filesystem > superblocks, > > see Bug 263979 - [meta] UFS / FFS / GEOM crash (panic) tracking > > which is tracking the reported corruption bugs. > > > > This change upgrades the checks that are performed. These additional > > checks should prevent panics from a corrupted superblock. Although > > it appears in only one place, the new code will apply to the kernel > > modules and (through libufs) user applications that read in > superblocks. > > > > Reported by: Robert Morris and Neeraj > > Reviewed by: kib > > Tested by: Peter Holm > > PR: 263979 > > MFC after: 1 month > > Differential Revision: https://reviews.freebsd.org/D35219 > > --- > > sys/ufs/ffs/ffs_subr.c | 163 > +++++++++++++++++++++++++++++++++++++++++++---- > > -- > > 1 file changed, 146 insertions(+), 17 deletions(-) > > > > diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c > > index 01e9f45e1205..28c2fee1cb37 100644 > > --- a/sys/ufs/ffs/ffs_subr.c > > +++ b/sys/ufs/ffs/ffs_subr.c > > @@ -35,6 +35,7 @@ > > __FBSDID("$FreeBSD$"); > > > > #include > > +#include > > > > #ifndef _KERNEL > > #include > > @@ -50,6 +51,7 @@ uint32_t ffs_calc_sbhash(struct fs *); > > struct malloc_type; > > #define UFS_MALLOC(size, type, flags) malloc(size) > > #define UFS_FREE(ptr, type) free(ptr) > > +#define maxphys MAXPHYS > > > > #else /* _KERNEL */ > > #include > > @@ -125,6 +127,7 @@ ffs_update_dinode_ckhash(struct fs *fs, struct > ufs2_dinod > > e *dip) > > static off_t sblock_try[] = SBLOCKSEARCH; > > static int readsuper(void *, struct fs **, off_t, int, int, > > int (*)(void *, off_t, void **, int)); > > +static int validate_sblock(struct fs *, int); > > > > /* > > * Read a superblock from the devfd device. > > @@ -141,7 +144,7 @@ static int readsuper(void *, struct fs **, off_t, > int, in > > t, > > * EIO: non-existent or truncated superblock. > > * EIO: error reading summary information. > > * ENOENT: no usable known superblock found. > > - * ENOSPC: failed to allocate space for the superblock. > > + * ENOMEM: failed to allocate space for the superblock. > > * EINVAL: The previous newfs operation on this volume did not > complete. > > * The administrator must complete newfs before using this > volume. > > */ > > @@ -152,7 +155,8 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t > altsblock, > > { > > struct fs *fs; > > struct fs_summary_info *fs_si; > > - int i, error, size, blks; > > + int i, error; > > + uint64_t size, blks; > > uint8_t *space; > > int32_t *lp; > > char *buf; > > @@ -190,17 +194,16 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t > altsblock > > , > > if (fs->fs_contigsumsize > 0) > > size += fs->fs_ncg * sizeof(int32_t); > > size += fs->fs_ncg * sizeof(u_int8_t); > > - /* When running in libufs or libsa, UFS_MALLOC may fail */ > > - if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_WAITOK)) == > NULL) { > > + if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_NOWAIT)) == > NULL) { > > UFS_FREE(fs, filltype); > > - return (ENOSPC); > > + return (ENOMEM); > > } > > bzero(fs_si, sizeof(*fs_si)); > > fs->fs_si = fs_si; > > - if ((space = UFS_MALLOC(size, filltype, M_WAITOK)) == NULL) { > > + if ((space = UFS_MALLOC(size, filltype, M_NOWAIT)) == NULL) { > > UFS_FREE(fs->fs_si, filltype); > > UFS_FREE(fs, filltype); > > - return (ENOSPC); > > + return (ENOMEM); > > } > > fs->fs_csp = (struct csum *)space; > > for (i = 0; i < blks; i += fs->fs_frag) { > > @@ -253,16 +256,8 @@ readsuper(void *devfd, struct fs **fsp, off_t > sblockloc, > > int isaltsblk, > > fs = *fsp; > > if (fs->fs_magic == FS_BAD_MAGIC) > > return (EINVAL); > > - if (!(((fs->fs_magic == FS_UFS1_MAGIC && (isaltsblk || > > - sblockloc <= SBLOCK_UFS1)) || > > - (fs->fs_magic == FS_UFS2_MAGIC && (isaltsblk || > > - sblockloc == fs->fs_sblockloc))) && > > - fs->fs_ncg >= 1 && > > - fs->fs_bsize >= MINBSIZE && > > - fs->fs_bsize <= MAXBSIZE && > > - fs->fs_bsize >= roundup(sizeof(struct fs), DEV_BSIZE) && > > - fs->fs_sbsize <= SBLOCKSIZE)) > > - return (ENOENT); > > + if ((error = validate_sblock(fs, isaltsblk)) != 0) > > + return (error); > > /* > > * If the filesystem has been run on a kernel without > > * metadata check hashes, disable them. > > @@ -310,6 +305,140 @@ readsuper(void *devfd, struct fs **fsp, off_t > sblockloc > > , int isaltsblk, > > return (0); > > } > > > > +/* > > + * Verify the filesystem values. > > + */ > > +#define ILOG2(num) (fls(num) - 1) > > + > > +static int > > +validate_sblock(struct fs *fs, int isaltsblk) > > +{ > > + int i, sectorsize; > > + u_int64_t maxfilesize, minfpg, sizepb; > > + > > + sectorsize = dbtob(1); > > + if (fs->fs_magic == FS_UFS2_MAGIC) { > > + if ((!isaltsblk && (fs->fs_sblockloc != SBLOCK_UFS2 || > > + fs->fs_sblockactualloc != SBLOCK_UFS2)) || > > + fs->fs_maxsymlinklen != ((UFS_NDADDR + UFS_NIADDR) * > > + sizeof(ufs2_daddr_t)) || > > + fs->fs_nindir != fs->fs_bsize / sizeof(ufs2_daddr_t) || > > + fs->fs_inopb != fs->fs_bsize / sizeof(struct > ufs2_dinode)) > > + return (ENOENT); > > + } else if (fs->fs_magic == FS_UFS1_MAGIC) { > > + if ((!isaltsblk && (fs->fs_sblockloc > SBLOCK_UFS1 || > > + fs->fs_sblockactualloc != SBLOCK_UFS1)) || > > + fs->fs_nindir != fs->fs_bsize / sizeof(ufs1_daddr_t) || > > + fs->fs_inopb != fs->fs_bsize / sizeof(struct > ufs1_dinode) | > > | > > + fs->fs_maxsymlinklen != ((UFS_NDADDR + UFS_NIADDR) * > > + sizeof(ufs1_daddr_t)) || > > + fs->fs_old_inodefmt != FS_44INODEFMT || > > + fs->fs_old_cgoffset != 0 || > > + fs->fs_old_cgmask != 0xffffffff || > > + fs->fs_old_size != fs->fs_size || > > + fs->fs_old_rotdelay != 0 || > > + fs->fs_old_rps != 60 || > > + fs->fs_old_nspf != fs->fs_fsize / sectorsize || > > + fs->fs_old_cpg != 1 || > > + fs->fs_old_interleave != 1 || > > + fs->fs_old_trackskew != 0 || > > + fs->fs_old_cpc != 0 || > > + fs->fs_old_postblformat != 1 || > > + fs->fs_old_nrpos != 1 || > > + fs->fs_old_spc != fs->fs_fpg * fs->fs_old_nspf || > > + fs->fs_old_nsect != fs->fs_old_spc || > > + fs->fs_old_npsect != fs->fs_old_spc || > > + fs->fs_old_dsize != fs->fs_dsize || > > + fs->fs_old_ncyl != fs->fs_ncg) > > + return (ENOENT); > > + } else { > > + return (ENOENT); > > + } > > + if (fs->fs_bsize < MINBSIZE || fs->fs_bsize > MAXBSIZE || > > + fs->fs_bsize < roundup(sizeof(struct fs), DEV_BSIZE) || > > + fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < fs->fs_fsize || > > + !powerof2(fs->fs_bsize)) > > + return (ENOENT); > > + if (fs->fs_fsize < sectorsize || fs->fs_fsize > fs->fs_bsize || > > + fs->fs_fsize * MAXFRAG < fs->fs_bsize || > !powerof2(fs->fs_fsize)) > > + return (ENOENT); > > + if (fs->fs_maxbsize < fs->fs_bsize || !powerof2(fs->fs_maxbsize) || > > + fs->fs_maxbsize > FS_MAXCONTIG * fs->fs_bsize) > > + return (ENOENT); > > + if (fs->fs_bmask != ~(fs->fs_bsize - 1) || > > + fs->fs_fmask != ~(fs->fs_fsize - 1) || > > + fs->fs_qbmask != ~fs->fs_bmask || > > + fs->fs_qfmask != ~fs->fs_fmask || > > + fs->fs_bshift != ILOG2(fs->fs_bsize) || > > + fs->fs_fshift != ILOG2(fs->fs_fsize) || > > + fs->fs_frag != numfrags(fs, fs->fs_bsize) || > > + fs->fs_fragshift != ILOG2(fs->fs_frag) || > > + fs->fs_frag > MAXFRAG || > > + fs->fs_fsbtodb != ILOG2(fs->fs_fsize / sectorsize)) > > + return (ENOENT); > > + if (fs->fs_sblkno != > > + roundup(howmany(fs->fs_sblockloc + SBLOCKSIZE, > fs->fs_fsize), > > + fs->fs_frag) || > > + fs->fs_cblkno != fs->fs_sblkno + > > + roundup(howmany(SBLOCKSIZE, fs->fs_fsize), fs->fs_frag) || > > + fs->fs_iblkno != fs->fs_cblkno + fs->fs_frag || > > + fs->fs_dblkno != fs->fs_iblkno + fs->fs_ipg / INOPF(fs) || > > + fs->fs_cgsize != fragroundup(fs, CGSIZE(fs))) > > + return (ENOENT); > > + if (fs->fs_csaddr != cgdmin(fs, 0) || > > + fs->fs_cssize != > > + fragroundup(fs, fs->fs_ncg * sizeof(struct csum)) || > > + fs->fs_dsize != fs->fs_size - fs->fs_sblkno - > > + fs->fs_ncg * (fs->fs_dblkno - fs->fs_sblkno) - > > + howmany(fs->fs_cssize, fs->fs_fsize) || > > + fs->fs_metaspace < 0 || fs->fs_metaspace > fs->fs_fpg / 2 || > > + fs->fs_minfree > 99) > > + return (ENOENT); > > + maxfilesize = fs->fs_bsize * UFS_NDADDR - 1; > > + for (sizepb = fs->fs_bsize, i = 0; i < UFS_NIADDR; i++) { > > + sizepb *= NINDIR(fs); > > + maxfilesize += sizepb; > > + } > > + if (fs->fs_maxfilesize != maxfilesize) > > + return (ENOENT); > > + /* > > + * These values have a tight interaction with each other that > > + * makes it hard to tightly bound them. So we can only check > > + * that they are within a broader possible range. > > + * > > + * Calculate minfpg, the minimum number of fragments that can be > > + * in a cylinder group. The value 12289 is calculated in newfs(8) > > + * when creating the smallest block size UFS version 1 filesystem > > + * (4096 block size) with no fragments (4096 fragment size). That > > + * number may be depressed even further for very small filesystems > > + * since newfs(8) strives to have at least four cylinder groups. > > + */ > > + minfpg = MIN(12289, fs->fs_size / 4); > > + if (fs->fs_ncg < 1 || fs->fs_ncg > (fs->fs_size / minfpg) + 1 || > > + fs->fs_fpg < minfpg || fs->fs_fpg > fs->fs_size || > > + fs->fs_ipg * fs->fs_ncg > (((int64_t)(1)) << 32) - INOPB(fs) || > > + fs->fs_ipg > fs->fs_fpg || fs->fs_size < 8 * fs->fs_frag) > > + return (ENOENT); > > + if (fs->fs_size <= (fs->fs_ncg - 1) * fs->fs_fpg || > > + fs->fs_size > fs->fs_ncg * fs->fs_fpg) > > + return (ENOENT); > > + /* > > + * Maxcontig sets the default for the maximum number of blocks > > + * that may be allocated sequentially. With file system clustering > > + * it is possible to allocate contiguous blocks up to the maximum > > + * transfer size permitted by the controller or buffering. > > + */ > > + if (fs->fs_maxcontig < 1 || > > + fs->fs_maxcontig > MAX(1, maxphys / fs->fs_bsize)) > > + return (ENOENT); > > + if (fs->fs_maxcontig < 0 || > > + (fs->fs_maxcontig == 0 && fs->fs_contigsumsize != 0) || > > + (fs->fs_maxcontig > 1 && > > + fs->fs_contigsumsize != MIN(fs->fs_maxcontig, FS_MAXCONTIG))) > > + return (ENOENT); > > + return (0); > > +} > > + > > /* > > * Write a superblock to the devfd device from the memory pointed to by > fs. > > * Write out the superblock summary information if it is present. > > > > Hi Kirk, > > This patch broke loader on one of my machines. > > I get the following error: > > LUA ERROR: Cannot open /boot/lua/loader.lua: no such file or directory" > can't load kernel > > Of course booting from my rescue worked. > > Copying loader* from /boot on the rescue disk to /boot works around the > problem. > > Backing up, newfs, and restoring the root filesystem, using my rescue disk > also didn't work around the problem. > > Reverting this patch provided permanent relief. > > Loader could read the filesystems on my rescue disk, which had blocksizes > of 16K but not those on my boot disk which had blocksizes of 32K. > > My three machines downstairs, all AMD gear with UFS blocksize of 32K, had > no no problems with this whereas my laptop, an Intel, had the problem. > > To repeat, a newly created filesystem restored from backup using my rescue > disk didn't resolve the problem. > > > -- > Cheers, > Cy Schubert or > FreeBSD UNIX: Web: http://www.FreeBSD.org > NTP: Web: https://nwtime.org > > e**(i*pi)+1=0 > > > --00000000000059353005e041e22c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
David Woofskill also reported this...
Warner

=
On Mon, May 30, 2022, 3:56 PM Cy Schu= bert <Cy.Schubert@cschubert= .com> wrote:
In message <= 202205271922.24RJMOJ2039923@gitrepo.freebsd.= org>, Kirk McKusick
wri
tes:
> The branch main has been updated by mckusick:
>
> URL: https= ://cgit.FreeBSD.org/src/commit/?id=3D076002f24d35962f0d21f44bfddd34ee > 4d7f015d
>
> commit 076002f24d35962f0d21f44bfddd34ee4d7f015d
> Author:=C2=A0 =C2=A0 =C2=A0Kirk McKusick <mckusick@FreeBSD.org><= br> > AuthorDate: 2022-05-27 19:21:11 +0000
> Commit:=C2=A0 =C2=A0 =C2=A0Kirk McKusick <mckusick@FreeBSD.org><= br> > CommitDate: 2022-05-27 19:22:07 +0000
>
>=C2=A0 =C2=A0 =C2=A0Do comprehensive UFS/FFS superblock integrity check= s when reading a super
> block.
>=C2=A0 =C2=A0 =C2=A0
>=C2=A0 =C2=A0 =C2=A0Historically only minimal checks were made of a sup= erblock when it
>=C2=A0 =C2=A0 =C2=A0was read in as it was assumed that fsck would have = been run to
>=C2=A0 =C2=A0 =C2=A0correct any errors before attempting to use the fil= esystem. Recently
>=C2=A0 =C2=A0 =C2=A0several bug reports have been submitted reporting k= ernel panics
>=C2=A0 =C2=A0 =C2=A0that can be triggered by deliberately corrupting fi= lesystem superblocks,
>=C2=A0 =C2=A0 =C2=A0see Bug 263979 - [meta] UFS / FFS / GEOM crash (pan= ic) tracking
>=C2=A0 =C2=A0 =C2=A0which is tracking the reported corruption bugs.
>=C2=A0 =C2=A0 =C2=A0
>=C2=A0 =C2=A0 =C2=A0This change upgrades the checks that are performed.= These additional
>=C2=A0 =C2=A0 =C2=A0checks should prevent panics from a corrupted super= block. Although
>=C2=A0 =C2=A0 =C2=A0it appears in only one place, the new code will app= ly to the kernel
>=C2=A0 =C2=A0 =C2=A0modules and (through libufs) user applications that= read in superblocks.
>=C2=A0 =C2=A0 =C2=A0
>=C2=A0 =C2=A0 =C2=A0Reported by:=C2=A0 Robert Morris and Neeraj
>=C2=A0 =C2=A0 =C2=A0Reviewed by:=C2=A0 kib
>=C2=A0 =C2=A0 =C2=A0Tested by:=C2=A0 =C2=A0 Peter Holm
>=C2=A0 =C2=A0 =C2=A0PR:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0263979<= br> >=C2=A0 =C2=A0 =C2=A0MFC after:=C2=A0 =C2=A0 1 month
>=C2=A0 =C2=A0 =C2=A0Differential Revision: https://= reviews.freebsd.org/D35219
> ---
>=C2=A0 sys/ufs/ffs/ffs_subr.c | 163 +++++++++++++++++++++++++++++++++++= ++++++++----
> --
>=C2=A0 1 file changed, 146 insertions(+), 17 deletions(-)
>
> diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
> index 01e9f45e1205..28c2fee1cb37 100644
> --- a/sys/ufs/ffs/ffs_subr.c
> +++ b/sys/ufs/ffs/ffs_subr.c
> @@ -35,6 +35,7 @@
>=C2=A0 __FBSDID("$FreeBSD$");
>=C2=A0
>=C2=A0 #include <sys/param.h>
> +#include <sys/limits.h>
>=C2=A0
>=C2=A0 #ifndef _KERNEL
>=C2=A0 #include <stdio.h>
> @@ -50,6 +51,7 @@ uint32_t ffs_calc_sbhash(struct fs *);
>=C2=A0 struct malloc_type;
>=C2=A0 #define UFS_MALLOC(size, type, flags) malloc(size)
>=C2=A0 #define UFS_FREE(ptr, type) free(ptr)
> +#define maxphys MAXPHYS
>=C2=A0
>=C2=A0 #else /* _KERNEL */
>=C2=A0 #include <sys/systm.h>
> @@ -125,6 +127,7 @@ ffs_update_dinode_ckhash(struct fs *fs, struct ufs= 2_dinod
> e *dip)
>=C2=A0 static off_t sblock_try[] =3D SBLOCKSEARCH;
>=C2=A0 static int readsuper(void *, struct fs **, off_t, int, int,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0int (*)(void *, off_t, void **, int));
> +static int validate_sblock(struct fs *, int);
>=C2=A0
>=C2=A0 /*
>=C2=A0 =C2=A0* Read a superblock from the devfd device.
> @@ -141,7 +144,7 @@ static int readsuper(void *, struct fs **, off_t, = int, in
> t,
>=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0EIO: non-existent or truncated superb= lock.
>=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0EIO: error reading summary informatio= n.
>=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0ENOENT: no usable known superblock fo= und.
> - *=C2=A0 =C2=A0 =C2=A0ENOSPC: failed to allocate space for the superb= lock.
> + *=C2=A0 =C2=A0 =C2=A0ENOMEM: failed to allocate space for the superb= lock.
>=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0EINVAL: The previous newfs operation = on this volume did not complete.
>=C2=A0 =C2=A0*=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The administrator must = complete newfs before using this volume.
>=C2=A0 =C2=A0*/
> @@ -152,7 +155,8 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t alts= block,
>=C2=A0 {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0struct fs *fs;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0struct fs_summary_info *fs_si;
> -=C2=A0 =C2=A0 =C2=A0int i, error, size, blks;
> +=C2=A0 =C2=A0 =C2=A0int i, error;
> +=C2=A0 =C2=A0 =C2=A0uint64_t size, blks;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0uint8_t *space;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0int32_t *lp;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0char *buf;
> @@ -190,17 +194,16 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t al= tsblock
> ,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fs->fs_contigsumsize > 0)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0size +=3D fs->= ;fs_ncg * sizeof(int32_t);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0size +=3D fs->fs_ncg * sizeof(u_int8_t);<= br> > -=C2=A0 =C2=A0 =C2=A0/* When running in libufs or libsa, UFS_MALLOC ma= y fail */
> -=C2=A0 =C2=A0 =C2=A0if ((fs_si =3D UFS_MALLOC(sizeof(*fs_si), filltyp= e, M_WAITOK)) =3D=3D NULL) {
> +=C2=A0 =C2=A0 =C2=A0if ((fs_si =3D UFS_MALLOC(sizeof(*fs_si), filltyp= e, M_NOWAIT)) =3D=3D NULL) {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UFS_FREE(fs, fil= ltype);
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOSPC);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOMEM);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>=C2=A0 =C2=A0 =C2=A0 =C2=A0bzero(fs_si, sizeof(*fs_si));
>=C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_si =3D fs_si;
> -=C2=A0 =C2=A0 =C2=A0if ((space =3D UFS_MALLOC(size, filltype, M_WAITO= K)) =3D=3D NULL) {
> +=C2=A0 =C2=A0 =C2=A0if ((space =3D UFS_MALLOC(size, filltype, M_NOWAI= T)) =3D=3D NULL) {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UFS_FREE(fs->= fs_si, filltype);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UFS_FREE(fs, fil= ltype);
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOSPC);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOMEM);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0}
>=C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_csp =3D (struct csum *)space;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i < blks; i +=3D fs->fs_= frag) {
> @@ -253,16 +256,8 @@ readsuper(void *devfd, struct fs **fsp, off_t sbl= ockloc,
>=C2=A0 int isaltsblk,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0fs =3D *fsp;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fs->fs_magic =3D=3D FS_BAD_MAGIC)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (EINVAL);=
> -=C2=A0 =C2=A0 =C2=A0if (!(((fs->fs_magic =3D=3D FS_UFS1_MAGIC &= ;& (isaltsblk ||
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sblockloc <=3D SBLOCK_UFS= 1)) ||
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (fs->fs_magic =3D=3D FS_UFS2_MA= GIC && (isaltsblk ||
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sblockloc =3D=3D fs->fs_s= blockloc))) &&
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_ncg >=3D 1 &&<= br> > -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_bsize >=3D MINBSIZE &a= mp;&
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_bsize <=3D MAXBSIZE &a= mp;&
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_bsize >=3D roundup(siz= eof(struct fs), DEV_BSIZE) &&
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_sbsize <=3D SBLOCKSIZE= ))
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if ((error =3D validate_sblock(fs, isaltsblk)) != =3D 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (error);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0/*
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 * If the filesystem has been run on a kerne= l without
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 * metadata check hashes, disable them.
> @@ -310,6 +305,140 @@ readsuper(void *devfd, struct fs **fsp, off_t sb= lockloc
> , int isaltsblk,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0return (0);
>=C2=A0 }
>=C2=A0
> +/*
> + * Verify the filesystem values.
> + */
> +#define ILOG2(num) (fls(num) - 1)
> +
> +static int
> +validate_sblock(struct fs *fs, int isaltsblk)
> +{
> +=C2=A0 =C2=A0 =C2=A0int i, sectorsize;
> +=C2=A0 =C2=A0 =C2=A0u_int64_t maxfilesize, minfpg, sizepb;
> +
> +=C2=A0 =C2=A0 =C2=A0sectorsize =3D dbtob(1);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_magic =3D=3D FS_UFS2_MAGIC) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if ((!isaltsblk &= & (fs->fs_sblockloc !=3D SBLOCK_UFS2 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_sblockactualloc !=3D SBLOCK_UFS2)) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_maxsymlinklen !=3D ((UFS_NDADDR + UFS_NIADDR) *
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0sizeof(ufs2_daddr_t)) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_nindir !=3D fs->fs_bsize / sizeof(ufs2_daddr_t) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_inopb !=3D fs->fs_bsize / sizeof(struct ufs2_dinode))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0} else if (fs->fs_magic =3D=3D FS_UFS1_MAGIC) = {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if ((!isaltsblk &= & (fs->fs_sblockloc > SBLOCK_UFS1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_sblockactualloc !=3D SBLOCK_UFS1)) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_nindir !=3D fs->fs_bsize / sizeof(ufs1_daddr_t) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_inopb !=3D fs->fs_bsize / sizeof(struct ufs1_dinode) |
> |
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_maxsymlinklen !=3D ((UFS_NDADDR + UFS_NIADDR) *
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0sizeof(ufs1_daddr_t)) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_inodefmt !=3D FS_44INODEFMT ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_cgoffset !=3D 0 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_cgmask !=3D 0xffffffff ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_size !=3D fs->fs_size ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_rotdelay !=3D 0 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_rps !=3D 60 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_nspf !=3D fs->fs_fsize / sectorsize ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_cpg !=3D 1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_interleave !=3D 1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_trackskew !=3D 0 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_cpc !=3D 0 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_postblformat !=3D 1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_nrpos !=3D 1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_spc !=3D fs->fs_fpg * fs->fs_old_nspf ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_nsect !=3D fs->fs_old_spc ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_npsect !=3D fs->fs_old_spc ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_dsize !=3D fs->fs_dsize ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_old_ncyl !=3D fs->fs_ncg)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0} else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_bsize < MINBSIZE || fs->fs_bs= ize > MAXBSIZE ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_bsize < roundup(sizeof= (struct fs), DEV_BSIZE) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_sbsize > SBLOCKSIZE ||= fs->fs_sbsize < fs->fs_fsize ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0!powerof2(fs->fs_bsize))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_fsize < sectorsize || fs->fs_= fsize > fs->fs_bsize ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_fsize * MAXFRAG < fs-&= gt;fs_bsize || !powerof2(fs->fs_fsize))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_maxbsize < fs->fs_bsize || !p= owerof2(fs->fs_maxbsize) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_maxbsize > FS_MAXCONTI= G * fs->fs_bsize)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_bmask !=3D ~(fs->fs_bsize - 1) |= |
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_fmask !=3D ~(fs->fs_fs= ize - 1) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_qbmask !=3D ~fs->fs_bm= ask ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_qfmask !=3D ~fs->fs_fm= ask ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_bshift !=3D ILOG2(fs->= fs_bsize) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_fshift !=3D ILOG2(fs->= fs_fsize) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_frag !=3D numfrags(fs, fs= ->fs_bsize) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_fragshift !=3D ILOG2(fs-&= gt;fs_frag) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_frag > MAXFRAG ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_fsbtodb !=3D ILOG2(fs->= ;fs_fsize / sectorsize))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_sblkno !=3D
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0roundup(howmany(fs-&g= t;fs_sblockloc + SBLOCKSIZE, fs->fs_fsize),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->= fs_frag) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_cblkno !=3D fs->fs_sbl= kno +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0roundup(howmany(SBLOC= KSIZE, fs->fs_fsize), fs->fs_frag) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_iblkno !=3D fs->fs_cbl= kno + fs->fs_frag ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_dblkno !=3D fs->fs_ibl= kno + fs->fs_ipg / INOPF(fs) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_cgsize !=3D fragroundup(f= s, CGSIZE(fs)))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_csaddr !=3D cgdmin(fs, 0) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_cssize !=3D
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fragroundup(fs, fs-&g= t;fs_ncg * sizeof(struct csum)) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_dsize !=3D fs->fs_size= - fs->fs_sblkno -
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_ncg * (fs-&= gt;fs_dblkno - fs->fs_sblkno) -
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0howmany(fs->fs_css= ize, fs->fs_fsize) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_metaspace < 0 || fs-&g= t;fs_metaspace > fs->fs_fpg / 2 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_minfree > 99)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0maxfilesize =3D fs->fs_bsize * UFS_NDADDR - 1;=
> +=C2=A0 =C2=A0 =C2=A0for (sizepb =3D fs->fs_bsize, i =3D 0; i < = UFS_NIADDR; i++) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sizepb *=3D NINDIR(fs= );
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0maxfilesize +=3D size= pb;
> +=C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_maxfilesize !=3D maxfilesize)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * These values have a tight interaction with eac= h other that
> +=C2=A0 =C2=A0 =C2=A0 * makes it hard to tightly bound them. So we can= only check
> +=C2=A0 =C2=A0 =C2=A0 * that they are within a broader possible range.=
> +=C2=A0 =C2=A0 =C2=A0 *
> +=C2=A0 =C2=A0 =C2=A0 * Calculate minfpg, the minimum number of fragme= nts that can be
> +=C2=A0 =C2=A0 =C2=A0 * in a cylinder group. The value 12289 is calcul= ated in newfs(8)
> +=C2=A0 =C2=A0 =C2=A0 * when creating the smallest block size UFS vers= ion 1 filesystem
> +=C2=A0 =C2=A0 =C2=A0 * (4096 block size) with no fragments (4096 frag= ment size). That
> +=C2=A0 =C2=A0 =C2=A0 * number may be depressed even further for very = small filesystems
> +=C2=A0 =C2=A0 =C2=A0 * since newfs(8) strives to have at least four c= ylinder groups.
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0minfpg =3D MIN(12289, fs->fs_size / 4);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_ncg < 1 || fs->fs_ncg > (f= s->fs_size / minfpg) + 1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_fpg < minfpg || fs->= ;fs_fpg > fs->fs_size ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_ipg * fs->fs_ncg > = (((int64_t)(1)) << 32) - INOPB(fs) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_ipg > fs->fs_fpg ||= fs->fs_size < 8 * fs->fs_frag)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_size <=3D (fs->fs_ncg - 1) * = fs->fs_fpg ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_size > fs->fs_ncg *= fs->fs_fpg)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * Maxcontig sets the default for the maximum num= ber of blocks
> +=C2=A0 =C2=A0 =C2=A0 * that may be allocated sequentially. With file = system clustering
> +=C2=A0 =C2=A0 =C2=A0 * it is possible to allocate contiguous blocks u= p to the maximum
> +=C2=A0 =C2=A0 =C2=A0 * transfer size permitted by the controller or b= uffering.
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_maxcontig < 1 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_maxcontig > MAX(1, max= phys / fs->fs_bsize))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0if (fs->fs_maxcontig < 0 ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(fs->fs_maxcontig =3D=3D 0 &= & fs->fs_contigsumsize !=3D 0) ||
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(fs->fs_maxcontig > 1 &&a= mp;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fs->fs_contigsumsize !=3D MIN(fs= ->fs_maxcontig, FS_MAXCONTIG)))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (ENOENT);
> +=C2=A0 =C2=A0 =C2=A0return (0);
> +}
> +
>=C2=A0 /*
>=C2=A0 =C2=A0* Write a superblock to the devfd device from the memory p= ointed to by fs.
>=C2=A0 =C2=A0* Write out the superblock summary information if it is pr= esent.
>

Hi Kirk,

This patch broke loader on one of my machines.

I get the following error:

LUA ERROR: Cannot open /boot/lua/loader.lua: no such file or directory"= ;
can't load kernel

Of course booting from my rescue worked.

Copying loader* from /boot on the rescue disk to /boot works around the problem.

Backing up, newfs, and restoring the root filesystem, using my rescue disk =
also didn't work around the problem.

Reverting this patch provided permanent relief.

Loader could read the filesystems on my rescue disk, which had blocksizes <= br> of 16K but not those on my boot disk which had blocksizes of 32K.

My three machines downstairs, all AMD gear with UFS blocksize of 32K, had <= br> no no problems with this whereas my laptop, an Intel, had the problem.

To repeat, a newly created filesystem restored from backup using my rescue =
disk didn't resolve the problem.


--
Cheers,
Cy Schubert <Cy.Schubert@komquats.com> or <Cy.Sch= ubert@cschubert.com>
FreeBSD UNIX:=C2=A0 <cy@FreeBSD.org>=C2=A0 =C2=A0Web:=C2=A0 http://www.FreeBSD.org
NTP:=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<cy@nwtime.org>=C2=A0 =C2= =A0 Web:=C2=A0 https://nwtime.org

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 e**(i*pi)+1=3D0


--00000000000059353005e041e22c--