Bugfix/Allow ssh_server to load libdbus1 when running in build directory#4815
Bugfix/Allow ssh_server to load libdbus1 when running in build directory#4815theartful wants to merge 1 commit intocanonical:mainfrom
Conversation
|
Thanks @theartful! I had a look and this makes sense to me. I'll just wait for CI before submitting a proper review. |
There was a problem hiding this comment.
Pull request overview
This PR aims to make sshfs_server runnable directly from the build directory on Linux by ensuring it can load libdbus-1.so.3 under the AppArmor profile used by multipassd, fixing multipass mount failures in that workflow.
Changes:
- Set a Linux-only build-tree RPATH for
sshfs_serverto load libraries from../lib. - Add a Linux-only build step intended to copy
libdbus-1.so.3into${CMAKE_BINARY_DIR}/libso it’s accessible under the AppArmor profile.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| COMPONENT multipassd) | ||
|
|
||
| if(LINUX) | ||
| set_target_properties(sshfs_server PROPERTIES BUILD_RPATH "\$ORIGIN/../lib") |
There was a problem hiding this comment.
Setting BUILD_RPATH via set_target_properties(... PROPERTIES BUILD_RPATH ...) replaces any existing build RPATH entries that may have been added elsewhere (e.g., by the vcpkg toolchain). If other shared libs are needed from their original locations, this can make the build-tree sshfs_server fail to start. Prefer appending (set_property(TARGET sshfs_server APPEND PROPERTY BUILD_RPATH "$ORIGIN/../lib")) rather than overwriting.
| set_target_properties(sshfs_server PROPERTIES BUILD_RPATH "\$ORIGIN/../lib") | |
| set_property(TARGET sshfs_server APPEND PROPERTY BUILD_RPATH "\$ORIGIN/../lib") |
There was a problem hiding this comment.
I don't think that's a real issue though (sshfs_server is defined in this file, and we can see that BUILD_RPATH was not defined anywhere).
But point taken. I would use PREPEND instead of APPEND (if available) because I want the first priority for the loader to be $ORIGIN/../lib.
There was a problem hiding this comment.
There is no prepend option. The alternative is to first get the BUILD_RPATH values, prepend to it, and then use set_target_properties.
The issue is that I want the loader to first look into $ORIGIN/../lib, otherwise if it found libdbus in another directory that is not mappable by the apparmor profile, then the error will still happen.
I'm ignoring this for now, since it will look needlessly ugly. The naive version of getting BUILD_RPATH, and prepending to it will cause problems, because every time the script is run, a new entry will be added. So I have to guard against this condition by checking if it first exists. I think this is needless.
| add_custom_target(copy_dbus1 | ||
| COMMAND ${CMAKE_COMMAND} -E copy | ||
| "${DBUS1_LIB_REAL}" | ||
| "${CMAKE_BINARY_DIR}/lib/libdbus-1.so.3" | ||
| COMMENT "Copy libdbus-1.so.3 to build/lib to fix AppArmor permissions issue with VCPKG_INSTALLED_DIR" |
There was a problem hiding this comment.
The destination name is hard-coded to libdbus-1.so.3. If the resolved DBus1_LIBRARY points to a different SONAME/major (or even a fully-versioned filename), this copy may not match what the binary actually needs at runtime. Consider deriving the destination filename from the resolved library path (or creating the necessary symlink chain) so the copied name always matches the NEEDED entry.
| add_custom_target(copy_dbus1 | |
| COMMAND ${CMAKE_COMMAND} -E copy | |
| "${DBUS1_LIB_REAL}" | |
| "${CMAKE_BINARY_DIR}/lib/libdbus-1.so.3" | |
| COMMENT "Copy libdbus-1.so.3 to build/lib to fix AppArmor permissions issue with VCPKG_INSTALLED_DIR" | |
| get_filename_component(DBUS1_LIB_REAL_NAME "${DBUS1_LIB_REAL}" NAME) | |
| get_filename_component(DBUS1_LIB_LINK_NAME "${DBus1_LIBRARY}" NAME) | |
| set(DBUS1_COPY_COMMANDS | |
| COMMAND ${CMAKE_COMMAND} -E copy | |
| "${DBUS1_LIB_REAL}" | |
| "${CMAKE_BINARY_DIR}/lib/${DBUS1_LIB_REAL_NAME}") | |
| if(NOT DBUS1_LIB_LINK_NAME STREQUAL DBUS1_LIB_REAL_NAME) | |
| list(APPEND DBUS1_COPY_COMMANDS | |
| COMMAND ${CMAKE_COMMAND} -E create_symlink | |
| "${DBUS1_LIB_REAL_NAME}" | |
| "${CMAKE_BINARY_DIR}/lib/${DBUS1_LIB_LINK_NAME}") | |
| endif() | |
| add_custom_target(copy_dbus1 | |
| ${DBUS1_COPY_COMMANDS} | |
| COMMENT "Copy libdbus-1 to build/lib using resolved library name and symlink to fix AppArmor permissions issue with VCPKG_INSTALLED_DIR" |
There was a problem hiding this comment.
I tried this, and it won't work.
DBus1_LIBRARY evaluates to libdbus-1.so which points to libdbus-1.so.3.38.3. Both names are incorrect, and sshfs_server links against libdbus-1.so.3 (which is another link to libdbus-1.so.3.38.3 but with the major version defined).
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4815 +/- ##
==========================================
+ Coverage 87.54% 87.54% +0.01%
==========================================
Files 258 258
Lines 14155 14156 +1
==========================================
+ Hits 12391 12392 +1
Misses 1764 1764 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
133c8d3 to
ae4006f
Compare
xmkg
left a comment
There was a problem hiding this comment.
Thanks for the contribution. I think allowing vcpkg-installed for the local dev builds would be a stronger way forward.
| find_package(DBus1 REQUIRED CONFIG) | ||
| endif() | ||
|
|
||
| get_target_property(DBUS1_LIB dbus-1 IMPORTED_LOCATION) |
There was a problem hiding this comment.
This only fixes the problem for libdbus. I'd rather have the vcpkg_installed path added to the allowed paths of all apparmored binaries (daemon, sshfs_server, etc.) for dev builds.
There was a problem hiding this comment.
Is it ok to assume that vcpkg_installed lives inside the build directory QCoreApplication::applicationDirPath()/../vcpkg_installed? Absolute paths would be problematic I think.
There was a problem hiding this comment.
Also note that currently everything vcpkg related is static, except for dbus
theartful:~/Programming/multipass/build/vcpkg_installed/x64-linux-release/lib (main)$ ls *so
libdbus-1.so
There was a problem hiding this comment.
Is it ok to assume that vcpkg_installed lives inside the build directory
QCoreApplication::applicationDirPath()/../vcpkg_installed?
That's good enough.
Also note that currently everything vcpkg related is static, except for dbus
That depends on what triplet we're building the dependencies with. It's a legit library path for our dev builds, so it's better to whitelist the folder itself than cherry-pick and copy individual dependencies.
There was a problem hiding this comment.
Done. I checked the processes that use an AppArmor profile:
SSHFSServerProcessSpec: fixed by addingvcpkg_installed.QemuImgProcessSpec: not owned by Multipass.QemuVMProcessSpec: not owned by Multipass.DNSMasqProcessSpec: not owned by Multipass.
ae4006f to
9da6153
Compare
Description
This PR fixes the issue where mount commands fail when using multipass from the build directory
The issue is that
sshfs_serverlinks againstlibdbus-1.so.3which lives invcpkg_installed/x64-linux-release/lib/. And whenmultipassdrunssshfs_serverit applies an AppArmor profile that doesn't include vcpkg_installed.The way I see it there are two ways to fix this:
vcpkg_installedto the list of available paths in the AppArmor profile.libdbusout ofvcpkg_installedtemporarily tolibdirectory, where the AppArmor profile allows access.I opted for the second solution.
Related Issue(s)
Closes #4607
Testing
First we can check what sshfs_server depends on:
We see that it needs
libdbus-1.so.3fromvcpkg_installed. To test the hypothesis that the apparmor profile is the culprit, I copy pasted the profile to a text fileprofile.apparmor, thenBut if I change rpath to include "$ORIGIN/../lib" and move "libdbus" to lib directory, I get
which is due to
Also
multipass mountworks after the patch.Additional informration
This is my apparmor profile (as snooped from multipassd)
Checklist