]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
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 | ||
15c0b25d AP |
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 | } |