summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sd_login/.gitignore2
-rw-r--r--sd_login/Makefile27
-rw-r--r--sd_login/doc.go2
-rw-r--r--sd_login/logind_session.go13
-rw-r--r--sd_login/logind_user.go4
-rw-r--r--sd_login/notes.org48
-rw-r--r--sd_login/systemd_cgroup.go (renamed from sd_login/systemd_cgroup_generic.go)93
-rw-r--r--sd_login/systemd_cgroup_skip.go102
-rwxr-xr-xsd_login/systemd_cgroup_skip_gen.go.gen41
-rw-r--r--sd_login/systemd_cgroup_systemd.go105
-rw-r--r--sd_login/systemd_process.go171
-rwxr-xr-xsd_login/systemd_process.go.gen76
-rw-r--r--sd_login/util.go2
-rw-r--r--sd_login/util_valid.go18
14 files changed, 320 insertions, 384 deletions
diff --git a/sd_login/.gitignore b/sd_login/.gitignore
deleted file mode 100644
index 5ad2264..0000000
--- a/sd_login/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/systemd_process.go
-/systemd_cgroup_skip_gen.go
diff --git a/sd_login/Makefile b/sd_login/Makefile
deleted file mode 100644
index 763ab3c..0000000
--- a/sd_login/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2016-2017 Luke Shumaker <lukeshu@sbcglobal.net>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-files.src.gen += systemd_process.go systemd_cgroup_skip_gen.go
-
-files.generate: $(files.src.gen)
-maintainer-clean:
- rm -f -- $(files.src.gen)
-.PHONY: files.generate maintainer-clean
-
-%.go: %.go.gen
- ./$^ > $@
-
-systemd_cgroup_skip_gen.go: systemd_cgroup_skip.go
-
-.DELETE_ON_ERROR:
diff --git a/sd_login/doc.go b/sd_login/doc.go
index 00e7250..7bef4fe 100644
--- a/sd_login/doc.go
+++ b/sd_login/doc.go
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//go:generate make
-
// Package sd_login introspects session and login information from
// systemd, logind, and machined.
//
diff --git a/sd_login/logind_session.go b/sd_login/logind_session.go
index 5c2c5ca..c48d619 100644
--- a/sd_login/logind_session.go
+++ b/sd_login/logind_session.go
@@ -14,9 +14,22 @@
package sd_login
+import (
+ "strings"
+)
+
// A SessionName represents a login session.
type SessionName string
+func (name SessionName) isValid() bool {
+ id := string(name)
+ if id == "" {
+ return false
+ }
+
+ return strings.TrimLeft(id, letters+digits) == ""
+}
+
type SessionState int
const (
diff --git a/sd_login/logind_user.go b/sd_login/logind_user.go
index 8d20d4b..fe908e0 100644
--- a/sd_login/logind_user.go
+++ b/sd_login/logind_user.go
@@ -20,6 +20,10 @@ import (
type UserID int
+func (uid UserID) isValid() bool {
+ return uid >= 0
+}
+
type UserState int
const (
diff --git a/sd_login/notes.org b/sd_login/notes.org
index 0627142..38e866b 100644
--- a/sd_login/notes.org
+++ b/sd_login/notes.org
@@ -8,6 +8,54 @@
* requested metadata on object is missing → -ENODATA
*/
+The format of a systemd cgroup path is:
+
+ /prefix.../slice/slice/slice/unit/extra...
+
+Where
+ - there may be 0 or more slices
+ - `prefix...` may be an arbitrary number/arrangement of path segments
+ - `extra...` may be an arbitrary number/arrangement of path segments
+
+If there is more than one slice in a path, then the rightmost slice is
+the one that we mean when we say "the slice".
+
+We will refer to everything under `prefix...` as a "tree" (my term).
+Because `prefix...` and `extra...` may be arbitrary, we can have
+multiple of trees nested inside eachother.
+
+Because `prefix...` may be arbitrary, we need to know how to skip over
+it; how to get to "our" tree.
+
+For the system cgroup tree, we do this by looking at the cgroup of PID
+1 and then trimming a designated suffix from it to get back to the
+root of the tree.
+
+For user cgroup trees, `prefix...` is a *unit* under the system cgroup
+tree, where the unit matches either `user@UID.service` or
+`session-SESSION.scope`.
+
+A container may nest its cgroup tree inside of a unit also. Because
+the container will have its own PID namespace, it will have its own
+PID 1, and be able to inspect the cgroup of PID 1, just as the host
+system does.
+
+
+| Thing | | |
+|-----------+------------------------------------------------+-------|
+| Cgroup | - | |
+|-----------+------------------------------------------------+-------|
+| Unit | | |
+| Slice | (/$X.slice){0,} or "-.slice" | |
+|-----------+------------------------------------------------+-------|
+| UserUnit | SkipUserPrefix.GetUnit | |
+| UserSlice | SkipUserPrefix.GetSlice | |
+|-----------+------------------------------------------------+-------|
+| Session | scanf("session-${SessionName}.scope") | Unit |
+| Owner | scanf("user-${UserID}.slice") | Slice |
+| Machine | readlink("/run/systemd/machines/unit:${Unit}") | Unit |
+
+
* PID
** get_...
*** session
diff --git a/sd_login/systemd_cgroup_generic.go b/sd_login/systemd_cgroup.go
index 86757d1..29ff38f 100644
--- a/sd_login/systemd_cgroup_generic.go
+++ b/sd_login/systemd_cgroup.go
@@ -26,6 +26,9 @@ import (
type _Cgroup string
+type _CgroupTree string
+type _CgroupLeaf string
+
var cgVersion_cache uint
func cgVersion() uint {
@@ -37,7 +40,6 @@ func cgVersion() uint {
if fs.Type == magic_CGROUP2_SUPER {
cgVersion_cache = 2
} else if fs.Type == magic_TMPFS {
- // XXX: systemd-specific cgroup v1 logic
fs, err = statfs("/sys/fs/cgroup/systemd/")
if err != nil {
return 0
@@ -76,21 +78,10 @@ func cgVersion() uint {
// come in if both "name=systemd" and "name=elogind" controllers
// exist. Systemd and elogind cannot be used together, so this isn't
// a concern.
-//
-// BUG(lukeshu): ProcessID.getCgroup: Has systemd-specific logic. However,
-// it is only for "legacy" cgroup v1 compatibility; the cgroup v2
-// logic is totally implementation-agnostic. Unfortunately(?), no
-// distro seems to be using cgroup v2 (introduced in Linux 4.5) yet by
-// default.
func (pid ProcessID) getCgroup() (_Cgroup, error) {
cgVer := cgVersion()
- var cgroupFilename string
- if pid == 0 {
- cgroupFilename = "/proc/self/cgroup"
- } else {
- cgroupFilename = fmt.Sprintf("/proc/%d/cgroup", pid)
- }
+ cgroupFilename := fmt.Sprintf("/proc/%d/cgroup", pid)
f, err := os.Open(cgroupFilename)
if err != nil {
@@ -140,24 +131,86 @@ func (pid ProcessID) getCgroup() (_Cgroup, error) {
// to. The common case is just "/", but it could be something else if
// we are inside of a container, but have a view of the entier cgroup
// hierarchy.
-//
-// BUG(lukeshu): cgGetRootPath: works correctly on systemd and
-// elogind, but I'm not sure it's general.
-func cgGetRootPath() (_Cgroup, error) {
- cgpath, err := ProcessID(1).getCgroup()
+func cgGetRootPath() (_CgroupTree, error) {
+ cgroup, err := ProcessID(1).getCgroup()
if err != nil {
return "/", err
}
- cgpath = _Cgroup(trimOneSuffix(string(cgpath),
+ cgTree := _CgroupTree(trimOneSuffix(string(cgroup),
"/init.scope", // modern systemd
"/system.slice", // legacy systemd
"/system", // even more legacy systemd
))
- return cgpath, nil
+ return cgTree, nil
}
func cgUnescape(s string) string {
return strings.TrimPrefix(s, "_")
}
+
+func cgDecodeUnit(unit string) string {
+ if len(unit) < 3 {
+ // because "X.Y" is at least 3 characters
+ return ""
+ }
+ unit = cgUnescape(unit)
+ if valid_unit_name(unit)&(unit_name_plain|unit_name_instance) == 0 {
+ return ""
+ }
+ return unit
+}
+
+func (tree _CgroupTree) Parse(cgroup _Cgroup) (leaf _CgroupLeaf) {
+ rest, ok := path_startswith(string(cgroup), string(tree))
+ if ok {
+ return _CgroupLeaf(rest)
+ } else {
+ return ""
+ }
+}
+
+// Even if there is an invalid unit, a slice might still be returned.
+func (leaf _CgroupLeaf) Parse() (slice, unit string, extra _CgroupLeaf) {
+ strLeaf := string(leaf)
+
+ slice = "-.slice"
+ for {
+ part, rest := split2(strings.TrimLeft(strLeaf, "/"), '/')
+ if valid_slice_name(part) {
+ slice = part
+ strLeaf = rest
+ } else {
+ break
+ }
+ }
+ slice = cgDecodeUnit(slice)
+ if slice == "" {
+ return
+ }
+
+ unit, extraStr := split2(strings.TrimLeft(strLeaf, "/"), '/')
+ unit = cgDecodeUnit(unit)
+ if unit == "" {
+ return
+ }
+
+ extra = _CgroupLeaf(extraStr)
+ return
+}
+
+func (leaf _CgroupLeaf) GetSlice() string {
+ slice, _, _ := leaf.Parse()
+ return slice
+}
+
+func (leaf _CgroupLeaf) GetUnit() string {
+ _, unit, _ := leaf.Parse()
+ return unit
+}
+
+func (leaf _CgroupLeaf) GetRest() _CgroupLeaf {
+ _, _, extra := leaf.Parse()
+ return extra
+}
diff --git a/sd_login/systemd_cgroup_skip.go b/sd_login/systemd_cgroup_skip.go
deleted file mode 100644
index e6e9042..0000000
--- a/sd_login/systemd_cgroup_skip.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (C) 2016-2017 Luke Shumaker <lukeshu@sbcglobal.net>
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package sd_login
-
-// The "skip:" comments in this file are used to automagically
-// generate helper functions. The lack of a space between "//" and
-// "skip:" is important
-
-import (
- "strconv"
- "strings"
-)
-
-func (cgroup _Cgroup) SkipPath(prefix _Cgroup) (_Cgroup, bool) {
- //skip: SkipPath(prefix _Cgroup) : SkipPath(prefix)
- rest, ok := path_startswith(string(cgroup), string(prefix))
- if ok {
- return _Cgroup(rest), true
- } else {
- return cgroup, false
- }
-}
-
-// Skip (*.slice){1,}
-func (cgroup _Cgroup) SkipSlices() (_Cgroup, bool) {
- //skip: SkipSlices() : SkipSlices()
- cg := string(cgroup)
- skipped := false
- for {
- cg = strings.TrimLeft(cg, "/")
- part, rest := split2(cg, '/')
- if !valid_slice_name(part) {
- return _Cgroup(cg), skipped
- }
- skipped = true
- cg = rest
- }
-}
-
-// Skip user@*.service
-func (cgroup _Cgroup) SkipUserManager() (_Cgroup, bool) {
- //skip: SkipUserManager() : SkipUserManager()
- part, rest := split2(strings.TrimLeft(string(cgroup), "/"), '/')
- uid_str, ok := trimPrefixSuffix(part, "user@", ".service")
- if !ok {
- return cgroup, false
- }
- _, err := strconv.Atoi(uid_str)
- if err != nil {
- return cgroup, false
- }
- return _Cgroup(rest), true
-}
-
-// Skip session-*.scope
-func (cgroup _Cgroup) SkipSession() (_Cgroup, bool) {
- //skip: SkipSession() : SkipSession()
- part, rest := split2(strings.TrimLeft(string(cgroup), "/"), '/')
- session, ok := trimPrefixSuffix(part, "session-", ".scope")
- if !ok {
- return cgroup, false
- }
- if !valid_session_name(session) {
- return cgroup, false
- }
- return _Cgroup(rest), true
-}
-
-// Skip (/*.slice){0,}/(user@*.service|session-*.scope)
-func (cgroup _Cgroup) SkipUserPrefix() (_Cgroup, bool) {
- //skip: SkipUserPrefix() : SkipUserPrefix()
- cgroup, _ = cgroup.SkipSlices()
- cgroup, ok := cgroup.SkipUserManager()
- if ok {
- return cgroup, ok
- }
- return cgroup.SkipSession()
-}
-
-// Skip cgGetRootPath
-func (cgroup _Cgroup) SkipSystemPrefix() (_Cgroup, bool) {
- //skip: SkipSystemPrefix() : SkipSystemPrefix()
-
- rootpath, err := cgGetRootPath()
- if err != nil {
- return cgroup, false
- }
-
- return cgroup.SkipPath(rootpath)
-}
diff --git a/sd_login/systemd_cgroup_skip_gen.go.gen b/sd_login/systemd_cgroup_skip_gen.go.gen
deleted file mode 100755
index 26c515a..0000000
--- a/sd_login/systemd_cgroup_skip_gen.go.gen
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (C) 2017 Luke Shumaker <lukeshu@sbcglobal.net>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- printf '//'
- printf ' %q' "$0" "$@"
- printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n'
-
- echo package sd_login
-
- grep -o '//skip:.*' "$1" | cut -d: -f2- | while read -r line; do
- sig=$(echo $(cut -d: -f1 <<<"$line"))
- cal=$(echo $(cut -d: -f2 <<<"$line"))
- cat <<EOF
-
-func (cgroup _Cgroup) Maybe${sig} _Cgroup {
- cgroup, _ = cgroup.${cal}
- return cgroup
-}
-func (cgroup _Cgroup) Must${sig} _Cgroup {
- cgroup, ok := cgroup.${cal}
- if !ok {
- return ""
- }
- return cgroup
-}
-EOF
- done
-} | gofmt
diff --git a/sd_login/systemd_cgroup_systemd.go b/sd_login/systemd_cgroup_systemd.go
deleted file mode 100644
index 834d378..0000000
--- a/sd_login/systemd_cgroup_systemd.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (C) 2016-2017 Luke Shumaker <lukeshu@sbcglobal.net>
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package sd_login
-
-import (
- "os"
- "strconv"
- "strings"
-)
-
-// XXX: logind
-func (cgroup _Cgroup) GetSession() SessionName {
- unit := cgroup.GetUnit()
-
- session, ok := trimPrefixSuffix(unit, "session-", ".scope")
- if !ok || !valid_session_name(session) {
- return ""
- }
-
- return SessionName(session)
-}
-
-func (cgroup _Cgroup) GetOwnerUser() UserID {
- slice := cgroup.GetSlice()
-
- uid_str, ok := trimPrefixSuffix(slice, "user-", ".slice")
- if !ok {
- return -1
- }
-
- uid, err := strconv.Atoi(uid_str)
- if err != nil {
- return -1
- }
-
- return UserID(uid)
-}
-
-// XXX: machined
-func (cgroup _Cgroup) GetMachine() MachineName {
- unit := cgroup.GetUnit()
- if unit == "" {
- return ""
- }
-
- machine, err := os.Readlink("/run/systemd/machines/unit:" + unit)
- if err != nil {
- return ""
- }
- return MachineName(machine)
-}
-
-// XXX: systemd
-func (cgroup _Cgroup) decodeUnit() string {
- unit, _ := split2(string(cgroup), '/')
- if len(unit) < 3 {
- return ""
- }
- unit = cgUnescape(unit)
- if valid_unit_name(unit)&(unit_name_plain|unit_name_instance) == 0 {
- return ""
- }
- return unit
-}
-
-func (cgroup _Cgroup) GetUnit() string {
- unit := cgroup.MaybeSkipSlices().decodeUnit()
- if strings.HasSuffix(unit, ".slice") {
- return ""
- }
- return unit
-}
-func (cgroup _Cgroup) GetUserUnit() string {
- return cgroup.MustSkipUserPrefix().GetUnit()
-}
-func (cgroup _Cgroup) GetSlice() string {
- cg := string(cgroup)
- n := 0
- for {
- cg = strings.TrimLeft(cg, "/")
- part, rest := split2(cg, '/')
- if !valid_slice_name(part) {
- if n == 0 {
- return "-.slice"
- }
- return _Cgroup(cg).decodeUnit()
- }
- cg = rest
- }
-}
-func (cgroup _Cgroup) GetUserSlice() string {
- return cgroup.MustSkipUserPrefix().GetSlice()
-}
diff --git a/sd_login/systemd_process.go b/sd_login/systemd_process.go
new file mode 100644
index 0000000..672eb2e
--- /dev/null
+++ b/sd_login/systemd_process.go
@@ -0,0 +1,171 @@
+// ./systemd_process.go.gen
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package sd_login
+
+import (
+ "net"
+ "os"
+ "strconv"
+
+ "golang.org/x/sys/unix"
+)
+
+// A ProcessID represents a process.
+type ProcessID int
+
+func (pid ProcessID) isValid() bool {
+ return pid >= 1
+}
+
+func GetPeer(conn *net.UnixConn) (ProcessID, error) {
+ ucred, err := getpeercred(conn)
+ if err != nil {
+ return -1, err
+ }
+ return ProcessID(ucred.Pid), nil
+}
+
+func (pid ProcessID) getSysCgroupLeaf() _CgroupLeaf {
+ cgroup, err := pid.getCgroup()
+ if err != nil {
+ return ""
+ }
+ cgTree, err := cgGetRootPath()
+ if err != nil {
+ return ""
+ }
+ return cgTree.Parse(cgroup)
+}
+
+func (pid ProcessID) GetSession() (v SessionName, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ vStr, ok := trimPrefixSuffix(pid.getSysCgroupLeaf().GetUnit(), "session-", ".scope")
+ _v := SessionName(vStr)
+
+ if !ok || _v.isValid() {
+ v = _v
+ } else {
+ err = unix.ENXIO
+ }
+ return
+}
+
+func (pid ProcessID) GetOwner() (v UserID, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ uidStr, ok := trimPrefixSuffix(pid.getSysCgroupLeaf().GetSlice(), "user-", ".slice")
+ if !ok {
+ err = unix.ENXIO
+ return
+ }
+ uidInt, err := strconv.Atoi(uidStr)
+ if err != nil {
+ err = unix.ENXIO
+ return
+ }
+ _v := UserID(uidInt)
+
+ if _v.isValid() {
+ v = _v
+ } else {
+ err = unix.ENXIO
+ }
+ return
+}
+
+func (pid ProcessID) GetMachine() (v MachineName, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ unit := pid.getSysCgroupLeaf().GetUnit()
+ if unit == "" {
+ err = unix.ENXIO
+ return
+ }
+ machine, err := os.Readlink("/run/systemd/machines/unit:" + unit)
+ if err != nil {
+ return
+ }
+ _v := MachineName(machine)
+
+ if _v.isValid() {
+ v = _v
+ } else {
+ err = unix.ENXIO
+ }
+ return
+}
+
+func (pid ProcessID) GetSlice() (v string, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ v = pid.getSysCgroupLeaf().GetSlice()
+ if v == "" {
+ err = unix.ENXIO
+ }
+ return
+}
+
+func (pid ProcessID) GetUnit() (v string, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ v = pid.getSysCgroupLeaf().GetUnit()
+ if v == "" {
+ err = unix.ENXIO
+ }
+ return
+}
+
+func (pid ProcessID) GetUserSlice() (v string, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ sysLeaf := pid.getSysCgroupLeaf()
+ if !valid_user_tree(sysLeaf.GetUnit()) {
+ err = unix.ENXIO
+ }
+ userLeaf := sysLeaf.GetRest()
+ v = userLeaf.GetSlice()
+
+ if v == "" {
+ err = unix.ENXIO
+ }
+ return
+}
+
+func (pid ProcessID) GetUserUnit() (v string, err error) {
+ if !pid.isValid() {
+ err = unix.EINVAL
+ return
+ }
+
+ sysLeaf := pid.getSysCgroupLeaf()
+ if !valid_user_tree(sysLeaf.GetUnit()) {
+ err = unix.ENXIO
+ }
+ userLeaf := sysLeaf.GetRest()
+ v = userLeaf.GetUnit()
+
+ if v == "" {
+ err = unix.ENXIO
+ }
+ return
+}
diff --git a/sd_login/systemd_process.go.gen b/sd_login/systemd_process.go.gen
deleted file mode 100755
index cadbfc6..0000000
--- a/sd_login/systemd_process.go.gen
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (C) 2016-2017 Luke Shumaker <lukeshu@sbcglobal.net>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- printf '//'
- printf ' %q' "$0" "$@"
- printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n'
-
- cat <<EOF
-package sd_login
-
-import (
- "net"
-
- "golang.org/x/sys/unix"
-)
-
-// A ProcessID represents a process.
-//
-// As a special case, ProcessID(0) refers to the current process.
-type ProcessID int
-
-func (pid ProcessID) isValid() bool {
- return pid >= 0
-}
-
-func GetPeer(conn *net.UnixConn) (ProcessID, error) {
- ucred, err := getpeercred(conn)
- if err != nil {
- return -1, err
- }
- return ProcessID(ucred.Pid), nil
-}
-
-EOF
-
- data=(
- 'GetSession SessionName'
- 'GetOwnerUser UserID'
- 'GetMachine MachineName'
-
- 'GetUnit string'
- 'GetUserUnit string'
- 'GetSlice string'
- 'GetUserSlice string'
- )
- for item in "${data[@]}"; do
- read Func Type <<<"$item"
- cat <<EOF
-
-func (pid ProcessID) ${Func}() (v ${Type}, err error) {
- if !pid.isValid() {
- err = unix.EINVAL
- return
- }
- cgroup, err := pid.getCgroup()
- if err != nil {
- return
- }
- return cgroup.MustSkipSystemPrefix().${Func}(), nil
-}
-EOF
- done
-} | gofmt
diff --git a/sd_login/util.go b/sd_login/util.go
index 2497aef..5a8e58d 100644
--- a/sd_login/util.go
+++ b/sd_login/util.go
@@ -19,7 +19,7 @@ import (
"os"
"path"
"strings"
-
+
"golang.org/x/sys/unix"
)
diff --git a/sd_login/util_valid.go b/sd_login/util_valid.go
index 46493b3..1837a8f 100644
--- a/sd_login/util_valid.go
+++ b/sd_login/util_valid.go
@@ -15,21 +15,23 @@
package sd_login
import (
+ "strconv"
"strings"
)
-func valid_session_name(id string) bool {
- if id == "" {
- return false
- }
-
- return strings.TrimLeft(id, letters+digits) == ""
-}
-
func valid_slice_name(s string) bool {
return strings.HasSuffix(s, ".slice") && valid_unit_name(s) == unit_name_plain
}
+func valid_user_tree(unit string) bool {
+ sessStr, sessOk := trimPrefixSuffix(unit, "session-", ".scope")
+
+ ownerStr, ownerOk := trimPrefixSuffix(unit, "user@", ".service")
+ _, ownerErr := strconv.Atoi(ownerStr)
+
+ return (sessOk && (SessionName(sessStr).isValid())) || (ownerOk && ownerErr == nil)
+}
+
func valid_filename(s string) bool {
switch s {
case "", ".", "..":