diff options
author | chunx <chunx@nvidia.com> | 2013-07-05 11:42:05 +0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:40:37 -0700 |
commit | db969bbf31dbb79c0f06497f083b4bad16ad88c7 (patch) | |
tree | 79b3f7b9091cbb454e70b1b0e28585175daa904c /net/core | |
parent | d8461f401990820027131da3ec597361d8906cb8 (diff) |
net: show cmdline in /proc/net/{tcp udp tcp6 udp6}
Get process's cmdline from a sock's corresponding inode pointer,
so that cmdline can't be used by Android active-standby app
to find the corresponding package name.
Bug 1185001
Change-Id: Idc8651e4bb85b8a152dfade9689a719f7d72687d
Signed-off-by: Chun Xu <chunx@nvidia.com>
Reviewed-on: http://git-master/r/253458
(cherry picked from commit 5dcfe4f561bd8d1767e0938dfd7565b2b7718478)
Reviewed-on: http://git-master/r/260013
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/sock.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index d6d024cfaaaf..7ba763cbf099 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -87,6 +87,8 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. + * + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -139,6 +141,8 @@ #include <net/tcp.h> #endif +#include <linux/eventpoll.h> + static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); @@ -2512,6 +2516,133 @@ void sk_common_release(struct sock *sk) } EXPORT_SYMBOL(sk_common_release); +char *sk_get_waiting_task_cmdline(struct sock *sk, char *cmdline) +{ + bool softirq_enabled = false; + int res = 0; + unsigned int len; + char *program_name = cmdline; + struct task_struct *task = NULL; + struct mm_struct *mm = NULL; + static char *apk_path_prefix = "/data/data"; + wait_queue_t *wq = NULL; + struct list_head *lh = NULL; + struct socket_wq *sk_wq = NULL; + wait_queue_func_t wait_func; + enum pid_type type; + struct pid *pid = NULL; + struct fown_struct *fown = NULL; + struct file *file; + + *program_name = '\0'; + + if (!sk || !sk->sk_wq) + goto out; + lh = sk->sk_wq->wait.task_list.next; + if (!wq_has_sleeper(sk->sk_wq)) { + sk_wq = sk->sk_wq; + if (sk_wq->fasync_list && sk_wq->fasync_list->fa_file) { + fown = &sk_wq->fasync_list->fa_file->f_owner; + pid = fown->pid; + type = fown->pid_type; + do_each_pid_task(pid, type, task) { + if (task) + break; + } while_each_pid_task(pid, type, task); + } + } else { + lh = sk->sk_wq->wait.task_list.next; + wq = list_entry(lh, wait_queue_t, task_list); + + wait_func = wq->func; + if (wait_func == pollwake) + task = ((struct poll_wqueues *) + (wq->private))->polling_task; + else if (wait_func == default_wake_function) + task = (struct task_struct *)(wq->private); + else if (wait_func == ep_poll_callback) + task = (struct task_struct *)(wq->private); + else if (wait_func == autoremove_wake_function) + task = (struct task_struct *)(wq->private); + else + pr_warning("Unknown wakeup:%p.\n", wait_func); + + if (task) + task = get_thread_process(task); + } + +#ifdef CONFIG_EPOLL + if (!task) { + file = sk->sk_socket->file; + if (file) + task = get_epoll_file_task(file); + } +#endif + + if (!task && sk && sk->sk_socket) + task = SOCK_INODE(sk->sk_socket)->i_private; + + if (!task) { + pr_err("Can't find a process for this sock.\n"); + goto out; + } + + mm = get_task_mm(task); + if (mm && mm->arg_end) { + len = mm->arg_end - mm->arg_start; + + if (len > PAGE_SIZE) + len = PAGE_SIZE; + + if (softirq_count()) { + softirq_enabled = true; + local_bh_enable(); + } + res = access_process_vm(task, mm->arg_start, cmdline, len, 0); + + if (res > 0 && cmdline[res-1] != '\0' && len < PAGE_SIZE) { + len = strnlen(cmdline, res); + if (len < res) { + res = len; + } else { + len = mm->env_end - mm->env_start; + if (len > PAGE_SIZE - res) + len = PAGE_SIZE - res; + res += access_process_vm(task, + mm->env_start, cmdline+res, len, 0); + res = strnlen(cmdline, res); + } + } + if (softirq_enabled) + local_bh_disable(); + + if (res > PAGE_SIZE) + cmdline[PAGE_SIZE-1] = '\0'; + + len = strlen(apk_path_prefix); + if (!strncmp(apk_path_prefix, program_name, len)) + program_name += len; + else + program_name = strrchr(cmdline, '/'); + + if (program_name == NULL) + program_name = cmdline; + else + program_name++; + } + + if (mm) + mmput(mm); + + len = strlen(program_name); + snprintf(program_name + len, PAGE_SIZE-(program_name-cmdline)-len, + " %d %s", task->pid, task->comm); +out: + return program_name; +} +EXPORT_SYMBOL(sk_get_waiting_task_cmdline); + + #ifdef CONFIG_PROC_FS #define PROTO_INUSE_NR 64 /* should be enough for the first time */ struct prot_inuse { |