Skip to content

Commit 0386f01

Browse files
committed
selinux: verify that writes to /proc/... are on procfs
This is an additional mitigation for CVE-2019-16884. The primary problem is that Docker can be coerced into bind-mounting a file system on top of /proc (resulting in label-related writes to /proc no longer happening). While runc is working on mitigations against permitting the mounts, this helps avoid go-selinux from being tricked into writing to non-procfs files. This is not a perfect solution (after all, there might be a bind-mount of a different procfs file over the target) but in order to exploit that you would need to be able to tweak a config.json pretty specifically (which thankfully Docker doesn't allow). Signed-off-by: Aleksa Sarai <[email protected]>
1 parent bd44319 commit 0386f01

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

go-selinux/selinux_linux.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"strings"
1919
"sync"
2020
"syscall"
21+
2122
"golang.org/x/sys/unix"
2223
)
2324

@@ -253,6 +254,12 @@ func getSELinuxPolicyRoot() string {
253254
return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
254255
}
255256

257+
func isProcHandle(fh *os.File) (bool, error) {
258+
var buf unix.Statfs_t
259+
err := unix.Fstatfs(int(fh.Fd()), &buf)
260+
return buf.Type == unix.PROC_SUPER_MAGIC, err
261+
}
262+
256263
func readCon(fpath string) (string, error) {
257264
if fpath == "" {
258265
return "", ErrEmptyPath
@@ -264,6 +271,12 @@ func readCon(fpath string) (string, error) {
264271
}
265272
defer in.Close()
266273

274+
if ok, err := isProcHandle(in); err != nil {
275+
return "", err
276+
} else if !ok {
277+
return "", fmt.Errorf("/proc path not on procfs: %s", fpath)
278+
}
279+
267280
var retval string
268281
if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
269282
return "", err
@@ -346,6 +359,12 @@ func writeCon(fpath string, val string) error {
346359
}
347360
defer out.Close()
348361

362+
if ok, err := isProcHandle(out); err != nil {
363+
return err
364+
} else if !ok {
365+
return fmt.Errorf("/proc path not on procfs: %s", fpath)
366+
}
367+
349368
if val != "" {
350369
_, err = out.Write([]byte(val))
351370
} else {
@@ -394,7 +413,7 @@ func SetExecLabel(label string) error {
394413
}
395414

396415
/*
397-
SetTaskLabel sets the SELinux label for the current thread, or an error.
416+
SetTaskLabel sets the SELinux label for the current thread, or an error.
398417
This requires the dyntransition permission.
399418
*/
400419
func SetTaskLabel(label string) error {

0 commit comments

Comments
 (0)