DF-5575 / fix.diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | 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 |