Commit 26edcf41db01e810ab2a4791b77222f5dc621ef4

Authored by ths
1 parent 01ba9816

copy_from_user_fdset() update, by Thayne Harbaugh.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3779 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 75 additions and 76 deletions
linux-user/syscall.c
@@ -443,50 +443,66 @@ abi_long do_brk(abi_ulong new_brk) @@ -443,50 +443,66 @@ abi_long do_brk(abi_ulong new_brk)
443 } 443 }
444 } 444 }
445 445
446 -static inline fd_set *target_to_host_fds(fd_set *fds,  
447 - abi_long *target_fds, int n) 446 +static inline abi_long copy_from_user_fdset(fd_set *fds,
  447 + abi_ulong target_fds_addr,
  448 + int n)
448 { 449 {
449 -#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)  
450 - return (fd_set *)target_fds;  
451 -#else  
452 - int i, b;  
453 - if (target_fds) {  
454 - FD_ZERO(fds);  
455 - for(i = 0;i < n; i++) {  
456 - b = (tswapl(target_fds[i / TARGET_ABI_BITS]) >>  
457 - (i & (TARGET_ABI_BITS - 1))) & 1;  
458 - if (b)  
459 - FD_SET(i, fds); 450 + int i, nw, j, k;
  451 + abi_ulong b, *target_fds;
  452 +
  453 + nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
  454 + if (!(target_fds = lock_user(VERIFY_READ,
  455 + target_fds_addr,
  456 + sizeof(abi_ulong) * nw,
  457 + 1)))
  458 + return -TARGET_EFAULT;
  459 +
  460 + FD_ZERO(fds);
  461 + k = 0;
  462 + for (i = 0; i < nw; i++) {
  463 + /* grab the abi_ulong */
  464 + __get_user(b, &target_fds[i]);
  465 + for (j = 0; j < TARGET_ABI_BITS; j++) {
  466 + /* check the bit inside the abi_ulong */
  467 + if ((b >> j) & 1)
  468 + FD_SET(k, fds);
  469 + k++;
460 } 470 }
461 - return fds;  
462 - } else {  
463 - return NULL;  
464 } 471 }
465 -#endif 472 +
  473 + unlock_user(target_fds, target_fds_addr, 0);
  474 +
  475 + return 0;
466 } 476 }
467 477
468 -static inline void host_to_target_fds(abi_long *target_fds,  
469 - fd_set *fds, int n) 478 +static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
  479 + const fd_set *fds,
  480 + int n)
470 { 481 {
471 -#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)  
472 - /* nothing to do */  
473 -#else  
474 int i, nw, j, k; 482 int i, nw, j, k;
475 abi_long v; 483 abi_long v;
  484 + abi_ulong *target_fds;
476 485
477 - if (target_fds) {  
478 - nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;  
479 - k = 0;  
480 - for(i = 0;i < nw; i++) {  
481 - v = 0;  
482 - for(j = 0; j < TARGET_ABI_BITS; j++) {  
483 - v |= ((FD_ISSET(k, fds) != 0) << j);  
484 - k++;  
485 - }  
486 - target_fds[i] = tswapl(v); 486 + nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
  487 + if (!(target_fds = lock_user(VERIFY_WRITE,
  488 + target_fds_addr,
  489 + sizeof(abi_ulong) * nw,
  490 + 0)))
  491 + return -TARGET_EFAULT;
  492 +
  493 + k = 0;
  494 + for (i = 0; i < nw; i++) {
  495 + v = 0;
  496 + for (j = 0; j < TARGET_ABI_BITS; j++) {
  497 + v |= ((FD_ISSET(k, fds) != 0) << j);
  498 + k++;
487 } 499 }
  500 + __put_user(v, &target_fds[i]);
488 } 501 }
489 -#endif 502 +
  503 + unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
  504 +
  505 + return 0;
490 } 506 }
491 507
492 #if defined(__alpha__) 508 #if defined(__alpha__)
@@ -565,74 +581,57 @@ static inline abi_long host_to_target_timeval(abi_ulong target_addr, @@ -565,74 +581,57 @@ static inline abi_long host_to_target_timeval(abi_ulong target_addr,
565 581
566 /* do_select() must return target values and target errnos. */ 582 /* do_select() must return target values and target errnos. */
567 static abi_long do_select(int n, 583 static abi_long do_select(int n,
568 - abi_ulong rfd_p, abi_ulong wfd_p,  
569 - abi_ulong efd_p, abi_ulong target_tv) 584 + abi_ulong rfd_addr, abi_ulong wfd_addr,
  585 + abi_ulong efd_addr, abi_ulong target_tv_addr)
570 { 586 {
571 fd_set rfds, wfds, efds; 587 fd_set rfds, wfds, efds;
572 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; 588 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
573 - abi_long *target_rfds, *target_wfds, *target_efds;  
574 struct timeval tv, *tv_ptr; 589 struct timeval tv, *tv_ptr;
575 abi_long ret; 590 abi_long ret;
576 - int ok;  
577 591
578 - if (rfd_p) {  
579 - target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1);  
580 - if (!target_rfds) {  
581 - ret = -TARGET_EFAULT;  
582 - goto end;  
583 - }  
584 - rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); 592 + if (rfd_addr) {
  593 + if (copy_from_user_fdset(&rfds, rfd_addr, n))
  594 + return -TARGET_EFAULT;
  595 + rfds_ptr = &rfds;
585 } else { 596 } else {
586 - target_rfds = NULL;  
587 rfds_ptr = NULL; 597 rfds_ptr = NULL;
588 } 598 }
589 - if (wfd_p) {  
590 - target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1);  
591 - if (!target_wfds) {  
592 - ret = -TARGET_EFAULT;  
593 - goto end;  
594 - }  
595 - wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); 599 + if (wfd_addr) {
  600 + if (copy_from_user_fdset(&wfds, wfd_addr, n))
  601 + return -TARGET_EFAULT;
  602 + wfds_ptr = &wfds;
596 } else { 603 } else {
597 - target_wfds = NULL;  
598 wfds_ptr = NULL; 604 wfds_ptr = NULL;
599 } 605 }
600 - if (efd_p) {  
601 - target_efds = lock_user(VERIFY_WRITE, efd_p, sizeof(abi_long) * n, 1);  
602 - if (!target_efds) {  
603 - ret = -TARGET_EFAULT;  
604 - goto end;  
605 - }  
606 - efds_ptr = target_to_host_fds(&efds, target_efds, n); 606 + if (efd_addr) {
  607 + if (copy_from_user_fdset(&efds, efd_addr, n))
  608 + return -TARGET_EFAULT;
  609 + efds_ptr = &efds;
607 } else { 610 } else {
608 - target_efds = NULL;  
609 efds_ptr = NULL; 611 efds_ptr = NULL;
610 } 612 }
611 613
612 - if (target_tv) {  
613 - target_to_host_timeval(&tv, target_tv); 614 + if (target_tv_addr) {
  615 + target_to_host_timeval(&tv, target_tv_addr);
614 tv_ptr = &tv; 616 tv_ptr = &tv;
615 } else { 617 } else {
616 tv_ptr = NULL; 618 tv_ptr = NULL;
617 } 619 }
  620 +
618 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); 621 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
619 - ok = !is_error(ret);  
620 622
621 - if (ok) {  
622 - host_to_target_fds(target_rfds, rfds_ptr, n);  
623 - host_to_target_fds(target_wfds, wfds_ptr, n);  
624 - host_to_target_fds(target_efds, efds_ptr, n); 623 + if (!is_error(ret)) {
  624 + if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
  625 + return -TARGET_EFAULT;
  626 + if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
  627 + return -TARGET_EFAULT;
  628 + if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
  629 + return -TARGET_EFAULT;
625 630
626 - if (target_tv) {  
627 - host_to_target_timeval(target_tv, &tv);  
628 - } 631 + if (target_tv_addr)
  632 + host_to_target_timeval(target_tv_addr, &tv);
629 } 633 }
630 634
631 -end:  
632 - unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);  
633 - unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);  
634 - unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);  
635 -  
636 return ret; 635 return ret;
637 } 636 }
638 637