Linux: secure NixOS helper lookup and report blocked elevation

Look up NixOS helpers only when trusted system metadata identifies NixOS
and each path component passes ownership and permission checks. Keep the
existing helper search on other distributions.

Detect NoNewPrivs before prompting for administrator credentials, with a
clear error for restricted launchers. Add regression coverage to Linux CI
and append the English fallback message to all language files.

Refs #1911
This commit is contained in:
Mounir IDRASSI
2026-10-10 22:25:42 +09:00
parent 3e3a271e52
commit 6e63041962
49 changed files with 666 additions and 0 deletions
+22
View File
@@ -23,6 +23,13 @@
#include <sys/wait.h>
#include <termios.h>
#include <stdio.h>
#ifdef TC_LINUX
#include <sys/prctl.h>
// Allow builds with headers predating Linux 3.5.
#ifndef PR_GET_NO_NEW_PRIVS
#define PR_GET_NO_NEW_PRIVS 39
#endif
#endif
#include "Platform/FileStream.h"
#include "Platform/MemoryStream.h"
#include "Platform/Serializable.h"
@@ -189,6 +196,17 @@ namespace VeraCrypt
}
#endif
static void CheckPrivilegeElevationAllowed ()
{
#ifdef TC_LINUX
// NoNewPrivs is inherited across fork/exec and prevents sudo or doas
// from gaining privileges. A password cannot remove this restriction.
// Older kernels reject the query; let normal elevation handle that case.
if (prctl (PR_GET_NO_NEW_PRIVS, 0L, 0L, 0L, 0L) == 1)
throw ElevationBlocked (SRC_POS);
#endif
}
static PrivilegeHelper FindPrivilegeHelper ()
{
std::string errorMsg;
@@ -1466,6 +1484,9 @@ namespace VeraCrypt
while (!ElevatedServiceAvailable)
{
// Check before authentication, but allow reuse of an elevated service.
CheckPrivilegeElevationAllowed ();
// Test if the user has an active privilege helper session.
bool authCheckDone = false;
bool passwordCollected = false;
@@ -1580,6 +1601,7 @@ namespace VeraCrypt
void CoreService::StartElevated (const CoreServiceRequest &request)
{
CheckPrivilegeElevationAllowed ();
PrivilegeHelper privilegeHelper = FindPrivilegeHelper ();
int doasAuthTerminal = -1;
string doasAuthTerminalPath;