18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * mm/memtrace_ashmem.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2022 Huawei Technologies Co., Ltd.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <linux/fs.h>
88c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
98c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
108c2ecf20Sopenharmony_ci#include <linux/fdtable.h>
118c2ecf20Sopenharmony_ci#include <linux/sched/task.h>
128c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
138c2ecf20Sopenharmony_ci#include <linux/memcheck.h>
148c2ecf20Sopenharmony_ci#include "../drivers/staging/android/ashmem.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic int ashmem_debug_process_info_open(struct inode *inode,
178c2ecf20Sopenharmony_ci		struct file *file);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistruct ashmem_debug_process_info_args {
208c2ecf20Sopenharmony_ci	struct seq_file *seq;
218c2ecf20Sopenharmony_ci	struct task_struct *tsk;
228c2ecf20Sopenharmony_ci};
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistatic const struct proc_ops debug_process_ashmem_info_fops = {
258c2ecf20Sopenharmony_ci	.proc_open = ashmem_debug_process_info_open,
268c2ecf20Sopenharmony_ci	.proc_read = seq_read,
278c2ecf20Sopenharmony_ci	.proc_lseek = seq_lseek,
288c2ecf20Sopenharmony_ci	.proc_release = single_release,
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int ashmem_debug_process_info_cb(const void *data,
328c2ecf20Sopenharmony_ci	struct file *f, unsigned int fd)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	const struct ashmem_debug_process_info_args *args = data;
358c2ecf20Sopenharmony_ci	struct task_struct *tsk = args->tsk;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	if (!is_ashmem_file(f))
388c2ecf20Sopenharmony_ci		return 0;
398c2ecf20Sopenharmony_ci	seq_printf(args->seq,
408c2ecf20Sopenharmony_ci		"%s %u %u %s %zu\n",
418c2ecf20Sopenharmony_ci		tsk->comm, tsk->pid, fd,
428c2ecf20Sopenharmony_ci		get_ashmem_name_by_file(f),
438c2ecf20Sopenharmony_ci		get_ashmem_size_by_file(f));
448c2ecf20Sopenharmony_ci	return 0;
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic int ashmem_debug_process_info_show(struct seq_file *s, void *d)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	struct task_struct *tsk = NULL;
508c2ecf20Sopenharmony_ci	struct ashmem_debug_process_info_args cb_args;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	seq_puts(s, "Process ashmem detail info:\n");
538c2ecf20Sopenharmony_ci	seq_puts(s, "----------------------------------------------------\n");
548c2ecf20Sopenharmony_ci	seq_printf(s, "%s %s %s %s %s\n",
558c2ecf20Sopenharmony_ci			"Process name", "Process ID",
568c2ecf20Sopenharmony_ci			"fd", "ashmem_name", "size");
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	ashmem_mutex_lock();
598c2ecf20Sopenharmony_ci	rcu_read_lock();
608c2ecf20Sopenharmony_ci	for_each_process(tsk) {
618c2ecf20Sopenharmony_ci		if (tsk->flags & PF_KTHREAD)
628c2ecf20Sopenharmony_ci			continue;
638c2ecf20Sopenharmony_ci		cb_args.seq = s;
648c2ecf20Sopenharmony_ci		cb_args.tsk = tsk;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci		task_lock(tsk);
678c2ecf20Sopenharmony_ci		iterate_fd(tsk->files, 0,
688c2ecf20Sopenharmony_ci			ashmem_debug_process_info_cb, (void *)&cb_args);
698c2ecf20Sopenharmony_ci		task_unlock(tsk);
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci	rcu_read_unlock();
728c2ecf20Sopenharmony_ci	ashmem_mutex_unlock();
738c2ecf20Sopenharmony_ci	seq_puts(s, "----------------------------------------------------\n");
748c2ecf20Sopenharmony_ci	return 0;
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic int ashmem_debug_process_info_open(struct inode *inode,
788c2ecf20Sopenharmony_ci	struct file *file)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	return single_open(file, ashmem_debug_process_info_show,
818c2ecf20Sopenharmony_ci			inode->i_private);
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_civoid init_ashmem_process_info(void)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	struct proc_dir_entry *entry = NULL;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	entry = proc_create_data("ashmem_process_info", 0444,
898c2ecf20Sopenharmony_ci			NULL, &debug_process_ashmem_info_fops, NULL);
908c2ecf20Sopenharmony_ci	if (!entry)
918c2ecf20Sopenharmony_ci		pr_err("Failed to create ashmem debug info\n");
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
94