From 3c8ebbc8658330fcd7794aecccdec16c46193da1 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 20 Apr 2016 17:58:33 -0400 Subject: [PATCH] Fix: ctf_user_integer should not trigger page fault It is not used by the instrumentation currently, but fix it nevertheless. Signed-off-by: Mathieu Desnoyers --- lib/ringbuffer/backend.h | 25 +++++++++++++++++++++++++ probes/lttng-tracepoint-event-impl.h | 27 ++++++++++++++++++--------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib/ringbuffer/backend.h b/lib/ringbuffer/backend.h index b908ed06..8f6d7d04 100644 --- a/lib/ringbuffer/backend.h +++ b/lib/ringbuffer/backend.h @@ -478,4 +478,29 @@ unsigned long lib_ring_buffer_get_records_unread( return records_unread; } +/* + * We use __copy_from_user_inatomic to copy userspace data after + * checking with access_ok() and disabling page faults. + * + * Return 0 if OK, nonzero on error. + */ +static inline +unsigned long lib_ring_buffer_copy_from_user_check_nofault(void *dest, + const void __user *src, + unsigned long len) +{ + unsigned long ret; + mm_segment_t old_fs; + + if (!access_ok(VERIFY_READ, src, len)) + return 1; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pagefault_disable(); + ret = __copy_from_user_inatomic(dest, src, len); + pagefault_enable(); + set_fs(old_fs); + return ret; +} + #endif /* _LIB_RING_BUFFER_BACKEND_H */ diff --git a/probes/lttng-tracepoint-event-impl.h b/probes/lttng-tracepoint-event-impl.h index f774dff5..a87d146a 100644 --- a/probes/lttng-tracepoint-event-impl.h +++ b/probes/lttng-tracepoint-event-impl.h @@ -29,6 +29,7 @@ #include #include /* for wrapper_vmalloc_sync_all() */ #include +#include #include #include #include @@ -515,11 +516,15 @@ static inline size_t __event_get_size__##_name(size_t *__dynamic_len, \ #undef _ctf_integer_ext_isuser1 #define _ctf_integer_ext_isuser1(_type, _item, _user_src, _byte_order, _base, _nowrite) \ -{ \ - __typeof__(_user_src) _src; \ - if (get_user(_src, &(_user_src))) \ - _src = 0; \ - _ctf_integer_ext_fetched(_type, _item, _src, _byte_order, _base, _nowrite) \ +{ \ + union { \ + char __array[sizeof(_user_src)]; \ + __typeof__(_user_src) __v; \ + } __tmp_fetch; \ + if (lib_ring_buffer_copy_from_user_check_nofault(__tmp_fetch.__array, \ + &(_user_src), sizeof(_user_src))) \ + memset(__tmp_fetch.__array, 0, sizeof(__tmp_fetch.__array)); \ + _ctf_integer_ext_fetched(_type, _item, __tmp_fetch.__v, _byte_order, _base, _nowrite) \ } #undef _ctf_integer_ext @@ -698,10 +703,14 @@ static inline size_t __event_get_align__##_name(void *__tp_locvar) \ #undef _ctf_integer_ext_isuser1 #define _ctf_integer_ext_isuser1(_type, _item, _user_src, _byte_order, _base, _nowrite) \ { \ - __typeof__(_user_src) _src; \ - if (get_user(_src, &(_user_src))) \ - _src = 0; \ - _ctf_integer_ext_fetched(_type, _item, _src, _byte_order, _base, _nowrite) \ + union { \ + char __array[sizeof(_user_src)]; \ + __typeof__(_user_src) __v; \ + } __tmp_fetch; \ + if (lib_ring_buffer_copy_from_user_check_nofault(__tmp_fetch.__array, \ + &(_user_src), sizeof(_user_src))) \ + memset(__tmp_fetch.__array, 0, sizeof(__tmp_fetch.__array)); \ + _ctf_integer_ext_fetched(_type, _item, __tmp_fetch.__v, _byte_order, _base, _nowrite) \ } #undef _ctf_integer_ext -- 2.34.1