Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'rust-fixes-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux

Pull Rust fixes from Miguel Ojeda:
"Toolchain and infrastructure:

- Add 'bindgen' target to make UML 32-bit builds work with GCC

- Disable two Clippy warnings ('collapsible_{if,match}')

'pin-init' crate:

- Fix unsoundness issue that created &'static references"

* tag 'rust-fixes-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux:
rust: allow `clippy::collapsible_if` globally
rust: allow `clippy::collapsible_match` globally
rust: pin-init: fix incorrect accessor reference lifetime
rust: pin-init: internal: move alignment check to `make_field_check`
rust: arch: um: Fix building 32-bit UML with GCC

+107 -110
+2
Makefile
··· 486 486 -Wclippy::as_ptr_cast_mut \ 487 487 -Wclippy::as_underscore \ 488 488 -Wclippy::cast_lossless \ 489 + -Aclippy::collapsible_if \ 490 + -Aclippy::collapsible_match \ 489 491 -Wclippy::ignored_unit_patterns \ 490 492 -Aclippy::incompatible_msrv \ 491 493 -Wclippy::mut_mut \
-1
drivers/android/binder/range_alloc/array.rs
··· 204 204 // caller will mark them as unused, which means that they can be freed if the system comes 205 205 // under memory pressure. 206 206 let mut freed_range = FreedRange::interior_pages(offset, size); 207 - #[expect(clippy::collapsible_if)] // reads better like this 208 207 if offset % PAGE_SIZE != 0 { 209 208 if i == 0 || self.ranges[i - 1].endpoint() <= (offset & PAGE_MASK) { 210 209 freed_range.start_page_idx -= 1;
+2
rust/Makefile
··· 403 403 BINDGEN_TARGET_arm64 := aarch64-linux-gnu 404 404 BINDGEN_TARGET_arm := arm-linux-gnueabi 405 405 BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf 406 + # This is only for i386 UM builds, which need the 32-bit target not -m32 407 + BINDGEN_TARGET_i386 := i386-linux-gnu 406 408 BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH)) 407 409 BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH)) 408 410
+84 -100
rust/pin-init/internal/src/init.rs
··· 249 249 }); 250 250 // Again span for better diagnostics 251 251 let write = quote_spanned!(ident.span()=> ::core::ptr::write); 252 - // NOTE: the field accessor ensures that the initialized field is properly aligned. 253 - // Unaligned fields will cause the compiler to emit E0793. We do not support 254 - // unaligned fields since `Init::__init` requires an aligned pointer; the call to 255 - // `ptr::write` below has the same requirement. 256 - let accessor = if pinned { 257 - let project_ident = format_ident!("__project_{ident}"); 258 - quote! { 259 - // SAFETY: TODO 260 - unsafe { #data.#project_ident(&mut (*#slot).#ident) } 261 - } 262 - } else { 263 - quote! { 264 - // SAFETY: TODO 265 - unsafe { &mut (*#slot).#ident } 266 - } 267 - }; 268 252 quote! { 269 253 #(#attrs)* 270 254 { ··· 256 272 // SAFETY: TODO 257 273 unsafe { #write(&raw mut (*#slot).#ident, #value_ident) }; 258 274 } 259 - #(#cfgs)* 260 - #[allow(unused_variables)] 261 - let #ident = #accessor; 262 275 } 263 276 } 264 277 InitializerKind::Init { ident, value, .. } => { 265 278 // Again span for better diagnostics 266 279 let init = format_ident!("init", span = value.span()); 267 - // NOTE: the field accessor ensures that the initialized field is properly aligned. 268 - // Unaligned fields will cause the compiler to emit E0793. We do not support 269 - // unaligned fields since `Init::__init` requires an aligned pointer; the call to 270 - // `ptr::write` below has the same requirement. 271 - let (value_init, accessor) = if pinned { 272 - let project_ident = format_ident!("__project_{ident}"); 273 - ( 274 - quote! { 275 - // SAFETY: 276 - // - `slot` is valid, because we are inside of an initializer closure, we 277 - // return when an error/panic occurs. 278 - // - We also use `#data` to require the correct trait (`Init` or `PinInit`) 279 - // for `#ident`. 280 - unsafe { #data.#ident(&raw mut (*#slot).#ident, #init)? }; 281 - }, 282 - quote! { 283 - // SAFETY: TODO 284 - unsafe { #data.#project_ident(&mut (*#slot).#ident) } 285 - }, 286 - ) 280 + let value_init = if pinned { 281 + quote! { 282 + // SAFETY: 283 + // - `slot` is valid, because we are inside of an initializer closure, we 284 + // return when an error/panic occurs. 285 + // - We also use `#data` to require the correct trait (`Init` or `PinInit`) 286 + // for `#ident`. 287 + unsafe { #data.#ident(&raw mut (*#slot).#ident, #init)? }; 288 + } 287 289 } else { 288 - ( 289 - quote! { 290 - // SAFETY: `slot` is valid, because we are inside of an initializer 291 - // closure, we return when an error/panic occurs. 292 - unsafe { 293 - ::pin_init::Init::__init( 294 - #init, 295 - &raw mut (*#slot).#ident, 296 - )? 297 - }; 298 - }, 299 - quote! { 300 - // SAFETY: TODO 301 - unsafe { &mut (*#slot).#ident } 302 - }, 303 - ) 290 + quote! { 291 + // SAFETY: `slot` is valid, because we are inside of an initializer 292 + // closure, we return when an error/panic occurs. 293 + unsafe { 294 + ::pin_init::Init::__init( 295 + #init, 296 + &raw mut (*#slot).#ident, 297 + )? 298 + }; 299 + } 304 300 }; 305 301 quote! { 306 302 #(#attrs)* ··· 288 324 let #init = #value; 289 325 #value_init 290 326 } 291 - #(#cfgs)* 292 - #[allow(unused_variables)] 293 - let #ident = #accessor; 294 327 } 295 328 } 296 329 InitializerKind::Code { block: value, .. } => quote! { ··· 300 339 if let Some(ident) = kind.ident() { 301 340 // `mixed_site` ensures that the guard is not accessible to the user-controlled code. 302 341 let guard = format_ident!("__{ident}_guard", span = Span::mixed_site()); 342 + 343 + // NOTE: The reference is derived from the guard so that it only lives as long as the 344 + // guard does and cannot escape the scope. If it's created via `&mut (*#slot).#ident` 345 + // like the unaligned field guard, it will become effectively `'static`. 346 + let accessor = if pinned { 347 + let project_ident = format_ident!("__project_{ident}"); 348 + quote! { 349 + // SAFETY: the initialization is pinned. 350 + unsafe { #data.#project_ident(#guard.let_binding()) } 351 + } 352 + } else { 353 + quote! { 354 + #guard.let_binding() 355 + } 356 + }; 357 + 303 358 res.extend(quote! { 304 359 #(#cfgs)* 305 - // Create the drop guard: 360 + // Create the drop guard. 306 361 // 307 - // We rely on macro hygiene to make it impossible for users to access this local 308 - // variable. 309 - // SAFETY: We forget the guard later when initialization has succeeded. 310 - let #guard = unsafe { 362 + // SAFETY: 363 + // - `&raw mut (*slot).#ident` is valid. 364 + // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned. 365 + // - `(*slot).#ident` has been initialized above. 366 + // - We only need the ownership to the pointee back when initialization has 367 + // succeeded, where we `forget` the guard. 368 + let mut #guard = unsafe { 311 369 ::pin_init::__internal::DropGuard::new( 312 370 &raw mut (*slot).#ident 313 371 ) 314 372 }; 373 + 374 + #(#cfgs)* 375 + #[allow(unused_variables)] 376 + let #ident = #accessor; 315 377 }); 316 378 guards.push(guard); 317 379 guard_attrs.push(cfgs); ··· 351 367 } 352 368 } 353 369 354 - /// Generate the check for ensuring that every field has been initialized. 370 + /// Generate the check for ensuring that every field has been initialized and aligned. 355 371 fn make_field_check( 356 372 fields: &Punctuated<InitializerField, Token![,]>, 357 373 init_kind: InitKind, 358 374 path: &Path, 359 375 ) -> TokenStream { 360 - let field_attrs = fields 376 + let field_attrs: Vec<_> = fields 361 377 .iter() 362 - .filter_map(|f| f.kind.ident().map(|_| &f.attrs)); 363 - let field_name = fields.iter().filter_map(|f| f.kind.ident()); 364 - match init_kind { 365 - InitKind::Normal => quote! { 366 - // We use unreachable code to ensure that all fields have been mentioned exactly once, 367 - // this struct initializer will still be type-checked and complain with a very natural 368 - // error message if a field is forgotten/mentioned more than once. 369 - #[allow(unreachable_code, clippy::diverging_sub_expression)] 370 - // SAFETY: this code is never executed. 371 - let _ = || unsafe { 372 - ::core::ptr::write(slot, #path { 373 - #( 374 - #(#field_attrs)* 375 - #field_name: ::core::panic!(), 376 - )* 377 - }) 378 - }; 379 - }, 380 - InitKind::Zeroing => quote! { 381 - // We use unreachable code to ensure that all fields have been mentioned at most once. 382 - // Since the user specified `..Zeroable::zeroed()` at the end, all missing fields will 383 - // be zeroed. This struct initializer will still be type-checked and complain with a 384 - // very natural error message if a field is mentioned more than once, or doesn't exist. 385 - #[allow(unreachable_code, clippy::diverging_sub_expression, unused_assignments)] 386 - // SAFETY: this code is never executed. 387 - let _ = || unsafe { 388 - ::core::ptr::write(slot, #path { 389 - #( 390 - #(#field_attrs)* 391 - #field_name: ::core::panic!(), 392 - )* 393 - ..::core::mem::zeroed() 394 - }) 395 - }; 396 - }, 378 + .filter_map(|f| f.kind.ident().map(|_| &f.attrs)) 379 + .collect(); 380 + let field_name: Vec<_> = fields.iter().filter_map(|f| f.kind.ident()).collect(); 381 + let zeroing_trailer = match init_kind { 382 + InitKind::Normal => None, 383 + InitKind::Zeroing => Some(quote! { 384 + ..::core::mem::zeroed() 385 + }), 386 + }; 387 + quote! { 388 + #[allow(unreachable_code, clippy::diverging_sub_expression)] 389 + // We use unreachable code to perform field checks. They're still checked by the compiler. 390 + // SAFETY: this code is never executed. 391 + let _ = || unsafe { 392 + // Create references to ensure that the initialized field is properly aligned. 393 + // Unaligned fields will cause the compiler to emit E0793. We do not support 394 + // unaligned fields since `Init::__init` requires an aligned pointer; the call to 395 + // `ptr::write` for value-initialization case has the same requirement. 396 + #( 397 + #(#field_attrs)* 398 + let _ = &(*slot).#field_name; 399 + )* 400 + 401 + // If the zeroing trailer is not present, this checks that all fields have been 402 + // mentioned exactly once. If the zeroing trailer is present, all missing fields will be 403 + // zeroed, so this checks that all fields have been mentioned at most once. The use of 404 + // struct initializer will still generate very natural error messages for any misuse. 405 + ::core::ptr::write(slot, #path { 406 + #( 407 + #(#field_attrs)* 408 + #field_name: ::core::panic!(), 409 + )* 410 + #zeroing_trailer 411 + }) 412 + }; 397 413 } 398 414 } 399 415
+19 -9
rust/pin-init/src/__internal.rs
··· 238 238 /// When a value of this type is dropped, it drops a `T`. 239 239 /// 240 240 /// Can be forgotten to prevent the drop. 241 + /// 242 + /// # Invariants 243 + /// 244 + /// - `ptr` is valid and properly aligned. 245 + /// - `*ptr` is initialized and owned by this guard. 241 246 pub struct DropGuard<T: ?Sized> { 242 247 ptr: *mut T, 243 248 } 244 249 245 250 impl<T: ?Sized> DropGuard<T> { 246 - /// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped. 251 + /// Creates a drop guard and transfer the ownership of the pointer content. 252 + /// 253 + /// The ownership is only relinguished if the guard is forgotten via [`core::mem::forget`]. 247 254 /// 248 255 /// # Safety 249 256 /// 250 - /// `ptr` must be a valid pointer. 251 - /// 252 - /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`: 253 - /// - has not been dropped, 254 - /// - is not accessible by any other means, 255 - /// - will not be dropped by any other means. 257 + /// - `ptr` is valid and properly aligned. 258 + /// - `*ptr` is initialized, and the ownership is transferred to this guard. 256 259 #[inline] 257 260 pub unsafe fn new(ptr: *mut T) -> Self { 261 + // INVARIANT: By safety requirement. 258 262 Self { ptr } 263 + } 264 + 265 + /// Create a let binding for accessor use. 266 + #[inline] 267 + pub fn let_binding(&mut self) -> &mut T { 268 + // SAFETY: Per type invariant. 269 + unsafe { &mut *self.ptr } 259 270 } 260 271 } 261 272 262 273 impl<T: ?Sized> Drop for DropGuard<T> { 263 274 #[inline] 264 275 fn drop(&mut self) { 265 - // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function 266 - // ensuring that this operation is safe. 276 + // SAFETY: `self.ptr` is valid, properly aligned and `*self.ptr` is owned by this guard. 267 277 unsafe { ptr::drop_in_place(self.ptr) } 268 278 } 269 279 }