/* * NOTES: * - val_len is ignored for everything other than PT_BYTEBUF. * - fromuser is ignored for numeric types */ inline int val_to_ring(struct event_filler_arguments *args, uint64_t val, u16 val_len, bool fromuser) { int len = -1; u16 *psize = (u16 *)(args->buffer + args->curarg * sizeof(u16)); if (unlikely(args->curarg >= args->nargs)) { pr_info("(%u)val_to_ring: too many arguments for event #%u, type=%u, curarg=%u, nargs=%u tid:%u\n", smp_processor_id(), args->nevents, (u32)args->event_type, args->curarg, args->nargs, current->pid); memory_dump(args->buffer - sizeof(struct ppm_evt_hdr), 32); ASSERT(0); return PPM_FAILURE_BUG; } switch (g_event_info[args->event_type].params[args->curarg].type) { case PT_CHARBUF: case PT_FSPATH: if (likely(val != 0)) { if (fromuser) { len = ppm_strncpy_from_user(args->buffer + args->arg_data_offset, (const char __user *)(unsigned long)val, args->arg_data_size); if (unlikely(len < 0)) return PPM_FAILURE_INVALID_USER_MEMORY; } else { char *dest = strncpy(args->buffer + args->arg_data_offset, (const char *)(unsigned long)val, args->arg_data_size); dest[args->arg_data_size - 1] = 0; len = strlen(dest) + 1; } /* * Make sure the string is null-terminated */ *(char *)(args->buffer + args->arg_data_offset + len) = 0; } else { /* * Handle NULL pointers */ char *dest = strncpy(args->buffer + args->arg_data_offset, "(NULL)", args->arg_data_size); dest[args->arg_data_size - 1] = 0; len = strlen(dest) + 1; } break; case PT_BYTEBUF: case PT_SOCKADDR: case PT_SOCKTUPLE: case PT_FDLIST: if (likely(val != 0)) { if (unlikely(val_len >= args->arg_data_size)) { return PPM_FAILURE_BUFFER_FULL; } else { if (fromuser) { len = (int)ppm_copy_from_user(args->buffer + args->arg_data_offset, (const void __user *)(unsigned long)val, val_len); if (unlikely(len != 0)) return PPM_FAILURE_INVALID_USER_MEMORY; len = val_len; } else { memcpy(args->buffer + args->arg_data_offset, (void *)(unsigned long)val, val_len); len = val_len; } } } else { /* * Handle NULL pointers */ len = 0; } break; case PT_FLAGS8: case PT_UINT8: case PT_SIGTYPE: if (likely(args->arg_data_size >= sizeof(u8))) { *(u8 *)(args->buffer + args->arg_data_offset) = (u8)val; len = sizeof(u8); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_FLAGS16: case PT_UINT16: case PT_SYSCALLID: if (likely(args->arg_data_size >= sizeof(u16))) { *(u16 *)(args->buffer + args->arg_data_offset) = (u16)val; len = sizeof(u16); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_FLAGS32: case PT_UINT32: if (likely(args->arg_data_size >= sizeof(u32))) { *(u32 *)(args->buffer + args->arg_data_offset) = (u32)val; len = sizeof(u32); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_RELTIME: case PT_ABSTIME: case PT_UINT64: if (likely(args->arg_data_size >= sizeof(u64))) { *(u64 *)(args->buffer + args->arg_data_offset) = (u64)val; len = sizeof(u64); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT8: if (likely(args->arg_data_size >= sizeof(s8))) { *(s8 *)(args->buffer + args->arg_data_offset) = (s8)(long)val; len = sizeof(s8); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT16: if (likely(args->arg_data_size >= sizeof(s16))) { *(s16 *)(args->buffer + args->arg_data_offset) = (s16)(long)val; len = sizeof(s16); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT32: if (likely(args->arg_data_size >= sizeof(s32))) { *(s32 *)(args->buffer + args->arg_data_offset) = (s32)(long)val; len = sizeof(s32); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT64: case PT_ERRNO: case PT_FD: case PT_PID: if (likely(args->arg_data_size >= sizeof(s64))) { *(s64 *)(args->buffer + args->arg_data_offset) = (s64)(long)val; len = sizeof(s64); } else { return PPM_FAILURE_BUFFER_FULL; } break; default: ASSERT(0); pr_info("val_to_ring: invalid argument type %d. Event %u (%s) might have less parameters than what has been declared in nparams\n", (int)g_event_info[args->event_type].params[args->curarg].type, (u32)args->event_type, g_event_info[args->event_type].name); return PPM_FAILURE_BUG; } ASSERT(len <= 65535); ASSERT(len <= args->arg_data_size); *psize = (u16)len; args->curarg++; args->arg_data_offset += len; args->arg_data_size -= len; return PPM_SUCCESS; }
/* * NOTES: * - val_len is ignored for everything other than PT_BYTEBUF. * - fromuser is ignored for numeric types * - dyn_idx is ignored for everything other than PT_DYN */ int val_to_ring(struct event_filler_arguments *args, uint64_t val, u16 val_len, bool fromuser, u8 dyn_idx) { const struct ppm_param_info *param_info; int len = -1; u16 *psize = (u16 *)(args->buffer + args->curarg * sizeof(u16)); if (unlikely(args->curarg >= args->nargs)) { pr_err("(%u)val_to_ring: too many arguments for event #%u, type=%u, curarg=%u, nargs=%u tid:%u\n", smp_processor_id(), args->nevents, (u32)args->event_type, args->curarg, args->nargs, current->pid); memory_dump(args->buffer - sizeof(struct ppm_evt_hdr), 32); ASSERT(0); return PPM_FAILURE_BUG; } if (unlikely(args->arg_data_size == 0)) return PPM_FAILURE_BUFFER_FULL; param_info = &(g_event_info[args->event_type].params[args->curarg]); if (param_info->type == PT_DYN && param_info->info != NULL) { const struct ppm_param_info *dyn_params; if (unlikely(dyn_idx >= param_info->ninfo)) { ASSERT(0); return PPM_FAILURE_BUG; } dyn_params = (const struct ppm_param_info *)param_info->info; param_info = &dyn_params[dyn_idx]; if (likely(args->arg_data_size >= sizeof(u8))) { *(u8 *)(args->buffer + args->arg_data_offset) = dyn_idx; len = sizeof(u8); } else { return PPM_FAILURE_BUFFER_FULL; } args->arg_data_offset += len; args->arg_data_size -= len; *psize = (u16)len; } else { *psize = 0; } switch (param_info->type) { case PT_CHARBUF: case PT_FSPATH: if (likely(val != 0)) { if (fromuser) { len = ppm_strncpy_from_user(args->buffer + args->arg_data_offset, (const char __user *)(unsigned long)val, args->arg_data_size); if (unlikely(len < 0)) return PPM_FAILURE_INVALID_USER_MEMORY; } else { len = strlcpy(args->buffer + args->arg_data_offset, (const char *)(unsigned long)val, args->arg_data_size); if (++len > args->arg_data_size) len = args->arg_data_size; } /* * Make sure the string is null-terminated */ *(char *)(args->buffer + args->arg_data_offset + len) = 0; } else { /* * Handle NULL pointers */ len = strlcpy(args->buffer + args->arg_data_offset, "(NULL)", args->arg_data_size); if (++len > args->arg_data_size) len = args->arg_data_size; } break; case PT_BYTEBUF: if (likely(val != 0)) { if (fromuser) { /* * Copy the lookahead portion of the buffer that we will use DPI-based * snaplen calculation */ u32 dpi_lookahead_size = DPI_LOOKAHED_SIZE; if (dpi_lookahead_size > val_len) dpi_lookahead_size = val_len; if (unlikely(dpi_lookahead_size >= args->arg_data_size)) return PPM_FAILURE_BUFFER_FULL; len = (int)ppm_copy_from_user(args->buffer + args->arg_data_offset, (const void __user *)(unsigned long)val, dpi_lookahead_size); if (unlikely(len != 0)) return PPM_FAILURE_INVALID_USER_MEMORY; /* * Check if there's more to copy */ if (likely((dpi_lookahead_size != val_len))) { /* * Calculate the snaplen */ if (likely(args->enforce_snaplen)) { u32 sl = args->consumer->snaplen; sl = compute_snaplen(args, args->buffer + args->arg_data_offset, dpi_lookahead_size); if (val_len > sl) val_len = sl; } if (unlikely((val_len) >= args->arg_data_size)) val_len = args->arg_data_size; if (val_len > dpi_lookahead_size) { len = (int)ppm_copy_from_user(args->buffer + args->arg_data_offset + dpi_lookahead_size, (const void __user *)(unsigned long)val + dpi_lookahead_size, val_len - dpi_lookahead_size); if (unlikely(len != 0)) return PPM_FAILURE_INVALID_USER_MEMORY; } } len = val_len; } else { if (likely(args->enforce_snaplen)) { u32 sl = compute_snaplen(args, (char *)(unsigned long)val, val_len); if (val_len > sl) val_len = sl; } if (unlikely(val_len >= args->arg_data_size)) return PPM_FAILURE_BUFFER_FULL; memcpy(args->buffer + args->arg_data_offset, (void *)(unsigned long)val, val_len); len = val_len; } } else { /* * Handle NULL pointers */ len = 0; } break; case PT_SOCKADDR: case PT_SOCKTUPLE: case PT_FDLIST: if (likely(val != 0)) { if (unlikely(val_len >= args->arg_data_size)) return PPM_FAILURE_BUFFER_FULL; if (fromuser) { len = (int)ppm_copy_from_user(args->buffer + args->arg_data_offset, (const void __user *)(unsigned long)val, val_len); if (unlikely(len != 0)) return PPM_FAILURE_INVALID_USER_MEMORY; len = val_len; } else { memcpy(args->buffer + args->arg_data_offset, (void *)(unsigned long)val, val_len); len = val_len; } } else { /* * Handle NULL pointers */ len = 0; } break; case PT_FLAGS8: case PT_UINT8: case PT_SIGTYPE: if (likely(args->arg_data_size >= sizeof(u8))) { *(u8 *)(args->buffer + args->arg_data_offset) = (u8)val; len = sizeof(u8); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_FLAGS16: case PT_UINT16: case PT_SYSCALLID: if (likely(args->arg_data_size >= sizeof(u16))) { *(u16 *)(args->buffer + args->arg_data_offset) = (u16)val; len = sizeof(u16); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_FLAGS32: case PT_UINT32: case PT_UID: case PT_GID: case PT_SIGSET: if (likely(args->arg_data_size >= sizeof(u32))) { *(u32 *)(args->buffer + args->arg_data_offset) = (u32)val; len = sizeof(u32); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_RELTIME: case PT_ABSTIME: case PT_UINT64: if (likely(args->arg_data_size >= sizeof(u64))) { *(u64 *)(args->buffer + args->arg_data_offset) = (u64)val; len = sizeof(u64); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT8: if (likely(args->arg_data_size >= sizeof(s8))) { *(s8 *)(args->buffer + args->arg_data_offset) = (s8)(long)val; len = sizeof(s8); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT16: if (likely(args->arg_data_size >= sizeof(s16))) { *(s16 *)(args->buffer + args->arg_data_offset) = (s16)(long)val; len = sizeof(s16); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT32: if (likely(args->arg_data_size >= sizeof(s32))) { *(s32 *)(args->buffer + args->arg_data_offset) = (s32)(long)val; len = sizeof(s32); } else { return PPM_FAILURE_BUFFER_FULL; } break; case PT_INT64: case PT_ERRNO: case PT_FD: case PT_PID: if (likely(args->arg_data_size >= sizeof(s64))) { *(s64 *)(args->buffer + args->arg_data_offset) = (s64)(long)val; len = sizeof(s64); } else { return PPM_FAILURE_BUFFER_FULL; } break; default: ASSERT(0); pr_err("val_to_ring: invalid argument type %d. Event %u (%s) might have less parameters than what has been declared in nparams\n", (int)g_event_info[args->event_type].params[args->curarg].type, (u32)args->event_type, g_event_info[args->event_type].name); return PPM_FAILURE_BUG; } ASSERT(len <= 65535); ASSERT(len <= args->arg_data_size); *psize += (u16)len; args->curarg++; args->arg_data_offset += len; args->arg_data_size -= len; return PPM_SUCCESS; }