From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E86EA32FA37 for ; Tue, 17 Feb 2026 11:51:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771329084; cv=none; b=fkF8sz1l6xhdwUwNo2PNAHa242jJ1kFACKYYBK0X3xsjDnu0QxFCcivYYN16T3qnv+49zHY8MyDzEr8gOcWaM2u/ax2wZ/RaJ2LSzKZJWkYg6raS002hMzQDLjOVjPW52JWyRpzqHyDqgEp9Mx64vVoFV7GwuH05C/V4Eiym8zI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771329084; c=relaxed/simple; bh=FK28VlCz/kieZEbnDDHfYWnmbeWGC9EEPtCcoJFnJHE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=uzDjeCxN3gQ2u+inNOc8a2OMwfxzTuhpT5ZZzdabiqlhJguTy7niUgeiEb9C71LnFv/5balGkY/JqWGr9NZlqKcL6PnC2bW1m8DZINfsgnD7aak3JGNOWs5n2SDstC1RITEFzW+MVekx6etjlK7/IQbj4gcfSkfKj0J6ct0QlCM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qUtn4YMO; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qUtn4YMO" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4837b9913c9so22916465e9.0 for ; Tue, 17 Feb 2026 03:51:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1771329081; x=1771933881; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=BJZSAw1OS3HkHNvztNaVejaKs19d/dpxzj4ZsznN3tA=; b=qUtn4YMOISbp75XPCiuKfo/vZo0loujYVJ+2thVs0aTmOzLu/FUY4aRldLABqX/Gt+ x74EFLKhDD42A4Gj++XgMUnBpYAeVZcDT8WDDupM8KDVerufRqRPX8rZ1U/meHEB5H4W wJhwlzCVvl5P+NNd+eDESm/k7VTYIUMkZ/TBCP179+hIJ8Z1vAKJQsYCCY87QRbtTq03 WQ/bJFKvG74+ekYkzhkm7lCQvbWoe55f8uT+0CJykSKF3F64Qk2nzUUDCgSu4jdIVAgR lKHSBYTC0IedCaNBw4euxKrLmtGr2Xh7AEhi6PlNh5hYMTTb6NT8zd+rQE432u9GTuCm 6DMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771329081; x=1771933881; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=BJZSAw1OS3HkHNvztNaVejaKs19d/dpxzj4ZsznN3tA=; b=D3p9esly2RDmOyUeTn2sXFIdZwwJXTb6H3hIRdSyHrF9HrWt40ClBdqVn4rFk4h/9R MEIdcZe7NLuvkRJK9f5iEIupVCjX6ngCha4ZzsNM8NEEXZtwCWqxUjvgaaefFMWOJe/o FrTvnfFRl/+NHbIUwaMDOb6K9ub7fr4IWiDi7g/mTOWrZXa1B4Tvm1Nq0BtNXFPsKZ9c ccAuhI5rJoMzSsTMAhjjP82PQfVjYhdL8uBjncjoWs4UQ656MgGpgYYQsZjLDAzZ5DrC svJojfjIi6vx7KXL+98OoLU/87smSk0adhAyNtXrz0QPhEJn7JRZyInETtO6Wdo0hMwK g9/w== X-Forwarded-Encrypted: i=1; AJvYcCUMSHqQMlFLo5pJYMoi7wqtaf/mAxcV418jTig0OoRMg8BRL0NkxEarHYRkO/cn6UdnPvPVWsezMdfa+r0=@vger.kernel.org X-Gm-Message-State: AOJu0YzpXNCVDFvp81AspP4v4RBJMS3WVitMDGgmA7+rhk6TYGy2HW8L m4eQ7E+7h+/k8+UguXV9QaegjqVrQ9V88xRmsDskygoaj8ITiXB9AiYu+/KUi1lLWFRb77I1ZWA +w/JRvkf6Dsfs2/Bv9g== X-Received: from wmte24.prod.google.com ([2002:a05:600c:8b38:b0:480:6c54:bb0a]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:4688:b0:483:703e:4ad5 with SMTP id 5b1f17b1804b1-48373a37af9mr213342565e9.22.1771329080922; Tue, 17 Feb 2026 03:51:20 -0800 (PST) Date: Tue, 17 Feb 2026 11:51:20 +0000 In-Reply-To: <20260217110911.GY1395266@noisy.programming.kicks-ass.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <2026021326-stark-coastline-c5bc@gregkh> <20260217091348.GT1395266@noisy.programming.kicks-ass.net> <20260217094515.GV1395266@noisy.programming.kicks-ass.net> <20260217102557.GX1395266@noisy.programming.kicks-ass.net> <20260217110911.GY1395266@noisy.programming.kicks-ass.net> Message-ID: Subject: Re: [PATCH v2] rust: page: add byte-wise atomic memory copy methods From: Alice Ryhl To: Peter Zijlstra Cc: Boqun Feng , Greg KH , Andreas Hindborg , Lorenzo Stoakes , "Liam R. Howlett" , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?B?QmrDtnJu?= Roy Baron" , Benno Lossin , Trevor Gross , Danilo Krummrich , Will Deacon , Mark Rutland , linux-mm@kvack.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" On Tue, Feb 17, 2026 at 12:09:11PM +0100, Peter Zijlstra wrote: > On Tue, Feb 17, 2026 at 10:47:03AM +0000, Alice Ryhl wrote: > > > > // OK! > > > > unsigned long *a, b; > > > > b = READ_ONCE(a); > > > > if is_valid(b) { > > > > // do stuff > > > > } > > > > > > > > Now consider the following code: > > > > > > > > // Is this ok? > > > > unsigned long *a, b; > > > > memcpy(a, &b, sizeof(unsigned long)); > > > > if is_valid(b) { > > > > // do stuff > > > > } > > > > > > Why the hell would you want to write that? But sure. I think similar but > > > less weird example would be with structures, where value copies end up > > > being similar to memcpy. > > > > I mean sure, let's say that it was a structure or whatever instead of a > > long. The point is that the general pattern of memcpy, then checking the > > bytes you copied, then use the bytes you copied, is potentially > > susceptible to this exacty optimization. > > > > And in that case, you can still use volatile and compiler must not do > > > silly. > > > > What you mean by "volatile" here is the same as what this patch means > > when it says "per-byte atomic". If you agree that a "volatile memcpy" > > would be a good idea to use in this scenario, then it sounds like you > > agree with the patch except for its naming / terminology. > > struct foo { > int a, b; > }; > > struct foo *ptr, val; > > val = *(volatile struct foo *)ptr; > > why would we need a an explicit new memcpy for this? In my experience with dealing with `struct page` that is mapped into a vma, you need memcpy because the struct might be split across two different pages in the vma. The pages are adjacent in userspace's address space, but not necessarily adjacent from the kernel's POV. So you might end up with something that looks like this: struct foo val; void *ptr1 = kmap_local_page(p1); void *ptr2 = kmap_local_page(p2); memcpy(ptr1 + offset, val, PAGE_SIZE - offset); memcpy(ptr2, val + offset, sizeof(struct foo) - (PAGE_SIZE - offset)); kunmap_local(ptr2); kunmap_local(ptr1); if (is_valid(&val)) { // use val } This exact thing happens in Binder. It has to be a memcpy. > > > So I'm still not exactly sure why this is a problem all of a sudden? > > > > I mean, this is for `struct page` specifically. If you have the struct > > page for a page that might also be mapped into a userspace vma, then the > > way to perform a "copy_from_user" operation is to: > > > > 1. kmap_local_page() > > 2. memcpy() > > 3. kunmap_local() > > > > Correct me if I'm wrong, but my understanding is that on 64-bit systems, > > kmap/kunmap are usually complete no-ops since you have enough address > > space to simply map all pages into the kernel's address space. Not even > > a barrier - just a `static inline` with an empty body. > > That is all correct -- however that cannot be all you do. > > Any shared memory will involved memory barriers of a sort. You cannot > just memcpy() and think you're done. > > So yeah, on x86_64 those 1,2,3 are insufficient to inhibit the re-load, > but nobody should ever just do 1,2,3 and think job-done. There must > always be more. > > If it is a ring-buffer like thing, you get: > > * if (LOAD ->data_tail) { LOAD ->data_head > * (A) smp_rmb() (C) > * STORE $data LOAD $data > * smp_wmb() (B) smp_mb() (D) > * STORE ->data_head STORE ->data_tail > * } > > if it is a seqlock like thing you get that. > > If it is DMA, you need dma fences. > > And the moment you use any of that, the re-load goes out the window. I don't know how Andreas is using this, but the usage pattern I'm familiar with for `struct page` from my work on Binder is this one: 1. memcpy into the page 2. return from ioctl 3. userspace reads from vma or 1. userspace writes to vma 2. call ioctl 3. kernel reads from page which needs no barriers whatsoever. There is nothing to prevent this kind of optimization in this kind of code, so an evil userspace could trigger TOCTOU bugs in the kernel that are not present in the source code if the code was optimized like I described. Alice