summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2023-05-11 12:39:01 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2023-05-22 13:53:32 +0000
commit8d72fb0c76db430488066b579fe787caf3889895 (patch)
treed07442a6716f8001bc4bc4fbe1c44a307cebee82 /src
parent2c12d1ce130be0e86dea7576d6d7841938695e11 (diff)
Fix admin rights handling during installer/updater/uninstaller runs
The installer.gainAdminRights() and installer.dropAdminRights() methods are invokable from the scripting API. During installing, updating or uninstalling components, installer does it's own decision making to request and drop admin rights on-demand, but this could be overridden with the aforementioned methods. This was not taken into account, instead it was only checked if admin rights were gained in the context of the calling method. Fix by checking if the admin rights were present at the start of the installer, or if they were requested by anyone during installation. Task-number: QTIFW-2929 Change-Id: Ie4f6fc0ac746183b00f460a2e60c57c2eae9808c Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/libs/installer/createdesktopentryoperation.cpp5
-rw-r--r--src/libs/installer/extractarchiveoperation.cpp4
-rw-r--r--src/libs/installer/installiconsoperation.cpp4
-rw-r--r--src/libs/installer/packagemanagercore.cpp15
-rw-r--r--src/libs/installer/packagemanagercore.h1
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp41
-rw-r--r--src/libs/installer/packagemanagercore_p.h10
7 files changed, 47 insertions, 33 deletions
diff --git a/src/libs/installer/createdesktopentryoperation.cpp b/src/libs/installer/createdesktopentryoperation.cpp
index c3988a8ec..27ff18fca 100644
--- a/src/libs/installer/createdesktopentryoperation.cpp
+++ b/src/libs/installer/createdesktopentryoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,7 @@
#include "globals.h"
#include "adminauthorization.h"
#include "remoteclient.h"
+#include "packagemanagercore.h"
#include <QDir>
#include <QFile>
@@ -64,7 +65,7 @@ QString CreateDesktopEntryOperation::absoluteFileName()
XDG_DATA_HOME.push_back(QDir::home().absoluteFilePath(QLatin1String(".local/share"))); // default user-specific path
- if (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive())
+ if (packageManager() && packageManager()->hasAdminRights())
XDG_DATA_HOME.push_front(QLatin1String("/usr/local/share")); // default system-wide path
const QStringList directories = XDG_DATA_HOME;
diff --git a/src/libs/installer/extractarchiveoperation.cpp b/src/libs/installer/extractarchiveoperation.cpp
index 162bd1609..8995bbcbf 100644
--- a/src/libs/installer/extractarchiveoperation.cpp
+++ b/src/libs/installer/extractarchiveoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2022 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -103,7 +103,7 @@ void ExtractArchiveOperation::backup()
return;
}
- const bool hasAdminRights = (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive());
+ const bool hasAdminRights = (packageManager() && packageManager()->hasAdminRights());
const bool canCreateSymLinks = QInstaller::canCreateSymbolicLinks();
bool needsAdminRights = false;
diff --git a/src/libs/installer/installiconsoperation.cpp b/src/libs/installer/installiconsoperation.cpp
index 5927ebf74..b21634cd7 100644
--- a/src/libs/installer/installiconsoperation.cpp
+++ b/src/libs/installer/installiconsoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -57,7 +57,7 @@ QString InstallIconsOperation::targetDirectory()
Qt::SkipEmptyParts);
XDG_DATA_HOME.push_back(QDir::home().absoluteFilePath(QLatin1String(".local/share"))); // default user-specific path
- if (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive())
+ if (packageManager() && packageManager()->hasAdminRights())
XDG_DATA_HOME.push_front(QLatin1String("/usr/local/share")); // default system-wide path
QString directory;
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 9feb195d8..8b8994c5a 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -2990,6 +2990,21 @@ void PackageManagerCore::dropAdminRights()
}
/*!
+ Returns \c true if the installer has admin rights. For example, if the installer
+ was started with a root account, or the internal admin rights elevation is active.
+
+ Returns \c false otherwise.
+
+ \sa {installer::hasAdminRights}{installer.hasAdminRights}
+ \sa gainAdminRights()
+ \sa dropAdminRights()
+*/
+bool PackageManagerCore::hasAdminRights() const
+{
+ return AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive();
+}
+
+/*!
Sets checkAvailableSpace based on value of \a check.
*/
void PackageManagerCore::setCheckAvailableSpace(bool check)
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index e5236112e..0c167f92c 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -307,6 +307,7 @@ public:
Q_INVOKABLE bool gainAdminRights();
Q_INVOKABLE void dropAdminRights();
+ Q_INVOKABLE bool hasAdminRights() const;
void setCheckAvailableSpace(bool check);
bool checkAvailableSpace(QString &message) const;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 79fb0c8dd..656a1d437 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -777,7 +777,7 @@ QString PackageManagerCorePrivate::maintenanceToolAliasPath() const
if (aliasName.isEmpty())
return QString();
- const bool isRoot = (AdminAuthorization::hasAdminRights() || RemoteClient::instance().isActive());
+ const bool isRoot = m_core->hasAdminRights();
const QString applicationsDir = m_core->value(
isRoot ? QLatin1String("ApplicationsDir") : QLatin1String("ApplicationsDirUser")
);
@@ -1744,7 +1744,7 @@ bool PackageManagerCorePrivate::runInstaller()
throw Error(tr("It is not possible to install from network location"));
}
- if (!adminRightsGained) {
+ if (!m_core->hasAdminRights()) {
foreach (Component *component, componentsToInstall) {
if (component->value(scRequiresAdminRights, scFalse) == scFalse)
continue;
@@ -1778,7 +1778,7 @@ bool PackageManagerCorePrivate::runInstaller()
double progressOperationSize = componentsInstallPartProgressSize / progressOperationCount;
// Now install the requested components
- unpackAndInstallComponents(componentsToInstall, progressOperationSize, adminRightsGained);
+ unpackAndInstallComponents(componentsToInstall, progressOperationSize);
if (m_core->isOfflineOnly() && PackageManagerCore::createLocalRepositoryFromBinary()) {
emit m_core->titleMessageChanged(tr("Creating local repository"));
@@ -1976,7 +1976,7 @@ bool PackageManagerCorePrivate::runPackageUpdater()
}
// we did not request admin rights till we found out that a component/ undo needs admin rights
- if (updateAdminRights && !adminRightsGained) {
+ if (updateAdminRights && !m_core->hasAdminRights()) {
m_core->gainAdminRights();
m_core->dropAdminRights();
}
@@ -1997,7 +1997,7 @@ bool PackageManagerCorePrivate::runPackageUpdater()
if (undoOperations.count() > 0) {
ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("Removing deselected components..."));
- runUndoOperations(undoOperations, undoOperationProgressSize, adminRightsGained, true);
+ runUndoOperations(undoOperations, undoOperationProgressSize, true);
}
m_performedOperationsOld = nonRevertedOperations; // these are all operations left: those not reverted
@@ -2005,7 +2005,7 @@ bool PackageManagerCorePrivate::runPackageUpdater()
const double progressOperationSize = componentsInstallPartProgressSize / progressOperationCount;
// Now install the requested new components
- unpackAndInstallComponents(componentsToInstall, progressOperationSize, adminRightsGained);
+ unpackAndInstallComponents(componentsToInstall, progressOperationSize);
emit m_core->titleMessageChanged(tr("Creating Maintenance Tool"));
@@ -2074,7 +2074,7 @@ bool PackageManagerCorePrivate::runUninstaller()
}
// We did not yet request elevated permissions but they are required.
- if (updateAdminRights && !adminRightsGained) {
+ if (updateAdminRights && !m_core->hasAdminRights()) {
m_core->gainAdminRights();
m_core->dropAdminRights();
}
@@ -2082,7 +2082,7 @@ bool PackageManagerCorePrivate::runUninstaller()
const int uninstallOperationCount = countProgressOperations(undoOperations);
const double undoOperationProgressSize = double(1) / double(uninstallOperationCount);
- runUndoOperations(undoOperations, undoOperationProgressSize, adminRightsGained, false);
+ runUndoOperations(undoOperations, undoOperationProgressSize, false);
// No operation delete here, as all old undo operations are deleted in the destructor.
deleteMaintenanceTool(); // this will also delete the TargetDir on Windows
@@ -2091,7 +2091,7 @@ bool PackageManagerCorePrivate::runUninstaller()
// If not on Windows, we need to remove TargetDir manually.
#ifndef Q_OS_WIN
if (QVariant(m_core->value(scRemoveTargetDir)).toBool() && !targetDir().isEmpty()) {
- if (updateAdminRights && !adminRightsGained)
+ if (updateAdminRights && !m_core->hasAdminRights())
adminRightsGained = m_core->gainAdminRights();
removeDirectoryThreaded(targetDir(), true);
qCDebug(QInstaller::lcInstallerInstallLog) << "Complete uninstallation was chosen.";
@@ -2253,7 +2253,7 @@ bool PackageManagerCorePrivate::runOfflineGenerator()
}
void PackageManagerCorePrivate::unpackComponents(const QList<Component *> &components,
- double progressOperationSize, bool adminRightsGained)
+ double progressOperationSize)
{
OperationList unpackOperations;
bool becameAdmin = false;
@@ -2277,7 +2277,7 @@ void PackageManagerCorePrivate::unpackComponents(const QList<Component *> &compo
// There's currently no way to control this on a per-operation basis, so
// any op requesting execution as admin means all extracts are done as admin.
- if (!adminRightsGained && !becameAdmin && op->value(QLatin1String("admin")).toBool())
+ if (!m_core->hasAdminRights() && op->value(QLatin1String("admin")).toBool())
becameAdmin = m_core->gainAdminRights();
}
}
@@ -2325,7 +2325,7 @@ void PackageManagerCorePrivate::unpackComponents(const QList<Component *> &compo
continue;
}
// Backup may request performing operation as admin
- if (!adminRightsGained && !becameAdmin && operation->value(QLatin1String("admin")).toBool())
+ if (!m_core->hasAdminRights() && operation->value(QLatin1String("admin")).toBool())
becameAdmin = m_core->gainAdminRights();
}
@@ -2394,8 +2394,7 @@ void PackageManagerCorePrivate::unpackComponents(const QList<Component *> &compo
ProgressCoordinator::instance()->emitDetailTextChanged(tr("Done"));
}
-void PackageManagerCorePrivate::installComponent(Component *component, double progressOperationSize,
- bool adminRightsGained)
+void PackageManagerCorePrivate::installComponent(Component *component, double progressOperationSize)
{
OperationList operations = component->operations(Operation::Install);
if (!component->operationsCreatedSuccessfully())
@@ -2416,7 +2415,7 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
// maybe this operations wants us to be admin...
bool becameAdmin = false;
- if (!adminRightsGained && operation->value(QLatin1String("admin")).toBool()) {
+ if (!m_core->hasAdminRights() && operation->value(QLatin1String("admin")).toBool()) {
becameAdmin = m_core->gainAdminRights();
qCDebug(QInstaller::lcInstallerInstallLog) << operation->name() << "as admin:" << becameAdmin;
}
@@ -2661,8 +2660,8 @@ void PackageManagerCorePrivate::unregisterMaintenanceTool()
#endif
}
-void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOperations, double progressSize,
- bool adminRightsGained, bool deleteOperation)
+void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOperations,
+ double progressSize, bool deleteOperation)
{
try {
const int operationsCount = undoOperations.size();
@@ -2673,7 +2672,7 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
throw Error(tr("Installation canceled by user"));
bool becameAdmin = false;
- if (!adminRightsGained && undoOperation->value(QLatin1String("admin")).toBool())
+ if (!m_core->hasAdminRights() && undoOperation->value(QLatin1String("admin")).toBool())
becameAdmin = m_core->gainAdminRights();
connectOperationToInstaller(undoOperation, progressSize);
@@ -2958,16 +2957,16 @@ void PackageManagerCorePrivate::addPathForDeletion(const QString &path)
}
void PackageManagerCorePrivate::unpackAndInstallComponents(const QList<Component *> &components,
- const double progressOperationSize, const bool adminRightsGained)
+ const double progressOperationSize)
{
// Perform extract operations
- unpackComponents(components, progressOperationSize, adminRightsGained);
+ unpackComponents(components, progressOperationSize);
// Perform rest of the operations and mark component as installed
const int componentsToInstallCount = components.size();
int installedComponents = 0;
foreach (Component *component, components) {
- installComponent(component, progressOperationSize, adminRightsGained);
+ installComponent(component, progressOperationSize);
++installedComponents;
ProgressCoordinator::instance()->emitAdditionalProgressStatus(tr("%1 of %2 components installed.")
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 75d0d69f8..986776479 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -169,11 +169,9 @@ public:
m_performedOperationsCurrentSession.clear();
}
- void unpackComponents(const QList<Component *> &components, double progressOperationSize,
- bool adminRightsGained = false);
+ void unpackComponents(const QList<Component *> &components, double progressOperationSize);
- void installComponent(Component *component, double progressOperationSize,
- bool adminRightsGained = false);
+ void installComponent(Component *component, double progressOperationSize);
void setComponentSelection(const QString &id, Qt::CheckState state);
@@ -243,7 +241,7 @@ private slots:
private:
void unpackAndInstallComponents(const QList<Component *> &components,
- const double progressOperationSize, const bool adminRightsGained);
+ const double progressOperationSize);
void deleteMaintenanceTool();
void deleteMaintenanceToolAlias();
@@ -256,7 +254,7 @@ private:
void writeMaintenanceToolAppBundle(OperationList &performedOperations);
void runUndoOperations(const OperationList &undoOperations, double undoOperationProgressSize,
- bool adminRightsGained, bool deleteOperation);
+ bool deleteOperation);
PackagesList remotePackages();
LocalPackagesMap localInstalledPackages();