@@ -33,16 +33,18 @@ fn get_current_security_context() -> Result<String> {
33
33
std:: fs:: read_to_string ( SELF_CURRENT ) . with_context ( || format ! ( "Reading {SELF_CURRENT}" ) )
34
34
}
35
35
36
- /// Determine if a security context is the "install_t" type which can
37
- /// write arbitrary labels.
38
- fn context_is_install_t ( context : & str ) -> bool {
39
- // TODO: we shouldn't actually hardcode this...it's just ugly though
40
- // to figure out whether we really can gain CAP_MAC_ADMIN.
41
- context. contains ( ":install_t:" )
36
+ #[ context( "Testing install_t" ) ]
37
+ fn test_install_t ( ) -> Result < bool > {
38
+ let tmpf = tempfile:: NamedTempFile :: new ( ) ?;
39
+ let st = Command :: new ( "chcon" )
40
+ . args ( [ "-t" , "invalid_bootcinstall_testlabel_t" ] )
41
+ . arg ( tmpf. path ( ) )
42
+ . status ( ) ?;
43
+ Ok ( st. success ( ) )
42
44
}
43
45
44
46
#[ context( "Ensuring selinux install_t type" ) ]
45
- pub ( crate ) fn selinux_ensure_install ( ) -> Result < ( ) > {
47
+ pub ( crate ) fn selinux_ensure_install ( ) -> Result < bool > {
46
48
let guardenv = "_bootc_selinuxfs_mounted" ;
47
49
let current = get_current_security_context ( ) ?;
48
50
tracing:: debug!( "Current security context is {current}" ) ;
@@ -54,9 +56,13 @@ pub(crate) fn selinux_ensure_install() -> Result<()> {
54
56
} else {
55
57
tracing:: debug!( "Assuming we now have a privileged (e.g. install_t) label" ) ;
56
58
}
57
- return Ok ( ( ) ) ;
59
+ return test_install_t ( ) ;
60
+ }
61
+ if test_install_t ( ) ? {
62
+ tracing:: debug!( "We have install_t" ) ;
63
+ return Ok ( true ) ;
58
64
}
59
- tracing:: debug!( "Copying self to temporary file for re-exec" ) ;
65
+ tracing:: debug!( "Lacking install_t capabilities; copying self to temporary file for re-exec" ) ;
60
66
// OK now, we always copy our binary to a tempfile, set its security context
61
67
// to match that of /usr/bin/ostree, and then re-exec. This is really a gross
62
68
// hack; we can't always rely on https://github.com/fedora-selinux/selinux-policy/pull/1500/commits/67eb283c46d35a722636d749e5b339615fe5e7f5
@@ -98,18 +104,17 @@ impl Drop for SetEnforceGuard {
98
104
#[ cfg( feature = "install" ) ]
99
105
pub ( crate ) fn selinux_ensure_install_or_setenforce ( ) -> Result < Option < SetEnforceGuard > > {
100
106
// If the process already has install_t, exit early
101
- let current = get_current_security_context ( ) ? ;
102
- if context_is_install_t ( & current ) {
107
+ // Note that this may re-exec the entire process
108
+ if selinux_ensure_install ( ) ? {
103
109
return Ok ( None ) ;
104
110
}
105
- // Note that this will re-exec the entire process
106
- selinux_ensure_install ( ) ?;
107
- let g = if !context_is_install_t ( & current) {
111
+ let g = if std:: env:: var_os ( "BOOTC_SETENFORCE0_FALLBACK" ) . is_some ( ) {
108
112
tracing:: warn!( "Failed to enter install_t; temporarily setting permissive mode" ) ;
109
113
selinux_set_permissive ( true ) ?;
110
114
Some ( SetEnforceGuard )
111
115
} else {
112
- None
116
+ let current = get_current_security_context ( ) ?;
117
+ anyhow:: bail!( "Failed to enter install_t (running as {current}) - use BOOTC_SETENFORCE0_FALLBACK=1 to override" ) ;
113
118
} ;
114
119
Ok ( g)
115
120
}
0 commit comments