diff --git a/validation/linux_readonly_paths.go b/validation/linux_readonly_paths.go
index 1f2d12635..6a7840657 100644
--- a/validation/linux_readonly_paths.go
+++ b/validation/linux_readonly_paths.go
@@ -1,22 +1,39 @@
 package main
 
 import (
+	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
 
 	"github.com/opencontainers/runtime-tools/validation/util"
+	"golang.org/x/sys/unix"
 )
 
-func main() {
+func checkReadonlyPaths() error {
 	g, err := util.GetDefaultGenerator()
 	if err != nil {
-		util.Fatal(err)
+		return err
 	}
-	g.AddLinuxReadonlyPaths("/readonly-dir")
-	g.AddLinuxReadonlyPaths("/readonly-file")
+
+	readonlyDir := "readonly-dir"
+	readonlySubDir := "readonly-subdir"
+	readonlyFile := "readonly-file"
+
+	readonlyDirTop := filepath.Join("/", readonlyDir)
+	readonlyFileTop := filepath.Join("/", readonlyFile)
+
+	readonlyDirSub := filepath.Join(readonlyDirTop, readonlySubDir)
+	readonlyFileSub := filepath.Join(readonlyDirTop, readonlyFile)
+	readonlyFileSubSub := filepath.Join(readonlyDirSub, readonlyFile)
+
+	g.AddLinuxReadonlyPaths(readonlyDirTop)
+	g.AddLinuxReadonlyPaths(readonlyFileTop)
+	g.AddLinuxReadonlyPaths(readonlyDirSub)
+	g.AddLinuxReadonlyPaths(readonlyFileSub)
+	g.AddLinuxReadonlyPaths(readonlyFileSubSub)
 	err = util.RuntimeInsideValidate(g, func(path string) error {
-		testDir := filepath.Join(path, "readonly-dir")
+		testDir := filepath.Join(path, readonlyDirSub)
 		err = os.MkdirAll(testDir, 0777)
 		if err != nil {
 			return err
@@ -28,13 +45,130 @@ func main() {
 		}
 		defer os.Remove(tmpfile.Name())
 
-		testFile := filepath.Join(path, "readonly-file")
-
 		// runtimetest cannot check the readability of empty files, so
 		// write something.
+		testSubSubFile := filepath.Join(path, readonlyFileSubSub)
+		if err := ioutil.WriteFile(testSubSubFile, []byte("immutable"), 0777); err != nil {
+			return err
+		}
+
+		testSubFile := filepath.Join(path, readonlyFileSub)
+		if err := ioutil.WriteFile(testSubFile, []byte("immutable"), 0777); err != nil {
+			return err
+		}
+
+		testFile := filepath.Join(path, readonlyFile)
 		return ioutil.WriteFile(testFile, []byte("immutable"), 0777)
 	})
+	return err
+}
+
+func checkReadonlyRelPaths() error {
+	g, err := util.GetDefaultGenerator()
+	if err != nil {
+		return err
+	}
+
+	// Deliberately set a relative path to be read-only, and expect an error
+	readonlyRelPath := "readonly-relpath"
+
+	g.AddLinuxReadonlyPaths(readonlyRelPath)
+	err = util.RuntimeInsideValidate(g, func(path string) error {
+		testFile := filepath.Join(path, readonlyRelPath)
+		if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) {
+			return err
+		}
+
+		return nil
+	})
+	if err != nil {
+		return nil
+	}
+	return fmt.Errorf("expected: err != nil, actual: err == nil")
+}
+
+func checkReadonlySymlinks() error {
+	g, err := util.GetDefaultGenerator()
 	if err != nil {
+		return err
+	}
+
+	// Deliberately create a read-only symlink that points an invalid file,
+	// and expect an error.
+	readonlySymlink := "/readonly-symlink"
+
+	g.AddLinuxReadonlyPaths(readonlySymlink)
+	err = util.RuntimeInsideValidate(g, func(path string) error {
+		testFile := filepath.Join(path, readonlySymlink)
+		// ln -s .. /readonly-symlink ; readlink -f /readonly-symlink; ls -L /readonly-symlink
+		if err := os.Symlink("../readonly-symlink", testFile); err != nil {
+			return err
+		}
+		rPath, errR := os.Readlink(testFile)
+		if errR != nil {
+			return errR
+		}
+		_, errS := os.Stat(rPath)
+		if errS != nil && os.IsNotExist(errS) {
+			return errS
+		}
+
+		return nil
+	})
+	if err != nil {
+		return nil
+	}
+	return fmt.Errorf("expected: err != nil, actual: err == nil")
+}
+
+func checkReadonlyDeviceNodes(mode uint32) error {
+	g, err := util.GetDefaultGenerator()
+	if err != nil {
+		return err
+	}
+
+	readonlyDevice := "/readonly-device"
+
+	g.AddLinuxReadonlyPaths(readonlyDevice)
+	return util.RuntimeInsideValidate(g, func(path string) error {
+		testFile := filepath.Join(path, readonlyDevice)
+
+		if err := unix.Mknod(testFile, mode, 0); err != nil {
+			return err
+		}
+
+		if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) {
+			return err
+		}
+
+		return nil
+	})
+}
+
+func main() {
+	if err := checkReadonlyPaths(); err != nil {
+		util.Fatal(err)
+	}
+
+	if err := checkReadonlyRelPaths(); err != nil {
 		util.Fatal(err)
 	}
+
+	if err := checkReadonlySymlinks(); err != nil {
+		util.Fatal(err)
+	}
+
+	// test creation of different type of devices, i.e. block device,
+	// character device, and FIFO.
+	modes := []uint32{
+		unix.S_IFBLK | 0666,
+		unix.S_IFCHR | 0666,
+		unix.S_IFIFO | 0666,
+	}
+
+	for _, m := range modes {
+		if err := checkReadonlyDeviceNodes(m); err != nil {
+			util.Fatal(err)
+		}
+	}
 }
