@@ -10,7 +10,6 @@ pub(crate) mod baseline;
10
10
pub ( crate ) mod config;
11
11
pub ( crate ) mod osconfig;
12
12
13
- use std:: io:: BufWriter ;
14
13
use std:: io:: Write ;
15
14
use std:: os:: fd:: AsFd ;
16
15
use std:: os:: unix:: process:: CommandExt ;
@@ -303,17 +302,17 @@ pub(crate) struct State {
303
302
}
304
303
305
304
impl State {
306
- // Wraps core lsm labeling functionality, conditionalizing based on source state
307
- pub ( crate ) fn lsm_label (
308
- & self ,
309
- target : & Utf8Path ,
310
- as_path : & Utf8Path ,
311
- recurse : bool ,
312
- ) -> Result < ( ) > {
313
- if !self . source . selinux {
314
- return Ok ( ( ) ) ;
305
+ #[ context( "Loading SELinux policy" ) ]
306
+ pub ( crate ) fn load_policy ( & self ) -> Result < Option < ostree:: SePolicy > > {
307
+ use std:: os:: fd:: AsRawFd ;
308
+ if !self . source . selinux || self . override_disable_selinux {
309
+ return Ok ( None ) ;
315
310
}
316
- crate :: lsm:: lsm_label ( target, as_path, recurse)
311
+ // We always use the physical container root to bootstrap policy
312
+ let rootfs = & Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
313
+ let r = ostree:: SePolicy :: new_at ( rootfs. as_raw_fd ( ) , gio:: Cancellable :: NONE ) ?;
314
+ tracing:: debug!( "Loaded SELinux policy: {}" , r. name( ) ) ;
315
+ Ok ( Some ( r) )
317
316
}
318
317
}
319
318
@@ -510,13 +509,17 @@ async fn initialize_ostree_root_from_self(
510
509
state : & State ,
511
510
root_setup : & RootSetup ,
512
511
) -> Result < InstallAleph > {
512
+ let sepolicy = state. load_policy ( ) ?;
513
+ let sepolicy = sepolicy. as_ref ( ) ;
514
+
515
+ // Load a fd for the mounted target physical root
513
516
let rootfs_dir = & root_setup. rootfs_fd ;
514
517
let rootfs = root_setup. rootfs . as_path ( ) ;
515
518
let cancellable = gio:: Cancellable :: NONE ;
516
519
517
520
// Ensure that the physical root is labeled.
518
521
// Another implementation: https://github.com/coreos/coreos-assembler/blob/3cd3307904593b3a131b81567b13a4d0b6fe7c90/src/create_disk.sh#L295
519
- state . lsm_label ( rootfs , "/" . into ( ) , false ) ?;
522
+ crate :: lsm :: ensure_dir_labeled ( rootfs_dir , "" , Some ( " /". into ( ) ) , 0o755 . into ( ) , sepolicy ) ?;
520
523
521
524
// TODO: make configurable?
522
525
let stateroot = STATEROOT_DEFAULT ;
@@ -529,7 +532,7 @@ async fn initialize_ostree_root_from_self(
529
532
// And also label /boot AKA xbootldr, if it exists
530
533
let bootdir = rootfs. join ( "boot" ) ;
531
534
if bootdir. try_exists ( ) ? {
532
- state . lsm_label ( & bootdir , "/ boot" . into ( ) , false ) ?;
535
+ crate :: lsm :: ensure_dir_labeled ( rootfs_dir , "boot" , None , 0o755 . into ( ) , sepolicy ) ?;
533
536
}
534
537
535
538
// Default to avoiding grub2-mkconfig etc., but we need to use zipl on s390x.
@@ -557,8 +560,17 @@ async fn initialize_ostree_root_from_self(
557
560
. cwd ( rootfs_dir) ?
558
561
. run ( ) ?;
559
562
560
- // Ensure everything in the ostree repo is labeled
561
- state. lsm_label ( & rootfs. join ( "ostree" ) , "/usr" . into ( ) , true ) ?;
563
+ // Bootstrap the initial labeling of the /ostree directory as usr_t
564
+ if let Some ( policy) = sepolicy {
565
+ let ostree_dir = rootfs_dir. open_dir ( "ostree" ) ?;
566
+ crate :: lsm:: ensure_dir_labeled (
567
+ & ostree_dir,
568
+ "." ,
569
+ Some ( "/usr" . into ( ) ) ,
570
+ 0o755 . into ( ) ,
571
+ Some ( policy) ,
572
+ ) ?;
573
+ }
562
574
563
575
let sysroot = ostree:: Sysroot :: new ( Some ( & gio:: File :: for_path ( rootfs) ) ) ;
564
576
sysroot. load ( cancellable) ?;
@@ -620,8 +632,6 @@ async fn initialize_ostree_root_from_self(
620
632
println ! ( "Installed: {target_image}" ) ;
621
633
println ! ( " Digest: {digest}" ) ;
622
634
623
- // Write the entry for /boot to /etc/fstab. TODO: Encourage OSes to use the karg?
624
- // Or better bind this with the grub data.
625
635
sysroot. load ( cancellable) ?;
626
636
let deployment = sysroot
627
637
. deployments ( )
@@ -633,28 +643,35 @@ async fn initialize_ostree_root_from_self(
633
643
let root = rootfs_dir
634
644
. open_dir ( path. as_str ( ) )
635
645
. context ( "Opening deployment dir" ) ?;
636
- let root_path = & rootfs. join ( & path. as_str ( ) ) ;
637
- let mut f = {
638
- let mut opts = cap_std:: fs:: OpenOptions :: new ( ) ;
639
- root. open_with ( "etc/fstab" , opts. append ( true ) . write ( true ) . create ( true ) )
640
- . context ( "Opening etc/fstab" )
641
- . map ( BufWriter :: new) ?
642
- } ;
643
- if let Some ( boot) = root_setup. boot . as_ref ( ) {
644
- writeln ! ( f, "{}" , boot. to_fstab( ) ) ?;
646
+
647
+ // And do another recursive relabeling pass over the ostree-owned directories
648
+ // but avoid recursing into the deployment root (because that's a *distinct*
649
+ // logical root).
650
+ if let Some ( policy) = sepolicy {
651
+ let deployment_root_meta = root. dir_metadata ( ) ?;
652
+ let deployment_root_devino = ( deployment_root_meta. dev ( ) , deployment_root_meta. ino ( ) ) ;
653
+ for d in [ "ostree" , "boot" ] {
654
+ let mut pathbuf = Utf8PathBuf :: from ( d) ;
655
+ crate :: lsm:: ensure_dir_labeled_recurse (
656
+ rootfs_dir,
657
+ & mut pathbuf,
658
+ policy,
659
+ Some ( deployment_root_devino) ,
660
+ )
661
+ . with_context ( || format ! ( "Recursive SELinux relabeling of {d}" ) ) ?;
662
+ }
645
663
}
646
- f. flush ( ) ?;
647
664
648
- let fstab_path = root_path. join ( "etc/fstab" ) ;
649
- state. lsm_label ( & fstab_path, "/etc/fstab" . into ( ) , false ) ?;
665
+ // Write the entry for /boot to /etc/fstab. TODO: Encourage OSes to use the karg?
666
+ // Or better bind this with the grub data.
667
+ if let Some ( boot) = root_setup. boot . as_ref ( ) {
668
+ crate :: lsm:: atomic_replace_labeled ( & root, "etc/fstab" , 0o644 . into ( ) , sepolicy, |w| {
669
+ writeln ! ( w, "{}" , boot. to_fstab( ) ) . map_err ( Into :: into)
670
+ } ) ?;
671
+ }
650
672
651
673
if let Some ( contents) = state. root_ssh_authorized_keys . as_deref ( ) {
652
- osconfig:: inject_root_ssh_authorized_keys (
653
- & root,
654
- & root_path,
655
- |target, path, recurse| state. lsm_label ( target, path, recurse) ,
656
- contents,
657
- ) ?;
674
+ osconfig:: inject_root_ssh_authorized_keys ( & root, sepolicy, contents) ?;
658
675
}
659
676
660
677
let uname = rustix:: system:: uname ( ) ;
0 commit comments