From db9d336823607b4108215cbc44d5a5d926985907 Mon Sep 17 00:00:00 2001 From: lk_hauwei Date: Fri, 10 Jun 2022 09:50:44 +0800 Subject: [PATCH] Add rss_threshold monitoring rss using ohos inclusion category: feature issue: #I5B694 CVE: NA -------------------------------- Add proc/pid/rss proc/pid/rss_threshold for rss Signed-off-by: lk_hauwei --- fs/proc/base.c | 4 ++ fs/proc/internal.h | 6 +++ include/linux/mm.h | 12 +++++ include/linux/mm_types.h | 3 ++ kernel/fork.c | 3 ++ mm/Kconfig | 10 ++++ mm/Makefile | 1 + mm/rss_threshold.c | 110 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 149 insertions(+) create mode 100644 mm/rss_threshold.c diff --git a/fs/proc/base.c b/fs/proc/base.c index 503fce587b67..27145778c144 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3361,6 +3361,10 @@ static const struct pid_entry tgid_base_stuff[] = { #endif #ifdef CONFIG_TIME_NS REG("timens_offsets", S_IRUGO|S_IWUSR, proc_timens_offsets_operations), +#endif +#ifdef CONFIG_RSS_THRESHOLD + ONE("rss", S_IRUGO, proc_pid_rss), + REG("rss_threshold", S_IRUGO|S_IWUSR, proc_pid_rss_threshold_operations), #endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), #ifdef CONFIG_HAVE_ARCH_TRACEHOOK diff --git a/fs/proc/internal.h b/fs/proc/internal.h index afbe96b6bf77..8b91a8395e1d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -171,6 +171,12 @@ extern int pid_delete_dentry(const struct dentry *); extern int proc_pid_readdir(struct file *, struct dir_context *); struct dentry *proc_pid_lookup(struct dentry *, unsigned int); extern loff_t mem_lseek(struct file *, loff_t, int); +#ifdef CONFIG_RSS_THRESHOLD +extern int proc_pid_rss(struct seq_file *, struct pid_namespace *, + struct pid *, struct task_struct *); +extern void listen_rss_threshold(struct mm_struct *mm); +extern const struct file_operations proc_pid_rss_threshold_operations; +#endif /* Lookups */ typedef struct dentry *instantiate_t(struct dentry *, diff --git a/include/linux/mm.h b/include/linux/mm.h index 01d012727a27..6a92fac06b44 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1903,10 +1903,18 @@ static inline unsigned long get_mm_counter(struct mm_struct *mm, int member) void mm_trace_rss_stat(struct mm_struct *mm, int member, long count); +#ifdef CONFIG_RSS_THRESHOLD +void listen_rss_threshold(struct mm_struct *mm); +#endif + static inline void add_mm_counter(struct mm_struct *mm, int member, long value) { long count = atomic_long_add_return(value, &mm->rss_stat.count[member]); +#ifdef CONFIG_RSS_THRESHOLD + listen_rss_threshold(mm); +#endif + mm_trace_rss_stat(mm, member, count); } @@ -1914,6 +1922,10 @@ static inline void inc_mm_counter(struct mm_struct *mm, int member) { long count = atomic_long_inc_return(&mm->rss_stat.count[member]); +#ifdef CONFIG_RSS_THRESHOLD + listen_rss_threshold(mm); +#endif + mm_trace_rss_stat(mm, member, count); } diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index c0aedba56912..a9249cb18123 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -497,6 +497,9 @@ struct mm_struct { unsigned long hiwater_rss; /* High-watermark of RSS usage */ unsigned long hiwater_vm; /* High-water virtual memory usage */ +#ifdef CONFIG_RSS_THRESHOLD + unsigned long rss_threshold; /* A threshold monitor RSS */ +#endif unsigned long total_vm; /* Total pages mapped */ unsigned long locked_vm; /* Pages that have PG_mlocked set */ diff --git a/kernel/fork.c b/kernel/fork.c index 298c44dc5e77..0426eb8a4042 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1022,6 +1022,9 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, mm->mmap = NULL; mm->mm_rb = RB_ROOT; mm->vmacache_seqnum = 0; +#ifdef CONFIG_RSS_THRESHOLD + mm->rss_threshold = 0; +#endif atomic_set(&mm->mm_users, 1); atomic_set(&mm->mm_count, 1); seqcount_init(&mm->write_protect_seq); diff --git a/mm/Kconfig b/mm/Kconfig index c35f9f8a0857..291e90d2de32 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -948,4 +948,14 @@ config MEMTRACE_ASHMEM help Enable the Ashmem Process Info Show +# +# Use rss_threshold to monitoring RSS +# +config RSS_THRESHOLD + bool "Enable /proc//rss and /proc//rss_threshold to monitoring RSS" + default n + depends on PROC_FS && MEMCG + help + Set a threshold to monitoring RSS in per pid + endmenu diff --git a/mm/Makefile b/mm/Makefile index 4c0ca82c4a64..d193db7a48e0 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -66,6 +66,7 @@ ifdef CONFIG_MMU obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o endif +obj-$(CONFIG_RSS_THRESHOLD) += rss_threshold.o obj-$(CONFIG_MEMTRACE_ASHMEM) += memtrace_ashmem.o obj-$(CONFIG_LMKD_DBG) += lmkd_dbg_trigger.o obj-$(CONFIG_LOWMEM) += lowmem_dbg.o diff --git a/mm/rss_threshold.c b/mm/rss_threshold.c new file mode 100644 index 000000000000..1fa01abf1401 --- /dev/null +++ b/mm/rss_threshold.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mm/rss_threshold.c + * + * Copyright (c) 2022 Huawei Technologies Co., Ltd. + */ +#include +#include +#include +#include "../fs/proc/internal.h" + +int proc_pid_rss(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) +{ + struct mm_struct *mm = get_task_mm(task); + unsigned long total_rss; + + if (mm) { + total_rss = get_mm_rss(mm); + seq_printf(m, "VMRss:%lu KB\n", total_rss << (PAGE_SHIFT - 10)); + mmput(mm); + } + return 0; +} + +void listen_rss_threshold(struct mm_struct *mm) +{ + unsigned long total_rss; + + total_rss = get_mm_rss(mm); + + if (!(mm->owner) || mm->rss_threshold == 0) + return; + + total_rss = total_rss << (PAGE_SHIFT - 10); + + if (likely(total_rss <= mm->rss_threshold)) + return; + + if (mm->owner->comm) + pr_err("rss_threshold monitor:Pid:%d [%s] rss size:%lu KB is out of range:%lu KB\n", + mm->owner->pid, mm->owner->comm, + total_rss, + mm->rss_threshold); + else + pr_err("rss_threshold monitor:Pid:%d [NULL] rss size:%lu KB is out of range:%lu KB\n", + mm->owner->pid, + total_rss, + mm->rss_threshold); +} + +static ssize_t rss_threshold_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file_inode(file); + struct task_struct *p; + unsigned long mem_total; + unsigned long rss_threshold; + int err; + + err = kstrtoul_from_user(buf, count, 0, &rss_threshold); + if (err < 0) + return err; + + mem_total = totalram_pages() << (PAGE_SHIFT - 10); + if (rss_threshold < 0 || rss_threshold > mem_total) + return -EINVAL; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + if (p->mm) { + p->mm->rss_threshold = rss_threshold; + listen_rss_threshold(p->mm); + } + + put_task_struct(p); + + return count; +} + +static int rss_threshold_show(struct seq_file *m, void *v) +{ + struct inode *inode = m->private; + struct task_struct *p; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + seq_printf(m, "Threshold:%lu KB\n", p->mm->rss_threshold); + + put_task_struct(p); + + return 0; +} + +static int rss_threshold_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, rss_threshold_show, inode); +} + +const struct file_operations proc_pid_rss_threshold_operations = { + .open = rss_threshold_open, + .read = seq_read, + .write = rss_threshold_write, + .llseek = seq_lseek, + .release = single_release, +}; -- Gitee