1 // Copyright 2016 CoreOS, Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 // #include <stdlib.h>
20 // #include <sys/types.h>
21 // #include <unistd.h>
24 // my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid)
26 // int (*sd_pid_get_owner_uid)(pid_t, uid_t *);
28 // sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f;
29 // return sd_pid_get_owner_uid(pid, uid);
33 // my_sd_pid_get_unit(void *f, pid_t pid, char **unit)
35 // int (*sd_pid_get_unit)(pid_t, char **);
37 // sd_pid_get_unit = (int (*)(pid_t, char **))f;
38 // return sd_pid_get_unit(pid, unit);
42 // my_sd_pid_get_slice(void *f, pid_t pid, char **slice)
44 // int (*sd_pid_get_slice)(pid_t, char **);
46 // sd_pid_get_slice = (int (*)(pid_t, char **))f;
47 // return sd_pid_get_slice(pid, slice);
51 // am_session_leader()
53 // return (getsid(0) == getpid());
61 "github.com/coreos/pkg/dlopen"
64 var libsystemdNames = []string{
66 "libsystemd-login.so.0",
67 "libsystemd-login.so",
69 // systemd >= 209 merged libsystemd-login into libsystemd proper
74 func getRunningSlice() (slice string, err error) {
75 var h *dlopen.LibHandle
76 h, err = dlopen.GetHandle(libsystemdNames)
81 if err1 := h.Close(); err1 != nil {
86 sd_pid_get_slice, err := h.GetSymbolPointer("sd_pid_get_slice")
93 defer C.free(unsafe.Pointer(sl))
95 ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl)
97 err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret))
101 return C.GoString(sl), nil
104 func runningFromSystemService() (ret bool, err error) {
105 var h *dlopen.LibHandle
106 h, err = dlopen.GetHandle(libsystemdNames)
111 if err1 := h.Close(); err1 != nil {
116 sd_pid_get_owner_uid, err := h.GetSymbolPointer("sd_pid_get_owner_uid")
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)
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
140 err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno))
145 func currentUnitName() (unit string, err error) {
146 var h *dlopen.LibHandle
147 h, err = dlopen.GetHandle(libsystemdNames)
152 if err1 := h.Close(); err1 != nil {
157 sd_pid_get_unit, err := h.GetSymbolPointer("sd_pid_get_unit")
164 defer C.free(unsafe.Pointer(u))
166 ret := C.my_sd_pid_get_unit(sd_pid_get_unit, 0, &u)
168 err = fmt.Errorf("error calling sd_pid_get_unit: %v", syscall.Errno(-ret))