[SailfishDevel] Scriptlets in RPM hot allowed to Harbour

Thomas Perl th.perl at gmail.com
Sat Jan 11 15:06:56 UTC 2014

Duty calls[1]...

tl;dr: No postinst scripts in Harbour. chmod 666 stuff in /usr/ is wrong.

On 11 Jan 2014, at 13:51, Martin Kolman <martin.kolman at gmail.com> wrote:
> 11.1.2014 13:34, Alejandro Exojo:
>>> QA can check if post script doing some good job and allow it?
>> If the script is simple, yes. If it is not, there is a serious risk that
>> somebody adds a trojan horse to the phone.
>> That would mean that somebody has to define what is a simple script. And that a
>> problem in QA could mean a trojan horse is added to users' phones.
> And yet normal Linux distributions like Fedora, Debian, Ubuntu or openSUSE manage to check their tens of thousands of packages just fine…

The following is just my personal opinion on this story in the form of a wall of text[4], in which you can choose to run into or not. Also, it’s not meant to be harsh, even if it reads like this in some parts of it. Just a (hopefully thorough enough) explanation of why it’s a bad idea to have postinst and chmod 666 stuff in /usr/ so that app developers can go back to creating great apps, understanding the reasons for not having postinst scripts and that it’s a Good Thing, and doesn’t conflict with What We’re Used To on Desktop Linux.

All the core packages (well, most of them at least) of Fedora, Debian, etc.. are open source in the repositories, built on their servers, and could at least in theory be reviewed by someone. Try to get a package into Fedora or Debian that does “chmod 666” to some directory in /usr/share/ in the postinst script - probably not going to be accepted there.

In fact, if you want to go all “Desktop Linux” on this issue, read the FHS[6], and let me quote RedHat’s documentation[7]:

  “The two most important elements of FHS compliance are: […] The ability to mount a /usr/ partition as read-only."

In any case, at least for Debian, here’s the policy page regarding maintainer scripts in case you haven’t read it yet:

Also, have a look at all those nice flow graphs (I especially like the “Upgrading” one) in the Debian wiki related to maintainer scripts (it might be different in the RPM world, but the point is that it’s not as trivial as it sounds initially):

But - we’re neither Debian nor Fedora (nor openSuSE for that matter); and I don’t even know if we comply to the FHS or not - this is Sailfish OS. Don’t say “It’s an RPM system - I know this”[2] while not understanding the subtle points, and that a package in Debian/Fedora is different from an “app” on a mobile device. Where postinst scripts make sense on Debian for system packages, and even where they make sense on Sailfish OS/Mer for system packages (we use postinst scripts there, and for good reasons!), these scripts in almost all cases do not make sense in third-party app packages.

If you think your package is that useful and needs to run as daemon and have postinst scripts, chances are you should be trying to get it into Mer or Nemo Mobile, from which it can then be picked up and be installed into the system - possibly even by default (yay!), because it’s so awesome (seriously, if you have such an app/middleware/service, don’t bother getting it into Harbour - get the middleware parts into Nemo Mobile and integrated well, then only push a GUI for it into Harbour [yes, I know that’s more work *for you* and will take “ages", but it will result in something much nicer and saner *for everybody*]).

The problem in this thread is that somebody is trying to do something that’s a bad idea in general. The question should not be “How do I make /usr/share/$NAME world-writable?” (that is usually NEVER a good idea), but rather “My app wants to do this and that, my initial approach was to make /usr/share/$NAME world-writable, but that’s not allowed by Harbour, and now that I come to think of it, it’s probably the wrong solution - how would I solve this problem in a way that is acceptable by Harbour and still achieves my goal?” (and if you ask that question, I’ll be more than happy to help ;).

By the way, the Harbour rules are not set in stone and up for discussion to be improved and more developer-friendly, so please post any issues that you have here. However, postinst scripts (at the current state where they are run as root at installation time) and world-writable /usr/ are NOT up for discussion (and this very mail tries to explain why).

Just for the record, in case it wasn’t clear:

 - Files in /usr/share/ must not be writable by normal users (guess what? that’s a requirement in Fedora, Debian, etc.. as well!, also it makes debugging so much harder; there’s no way to just “nuke the app’s config in /home/nemo/ to start afresh“ if the app might have overwritten, changed or deleted some data in /user/share/ that it also uses at runtime)
 - RPM packages must not install files to /home/nemo/ (guess what? if you were to install files there on a Fedora/Debian system, it would be pretty, pretty bad for obvious reasons [hint: your username on your Desktop system might not be “nemo”, and your Desktop system might have multiple users, and the numeric UID of the user might be a different one, etc])

In addition, don’t forget that:

 - Deleting files in /usr/share/ doesn’t work, as those files will be re-created each time the package is upgraded
 - Modifying files in /usr/share/ doesn’t work, as those files will be overwritten each time the package is upgraded

(see a pattern there?)

The *user* as owner of the device can do whatever he/she pleases (they can be root and mess with the system as much as they want), they are the ones paying for fixing the device in case it’s bricked and needs to be sent to care. The *app* as “guest” on the user’s device should do sane things, and ideally not cause breakage, and ideally not run as root, at least not without the user’s permission - definitely not at installation time without user confirmation.

There are still an infinite number of things that a bad app can do, even as “nemo” user, that harbour QA or any amount of manual checking will never be able to catch (hint: google “Static program analysis” and “Halting problem” for a very scientific approach or think about embedding/encrypting shared libraries/executables in your binary and extracting + executing/loading them at runtime for a very practical approach). Those will be catched and dealt with later / when the app is out.

Again, the *user* is root on the device, not the *app*. If you install one of my applications, it’s still you who owns the device and has root, not my application - and that is a very, very good thing. It really is. Trust me. Or actually don’t trust me. Because you don’t want my code running as root when my app is installed (I wouldn’t want my code running as root when my app is installed, for that matter).

The fact that there might have been some packages in Maemo Extras back in the day that installed files to /home/user/ or even /home/user/MyDocs/ (think about what happens when the device is connected as USB Mass Storage while the package is installed [hint: yeah, MyDocs isn’t mounted during that time]) doesn’t necessarily mean that it’s a good idea in general (hint: it really isn’t a good idea, and never was).

> BTW, I would be more concerned of closed source binary-only packages being submitted to the store, than about scripts you can actually read.

When a user installs an app from the Store, nowhere do they have the chance to read (or even understand) the script. The script can be anything, even calling a closed source binary that’s installed as part of the package. Even if we had the manpower and expertised people in QA that can read, check and understand(!) all postinst scriptlets (even I can’t do that), it would still be a bad idea. Even if the sources were open (hint: open source doesn’t mean readable or understandable code[3]).

The fact that the postinst scripts are shell scripts doesn’t have anything to do with “scripts you can actually read” (or understand), of course for the pathological case of “chmod 666” it would be easy to do, but in the general case, it’s not. And it doesn’t change the fact that “chmod 666” in /usr/share/ is still a bad idea.

Also, when talking about maintainer scripts, people often forget about upgrading packages — postinst/preinst/postrm/prerm scripts sometimes have to be really really smart about those situations to not mess things up; if you’ve ever upgraded a Debian system, they even have things in place that will try the old postrm (for example) script and fall back to the new one in case the old one fails, because otherwise you’d be stuck with a non-working system (the postrm can never be run -> the package can never be upgraded, or something like that - go checkout the Debian Wiki link from above, it’s complicated).

I don’t even know of any other user-friendly mobile platform that allows something like postinst scripts (certainly not as root user). If it’s a good idea, do it and be “unlike”, but if it’s a bad idea, stick to whatever everyone else is doing (be “like”) and/or improve on that with good ideas.

> The blob can on the other hand do anything without QA having any reasonable means to check for that.

The “blob” is usually run as “nemo” user, which by default has less permissions than the root user (which is the user with which postinst scripts are run). Ideally I’d personally like to see those apps running completely sandboxed - again, not to “close down the system”, but rather to protect you and me - the users - from bad apps (and they don’t even have to be programmed to be bad, it might just be a typo[5] without bad intentions ending up doing something really really bad).

Eventually I’d like to be able to download a random RPM package from the web, and install it without checking what’s inside, and still have some degree of certainty that this app won’t do anything bad to my system, or my user data. But again, we’re not there yet, so the Harbour rules try to atleast avoid the obvious places where such problems usually crop up.

Again, in my very personal opinion (like everything in this mail), an open device to me means that I *as user* can have root and do everything I want to do, but I don’t want random apps that I install (that includes my own apps) to run as root, not during install time and also not during runtime. if *I* on *my device* decide that it’s a good idea to run app A as root, I can do so from the command line in a root shell or from a GUI app that I installed myself.

HTH :)

[1] http://xkcd.com/386/
[2] http://www.youtube.com/watch?v=dFUlAQZB9Ng
[3] http://www.ioccc.org/
[4] http://en.wikipedia.org/wiki/Wikipedia:Wall_of_text
[5] https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/issues/123
[6] http://www.pathname.com/fhs/
[7] https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/s1-filesystem-fhs.html

More information about the Devel mailing list