LWN: Comments on "Tracking trust with Rust in the kernel" https://lwn.net/Articles/1034603/ This is a special feed containing comments posted to the individual LWN article titled "Tracking trust with Rust in the kernel". en-us Mon, 13 Oct 2025 01:16:41 +0000 Mon, 13 Oct 2025 01:16:41 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net Different kinds of validation? https://lwn.net/Articles/1039434/ https://lwn.net/Articles/1039434/ farnz <tt>Untrusted</tt> deals with the problem of "this is a valid HTML string that preserves soundness-relevant invariants and has the correct structure for HTML, but the <em>contents</em> of this string may not meet other invariants, like "does not contain the English word 'Administrator'". <p>So <tt>&lt;em&gt;Microsoft&amp;reg; notice:&lt;/em&gt;: please update your credentials in &lt;a href="https://phishing-site.example.com"&gt;our new identity system</tt> is a valid HTML string, preserving all the invariants you need preserved (balanced tags, valid tags, entity escaping etc). However, if it came from a template file, it's untrusted (in the sense of <tt>Untrusted&lt;&amp;HtmlStr&gt;</tt>), and needs validation before you treat it in the same way as HTML generated by your application. <p>Contrast <tt>impl TryFrom&lt;&amp;str&gt; for HtmlStr&lt;'_gt;</tt>, where you're saying that the input is a string, and it might, or might not, be valid HTML, but you need to do work to confirm that it is valid. Different problem - "this might not be valid HTML", as opposed to "this is definitely valid HTML, but the source might not be trustworthy". Thu, 25 Sep 2025 09:16:14 +0000 Different kinds of validation? https://lwn.net/Articles/1039205/ https://lwn.net/Articles/1039205/ taladar <div class="FormattedComment"> So you are talking about e.g. a &amp;str that you think is HTML but you have to parse it to validate that it has the correct structure and preserves invariants?<br> </div> Wed, 24 Sep 2025 07:46:30 +0000 Different kinds of validation? https://lwn.net/Articles/1039096/ https://lwn.net/Articles/1039096/ farnz That's a related problem, solved already (as you've shown) by the newtype pattern. <p><tt>Untrusted&lt;T&gt;</tt> is closer to the way <tt>&amp;str</tt> relates to <tt>&amp;[u8]</tt>; a string slice is a byte slice with the additional promise on top that it's valid UTF-8. In this analogy, <tt>Untrusted&lt;T&gt;</tt> is to <tt>T</tt> as <tt>&amp;[u8]</tt> is to <tt>&amp;str</tt>; you may "know" that this "should" be a safe string, but you have to actually validate it to use it (like you would with <a href="https://doc.rust-lang.org/std/primitive.str.html#method.from_utf8"><tt>str::from_utf8</tt></a> if you were dealing with byte slices). Tue, 23 Sep 2025 09:20:31 +0000 Different kinds of validation? https://lwn.net/Articles/1039092/ https://lwn.net/Articles/1039092/ taladar <div class="FormattedComment"> What I would really want is more along the lines of converting any &amp;str to SafeHTMLString, SafeSQLString,... and then have the templating syntax only allow the latter types. I also don't see why that conversion couldn't be done with TryFrom. No real need for generics here either since the various types of safe string have nothing to do with each other and neither does the question if they exist for any given input type.<br> </div> Tue, 23 Sep 2025 08:03:55 +0000 Different kinds of validation? https://lwn.net/Articles/1038992/ https://lwn.net/Articles/1038992/ farnz The challenge is that you want to model "convert <tt>Untrusted&lt;&amp;str&gt;</tt> to <tt>Untrusted&lt;HTML&gt;</tt> or <tt>Untrusted&lt;SQL&gt;</tt>", so that what you're passing round is always an <tt>Untrusted&lt;T&gt;</tt>, the conversions are zero-cost, the validations are cheap, and using a newtype like <tt>DisplayName</tt> that requires that something validates as SQL, HTML, shell, and whatever other places you want to use it in. <p>Solutions to this tend to either feel un-Rusty (since you have your own special <tt>UntrustedFrom</tt>, instead of using <tt>From</tt> like everyone else), or fall foul of the orphan rule, or make it hard to verify that <tt>Untrusted&lt;DisplayName&gt;::validate</tt> really does validate against all of the required validation types cheaply. Mon, 22 Sep 2025 09:34:45 +0000 Different kinds of validation? https://lwn.net/Articles/1038991/ https://lwn.net/Articles/1038991/ taladar <div class="FormattedComment"> I don't think Untrusted&lt;HTMLText&gt; and Untrusted&lt;SQLText&gt; are quite the right way to model this. Usually it is more that we have a non-specific untrusted value that we want to use in one or more contexts that require specific validation (e.g. the user's display name might need a different validation to be displayed in HTML than to be used in SQL and a different again to be used as a shell parameter).<br> </div> Mon, 22 Sep 2025 08:52:12 +0000 Different kinds of validation? https://lwn.net/Articles/1038922/ https://lwn.net/Articles/1038922/ mrugiero <p> The easy solution to that (both in Rust and many other strongly typed languages) is the newtype pattern. Rather than using `Untrusted&lt;String&gt;` for both your HTML and SQL sanitization, you would do something like: </p> <code> <pre> struct SQLText(pub String); struct HTMLText(pub String); impl Validate for Untrusted&lt;HTMLText&gt; { fn validate(self) -&gt; Result&lt;HTMLText&gt; { // HTML validation logic here } } impl Validate for Untrusted&lt;SQLText&gt; { fn validate(self) -&gt; Result&lt;SQLText&gt; { // HTML validation logic here } } </pre> </code> <br>And the functions receiving each trusted type would look like:</br> <code><pre> fn operate_on_html(HTMLText(text): HTMLText) -&gt; Something { // Stuff } fn operate_on_sql(SQLText(text): SQLText) -&gt; SomethingElse { // Other stuff } </pre></code> <p> I wonder if there's a way to ban implementing `Validate` for types that are considered too generic to force one into the newtype pattern when that should be a reasonable requirement (such as strings that may be literally anything). </p> Sat, 20 Sep 2025 19:24:39 +0000 Parse not validate! https://lwn.net/Articles/1037048/ https://lwn.net/Articles/1037048/ adobriyan <div class="FormattedComment"> <span class="QuotedText">&gt; + pub fn validate_ref&lt;'a, V: Validate&lt;&amp;'a Self&gt;&gt;(&amp;'a self) -&gt; Result&lt;V, V::Err&gt; {</span><br> <span class="QuotedText">&gt; + V::validate(&amp;self.0)</span><br> <span class="QuotedText">&gt; + }</span><br> <p> I suspect this will be as useful as Ada's integers for months from 1 to 12 mentioned above,<br> covering only the most simplest examples (which are the least interesting).<br> <p> Here is the simplest example where "validation" happens in wider context (of a block device).<br> <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=697ba0b6ec4ae04afb67d3911799b5e2043b4455">https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/...</a><br> <p> <p> </div> Sun, 07 Sep 2025 17:13:00 +0000 Trusted slice lengths https://lwn.net/Articles/1036951/ https://lwn.net/Articles/1036951/ tialaramex <div class="FormattedComment"> <span class="QuotedText">&gt; that I'm sure serve some useful purpose</span><br> <p> Two things are going on here for anybody fascinated but not wanting to go read the Rust internals<br> <p> 1. Runtime performance optimizations. Vec&lt;T&gt; is Rust's growable array type so it must have excellent performance. This is less crucial in Linux or some embedded code but in most normal userspace code you're using growable arrays a LOT and so the performance of this type is crucial to overall Rust performance.<br> <p> An example of this would be do_reserve_and_handle which is an inner cold function, so that the compiler will emit all the code to actually go do a bunch of work in a separate function, whereas the code around it is warm, and will be inlined aggressively but it will usually do something very cheap, such as checking n &lt;= capacity, only calling do_reserve_and_handle when that's not true.<br> <p> 2. Separation of concerns. RawVecInner literally doesn't know about T. It just makes growable arrays of bytes. The people working on RawVecInner do need to fret about Allocators (you might not use the default one) and efficiency but not about the type T. On the other hand RawVec&lt;T&gt; can pass the allocator problem to RawVecInner and cope only with the difference between bytes and T if T isn't a byte. Cap is a type dedicated solely to the problem of efficiently improving upon the obvious but not quite adequate "Capacity is just an integer" idea. People working on Cap don't need to think about any other part of the Vec&lt;T&gt; problem.<br> </div> Sat, 06 Sep 2025 11:22:38 +0000 Bounded integers https://lwn.net/Articles/1036949/ https://lwn.net/Articles/1036949/ tialaramex <div class="FormattedComment"> I disagree that bounded integers aren't useful, but then I would since I'm the person who really wants BalancedI8 and similar types (in that case, the signed 8-bit integer minus its most negative value, thus conveniently balanced, given a niche so that Option&lt;BalancedI8&gt; is also a single byte, and yet in practical terms just as useful as the existing i8 for almost any purpose)<br> <p> Firstly, bounded integers give us a niche and Rust knows how to use the niche, with built-in types such as Option&lt;T&gt; as well as any user types being allowed to consume a niche - so now our data structures are smaller, yet our software is more correct, that's a win-win deal.<br> <p> But also - this isn't a thing Rust is expected to do in the foreseeable future but it's certainly reasonable for Linux to be thinking about it in this context, bounded integers mean you can use mechanical proofs to ensure you can't write certain crucial types of bug. This is why WUFFS gets to have no bound misses despite not explicitly emitting bounds checks. It has verified that your code doesn't use any values which would cause a miss, ensuring that you meet these mathematical criteria is your problem and so you might need to write bounds checks, but often your algorithm can prove it doesn't miss anyway and WUFFS checks the proof.<br> </div> Sat, 06 Sep 2025 10:40:50 +0000 Validate & Copy? https://lwn.net/Articles/1036943/ https://lwn.net/Articles/1036943/ lossin I think we definitely can add functions to <code>UserSliceReader</code> that copy and validate in the same step. But we'll have to do that for every single way you can read untrusted data. Having a generic API that you can just plug untrusted values into should still exist for APIs that don't provide such a function themselves. There are also other use-cases for untrusted data, for example with <code>UserSliceReader</code> you might also just want to copy some bytes from one place in userspace to another and you wouldn't want to validate anything in between. So if we only had the copy &amp; validate function, you would have to write an empty validation function for <code>[u8]</code>. Sat, 06 Sep 2025 08:04:19 +0000 Different kinds of validation? https://lwn.net/Articles/1036885/ https://lwn.net/Articles/1036885/ daroc <div class="FormattedComment"> This kind of mechanism definitely still needs care. I think no language can mechanically ensure all validation is correct, for exactly the reason you point out. Lossin's goal with this patch set, as described in the cover letter at least, is to make mistakes harder and the good way to do it easier. So unlike some other Rust mechanisms, this isn't a bullet-proof guarantee, just a helpful API.<br> </div> Fri, 05 Sep 2025 14:07:24 +0000 Trusted slice lengths https://lwn.net/Articles/1036830/ https://lwn.net/Articles/1036830/ NYKevin <div class="FormattedComment"> I'm doubtful that Untrusted&lt;Vec&lt;T&gt;&gt; can plausibly mean anything other than Vec&lt;Untrusted&lt;T&gt;&gt;. Vec&lt;T&gt; is a struct consisting of the following fields (behind several layers of internal indirection, that I'm sure serve some useful purpose, but I can't be bothered to understand them now):<br> <p> * A pointer to some heap allocation, which can be dynamically resized.<br> * A size<br> * A capacity<br> <p> If the pointer points to userspace, then it is very questionable to call this thing a Vec, because you can't dynamically reallocate userspace memory - it's better to characterize that as a slice, or something[1] resembling a slice. But if the pointer points to kernelspace, then that means you called kmalloc or one of its equivalents, and you had darned well better know that it's still a valid allocation, as well as how big that allocation is. That implies the capacity is trusted completely, and the pointer is trusted to point to a live allocation of the correct size and alignment. Which just leaves size. Size tells us how many elements (T objects) in the allocation are initialized.<br> <p> Technically, uninitialized values are instant UB unless protected by MaybeUninit&lt;T&gt; (or behind a raw pointer). If size is wrong, Vec will produce uninitialized values when we index it, and that's UB. So we do need to validate size at some point in this whole procedure, or else we lose soundness. But by assumption, we are in kernelspace, so "initialized" just means that we called something resembling copy_from_user(), and it wrote some sort of data into that array slot. When we did that, we should have set size to the appropriate value for whatever copying we did (because we know what arguments we passed to copy_from_user()).<br> <p> In short, if you really have a Vec, and not an elaborately disguised UserSlice or the like, then you should already trust enough of it to make this transformation valid.<br> <p> [1]: <a href="https://rust.docs.kernel.org/next/kernel/uaccess/struct.UserSlice.html">https://rust.docs.kernel.org/next/kernel/uaccess/struct.U...</a><br> </div> Thu, 04 Sep 2025 22:56:58 +0000 Trusted slice lengths https://lwn.net/Articles/1036821/ https://lwn.net/Articles/1036821/ NYKevin <div class="FormattedComment"> <span class="QuotedText">&gt; If you want to imply that the length is not trusted, this would be sth. like Untrusted&lt;&amp;mut [u8]&gt;. This would be indeed very strange as not only the length would now be untrusted but also the pointer and the associated lifetime.</span><br> <p> The lifetime parameter is indeed trusted, because the borrow checker "lifts" it out of the type parameter and treats it roughly the same as a top-level lifetime parameter (i.e. if you have Untrusted&lt;&amp;'a T&gt;, then Rust automatically infers that the Untrusted object must not outlive 'a, because &amp;'a T must not outlive 'a).<br> <p> Technically, it's more complicated than that, and the precise behavior depends on the fields of Untrusted, see [1] for details. But in short, Rust will automatically infer relationships between Untrusted&lt;&amp;'a T&gt; and &amp;'a T as appropriate to prevent you from using a reference whose lifetime has ended, and at no point does it consider the possibility that &amp;'a T points to a T object that fails to live for at least 'a. Even if &amp;'a T only appears in PhantomData, a relationship is still inferred (Rust interprets this as "I logically own some &amp;'a T even though you can't see it listed in my fields").<br> <p> But it gets even worse. If you ever expose a real &amp;'a T to safe code (i.e. code that does not live inside the implementation of Untrusted or its owning crate), and it points into userspace-controlled memory, then you have probably violated soundness in multiple different ways:<br> <p> * If userspace modifies the T while the reference exists (e.g. from another thread), and T is not UnsafeCell&lt;U&gt;, then the behavior is undefined. If T is UnsafeCell, then you have to turn it into a raw pointer (*mut U) via UnsafeCell::get() to do anything anyway. We can't have e.g. T = Mutex&lt;U&gt;, because then the whole Mutex object lives in userspace, and userspace is not beholden to Rust's safety rules (so it could modify the inner value without taking the lock, or even stomp on the futex and break everything).<br> * Safe Rust assumes that you can dereference &amp;'a T at any time during 'a, and that it will always succeed and produce a T instance. In particular, the dereference operation is not allowed to fail with EFAULT or the like, so that would have to panic (obviously an unacceptable response to "userspace gave me a bad pointer").<br> * The T instance must be initialized unless T is MaybeUninit&lt;U&gt; (or some equivalent, since unlike UnsafeCell, MaybeUninit is not magic and can be implemented by hand). I have no idea how that rule even applies when you're pointing into shared memory, but I think it doesn't have a good answer because...<br> * Safe references are never volatile, so it's pretty much always incorrect to produce or dereference a safe reference pointing into shared memory. This is the case even if you fully serialize all reads and writes with some external locking, because LLVM (or GCC etc.) is permitted to optimize under the assumption that nobody else is reaching into your memory and modifying it behind your back (if the pointer escapes, then the compiler probably has to pessimistically assume that foreign code might fiddle with it, but that does not mean it is valid to do this in general). The "correct" way to do it is with functions like read_volatile[2], but those all take raw pointers, not safe references.<br> <p> On the other side of things, once you have all of the necessary guardrails around a userspace pointer, there is not much point in giving it a lifetime parameter. You're already (by assumption) calling fallible functions like copy_from_user() or get_user() (or their Rust equivalents) instead of directly dereferencing an address. You already have runtime error checking, and cannot violate soundness by holding onto the pointer for too long. Static borrow checking would provide no benefit, and might as well be disabled for ergonomic reasons.<br> <p> This is one of (probably) several reasons why UserPtr&lt;T&gt; has to exist and can't be spelled as Untrusted&lt;&amp;'a T&gt; or any similar signature (note the lack of a lifetime).<br> <p> [1]: <a href="https://doc.rust-lang.org/reference/subtyping.html#variance">https://doc.rust-lang.org/reference/subtyping.html#variance</a><br> [2]: <a href="https://doc.rust-lang.org/std/ptr/fn.read_volatile.html">https://doc.rust-lang.org/std/ptr/fn.read_volatile.html</a><br> </div> Thu, 04 Sep 2025 20:14:09 +0000 Different kinds of validation? https://lwn.net/Articles/1036824/ https://lwn.net/Articles/1036824/ Cyberax <div class="FormattedComment"> Bounded numeric types are not really that useful. They were often historically used in place of algebraic types, like the names of months or weekdays.<br> <p> If you want to start using numeric types for things like packet length, you quickly get bogged down with casts when arithmetic results in possible out-of-bounds. In the end, it's just easier to use safe arrays with safe indexing.<br> </div> Thu, 04 Sep 2025 19:48:21 +0000 Different kinds of validation? https://lwn.net/Articles/1036810/ https://lwn.net/Articles/1036810/ epa <div class="FormattedComment"> My experience with defending against injection is that usually you can take an approximate, but safe approach. If some field can genuinely be arbitrary text then you must take care to escape it appropriately for each use, but if not, you can define a safe character set like [A-Za-z0-9_] and restrict it to that. Perhaps the $ character does not cause any real injection problems when generating SQL, or HTML for that matter -- but so what, forbid it anyway. A username or the name of a report or a date and time will not contain that character.<br> <p> Getting back to the kernel and Rust, I would love it if more languages adopted bounded integers as provided by Ada. You can declare your month number variable as range 1..12. I'm not an Ada programmer and I am sure those more experienced with it will point out practical shortcomings in the way Ada does it. But I'm sure it could be nicer in Rust. (You can even do it in C++ templates.) There is a bounded_integer crate, I see.<br> </div> Thu, 04 Sep 2025 17:51:21 +0000 Trusted slice lengths https://lwn.net/Articles/1036809/ https://lwn.net/Articles/1036809/ excors <div class="FormattedComment"> Ah, thanks, that makes it a bit clearer. I think the specific detail I didn't realise is that when a struct's last field is a DST, that struct becomes a DST, and so a reference to the struct will contain the size of the struct's last field. Untrusted&lt;[T]&gt; is a struct with a single field of type [T], so that rule applies here. (I had been wrongly assuming the length had to be stored with the slice itself somehow, inside the struct, but the DST rules bring it outside.)<br> <p> On the other hand Untrusted&lt;Vec&lt;T&gt;&gt; derefs to Vec&lt;Untrusted&lt;T&gt;&gt;, and in that case I don't think there's any DST cleverness happening - it's simply moving the Vec's length field from inside to outside the Untrusted, which looks like a change in the trustedness of the length field, without any validation. I don't think this is a big problem, it just seems like an unfortunate hole in the trust boundary.<br> </div> Thu, 04 Sep 2025 17:46:42 +0000 Rust could prohibit reuse of a value https://lwn.net/Articles/1036805/ https://lwn.net/Articles/1036805/ iabervon <div class="FormattedComment"> Oh, yeah, I guess it's not actually necessary to ensure that code doesn't validate a different copy if you ensure that it does validate the copy it uses. Reviewers would take a dim view towards doing inadequate validation of the real one based on having done something (on a different copy) elsewhere.<br> </div> Thu, 04 Sep 2025 17:12:56 +0000 Rust could prohibit reuse of a value https://lwn.net/Articles/1036797/ https://lwn.net/Articles/1036797/ farnz It strikes me, reading <a href="https://rust.docs.kernel.org/kernel/uaccess/struct.UserSlice.html"><tt>UserSlice</tt>'s documentation</a> that the fix isn't so much making <tt>UserPtr</tt> not implement <tt>Copy</tt> (since <tt>UserPtr</tt> is equivalent to a raw pointer), but making <tt>UserSlice</tt>'s, <tt>UserSliceReader</tt>'s and <tt>UserSliceWriter</tt>'s methods always handle <tt>Untrusted&lt;T&gt;</tt>, and not <tt>T</tt> directly. <p>That would prevent the TOCTOU bug, since <tt>UserSliceReader::read_all</tt> would work in terms of <tt>Untrusted&lt;KVec&lt;u8&gt;&gt;</tt> instead of <tt>KVec&lt;u8&gt;</tt>, and thus to return <tt>KVec&lt;u8&gt;</tt> as per the method signature in the TOCTOU bug example, you'd have to call <tt>validate</tt> and get back a validated buffer. Thu, 04 Sep 2025 15:57:43 +0000 Trusted slice lengths https://lwn.net/Articles/1036784/ https://lwn.net/Articles/1036784/ matthias <div class="FormattedComment"> <span class="QuotedText">&gt; &gt; converting an &amp;mut Untrusted&lt;[u8]&gt; (a mutable reference to an untrusted slice of bytes) into an &amp;mut [Untrusted&lt;u8&gt;] (a mutable reference to a slice of individually untrusted bytes) can be done automatically</span><br> <span class="QuotedText">&gt; My initial thought was: doesn't the first type imply that the length of the slice is untrusted, while the second implies it is trusted? That sounds like a dangerous conversion to do automatically. But from reading the patch set, Untrusted&lt;[T]&gt; is documented as having a trusted length ("as it would otherwise violate normal Rust rules") and only the elements are untrusted, so the conversion is fine.</span><br> <p> Actually, the length of a slice is stored in the reference and not stored as part of the slice. &amp;mut Untrusted&lt;[u8]&gt; is a wide pointer that is a pair (ptr,len) that says at position ptr, there is data of type Untrusted&lt;[u8]&gt; that has size len. The len is always part of the reference, not part of the type T inside Untrusted&lt;T&gt;. <br> <p> This is how all dynamically sized types work in rust. The length is always stored in the reference which therefore needs twice as much space as ordinary references. The difference between &amp;mut Untrusted&lt;[u8]&gt; and &amp;mut [&lt;Untrusted&lt;u8&gt;] is really just the difference between a slice of size len that is untrusted and len many bytes that are individually untrusted. <br> <p> If you want to imply that the length is not trusted, this would be sth. like Untrusted&lt;&amp;mut [u8]&gt;. This would be indeed very strange as not only the length would now be untrusted but also the pointer and the associated lifetime.<br> </div> Thu, 04 Sep 2025 15:09:02 +0000 Trusted slice lengths https://lwn.net/Articles/1036679/ https://lwn.net/Articles/1036679/ excors <div class="FormattedComment"> <span class="QuotedText">&gt; converting an &amp;mut Untrusted&lt;[u8]&gt; (a mutable reference to an untrusted slice of bytes) into an &amp;mut [Untrusted&lt;u8&gt;] (a mutable reference to a slice of individually untrusted bytes) can be done automatically</span><br> <p> My initial thought was: doesn't the first type imply that the length of the slice is untrusted, while the second implies it is trusted? That sounds like a dangerous conversion to do automatically. But from reading the patch set, Untrusted&lt;[T]&gt; is documented as having a trusted length ("as it would otherwise violate normal Rust rules") and only the elements are untrusted, so the conversion is fine.<br> <p> I don't entirely see how that would work, though. I guess low-level code that's constructing an Untrusted&lt;[T]&gt; from e.g. core::slice::from_raw_parts(ptr, len) will be responsible for ensuring the length is safe (not extending outside the appropriate address space or backing buffer, etc). But 'safe' does not mean 'trusted' (that distinction is fundamental to this patch set), and the Untrusted&lt;[T]&gt; / [Untrusted&lt;T&gt;] will come into existence before we reach the higher-level code that knows how to validate the length properly, so I'm not sure how it can be claimed that the slice length is trusted.<br> <p> With APIs like copy_from_user (in C) and iov::IovIterSource::copy_from_iter_raw (in Rust), the caller has to provide a (trusted) maximum length to copy - but the actual length copied might be smaller than that, since it'll truncate the copy if e.g. it hits an unmapped page (I think), meaning the length returned is a user-controlled value and I believe it should be considered untrusted. Otherwise there's a risk of attackers causing out-of-bounds panics, when a driver makes invalid assumptions about the slice length because it's documented as being trusted and they don't realise it's still attacker-controlled and needs validating.<br> </div> Thu, 04 Sep 2025 12:28:48 +0000 Different kinds of validation? https://lwn.net/Articles/1036665/ https://lwn.net/Articles/1036665/ taladar <div class="FormattedComment"> My concern with this is that validation depends on the way you want to use the data, e.g. similar mechanisms in user space have often struggled with the different kinds of injection vulnerabilities where HTML injection is not the same as SQL injection is not the same as shell injection,... where validation needs to test for the absence of different kinds of problems in the input.<br> <p> I would assume similar concerns could be present in the kernel where e.g. an integer needs to be validated differently if it is used as, say, a month number in a date, than if it was used as a plausible size for a TCP packet.<br> </div> Thu, 04 Sep 2025 09:53:26 +0000 Validate & Copy? https://lwn.net/Articles/1036660/ https://lwn.net/Articles/1036660/ Wol <div class="FormattedComment"> My reaction on reading bits of this, was should you combine the validate and copy functions? So a user-space untrusted S could be copied into a validated kernel space T. This would then make clear that TOCTOU bugs are (absent other bugs) impossible, and also - by creating a slightly higher abstraction - make it easier for users of the API.<br> <p> Cheers,<br> Wol<br> </div> Thu, 04 Sep 2025 06:57:38 +0000 Rust could prohibit reuse of a value https://lwn.net/Articles/1036644/ https://lwn.net/Articles/1036644/ iabervon <div class="FormattedComment"> The UserPtr abstraction does prevent you from validating data you haven't copied (it's an integer rather than a pointer, so you can't dereference it), but it doesn't prevent you from effectively doing copy_from_user() twice. (The documentation of UserPtr even provides an example of how you could implement a TOCTOU bug, presumably as a cautionary tale.) It's like a more intense version of "__user", but addresses the same issue.<br> <p> I think it might be wise for UserPtr to lack the Copy trait, however, which (I think) would mean that the example bug wouldn't compile without using a clone() method call that shows where the data you check diverges from the data you use, while not affecting any code that only sets up the user/kernel data transfer once.<br> </div> Wed, 03 Sep 2025 22:23:43 +0000 Finally https://lwn.net/Articles/1036636/ https://lwn.net/Articles/1036636/ Sesse <div class="FormattedComment"> This is a Good Thing, and I am happy that Rust's type system is strong enough to implement it (or so it seems). I've been using this in Perl since forever, and while it's certainly not a panacea in all situations (e.g., does stuff from your database count as tainted or not?), it's a great way of avoiding XSS-by-just-forgetting-to-validate-stuff and similar.<br> </div> Wed, 03 Sep 2025 19:53:06 +0000