diff --git a/CHANGELOG.md b/CHANGELOG.md index f248d42c..b260d138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,14 @@ NOTE: Add new changes BELOW THIS COMMENT. - The release executables are now signed. +### Added + +- The `--no-permcheck` command-line option to disable checking and migration of + permissions for the security-sensitive files and directories, which caused + issues on Windows ([#7400]). + +[#7400]: https://github.com/AdguardTeam/AdGuardHome/issues/7400 + [go-1.23.3]: https://groups.google.com/g/golang-announce/c/X5KodEJYuqI <!-- diff --git a/internal/home/home.go b/internal/home/home.go index 4c2771e4..34620e2c 100644 --- a/internal/home/home.go +++ b/internal/home/home.go @@ -159,7 +159,7 @@ func setupContext(opts options) (err error) { if Context.firstRun { log.Info("This is the first time AdGuard Home is launched") - checkPermissions() + checkNetworkPermissions() return nil } @@ -686,18 +686,26 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) { } } - if permcheck.NeedsMigration(confPath) { - permcheck.Migrate(Context.workDir, dataDir, statsDir, querylogDir, confPath) + if !opts.noPermCheck { + checkPermissions(Context.workDir, confPath, dataDir, statsDir, querylogDir) } - permcheck.Check(Context.workDir, dataDir, statsDir, querylogDir, confPath) - Context.web.start() // Wait for other goroutines to complete their job. <-done } +// checkPermissions checks and migrates permissions of the files and directories +// used by AdGuard Home, if needed. +func checkPermissions(workDir, confPath, dataDir, statsDir, querylogDir string) { + if permcheck.NeedsMigration(confPath) { + permcheck.Migrate(workDir, dataDir, statsDir, querylogDir, confPath) + } + + permcheck.Check(workDir, dataDir, statsDir, querylogDir, confPath) +} + // initUsers initializes context auth module. Clears config users field. func initUsers() (auth *Auth, err error) { sessFilename := filepath.Join(Context.getDataDir(), "sessions.db") @@ -757,8 +765,9 @@ func startMods(l *slog.Logger) (err error) { return nil } -// Check if the current user permissions are enough to run AdGuard Home -func checkPermissions() { +// checkNetworkPermissions checks if the current user permissions are enough to +// use the required networking functionality. +func checkNetworkPermissions() { log.Info("Checking if AdGuard Home has necessary permissions") if ok, err := aghnet.CanBindPrivilegedPorts(); !ok || err != nil { diff --git a/internal/home/options.go b/internal/home/options.go index 35f26303..dd7e53e4 100644 --- a/internal/home/options.go +++ b/internal/home/options.go @@ -78,6 +78,10 @@ type options struct { // localFrontend forces AdGuard Home to use the frontend files from disk // rather than the ones that have been compiled into the binary. localFrontend bool + + // noPermCheck disables checking and migration of permissions for the + // security-sensitive files. + noPermCheck bool } // initCmdLineOpts completes initialization of the global command-line option @@ -305,6 +309,15 @@ var cmdLineOpts = []cmdLineOpt{{ description: "Run in GL-Inet compatibility mode.", longName: "glinet", shortName: "", +}, { + updateWithValue: nil, + updateNoValue: func(o options) (options, error) { o.noPermCheck = true; return o, nil }, + effect: nil, + serialize: func(o options) (val string, ok bool) { return "", o.noPermCheck }, + description: "Skip checking and migration of permissions " + + "of security-sensitive files.", + longName: "no-permcheck", + shortName: "", }, { updateWithValue: nil, updateNoValue: nil, diff --git a/internal/next/cmd/opt.go b/internal/next/cmd/opt.go index 8e06a492..b565b9fc 100644 --- a/internal/next/cmd/opt.go +++ b/internal/next/cmd/opt.go @@ -89,6 +89,12 @@ type options struct { // TODO(a.garipov): Use. performUpdate bool + // noPermCheck, if true, instructs AdGuard Home to skip checking and + // migrating the permissions of its security-sensitive files. + // + // TODO(e.burkov): Use. + noPermCheck bool + // verbose, if true, instructs AdGuard Home to enable verbose logging. verbose bool @@ -110,7 +116,8 @@ const ( disableUpdateIdx glinetModeIdx helpIdx - localFrontend + localFrontendIdx + noPermCheckIdx performUpdateIdx verboseIdx versionIdx @@ -214,7 +221,7 @@ var commandLineOptions = []*commandLineOption{ valueType: "", }, - localFrontend: { + localFrontendIdx: { defaultValue: false, description: "Use local frontend directories.", long: "local-frontend", @@ -222,6 +229,14 @@ var commandLineOptions = []*commandLineOption{ valueType: "", }, + noPermCheckIdx: { + defaultValue: false, + description: "Skip checking the permissions of security-sensitive files.", + long: "no-permcheck", + short: "", + valueType: "", + }, + performUpdateIdx: { defaultValue: false, description: "Update the current binary and restart the service in case it's installed.", @@ -264,7 +279,8 @@ func parseOptions(cmdName string, args []string) (opts *options, err error) { disableUpdateIdx: &opts.disableUpdate, glinetModeIdx: &opts.glinetMode, helpIdx: &opts.help, - localFrontend: &opts.localFrontend, + localFrontendIdx: &opts.localFrontend, + noPermCheckIdx: &opts.noPermCheck, performUpdateIdx: &opts.performUpdate, verboseIdx: &opts.verbose, versionIdx: &opts.version,