[prev in list] [next in list] [prev in thread] [next in thread] 

List:       qubes-devel
Subject:    [qubes-devel] Re: [GSoC] Qubes-MIME-Handlers Weekly Progress Report #8
From:       Andrew Morgan <andrew () amorgan ! xyz>
Date:       2017-08-09 19:02:50
Message-ID: omfm8l$vlh$1 () blaine ! gmane ! org
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


On 08/09/2017 08:03 AM, Marek Marczykowski-Górecki wrote:
> On Wed, Aug 09, 2017 at 07:28:21AM -0700, Andrew Morgan wrote:
> > On 08/08/2017 03:38 AM, Andrew Morgan wrote:
> > > Another report with some long-awaited news, enjoy!
> > > 
> > > Blog post with screenshots:
> > > https://blog.amorgan.xyz/gsoc-weekly-progress-report-8.html
> > > 
> > > Otherwise text-only is below (with screenshots attached):
> > > 
> > > ---
> > > 
> > > Hey there, welcome to another report! Since the last one, you may
> > > remember that I had finished setting up the build environment for
> > > Nautilus inside of GNOME Builder and was just getting started on
> > > properly doing the patch for supporting file trust attributes. Well, I'm
> > > happy to report that the patch is now finished! Screenshots and details
> > > below.
> > > 
> > > ## Working Demo
> > > 
> > > As screen recording in dom0 still isn't really doable yet, you'll have
> > > to settle for some screenshots of it in action :)
> > > 
> > > ![Double-clicking a trusted file opens
> > > normally...](images/open-trusted.png)
> > > *Double-clicking a trusted file opens normally...*
> > > 
> > > ![Everyone knows gedit is the ultimate text
> > > editor.](images/opened-gedit.png)
> > > *Everyone knows gedit is the ultimate text editor.*
> > > 
> > > ![Whereas an untrusted file summons a DispVM!](images/open-untrusted.png)
> > > *Whereas an untrusted file summons a DispVM!*
> > > 
> > > ![Virus free, yes-sir-ee!](images/opened-dispvm.png)
> > > *Virus free, yes-sir-ee!*
> > > 
> > > This short demo makes use of a majority of all the different components
> > > that have been worked on throughout the project. The now-patched
> > > Nautilus makes a call to the patched NautilusPython which asks our
> > > `qvm_trust` python extension to open a file, which it gives a response
> > > based on what our cli tool, `qvm-file-trust`, says about it, and if it
> > > is determined an untrusted file, `open-file-trust-based` will open it
> > > securely in a DisposableVM. The contents of the file were never parsed
> > > on the local machine!
> > > 
> > > The low-level part of this process was already working, but it took the
> > > patch to Nautilus allowing us to set off the chain from the GUI to
> > > really bring it all together. Let's talk about how that was done and how
> > > it works.
> > > 
> > > ## Nautilus and NautilusPython
> > > 
> > > By default, Nautilus does not support extensions written in Python, but
> > > rather only those written in C. To get around this, a _Nautilus C
> > > extension called NautilusPython_ was created. This extension has the
> > > ability to provide a bridging interface from Nautilus' extension
> > > infastructure to Python, handling any calls Python programs make to
> > > Nautilus and calling them from C. Arguments and return variables are all
> > > passed along seamlessly.
> > > 
> > > This is a really nice feature, as writing extensions in Python are about
> > > 90% less work than writing them in C, due to the large amount of
> > > boiler-plate associated with setting up and tearing down an extension.
> > > If you recall, the point of patching Nautilus was to allow extensions to
> > > be able to be notified of when a file is being opened, and block that
> > > request if necessary. I didn't want to subject myself or anyone else to
> > > only being able to write an extension that made use of this new
> > > functionality in C, thus patching NautilusPython as well as Nautilus
> > > itself to add our new `file_open` function was necessary. So how was
> > > each one done then?
> > > 
> > > Patching NautilusPython to add a new method was relatively simple, you
> > > only need look at the existing methods that an extension can subclass,
> > > find one that is functionally similar your own (I used
> > > `update_file_info` as my guide), then insert your own method
> > > (`file_open` in this case) at all the relevant points as well as create
> > > the appropriate function bodies and set argument/return variables
> > > appropriately.
> > > 
> > > So overall NautilusPython wasn't too bad really. The real time sink was
> > > Nautilus itself.
> > > 
> > > ## Patching Nautilus
> > > 
> > > First of all, I almost immediately ditched GNOME Builder after my last
> > > blog post. It's not that it was a bad IDE, far from it actually, I quite
> > > liked the interface and the various tools it contained. The ability to
> > > download a project from git, package and run it inside a Flatpak, and
> > > then send patches upstream all from within the editor was quite
> > > appealing! The first major showstopper however, was that the version of
> > > Nautilus that Qubes makes use of (v3.22.3), doesn't support Flatpak.
> > > While building and running from GNOME Builder without Flatpak seemed
> > > possible, no matter what I tried I could not get extensions to function
> > > properly with the GNOME Builder version.
> > > 
> > > After a lot of fiddling about, I settled on what I probably should have
> > > been using since the very beginning:
> > > [qubes-builder](https://github.com/qubesos/qubes-builder)!
> > > 
> > > Not only does it build the correct version (and supports extensions),
> > > but I knew that whatever I did with this build system would be exactly
> > > what users would be using when they built Qubes' templates or got them
> > > from the build servers. So, unfortunately no Flatpak'd builds, but I do
> > > have pre-packaged RPMs with debug-symbols! That's probably even better,
> > > right?
> > > 
> > > I'll post them in a separate blog post with instructions on how to set
> > > everything up soon.
> > > 
> > > qubes-builder worked very well and was quite easy to drill into and mess
> > > about with, as it is mostly just a collection of various scripts. I
> > > eventually built a script that ran in dom0 that would build Nautilus in
> > > my development VM, transfer it to my testing VM, delete the old version
> > > and install the new version.
> > > 
> > > The only downside to this process was that building Nautilus took quite
> > > a while each time (2-3m) which made quick changes quite an agonizing
> > > process. I believe this was due to both having to rebuild _every_ file
> > > each time (as they were packaged in a .tar.xz before being built,
> > > meaning all files were considered to be modified) as well as a call to
> > > `dnf` to fetch any updates was made, _every time_. I found out the
> > > latter when working without internet and realizing my could would not
> > > build! Each of these things probably could have been worked out or
> > > changed if I had felt the need to, but I just stuck with the loading
> > > times and usually had internet, so it was not too terrible.
> > > 
> > > Was _was_ terrible and time-consuming were a couple of very strange
> > > issues I had during the creation of the patch.
> > > 
> > > The first was the dreaded _provider issue_. You see, every time Nautilus
> > > calls a method that is meant to be subclassed by a Nautilus extension,
> > > you must _provide a provider_. This can be an `INFO` provider, `MENU`
> > > provider, and so on. Each method only accepts one of each type,
> > > typically corresponding to the category of method you were calling. For
> > > the `file_open` method I decided to stick it under the `INFO` provider
> > > category, as that had to do with information about files, which I felt
> > > 'when they were opened' best fell into.
> > > 
> > > Well, these providers don't just pop out of nowhere. You have to create
> > > them! You can do that by calling the intuitively-named
> > > `nautilus_module_get_extensions_for_type` method, providing it the
> > > `NAUTILUS_TYPE_INFO_PROVIDER` enum. It is then _supposed_ to return a
> > > provider with a type that matches the one you gave it, but no matter
> > > what I did it would always just return a `NULL` pointer! I spent _days_
> > > on this problem, trying loads of different things. Every other call of
> > > `nautilus_module_get_extensions_for_type` had no special setup or
> > > initialization, leading me confused why my own calling of it brought
> > > such different results.
> > > 
> > > After picking through many lines of code, talking with GNOME people over
> > > IRC who were currently GUADEC'ing, and trying to understand the whole
> > > GNOME development ecosystem, I eventually traced it all back to
> > > NautilusPython not finding an extension that made use of a subclassed
> > > method from the `INFO` method type. But wait, we _do_ have an extension
> > > that does that with `qvm_trust`, so why doesn't it work??
> > > 
> > > Well I hit my head after this one folks. The version of NautilusPython
> > > that Nautilus was loading in my test VM was the original, from-repo
> > > version, not our modified version. **D'oh!**
> > > 
> > > "Well that's just a simple fix, I just have to build it and import it
> > > into Nautilus in the testing VM!", I assumed, before realizing that
> > > while my modified NautilusPython built, Nautilus _would not accept it_.
> > > Nautilus would just _hang_ with little to no output.
> > > 
> > > After a few emails, Marek pointed me in the correct direction with the
> > > `nautilus-3.0` branch of NautilusPython, which, while 6 years since the
> > > last commit, worked with the latest version. Alright no problem. Rebase
> > > my commits on that branch, rebuild, transfer the newly-built
> > > shared-library over and bam, Nautilus runs again! And we have a provider
> > > that's not NULL, hooray!
> > > 
> > > And then, ladies and gentlemen, problem #2 reared _its_ ugly head.
> > > 
> > > Here's the code to get a list (`GList*`) of providers to use with a
> > > Nautilus extension:
> > > 
> > > providers = nautilus_module_get_extensions_for_type
> > > (NAUTILUS_TYPE_INFO_PROVIDER);
> > > 
> > > While we were getting a _non-null_ provider value, the value we received
> > > was _different_ from the one returned by the method we called. "Wat?"
> > > you say, and I too said the same. For some reason we were returning a
> > > 64-bit `GList` pointer from `nautilus_module_get_extensions_for_type`,
> > > but storing a 32-bit `GList` pointer in `providers`.
> > > 
> > > I tried all sorts of weird tricks to get this fixed. Nobody I talked to
> > > seemed to have a solution, and after wrestling with it for a few days I
> > > begrudingly settled on this very elegant workaround:
> > > 
> > > // TODO: Providers ends up as 0x55f65ac0
> > > // when method is returning 0x555555f65ac0, very odd...
> > > providers = (GList*) (nautilus_module_get_extensions_for_type
> > > (NAUTILUS_TYPE_INFO_PROVIDER) + 0x555500000000);
> > > 
> > > Yes I know this is terrible. It did work though, and I needed to stop
> > > hitting this strange bug and get on with patching, so that's where it
> > > currently sits. I'm still actively looking for a proper solution. If
> > > anyone knows why a 64bit pointer might get truncated to a 32bit pointer
> > > after a function call in C please do let me know! You can find the full
> > > code
> > > [here](https://github.com/anoadragon453/nautilus/blob/master/src/nautilus-mime-actions.c#L2496)
> > >  and the `type` method
> > > [here](https://github.com/anoadragon453/nautilus/blob/master/src/nautilus-module.c#L269).
> > >  
> > > After this was out of the way, and a handful of more methods were
> > > implemented, we finally had a working solution between the `qvm_trust`
> > > extension and our patched Nautilus! It was beautiful, really.
> > > 
> > > ## Conclusion and going forward
> > > 
> > > My [email](https://amorgan.xyz/upstream-request.html) to the [Nautilus
> > > mailing list](https://mail.gnome.org/archives/nautilus-list/) is still
> > > awaiting moderation. GUADEC has now concluded, and with no update on the
> > > situation it seems I need to do some more active poking of people to get
> > > moderation approval. We'll see where that lands, the code still needs to
> > > be cleaned up a bit before sending it upstream anyways, so I'm not too
> > > worried.
> > > 
> > > At this point in the project, we essentially have the following tasks left:
> > > 
> > > * Patch KDE Dolphin to provide the same functionality as Nautilus now does
> > > * Finish up some small tasks with the daemon like logging and some more
> > > interfacing with the cli tool
> > > * Code cleanup, linting, tests
> > > * Integrate into main QubesOS repos
> > > 
> > > I'm going to prioritize the latter 3 bullet points at this point to
> > > ensure we get a really solid core implementation down of the project. I
> > > don't want to spend another couple weeks patching Dolphin only to run
> > > out of time for a general cleanup and other polish. I will try to pour
> > > through the Dolphin code and note down everything that one would need to
> > > do with Dolphin to make it work with file trust attributes, so that in
> > > the future either myself or someone else can give it a shot.
> > > 
> > > It may end up that Dolphin already has most of the functionality and the
> > > patch will be very small, we'll see!
> > > 
> > > Anyways, for now I'm going to start on finishing the remaining small
> > > tasks, and will post any questions regarding packaging and/or cleanup to
> > > the qubes-devel mailing list.
> > > 
> > > As always, you can find the code
> > > [here](https://github.com/anoadragon453/qubes-mime-types).
> > > 
> > > And as of now, you can also find the patched code for
> > > [Nautilus](https://github.com/anoadragon453/nautilus) and
> > > [NautilusPython](https://github.com/anoadragon453/nautilus-python/tree/nautilus-3.0)
> > >  on Github as well. Make sure that when you're inspecting the
> > > NautilusPython code, you're looking at the `nautilus-3.0` branch. That's
> > > where all the important commits are!
> > > 
> > > That's all for now, thanks for reading!
> > > 
> 
> > Marek,
> 
> > The git commits for nautilus/python seem like a bit of a mess at the
> > moment. Are you currently reviewing them individually or can I squash
> > them into just a few and force push to the repo?
> 
> Feel free to squash them.
> 
> 

Hey Marek,

Nautilus has been squashed into one, easily-reviewable commit:
https://github.com/anoadragon453/nautilus/commit/1325725451220447f53e5ab3016423e6d3372682


Currently doing the same for nautilus-python.

Thanks,
Andrew Morgan

-- 
You received this message because you are subscribed to the Google Groups \
"qubes-devel" group. To unsubscribe from this group and stop receiving emails from \
it, send an email to qubes-devel+unsubscribe@googlegroups.com. To post to this group, \
send email to qubes-devel@googlegroups.com. To view this discussion on the web visit \
https://groups.google.com/d/msgid/qubes-devel/omfm8l%24vlh%241%40blaine.gmane.org. \
For more options, visit https://groups.google.com/d/optout.


["signature.asc" (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic