Revision 5a4a898d

b/linux-user/syscall.c
669 669
}
670 670

  
671 671
/* ??? Should this also swap msgh->name?  */
672
static inline void target_to_host_cmsg(struct msghdr *msgh,
673
                                       struct target_msghdr *target_msgh)
672
static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
673
                                           struct target_msghdr *target_msgh)
674 674
{
675 675
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
676
    struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);
676
    abi_long msg_controllen;
677
    abi_ulong target_cmsg_addr;
678
    struct target_cmsghdr *target_cmsg;
677 679
    socklen_t space = 0;
680
    
681
    msg_controllen = tswapl(target_msgh->msg_controllen);
682
    if (msg_controllen < sizeof (struct target_cmsghdr)) 
683
        goto the_end;
684
    target_cmsg_addr = tswapl(target_msgh->msg_control);
685
    target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
686
    if (!target_cmsg)
687
        return -TARGET_EFAULT;
678 688

  
679 689
    while (cmsg && target_cmsg) {
680 690
        void *data = CMSG_DATA(cmsg);
......
709 719
        cmsg = CMSG_NXTHDR(msgh, cmsg);
710 720
        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
711 721
    }
712

  
722
    unlock_user(target_cmsg, target_cmsg_addr, 0);
723
 the_end:
713 724
    msgh->msg_controllen = space;
725
    return 0;
714 726
}
715 727

  
716 728
/* ??? Should this also swap msgh->name?  */
717
static inline void host_to_target_cmsg(struct target_msghdr *target_msgh,
718
                                       struct msghdr *msgh)
729
static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
730
                                           struct msghdr *msgh)
719 731
{
720 732
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
721
    struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);
733
    abi_long msg_controllen;
734
    abi_ulong target_cmsg_addr;
735
    struct target_cmsghdr *target_cmsg;
722 736
    socklen_t space = 0;
723 737

  
738
    msg_controllen = tswapl(target_msgh->msg_controllen);
739
    if (msg_controllen < sizeof (struct target_cmsghdr)) 
740
        goto the_end;
741
    target_cmsg_addr = tswapl(target_msgh->msg_control);
742
    target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
743
    if (!target_cmsg)
744
        return -TARGET_EFAULT;
745

  
724 746
    while (cmsg && target_cmsg) {
725 747
        void *data = CMSG_DATA(cmsg);
726 748
        void *target_data = TARGET_CMSG_DATA(target_cmsg);
......
728 750
        int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
729 751

  
730 752
        space += TARGET_CMSG_SPACE(len);
731
        if (space > tswapl(target_msgh->msg_controllen)) {
753
        if (space > msg_controllen) {
732 754
            space -= TARGET_CMSG_SPACE(len);
733 755
            gemu_log("Target cmsg overflow\n");
734 756
            break;
......
753 775
        cmsg = CMSG_NXTHDR(msgh, cmsg);
754 776
        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
755 777
    }
756

  
757
    msgh->msg_controllen = tswapl(space);
778
    unlock_user(target_cmsg, target_cmsg_addr, space);
779
 the_end:
780
    target_msgh->msg_controllen = tswapl(space);
781
    return 0;
758 782
}
759 783

  
760 784
/* do_setsockopt() Must return target values and target errnos. */
......
1109 1133
    msg.msg_iov = vec;
1110 1134

  
1111 1135
    if (send) {
1112
        target_to_host_cmsg(&msg, msgp);
1113
        ret = get_errno(sendmsg(fd, &msg, flags));
1136
        ret = target_to_host_cmsg(&msg, msgp);
1137
        if (ret == 0)
1138
            ret = get_errno(sendmsg(fd, &msg, flags));
1114 1139
    } else {
1115 1140
        ret = get_errno(recvmsg(fd, &msg, flags));
1116 1141
        if (!is_error(ret))
1117
            host_to_target_cmsg(msgp, &msg);
1142
            ret = host_to_target_cmsg(msgp, &msg);
1118 1143
    }
1119 1144
    unlock_iovec(vec, target_vec, count, !send);
1120 1145
    unlock_user_struct(msgp, target_msg, send ? 0 : 1);
......
1409 1434
#define N_SHM_REGIONS	32
1410 1435

  
1411 1436
static struct shm_region {
1412
    uint32_t	start;
1413
    uint32_t	size;
1437
    abi_ulong	start;
1438
    abi_ulong	size;
1414 1439
} shm_regions[N_SHM_REGIONS];
1415 1440

  
1416 1441
struct target_ipc_perm
......
1776 1801
{
1777 1802
    int version;
1778 1803
    abi_long ret = 0;
1779
    unsigned long raddr;
1780 1804
    struct shmid_ds shm_info;
1781 1805
    int i;
1782 1806

  
......
1831 1855
		break;
1832 1856

  
1833 1857
    case IPCOP_shmat:
1834
	/* SHM_* flags are the same on all linux platforms */
1835
	ret = get_errno((long) shmat(first, (void *) ptr, second));
1836
        if (is_error(ret))
1837
            break;
1838
        raddr = ret;
1839
	/* find out the length of the shared memory segment */
1840

  
1841
        ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
1842
        if (is_error(ret)) {
1843
            /* can't get length, bail out */
1844
            shmdt((void *) raddr);
1845
	    break;
1846
	}
1847
	page_set_flags(raddr, raddr + shm_info.shm_segsz,
1848
		       PAGE_VALID | PAGE_READ |
1849
		       ((second & SHM_RDONLY)? 0: PAGE_WRITE));
1850
	for (i = 0; i < N_SHM_REGIONS; ++i) {
1851
	    if (shm_regions[i].start == 0) {
1852
		shm_regions[i].start = raddr;
1853
		shm_regions[i].size = shm_info.shm_segsz;
1858
        {
1859
            abi_ulong raddr;
1860
            void *host_addr;
1861
            /* SHM_* flags are the same on all linux platforms */
1862
            host_addr = shmat(first, (void *)g2h(ptr), second);
1863
            if (host_addr == (void *)-1) {
1864
                ret = get_errno((long)host_addr);
1854 1865
                break;
1855
	    }
1856
	}
1857
        if (put_user(raddr, third, abi_ulong))
1858
            return -TARGET_EFAULT;
1859
        ret = 0;
1866
            }
1867
            raddr = h2g((unsigned long)host_addr);
1868
            /* find out the length of the shared memory segment */
1869
            
1870
            ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
1871
            if (is_error(ret)) {
1872
                /* can't get length, bail out */
1873
                shmdt(host_addr);
1874
                break;
1875
            }
1876
            page_set_flags(raddr, raddr + shm_info.shm_segsz,
1877
                           PAGE_VALID | PAGE_READ |
1878
                           ((second & SHM_RDONLY)? 0: PAGE_WRITE));
1879
            for (i = 0; i < N_SHM_REGIONS; ++i) {
1880
                if (shm_regions[i].start == 0) {
1881
                    shm_regions[i].start = raddr;
1882
                    shm_regions[i].size = shm_info.shm_segsz;
1883
                    break;
1884
                }
1885
            }
1886
            if (put_user(raddr, third, abi_ulong))
1887
                return -TARGET_EFAULT;
1888
            ret = 0;
1889
        }
1860 1890
	break;
1861 1891
    case IPCOP_shmdt:
1862 1892
	for (i = 0; i < N_SHM_REGIONS; ++i) {
......
1866 1896
		break;
1867 1897
	    }
1868 1898
	}
1869
	ret = get_errno(shmdt((void *) ptr));
1899
	ret = get_errno(shmdt((void *)g2h(ptr)));
1870 1900
	break;
1871 1901

  
1872 1902
    case IPCOP_shmget:

Also available in: Unified diff