From: Helge Deller <deller@gmx.de>
To: linux-arch@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 1/3] proc: Add get_task_cmdline_kernel() function
Date: Mon, 1 Aug 2022 17:20:14 +0200 [thread overview]
Message-ID: <20220801152016.36498-2-deller@gmx.de> (raw)
In-Reply-To: <20220801152016.36498-1-deller@gmx.de>
Add a new function get_task_cmdline_kernel() which reads the command
line of a process into a kernel buffer. This command line can then be
dumped by arch code to print additional debug info on how a faulting
process was started.
The new function re-uses the existing code which provides the cmdline
for the procfs. For that the existing functions were modified so that
the buffer page is allocated outside of get_mm_proctitle() and
get_mm_cmdline() and instead provided as parameter.
Signed-off-by: Helge Deller <deller@gmx.de>
---
fs/proc/base.c | 68 +++++++++++++++++++++++++++--------------
include/linux/proc_fs.h | 5 +++
2 files changed, 50 insertions(+), 23 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8dfa36a99c74..4da9a8b3c7d1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -217,20 +217,17 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
*/
static ssize_t get_mm_proctitle(struct mm_struct *mm, char __user *buf,
size_t count, unsigned long pos,
- unsigned long arg_start)
+ unsigned long arg_start, char *page)
{
- char *page;
int ret, got;
+ size_t size;
- if (pos >= PAGE_SIZE)
+ size = min_t(size_t, PAGE_SIZE, count);
+ if (pos >= size)
return 0;
- page = (char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
ret = 0;
- got = access_remote_vm(mm, arg_start, page, PAGE_SIZE, FOLL_ANON);
+ got = access_remote_vm(mm, arg_start, page, size, FOLL_ANON);
if (got > 0) {
int len = strnlen(page, got);
@@ -238,7 +235,9 @@ static ssize_t get_mm_proctitle(struct mm_struct *mm, char __user *buf,
if (len < got)
len++;
- if (len > pos) {
+ if (!buf)
+ ret = len;
+ else if (len > pos) {
len -= pos;
if (len > count)
len = count;
@@ -248,16 +247,15 @@ static ssize_t get_mm_proctitle(struct mm_struct *mm, char __user *buf,
ret = len;
}
}
- free_page((unsigned long)page);
return ret;
}
static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos, char *page)
{
unsigned long arg_start, arg_end, env_start, env_end;
unsigned long pos, len;
- char *page, c;
+ char c;
/* Check if process spawned far enough to have cmdline. */
if (!mm->env_end)
@@ -283,7 +281,7 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
len = env_end - arg_start;
/* We're not going to care if "*ppos" has high bits set */
- pos = *ppos;
+ pos = ppos ? *ppos : 0;
if (pos >= len)
return 0;
if (count > len - pos)
@@ -299,7 +297,7 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
* pos is 0, and set a flag in the 'struct file'.
*/
if (access_remote_vm(mm, arg_end-1, &c, 1, FOLL_ANON) == 1 && c)
- return get_mm_proctitle(mm, buf, count, pos, arg_start);
+ return get_mm_proctitle(mm, buf, count, pos, arg_start, page);
/*
* For the non-setproctitle() case we limit things strictly
@@ -311,10 +309,6 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
if (count > arg_end - pos)
count = arg_end - pos;
- page = (char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
len = 0;
while (count) {
int got;
@@ -323,7 +317,8 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
got = access_remote_vm(mm, pos, page, size, FOLL_ANON);
if (got <= 0)
break;
- got -= copy_to_user(buf, page, got);
+ if (buf)
+ got -= copy_to_user(buf, page, got);
if (unlikely(!got)) {
if (!len)
len = -EFAULT;
@@ -335,12 +330,11 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
count -= got;
}
- free_page((unsigned long)page);
return len;
}
static ssize_t get_task_cmdline(struct task_struct *tsk, char __user *buf,
- size_t count, loff_t *pos)
+ size_t count, loff_t *pos, char *page)
{
struct mm_struct *mm;
ssize_t ret;
@@ -349,23 +343,51 @@ static ssize_t get_task_cmdline(struct task_struct *tsk, char __user *buf,
if (!mm)
return 0;
- ret = get_mm_cmdline(mm, buf, count, pos);
+ ret = get_mm_cmdline(mm, buf, count, pos, page);
mmput(mm);
return ret;
}
+/*
+ * Place up to maxcount chars of the command line of the process into the
+ * cmdline buffer.
+ */
+void get_task_cmdline_kernel(struct task_struct *tsk,
+ char *cmdline, size_t maxcount)
+{
+ int i;
+
+ memset(cmdline, 0, maxcount);
+ get_task_cmdline(tsk, NULL, maxcount - 1, NULL, cmdline);
+
+ /* remove NULs between parameters */
+ for (i = 0; i < maxcount - 2; i++) {
+ if (cmdline[i])
+ continue;
+ if (cmdline[i+1] == 0)
+ break;
+ cmdline[i] = ' ';
+ }
+}
+
static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
struct task_struct *tsk;
ssize_t ret;
+ char *page;
BUG_ON(*pos < 0);
tsk = get_proc_task(file_inode(file));
if (!tsk)
return -ESRCH;
- ret = get_task_cmdline(tsk, buf, count, pos);
+ page = (char *)__get_free_page(GFP_KERNEL);
+ if (page) {
+ ret = get_task_cmdline(tsk, buf, count, pos, page);
+ free_page((unsigned long)page);
+ } else
+ ret = -ENOMEM;
put_task_struct(tsk);
if (ret > 0)
*pos += ret;
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 81d6e4ec2294..9a256e86205c 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -158,6 +158,9 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task);
#endif /* CONFIG_PROC_PID_ARCH_STATUS */
+void get_task_cmdline_kernel(struct task_struct *tsk,
+ char *cmdline, size_t maxcount);
+
#else /* CONFIG_PROC_FS */
static inline void proc_root_init(void)
@@ -216,6 +219,8 @@ static inline struct pid *tgid_pidfd_to_pid(const struct file *file)
return ERR_PTR(-EBADF);
}
+static inline void get_task_cmdline_kernel(struct task_struct *, char *, size_t) { }
+
#endif /* CONFIG_PROC_FS */
struct net;
--
2.37.1
next prev parent reply other threads:[~2022-08-01 15:20 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-01 15:20 [PATCH 0/3] Dump command line of faulting process to syslog Helge Deller
2022-08-01 15:20 ` Helge Deller [this message]
2022-08-07 14:28 ` [PATCH 1/3] proc: Add get_task_cmdline_kernel() function kernel test robot
2022-08-07 15:11 ` Helge Deller
2022-08-07 15:11 ` Helge Deller
2022-08-01 15:20 ` [PATCH 2/3] lib/dump_stack: Add dump_stack_print_cmdline() and wire up in dump_stack_print_info() Helge Deller
2022-08-06 14:40 ` [lib/dump_stack] 9ac328fc55: BUG:sleeping_function_called_from_invalid_context_at_kernel/locking/rwsem.c kernel test robot
2022-08-06 14:40 ` kernel test robot
2022-08-01 15:20 ` [PATCH 3/3] x86/fault: Dump command line of faulting process to syslog Helge Deller
2022-08-01 16:57 ` [PATCH 0/3] " Josh Triplett
2022-08-02 19:40 ` Helge Deller
2022-08-04 8:09 ` Josh Triplett
2022-08-04 8:39 ` Helge Deller
2022-08-04 9:06 ` Josh Triplett
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220801152016.36498-2-deller@gmx.de \
--to=deller@gmx.de \
--cc=linux-arch@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.