Skip to content

Commit 3e649be

Browse files
committed
unix: use libc stubs for OpenBSD pledge+unveil
For both compatibility and security concerns, it is preferrable to perform system calls through the libc stubs rather than syscall(2). Besides making programs resilient to changing system call numbers, it removes an unnecessary use of the syscall(2) call which, if found by an attacker, could be abused to perform any system call. As OpenBSD 6.2 is the oldest supported version of OpenBSD, remove the handling of pledge on versions prior to this release. PledgeExecpromises is no longer usable on 6.2, as the execpromises is treated as required (unlike Pledge, where on 6.2 it is allowed but must be empty). The empty execpromises string is no longer converted to a nil pointer on 6.2. This fixes an out-of-bounds read where, on 6.2, an empty string would be passed to the deprecated pledge(2) API, which would interpret the pointer as an array of strings.
1 parent 249e16f commit 3e649be

7 files changed

+97
-52
lines changed

unix/pledge_openbsd.go

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import (
88
"errors"
99
"fmt"
1010
"strconv"
11-
"syscall"
12-
"unsafe"
1311
)
1412

1513
// Pledge implements the pledge syscall.
@@ -24,23 +22,17 @@ func Pledge(promises, execpromises string) error {
2422
return err
2523
}
2624

27-
pptr, err := syscall.BytePtrFromString(promises)
25+
pptr, err := BytePtrFromString(promises)
2826
if err != nil {
2927
return err
3028
}
3129

32-
exptr, err := syscall.BytePtrFromString(execpromises)
30+
exptr, err := BytePtrFromString(execpromises)
3331
if err != nil {
3432
return err
3533
}
3634

37-
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)),
38-
uintptr(unsafe.Pointer(exptr)), 0)
39-
if e != 0 {
40-
return e
41-
}
42-
43-
return nil
35+
return pledge(pptr, exptr)
4436
}
4537

4638
// PledgePromises implements the pledge syscall.
@@ -53,48 +45,33 @@ func PledgePromises(promises string) error {
5345
return err
5446
}
5547

56-
// This variable holds the execpromises and is always nil.
57-
var expr unsafe.Pointer
58-
59-
pptr, err := syscall.BytePtrFromString(promises)
48+
pptr, err := BytePtrFromString(promises)
6049
if err != nil {
6150
return err
6251
}
6352

64-
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)),
65-
uintptr(expr), 0)
66-
if e != 0 {
67-
return e
68-
}
69-
70-
return nil
53+
return pledge(pptr, nil)
7154
}
7255

7356
// PledgeExecpromises implements the pledge syscall.
7457
//
7558
// This changes the execpromises and leaves the promises untouched.
7659
//
60+
// The pledge syscall does not accept execpromises on OpenBSD releases
61+
// before 6.3.
62+
//
7763
// For more information see pledge(2).
7864
func PledgeExecpromises(execpromises string) error {
7965
if err := pledgeAvailable(); err != nil {
8066
return err
8167
}
8268

83-
// This variable holds the promises and is always nil.
84-
var pptr unsafe.Pointer
85-
86-
exptr, err := syscall.BytePtrFromString(execpromises)
69+
exptr, err := BytePtrFromString(execpromises)
8770
if err != nil {
8871
return err
8972
}
9073

91-
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr),
92-
uintptr(unsafe.Pointer(exptr)), 0)
93-
if e != 0 {
94-
return e
95-
}
96-
97-
return nil
74+
return pledge(nil, exptr)
9875
}
9976

10077
// majmin returns major and minor version number for an OpenBSD system.

unix/syscall_openbsd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,3 +327,5 @@ func Uname(uname *Utsname) error {
327327
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
328328
//sys munmap(addr uintptr, length uintptr) (err error)
329329
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
330+
//sys pledge(promises *byte, execpromises *byte) (err error)
331+
//sys unveil(path *byte, flags *byte) (err error)

unix/unveil_openbsd.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,38 @@
44

55
package unix
66

7-
import (
8-
"fmt"
9-
"syscall"
10-
"unsafe"
11-
)
7+
import "fmt"
128

139
// Unveil implements the unveil syscall.
1410
// For more information see unveil(2).
1511
// Note that the special case of blocking further
1612
// unveil calls is handled by UnveilBlock.
13+
//
14+
// Unveil requires OpenBSD 6.4 or later.
1715
func Unveil(path string, flags string) error {
1816
if err := supportsUnveil(); err != nil {
1917
return err
2018
}
21-
pathPtr, err := syscall.BytePtrFromString(path)
19+
pathPtr, err := BytePtrFromString(path)
2220
if err != nil {
2321
return err
2422
}
25-
flagsPtr, err := syscall.BytePtrFromString(flags)
23+
flagsPtr, err := BytePtrFromString(flags)
2624
if err != nil {
2725
return err
2826
}
29-
_, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(unsafe.Pointer(pathPtr)), uintptr(unsafe.Pointer(flagsPtr)), 0)
30-
if e != 0 {
31-
return e
32-
}
33-
return nil
27+
return unveil(pathPtr, flagsPtr)
3428
}
3529

3630
// UnveilBlock blocks future unveil calls.
3731
// For more information see unveil(2).
32+
//
33+
// Unveil requires OpenBSD 6.4 or later.
3834
func UnveilBlock() error {
3935
if err := supportsUnveil(); err != nil {
4036
return err
4137
}
42-
// Both pointers must be nil.
43-
var pathUnsafe, flagsUnsafe unsafe.Pointer
44-
_, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(pathUnsafe), uintptr(flagsUnsafe), 0)
45-
if e != 0 {
46-
return e
47-
}
48-
return nil
38+
return unveil(nil, nil)
4939
}
5040

5141
// supportsUnveil checks for availability of the unveil(2) system call based

unix/zsyscall_openbsd_386.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_openbsd_386.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,13 @@ TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0
672672
JMP libc_utimensat(SB)
673673
GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4
674674
DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB)
675+
676+
TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0
677+
JMP libc_pledge(SB)
678+
GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4
679+
DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB)
680+
681+
TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0
682+
JMP libc_unveil(SB)
683+
GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4
684+
DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB)

unix/zsyscall_openbsd_amd64.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_openbsd_amd64.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,13 @@ TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0
672672
JMP libc_utimensat(SB)
673673
GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8
674674
DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB)
675+
676+
TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0
677+
JMP libc_pledge(SB)
678+
GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8
679+
DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB)
680+
681+
TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0
682+
JMP libc_unveil(SB)
683+
GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8
684+
DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB)

0 commit comments

Comments
 (0)