path: root/mm/util.c
diff options
authorMichal Koutný <>2019-05-31 22:30:19 -0700
committerLinus Torvalds <>2019-06-01 15:51:31 -0700
commitbc81426f5beef7da863d3365bc9d45e820448745 (patch)
treec26cfabbc7b48e47b65ea33060067dd7b00567c1 /mm/util.c
parent11bbd8b416f8abf40900dc5041152892f873d915 (diff)
prctl_set_mm: downgrade mmap_sem to read lock
The commit a3b609ef9f8b ("proc read mm's {arg,env}_{start,end} with mmap semaphore taken.") added synchronization of reading argument/environment boundaries under mmap_sem. Later commit 88aa7cc688d4 ("mm: introduce arg_lock to protect arg_start|end and env_start|end in mm_struct") avoided the coarse use of mmap_sem in similar situations. But there still remained two places that (mis)use mmap_sem. get_cmdline should also use arg_lock instead of mmap_sem when it reads the boundaries. The second place that should use arg_lock is in prctl_set_mm. By protecting the boundaries fields with the arg_lock, we can downgrade mmap_sem to reader lock (analogous to what we already do in prctl_set_mm_map). [ coding style fixes] Link: Fixes: 88aa7cc688d4 ("mm: introduce arg_lock to protect arg_start|end and env_start|end in mm_struct") Signed-off-by: Michal Koutný <> Signed-off-by: Laurent Dufour <> Co-developed-by: Laurent Dufour <> Reviewed-by: Cyrill Gorcunov <> Acked-by: Michal Hocko <> Cc: Yang Shi <> Cc: Mateusz Guzik <> Cc: Kirill Tkhai <> Cc: Konstantin Khlebnikov <> Signed-off-by: Andrew Morton <> Signed-off-by: Linus Torvalds <>
Diffstat (limited to 'mm/util.c')
1 files changed, 2 insertions, 2 deletions
diff --git a/mm/util.c b/mm/util.c
index 91682a2090ee..9834c4ab7d8e 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -718,12 +718,12 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
if (!mm->arg_end)
goto out_mm; /* Shh! No looking before we're done */
- down_read(&mm->mmap_sem);
+ spin_lock(&mm->arg_lock);
arg_start = mm->arg_start;
arg_end = mm->arg_end;
env_start = mm->env_start;
env_end = mm->env_end;
- up_read(&mm->mmap_sem);
+ spin_unlock(&mm->arg_lock);
len = arg_end - arg_start;