@@ -36,6 +36,10 @@ var gitCommit = ""
36
36
// VERSION file of the source code.
37
37
var version = ""
38
38
39
+ // errAccess will be used for defining either a read error or a write error
40
+ // from any type of files.
41
+ var errAccess error
42
+
39
43
// PrGetNoNewPrivs isn't exposed in Golang so we define it ourselves copying the value from
40
44
// the kernel
41
45
const PrGetNoNewPrivs = 39
@@ -410,23 +414,35 @@ func testReadAccess(path string) (readable bool, err error) {
410
414
return false , err
411
415
}
412
416
413
- // In case of a directory, we should check its readability in a special way.
414
- // In other files, we should not check its Mode explicitly, because the runtime
415
- // spec does not mandate the type of masked files. It could be a regular file
416
- // or a character file (/dev/null), which is the case for runtimes like runc.
417
- if fi .IsDir () {
417
+ // Check for readability in case of regular files, character device, or
418
+ // directory. Although the runtime spec does not mandate the type of
419
+ // masked files, we should check its Mode explicitly. A masked file
420
+ // could be represented as a character file (/dev/null), which is the
421
+ // case for runtimes like runc.
422
+ switch fi .Mode () & os .ModeType {
423
+ case 0 , os .ModeDevice | os .ModeCharDevice :
424
+ return testFileReadAccess (path )
425
+ case os .ModeDir :
418
426
return testDirectoryReadAccess (path )
419
427
}
420
- return testFileReadAccess (path )
428
+
429
+ errAccess = fmt .Errorf ("cannot test read access for %q (mode %d)" , path , fi .Mode ())
430
+ return false , errAccess
421
431
}
422
432
423
433
func testDirectoryReadAccess (path string ) (readable bool , err error ) {
424
- if files , err := ioutil .ReadDir (path ); err != nil || len (files ) == 0 {
425
- // err from reading from a directory should not be considered as test failure,
426
- // it just means that the test program successfully assessed that
427
- // the directory is not readable.
434
+ files , err := ioutil .ReadDir (path )
435
+ if err == io .EOF || len (files ) == 0 {
436
+ // Our validation/ tests only use non-empty directories for read-access
437
+ // tests. So if we get an EOF on the first read, the runtime did
438
+ // successfully block readability. So it should not be considered as test
439
+ // failure, it just means that the test program successfully assessed
440
+ // that the directory is not readable.
428
441
return false , nil
429
442
}
443
+ if err != nil {
444
+ return false , err
445
+ }
430
446
return true , nil
431
447
}
432
448
@@ -455,14 +471,19 @@ func testWriteAccess(path string) (writable bool, err error) {
455
471
return false , err
456
472
}
457
473
458
- // In case of a directory, we should check its readability in a special way.
459
- // In other files, we should not check its Mode explicitly, because the runtime
460
- // spec does not mandate the type of masked files. It could be a regular file
461
- // or a character file (/dev/null), which is the case for runtimes like runc.
462
- if fi .IsDir () {
474
+ // Check for writability in case of regular files, character device, or
475
+ // directory. Although the runtime spec does not mandate the type of
476
+ // masked files, we should check its Mode explicitly. A masked file
477
+ // could be represented as a character file (/dev/null), which is the
478
+ // case for runtimes like runc.
479
+ switch fi .Mode () & os .ModeType {
480
+ case 0 , os .ModeDevice | os .ModeCharDevice :
481
+ return testFileWriteAccess (path )
482
+ case os .ModeDir :
463
483
return testDirectoryWriteAccess (path )
464
484
}
465
- return testFileWriteAccess (path )
485
+ errAccess = fmt .Errorf ("cannot test write access for %q (mode %d)" , path , fi .Mode ())
486
+ return false , errAccess
466
487
}
467
488
468
489
func testDirectoryWriteAccess (path string ) (writable bool , err error ) {
@@ -874,7 +895,7 @@ func (c *complianceTester) validateMaskedPaths(spec *rspec.Spec) error {
874
895
875
896
for _ , maskedPath := range spec .Linux .MaskedPaths {
876
897
readable , err := testReadAccess (maskedPath )
877
- if err != nil && ! os .IsNotExist (err ) {
898
+ if err != nil && ! os .IsNotExist (err ) && err != errAccess {
878
899
return err
879
900
}
880
901
c .harness .Ok (! readable , fmt .Sprintf ("cannot read masked path %q" , maskedPath ))
@@ -917,15 +938,15 @@ func (c *complianceTester) validateROPaths(spec *rspec.Spec) error {
917
938
918
939
for i , path := range spec .Linux .ReadonlyPaths {
919
940
readable , err := testReadAccess (path )
920
- if err != nil {
941
+ if err != nil && err != errAccess {
921
942
return err
922
943
}
923
944
if ! readable {
924
945
c .harness .Skip (1 , fmt .Sprintf ("%q (linux.readonlyPaths[%d]) is not readable" , path , i ))
925
946
}
926
947
927
948
writable , err := testWriteAccess (path )
928
- if err != nil && ! os .IsNotExist (err ) {
949
+ if err != nil && ! os .IsNotExist (err ) && err != errAccess {
929
950
return err
930
951
}
931
952
c .harness .Ok (! writable , fmt .Sprintf ("%q (linux.readonlyPaths[%d]) is not writable" , path , i ))
0 commit comments