diff --git a/driver/ppm_fillers.c b/driver/ppm_fillers.c index 169f9af8f4..456a52f979 100644 --- a/driver/ppm_fillers.c +++ b/driver/ppm_fillers.c @@ -2798,6 +2798,198 @@ int f_sys_sendmsg_x(struct event_filler_arguments *args) return add_sentinel(args); } +int f_sys_sendmmsg_e(struct event_filler_arguments *args) +{ + int res; + unsigned long val; + struct mmsghdr mmh; + char *targetbuf = args->str_storage; + const struct iovec __user *iov; +#ifdef CONFIG_COMPAT + const struct compat_iovec __user *compat_iov; + struct compat_mmsghdr compat_mmh; +#endif + unsigned long iovcnt; + int fd; + uint16_t size = 0; + int addrlen; + int err = 0; + struct sockaddr __user *usrsockaddr; + struct sockaddr_storage address; + + /* + * fd + */ + syscall_get_arguments_deprecated(args, 0, 1, &val); + + fd = val; + res = val_to_ring(args, val, 0, false, 0); + CHECK_RES(res); + + /* + * Retrieve the message header + */ + syscall_get_arguments_deprecated(args, 1, 1, &val); + +#ifdef CONFIG_COMPAT + if (!args->compat) { +#endif + if (unlikely(ppm_copy_from_user(&mmh, (const void __user *)val, sizeof(mmh)))) + return PPM_FAILURE_INVALID_USER_MEMORY; + + /* + * size + */ + iov = (const struct iovec __user *)mmh.msg_hdr.msg_iov; + iovcnt = mmh.msg_hdr.msg_iovlen; + + res = parse_readv_writev_bufs(args, iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_SIZE | PRB_FLAG_IS_WRITE); + + + CHECK_RES(res); + + /* + * tuple + */ + usrsockaddr = (struct sockaddr __user *)mmh.msg_hdr.msg_name; + addrlen = mmh.msg_hdr.msg_namelen; +#ifdef CONFIG_COMPAT + } else { + if (unlikely(ppm_copy_from_user(&compat_mmh, (const void __user *)compat_ptr(val), sizeof(compat_mmh)))) + return PPM_FAILURE_INVALID_USER_MEMORY; + + /* + * size + */ + compat_iov = (const struct compat_iovec __user *)compat_ptr(compat_mmh.msg_hdr.msg_iov); + iovcnt = compat_mmh.msg_hdr.msg_iovlen; + + res = compat_parse_readv_writev_bufs(args, compat_iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_SIZE | PRB_FLAG_IS_WRITE); + + + CHECK_RES(res); + + /* + * tuple + */ + usrsockaddr = (struct sockaddr __user *)compat_ptr(compat_mmh.msg_hdr.msg_name); + addrlen = compat_mmh.msg_hdr.msg_namelen; + } +#endif + + if (usrsockaddr != NULL && addrlen != 0) { + /* + * Copy the address + */ + err = addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)&address); + if (likely(err >= 0)) { + /* + * Convert the fd into socket endpoint information + */ + size = fd_to_socktuple(fd, + (struct sockaddr *)&address, + addrlen, + true, + false, + targetbuf, + STR_STORAGE_SIZE); + } + } + + /* Copy the endpoint info into the ring */ + res = val_to_ring(args, + (uint64_t)(unsigned long)targetbuf, + size, + false, + 0); + CHECK_RES(res); + + return add_sentinel(args); +} + +int f_sys_sendmmsg_x(struct event_filler_arguments *args) +{ + int res; + unsigned long val; + long retval; + const struct iovec __user *iov; +#ifdef CONFIG_COMPAT + const struct compat_iovec __user *compat_iov; + struct compat_mmsghdr compat_mmh; +#endif + unsigned long iovcnt; + + struct mmsghdr mmh; + + retval = syscall_get_return_value(current, args->regs); + + /* If the syscall fails we are not able to collect reliable params + * so we return empty ones. + */ + if(retval < 0) + { + res = val_to_ring(args, retval, 0, false, 0); + CHECK_RES(res); + + /* Parameter 2: data (type: PT_BYTEBUF) */ + res = push_empty_param(args); + CHECK_RES(res); + + return add_sentinel(args); + } + + /* + * Retrieve the message header + */ + syscall_get_arguments_deprecated(args, 1, 1, &val); + +#ifdef CONFIG_COMPAT + if (!args->compat) { +#endif + if (unlikely(ppm_copy_from_user(&mmh, (const void __user *)val, sizeof(mmh)))) + { + res = val_to_ring(args, retval, 0, false, 0); + CHECK_RES(res); + + res = val_to_ring(args, 0, 0, false, 0); + CHECK_RES(res); + return add_sentinel(args); + } + + /* Parameter 1: res (type: PT_ERRNO) */ + res = val_to_ring(args, mmh.msg_len, 0, false, 0); + CHECK_RES(res); + + iov = (const struct iovec __user *)mmh.msg_hdr.msg_iov; + iovcnt = mmh.msg_hdr.msg_iovlen; + + /* Parameter 2: data (type: PT_BYTEBUF) */ + res = parse_readv_writev_bufs(args, iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_DATA | PRB_FLAG_IS_WRITE); + CHECK_RES(res); +#ifdef CONFIG_COMPAT + } else { + if (unlikely(ppm_copy_from_user(&compat_mmh, (const void __user *)compat_ptr(val), sizeof(compat_mmh)))) + { + res = val_to_ring(args, retval, 0, false, 0); + CHECK_RES(res); + + res = val_to_ring(args, 0, 0, false, 0); + CHECK_RES(res); + return add_sentinel(args); + } + + compat_iov = (const struct compat_iovec __user *)compat_ptr(compat_mmh.msg_hdr.msg_iov); + iovcnt = compat_mmh.msg_hdr.msg_iovlen; + + /* Parameter 2: data (type: PT_BYTEBUF) */ + res = compat_parse_readv_writev_bufs(args, compat_iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_DATA | PRB_FLAG_IS_WRITE); + CHECK_RES(res); + } +#endif + + return add_sentinel(args); +} + int f_sys_listen_e(struct event_filler_arguments *args) { unsigned long val = 0; @@ -2985,6 +3177,176 @@ int f_sys_recvmsg_x(struct event_filler_arguments *args) return add_sentinel(args); } +int f_sys_recvmmsg_e(struct event_filler_arguments *args) +{ + unsigned long val = 0; + int res = 0; + int32_t fd = 0; + + /* Parameter 1: fd (type: PT_FD)*/ + syscall_get_arguments_deprecated(args, 0, 1, &val); + fd = (int32_t)val; + res = val_to_ring(args, (int64_t)fd, 0, false, 0); + CHECK_RES(res); + + return add_sentinel(args); +} + +int f_sys_recvmmsg_x(struct event_filler_arguments *args) +{ + int res; + unsigned long val; + int64_t retval; + const struct iovec __user *iov; +#ifdef CONFIG_COMPAT + const struct compat_iovec __user *compat_iov; + struct compat_mmsghdr compat_mmh; +#endif + unsigned long iovcnt; + struct mmsghdr mmh; + char *targetbuf = args->str_storage; + int fd; + struct sockaddr __user *usrsockaddr; + struct sockaddr_storage address; + uint16_t size = 0; + int addrlen; + int err = 0; + + retval = (int64_t)syscall_get_return_value(current, args->regs); + + /* If the syscall fails we are not able to collect reliable params + * so we return empty ones. + */ + if(retval < 0) + { + /* Parameter 1: res (type: PT_ERRNO) */ + res = val_to_ring(args, retval, 0, false, 0); + CHECK_RES(res); + + /* Parameter 2: size (type: PT_UINT32) */ + res = val_to_ring(args, 0, 0, false, 0); + CHECK_RES(res); + + /* Parameter 3: data (type: PT_BYTEBUF) */ + res = push_empty_param(args); + CHECK_RES(res); + + /* Parameter 4: tuple (type: PT_SOCKTUPLE) */ + res = push_empty_param(args); + CHECK_RES(res); + + /* Parameter 5: msg_control (type: PT_BYTEBUF) */ + res = push_empty_param(args); + CHECK_RES(res); + + return add_sentinel(args); + } + + /* + * Retrieve the message header + */ + syscall_get_arguments_deprecated(args, 1, 1, &val); + +#ifdef CONFIG_COMPAT + if (!args->compat) { +#endif + if (unlikely(ppm_copy_from_user(&mmh, (const void __user *)val, sizeof(mmh)))) + return PPM_FAILURE_INVALID_USER_MEMORY; + + /* Parameter 1: res (type: PT_ERRNO) */ + res = val_to_ring(args, mmh.msg_len, 0, false, 0); + CHECK_RES(res); + + /* + * data and size + */ + iov = (const struct iovec __user *)mmh.msg_hdr.msg_iov; + iovcnt = mmh.msg_hdr.msg_iovlen; + + res = parse_readv_writev_bufs(args, iov, iovcnt, mmh.msg_len, PRB_FLAG_PUSH_ALL); +#ifdef CONFIG_COMPAT + } else { + if (unlikely(ppm_copy_from_user(&compat_mmh, (const void __user *)compat_ptr(val), sizeof(compat_mmh)))) + return PPM_FAILURE_INVALID_USER_MEMORY; + + /* Parameter 1: res (type: PT_ERRNO) */ + res = val_to_ring(args, compat_mmh.msg_len, 0, false, 0); + CHECK_RES(res); + + /* + * data and size + */ + compat_iov = (const struct compat_iovec __user *)compat_ptr(compat_mmh.msg_hdr.msg_iov); + iovcnt = compat_mmh.msg_hdr.msg_iovlen; + + res = compat_parse_readv_writev_bufs(args, compat_iov, iovcnt, compat_mmh.msg_len, PRB_FLAG_PUSH_ALL); + } +#endif + + CHECK_RES(res); + + /* + * tuple + */ + if (retval >= 0) { + /* + * Get the fd + */ + syscall_get_arguments_deprecated(args, 0, 1, &val); + fd = (int)val; + + /* + * Get the address + */ + usrsockaddr = (struct sockaddr __user *)mmh.msg_hdr.msg_name; + addrlen = mmh.msg_hdr.msg_namelen; + + if (usrsockaddr != NULL && addrlen != 0) { + /* + * Copy the address + */ + err = addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)&address); + if (likely(err >= 0)) { + /* + * Convert the fd into socket endpoint information + */ + size = fd_to_socktuple(fd, + (struct sockaddr *)&address, + addrlen, + true, + true, + targetbuf, + STR_STORAGE_SIZE); + } + } + } + + /* Copy the endpoint info into the ring */ + res = val_to_ring(args, + (uint64_t)(unsigned long)targetbuf, + size, + false, + 0); + CHECK_RES(res); + + /* + msg_control: ancillary data. + */ + if (mmh.msg_hdr.msg_control != NULL && mmh.msg_hdr.msg_controllen > 0) + { + res = val_to_ring(args, (uint64_t)mmh.msg_hdr.msg_control, (uint32_t)mmh.msg_hdr.msg_controllen, true, 0); + CHECK_RES(res); + } + else + { + /* pushing empty data */ + res = push_empty_param(args); + CHECK_RES(res); + } + + return add_sentinel(args); +} + int f_sys_creat_e(struct event_filler_arguments *args) { unsigned long val; diff --git a/test/drivers/test_suites/syscall_exit_suite/sendmmsg_x.cpp b/test/drivers/test_suites/syscall_exit_suite/sendmmsg_x.cpp index 8bf2431eb4..65be9b4e06 100644 --- a/test/drivers/test_suites/syscall_exit_suite/sendmmsg_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/sendmmsg_x.cpp @@ -223,18 +223,7 @@ TEST(SyscallExit, sendmmsgXNullIovec) evt_test->disable_capture(); - if(evt_test->is_modern_bpf_engine() || evt_test->is_bpf_engine()) - { - evt_test->assert_event_presence(); - } - else - { - /* we need to rewrite the logic in old drivers to support this partial collection - * right now we drop the entire event. - */ - evt_test->assert_event_absence(); - GTEST_SKIP() << "[SENDMSG_X]: what we receive is correct but we need to reimplement it, see the code" << std::endl; - } + evt_test->assert_event_presence(); if(HasFatalFailure()) {