Skip to content

Commit 60b7021

Browse files
author
Anthony Romano
committed
util: conditionally build CGO functions
Some projects don't need the CGO functions in the util package; split out the functions into a separate file so CGO_ENABLED=0 works if those functions are never used. Fixes coreos#171
1 parent fa8411d commit 60b7021

File tree

3 files changed

+210
-148
lines changed

3 files changed

+210
-148
lines changed

util/util.go

Lines changed: 7 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -18,96 +18,19 @@
1818
// than linking against them.
1919
package util
2020

21-
// #include <stdlib.h>
22-
// #include <sys/types.h>
23-
// #include <unistd.h>
24-
//
25-
// int
26-
// my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
27-
// {
28-
// int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
29-
//
30-
// sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
31-
// return sd_pid_get_owner_uid(pid, uid);
32-
// }
33-
//
34-
// int
35-
// my_sd_pid_get_unit(void *f, pid_t pid, char **unit)
36-
// {
37-
// int (*sd_pid_get_unit)(pid_t, char **);
38-
//
39-
// sd_pid_get_unit = (int (*)(pid_t, char **))f;
40-
// return sd_pid_get_unit(pid, unit);
41-
// }
42-
//
43-
// int
44-
// my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
45-
// {
46-
// int (*sd_pid_get_slice)(pid_t, char **);
47-
//
48-
// sd_pid_get_slice = (int (*)(pid_t, char **))f;
49-
// return sd_pid_get_slice(pid, slice);
50-
// }
51-
//
52-
// int
53-
// am_session_leader()
54-
// {
55-
// return (getsid(0) == getpid());
56-
// }
57-
import "C"
5821
import (
5922
"fmt"
6023
"io/ioutil"
6124
"os"
6225
"strings"
63-
"syscall"
64-
"unsafe"
65-
66-
"github.com/coreos/pkg/dlopen"
6726
)
6827

69-
var libsystemdNames = []string{
70-
// systemd < 209
71-
"libsystemd-login.so.0",
72-
"libsystemd-login.so",
73-
74-
// systemd >= 209 merged libsystemd-login into libsystemd proper
75-
"libsystemd.so.0",
76-
"libsystemd.so",
77-
}
78-
7928
// GetRunningSlice attempts to retrieve the name of the systemd slice in which
8029
// the current process is running.
8130
// This function is a wrapper around the libsystemd C library; if it cannot be
8231
// opened, an error is returned.
83-
func GetRunningSlice() (slice string, err error) {
84-
var h *dlopen.LibHandle
85-
h, err = dlopen.GetHandle(libsystemdNames)
86-
if err != nil {
87-
return
88-
}
89-
defer func() {
90-
if err1 := h.Close(); err1 != nil {
91-
err = err1
92-
}
93-
}()
94-
95-
sd_pid_get_slice, err := h.GetSymbolPointer("sd_pid_get_slice")
96-
if err != nil {
97-
return
98-
}
99-
100-
var s string
101-
sl := C.CString(s)
102-
defer C.free(unsafe.Pointer(sl))
103-
104-
ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
105-
if ret < 0 {
106-
err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
107-
return
108-
}
109-
110-
return C.GoString(sl), nil
32+
func GetRunningSlice() (string, error) {
33+
return getRunningSlice()
11134
}
11235

11336
// RunningFromSystemService tries to detect whether the current process has
@@ -125,81 +48,17 @@ func GetRunningSlice() (slice string, err error) {
12548
//
12649
// This function is a wrapper around the libsystemd C library; if this is
12750
// unable to successfully open a handle to the library for any reason (e.g. it
128-
// cannot be found), an errr will be returned
129-
func RunningFromSystemService() (ret bool, err error) {
130-
var h *dlopen.LibHandle
131-
h, err = dlopen.GetHandle(libsystemdNames)
132-
if err != nil {
133-
return
134-
}
135-
defer func() {
136-
if err1 := h.Close(); err1 != nil {
137-
err = err1
138-
}
139-
}()
140-
141-
sd_pid_get_owner_uid, err := h.GetSymbolPointer("sd_pid_get_owner_uid")
142-
if err != nil {
143-
return
144-
}
145-
146-
var uid C.uid_t
147-
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
148-
serrno := syscall.Errno(-errno)
149-
// when we're running from a unit file, sd_pid_get_owner_uid returns
150-
// ENOENT (systemd <220) or ENXIO (systemd >=220)
151-
switch {
152-
case errno >= 0:
153-
ret = false
154-
case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
155-
// Since the implementation of sessions in systemd relies on
156-
// the `pam_systemd` module, using the sd_pid_get_owner_uid
157-
// heuristic alone can result in false positives if that module
158-
// (or PAM itself) is not present or properly configured on the
159-
// system. As such, we also check if we're the session leader,
160-
// which should be the case if we're invoked from a unit file,
161-
// but not if e.g. we're invoked from the command line from a
162-
// user's login session
163-
ret = C.am_session_leader() == 1
164-
default:
165-
err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
166-
}
167-
return
51+
// cannot be found), an error will be returned.
52+
func RunningFromSystemService() (bool, error) {
53+
return runningFromSystemService()
16854
}
16955

17056
// CurrentUnitName attempts to retrieve the name of the systemd system unit
17157
// from which the calling process has been invoked. It wraps the systemd
17258
// `sd_pid_get_unit` call, with the same caveat: for processes not part of a
17359
// systemd system unit, this function will return an error.
174-
func CurrentUnitName() (unit string, err error) {
175-
var h *dlopen.LibHandle
176-
h, err = dlopen.GetHandle(libsystemdNames)
177-
if err != nil {
178-
return
179-
}
180-
defer func() {
181-
if err1 := h.Close(); err1 != nil {
182-
err = err1
183-
}
184-
}()
185-
186-
sd_pid_get_unit, err := h.GetSymbolPointer("sd_pid_get_unit")
187-
if err != nil {
188-
return
189-
}
190-
191-
var s string
192-
u := C.CString(s)
193-
defer C.free(unsafe.Pointer(u))
194-
195-
ret := C.my_sd_pid_get_unit(sd_pid_get_unit, 0, &u)
196-
if ret < 0 {
197-
err = fmt.Errorf("error calling sd_pid_get_unit: %v", syscall.Errno(-ret))
198-
return
199-
}
200-
201-
unit = C.GoString(u)
202-
return
60+
func CurrentUnitName() (string, error) {
61+
return currentUnitName()
20362
}
20463

20564
// IsRunningSystemd checks whether the host was booted with systemd as its init

util/util_cgo.go

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Copyright 2016 CoreOS, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// +build cgo
16+
17+
package util
18+
19+
// #include <stdlib.h>
20+
// #include <sys/types.h>
21+
// #include <unistd.h>
22+
//
23+
// int
24+
// my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
25+
// {
26+
// int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
27+
//
28+
// sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
29+
// return sd_pid_get_owner_uid(pid, uid);
30+
// }
31+
//
32+
// int
33+
// my_sd_pid_get_unit(void *f, pid_t pid, char **unit)
34+
// {
35+
// int (*sd_pid_get_unit)(pid_t, char **);
36+
//
37+
// sd_pid_get_unit = (int (*)(pid_t, char **))f;
38+
// return sd_pid_get_unit(pid, unit);
39+
// }
40+
//
41+
// int
42+
// my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
43+
// {
44+
// int (*sd_pid_get_slice)(pid_t, char **);
45+
//
46+
// sd_pid_get_slice = (int (*)(pid_t, char **))f;
47+
// return sd_pid_get_slice(pid, slice);
48+
// }
49+
//
50+
// int
51+
// am_session_leader()
52+
// {
53+
// return (getsid(0) == getpid());
54+
// }
55+
import "C"
56+
import (
57+
"fmt"
58+
"syscall"
59+
"unsafe"
60+
61+
"github.com/coreos/pkg/dlopen"
62+
)
63+
64+
var libsystemdNames = []string{
65+
// systemd < 209
66+
"libsystemd-login.so.0",
67+
"libsystemd-login.so",
68+
69+
// systemd >= 209 merged libsystemd-login into libsystemd proper
70+
"libsystemd.so.0",
71+
"libsystemd.so",
72+
}
73+
74+
func getRunningSlice() (slice string, err error) {
75+
var h *dlopen.LibHandle
76+
h, err = dlopen.GetHandle(libsystemdNames)
77+
if err != nil {
78+
return
79+
}
80+
defer func() {
81+
if err1 := h.Close(); err1 != nil {
82+
err = err1
83+
}
84+
}()
85+
86+
sd_pid_get_slice, err := h.GetSymbolPointer("sd_pid_get_slice")
87+
if err != nil {
88+
return
89+
}
90+
91+
var s string
92+
sl := C.CString(s)
93+
defer C.free(unsafe.Pointer(sl))
94+
95+
ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
96+
if ret < 0 {
97+
err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
98+
return
99+
}
100+
101+
return C.GoString(sl), nil
102+
}
103+
104+
func runningFromSystemService() (ret bool, err error) {
105+
var h *dlopen.LibHandle
106+
h, err = dlopen.GetHandle(libsystemdNames)
107+
if err != nil {
108+
return
109+
}
110+
defer func() {
111+
if err1 := h.Close(); err1 != nil {
112+
err = err1
113+
}
114+
}()
115+
116+
sd_pid_get_owner_uid, err := h.GetSymbolPointer("sd_pid_get_owner_uid")
117+
if err != nil {
118+
return
119+
}
120+
121+
var uid C.uid_t
122+
errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid)
123+
serrno := syscall.Errno(-errno)
124+
// when we're running from a unit file, sd_pid_get_owner_uid returns
125+
// ENOENT (systemd <220) or ENXIO (systemd >=220)
126+
switch {
127+
case errno >= 0:
128+
ret = false
129+
case serrno == syscall.ENOENT, serrno == syscall.ENXIO:
130+
// Since the implementation of sessions in systemd relies on
131+
// the `pam_systemd` module, using the sd_pid_get_owner_uid
132+
// heuristic alone can result in false positives if that module
133+
// (or PAM itself) is not present or properly configured on the
134+
// system. As such, we also check if we're the session leader,
135+
// which should be the case if we're invoked from a unit file,
136+
// but not if e.g. we're invoked from the command line from a
137+
// user's login session
138+
ret = C.am_session_leader() == 1
139+
default:
140+
err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
141+
}
142+
return
143+
}
144+
145+
func currentUnitName() (unit string, err error) {
146+
var h *dlopen.LibHandle
147+
h, err = dlopen.GetHandle(libsystemdNames)
148+
if err != nil {
149+
return
150+
}
151+
defer func() {
152+
if err1 := h.Close(); err1 != nil {
153+
err = err1
154+
}
155+
}()
156+
157+
sd_pid_get_unit, err := h.GetSymbolPointer("sd_pid_get_unit")
158+
if err != nil {
159+
return
160+
}
161+
162+
var s string
163+
u := C.CString(s)
164+
defer C.free(unsafe.Pointer(u))
165+
166+
ret := C.my_sd_pid_get_unit(sd_pid_get_unit, 0, &u)
167+
if ret < 0 {
168+
err = fmt.Errorf("error calling sd_pid_get_unit: %v", syscall.Errno(-ret))
169+
return
170+
}
171+
172+
unit = C.GoString(u)
173+
return
174+
}

util/util_stub.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2016 CoreOS, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// +build !cgo
16+
17+
package util
18+
19+
import (
20+
"fmt"
21+
)
22+
23+
var errNoCGO = fmt.Errorf("go-systemd built with CGO disabled")
24+
25+
func getRunningSlice() (string, error) { return "", errNoCGO }
26+
27+
func runningFromSystemService() (bool, error) { return false, errNoCGO }
28+
29+
func currentUnitName() (string, error) { return "", errNoCGO }

0 commit comments

Comments
 (0)