pledge_openbsd.go (3746B)
1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package unix 6 7 import ( 8 "errors" 9 "fmt" 10 "strconv" 11 "syscall" 12 "unsafe" 13 ) 14 15 // Pledge implements the pledge syscall. 16 // 17 // The pledge syscall does not accept execpromises on OpenBSD releases 18 // before 6.3. 19 // 20 // execpromises must be empty when Pledge is called on OpenBSD 21 // releases predating 6.3, otherwise an error will be returned. 22 // 23 // For more information see pledge(2). 24 func Pledge(promises, execpromises string) error { 25 maj, min, err := majmin() 26 if err != nil { 27 return err 28 } 29 30 err = pledgeAvailable(maj, min, execpromises) 31 if err != nil { 32 return err 33 } 34 35 pptr, err := syscall.BytePtrFromString(promises) 36 if err != nil { 37 return err 38 } 39 40 // This variable will hold either a nil unsafe.Pointer or 41 // an unsafe.Pointer to a string (execpromises). 42 var expr unsafe.Pointer 43 44 // If we're running on OpenBSD > 6.2, pass execpromises to the syscall. 45 if maj > 6 || (maj == 6 && min > 2) { 46 exptr, err := syscall.BytePtrFromString(execpromises) 47 if err != nil { 48 return err 49 } 50 expr = unsafe.Pointer(exptr) 51 } 52 53 _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) 54 if e != 0 { 55 return e 56 } 57 58 return nil 59 } 60 61 // PledgePromises implements the pledge syscall. 62 // 63 // This changes the promises and leaves the execpromises untouched. 64 // 65 // For more information see pledge(2). 66 func PledgePromises(promises string) error { 67 maj, min, err := majmin() 68 if err != nil { 69 return err 70 } 71 72 err = pledgeAvailable(maj, min, "") 73 if err != nil { 74 return err 75 } 76 77 // This variable holds the execpromises and is always nil. 78 var expr unsafe.Pointer 79 80 pptr, err := syscall.BytePtrFromString(promises) 81 if err != nil { 82 return err 83 } 84 85 _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) 86 if e != 0 { 87 return e 88 } 89 90 return nil 91 } 92 93 // PledgeExecpromises implements the pledge syscall. 94 // 95 // This changes the execpromises and leaves the promises untouched. 96 // 97 // For more information see pledge(2). 98 func PledgeExecpromises(execpromises string) error { 99 maj, min, err := majmin() 100 if err != nil { 101 return err 102 } 103 104 err = pledgeAvailable(maj, min, execpromises) 105 if err != nil { 106 return err 107 } 108 109 // This variable holds the promises and is always nil. 110 var pptr unsafe.Pointer 111 112 exptr, err := syscall.BytePtrFromString(execpromises) 113 if err != nil { 114 return err 115 } 116 117 _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0) 118 if e != 0 { 119 return e 120 } 121 122 return nil 123 } 124 125 // majmin returns major and minor version number for an OpenBSD system. 126 func majmin() (major int, minor int, err error) { 127 var v Utsname 128 err = Uname(&v) 129 if err != nil { 130 return 131 } 132 133 major, err = strconv.Atoi(string(v.Release[0])) 134 if err != nil { 135 err = errors.New("cannot parse major version number returned by uname") 136 return 137 } 138 139 minor, err = strconv.Atoi(string(v.Release[2])) 140 if err != nil { 141 err = errors.New("cannot parse minor version number returned by uname") 142 return 143 } 144 145 return 146 } 147 148 // pledgeAvailable checks for availability of the pledge(2) syscall 149 // based on the running OpenBSD version. 150 func pledgeAvailable(maj, min int, execpromises string) error { 151 // If OpenBSD <= 5.9, pledge is not available. 152 if (maj == 5 && min != 9) || maj < 5 { 153 return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min) 154 } 155 156 // If OpenBSD <= 6.2 and execpromises is not empty, 157 // return an error - execpromises is not available before 6.3 158 if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" { 159 return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min) 160 } 161 162 return nil 163 }