diff --git a/sys/bus/ppbus/ppb_msq.c b/sys/bus/ppbus/ppb_msq.c --- a/sys/bus/ppbus/ppb_msq.c +++ b/sys/bus/ppbus/ppb_msq.c @@ -67,7 +67,7 @@ break; default: - panic("%s: unknown opcode (%d)", __func__, opcode); + return (NULL); /* DF-5576b: caller reports EINVAL */ } /* retrieve the device operating mode */ @@ -90,15 +90,15 @@ index = EPP19_MSQ; break; default: - panic("%s: unknown EPP protocol (0x%x)!", __func__, - epp); + return (NULL); /* DF-5576b */ } break; case PPB_ECP: index = ECP_MSQ; break; default: - panic("%s: unknown mode (%d)", __func__, ppbdev->mode); + return (NULL); /* DF-5576b; also retires the panic that + * printed ppbdev->mode instead of the bus mode */ } return (&table[index]); @@ -116,6 +116,9 @@ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev); struct ppb_xfer *xfer = mode2xfer(bus, ppbdev, opcode); + if (xfer == NULL) + return (EINVAL); + xfer->loop = loop; return (0); @@ -163,7 +166,7 @@ MS_SET(MS_UNKNOWN), /* set size of transfer */ /* loop: */ MS_CALL(0), /* execute body */ - MS_DBRA(-1 /* loop: */), + MS_DBRA(-2 /* loop: */), MS_CALL(0), /* execute epilog */ MS_RET(0) @@ -203,6 +206,9 @@ type = MS_TYP(param); /* check the instruction position */ + if (ins >= PPB_MS_MAXLEN) + panic("%s: instruction out of range (%d)!", + __func__, ins); if (arg >= PPB_MS_MAXARGS) panic("%s: parameter out of range (0x%x)!", __func__, param); @@ -277,6 +283,11 @@ /* attempt to choose the best mode for the device */ xfer = mode2xfer(bus, ppbdev, mi->opcode); + if (xfer == NULL) { + error = EINVAL; /* DF-5576b */ + goto error; + } + /* figure out if we should use ieee1284 code */ if (!xfer->loop) { if (mi->opcode == MS_OP_PUT) { @@ -289,10 +300,23 @@ INCR_PC; continue; } else { - panic("%s: IEEE1284 read not supported", __func__); + /* DF-5576a: was panic() */ + error = EOPNOTSUPP; + goto error; } } + /* DF-5574: enforce "the xfer microsequence should not + * contain any MS_OP_PUT or MS_OP_GET!" -- the recursive + * ppb_MS_microseq() calls below make a violating loop + * recurse without any depth limit + */ + if (ppb->ppb_in_xfer) { + error = EINVAL; + goto error; + } + ppb->ppb_in_xfer = 1; + /* XXX should use ppb_MS_init_msq() */ initxfer[0].arg[0].p = mi->arg[0].p; initxfer[1].arg[0].i = mi->arg[1].i; @@ -300,16 +324,22 @@ /* initialize transfer */ ppb_MS_microseq(bus, dev, initxfer, &error); - if (error) + if (error) { + ppb->ppb_in_xfer = 0; goto error; + } /* the xfer microsequence should not contain any * MS_OP_PUT or MS_OP_GET! */ ppb_MS_microseq(bus, dev, xfer->loop, &error); - if (error) + if (error) { + ppb->ppb_in_xfer = 0; goto error; + } + + ppb->ppb_in_xfer = 0; INCR_PC; break; diff --git a/sys/bus/ppbus/ppbconf.h b/sys/bus/ppbus/ppbconf.h --- a/sys/bus/ppbus/ppbconf.h +++ b/sys/bus/ppbus/ppbconf.h @@ -244,6 +244,8 @@ * NIBBLE, PS2, EPP or ECP */ void *ppb_owner; /* device which owns the bus */ + + int ppb_in_xfer; /* DF-5574: MS_OP_PUT/GET re-entry guard */ }; #ifdef _KERNEL