@@ -4,8 +4,10 @@ import (
44 "compress/gzip"
55 "context"
66 "errors"
7+ "fmt"
78 "github.com/go-chi/chi/v5"
89 "github.com/go-chi/chi/v5/middleware"
10+ "github.com/landlock-lsm/go-landlock/landlock"
911 "github.com/ngergs/websrv/v3/internal/utils"
1012 "github.com/prometheus/client_golang/prometheus"
1113 "io/fs"
@@ -34,6 +36,9 @@ func main() {
3436 if err = setup (conf ); err != nil {
3537 log .Fatal ().Err (err ).Msg ("Error during initialization" )
3638 }
39+ if err := setupLandlock (conf ); err != nil {
40+ log .Fatal ().Err (err ).Msg ("" )
41+ }
3742 var wg sync.WaitGroup
3843 sigtermCtx := server .SigTermCtx (context .Background (), time .Duration (conf .ShutdownDelay )* time .Second )
3944 unzipfs , zipfs := initFs (conf )
@@ -170,3 +175,29 @@ func logErrors(errChan <-chan error) {
170175 }
171176 }
172177}
178+
179+ // setupLandlock activates the linux landlock sandbox features on an best effort basis
180+ func setupLandlock (conf * config ) error {
181+ llConf := landlock .V4 .BestEffort ()
182+ if err := llConf .RestrictPaths (landlock .RODirs (targetDir )); err != nil {
183+ return fmt .Errorf ("error during landlock filesystem setup: %w" , err )
184+ }
185+ ports := []uint16 {conf .Port .Webserver }
186+ if conf .Health {
187+ ports = append (ports , conf .Port .Health )
188+ }
189+ if conf .H2C {
190+ ports = append (ports , conf .Port .H2c )
191+ }
192+ if conf .Metrics .Enabled {
193+ ports = append (ports , conf .Port .Metrics )
194+ }
195+ portRules := make ([]landlock.Rule , len (ports ))
196+ for i , port := range ports {
197+ portRules [i ] = landlock .BindTCP (port )
198+ }
199+ if err := llConf .RestrictNet (portRules ... ); err != nil {
200+ return fmt .Errorf ("error during landlock network setup: %w" , err )
201+ }
202+ return nil
203+ }
0 commit comments