Revision 5a4a898d linux-user/syscall.c
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