From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (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 95A7B38FF0E for ; Wed, 7 Jan 2026 15:27:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=90.155.92.199 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767799652; cv=none; b=a7CKS33rYMuQItJpHanhA88XTQLpprlrniB2pf3N3/RqPe2gEPlxziNg2GNupkpqvrMnX6/sHreTgheLwkqUa0xZq2z66mUUnqQ7a2j8CKkBuaWl5HZ2uHKOqOKgGc7hEzR/ppSdQDoqUyUD9W/m3r0N9181LtqzEL7s8ed7+/E= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767799652; c=relaxed/simple; bh=xD+t8zM1LmUeNqE5L5KTLpEjMj+cv3+1UJYrkK3cl2E=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=KsELcRJRSSFki1/QkOEgMS4SFt8riPQPqjpl28rqYlbZ55whCsmhp72LqC5aTBhGIUw0AbbKmZ4xe+g3LorzHZdo/eBbRwA82JqKzMW3bdqdczEUsrKxxksq4ToJLTjYWwuSz6ASL2MUrkCY79KAShPJS1MeHe1iTR1lk6DnfW8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=none smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=PVxwMWEg; arc=none smtp.client-ip=90.155.92.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="PVxwMWEg" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=wB5co/21ObLGcNk4sK8eTDMrQd9SUZ98QJpoMflqPm4=; b=PVxwMWEg3hVKjQrd5ZBlHGNyfk svXjJ3OXLuXFGAPBeFsn3Fx5bUU74hL9maPyVSxYGu6AFwcKeiDZzuiER+hg2o1fbK/iL82KqGUqw O+ey0YbQfKIXYWuFuMLSMg9oE90+Q6YlxM/F6B7I3MqvBgwx21PicktUZlNlmQ5x6XMB78oAn2eog LK8v9RaGuPmaD/Gn5mZ5F1YICz3QXgFypGy29yT/1XphTWwFXt+os0PazSNPx+C5+q0V68xwm4hsm vMy3055ODF6McJUMv5UuFgJYz+SpUNtr9QleRTLH0wZ1EEszuGR+CM9JDZe/e11w1NWCi5q01qML9 EZ+BVuqQ==; Received: from 77-249-17-252.cable.dynamic.v4.ziggo.nl ([77.249.17.252] helo=noisy.programming.kicks-ass.net) by desiato.infradead.org with esmtpsa (Exim 4.98.2 #2 (Red Hat Linux)) id 1vdVRN-0000000BaAm-3lc1; Wed, 07 Jan 2026 15:27:18 +0000 Received: by noisy.programming.kicks-ass.net (Postfix, from userid 1000) id 7E34630057E; Wed, 07 Jan 2026 16:27:16 +0100 (CET) Date: Wed, 7 Jan 2026 16:27:16 +0100 From: Peter Zijlstra To: Oleg Nesterov Cc: Andrii Nakryiko , Borislav Petkov , Dave Hansen , David Hildenbrand , "H. Peter Anvin" , Ingo Molnar , Jiri Olsa , Masami Hiramatsu , Paulo Andrade , Thomas Gleixner , linux-kernel@vger.kernel.org, x86@kernel.org Subject: Re: [BUG] x86: 32-bit uprobes are broken Message-ID: <20260107152716.GG2393663@noisy.programming.kicks-ass.net> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: On Wed, Jan 07, 2026 at 03:32:53PM +0100, Oleg Nesterov wrote: > Paulo reported that uprobing the 32-bit tasks is broken. > > This script > > #!/usr/bin/bash > > echo 0 > /proc/sys/kernel/randomize_va_space > > echo 'void main(void) {}' > TEST.c > > # -fcf-protection to ensure that the 1st endbr32 insn can't be eulated > gcc -m32 -fcf-protection=branch TEST.c -o test > > bpftrace -e 'uprobe:./test:main {}' -c ./test > > "hangs", the probed ./test task enters the endless loop. > > This patch > > --- a/kernel/events/uprobes.c > +++ b/kernel/events/uprobes.c > @@ -1710,8 +1710,11 @@ static int xol_add_vma(struct mm_struct *mm, struct xol_area *area) > > if (!area->vaddr) { > /* Try to map as high as possible, this is only a hint. */ > + if (test_thread_flag(TIF_ADDR32)) > + current_thread_info()->status |= TS_COMPAT; > area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, > PAGE_SIZE, 0, 0); > + current_thread_info()->status &= ~TS_COMPAT; > if (IS_ERR_VALUE(area->vaddr)) { > ret = area->vaddr; > goto fail; Urgh. Also I'm a little bit confused; set_personality_ia32(), which is what sets TIF_ADDR32 (afaict) would also set TS_COMPAT, no? > or this one > > --- a/arch/x86/kernel/sys_x86_64.c > +++ b/arch/x86/kernel/sys_x86_64.c > @@ -205,6 +205,8 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0, > info.low_limit = PAGE_SIZE; > > info.high_limit = get_mmap_base(0); > + if (test_thread_flag(TIF_ADDR32)) > + info.high_limit = current->mm->mmap_compat_base; > if (!(filp && is_file_hugepages(filp))) { > info.start_gap = stack_guard_placement(vm_flags); > info.align_offset = pgoff << PAGE_SHIFT; This one would be broken if there is ever a case where get_unmapped_area() is called for mm != current->mm. Ah, but get_mmap_base() seems to already rely on that. What a mess :/ Why can't get_mmap_base() rely on TIF_ADDR32 rather than TS_COMPAT? What funny games are being played here? Mixed mode mm where some threads are 32bit and others are not? > "fixes" the problem. > > ----------------------------------------------------------------------------------------- > The problem is that with randomize_va_space == 0 get_unmapped_area(TASK_SIZE - PAGE_SIZE) > called by xol_add_vma() can't just return the "addr == TASK_SIZE - PAGE_SIZE" hint, this > addr is used by the stack vma. > > arch_get_unmapped_area/arch_get_unmapped_area_topdown() doesn't take TIF_ADDR32 into > account and in_32bit_syscall() is false, this leads to info.high_limit > TASK_SIZE. > get_area() happily returns the "high" address and then get_unmapped_area() returns > ENOMEM after the > > if (addr > TASK_SIZE - len) > return -ENOMEM; > > check; TASK_SIZE checks TIF_ADDR32. > > handle_swbp() doesn't report this failure (probably it should) and silently restarts > the probed insn. Endless loop. > > ----------------------------------------------------------------------------------------- > I am considering the patch which adds something like > > // x86 version will use the TS_COMPAT hack > unsigned long __weak arch_uprobe_area(void) > { > return get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0); > } > > but perhaps there is a better solution? perhaps it makes more sense to change > arch/x86/kernel/sys_x86_64.c? What is the point of ignoring TIF_ADDR32 if the > high adress will be nacked by the "if (addr > TASK_SIZE - len)" check anyway? To me it seems a bit weird that get_unmapped_area() is so disconnected from mm_struct.