From 239688180dab207bc0df8b6407be576124e5f787 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 1 Feb 2022 14:51:23 +0100 Subject: [PATCH] Fix running as root There is no need for TerminalRunner::setRunAsRoot() as debugger is already being run as root. Implement runAsRoot for non-terminal QtcProcess, too. Fixes: QTCREATORBUG-26964 Change-Id: Id5110db86b7b809a5608714464241cee73875f2b Reviewed-by: Reviewed-by: hjk --- src/libs/utils/qtcprocess.cpp | 92 ++++++++++++------- src/libs/utils/qtcprocess.h | 1 + src/libs/utils/terminalprocess.cpp | 8 -- src/libs/utils/terminalprocess_p.h | 2 - src/plugins/debugger/debuggerruncontrol.cpp | 3 - src/plugins/debugger/gdb/gdbengine.cpp | 7 +- src/plugins/debugger/terminal.cpp | 16 +--- src/plugins/debugger/terminal.h | 2 - .../projectexplorer/applicationlauncher.cpp | 8 +- 9 files changed, 62 insertions(+), 77 deletions(-) diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 04561a5af8b..7bd1891efa8 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -263,9 +263,6 @@ public: void setAbortOnMetaChars(bool abort) { m_abortOnMetaChars = abort; } bool isAbortOnMetaChars() const { return m_abortOnMetaChars; } - void setRunAsRoot(bool on) { m_runAsRoot = on; } - bool runAsRoot() const { return m_runAsRoot; } - void setBelowNormalPriority() { m_belowNormalPriority = true; } bool isBelowNormalPriority() const { return m_belowNormalPriority; } void setNativeArguments(const QString &arguments) { m_nativeArguments = arguments; } @@ -287,7 +284,6 @@ private: bool m_lowPriority = false; bool m_unixTerminalDisabled = false; bool m_abortOnMetaChars = true; - bool m_runAsRoot = false; }; class TerminalImpl : public ProcessInterface @@ -319,7 +315,6 @@ public: void customStart(const CommandLine &command, const FilePath &workingDirectory, const Environment &environment) override { - m_terminal.setRunAsRoot(runAsRoot()); m_terminal.setAbortOnMetaChars(isAbortOnMetaChars()); m_terminal.setCommand(command); m_terminal.setWorkingDirectory(workingDirectory); @@ -606,11 +601,10 @@ public: return filePath.searchInPath(); } - void defaultStart() + void defaultStart(const CommandLine &commandLine, const FilePath &workingDirectory, + const Environment &environment) { - clearForRun(); - - if (m_commandLine.executable().needsDevice()) { + if (commandLine.executable().needsDevice()) { QTC_ASSERT(s_deviceHooks.startProcessHook, return); s_deviceHooks.startProcessHook(*q); return; @@ -618,33 +612,24 @@ public: if (processLog().isDebugEnabled()) { static int n = 0; - qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << m_commandLine.toUserOutput(); + qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << commandLine.toUserOutput(); } - Environment env; - if (m_haveEnv) { - if (m_environment.size() == 0) - qWarning("QtcProcess::start: Empty environment set when running '%s'.", - qPrintable(m_commandLine.executable().toString())); - env = m_environment; - } else { - env = Environment::systemEnvironment(); - } - m_process->setProcessEnvironment(env.toProcessEnvironment()); - m_process->setWorkingDirectory(m_workingDirectory.path()); + m_process->setProcessEnvironment(environment.toProcessEnvironment()); + m_process->setWorkingDirectory(workingDirectory.path()); - QString command; + QString commandString; ProcessArgs arguments; - const bool success = ProcessArgs::prepareCommand(m_commandLine, &command, &arguments, &env, - &m_workingDirectory); + const bool success = ProcessArgs::prepareCommand(commandLine, &commandString, &arguments, + &environment, &workingDirectory); - if (m_commandLine.executable().osType() == OsTypeWindows) { + if (commandLine.executable().osType() == OsTypeWindows) { QString args; if (m_useCtrlCStub) { if (m_process->isLowPriority()) ProcessArgs::addArg(&args, "-nice"); - ProcessArgs::addArg(&args, QDir::toNativeSeparators(command)); - command = QCoreApplication::applicationDirPath() + ProcessArgs::addArg(&args, QDir::toNativeSeparators(commandString)); + commandString = QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_ctrlc_stub.exe"); } else if (m_process->isLowPriority()) { m_process->setBelowNormalPriority(); @@ -655,7 +640,7 @@ public: #endif // Note: Arguments set with setNativeArgs will be appended to the ones // passed with start() below. - start(command, QStringList(), m_writeData); + start(commandString, QStringList(), workingDirectory, m_writeData); } else { if (!success) { q->setErrorString(tr("Error in command line.")); @@ -664,13 +649,14 @@ public: emit q->errorOccurred(QProcess::UnknownError); return; } - start(command, arguments.toUnixArgs(), m_writeData); + start(commandString, arguments.toUnixArgs(), workingDirectory, m_writeData); } } - void start(const QString &program, const QStringList &arguments, const QByteArray &writeData) + void start(const QString &program, const QStringList &arguments, + const FilePath &workingDirectory, const QByteArray &writeData) { - const FilePath programFilePath = resolve(m_workingDirectory, FilePath::fromString(program)); + const FilePath programFilePath = resolve(workingDirectory, FilePath::fromString(program)); if (programFilePath.exists() && programFilePath.isExecutableFile()) { s_start.measureAndRun(&ProcessInterface::start, m_process, program, arguments, writeData); } else { @@ -680,6 +666,33 @@ public: } } + CommandLine fullCommandLine() const + { + if (!m_runAsRoot || HostOsInfo::isWindowsHost()) + return m_commandLine; + CommandLine rootCommand("sudo", {"-A"}); + rootCommand.addCommandLineAsArgs(m_commandLine); + return rootCommand; + } + + Environment fullEnvironment() const + { + Environment env; + if (m_haveEnv) { + if (m_environment.size() == 0) + qWarning("QtcProcess::start: Empty environment set when running '%s'.", + qPrintable(m_commandLine.executable().toString())); + env = m_environment; + } else { + env = Environment::systemEnvironment(); + } + +// TODO: needs SshSettings +// if (m_runAsRoot) +// RunControl::provideAskPassEntry(env); + return env; + } + QtcProcess *q; ProcessInterface *m_process; const ProcessMode m_processMode; @@ -687,6 +700,7 @@ public: FilePath m_workingDirectory; Environment m_environment; QByteArray m_writeData; + bool m_runAsRoot = false; bool m_haveEnv = false; bool m_useCtrlCStub = false; @@ -796,7 +810,7 @@ void QtcProcess::setCommand(const CommandLine &cmdLine) if (d->m_workingDirectory.needsDevice() && cmdLine.executable().needsDevice()) { QTC_CHECK(d->m_workingDirectory.host() == cmdLine.executable().host()); } - d->m_commandLine = cmdLine; + d->m_commandLine = cmdLine; } const CommandLine &QtcProcess::commandLine() const @@ -831,10 +845,13 @@ void QtcProcess::setUseCtrlCStub(bool enabled) void QtcProcess::start() { + d->clearForRun(); + const CommandLine cmd = d->fullCommandLine(); + const Environment env = d->fullEnvironment(); if (d->m_process->isCustomStart()) - d->m_process->customStart(d->m_commandLine, d->m_workingDirectory, d->m_environment); + d->m_process->customStart(cmd, d->m_workingDirectory, env); else - d->defaultStart(); + d->defaultStart(cmd, d->m_workingDirectory, env); } #ifdef Q_OS_WIN @@ -905,7 +922,12 @@ void QtcProcess::setAbortOnMetaChars(bool abort) void QtcProcess::setRunAsRoot(bool on) { - d->m_process->setRunAsRoot(on); + d->m_runAsRoot = on; +} + +bool QtcProcess::isRunAsRoot() const +{ + return d->m_runAsRoot; } void QtcProcess::setStandardInputFile(const QString &inputFile) diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index eb2bff71331..d64991f759b 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -122,6 +122,7 @@ public: void setLowPriority(); void setDisableUnixTerminal(); void setRunAsRoot(bool on); + bool isRunAsRoot() const; void setAbortOnMetaChars(bool abort); diff --git a/src/libs/utils/terminalprocess.cpp b/src/libs/utils/terminalprocess.cpp index a12107e1715..f24b6aaf952 100644 --- a/src/libs/utils/terminalprocess.cpp +++ b/src/libs/utils/terminalprocess.cpp @@ -142,7 +142,6 @@ public: QProcess::ProcessError m_error = QProcess::UnknownError; QString m_errorString; bool m_abortOnMetaChars = true; - bool m_runAsRoot = false; // Used on Unix only QtcProcess m_process; @@ -431,8 +430,6 @@ void TerminalProcess::start() + QLatin1String("/" RELATIVE_LIBEXEC_PATH "/qtcreator_process_stub"); QStringList allArgs = terminalArgs.toUnixArgs(); - if (d->m_runAsRoot) - allArgs << "sudo" << "-A"; allArgs << stubPath << modeOption(d->m_terminalMode) @@ -797,11 +794,6 @@ const Environment &TerminalProcess::environment() const return d->m_environment; } -void TerminalProcess::setRunAsRoot(bool on) -{ - d->m_runAsRoot = on; -} - QProcess::ProcessError TerminalProcess::error() const { return d->m_error; diff --git a/src/libs/utils/terminalprocess_p.h b/src/libs/utils/terminalprocess_p.h index 006b3c3d8a0..0fb2006049e 100644 --- a/src/libs/utils/terminalprocess_p.h +++ b/src/libs/utils/terminalprocess_p.h @@ -52,8 +52,6 @@ public: void setEnvironment(const Environment &env); const Environment &environment() const; - void setRunAsRoot(bool on); - QProcess::ProcessError error() const; QString errorString() const; diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 736acadaf0e..ca638e41036 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -316,7 +316,6 @@ void DebuggerRunTool::setUseTerminal(bool on) if (on && !d->terminalRunner && !useCdbConsole) { d->terminalRunner = new TerminalRunner(runControl(), [this] { return m_runParameters.inferior; }); - d->terminalRunner->setRunAsRoot(m_runParameters.runAsRoot); addStartDependency(d->terminalRunner); } if (!on && d->terminalRunner) { @@ -327,8 +326,6 @@ void DebuggerRunTool::setUseTerminal(bool on) void DebuggerRunTool::setRunAsRoot(bool on) { m_runParameters.runAsRoot = on; - if (d->terminalRunner) - d->terminalRunner->setRunAsRoot(on); } void DebuggerRunTool::setCommandsAfterConnect(const QString &commands) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 811f8d42e4e..6a644892fea 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3852,12 +3852,9 @@ void GdbEngine::setupEngine() Environment gdbEnv = rp.debugger.environment; gdbEnv.setupEnglishOutput(); - if (rp.runAsRoot) { - CommandLine wrapped("sudo", {"-A"}); - wrapped.addCommandLineAsArgs(gdbCommand); - gdbCommand = wrapped; + if (rp.runAsRoot) RunControl::provideAskPassEntry(gdbEnv); - } + m_gdbProc.setRunAsRoot(rp.runAsRoot); showMessage("STARTING " + gdbCommand.toUserOutput()); diff --git a/src/plugins/debugger/terminal.cpp b/src/plugins/debugger/terminal.cpp index 1856e7620b0..fc1d228d787 100644 --- a/src/plugins/debugger/terminal.cpp +++ b/src/plugins/debugger/terminal.cpp @@ -188,11 +188,6 @@ void TerminalRunner::interruptProcess() m_stubProc->interruptProcess(); } -void TerminalRunner::setRunAsRoot(bool on) -{ - m_runAsRoot = on; -} - void TerminalRunner::start() { QTC_ASSERT(m_stubRunnable, reportFailure({}); return); @@ -209,20 +204,11 @@ void TerminalRunner::start() connect(m_stubProc, &QtcProcess::finished, this, &TerminalRunner::reportDone); - CommandLine commandLine = stub.command; - if (m_runAsRoot) { // TODO: fix me - m_stubProc->setRunAsRoot(true); -// CommandLine wrapped("sudo", {"-A"}); -// wrapped.addCommandLineAsArgs(commandLine); -// commandLine = wrapped; - RunControl::provideAskPassEntry(stub.environment); - } - m_stubProc->setEnvironment(stub.environment); m_stubProc->setWorkingDirectory(stub.workingDirectory); // Error message for user is delivered via a signal. - m_stubProc->setCommand(commandLine); + m_stubProc->setCommand(stub.command); m_stubProc->start(); } diff --git a/src/plugins/debugger/terminal.h b/src/plugins/debugger/terminal.h index 4d3679f31ab..2227bdbce4b 100644 --- a/src/plugins/debugger/terminal.h +++ b/src/plugins/debugger/terminal.h @@ -79,7 +79,6 @@ public: void kickoffProcess(); void interruptProcess(); - void setRunAsRoot(bool on); private: void start() final; @@ -92,7 +91,6 @@ private: std::function m_stubRunnable; qint64 m_applicationPid = 0; qint64 m_applicationMainThreadId = 0; - bool m_runAsRoot = false; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp index b3dfc5a2161..ea9dbd4a059 100644 --- a/src/plugins/projectexplorer/applicationlauncher.cpp +++ b/src/plugins/projectexplorer/applicationlauncher.cpp @@ -381,13 +381,7 @@ void ApplicationLauncherPrivate::start(const Runnable &runnable, const IDevice:: cmdLine = disclaim; } - if (m_runAsRoot) { - CommandLine wrapped("sudo", {"-A"}); - wrapped.addCommandLineAsArgs(cmdLine); - cmdLine = wrapped; - } - // TODO: QtcProcess::setRunAsRoot() doens't work as expected currently - // m_localProcess->setRunAsRoot(m_runAsRoot); + m_localProcess->setRunAsRoot(m_runAsRoot); m_localProcess->setCommand(cmdLine); m_localProcess->start(); } else {