From 7d6018638ec7de5398b67c614c78a9952c1c36a6 Mon Sep 17 00:00:00 2001 From: maximilionus Date: Tue, 22 Jul 2025 23:50:47 +0300 Subject: [PATCH] Robust privilege elevation on Unix platform This improves the elevation on Linux/macOS platforms, that now will work in 100% of the calls. Fixes the periodical tunnel start/stop problems. And also a few sudo call enhancements: - '-k' clears the credentials for current session, will require the password input on the next call. - '-p' removes the password prompt. - '--' mark the end of command options in Unix style. --- v2rayN/ServiceLib/Handler/CoreAdminHandler.cs | 70 ++++++------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/CoreAdminHandler.cs b/v2rayN/ServiceLib/Handler/CoreAdminHandler.cs index 7fd07262..85830fa1 100644 --- a/v2rayN/ServiceLib/Handler/CoreAdminHandler.cs +++ b/v2rayN/ServiceLib/Handler/CoreAdminHandler.cs @@ -32,57 +32,31 @@ public class CoreAdminHandler var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}"; var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh"); - Process proc = new() - { - StartInfo = new() - { - FileName = shFilePath, - Arguments = "", - WorkingDirectory = Utils.GetBinConfigPath(), - UseShellExecute = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - StandardInputEncoding = Encoding.UTF8, - StandardOutputEncoding = Encoding.UTF8, - StandardErrorEncoding = Encoding.UTF8, - } - }; + var cmdTask = Cli.Wrap(shFilePath) + .WithWorkingDirectory(Utils.GetBinConfigPath()) + .WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd)) + .WithStandardOutputPipe(PipeTarget.ToDelegate( + s => + { + if (!string.IsNullOrEmpty(s)) + UpdateFunc(false, s + Environment.NewLine); + })) + .WithStandardErrorPipe(PipeTarget.ToDelegate( + s => + { + if (!string.IsNullOrEmpty(s)) + UpdateFunc(false, s + Environment.NewLine); + })) + .WithValidation(CommandResultValidation.None) + .ExecuteAsync(); - proc.OutputDataReceived += (sender, e) => - { - if (e.Data.IsNotEmpty()) - { - UpdateFunc(false, e.Data + Environment.NewLine); - } - }; - proc.ErrorDataReceived += (sender, e) => - { - if (e.Data.IsNotEmpty()) - { - UpdateFunc(false, e.Data + Environment.NewLine); - } - }; - - proc.Start(); - proc.BeginOutputReadLine(); - proc.BeginErrorReadLine(); - - await Task.Delay(10); - await proc.StandardInput.WriteLineAsync(); - await Task.Delay(10); - await proc.StandardInput.WriteLineAsync(AppHandler.Instance.LinuxSudoPwd); - - await Task.Delay(100); - if (proc is null or { HasExited: true }) - { + Task.Delay(100) + if (cmdTask.ProcessId is null) throw new Exception(ResUI.FailedToRunCore); - } - _linuxSudoPid = proc.Id; + _linuxSudoPid = cmdTask.ProcessId; - return proc; + return Process.GetProcessById(_linuxSudoPid); } public async Task KillProcessAsLinuxSudo() @@ -115,7 +89,7 @@ public class CoreAdminHandler } else { - sb.AppendLine($"sudo -S {cmdLine}"); + sb.AppendLine($"sudo -S -k -p '' -- {cmdLine}"); } await File.WriteAllTextAsync(shFilePath, sb.ToString());