aboutsummaryrefslogtreecommitdiff
path: root/src/syscall/syscall_linux.go
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2016-06-03 15:04:53 -0700
committerDamien Neil <dneil@google.com>2016-09-20 19:27:57 +0000
commitf5f7d6e32d5384a3638325ff8393bf94ec8d6971 (patch)
treef03ae9f878d3fbcd85b419e238f19e5e512d38e5 /src/syscall/syscall_linux.go
parentab5923572984651af05a47755109642bfc529cb5 (diff)
downloadgo-f5f7d6e32d5384a3638325ff8393bf94ec8d6971.tar.xz
syscall: validate ParseDirent inputs
Don't panic, crash, or return references to uninitialized memory when ParseDirent is passed invalid input. Move common dirent parsing to syscall.go with minimal platform-specific functions in syscall_$GOOS.go. Fixes #15653 Change-Id: I5602475e02321fe381064488401c14b33bec6886 Reviewed-on: https://go-review.googlesource.com/23780 Run-TryBot: Damien Neil <dneil@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/syscall/syscall_linux.go')
-rw-r--r--src/syscall/syscall_linux.go40
1 files changed, 13 insertions, 27 deletions
diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
index 73a16f8959..d70e471ba5 100644
--- a/src/syscall/syscall_linux.go
+++ b/src/syscall/syscall_linux.go
@@ -757,38 +757,24 @@ func Reboot(cmd int) (err error) {
return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
}
-func clen(n []byte) int {
- for i := 0; i < len(n); i++ {
- if n[i] == 0 {
- return i
- }
- }
- return len(n)
-}
-
func ReadDirent(fd int, buf []byte) (n int, err error) {
return Getdents(fd, buf)
}
-func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
- origlen := len(buf)
- count = 0
- for max != 0 && len(buf) > 0 {
- dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
- buf = buf[dirent.Reclen:]
- if dirent.Ino == 0 { // File absent in directory.
- continue
- }
- bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
- var name = string(bytes[0:clen(bytes[:])])
- if name == "." || name == ".." { // Useless names
- continue
- }
- max--
- count++
- names = append(names, name)
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ reclen, ok := direntReclen(buf)
+ if !ok {
+ return 0, false
}
- return origlen - len(buf), count, names
+ return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
}
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)