#define FUNCTION_NAME_OFFSET 8
#define SOURCE_FILE_NAME_OFFSET 12
-static int __string_pack(void *data, size_t size, const char __user *s)
+static long pack_str_form_user(void *data, size_t size, const char __user *s)
{
- int ret;
- long len;
+ long ret, len;
- if (!s)
- return -EPERM;
-
- len = strlen_user(s);
- if (!len) {
- pr_err(WEB_PREFIX "failed to get userspace string length\n");
- return -EPERM;
- }
-
- if (size < len) {
- printk(WEB_PREFIX "function name is very long(len=%ld)\n", len);
+ if (!size)
return -ENOMEM;
- }
- ret = copy_from_user(data, s, len);
+ ret = strncpy_from_user(data, s, size);
if (ret < 0) {
- printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
+ pr_err(WEB_PREFIX "failed to get userspace string s=%p\n", s);
return ret;
+
+ } else if (ret == size) {
+ pr_warn(WEB_PREFIX "user string is very long ret=%ld\n", ret);
+ len = ret;
+ } else {
+ len = ret + 1;
}
- ((char *)data)[ret] = '\0';
+ ((char *)data)[len - 1] = '\0';
- return ret + 1;
+ return len;
}
void web_sample_msg(struct pt_regs *regs)
{
+ struct task_struct *task = current;
struct swap_msg *m;
void *p;
- struct task_struct *task = current;
- void *call_id;
- size_t pack_size = 0, size;
- int line = 0;
- long tmp, offset;
- int ret;
- u8 type = WEB_MSG_SAMPLING;
+ size_t old_size, size;
+ long ret;
+ void __user *obj_ptr;
+ int line;
+ int __user *line_number_ptr;
+ const char __user **func_name_ptr;
+ const char __user *func_name;
+ const char __user **file_name_ptr;
+ const char __user *file_name;
if (!check_event(task))
return;
/* Get opbject pointer */
- call_id = (void *)swap_get_uarg(regs, 1);
+ obj_ptr = (void __user *)swap_get_uarg(regs, 1);
m = swap_msg_get(MSG_WEB_PROFILING);
p = swap_msg_payload(m);
- size = swap_msg_size(m);
+ old_size = size = swap_msg_size(m);
/* Type */
- *(u8 *)p = type;
+ *(u8 *)p = WEB_MSG_SAMPLING;
p += sizeof(u8);
size -= sizeof(u8);
- pack_size += sizeof(u8);
/* PID */
*(u32 *)p = task->tgid;
p += sizeof(u32);
size -= sizeof(u32);
- pack_size += sizeof(u32);
/* TID */
*(u32 *)p = task->pid;
p += sizeof(u32);
size -= sizeof(u32);
- pack_size += sizeof(u32);
/* Line number (in source file) */
- offset = (long)call_id + LINE_NUMBER_OFFSET;
- if (get_user(line, (int __user *)offset)) {
+ line_number_ptr = obj_ptr + LINE_NUMBER_OFFSET;
+ if (get_user(line, line_number_ptr)) {
pr_err("failed to get line number\n");
goto out;
}
*(u32 *)p = (u32)line;
p += sizeof(u32);
size -= sizeof(u32);
- pack_size += sizeof(u32);
/* Get function name string pointer */
- offset = (long)call_id + FUNCTION_NAME_OFFSET;
- if (get_user(tmp, (long __user *)offset)) {
+ func_name_ptr = obj_ptr + FUNCTION_NAME_OFFSET;
+ if (get_user(func_name, func_name_ptr)) {
pr_err("failed to get function name\n");
goto out;
}
- ret = __string_pack(p, size, (const char __user *)tmp);
+ ret = pack_str_form_user(p, size, func_name);
if (ret < 0)
goto out;
-
p += ret;
size -= ret;
- pack_size += ret;
/* Get source file name string pointer */
- offset = (long)call_id + SOURCE_FILE_NAME_OFFSET;
- if (get_user(tmp, (long __user *)offset)) {
- pr_err("failed to get line number\n");
+ file_name_ptr = obj_ptr + SOURCE_FILE_NAME_OFFSET;
+ if (get_user(file_name, file_name_ptr)) {
+ pr_err("failed to get file name\n");
goto out;
}
- ret = __string_pack(p, size, (const char __user *)tmp);
+ ret = pack_str_form_user(p, size, file_name);
if (ret < 0)
goto out;
-
- p += ret;
size -= ret;
- pack_size += ret;
- swap_msg_flush(m, pack_size);
+ swap_msg_flush(m, old_size - size);
out:
swap_msg_put(m);