hst: improve doc comments
All checks were successful
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 2m40s
Test / Hakurei (push) Successful in 3m40s
Test / ShareFS (push) Successful in 3m47s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 5m58s
Test / Flake checks (push) Successful in 1m26s
All checks were successful
Test / Create distribution (push) Successful in 1m3s
Test / Sandbox (push) Successful in 2m40s
Test / Hakurei (push) Successful in 3m40s
Test / ShareFS (push) Successful in 3m47s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 5m58s
Test / Flake checks (push) Successful in 1m26s
These now read a lot better both in source and on pkgsite. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
122
hst/config.go
122
hst/config.go
@@ -8,74 +8,97 @@ import (
|
||||
"hakurei.app/container/check"
|
||||
)
|
||||
|
||||
// Config configures an application container, implemented in internal/app.
|
||||
// Config configures an application container.
|
||||
type Config struct {
|
||||
// Reverse-DNS style configured arbitrary identifier string.
|
||||
// Passed to wayland security-context-v1 and used as part of defaults in dbus session proxy.
|
||||
//
|
||||
// This value is passed as is to Wayland security-context-v1 and used as
|
||||
// part of defaults in D-Bus session proxy. The zero value causes a default
|
||||
// value to be derived from the container instance.
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
// System services to make available in the container.
|
||||
Enablements *Enablements `json:"enablements,omitempty"`
|
||||
|
||||
// Session D-Bus proxy configuration.
|
||||
// If set to nil, session bus proxy assume built-in defaults.
|
||||
//
|
||||
// Has no effect if [EDBus] but is not set in Enablements. The zero value
|
||||
// assumes built-in defaults derived from ID.
|
||||
SessionBus *BusConfig `json:"session_bus,omitempty"`
|
||||
// System D-Bus proxy configuration.
|
||||
// If set to nil, system bus proxy is disabled.
|
||||
//
|
||||
// Has no effect if [EDBus] but is not set in Enablements. The zero value
|
||||
// disables system bus proxy.
|
||||
SystemBus *BusConfig `json:"system_bus,omitempty"`
|
||||
|
||||
// Direct access to wayland socket, no attempt is made to attach security-context-v1
|
||||
// and the bare socket is made available to the container.
|
||||
// Direct access to Wayland socket, no attempt is made to attach
|
||||
// security-context-v1 and the bare socket is made available to the
|
||||
// container.
|
||||
//
|
||||
// This option is unsupported and most likely enables full control over the Wayland
|
||||
// session. Do not set this to true unless you are sure you know what you are doing.
|
||||
// This option is unsupported and will most likely enable full control over
|
||||
// the Wayland session from within the container. Do not set this to true
|
||||
// unless you are sure you know what you are doing.
|
||||
DirectWayland bool `json:"direct_wayland,omitempty"`
|
||||
// Direct access to the PipeWire socket established via SecurityContext::Create, no
|
||||
// attempt is made to start the pipewire-pulse server.
|
||||
|
||||
// Direct access to the PipeWire socket established via SecurityContext::Create,
|
||||
// no attempt is made to start the pipewire-pulse server.
|
||||
//
|
||||
// The SecurityContext machinery is fatally flawed, it blindly sets read and execute
|
||||
// bits on all objects for clients with the lowest achievable privilege level (by
|
||||
// setting PW_KEY_ACCESS to "restricted"). This enables them to call any method
|
||||
// targeting any object, and since Registry::Destroy checks for the read and execute bit,
|
||||
// allows the destruction of any object other than PW_ID_CORE as well. This behaviour
|
||||
// is implemented separately in media-session and wireplumber, with the wireplumber
|
||||
// implementation in Lua via an embedded Lua vm. In all known setups, wireplumber is
|
||||
// in use, and there is no known way to change its behaviour and set permissions
|
||||
// differently without replacing the Lua script. Also, since PipeWire relies on these
|
||||
// permissions to work, reducing them is not possible.
|
||||
// The SecurityContext machinery is fatally flawed, it unconditionally sets
|
||||
// read and execute bits on all objects for clients with the lowest achievable
|
||||
// privilege level (by setting PW_KEY_ACCESS to "restricted" or by satisfying
|
||||
// all conditions of [the /.flatpak-info hack]). This enables them to call
|
||||
// any method targeting any object, and since Registry::Destroy checks for
|
||||
// the read and execute bit, allows the destruction of any object other than
|
||||
// PW_ID_CORE as well.
|
||||
//
|
||||
// Currently, the only other sandboxed use case is flatpak, which is not aware of
|
||||
// PipeWire and blindly exposes the bare PulseAudio socket to the container (behaves
|
||||
// like DirectPulse). This socket is backed by the pipewire-pulse compatibility daemon,
|
||||
// which obtains client pid via the SO_PEERCRED option. The PipeWire daemon, pipewire-pulse
|
||||
// daemon and the session manager daemon then separately performs the /.flatpak-info hack
|
||||
// described in https://git.gensokyo.uk/security/hakurei/issues/21. Under such use case,
|
||||
// since the client has no direct access to PipeWire, insecure parts of the protocol are
|
||||
// obscured by pipewire-pulse simply not implementing them, and thus hiding the flaws
|
||||
// described above.
|
||||
// This behaviour is implemented separately in media-session and wireplumber,
|
||||
// with the wireplumber implementation in Lua via an embedded Lua vm. In all
|
||||
// known setups, wireplumber is in use, and in that case, no option for
|
||||
// configuring this behaviour exists, without replacing the Lua script.
|
||||
// Also, since PipeWire relies on these permissions to work, reducing them
|
||||
// was never possible in the first place.
|
||||
//
|
||||
// Hakurei does not rely on the /.flatpak-info hack. Instead, a socket is sets up via
|
||||
// SecurityContext. A pipewire-pulse server connected through it achieves the same
|
||||
// permissions as flatpak does via the /.flatpak-info hack and is maintained for the
|
||||
// life of the container.
|
||||
// Currently, the only other sandboxed use case is flatpak, which is not
|
||||
// aware of PipeWire and blindly exposes the bare PulseAudio socket to the
|
||||
// container (behaves like DirectPulse). This socket is backed by the
|
||||
// pipewire-pulse compatibility daemon, which obtains client pid via the
|
||||
// SO_PEERCRED option. The PipeWire daemon, pipewire-pulse daemon and the
|
||||
// session manager daemon then separately performs [the /.flatpak-info hack].
|
||||
// Under such use case, since the client has no direct access to PipeWire,
|
||||
// insecure parts of the protocol are obscured by the absence of an
|
||||
// equivalent API in PulseAudio, or pipewire-pulse simply not implementing
|
||||
// them.
|
||||
//
|
||||
// Hakurei does not rely on [the /.flatpak-info hack]. Instead, a socket is
|
||||
// sets up via SecurityContext. A pipewire-pulse server connected through it
|
||||
// achieves the same permissions as flatpak does via [the /.flatpak-info hack]
|
||||
// and is maintained for the life of the container.
|
||||
//
|
||||
// This option is unsupported and enables a denial-of-service attack as the
|
||||
// sandboxed client is able to destroy any client object and thus
|
||||
// disconnecting them from PipeWire, or destroy the SecurityContext object,
|
||||
// preventing any further container creation.
|
||||
//
|
||||
// This option is unsupported and enables a denial-of-service attack as the sandboxed
|
||||
// client is able to destroy any client object and thus disconnecting them from PipeWire,
|
||||
// or destroy the SecurityContext object preventing any further container creation.
|
||||
// Do not set this to true, it is insecure under any configuration.
|
||||
DirectPipeWire bool `json:"direct_pipewire,omitempty"`
|
||||
// Direct access to PulseAudio socket, no attempt is made to establish pipewire-pulse
|
||||
// server via a PipeWire socket with a SecurityContext attached and the bare socket
|
||||
// is made available to the container.
|
||||
//
|
||||
// This option is unsupported and enables arbitrary code execution as the PulseAudio
|
||||
// server. Do not set this to true, it is insecure under any configuration.
|
||||
// [the /.flatpak-info hack]: https://git.gensokyo.uk/security/hakurei/issues/21
|
||||
DirectPipeWire bool `json:"direct_pipewire,omitempty"`
|
||||
|
||||
// Direct access to PulseAudio socket, no attempt is made to establish
|
||||
// pipewire-pulse server via a PipeWire socket with a SecurityContext
|
||||
// attached, and the bare socket is made available to the container.
|
||||
//
|
||||
// This option is unsupported and enables arbitrary code execution as the
|
||||
// PulseAudio server.
|
||||
//
|
||||
// Do not set this to true, it is insecure under any configuration.
|
||||
DirectPulse bool `json:"direct_pulse,omitempty"`
|
||||
|
||||
// Extra acl updates to perform before setuid.
|
||||
ExtraPerms []ExtraPermConfig `json:"extra_perms,omitempty"`
|
||||
|
||||
// Numerical application id, passed to hsu, used to derive init user namespace credentials.
|
||||
// Numerical application id, passed to hsu, used to derive init user
|
||||
// namespace credentials.
|
||||
Identity int `json:"identity"`
|
||||
// Init user namespace supplementary groups inherited by all container processes.
|
||||
Groups []string `json:"groups"`
|
||||
@@ -85,17 +108,20 @@ type Config struct {
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrConfigNull is returned by [Config.Validate] for an invalid configuration that contains a null value for any
|
||||
// field that must not be null.
|
||||
// ErrConfigNull is returned by [Config.Validate] for an invalid configuration
|
||||
// that contains a null value for any field that must not be null.
|
||||
ErrConfigNull = errors.New("unexpected null in config")
|
||||
|
||||
// ErrIdentityBounds is returned by [Config.Validate] for an out of bounds [Config.Identity] value.
|
||||
// ErrIdentityBounds is returned by [Config.Validate] for an out of bounds
|
||||
// [Config.Identity] value.
|
||||
ErrIdentityBounds = errors.New("identity out of bounds")
|
||||
|
||||
// ErrEnviron is returned by [Config.Validate] if an environment variable name contains '=' or NUL.
|
||||
// ErrEnviron is returned by [Config.Validate] if an environment variable
|
||||
// name contains '=' or NUL.
|
||||
ErrEnviron = errors.New("invalid environment variable name")
|
||||
|
||||
// ErrInsecure is returned by [Config.Validate] if the configuration is considered insecure.
|
||||
// ErrInsecure is returned by [Config.Validate] if the configuration is
|
||||
// considered insecure.
|
||||
ErrInsecure = errors.New("configuration is insecure")
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user