webprobe: fix web messages sending 56/100256/1
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Fri, 25 Nov 2016 12:02:15 +0000 (15:02 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Fri, 25 Nov 2016 12:02:15 +0000 (15:02 +0300)
Fix parameters getting and strings packing.

Change-Id: I26d2f2df86cf17da7246a8e02faa362120745eec
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
webprobe/web_msg.c

index eb2939f..e94b895 100644 (file)
 #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);