return vma;
}
+static inline bool __inverted(struct us_ip *ip)
+{
+ unsigned long flags = ip->info->pl_i.flags;
+
+ if (flags & SWAP_PRELOAD_INVERTED_PROBE)
+ return true;
+
+ return false;
+}
+
+static inline bool __should_drop(struct us_ip *ip, enum preload_call_type ct)
+{
+ if (ct == NOT_INSTRUMENTED)
+ return true;
+
+ return false;
+}
+
+static inline bool __check_flag_and_call_type(struct us_ip *ip,
+ enum preload_call_type ct)
+{
+ bool inverted = __inverted(ip);
+
+ if (ct != NOT_INSTRUMENTED || inverted)
+ return true;
+
+ return false;
+}
+
static inline bool __is_probe_non_block(struct us_ip *ip)
{
if (ip->info->pl_i.flags & SWAP_PRELOAD_NON_BLOCK_PROBE)
struct vm_area_struct *cvma = __get_vma_by_addr(current, caddr);
enum preload_call_type ct;
- disable_addr = __is_probe_non_block(ip) ? ip->orig_addr : 0;
ct = preload_control_call_type(ip, (void *)caddr);
+ disable_addr = __is_probe_non_block(ip) ?
+ ip->orig_addr : 0;
/* jump only if caller is instumented and it is not a system lib -
* this leads to some errors */
- if (__not_system_caller(current, cvma) && ct != NOT_INSTRUMENTED &&
+ if (__not_system_caller(current, cvma) &&
+ __check_flag_and_call_type(ip, ct) &&
!__is_handlers_call(cvma)) {
if (preload_threads_set_data(current,
caddr, ct,
- disable_addr) != 0)
+ disable_addr,
+ __should_drop(ip,
+ ct)) != 0)
printk(PRELOAD_PREFIX "Error! Failed to set caller 0x%lx"
" for %d/%d\n", caddr, current->tgid,
current->pid);
size_t len;
unsigned long caller_offset;
unsigned long call_type_offset;
+ bool drop;
int ret;
user_buf = (char *)swap_get_uarg(regs, 0);
return 0;
}
+ ret = preload_threads_get_drop(current, &drop);
+ if (ret != 0 || drop)
+ return 0;
+
buf = kmalloc(len, GFP_KERNEL);
if (buf == NULL) {
printk(PRELOAD_PREFIX "No mem for buffer! Size = %d\n", len);
*
* 00 - probe is disabling internal probes;
* 10 - probe is non blocking one;
+ *
+ * 000 - probe is executed for instrumented binaries
+ * 100 - probe is executed for non-instrumented binaries
*/
enum {
SWAP_PRELOAD_ALWAYS_RUN = (1 << 0),
- SWAP_PRELOAD_NON_BLOCK_PROBE = (1 << 1)
+ SWAP_PRELOAD_NON_BLOCK_PROBE = (1 << 1),
+ SWAP_PRELOAD_INVERTED_PROBE = (1 << 2)
};
/* Preload probe info. */
in one thread */
unsigned long caller;
unsigned char call_type;
+ bool drop; /* TODO Workaround, remove when will be possible to install
+ * several us probes at the same addr. */
};
struct disabled_addr {
slot->task = NULL;
slot->caller = 0;
slot->call_type = 0;
+ slot->drop = false;
INIT_LIST_HEAD(&slot->disabled_addrs);
}
static inline void __set_slot(struct thread_slot *slot,
struct task_struct *task, unsigned long caller,
- unsigned char call_type)
+ unsigned char call_type, bool drop)
{
slot->task = task;
slot->caller = caller;
slot->call_type = call_type;
+ slot->drop = drop;
}
static inline int __add_to_disable_list(struct thread_slot *slot,
int preload_threads_set_data(struct task_struct *task, unsigned long caller,
- unsigned char call_type, unsigned long disable_addr)
+ unsigned char call_type,
+ unsigned long disable_addr, bool drop)
{
struct thread_slot *slot;
int ret = 0;
list_for_each_entry(slot, &thread_slot_list, list) {
if (__is_slot_free(slot)) {
- __set_slot(slot, task, caller, call_type);
+ __set_slot(slot, task, caller, call_type, drop);
if ((disable_addr != 0) &&
(__add_to_disable_list(slot, disable_addr) != 0)) {
printk(PRELOAD_PREFIX "Cannot alloc memory!\n");
goto set_data_done;
}
- __set_slot(slot, task, caller, call_type);
+ __set_slot(slot, task, caller, call_type, drop);
set_data_done:
__unlock();
return ret;
}
+int preload_threads_get_drop(struct task_struct *task, bool *drop)
+{
+ struct thread_slot *slot;
+ int ret = 0;
+
+ __lock();
+
+ slot = __get_task_slot(task);
+ if (slot != NULL) {
+ *drop = slot->drop;
+ goto get_drop_done;
+ }
+
+ /* If we're here - slot was not found */
+ ret = -EINVAL;
+
+get_drop_done:
+ __unlock();
+
+ return ret;
+}
+
bool preload_threads_check_disabled_probe(struct task_struct *task,
unsigned long addr)
{
struct task_struct;
int preload_threads_set_data(struct task_struct *task, unsigned long caller,
- unsigned char call_type, unsigned long disable_addr);
+ unsigned char call_type,
+ unsigned long disable_addr, bool drop);
int preload_threads_get_caller(struct task_struct *task, unsigned long *caller);
int preload_threads_get_call_type(struct task_struct *task,
unsigned char *call_type);
+int preload_threads_get_drop(struct task_struct *task, bool *drop);
bool preload_threads_check_disabled_probe(struct task_struct *task,
unsigned long addr);
void preload_threads_enable_probe(struct task_struct *task, unsigned long addr);