Skip to content

Commit

Permalink
[LW-10649] Fix installing & running with strict AppArmor
Browse files Browse the repository at this point in the history
… by removing the `nix-chroot`
  • Loading branch information
michalrus committed Jun 27, 2024
1 parent 7e73d49 commit d17ba50
Show file tree
Hide file tree
Showing 8 changed files with 367 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## vNext

### Fixes

- Fixed installation and running on Ubuntu 24.04 LTS with AppArmor enabled by removing the `chroot` ([PR 3207](https://github.com/input-output-hk/daedalus/pull/3207))

## 5.4.0

### Fixes
Expand Down
17 changes: 17 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
tullia.flake = false; # otherwie, +1k dependencies in flake.lock…
flake-compat.url = "github:input-output-hk/flake-compat";
flake-compat.flake = false;
nix-bundle-exe.url = "github:3noch/nix-bundle-exe";
nix-bundle-exe.flake = false;
};

outputs = inputs: let
Expand Down
1 change: 1 addition & 0 deletions nix/internal/common.nix
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ rec {
srcWithoutNix = pkgs.lib.cleanSourceWith {
src = inputs.self;
filter = name: type: !(type == "regular" && (
pkgs.lib.hasInfix "-source/nix/" name ||
pkgs.lib.hasSuffix ".nix" name ||
pkgs.lib.hasSuffix ".hs" name ||
pkgs.lib.hasSuffix ".cabal" name
Expand Down
94 changes: 94 additions & 0 deletions nix/internal/glibc-electron-loader.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
diff --git a/elf/dl-main.h b/elf/dl-main.h
index 3e32f254c5..9efa037f6c 100644
--- a/elf/dl-main.h
+++ b/elf/dl-main.h
@@ -99,6 +99,9 @@ struct dl_main_state

/* True if information about versions has to be printed. */
bool version_info;
+
+ /* <michalrus> Another way to pass argv[1] when running `./ld.so` directly (for Electron relaunching) */
+ const char *please_interpret;
};

/* Helper function to invoke _dl_init_paths with the right arguments
diff --git a/elf/rtld.c b/elf/rtld.c
index 86354fb0c2..955d672144 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -310,6 +310,7 @@ dl_main_state_init (struct dl_main_state *state)
state->mode = rtld_mode_normal;
state->any_debug = false;
state->version_info = false;
+ state->please_interpret = NULL;
}

#ifndef HAVE_INLINED_SYSCALLS
@@ -1396,6 +1397,8 @@ dl_main (const ElfW(Phdr) *phdr,
/* Process the environment variable which control the behaviour. */
process_envvars (&state);

+ _dl_printf ("; state.please_interpret = %s\n", (state.please_interpret == NULL ? "NULL" : state.please_interpret));
+
#ifndef HAVE_INLINED_SYSCALLS
/* Set up a flag which tells we are just starting. */
_dl_starting_up = 1;
@@ -1421,13 +1424,15 @@ dl_main (const ElfW(Phdr) *phdr,
installing it. */
rtld_is_main = true;

+ _dl_printf ("; rtld_is_main = true\n");
+
char *argv0 = NULL;
char **orig_argv = _dl_argv;

/* Note the place where the dynamic linker actually came from. */
GL(dl_rtld_map).l_name = rtld_progname;

- while (_dl_argc > 1)
+ while (state.please_interpret == NULL && _dl_argc > 1)
if (! strcmp (_dl_argv[1], "--list"))
{
if (state.mode != rtld_mode_help)
@@ -1554,17 +1559,24 @@ dl_main (const ElfW(Phdr) *phdr,

/* If we have no further argument the program was called incorrectly.
Grant the user some education. */
- if (_dl_argc < 2)
+ if (state.please_interpret == NULL && _dl_argc < 2)
{
if (state.mode == rtld_mode_help)
/* --help without an executable is not an error. */
_dl_help (ld_so_name, &state);
- else
+ else {
+ _dl_printf ("; will end with _dl_usage(NULL)\n");
_dl_usage (ld_so_name, NULL);
+ }
}

- --_dl_argc;
- ++_dl_argv;
+ if (state.please_interpret == NULL)
+ {
+ --_dl_argc;
+ ++_dl_argv;
+ }
+ else
+ _dl_argv[0] = (char *)state.please_interpret;

/* The initialization of _dl_stack_flags done below assumes the
executable's PT_GNU_STACK may have been honored by the kernel, and
@@ -2865,7 +2877,12 @@ process_envvars (struct dl_main_state *state)
GLRO(dl_verbose) = 1;
GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
GLRO(dl_trace_prelink) = &envline[17];
+ break;
}
+
+ if (memcmp (envline, "PLEASE_INTERPRET", 16) == 0
+ && envline[17] != '\0')
+ state->please_interpret = &envline[17];
break;

case 20:
8 changes: 3 additions & 5 deletions nix/internal/launcher-config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,12 @@ let

dirSep = if os == "windows" then "\\" else "/";
configDir = configFilesSource: {
linux = configFilesSource;
linux = if devShell then configFilesSource else "\${ENTRYPOINT_DIR}/config";
macos64 = if devShell then configFilesSource else "\${DAEDALUS_INSTALL_DIRECTORY}/../Resources";
macos64-arm = if devShell then configFilesSource else "\${DAEDALUS_INSTALL_DIRECTORY}/../Resources";
windows = "\${DAEDALUS_INSTALL_DIRECTORY}";
};

isDevOrLinux = devShell || os == "linux";

mkSpacedName = network: "Daedalus ${installDirectorySuffix}";
spacedName = mkSpacedName network;

Expand Down Expand Up @@ -99,7 +97,7 @@ let
windows = "\${DAEDALUS_INSTALL_DIRECTORY}";
};
binary' = if binary == "frontend" then frontendBinPath else binary;
in if isDevOrLinux then binary' else "${binDir.${os}}${dirSep}${binary'}${lib.optionalString (os == "windows") ".exe"}";
in if (devShell || os == "linux") then binary' else "${binDir.${os}}${dirSep}${binary'}${lib.optionalString (os == "windows") ".exe"}";
# Helper function to make a path to a config file
mkConfigPath = configSrc: configPath: "${(configDir configSrc).${os}}${dirSep}${configPath}";

Expand Down Expand Up @@ -229,7 +227,7 @@ let
cliBin = mkBinPath "cardano-cli";
nodeConfig = let
nodeConfigAttrs = if (configOverride == null) then envCfg.nodeConfig else __fromJSON (__readFile configOverride);
in builtins.toJSON (filterMonitoring (nodeConfigAttrs // (lib.optionalAttrs (!isDevOrLinux || network == "local") {
in builtins.toJSON (filterMonitoring (nodeConfigAttrs // (lib.optionalAttrs (!devShell || network == "local") {
ByronGenesisFile = "genesis-byron.json";
ShelleyGenesisFile = "genesis-shelley.json";
AlonzoGenesisFile = "genesis-alonzo.json";
Expand Down
64 changes: 64 additions & 0 deletions nix/internal/linux-self-extracting-archive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/sh

# XXX: Be *super careful* changing this!!! You WILL DELETE user data if you make a mistake.

# XXX: no -o pipefail in dash (on debians)
set -eu

skip_bytes=$(( 1010101010 - 1000000000 ))

echo "Verifying SHA-256 checksum..."
our_checksum=$(tail -c+$((skip_bytes+1)) "$0" | sha256sum | cut -d' ' -f1)
if [ "$our_checksum" != 0000000000000000000000000000000000000000000000000000000000000000 ] ; then
echo "Checksum verification failure. Please, download the installer again."
exit 1
fi

target="$HOME"/.daedalus/@CLUSTER@
if [ -e "$target" ] ; then
echo "Found an older version of Daedalus "@CLUSTER@", removing it..."
chmod -R +w "$target"
rm -rf "$target"
fi
mkdir -p "$target"

old_nix="$HOME"/.daedalus/nix
if [ -e "$old_nix" ] ; then
old_clusters=$(ls "$old_nix"/var/nix/profiles/ | grep '^profile-' | grep -v '[0-9]' || true)
if [ "$old_clusters" = "profile-"@CLUSTER@ ] ; then
# If the user *only* used Mainnet (most common), we're safe to remove the whole ~/.daedalus/nix:
echo "Found an older non-portable version of Daedalus in $old_nix, removing it..."
chmod -R +w "$old_nix"
rm -rf "$old_nix"
else
# But if it contains more Daedaluses for other networks, we can't risk breaking them:
echo "Found older non-portable versions of Daedalus for multiple networks in $old_nix, you are free to remove the directory manually, if you no longer use them."
fi
fi

progress_cmd="cat"
if type pv >/dev/null ; then
total_size=$(stat -c "%s" "$0")
progress_cmd="pv -s "$((total_size - skip_bytes))
else
echo "Note: you don't have \`pv' installed, so we can't show progress"
fi

echo "Unpacking..."
tail -c+$((skip_bytes+1)) "$0" | $progress_cmd | tar -C "$target" -xJ

echo "Setting up a .desktop entry..."
mkdir -p "$HOME"/.local/share/applications
chmod -R +w "$target"/share/applications
sed -r "s+INSERT_PATH_HERE+$(echo "$target"/bin/*)+g" -i "$target"/share/applications/*.desktop
sed -r "s+INSERT_ICON_PATH_HERE+$target/share/icon_large.png+g" -i "$target"/share/applications/*.desktop
chmod -R -w "$target"/share/applications
ln -sf "$target"/share/applications/*.desktop "$HOME"/.local/share/applications/Daedalus-@CLUSTER@.desktop

echo "Installed successfully!"
echo
echo "Now, either:"
echo " 1. In a terminal, run $(echo "$target"/bin/* | sed -r "s+^$HOME+~+")"
echo " 2. Or select Start -> Daedalus "@CLUSTER@"."

exit 0
Loading

0 comments on commit d17ba50

Please sign in to comment.