summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorchunx <chunx@nvidia.com>2013-07-05 11:42:05 +0800
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:40:37 -0700
commitdb969bbf31dbb79c0f06497f083b4bad16ad88c7 (patch)
tree79b3f7b9091cbb454e70b1b0e28585175daa904c /net/core
parentd8461f401990820027131da3ec597361d8906cb8 (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.c131
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 {