Loading linux-user/syscall.c +44 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/dm-ioctl.h> #include <linux/reboot.h> #include <linux/route.h> #include <linux/filter.h> #include "linux_loop.h" #include "cpu-uname.h" Loading Loading @@ -1357,6 +1358,49 @@ set_timeout: case TARGET_SO_SNDTIMEO: optname = SO_SNDTIMEO; goto set_timeout; case TARGET_SO_ATTACH_FILTER: { struct target_sock_fprog *tfprog; struct target_sock_filter *tfilter; struct sock_fprog fprog; struct sock_filter *filter; int i; if (optlen != sizeof(*tfprog)) { return -TARGET_EINVAL; } if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) { return -TARGET_EFAULT; } if (!lock_user_struct(VERIFY_READ, tfilter, tswapal(tfprog->filter), 0)) { unlock_user_struct(tfprog, optval_addr, 1); return -TARGET_EFAULT; } fprog.len = tswap16(tfprog->len); filter = malloc(fprog.len * sizeof(*filter)); if (filter == NULL) { unlock_user_struct(tfilter, tfprog->filter, 1); unlock_user_struct(tfprog, optval_addr, 1); return -TARGET_ENOMEM; } for (i = 0; i < fprog.len; i++) { filter[i].code = tswap16(tfilter[i].code); filter[i].jt = tfilter[i].jt; filter[i].jf = tfilter[i].jf; filter[i].k = tswap32(tfilter[i].k); } fprog.filter = filter; ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog))); free(filter); unlock_user_struct(tfilter, tfprog->filter, 1); unlock_user_struct(tfprog, optval_addr, 1); return ret; } /* Options with 'int' argument. */ case TARGET_SO_DEBUG: optname = SO_DEBUG; Loading linux-user/syscall_defs.h +12 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,18 @@ struct target_sockaddr { uint8_t sa_data[14]; }; struct target_sock_filter { abi_ushort code; uint8_t jt; uint8_t jf; abi_uint k; }; struct target_sock_fprog { abi_ushort len; abi_ulong filter; }; struct target_in_addr { uint32_t s_addr; /* big endian */ }; Loading Loading
linux-user/syscall.c +44 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/dm-ioctl.h> #include <linux/reboot.h> #include <linux/route.h> #include <linux/filter.h> #include "linux_loop.h" #include "cpu-uname.h" Loading Loading @@ -1357,6 +1358,49 @@ set_timeout: case TARGET_SO_SNDTIMEO: optname = SO_SNDTIMEO; goto set_timeout; case TARGET_SO_ATTACH_FILTER: { struct target_sock_fprog *tfprog; struct target_sock_filter *tfilter; struct sock_fprog fprog; struct sock_filter *filter; int i; if (optlen != sizeof(*tfprog)) { return -TARGET_EINVAL; } if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) { return -TARGET_EFAULT; } if (!lock_user_struct(VERIFY_READ, tfilter, tswapal(tfprog->filter), 0)) { unlock_user_struct(tfprog, optval_addr, 1); return -TARGET_EFAULT; } fprog.len = tswap16(tfprog->len); filter = malloc(fprog.len * sizeof(*filter)); if (filter == NULL) { unlock_user_struct(tfilter, tfprog->filter, 1); unlock_user_struct(tfprog, optval_addr, 1); return -TARGET_ENOMEM; } for (i = 0; i < fprog.len; i++) { filter[i].code = tswap16(tfilter[i].code); filter[i].jt = tfilter[i].jt; filter[i].jf = tfilter[i].jf; filter[i].k = tswap32(tfilter[i].k); } fprog.filter = filter; ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog))); free(filter); unlock_user_struct(tfilter, tfprog->filter, 1); unlock_user_struct(tfprog, optval_addr, 1); return ret; } /* Options with 'int' argument. */ case TARGET_SO_DEBUG: optname = SO_DEBUG; Loading
linux-user/syscall_defs.h +12 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,18 @@ struct target_sockaddr { uint8_t sa_data[14]; }; struct target_sock_filter { abi_ushort code; uint8_t jt; uint8_t jf; abi_uint k; }; struct target_sock_fprog { abi_ushort len; abi_ulong filter; }; struct target_in_addr { uint32_t s_addr; /* big endian */ }; Loading