On 20-06-05 22:42:17, Klemens Nanni wrote: > On Mon, Jun 01, 2020 at 11:48:05PM +0200, Klemens Nanni wrote: > > Installing an unstripped boot loader on softraid on sparc64 fails > > without proper error message. > > > > Make BIOCINSTALLBOOT return a proper errno, make installboot(8) use it > > to provide proper usage errors plus unique code paths for debugging. > > > > At first, I made sr_ioctl_installboot() use sr_error() in the relevant > > spot and this made the kernel print my errors, however the following > > piece in softraid.c:sr_bio_handler() means using sr_error() will hide > > the error code from the ioctl(2) call, i.e. installboot(8) would > > report no error message on stderr and exit zero: > > > > if (sc->sc_status.bs_msg_count > 0) > > rv = 0; > > > > So instead, use a proper errno that yields a simple > > > > # ./obj/installboot sd2 /usr/mdec/bootblk /ofwboot.new > > installboot.sr: softraid installboot failed: File too large > > > > > > > > Background: I built ofwboot on one machine ("make" without > > "make install", then copy obj/ofwboot over), the resulting executable > > was not stripped during build (happens during "make install") and was > > about twice as big: > > > > # ls -l /ofwboot* > > -rw-r--r-- 1 root wheel 106688 May 23 22:42 /ofwboot > > -rwxr-xr-x 1 kn wheel 272452 May 24 00:20 /ofwboot.new > > -rwxr-xr-x 1 root wheel 106752 May 24 01:21 /ofwboot.new.strip > > > > It took me longer than anticipated to find out that installboot(8) > > fails beause my new boot loader was too big: > > > > # installboot sd2 /usr/mdec/bootblk /ofwboot.new > > installboot: softraid installboot failed > > > > # installboot -v sd2 /usr/mdec/bootblk /ofwboot.new > > Using / as root > > installing bootstrap on /dev/rsd2c > > using first-stage /usr/mdec/bootblk, second-stage /ofwboot.new > > boot block is 6882 bytes (14 blocks @ 512 bytes = 7168 bytes) > > sd2: softraid volume with 1 disk(s) > > sd2: installing boot loader on softraid volume > > installboot: softraid installboot failed > > > > That's it, no details or additional messages from the kernel. > > While this was primarily my own fault, perhaps there are more legitimate > > reasons foor bootblk/ofwboot builds to exceed their maximum size. > > In a i386 VM with root on crypto softraid, I built a much bigger second > stage boot loader and performed the same tests as on sparc64: i386 does > not try to install the bogus boot code due to checks in i386_softraid.c > up front: > > # ls -l /usr/mdec/boot /boot.efbig > -r-xr-xr-x 1 root bin 89728 Jun 5 03:02 /usr/mdec/boot > -rwxr-xr-x 1 root wheel 176172 Jun 5 22:16 /boot.efbig > # installboot -v sd1 /usr/mdec/biosboot /boot.efbig > Using / as root > installing bootstrap on /dev/rsd1c > using first-stage /usr/mdec/biosboot, second-stage /boot.efbig > sd1: softraid volume with 1 disk(s) > installboot: boot code will not fit > > So for installboot(8) on sparc64 and i386 as the only two users of > BIOCINSTALLBOOT, this makes root on softraid on sparc64 the only use > that actually hits size checks in the ioctl code.
Keep in mind that the i386 installboot code is used on both i386 and amd64. > sr_ioctl_installboot() seems inconsistent to me in how it reports some > errors through sr_error() (causing ioctl() to return zero) and returing > proper error codes (causing ioctl() and therefore installboot to fail); sr_error() is used to add detail - the installboot code should be checking and handling the case where bs->bs_status is non-zero. IIRC the reason the ioctl has to succeed for this to work, is that on failure there is no copyout(). > Assuming my EFBIG approach is still sensible (for sparc64), diff below > adjusts the errx() call to err() in installboot for both platforms, even > though i386 never reaches it. > > Feedback? OK? While this works, you would be better off making use of the error reporting mechanism that exists. A compile tested only diff for the kernel side is below. A diff to installboot would be needed to graft some code similar to that in bioctl's bio_status() function. Index: softraid.c =================================================================== RCS file: /cvs/src/sys/dev/softraid.c,v retrieving revision 1.401 diff -u -p -u -p -r1.401 softraid.c --- softraid.c 14 Apr 2020 07:38:21 -0000 1.401 +++ softraid.c 6 Jun 2020 14:32:56 -0000 @@ -3704,11 +3704,17 @@ sr_ioctl_installboot(struct sr_softc *sc goto done; } - if (bb->bb_bootblk_size > SR_BOOT_BLOCKS_SIZE * DEV_BSIZE) + if (bb->bb_bootblk_size > SR_BOOT_BLOCKS_SIZE * DEV_BSIZE) { + sr_error(sc, "boot block is too large (%d > %d)", + bb->bb_bootblk_size, SR_BOOT_BLOCKS_SIZE * DEV_BSIZE); goto done; + } - if (bb->bb_bootldr_size > SR_BOOT_LOADER_SIZE * DEV_BSIZE) + if (bb->bb_bootldr_size > SR_BOOT_LOADER_SIZE * DEV_BSIZE) { + sr_error(sc, "boot loader is too large (%d > %d)", + bb->bb_bootldr_size, SR_BOOT_LOADER_SIZE * DEV_BSIZE); goto done; + } secsize = sd->sd_meta->ssdi.ssd_secsize;