Revision 2efbe911 linux-user/syscall.c

b/linux-user/syscall.c
547 547
        break;
548 548
    case SOL_IP:
549 549
        switch(optname) {
550
        case IP_TOS:
551
        case IP_TTL:
550 552
        case IP_HDRINCL:
553
        case IP_ROUTER_ALERT:
554
        case IP_RECVOPTS:
555
        case IP_RETOPTS:
556
        case IP_PKTINFO:
557
        case IP_MTU_DISCOVER:
558
        case IP_RECVERR:
559
        case IP_RECVTOS:
560
#ifdef IP_FREEBIND
561
        case IP_FREEBIND:
562
#endif
563
        case IP_MULTICAST_TTL:
564
        case IP_MULTICAST_LOOP:
551 565
            val = 0;
552 566
            if (optlen >= sizeof(uint32_t)) {
553 567
                if (get_user(val, (uint32_t *)optval))
......
619 633
	    /* These don't just return a single integer */
620 634
	    goto unimplemented;
621 635
        default:
636
            goto int_case;
637
        }
638
        break;
639
    case SOL_TCP:
640
        /* TCP options all take an 'int' value.  */
641
    int_case:
642
        if (get_user(len, optlen))
643
            return -EFAULT;
644
        if (len < 0)
645
            return -EINVAL;
646
        lv = sizeof(int);
647
        ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
648
        if (ret < 0)
649
            return ret;
650
        val = tswap32(val);
651
        if (len > lv)
652
            len = lv;
653
        if (copy_to_user(optval, &val, len))
654
            return -EFAULT;
655
        if (put_user(len, optlen))
656
            return -EFAULT;
657
        break;
658
    case SOL_IP:
659
        switch(optname) {
660
        case IP_TOS:
661
        case IP_TTL:
662
        case IP_HDRINCL:
663
        case IP_ROUTER_ALERT:
664
        case IP_RECVOPTS:
665
        case IP_RETOPTS:
666
        case IP_PKTINFO:
667
        case IP_MTU_DISCOVER:
668
        case IP_RECVERR:
669
        case IP_RECVTOS:
670
#ifdef IP_FREEBIND
671
        case IP_FREEBIND:
672
#endif
673
        case IP_MULTICAST_TTL:
674
        case IP_MULTICAST_LOOP:
622 675
            if (get_user(len, optlen))
623 676
                return -EFAULT;
624 677
            if (len < 0)
......
627 680
            ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
628 681
            if (ret < 0)
629 682
                return ret;
630
            val = tswap32(val);
631
            if (len > lv)
632
                len = lv;
633
            if (copy_to_user(optval, &val, len))
634
                return -EFAULT;
635
            if (put_user(len, optlen))
636
                return -EFAULT;
683
            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
684
                unsigned char ucval = val;
685
                len = 1;
686
		if (put_user(len, optlen))
687
                    return -EFAULT;
688
		if (copy_to_user(optval,&ucval,1))
689
                    return -EFAULT;
690
            } else {
691
                val = tswap32(val);
692
                if (len > sizeof(int))
693
                    len = sizeof(int);
694
                if (put_user(len, optlen))
695
                    return -EFAULT;
696
                if (copy_to_user(optval, &val, len))
697
                    return -EFAULT;
698
            }
637 699
            break;
700
        default:
701
            goto unimplemented;
638 702
        }
639 703
        break;
640 704
    default:

Also available in: Unified diff