@@ -27,6 +27,7 @@ const (
2727 selinuxDir = "/etc/selinux/"
2828 selinuxUsersDir = "contexts/users"
2929 defaultContexts = "contexts/default_contexts"
30+ failsafeContext = "contexts/failsafe_context"
3031 selinuxConfig = selinuxDir + "config"
3132 selinuxfsMount = "/sys/fs/selinux"
3233 selinuxTypeTag = "SELINUXTYPE"
@@ -57,6 +58,7 @@ type defaultSECtx struct {
5758 userRdr io.Reader
5859 verifier func (string ) error
5960 defaultRdr io.Reader
61+ failsafeRdr io.Reader
6062 user , level , scon string
6163}
6264
@@ -1349,6 +1351,33 @@ func findUserInContext(context Context, r io.Reader, verifier func(string) error
13491351 return "" , nil
13501352}
13511353
1354+ // getFailsafeContext returns the context in the failsafe_context file:
1355+ // https://www.man7.org/linux/man-pages/man5/failsafe_context.5.html
1356+ func getFailsafeContext (context Context , r io.Reader , verifier func (string ) error ) (string , error ) {
1357+ conn := make ([]byte , 256 )
1358+ limReader := io .LimitReader (r , int64 (len (conn )))
1359+ _ , err := limReader .Read (conn )
1360+ if err != nil {
1361+ return "" , fmt .Errorf ("failed to read failsafe context: %w" , err )
1362+ }
1363+
1364+ conn = bytes .TrimSpace (conn )
1365+ toConns := strings .SplitN (string (conn ), ":" , 4 )
1366+ if len (toConns ) != 3 {
1367+ return "" , nil
1368+ }
1369+
1370+ context ["role" ] = toConns [0 ]
1371+ context ["type" ] = toConns [1 ]
1372+
1373+ outConn := context .get ()
1374+ if err := verifier (outConn ); err != nil {
1375+ return "" , nil
1376+ }
1377+
1378+ return outConn , nil
1379+ }
1380+
13521381func getDefaultContextFromReaders (c * defaultSECtx ) (string , error ) {
13531382 if c .verifier == nil {
13541383 return "" , ErrVerifierNil
@@ -1365,7 +1394,7 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
13651394
13661395 conn , err := findUserInContext (context , c .userRdr , c .verifier )
13671396 if err != nil {
1368- return "" , err
1397+ return "" , fmt . Errorf ( "failed to read %q's user context file: %w" , c . user , err )
13691398 }
13701399
13711400 if conn != "" {
@@ -1374,7 +1403,16 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
13741403
13751404 conn , err = findUserInContext (context , c .defaultRdr , c .verifier )
13761405 if err != nil {
1377- return "" , err
1406+ return "" , fmt .Errorf ("failed to read default user context file: %w" , err )
1407+ }
1408+
1409+ if conn != "" {
1410+ return conn , nil
1411+ }
1412+
1413+ conn , err = getFailsafeContext (context , c .failsafeRdr , c .verifier )
1414+ if err != nil {
1415+ return "" , fmt .Errorf ("failed to read failsafe_context: %w" , err )
13781416 }
13791417
13801418 if conn != "" {
@@ -1388,24 +1426,32 @@ func getDefaultContextWithLevel(user, level, scon string) (string, error) {
13881426 userPath := filepath .Join (policyRoot (), selinuxUsersDir , user )
13891427 fu , err := os .Open (userPath )
13901428 if err != nil {
1391- return "" , err
1429+ return "" , fmt . Errorf ( "failed to open %q's user context file: %w" , user , err )
13921430 }
13931431 defer fu .Close ()
13941432
13951433 defaultPath := filepath .Join (policyRoot (), defaultContexts )
13961434 fd , err := os .Open (defaultPath )
13971435 if err != nil {
1398- return "" , err
1436+ return "" , fmt . Errorf ( "failed to open default user context file: %w" , err )
13991437 }
14001438 defer fd .Close ()
14011439
1440+ failsafePath := filepath .Join (policyRoot (), failsafeContext )
1441+ fs , err := os .Open (failsafePath )
1442+ if err != nil {
1443+ return "" , fmt .Errorf ("failed to open failsafe user context file: %w" , err )
1444+ }
1445+ defer fs .Close ()
1446+
14021447 c := defaultSECtx {
1403- user : user ,
1404- level : level ,
1405- scon : scon ,
1406- userRdr : fu ,
1407- defaultRdr : fd ,
1408- verifier : securityCheckContext ,
1448+ user : user ,
1449+ level : level ,
1450+ scon : scon ,
1451+ userRdr : fu ,
1452+ defaultRdr : fd ,
1453+ failsafeRdr : fs ,
1454+ verifier : securityCheckContext ,
14091455 }
14101456
14111457 return getDefaultContextFromReaders (& c )
0 commit comments