[Suggestion] drivers/usb/host/uhci* : sprintf, need check len when use buf

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Alan Stern:

in drivers/usb/host/uhci-debug.c, for function uhci_sprint_schedule:
  we are not check the len of buf (not like another static functions in this file).
    the buffer len is MAX_OUTPUT: 64 * 1024  (line 491, line 517)
    the buffer may not be enough:
      we may loop UHCI_NUMFRAMES times (line 383..433)
      UHCI_NUMFRAMES is 1024 (drivers/usb/host/uhci-hcd.h:87)
      each time of loop may get more than 64 bytes (line 383..433)
        it seems we have noticed len checking when call uhci_show_td (line 411)
        but we not check it outside of uhci_show_td (line 400..414)

  so I suggest to add checking len when use buf (although it seems a little complex)

  I find it by code review, please help checking this suggestion, thanks.

  if this suggestion is valid:
    please help sending patch.
    better to mark me as Reported-by.
    not need cc to me (I am not reviewer)

  Regards.

gchen.

drivers/usb/host/uhci-hcd.h:87:#define UHCI_NUMFRAMES		1024	/* in the frame list [array] */

drivers/usb/host/uhci-debug.c  

347 static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
348 {
349         char *out = buf;
350         int i, j;
351         struct uhci_qh *qh;
352         struct uhci_td *td;
353         struct list_head *tmp, *head;
354         int nframes, nerrs;
355         __hc32 link;
356         __hc32 fsbr_link;
357 
358         static const char * const qh_names[] = {
359                 "unlink", "iso", "int128", "int64", "int32", "int16",
360                 "int8", "int4", "int2", "async", "term"
361         };
362 
363         out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
364         out += sprintf(out, "HC status\n");
365         out += uhci_show_status(uhci, out, len - (out - buf));
366 
367         out += sprintf(out, "Periodic load table\n");
368         for (i = 0; i < MAX_PHASE; ++i) {
369                 out += sprintf(out, "\t%d", uhci->load[i]);
370                 if (i % 8 == 7)
371                         *out++ = '\n';
372         }
373         out += sprintf(out, "Total: %d, #INT: %d, #ISO: %d\n",
374                         uhci->total_load,
375                         uhci_to_hcd(uhci)->self.bandwidth_int_reqs,
376                         uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs);
377         if (debug <= 1)
378                 return out - buf;
379 
380         out += sprintf(out, "Frame List\n");
381         nframes = 10;
382         nerrs = 0;
383         for (i = 0; i < UHCI_NUMFRAMES; ++i) {
384                 __hc32 qh_dma;
385 
386                 j = 0;
387                 td = uhci->frame_cpu[i];
388                 link = uhci->frame[i];
389                 if (!td)
390                         goto check_link;
391 
392                 if (nframes > 0) {
393                         out += sprintf(out, "- Frame %d -> (%08x)\n",
394                                         i, hc32_to_cpu(uhci, link));
395                         j = 1;
396                 }
397 
398                 head = &td->fl_list;
399                 tmp = head;
400                 do {
401                         td = list_entry(tmp, struct uhci_td, fl_list);
402                         tmp = tmp->next;
403                         if (link != LINK_TO_TD(uhci, td)) {
404                                 if (nframes > 0)
405                                         out += sprintf(out, "    link does "
406                                                 "not match list entry!\n");
407                                 else
408                                         ++nerrs;
409                         }
410                         if (nframes > 0)
411                                 out += uhci_show_td(uhci, td, out,
412                                                 len - (out - buf), 4);
413                         link = td->link;
414                 } while (tmp != head);
415 
416 check_link:
417                 qh_dma = uhci_frame_skel_link(uhci, i);
418                 if (link != qh_dma) {
419                         if (nframes > 0) {
420                                 if (!j) {
421                                         out += sprintf(out,
422                                                 "- Frame %d -> (%08x)\n",
423                                                 i, hc32_to_cpu(uhci, link));
424                                         j = 1;
425                                 }
426                                 out += sprintf(out, "   link does not match "
427                                         "QH (%08x)!\n",
428                                         hc32_to_cpu(uhci, qh_dma));
429                         } else
430                                 ++nerrs;
431                 }
432                 nframes -= j;
433         }
434         if (nerrs > 0)
435                 out += sprintf(out, "Skipped %d bad links\n", nerrs);
436 
437         out += sprintf(out, "Skeleton QHs\n");
438 
439         fsbr_link = 0;
440         for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
441                 int cnt = 0;
442 
443                 qh = uhci->skelqh[i];
444                 out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
445                 out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4);
446 
447                 /* Last QH is the Terminating QH, it's different */
448                 if (i == SKEL_TERM) {
449                         if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td))
450                                 out += sprintf(out, "    skel_term_qh element is not set to term_td!\n");
451                         link = fsbr_link;
452                         if (!link)
453                                 link = LINK_TO_QH(uhci, uhci->skel_term_qh);
454                         goto check_qh_link;
455                 }
456 
457                 head = &qh->node;
458                 tmp = head->next;
459 
460                 while (tmp != head) {
461                         qh = list_entry(tmp, struct uhci_qh, node);
462                         tmp = tmp->next;
463                         if (++cnt <= 10)
464                                 out += uhci_show_qh(uhci, qh, out,
465                                                 len - (out - buf), 4);
466                         if (!fsbr_link && qh->skel >= SKEL_FSBR)
467                                 fsbr_link = LINK_TO_QH(uhci, qh);
468                 }
469                 if ((cnt -= 10) > 0)
470                         out += sprintf(out, "    Skipped %d QHs\n", cnt);
471 
472                 link = UHCI_PTR_TERM(uhci);
473                 if (i <= SKEL_ISO)
474                         ;
475                 else if (i < SKEL_ASYNC)
476                         link = LINK_TO_QH(uhci, uhci->skel_async_qh);
477                 else if (!uhci->fsbr_is_on)
478                         ;
479                 else
480                         link = LINK_TO_QH(uhci, uhci->skel_term_qh);
481 check_qh_link:
482                 if (qh->link != link)
483                         out += sprintf(out, "    last QH not linked to next skeleton!\n");
484         }
485 
486         return out - buf;
487 }
488 
489 #ifdef CONFIG_DEBUG_FS
490 
491 #define MAX_OUTPUT      (64 * 1024)
492 
493 struct uhci_debug {
494         int size;
495         char *data;
496 };
497 
498 static int uhci_debug_open(struct inode *inode, struct file *file)
499 {
500         struct uhci_hcd *uhci = inode->i_private;
501         struct uhci_debug *up;
502         unsigned long flags;
503 
504         up = kmalloc(sizeof(*up), GFP_KERNEL);
505         if (!up)
506                 return -ENOMEM;
507 
508         up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
509         if (!up->data) {
510                 kfree(up);
511                 return -ENOMEM;
512         }
513 
514         up->size = 0;
515         spin_lock_irqsave(&uhci->lock, flags);
516         if (uhci->is_initialized)
517                 up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
518         spin_unlock_irqrestore(&uhci->lock, flags);
519 
520         file->private_data = up;
521 
522         return 0;
523 }
524 



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux