Skip to content

Commit 65c6604

Browse files
superman-xptakpm00
authored andcommitted
proc: fix the issue of proc_mem_open returning NULL
proc_mem_open() can return an errno, NULL, or mm_struct*. If it fails to acquire mm, it returns NULL, but the caller does not check for the case when the return value is NULL. The following conditions lead to failure in acquiring mm: - The task is a kernel thread (PF_KTHREAD) - The task is exiting (PF_EXITING) Changes: - Add documentation comments for the return value of proc_mem_open(). - Add checks in the caller to return -ESRCH when proc_mem_open() returns NULL. Link: https://lkml.kernel.org/r/[email protected] Reported-by: [email protected] Closes: https://lore.kernel.org/all/[email protected] Signed-off-by: Penglei Jiang <[email protected]> Cc: Al Viro <[email protected]> Cc: Adrian Ratiu <[email protected]> Cc: Christian Brauner <[email protected]> Cc: Felix Moessbauer <[email protected]> Cc: Jeff layton <[email protected]> Cc: Lorenzo Stoakes <[email protected]> Cc: Mateusz Guzik <[email protected]> Cc: Thomas Gleinxer <[email protected]> Cc: xu xin <[email protected]> Cc: Alexey Dobriyan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 3dfd79c commit 65c6604

File tree

3 files changed

+17
-11
lines changed

3 files changed

+17
-11
lines changed

fs/proc/base.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,13 @@ static const struct file_operations proc_single_file_operations = {
827827
.release = single_release,
828828
};
829829

830-
830+
/*
831+
* proc_mem_open() can return errno, NULL or mm_struct*.
832+
*
833+
* - Returns NULL if the task has no mm (PF_KTHREAD or PF_EXITING)
834+
* - Returns mm_struct* on success
835+
* - Returns error code on failure
836+
*/
831837
struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
832838
{
833839
struct task_struct *task = get_proc_task(inode);
@@ -854,8 +860,8 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
854860
{
855861
struct mm_struct *mm = proc_mem_open(inode, mode);
856862

857-
if (IS_ERR(mm))
858-
return PTR_ERR(mm);
863+
if (IS_ERR_OR_NULL(mm))
864+
return mm ? PTR_ERR(mm) : -ESRCH;
859865

860866
file->private_data = mm;
861867
return 0;

fs/proc/task_mmu.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ static int proc_maps_open(struct inode *inode, struct file *file,
212212

213213
priv->inode = inode;
214214
priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
215-
if (IS_ERR(priv->mm)) {
216-
int err = PTR_ERR(priv->mm);
215+
if (IS_ERR_OR_NULL(priv->mm)) {
216+
int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
217217

218218
seq_release_private(inode, file);
219219
return err;
@@ -1325,8 +1325,8 @@ static int smaps_rollup_open(struct inode *inode, struct file *file)
13251325

13261326
priv->inode = inode;
13271327
priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
1328-
if (IS_ERR(priv->mm)) {
1329-
ret = PTR_ERR(priv->mm);
1328+
if (IS_ERR_OR_NULL(priv->mm)) {
1329+
ret = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
13301330

13311331
single_release(inode, file);
13321332
goto out_free;
@@ -2069,8 +2069,8 @@ static int pagemap_open(struct inode *inode, struct file *file)
20692069
struct mm_struct *mm;
20702070

20712071
mm = proc_mem_open(inode, PTRACE_MODE_READ);
2072-
if (IS_ERR(mm))
2073-
return PTR_ERR(mm);
2072+
if (IS_ERR_OR_NULL(mm))
2073+
return mm ? PTR_ERR(mm) : -ESRCH;
20742074
file->private_data = mm;
20752075
return 0;
20762076
}

fs/proc/task_nommu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ static int maps_open(struct inode *inode, struct file *file,
260260

261261
priv->inode = inode;
262262
priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
263-
if (IS_ERR(priv->mm)) {
264-
int err = PTR_ERR(priv->mm);
263+
if (IS_ERR_OR_NULL(priv->mm)) {
264+
int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
265265

266266
seq_release_private(inode, file);
267267
return err;

0 commit comments

Comments
 (0)