Harbour: is a bundled third-party binary acceptable in the /usr/bin/harbour-<app> slot?

Hello guys,

currently i try to make my app “Ferry Sync” (file sync client for Sailfish OS, using RCLONE as backend) harbour-ready, but i am stuck on one question that decides whether that is possible at all.

Situation: Ferry is a QML-only app (CONFIG += sailfishapp_qml, Exec=sailfish-qml harbour-ferry). It has no binary of its own. The actual transfer and sync work is done by rclone (MIT-licensed), which I currently ship at /usr/share/harbour-ferry/bin/rclone and start as a subprocess. The harbour validator rejects this, correctly:

ERROR [/usr/share/harbour-ferry/bin/rclone] ELF binary in wrong location (must be /usr/bin/harbour-ferry)
ERROR [/usr/share/harbour-ferry/bin/rclone] File must not be executable (current permissions: 755)

The question: since the app is QML-only, the /usr/bin/harbour-ferry slot is unused. Would it be acceptable to install the bundled rclone there — so the package contains exactly one ELF binary, named harbour-ferry, in the allowed location, but that binary is rclone rather than the app’s own entry point?

The desktop file would keep Exec=sailfish-qml harbour-ferry; the app would launch /usr/bin/harbour-ferry only as a helper subprocess, never as itself.

This would pass the automated check i think, which is exactly why I am unsure about it. The slot is clearly intended for the application’s own binary, and I do not want to submit something that looks like a rule circumvention.

→ What do you think about it?

If it is not acceptable, the alternative I see is to not bundle rclone at all and require the user to install it from Chum/OpenRepos first (Requires: rclone is not permitted either). That means a Store app that does nothing after installation until the user finds and installs a dependency by hand — which I would rather avoid. If there is a third option I am missing, I would be glad to hear it.

One side question:

  • Is there a package size limit for Jolla-AppStore submissions? An unstripped rclone build is around 72 MB per architecture.
4 Likes

Can’t really help, but wanted quickly come and say that I really highly appreciate the Ferry Sync :heart: and I highly appreciate the effort you see to get the apps to Harbour!:heart:

3 Likes

Yes, this is possible. See the Harbour FAQ for more.

I’m sure it’s possible, but is it acceptable to have rclone stored as /usr/bin/harbour-ferry? Absolutely not.

You should package rclone separately and define it (or the older version in Openrepos) as a dependency.

That way people can recognize & use rclone for other purposes as well.

But this is just my Linux Luddite opinion; maybe app developers don’t think that way.

Please read the Harbour FAQ

Bundle rclone in /usr/share/appname/lib/rclone.so to trick the validation.

Call it as you do now.

(And yeah, rclone is huge, but that’s what you get with language “runtimes” which statically-link the world on principle.)

This Harbour rule is weird, it would be great that Jolla will review and remove this restriction…

Not sure if @nephros suggestion will work, as the harbour check validates ELF header.

Anyway, I had the same problem with ffmpeg bundled with my TimeLapse tools. I pack it to the tar archive ( /usr/share/harbour-timelapse-tools/bin/ffmpeg.tar ), it effectively hide its ELF header before the rpm validator. And the application then unpack this tar on the startup (using c++, header-only tar implementation) to the ~/.cache directory and start the binary from this location…

This solution is not ideal for you, as you have QML-only application. You would need thin service layer in C++…

1 Like

You could also download it from a known location on first start and extract it into .local/share/<namespace>/<app>.

No need to bundle an executable here. Use librclone:

You can build a SFOS lib and add this lib to your project tree. Or - more elegant - add the source code as a subproject to your project. This subproject creates the needed lib. The advantage: it is always correct compiled and build with the same version of compiler and so.

You need a new project including C++ for this. If you created your QML project in SDK create an new project for QML + C++ in SDK and copy the programming. Don’t extend the old pure QML project.

6 Likes

Alternatively, to remain QML only, run rclone in remote control mode, and use http api calls via xmlhttprequest:

Of course, the original problem remains, and I’d probably also go via the ‘download binary on first launch’ route.

For launching from QML, use a very small pyotherside call to subprocess.run or similar.

2 Likes

Thank You for your good Input and ideas guys, I will have a Look in all your proposals!

1 Like

I’d also be interested in @Jolla’s take on this, as I’m facing the same challenge with postivene :sailboat::speech_balloon:. I was considering opening a separate thread for this, but I hope it’s ok if I piggy-back on this one :slightly_smiling_face: I would like to eventually make postivene available via Harbour. I would like your guidance before submitting, rather than finding out at QA.

The situation

The app bundles one additional executable: deltachat-rpc-server, the upstream Delta Chat core, which the app launches as a subprocess and drives over JSON-RPC on stdin/stdout. All messaging, IMAP/SMTP and encryption happen there; the app itself contributes only the Silica UI and packaging, and never implements protocol or crypto of its own.

This falls foul of the rule that a package may contain only /usr/bin/<NAME> plus shared libraries under /usr/share/<NAME>/lib/. As far as I can tell*, everything else complies with the Harbour requirements.

The question

I’d rather ask than work around it. Specifically:

  1. Is there an accepted way to ship an upstream helper binary of this kind?

  2. If not, would you consider it for the allowed layout?

Why on earth?

The reasoning, briefly:

  • It’s the integration method upstream recommends. Delta Chat has deprecated its C library (libdeltachat), which exists now only because Android and iOS still use it, and directs new projects to the JSON-RPC server instead. The alternative would mean adopting an interface its authors are retiring.

  • The in-process route is not available. The Rust API that replaces the C library requires Rust 1.89; the Sailfish SDK ships 1.75.

  • It is not opaque. The binary is upstream’s reproducible build, fetched at a pinned version and verified by SHA-256 at package time. It is confined by the same Sailjail profile as the app, holds no privileges of its own, and is never updated independently of the package.

  • It is small. The complete RPM is about 11 MB.

No workarounds

I’m aware I could rename the binary with a .so suffix and place it under /usr/share/<NAME>/lib/, which would technically pass validation. I haven’t, because your validator’s README states that circumventing the rules is grounds for removal.

No OpenRepos/Chum

I do not want to go the OpenRepos/Chum route. I want to help improve this platform and get it to a point where it appeals to a broad majority of regular, non-technical people. That means no developer mode, no SSH’ing to fix small things, no community repos. Most importantly, that means dogfooding and, frankly, nagging you about the things that the platform is still missing. :blush:

Let me know if you have questions. Happy to provide an RPM, too.

Keep on sailing :sailboat::vulcan_salute:t2:

* I am validating all generated RPMs against your RPM validator to make sure I stay on track.

3 Likes

If I saw this kind of behaviour without knowing why or what it’s doing I would assume this is malware. You’re effectively working around security limitations to install an arbitrary and unvetted (by Jolla) binary.

I don’t have an opinion on whether these binaries should be allowed or not, but intentionally hiding stuff from the validator should be explicitly forbidden imo. If this doesn’t work for you, you should try to work with Jolla to fix the validator (assuming they’d agree this should be allowed), and in the meantime publish your app to chum or openrepos.

3 Likes

One works with the system one has. Like they tell you in recovery programs: “Change what you can control, accept what you can’t, and know the difference between them.”

I don’t think working around security measures is the way to go though. The proper way to “work around” this particular issue, is to not publish the app to harbour where this is not allowed, but to Chum (assuming it is allowed there, not sure) or openrepos.

Working around security measures should never be a valid workaround imo.

1 Like

Forbid multiple binaries in the package makes sense for the paths that are part of the usual lookup for binaries (part of the PATH variable). You do not want to bring bash or dash binary with some random application. But when the binary is stored in the /usr/share/{app name}, I see no reason for such limitation today. There was one reason in the past - as every application in the Harbour pass the QA review, they are checking what places the application is touching and check if the application do not do obvious malicious things. But we have Sailjail sandboxing today. Map application cannot read configuration of the password manager…

You as a developer cannot integrate third-party code to your application for license reason sometimes. Or you just don’t want to deal with the symbol hell. So, distributing ffmpeg binary together with the video-handling application is completely fine in my eyes.

If you are looking to such techniques as malicious, look how JIT compilers in the Java or Python are working. They just generate executable code from the bytecode, load it to the memory, mark it as executable and execute it… The only difference is that my application is storing the executable code to the application cache on the storage.

2 Likes

Thx for developing a fancy app for SFOS. But please respect the basic rules for Store.

As you know you can install what you want on your SFOS device. That’s an advantage for all people who can understand what happened in the depth. The opposite of this freedom is the Store. Here we have rules. So all people can install without checking all details. They can trust the rules. This is an advantage for all SFOS user.

Every some month there is a new post here in this forum for getting more freedom for Store apps. Every post has one special case why exact his app must be fine for the Store. Of course all have good reason to ask for. But in the sum all the exceptions make it’s difficult to check an app against the rules.

Less is better here. Some clear rules are enough.

1 Like

One option could be that perhaps some “libexec” directory under the application directory could be allowed to have executable binaries. It should be quite clear that those binaries are only meant to be run by the application and not by anyone.

4 Likes

I’d appreciate having that option. :+1:

To be clear (pun not intended), this would not only be convention, but enforced by sailjail/firejail’s user namespacing, I imagine?

Maybe. At the minimum it would be enforced by the harbour validator.