From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E758344DB7 for ; Fri, 17 Jul 2026 19:24:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784316242; cv=none; b=HwiJJIpbUqrnOQ7s0GKVGJCH4POL6BK7bTLrvgbVZhV5PNIb82XHzEA5vlgmx3LyZQhD6Y+hDw/A6Xm8m/UOGrpfcXFoj7DTLFHFdCdpPrdPXXL7OMt8UmhehQbe4SicYXO0D0CqteCWKgDOibPG2VtSdA4Q8ZN7WOc6VBttGAk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784316242; c=relaxed/simple; bh=e1bQR5oI8QTHYmFnSn68V2EV9q5mBbeizrMpb9L9OvY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SSsHr7TlQqFp09yM6jez+JKnj/dMI2+x7X5ob3uYrnWEIrOobfYqsnn6FJ5o4GgSICQY2qy22m5dMM6w2q8gNJbeM2OndIVLhOv40IX4H+qYAX16mD7wlL5Pm6kpwLyO2RHv4oexvIfT/BufbYAtjyE5HqbGHdLdb5kDxl1jAls= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kLk4RUI2; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kLk4RUI2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 797681F000E9; Fri, 17 Jul 2026 19:24:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784316241; bh=RD9HIf7Z9HtMyghlfTKJZHhLhfy/96Vf+l1LwACBDMM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kLk4RUI2CMiaQ5FkmBHN1NJkhI0TDbKF94GhhipAt8G7ZcpLtx07Q8A3NgdOC7uJS OZ1kILk1OzBQwHv9gY/7UK76Pzt02kkNVITgr2Q6Hz1a5EUDUCtPEEl1ezuNPhxkHA FrNACmD1SQq9Ea4jJ58fUIFJS/dawhRh78LFTPqPtbav1B4NdNqVME+DWJ8fULoIg8 t/1dLr7N3ZppEUqtp2MKAy2P/4ML7Cw6+ffhnhDJvWoAGVr8RsMgC1FnNliUdO6jH9 9XRhTJZqW/GpxhqAuaLe4SgysGnPz3O9kwS0wBnMcUTxjroYFvMZZomnHWPnRNPqi+ xoEh+at3CewKA== From: Sasha Levin To: stable@vger.kernel.org Cc: Jann Horn , "Christian Brauner (Amutable)" , Sasha Levin Subject: [PATCH 5.10.y] proc: protect ptrace_may_access() with exec_update_lock (part 1) Date: Fri, 17 Jul 2026 15:23:58 -0400 Message-ID: <20260717192358.2131761-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <2026071446-splatter-overlay-9239@gregkh> References: <2026071446-splatter-overlay-9239@gregkh> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Jann Horn [ Upstream commit 6650527444dadc63d84aa939d14ecba4fadb2f69 ] Fix the easy cases where procfs currently calls ptrace_may_access() without exec_update_lock protection, where the fix is to simply add the extra lock or use mm_access(): - do_task_stat(): grab exec_update_lock - proc_pid_wchan(): grab exec_update_lock - proc_map_files_lookup(): use mm_access() instead of get_task_mm() - proc_map_files_readdir(): use mm_access() instead of get_task_mm() - proc_ns_get_link(): grab exec_update_lock - proc_ns_readlink(): grab exec_update_lock Fixes: f83ce3e6b02d ("proc: avoid information leaks to non-privileged processes") Cc: stable@vger.kernel.org Signed-off-by: Jann Horn Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-1-5c3d20e0ac33@google.com Signed-off-by: Christian Brauner (Amutable) [ converted NULL return from mm_access() to ERR_PTR(-ESRCH) at call sites since 5.15's mm_access() returns NULL when the task has no mm ] Signed-off-by: Sasha Levin --- fs/proc/array.c | 6 ++++++ fs/proc/base.c | 41 ++++++++++++++++++++++++----------------- fs/proc/namespaces.c | 12 ++++++++++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index e97ad2bd7a9dc5..f5da742340df47 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -449,6 +449,11 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, unsigned long flags; struct signal_struct *sig = task->signal; unsigned int seq = 1; + int ret; + + ret = down_read_killable(&task->signal->exec_update_lock); + if (ret) + return ret; state = *get_task_state(task); vsize = eip = esp = 0; @@ -626,6 +631,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, seq_puts(m, " 0"); seq_putc(m, '\n'); + up_read(&task->signal->exec_update_lock); if (mm) mmput(mm); return 0; diff --git a/fs/proc/base.c b/fs/proc/base.c index b09cc9e6d5914e..46f19237492ca2 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -422,18 +422,24 @@ static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns, { unsigned long wchan; char symname[KSYM_NAME_LEN]; + int err; + err = down_read_killable(&task->signal->exec_update_lock); + if (err) + return err; if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) goto print0; wchan = get_wchan(task); if (wchan && !lookup_symbol_name(wchan, symname)) { seq_puts(m, symname); + up_read(&task->signal->exec_update_lock); return 0; } print0: seq_putc(m, '0'); + up_read(&task->signal->exec_update_lock); return 0; } #endif /* CONFIG_KALLSYMS */ @@ -2352,17 +2358,17 @@ static struct dentry *proc_map_files_lookup(struct inode *dir, if (!task) goto out; - result = ERR_PTR(-EACCES); - if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) - goto out_put_task; - result = ERR_PTR(-ENOENT); if (dname_to_vma_addr(dentry, &vm_start, &vm_end)) goto out_put_task; - mm = get_task_mm(task); + mm = mm_access(task, PTRACE_MODE_READ_FSCREDS); if (!mm) + mm = ERR_PTR(-ESRCH); + if (IS_ERR(mm)) { + result = ERR_CAST(mm); goto out_put_task; + } result = ERR_PTR(-EINTR); if (mmap_read_lock_killable(mm)) @@ -2411,23 +2417,24 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx) if (!task) goto out; - ret = -EACCES; - if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) - goto out_put_task; - ret = 0; if (!dir_emit_dots(file, ctx)) goto out_put_task; - mm = get_task_mm(task); + mm = mm_access(task, PTRACE_MODE_READ_FSCREDS); if (!mm) + mm = ERR_PTR(-ESRCH); + if (IS_ERR(mm)) { + ret = PTR_ERR(mm); + /* if the task has no mm, the directory should just be empty */ + if (ret == -ESRCH) + ret = 0; goto out_put_task; + } ret = mmap_read_lock_killable(mm); - if (ret) { - mmput(mm); - goto out_put_task; - } + if (ret) + goto out_put_mm; nr_files = 0; @@ -2451,8 +2458,7 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx) if (!p) { ret = -ENOMEM; mmap_read_unlock(mm); - mmput(mm); - goto out_put_task; + goto out_put_mm; } p->start = vma->vm_start; @@ -2460,7 +2466,6 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx) p->mode = vma->vm_file->f_mode; } mmap_read_unlock(mm); - mmput(mm); for (i = 0; i < nr_files; i++) { char buf[4 * sizeof(long) + 2]; /* max: %lx-%lx\0 */ @@ -2477,6 +2482,8 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx) ctx->pos++; } +out_put_mm: + mmput(mm); out_put_task: put_task_struct(task); out: diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 8e159fc78c0a12..3a824f62dfccd6 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c @@ -55,6 +55,10 @@ static const char *proc_ns_get_link(struct dentry *dentry, if (!task) return ERR_PTR(-EACCES); + error = down_read_killable(&task->signal->exec_update_lock); + if (error) + goto out_put_task; + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) goto out; @@ -64,6 +68,8 @@ static const char *proc_ns_get_link(struct dentry *dentry, error = nd_jump_link(&ns_path); out: + up_read(&task->signal->exec_update_lock); +out_put_task: put_task_struct(task); return ERR_PTR(error); } @@ -80,11 +86,17 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl if (!task) return res; + res = down_read_killable(&task->signal->exec_update_lock); + if (res) + goto out_put_task; + if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { res = ns_get_name(name, sizeof(name), task, ns_ops); if (res >= 0) res = readlink_copy(buffer, buflen, name); } + up_read(&task->signal->exec_update_lock); +out_put_task: put_task_struct(task); return res; } -- 2.53.0