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
5package unix
6
7import (
8	"errors"
9	"fmt"
10	"strconv"
11)
12
13// Pledge implements the pledge syscall.
14//
15// This changes both the promises and execpromises; use PledgePromises or
16// PledgeExecpromises to only change the promises or execpromises
17// respectively.
18//
19// For more information see pledge(2).
20func Pledge(promises, execpromises string) error {
21	if err := pledgeAvailable(); err != nil {
22		return err
23	}
24
25	pptr, err := BytePtrFromString(promises)
26	if err != nil {
27		return err
28	}
29
30	exptr, err := BytePtrFromString(execpromises)
31	if err != nil {
32		return err
33	}
34
35	return pledge(pptr, exptr)
36}
37
38// PledgePromises implements the pledge syscall.
39//
40// This changes the promises and leaves the execpromises untouched.
41//
42// For more information see pledge(2).
43func PledgePromises(promises string) error {
44	if err := pledgeAvailable(); err != nil {
45		return err
46	}
47
48	pptr, err := BytePtrFromString(promises)
49	if err != nil {
50		return err
51	}
52
53	return pledge(pptr, nil)
54}
55
56// PledgeExecpromises implements the pledge syscall.
57//
58// This changes the execpromises and leaves the promises untouched.
59//
60// For more information see pledge(2).
61func PledgeExecpromises(execpromises string) error {
62	if err := pledgeAvailable(); err != nil {
63		return err
64	}
65
66	exptr, err := BytePtrFromString(execpromises)
67	if err != nil {
68		return err
69	}
70
71	return pledge(nil, exptr)
72}
73
74// majmin returns major and minor version number for an OpenBSD system.
75func majmin() (major int, minor int, err error) {
76	var v Utsname
77	err = Uname(&v)
78	if err != nil {
79		return
80	}
81
82	major, err = strconv.Atoi(string(v.Release[0]))
83	if err != nil {
84		err = errors.New("cannot parse major version number returned by uname")
85		return
86	}
87
88	minor, err = strconv.Atoi(string(v.Release[2]))
89	if err != nil {
90		err = errors.New("cannot parse minor version number returned by uname")
91		return
92	}
93
94	return
95}
96
97// pledgeAvailable checks for availability of the pledge(2) syscall
98// based on the running OpenBSD version.
99func pledgeAvailable() error {
100	maj, min, err := majmin()
101	if err != nil {
102		return err
103	}
104
105	// Require OpenBSD 6.4 as a minimum.
106	if maj < 6 || (maj == 6 && min <= 3) {
107		return fmt.Errorf("cannot call Pledge on OpenBSD %d.%d", maj, min)
108	}
109
110	return nil
111}
112