Read DVDs with bogus permissions in Ubuntu
What if your DVD recorder sets bogus permissions to your DVDs?
My dad has a DVD recorder (a Panasonic DMR-EX769) which he uses to record TV programs to watch them later. That device includes an internal hard disk so the recorded shows can later be burnt in a DVD. Unfortunately such DVDs cannot be played in Ubuntu. Why? Because the recorder sets bogus permissions to the directories: all directories only have the read permission set. When the user (my dad) inserts the DVD into the reader, Ubuntu correctly mounts the DVD and grants ownership of its files and directories to the user. But since the permissions of the directories inside the DVD are wrong, the user itself cannot enter any directory, effectively preventing the user to be able to use that DVD. The net effect is that the DVD cannot be played.
DVDs use the UDF. This format seems to include support for permissions. According to some comments I read when looking information about this, Windows seems to ignore them (although I have not verified this fact by myself). But the UDF driver in the Linux kernel seems to honour these permissions, even if they happen to be meaningless.
This issue affects Ubuntu (and probably other Linux distributions) according to these two bug reports: #10550 and #635499.
Technically speaking this is not a blocker since it can be worked around by being superuser (using sudo
and friends) or mounting the DVD passing a mode
and dmode
option at mount-time. This may work if you just want to retrieve your files from the DVD but it is ludicrous if your goal was as mundane as trying to play a DVD.
An expert Linux user is now thinking just
. Ok, I tried this first, but, you know, Linux (or whoever is responsible for this bit) happily ignores you. So the only way to change the permissions is first unmounting and then mounting again: remount
the DVD with the appropiate mode
and dmode
options, no big deal-o remount
does not work for that.
For Ubuntu 14.04 LTS, the problem lies in package udisks2
. This package provides a DBus service for disk management, including automounting facilities when a new disk is inserted (i.e. a DVD or a USB pendrive). One of the applications provided by this package, udisksctl
, can mount and unmount drives for you (which is very nice and handy). As a security measure it filters out unsafe mount-options (those that would let the user of this tool elevate its privileges). Sadly, both mode
and dmode
are filtered, so it is not possible to use that tool. So we have to resort with old-school mount
tool (which is what udisks
is internally calling, probably).
Abovementioned bug report #635499 includes a comment with a (more or less) crude patch in the source code of udisks
(version 1) which tries to dynamically add mode
and dmode
flags when a readonly DVD is about to be mounted. The patch cannot be applied directly to udisks2
but it gives an idea of the defaults used by udisks
and how it filters out options in udisksctl
.
So our goal is make a minimal patch to udisk2
so it always passes mode=0400
and dmode=0500
when it mounts an UDF filesystem. This will force the files to have r--------
permissions (only the owner can read the file) and directories r-x------
(only the owner can read and enter the directory). Note that this patch is obviously not realistic for general consumption since some systems can use UDF filesystems in a read/write fashion (according to Wikipedia for DVD-RW with packet writing). This patch would effectively prevent that. But, this is not the scenario of my dad, who only wants to be able the DVDs with films he recorded from the TV.
Setup your environment
Before anything, let's create some working directory and do everything therein.
Now we need to install a tool that we will need later when building the package.
Now we have to be sure that the package will be buildable. Since Ubuntu is a Debian derivative it uses apt
for package managing. This nice tool includes an option to install all the build dependencies of another package. This is, all the (development) packages you are going to need to successfully build the package. This may install a ton or just a few packages into your system, depending on its current installation state.
This may take a few minutes. The next step is getting the source. Again we will use apt
for this.
apt-get
source downloads the code, unpacks it and applies any patches of the distribution (in this case there are two patches).
Build the current package
The next step is to make sure we can build the existing version of the package. This may take a few minutes.
Now the packages should have been built in the upper directory.
These are the packages files that Ubuntu uses to install software. But now they are not interesting to us since they still do not do what we want. Let's remove the packages first, to make sure that later we install the new ones.
Use the source, Luke
Time to hack! We will modify the file src/udiskslinuxfilesystem.c
using our favorite editor. Around line 300 we will see the following.
298
299
300
301
/* ---------------------- udf -------------------- */
static const gchar *udf_defaults[] = { "uid=", "gid=", "iocharset=utf8", "umask=0077", NULL };
static const gchar *udf_allow[] = { "iocharset=", "umask=", NULL };
The first array is the default parameters that udisks
uses when mounting a filesystem. The second array are the parameters allowed by udisksctl
in its mount
subcommand. Let's change these two arrays to
298
299
300
301
/* ---------------------- udf -------------------- */
static const gchar *udf_defaults[] = { "uid=", "gid=", "iocharset=utf8", "umask=0077", "mode=0400", "dmode=0500", NULL };
static const gchar *udf_allow[] = { "iocharset=", "umask=", "mode=", "dmode=", NULL };
This will set mode=0400
and dmode=0500
by default. We will be able to override them in udisksctl
tool also. Save the file and now let's rebuild the package.
Rebuild package
dpkg
has detected that we changed a file and tells us to make a patch for it. It even tells us what we have to do.
It asks us the name of the patch, I used force-udf-permissions
(press $EDITOR
. Just save it.
Now we can build the package. Again this will take a few minutes.
Now there should be several deb
files again, in the upper directory.
Cool!
Installation of the new packages
Let's install the only two that are actually needed (the other ones are development files and development documentation).
Now restart Ubuntu (maybe this is not needed but I'm now too lazy to figure out what would be the minimum required to reload the udisks2
thing). Once logged on, insert a DVD, wait it to be mounted. Now open a terminal and check that the mode
and dmode
flags were passed:
Yeah.
Hold the package
Next time we update Ubuntu, it will overwrite our package, so make sure it is held.
Future work
The next step is to figure out how to more or less automate this process when Ubuntu updates a new version of udisks2
.
Have a good day.