Skip to content

Commit c9cd8b1

Browse files
committed
feat(kmod): add arguments to recvmmsg and sendmmsg
The current implementation is not complete, only the first message is processed. In order to allow for multiple messages to be processed the kmod needs to allow for multiple headers to be added to the ringbuffer from the filler. Signed-off-by: Mauro Ezequiel Moltrasio <[email protected]>
1 parent 64601a2 commit c9cd8b1

File tree

2 files changed

+363
-12
lines changed

2 files changed

+363
-12
lines changed

Diff for: driver/ppm_fillers.c

+362
Original file line numberDiff line numberDiff line change
@@ -2743,6 +2743,198 @@ int f_sys_sendmsg_x(struct event_filler_arguments *args)
27432743
return add_sentinel(args);
27442744
}
27452745

2746+
int f_sys_sendmmsg_e(struct event_filler_arguments *args)
2747+
{
2748+
int res;
2749+
unsigned long val;
2750+
struct mmsghdr mmh;
2751+
char *targetbuf = args->str_storage;
2752+
const struct iovec __user *iov;
2753+
#ifdef CONFIG_COMPAT
2754+
const struct compat_iovec __user *compat_iov;
2755+
struct compat_mmsghdr compat_mmh;
2756+
#endif
2757+
unsigned long iovcnt;
2758+
int fd;
2759+
uint16_t size = 0;
2760+
int addrlen;
2761+
int err = 0;
2762+
struct sockaddr __user *usrsockaddr;
2763+
struct sockaddr_storage address;
2764+
2765+
/*
2766+
* fd
2767+
*/
2768+
syscall_get_arguments_deprecated(args, 0, 1, &val);
2769+
2770+
fd = val;
2771+
res = val_to_ring(args, val, 0, false, 0);
2772+
CHECK_RES(res);
2773+
2774+
/*
2775+
* Retrieve the message header
2776+
*/
2777+
syscall_get_arguments_deprecated(args, 1, 1, &val);
2778+
2779+
#ifdef CONFIG_COMPAT
2780+
if (!args->compat) {
2781+
#endif
2782+
if (unlikely(ppm_copy_from_user(&mmh, (const void __user *)val, sizeof(mmh))))
2783+
return PPM_FAILURE_INVALID_USER_MEMORY;
2784+
2785+
/*
2786+
* size
2787+
*/
2788+
iov = (const struct iovec __user *)mmh.msg_hdr.msg_iov;
2789+
iovcnt = mmh.msg_hdr.msg_iovlen;
2790+
2791+
res = parse_readv_writev_bufs(args, iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_SIZE | PRB_FLAG_IS_WRITE);
2792+
2793+
2794+
CHECK_RES(res);
2795+
2796+
/*
2797+
* tuple
2798+
*/
2799+
usrsockaddr = (struct sockaddr __user *)mmh.msg_hdr.msg_name;
2800+
addrlen = mmh.msg_hdr.msg_namelen;
2801+
#ifdef CONFIG_COMPAT
2802+
} else {
2803+
if (unlikely(ppm_copy_from_user(&compat_mmh, (const void __user *)compat_ptr(val), sizeof(compat_mmh))))
2804+
return PPM_FAILURE_INVALID_USER_MEMORY;
2805+
2806+
/*
2807+
* size
2808+
*/
2809+
compat_iov = (const struct compat_iovec __user *)compat_ptr(compat_mmh.msg_hdr.msg_iov);
2810+
iovcnt = compat_mmh.msg_hdr.msg_iovlen;
2811+
2812+
res = compat_parse_readv_writev_bufs(args, compat_iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_SIZE | PRB_FLAG_IS_WRITE);
2813+
2814+
2815+
CHECK_RES(res);
2816+
2817+
/*
2818+
* tuple
2819+
*/
2820+
usrsockaddr = (struct sockaddr __user *)compat_ptr(compat_mmh.msg_hdr.msg_name);
2821+
addrlen = compat_mmh.msg_hdr.msg_namelen;
2822+
}
2823+
#endif
2824+
2825+
if (usrsockaddr != NULL && addrlen != 0) {
2826+
/*
2827+
* Copy the address
2828+
*/
2829+
err = addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)&address);
2830+
if (likely(err >= 0)) {
2831+
/*
2832+
* Convert the fd into socket endpoint information
2833+
*/
2834+
size = fd_to_socktuple(fd,
2835+
(struct sockaddr *)&address,
2836+
addrlen,
2837+
true,
2838+
false,
2839+
targetbuf,
2840+
STR_STORAGE_SIZE);
2841+
}
2842+
}
2843+
2844+
/* Copy the endpoint info into the ring */
2845+
res = val_to_ring(args,
2846+
(uint64_t)(unsigned long)targetbuf,
2847+
size,
2848+
false,
2849+
0);
2850+
CHECK_RES(res);
2851+
2852+
return add_sentinel(args);
2853+
}
2854+
2855+
int f_sys_sendmmsg_x(struct event_filler_arguments *args)
2856+
{
2857+
int res;
2858+
unsigned long val;
2859+
long retval;
2860+
const struct iovec __user *iov;
2861+
#ifdef CONFIG_COMPAT
2862+
const struct compat_iovec __user *compat_iov;
2863+
struct compat_mmsghdr compat_mmh;
2864+
#endif
2865+
unsigned long iovcnt;
2866+
2867+
struct mmsghdr mmh;
2868+
2869+
retval = syscall_get_return_value(current, args->regs);
2870+
2871+
/* If the syscall fails we are not able to collect reliable params
2872+
* so we return empty ones.
2873+
*/
2874+
if(retval < 0)
2875+
{
2876+
res = val_to_ring(args, retval, 0, false, 0);
2877+
CHECK_RES(res);
2878+
2879+
/* Parameter 2: data (type: PT_BYTEBUF) */
2880+
res = push_empty_param(args);
2881+
CHECK_RES(res);
2882+
2883+
return add_sentinel(args);
2884+
}
2885+
2886+
/*
2887+
* Retrieve the message header
2888+
*/
2889+
syscall_get_arguments_deprecated(args, 1, 1, &val);
2890+
2891+
#ifdef CONFIG_COMPAT
2892+
if (!args->compat) {
2893+
#endif
2894+
if (unlikely(ppm_copy_from_user(&mmh, (const void __user *)val, sizeof(mmh))))
2895+
{
2896+
res = val_to_ring(args, retval, 0, false, 0);
2897+
CHECK_RES(res);
2898+
2899+
res = val_to_ring(args, 0, 0, false, 0);
2900+
CHECK_RES(res);
2901+
return add_sentinel(args);
2902+
}
2903+
2904+
/* Parameter 1: res (type: PT_ERRNO) */
2905+
res = val_to_ring(args, mmh.msg_len, 0, false, 0);
2906+
CHECK_RES(res);
2907+
2908+
iov = (const struct iovec __user *)mmh.msg_hdr.msg_iov;
2909+
iovcnt = mmh.msg_hdr.msg_iovlen;
2910+
2911+
/* Parameter 2: data (type: PT_BYTEBUF) */
2912+
res = parse_readv_writev_bufs(args, iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_DATA | PRB_FLAG_IS_WRITE);
2913+
CHECK_RES(res);
2914+
#ifdef CONFIG_COMPAT
2915+
} else {
2916+
if (unlikely(ppm_copy_from_user(&compat_mmh, (const void __user *)compat_ptr(val), sizeof(compat_mmh))))
2917+
{
2918+
res = val_to_ring(args, retval, 0, false, 0);
2919+
CHECK_RES(res);
2920+
2921+
res = val_to_ring(args, 0, 0, false, 0);
2922+
CHECK_RES(res);
2923+
return add_sentinel(args);
2924+
}
2925+
2926+
compat_iov = (const struct compat_iovec __user *)compat_ptr(compat_mmh.msg_hdr.msg_iov);
2927+
iovcnt = compat_mmh.msg_hdr.msg_iovlen;
2928+
2929+
/* Parameter 2: data (type: PT_BYTEBUF) */
2930+
res = compat_parse_readv_writev_bufs(args, compat_iov, iovcnt, args->consumer->snaplen, PRB_FLAG_PUSH_DATA | PRB_FLAG_IS_WRITE);
2931+
CHECK_RES(res);
2932+
}
2933+
#endif
2934+
2935+
return add_sentinel(args);
2936+
}
2937+
27462938
int f_sys_listen_e(struct event_filler_arguments *args)
27472939
{
27482940
unsigned long val = 0;
@@ -2930,6 +3122,176 @@ int f_sys_recvmsg_x(struct event_filler_arguments *args)
29303122
return add_sentinel(args);
29313123
}
29323124

3125+
int f_sys_recvmmsg_e(struct event_filler_arguments *args)
3126+
{
3127+
unsigned long val = 0;
3128+
int res = 0;
3129+
int32_t fd = 0;
3130+
3131+
/* Parameter 1: fd (type: PT_FD)*/
3132+
syscall_get_arguments_deprecated(args, 0, 1, &val);
3133+
fd = (int32_t)val;
3134+
res = val_to_ring(args, (int64_t)fd, 0, false, 0);
3135+
CHECK_RES(res);
3136+
3137+
return add_sentinel(args);
3138+
}
3139+
3140+
int f_sys_recvmmsg_x(struct event_filler_arguments *args)
3141+
{
3142+
int res;
3143+
unsigned long val;
3144+
int64_t retval;
3145+
const struct iovec __user *iov;
3146+
#ifdef CONFIG_COMPAT
3147+
const struct compat_iovec __user *compat_iov;
3148+
struct compat_mmsghdr compat_mmh;
3149+
#endif
3150+
unsigned long iovcnt;
3151+
struct mmsghdr mmh;
3152+
char *targetbuf = args->str_storage;
3153+
int fd;
3154+
struct sockaddr __user *usrsockaddr;
3155+
struct sockaddr_storage address;
3156+
uint16_t size = 0;
3157+
int addrlen;
3158+
int err = 0;
3159+
3160+
retval = (int64_t)syscall_get_return_value(current, args->regs);
3161+
3162+
/* If the syscall fails we are not able to collect reliable params
3163+
* so we return empty ones.
3164+
*/
3165+
if(retval < 0)
3166+
{
3167+
/* Parameter 1: res (type: PT_ERRNO) */
3168+
res = val_to_ring(args, retval, 0, false, 0);
3169+
CHECK_RES(res);
3170+
3171+
/* Parameter 2: size (type: PT_UINT32) */
3172+
res = val_to_ring(args, 0, 0, false, 0);
3173+
CHECK_RES(res);
3174+
3175+
/* Parameter 3: data (type: PT_BYTEBUF) */
3176+
res = push_empty_param(args);
3177+
CHECK_RES(res);
3178+
3179+
/* Parameter 4: tuple (type: PT_SOCKTUPLE) */
3180+
res = push_empty_param(args);
3181+
CHECK_RES(res);
3182+
3183+
/* Parameter 5: msg_control (type: PT_BYTEBUF) */
3184+
res = push_empty_param(args);
3185+
CHECK_RES(res);
3186+
3187+
return add_sentinel(args);
3188+
}
3189+
3190+
/*
3191+
* Retrieve the message header
3192+
*/
3193+
syscall_get_arguments_deprecated(args, 1, 1, &val);
3194+
3195+
#ifdef CONFIG_COMPAT
3196+
if (!args->compat) {
3197+
#endif
3198+
if (unlikely(ppm_copy_from_user(&mmh, (const void __user *)val, sizeof(mmh))))
3199+
return PPM_FAILURE_INVALID_USER_MEMORY;
3200+
3201+
/* Parameter 1: res (type: PT_ERRNO) */
3202+
res = val_to_ring(args, mmh.msg_len, 0, false, 0);
3203+
CHECK_RES(res);
3204+
3205+
/*
3206+
* data and size
3207+
*/
3208+
iov = (const struct iovec __user *)mmh.msg_hdr.msg_iov;
3209+
iovcnt = mmh.msg_hdr.msg_iovlen;
3210+
3211+
res = parse_readv_writev_bufs(args, iov, iovcnt, mmh.msg_len, PRB_FLAG_PUSH_ALL);
3212+
#ifdef CONFIG_COMPAT
3213+
} else {
3214+
if (unlikely(ppm_copy_from_user(&compat_mmh, (const void __user *)compat_ptr(val), sizeof(compat_mmh))))
3215+
return PPM_FAILURE_INVALID_USER_MEMORY;
3216+
3217+
/* Parameter 1: res (type: PT_ERRNO) */
3218+
res = val_to_ring(args, compat_mmh.msg_len, 0, false, 0);
3219+
CHECK_RES(res);
3220+
3221+
/*
3222+
* data and size
3223+
*/
3224+
compat_iov = (const struct compat_iovec __user *)compat_ptr(compat_mmh.msg_hdr.msg_iov);
3225+
iovcnt = compat_mmh.msg_hdr.msg_iovlen;
3226+
3227+
res = compat_parse_readv_writev_bufs(args, compat_iov, iovcnt, compat_mmh.msg_len, PRB_FLAG_PUSH_ALL);
3228+
}
3229+
#endif
3230+
3231+
CHECK_RES(res);
3232+
3233+
/*
3234+
* tuple
3235+
*/
3236+
if (retval >= 0) {
3237+
/*
3238+
* Get the fd
3239+
*/
3240+
syscall_get_arguments_deprecated(args, 0, 1, &val);
3241+
fd = (int)val;
3242+
3243+
/*
3244+
* Get the address
3245+
*/
3246+
usrsockaddr = (struct sockaddr __user *)mmh.msg_hdr.msg_name;
3247+
addrlen = mmh.msg_hdr.msg_namelen;
3248+
3249+
if (usrsockaddr != NULL && addrlen != 0) {
3250+
/*
3251+
* Copy the address
3252+
*/
3253+
err = addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)&address);
3254+
if (likely(err >= 0)) {
3255+
/*
3256+
* Convert the fd into socket endpoint information
3257+
*/
3258+
size = fd_to_socktuple(fd,
3259+
(struct sockaddr *)&address,
3260+
addrlen,
3261+
true,
3262+
true,
3263+
targetbuf,
3264+
STR_STORAGE_SIZE);
3265+
}
3266+
}
3267+
}
3268+
3269+
/* Copy the endpoint info into the ring */
3270+
res = val_to_ring(args,
3271+
(uint64_t)(unsigned long)targetbuf,
3272+
size,
3273+
false,
3274+
0);
3275+
CHECK_RES(res);
3276+
3277+
/*
3278+
msg_control: ancillary data.
3279+
*/
3280+
if (mmh.msg_hdr.msg_control != NULL && mmh.msg_hdr.msg_controllen > 0)
3281+
{
3282+
res = val_to_ring(args, (uint64_t)mmh.msg_hdr.msg_control, (uint32_t)mmh.msg_hdr.msg_controllen, true, 0);
3283+
CHECK_RES(res);
3284+
}
3285+
else
3286+
{
3287+
/* pushing empty data */
3288+
res = push_empty_param(args);
3289+
CHECK_RES(res);
3290+
}
3291+
3292+
return add_sentinel(args);
3293+
}
3294+
29333295
int f_sys_creat_e(struct event_filler_arguments *args)
29343296
{
29353297
unsigned long val;

Diff for: test/drivers/test_suites/syscall_exit_suite/sendmmsg_x.cpp

+1-12
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,7 @@ TEST(SyscallExit, sendmmsgXNullIovec)
223223

224224
evt_test->disable_capture();
225225

226-
if(evt_test->is_modern_bpf_engine() || evt_test->is_bpf_engine())
227-
{
228-
evt_test->assert_event_presence();
229-
}
230-
else
231-
{
232-
/* we need to rewrite the logic in old drivers to support this partial collection
233-
* right now we drop the entire event.
234-
*/
235-
evt_test->assert_event_absence();
236-
GTEST_SKIP() << "[SENDMSG_X]: what we receive is correct but we need to reimplement it, see the code" << std::endl;
237-
}
226+
evt_test->assert_event_presence();
238227

239228
if(HasFatalFailure())
240229
{

0 commit comments

Comments
 (0)