1
- use std :: fs :: File ;
1
+ # [ cfg ( feature = "install" ) ]
2
2
use std:: io:: Write ;
3
3
use std:: os:: unix:: process:: CommandExt ;
4
4
use std:: path:: Path ;
@@ -31,6 +31,9 @@ pub(crate) fn selinux_enabled() -> Result<bool> {
31
31
#[ context( "Ensuring selinux install_t type" ) ]
32
32
pub ( crate ) fn selinux_ensure_install ( ) -> Result < ( ) > {
33
33
let guardenv = "_bootc_selinuxfs_mounted" ;
34
+ let current = std:: fs:: read_to_string ( "/proc/self/attr/current" )
35
+ . context ( "Reading /proc/self/attr/current" ) ?;
36
+ tracing:: debug!( "Current security context is {current}" ) ;
34
37
if let Some ( p) = std:: env:: var_os ( guardenv) {
35
38
let p = Path :: new ( & p) ;
36
39
if p. exists ( ) {
@@ -59,10 +62,42 @@ pub(crate) fn selinux_ensure_install() -> Result<()> {
59
62
let mut cmd = Command :: new ( & tmpf) ;
60
63
cmd. env ( guardenv, tmpf) ;
61
64
cmd. args ( std:: env:: args_os ( ) . skip ( 1 ) ) ;
62
- tracing:: debug!( "Re-executing" ) ;
65
+ tracing:: debug!( "Re-executing {cmd:?} " ) ;
63
66
Err ( anyhow:: Error :: msg ( cmd. exec ( ) ) . context ( "execve" ) )
64
67
}
65
68
69
+ /// A type which will reset SELinux back to enforcing mode when dropped.
70
+ /// This is a workaround for the deep difficulties in trying to reliably
71
+ /// gain the `mac_admin` permission (install_t).
72
+ #[ cfg( feature = "install" ) ]
73
+ #[ must_use]
74
+ pub ( crate ) struct SetEnforceGuard ;
75
+
76
+ #[ cfg( feature = "install" ) ]
77
+ impl Drop for SetEnforceGuard {
78
+ fn drop ( & mut self ) {
79
+ let _ = selinux_set_permissive ( false ) ;
80
+ }
81
+ }
82
+
83
+ /// Try to enter the install_t domain, but if we can't do that, then
84
+ /// just setenforce 0.
85
+ #[ context( "Ensuring selinux install_t type" ) ]
86
+ #[ cfg( feature = "install" ) ]
87
+ pub ( crate ) fn selinux_ensure_install_or_setenforce ( ) -> Result < Option < SetEnforceGuard > > {
88
+ selinux_ensure_install ( ) ?;
89
+ let current = std:: fs:: read_to_string ( "/proc/self/attr/current" )
90
+ . context ( "Reading /proc/self/attr/current" ) ?;
91
+ let g = if !current. contains ( "install_t" ) {
92
+ tracing:: warn!( "Failed to enter install_t; temporarily setting permissive mode" ) ;
93
+ selinux_set_permissive ( true ) ?;
94
+ Some ( SetEnforceGuard )
95
+ } else {
96
+ None
97
+ } ;
98
+ Ok ( g)
99
+ }
100
+
66
101
/// Ensure that /sys/fs/selinux is mounted, and ensure we're running
67
102
/// as install_t.
68
103
#[ context( "Ensuring selinux mount" ) ]
@@ -84,13 +119,13 @@ pub(crate) fn container_setup_selinux() -> Result<()> {
84
119
#[ context( "Setting SELinux permissive mode" ) ]
85
120
#[ allow( dead_code) ]
86
121
#[ cfg( feature = "install" ) ]
87
- pub ( crate ) fn selinux_set_permissive ( ) -> Result < ( ) > {
122
+ pub ( crate ) fn selinux_set_permissive ( permissive : bool ) -> Result < ( ) > {
88
123
let enforce_path = & Utf8Path :: new ( SELINUXFS ) . join ( "enforce" ) ;
89
124
if !enforce_path. exists ( ) {
90
125
return Ok ( ( ) ) ;
91
126
}
92
- let mut f = File :: open ( enforce_path) ?;
93
- f. write_all ( b"0" ) ?;
127
+ let mut f = std :: fs :: File :: options ( ) . write ( true ) . open ( enforce_path) ?;
128
+ f. write_all ( if permissive { b"0" } else { b"1" } ) ?;
94
129
tracing:: debug!( "Set SELinux permissive mode" ) ;
95
130
Ok ( ( ) )
96
131
}
@@ -111,6 +146,7 @@ fn selinux_label_for_path(target: &str) -> Result<String> {
111
146
#[ context( "Labeling {as_path}" ) ]
112
147
pub ( crate ) fn lsm_label ( target : & Utf8Path , as_path : & Utf8Path , recurse : bool ) -> Result < ( ) > {
113
148
let label = selinux_label_for_path ( as_path. as_str ( ) ) ?;
149
+ tracing:: debug!( "Label for {target} is {label}" ) ;
114
150
let st = Command :: new ( "chcon" )
115
151
. arg ( "-h" )
116
152
. args ( recurse. then_some ( "-R" ) )
0 commit comments