* @param pi Pointer to the probe_info struct.
* @return 0 on success, error code on error.
*/
+
int get_get_caller_probe(struct msg_buf *mb, struct probe_info *pi)
{
pi->probe_type = SWAP_GET_CALLER;
{
}
+/**
+ * @brief Gets preload write_msg and puts it to the probe_info struct.
+ *
+ * @param mb Pointer to the message buffer.
+ * @param pi Pointer to the probe_info struct.
+ * @return 0 on success, error code on error.
+ */
+int get_write_msg_probe(struct msg_buf *mb, struct probe_info *pi)
+{
+ pi->probe_type = SWAP_WRITE_MSG;
+ pi->size = sizeof(pi->wm_i);
+
+ return 0;
+}
+
+/**
+ * @brief Preload write_msg type probe data cleanup.
+ *
+ * @param pi Pointer to the probe_info comprising retprobe.
+ * @return Void.
+ */
+void put_write_msg_probe(struct probe_info *pi)
+{
+}
+
if (get_fbi_probe(mb, &(fi->probe_i)) != 0)
goto free_func_inst;
break;
+ case SWAP_WRITE_MSG:
+ if (get_write_msg_probe(mb, &(fi->probe_i)) != 0)
+ goto free_func_inst;
+ break;
default:
printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
type);
case SWAP_FBIPROBE:
put_fbi_probe(&(fi->probe_i));
break;
+ case SWAP_WRITE_MSG:
+ put_write_msg_probe(&(fi->probe_i));
+ break;
default:
printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
fi->probe_i.probe_type);
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
#include <kprobe/swap_kprobes.h>
#include <us_manager/us_manager_common.h>
#include <us_manager/sspt/sspt_page.h>
#include <us_manager/callbacks.h>
#include <writer/kernel_operations.h>
#include <master/swap_initializer.h>
+#include <writer/swap_msg.h>
#include <task_data/task_data.h>
#include "preload.h"
#include "preload_probe.h"
return res;
}
+static inline int __msg_sanitization(char *user_msg, size_t len,
+ char *call_type_p, char *caller_p)
+{
+ int ret;
+
+ ret = access_ok(VERIFY_READ, (unsigned long)user_msg, (unsigned long)len);
+ if (ret == 0)
+ return -EINVAL;
+
+ if ((call_type_p < user_msg) || (call_type_p > user_msg + len) ||
+ (caller_p < user_msg) || (caller_p > user_msg + len))
+ return -EINVAL;
+
+ return 0;
+}
+
return true;
}
+static inline void __write_data_to_msg(char *msg, size_t len,
+ unsigned long call_type_off,
+ unsigned long caller_off)
+{
+ unsigned char call_type = 0;
+ unsigned long caller = 0;
+ int ret;
+
+ ret = preload_threads_get_caller(current, &caller);
+ if (ret != 0) {
+ caller = 0xbadbeef;
+ printk(PRELOAD_PREFIX "Error! Cannot get caller address for %d/%d\n",
+ current->tgid, current->pid);
+ }
+
+ ret = preload_threads_get_call_type(current, &call_type);
+ if (ret != 0) {
+ call_type = 0xff;
+ printk(PRELOAD_PREFIX "Error! Cannot get call type for %d/%d\n",
+ current->tgid, current->pid);
+ }
+
+ /* Using the same types as in the library. */
+ *(uint32_t *)(msg + call_type_off) = (uint32_t)call_type;
+ *(uintptr_t *)(msg + caller_off) = (uintptr_t)caller;
+}
+
+
enum mmap_type_t {
return 0;
}
+static int write_msg_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ char *user_buf;
+ char *buf;
+ char *caller_p;
+ char *call_type_p;
+ size_t len;
+ unsigned long caller_offset;
+ unsigned long call_type_offset;
+ int ret;
+
+ user_buf = (char *)swap_get_uarg(regs, 0);
+ len = swap_get_uarg(regs, 1);
+ call_type_p = (char *)swap_get_uarg(regs, 2);
+ caller_p = (char *)swap_get_uarg(regs, 3);
+
+ ret = __msg_sanitization(user_buf, len, call_type_p, caller_p);
+ if (ret != 0) {
+ printk(PRELOAD_PREFIX "Invalid message pointers!\n");
+ return 0;
+ }
+
+ buf = kmalloc(len, GFP_KERNEL);
+ if (buf == NULL) {
+ printk(PRELOAD_PREFIX "No mem for buffer! Size = %d\n", len);
+ return 0;
+ }
+
+ if (copy_from_user(buf, user_buf, len)) {
+ printk(PRELOAD_PREFIX "Cannot copy data from userspace! Size = %d"
+ " ptr 0x%lx\n", len, (unsigned long)user_buf);
+ goto write_msg_fail;
+ }
+
+ /* Evaluating call_type and caller offset in message:
+ * data offset = data pointer - beginning of the message.
+ */
+ call_type_offset = (unsigned long)(call_type_p - user_buf);
+ caller_offset = (unsigned long)(caller_p - user_buf);
+
+ __write_data_to_msg(buf, len, call_type_offset, caller_offset);
+
+ ret = swap_msg_raw(buf, len);
+ if (ret != len)
+ printk(PRELOAD_PREFIX "Error writing probe lib message\n");
+
+write_msg_fail:
+ kfree(buf);
+
+ return 0;
+}
+
{
}
+int preload_module_write_msg_init(struct us_ip *ip)
+{
+ struct uprobe *up = &ip->uprobe;
+
+ up->kp.pre_handler = write_msg_handler;
+
+ return 0;
+}
+
+void preload_module_write_msg_exit(struct us_ip *ip)
+{
+}
+
+
int preload_module_uprobe_init(struct us_ip *ip)
{
struct uretprobe *rp = &ip->retprobe;
.cleanup = get_caller_info_cleanup
};
+static void write_msg_init(struct us_ip *ip)
+{
+ preload_module_write_msg_init(ip);
+}
+
+static void write_msg_uninit(struct us_ip *ip)
+{
+ preload_module_write_msg_exit(ip);
+ get_caller_info_cleanup(ip->info);
+}
+
+static struct probe_iface write_msg_iface = {
+ .init = write_msg_init,
+ .uninit = write_msg_uninit,
+ .reg = get_caller_register_probe,
+ .unreg = get_caller_unregister_probe,
+ .get_uprobe = get_caller_get_uprobe,
+ .copy = get_caller_info_copy,
+ .cleanup = get_caller_info_cleanup
+};
int register_preload_probes(void)
{
return ret;
ret = swap_register_probe_type(SWAP_GET_CALL_TYPE, &get_call_type_iface);
+ if (ret != 0)
+ return ret;
+
+ ret = swap_register_probe_type(SWAP_WRITE_MSG, &write_msg_iface);
return ret;
}
swap_unregister_probe_type(SWAP_PRELOAD_PROBE);
swap_unregister_probe_type(SWAP_GET_CALLER);
swap_unregister_probe_type(SWAP_GET_CALL_TYPE);
+ swap_unregister_probe_type(SWAP_WRITE_MSG);
}