From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753629AbbE0W3u (ORCPT ); Wed, 27 May 2015 18:29:50 -0400 Received: from mail-wg0-f51.google.com ([74.125.82.51]:36492 "EHLO mail-wg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932355AbbE0W3p (ORCPT ); Wed, 27 May 2015 18:29:45 -0400 Date: Thu, 28 May 2015 01:29:42 +0300 From: Alexey Dobriyan To: Cyrill Gorcunov Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, jarod@redhat.com, jstancek@redhat.com Subject: Re: [PATCH 2/2] proc: fix PAGE_SIZE limit of /proc/$PID/cmdline Message-ID: <20150527222941.GA28699@p183.telecom.by> References: <20150527214757.GA12863@p183.telecom.by> <20150527214953.GB12863@p183.telecom.by> <20150527221435.GG17625@uranus.sw.swsoft.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150527221435.GG17625@uranus.sw.swsoft.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, May 28, 2015 at 01:14:35AM +0300, Cyrill Gorcunov wrote: > On Thu, May 28, 2015 at 12:49:53AM +0300, Alexey Dobriyan wrote: > ... > > -static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns, > > - struct pid *pid, struct task_struct *task) > > +static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, > > + size_t _count, loff_t *pos) > > { > > + struct task_struct *tsk; > > + struct mm_struct *mm; > > + char *page; > > + unsigned long count = _count; > > + unsigned long arg_start, arg_end, env_start, env_end; > > + unsigned long len1, len2, len; > > + unsigned long p; > > + char c; > > + ssize_t rv; > > + > > + BUG_ON(*pos < 0); > > + > > + tsk = get_proc_task(file_inode(file)); > > + if (!tsk) > > + return -ESRCH; > > + mm = get_task_mm(tsk); > > + put_task_struct(tsk); > > + if (!mm) > > + return 0; > > + /* Check if process spawned far enough to have cmdline. */ > > + if (!mm->env_end) { > > + rv = 0; > > + goto out_mmput; > > + } > > + > > + page = (char *)__get_free_page(GFP_TEMPORARY); > > + if (!page) { > > + rv = -ENOMEM; > > + goto out_mmput; > > + } > > + > > + down_read(&mm->mmap_sem); > > + 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); > > Could you please explain why this down/up is needed? Code is written this way to get constistent snapshot of data. If you look at PR_SET_MM_* code, you'll notice down_read(&mm->mmap_sem) as well which is a separate bug because you're _writing_ those fields eventually in prctl_set_mm(), yuck!