Browse Source

Improve error reporting for strange length combinations reported by

the UNDI stack.

Ignore obviously invalid length combinations (as returned by
e.g. VMWare's PXE stack).

Limit to one packet per poll to avoid memory exhaustion.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
2ac7694c3e
1 changed files with 21 additions and 6 deletions
  1. 21
    6
      src/arch/i386/drivers/net/undinet.c

+ 21
- 6
src/arch/i386/drivers/net/undinet.c View File

418
 	struct io_buffer *iobuf = NULL;
418
 	struct io_buffer *iobuf = NULL;
419
 	size_t len;
419
 	size_t len;
420
 	size_t frag_len;
420
 	size_t frag_len;
421
+	size_t max_frag_len;
421
 	int rc;
422
 	int rc;
422
 
423
 
423
 	if ( ! undinic->isr_processing ) {
424
 	if ( ! undinic->isr_processing ) {
446
 			/* Packet fragment received */
447
 			/* Packet fragment received */
447
 			len = undi_isr.FrameLength;
448
 			len = undi_isr.FrameLength;
448
 			frag_len = undi_isr.BufferLength;
449
 			frag_len = undi_isr.BufferLength;
450
+			if ( ( len == 0 ) || ( len < frag_len ) ) {
451
+				/* Don't laugh.  VMWare does it. */
452
+				DBGC ( undinic, "UNDINIC %p reported insane "
453
+				       "fragment (%zd of %zd bytes)\n",
454
+				       undinic, frag_len, len );
455
+				netdev_rx_err ( netdev, NULL, -EINVAL );
456
+				break;
457
+			}
449
 			if ( ! iobuf )
458
 			if ( ! iobuf )
450
 				iobuf = alloc_iob ( len );
459
 				iobuf = alloc_iob ( len );
451
 			if ( ! iobuf ) {
460
 			if ( ! iobuf ) {
456
 				netdev_rx_err ( netdev, NULL, -ENOMEM );
465
 				netdev_rx_err ( netdev, NULL, -ENOMEM );
457
 				goto done;
466
 				goto done;
458
 			}
467
 			}
459
-			if ( frag_len > iob_tailroom ( iobuf ) ) {
468
+			max_frag_len = iob_tailroom ( iobuf );
460
-				DBGC ( undinic, "UNDINIC %p fragment too "
469
+			if ( frag_len > max_frag_len ) {
461
-				       "large\n", undinic );
470
+				DBGC ( undinic, "UNDINIC %p fragment too big "
462
-				frag_len = iob_tailroom ( iobuf );
471
+				       "(%zd+%zd does not fit into %zd)\n",
472
+				       undinic, iob_len ( iobuf ), frag_len,
473
+				       ( iob_len ( iobuf ) + max_frag_len ) );
474
+				frag_len = max_frag_len;
463
 			}
475
 			}
464
 			copy_from_real ( iob_put ( iobuf, frag_len ),
476
 			copy_from_real ( iob_put ( iobuf, frag_len ),
465
 					 undi_isr.Frame.segment,
477
 					 undi_isr.Frame.segment,
473
 				 */
485
 				 */
474
 				if ( undinic->hacks & UNDI_HACK_EB54 )
486
 				if ( undinic->hacks & UNDI_HACK_EB54 )
475
 					--last_trigger_count;
487
 					--last_trigger_count;
488
+				/** HACK: effective RX quota of 1 */
489
+				goto done;
476
 			}
490
 			}
477
 			break;
491
 			break;
478
 		case PXENV_UNDI_ISR_OUT_DONE:
492
 		case PXENV_UNDI_ISR_OUT_DONE:
491
 
505
 
492
  done:
506
  done:
493
 	if ( iobuf ) {
507
 	if ( iobuf ) {
494
-		DBGC ( undinic, "UNDINIC %p returned incomplete packet\n",
508
+		DBGC ( undinic, "UNDINIC %p returned incomplete packet "
495
-		       undinic );
509
+		       "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
510
+		       ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
496
 		netdev_rx_err ( netdev, iobuf, -EINVAL );
511
 		netdev_rx_err ( netdev, iobuf, -EINVAL );
497
 	}
512
 	}
498
 }
513
 }

Loading…
Cancel
Save