inspektor-gadget
84 строки · 2.4 Кб
1//go:build linux
2// +build linux
3
4// Copyright 2023 The Inspektor Gadget authors
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18// Package host provides ways to access the host filesystem.
19//
20// Inspektor Gadget can run either in the host or in a container. When running
21// in a container, the host filesystem must be available in a specific
22// directory.
23package host
24
25import (
26"fmt"
27"os"
28"sync"
29"syscall"
30)
31
32var (
33onceHostPidNs sync.Once
34isHostPidNs bool
35errHostPidNs error
36
37onceHostNetNs sync.Once
38isHostNetNs bool
39errHostNetNs error
40)
41
42// IsHostPidNs returns true if the current process is running in the host PID namespace
43func IsHostPidNs() (bool, error) {
44onceHostPidNs.Do(func() {
45isHostPidNs, errHostPidNs = isHostNamespace("pid")
46})
47return isHostPidNs, errHostPidNs
48}
49
50// IsHostNetNs returns true if the current process is running in the host network namespace
51func IsHostNetNs() (bool, error) {
52onceHostNetNs.Do(func() {
53isHostNetNs, errHostNetNs = isHostNamespace("net")
54})
55return isHostNetNs, errHostNetNs
56}
57
58// isHostNamespace checks if the current process is running in the specified host namespace
59func isHostNamespace(nsKind string) (bool, error) {
60if !initDone {
61// HostProcFs can be overwritten by workarounds, so Init() must be called first.
62return false, fmt.Errorf("host.Init() must be called before calling isHostNamespace()")
63}
64
65selfFileInfo, err := os.Stat("/proc/self/ns/" + nsKind)
66if err != nil {
67return false, err
68}
69selfStat, ok := selfFileInfo.Sys().(*syscall.Stat_t)
70if !ok {
71return false, fmt.Errorf("reading inode of /proc/self/ns/%s", nsKind)
72}
73
74systemdFileInfo, err := os.Stat(fmt.Sprintf("%s/1/ns/%s", HostProcFs, nsKind))
75if err != nil {
76return false, err
77}
78systemdStat, ok := systemdFileInfo.Sys().(*syscall.Stat_t)
79if !ok {
80return false, fmt.Errorf("reading inode of %s/1/ns/%s", HostProcFs, nsKind)
81}
82
83return selfStat.Ino == systemdStat.Ino, nil
84}
85