Documentation ¶
Index ¶
- Constants
- Variables
- func CheckMemoryCgroup() error
- func ConfirmSystemdAppTracking(securityTag string) error
- func ConfirmSystemdServiceTracking(securityTag string) error
- func CreateTransientScopeForTracking(securityTag string, opts *TrackingOptions) error
- func InstancePathsOfSnap(snapInstanceName string, options InstancePathsOptions) ([]string, error)
- func IsUnified() bool
- func MockFreezing(freeze func(ctx context.Context, snapName string) error, ...) (restore func())
- func MockVersion(mockVersion int, mockErr error) (restore func())
- func MonitorSnapEnded(snapName string, channel chan<- string) error
- func PidsOfSnap(snapInstanceName string) (map[string][]int, error)
- func ProcGroup(pid int, matcher GroupMatcher) (string, error)
- func ProcPidPath(pid int) string
- func ProcessPathInTrackingCgroup(pid int) (string, error)
- func SnapNameFromPid(pid int) (string, error)
- func Version() (int, error)
- type GroupMatcher
- type InstancePathsOptions
- type TrackingOptions
Constants ¶
const ( // Separate block, because iota is fun Unknown = iota V1 V2 )
Variables ¶
var ErrCannotTrackProcess = errors.New("cannot track application process")
var FreezeSnapProcesses = func(ctx context.Context, snapName string) error { return errors.New("FreezeSnapProcesses not implemented") }
FreezeSnapProcesses suspends execution of all the processes belonging to a given snap. Processes remain frozen until ThawSnapProcesses is called, care must be taken not to freezer processes indefinitely.
The freeze operation is not instant. Once commenced it proceeds asynchronously. Internally the function waits for the freezing to complete in at most maxFreezeTimeout or if the passed context is cancelled. If this time is insufficient then the processes are thawed and an error is returned.
A correct implementation is picked depending on cgroup v1 or v2 use in the system. When cgroup v1 is detected, the call will directly act on the freezer group created when a snap process was started, while with v2 the call will act on all tracking groups of a snap.
This operation can be mocked with MockFreezing
var KillSnapProcesses = func(ctx context.Context, snapName string) error { return errors.New("KillSnapProcesses not implemented") }
KillSnapProcesses sends a signal to all the processes belonging to a given snap.
A correct implementation is picked depending on cgroup v1 or v2 use in the system. For both cgroup v1 and v2, the call will act on all tracking groups of a snap.
Note: Algorithms used for killing in cgroup v1 and v2 are slightly different.
- cgroup v1: freeze/kill/thaw. This is to address multiple edge cases: (1) Hybrid v1/v2 cgroups with pids controller mounted only on v1 or v2 (Ubuntu 20.04) so we cannot guarantee having pids.max so we use the freezer cgroup instead. (2) Address a known bug on systemd v237 for non-root users where transient scopes are not created (e.g. on Ubuntu 18.04) so we use the freezer cgroup for tracking. This is only useful for killing apps or processes which do not have their lifecycle managed by external entities like systemd.
- cgroup v2: stop forking through pids.max, kill processes until cgroup is drained. This is to address kernel versions without v2 freezer support so we use pids.max to prevent fork bombs from racing with snapd.
var ThawSnapProcesses = func(snapName string) error { return errors.New("ThawSnapProcesses not implemented") }
ThawSnapProcesses resumes execution of all processes belonging to a given snap.
A correct implementation is picked depending on cgroup v1 or v2 use in the system. When cgroup v1 is detected, the call will directly act on the freezer group created when a snap process was started, while with v2 the call will act on all tracking groups of a snap.
This operation can be mocked with MockFreezing
Functions ¶
func CheckMemoryCgroup ¶
func CheckMemoryCgroup() error
CheckMemoryCgroup checks if the memory cgroup is enabled. It will return an error if not.
Since the control groups can be enabled/disabled without the kernel config the only way to identify the status of memory control groups is via /proc/cgroups "cat /proc/cgroups | grep memory" returns the active status of memory control group and the 3rd parameter is the status 0 => false => disabled 1 => true => enabled
func ConfirmSystemdAppTracking ¶
ConfirmSystemdAppTracking checks if systemd tracks this process as a snap app.
If the application process is not tracked then ErrCannotTrackProcess is returned.
func ConfirmSystemdServiceTracking ¶
ConfirmSystemdServiceTracking checks if systemd tracks this process as a snap service.
Systemd is placing started services, both user and system, into appropriate tracking groups. Given a security tag we can confirm if the current process belongs to such tracking group and thus could be identified by snapd as belonging to a particular snap and application.
If the application process is not tracked then ErrCannotTrackProcess is returned.
func CreateTransientScopeForTracking ¶
func CreateTransientScopeForTracking(securityTag string, opts *TrackingOptions) error
CreateTransientScopeForTracking puts the current process in a transient scope.
To quote systemd documentation about scope units:
>> Scopes units manage a set of system processes. Unlike service units, >> scope units manage externally created processes, and do not fork off >> processes on its own.
Scope names must be unique, a randomly generated UUID is appended to the security tag, further suffixed with the string ".scope".
func InstancePathsOfSnap ¶
func InstancePathsOfSnap(snapInstanceName string, options InstancePathsOptions) ([]string, error)
func IsUnified ¶
func IsUnified() bool
IsUnified returns true when a unified cgroup hierarchy is in use
func MockFreezing ¶
func MockFreezing(freeze func(ctx context.Context, snapName string) error, thaw func(snapName string) error) (restore func())
MockFreezing replaces the real implementation of freeze and thaw.
func MockVersion ¶
MockVersion sets the reported version of cgroup support. For use in testing only
func MonitorSnapEnded ¶
MonitorSnapEnded monitors the running instances of a snap. Once all instances of the snap have stopped, its name is pushed through the supplied channel. This allows the caller to use the same channel to monitor several snaps.
func PidsOfSnap ¶
PidsOfSnap returns the association of security tags to PIDs.
NOTE: This function returns a reliable result only if the refresh-app-awareness feature was enabled before all processes related to the given snap were started. If the feature wasn't always enabled then only service process are correctly accounted for.
The return value is a snapshot of the pids for a given snap, grouped by security tag. The result may be immediately stale as processes fork and exit.
Importantly, if the per-snap lock is held while computing the set, then the following guarantee is true: if a security tag is not among the results then no such tag can come into existence while the lock is held.
This can be used to classify the activity of a given snap into activity classes, based on the nature of the security tags encountered.
func ProcGroup ¶
func ProcGroup(pid int, matcher GroupMatcher) (string, error)
ProcGroup finds the path of a given cgroup controller for provided process id.
func ProcPidPath ¶
ProcPidPath returns the path to the cgroup file under /proc for the given process id.
func ProcessPathInTrackingCgroup ¶
ProcessPathInTrackingCgroup returns the path in the hierarchy of the tracking cgroup.
Tracking cgroup is whichever cgroup systemd uses for tracking processes. On modern systems this is the v2 cgroup. On older systems it is the controller-less name=systemd cgroup.
This function fails on systems where systemd is not used and subsequently cgroups are not mounted.
func SnapNameFromPid ¶
Types ¶
type GroupMatcher ¶
type GroupMatcher interface { String() string // Match returns true when given tuple of hierarchy-ID and controllers is a match Match(id, maybeControllers string) bool }
GroupMatcher attempts to match the cgroup entry
func MatchUnifiedHierarchy ¶
func MatchUnifiedHierarchy() GroupMatcher
MatchUnifiedHierarchy provides matches for unified cgroup hierarchies
func MatchV1Controller ¶
func MatchV1Controller(controller string) GroupMatcher
MatchV1Controller provides a matches for a given v1 controller
func MatchV1NamedHierarchy ¶
func MatchV1NamedHierarchy(hierarchyName string) GroupMatcher
MatchV1NamedHierarchy provides a matcher for a given named v1 hierarchy
type InstancePathsOptions ¶
type InstancePathsOptions struct {
ReturnCGroupPath bool
}
type TrackingOptions ¶
type TrackingOptions struct { // AllowSessionBus controls if CreateTransientScopeForTracking will // consider using the session bus for making the request. AllowSessionBus bool }
TrackingOptions control how tracking, based on systemd transient scope, operates.