MaskPaths: support directory

For example, the /sys/firmware directory should be masked because it can contain some sensitive files:
  - /sys/firmware/acpi/tables/{SLIC,MSDM}: Windows license information:
  - /sys/firmware/ibft/target0/chap-secret: iSCSI CHAP secret

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
This commit is contained in:
Akihiro Suda 2016-09-23 07:02:10 +00:00
parent e83ccf62aa
commit 53179559a1
6 changed files with 69 additions and 4 deletions

View File

@ -83,6 +83,7 @@ config := &configs.Config{
}, },
MaskPaths: []string{ MaskPaths: []string{
"/proc/kcore", "/proc/kcore",
"/sys/firmware",
}, },
ReadonlyPaths: []string{ ReadonlyPaths: []string{
"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",

View File

@ -56,6 +56,7 @@ func newTemplateConfig(rootfs string) *configs.Config {
}, },
MaskPaths: []string{ MaskPaths: []string{
"/proc/kcore", "/proc/kcore",
"/sys/firmware",
}, },
ReadonlyPaths: []string{ ReadonlyPaths: []string{
"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",

View File

@ -665,10 +665,16 @@ func remountReadonly(path string) error {
return fmt.Errorf("unable to mount %s as readonly max retries reached", path) return fmt.Errorf("unable to mount %s as readonly max retries reached", path)
} }
// maskFile bind mounts /dev/null over the top of the specified path inside a container // maskPath masks the top of the specified path inside a container to avoid
// to avoid security issues from processes reading information from non-namespace aware mounts ( proc/kcore ). // security issues from processes reading information from non-namespace aware
func maskFile(path string) error { // mounts ( proc/kcore ).
// For files, maskPath bind mounts /dev/null over the top of the specified path.
// For directories, maskPath mounts read-only tmpfs over the top of the specified path.
func maskPath(path string) error {
if err := syscall.Mount("/dev/null", path, "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) { if err := syscall.Mount("/dev/null", path, "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) {
if err == syscall.ENOTDIR {
return syscall.Mount("tmpfs", path, "tmpfs", syscall.MS_RDONLY, "")
}
return err return err
} }
return nil return nil

View File

@ -108,7 +108,7 @@ func (l *linuxStandardInit) Init() error {
} }
} }
for _, path := range l.config.Config.MaskPaths { for _, path := range l.config.Config.MaskPaths {
if err := maskFile(path); err != nil { if err := maskPath(path); err != nil {
return err return err
} }
} }

View File

@ -152,6 +152,7 @@ container on your host.`,
"/proc/timer_list", "/proc/timer_list",
"/proc/timer_stats", "/proc/timer_stats",
"/proc/sched_debug", "/proc/sched_debug",
"/sys/firmware",
}, },
ReadonlyPaths: []string{ ReadonlyPaths: []string{
"/proc/asound", "/proc/asound",

View File

@ -0,0 +1,56 @@
#!/usr/bin/env bats
load helpers
function setup() {
teardown_busybox
setup_busybox
}
function teardown() {
teardown_busybox
}
@test "MaskPaths(file)" {
# run busybox detached
runc run -d --console /dev/pts/ptmx test_busybox
[ "$status" -eq 0 ]
wait_for_container 15 1 test_busybox
runc exec test_busybox cat /proc/kcore
[ "$status" -eq 0 ]
[[ "${output}" == "" ]]
runc exec test_busybox rm -f /proc/kcore
[ "$status" -eq 1 ]
[[ "${output}" == *"Permission denied"* ]]
runc exec test_busybox umount /proc/kcore
[ "$status" -eq 1 ]
[[ "${output}" == *"Operation not permitted"* ]]
}
@test "MaskPaths(directory)" {
# run busybox detached
runc run -d --console /dev/pts/ptmx test_busybox
[ "$status" -eq 0 ]
wait_for_container 15 1 test_busybox
runc exec test_busybox ls /sys/firmware
[ "$status" -eq 0 ]
[[ "${output}" == "" ]]
runc exec test_busybox touch /sys/firmware/foo
[ "$status" -eq 1 ]
[[ "${output}" == *"Read-only file system"* ]]
runc exec test_busybox rm -rf /sys/firmware
[ "$status" -eq 1 ]
[[ "${output}" == *"Read-only file system"* ]]
runc exec test_busybox umount /sys/firmware
[ "$status" -eq 1 ]
[[ "${output}" == *"Operation not permitted"* ]]
}