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