A bittorrent client should not run as your main user. That should be self evident. It should run as a system user with no rights outside of the download directory. That way, any RCE exploits in the client would need to be coupled with privilege escalation in order to do serious damage.
This is also the default way to run Transmission (CLI/web): as the transmission
user, with primary group transmission
(169:169). That poses the question then: How do I manipulate the files created if they belong to a system user?
The easy answer to this is to join the system user’s group and see to it that added files are created with 77x permissions, i.e. that members of the group have write permissions equal to those of the file owner.
Transmission (the daemon/web appplication version) does make this possible but not necessarily easy and selfevident. Here’s how.
The main way to decide what permissions a file is ‘born’ with on linux is umask. Umask is the inverse of the octal permissions set. Basically, if the umask is 000
, the permissions are 777
. A common, default umask of 022
will result in files created with 755
permissions. That math is simple: 7-0=7, 7-2=5, 7-2=5.
This can be tested by changing the umask for a single session (thus not risking any permanent changes) and creating a file. Here’s a private file first:
$ umask 077
$ touch file_just_for_me
$ ls -lh file_just_for_me
-rw------- 1 mads mads 0 May 7 20:58 file_just_for_me
And then a file that is equally mine and the group’s:
$ umask 007
$ touch shared_file
$ ls -lh shared_file
-rw-rw---- 1 mads mads 0 May 7 20:59 shared_file
Transmission happens to have a “umask” setting. So surely it’s just a matter of popping in, say, 007
to ensure that new files are created with all permissions for owner and group alike, yes? Not quite. For two reasons.
The first is simple: Transmission is set to think of the umask setting as an integer. So a value of 007
will cause Transmission to refuse to start. A string value, i.e. "007"
, will get rewritten as 0, once Transmission starts and parses the settings file (remember to only edit settings.json while Transmission is stopped). You need to use the integer value corresponding to 007
which is just 7
, i.e.
...
"umask": 7,
...
The second can be a bit trickier to figure out. The Transmission daemon is not currently free to set it’s own umask value. It is circumscribed by how the daemon is run. Setting the “umask” as above will not have the desired effect on it’s own. I will need to make sure that the transmission
user’s umask for the session is also set to the desired value when the process is started.
As a non-system user I can call umask interactively, or have it set automatically whenever I open a terminal through my .bashrc
. System users cannot rely on this as they do not have such shell config files.
Fortunately, systemd service files allow me to set the umask for the process session. I copy the default .service
file to the user editable service file location (/etc/systemd/system
) and add the “UMask” setting to the [Service]
section:
...
[Service]
User=transmission
UMask=007
Type=notify
...
Note the capitalization and not reducing 007
to an integer.
The two settings taken together should make Transmission create nice, orderly -rw-rw----
files.
On a related note: If you want to make sure that files you add to the folder are accessible by the transmission daemon, the best way is to make it so that all new files are created with the directory’s group as the file’s group (rather than the user’s primary group as is the default). As I have talked about previously, that is accomplished using the setgid bit on the top level folder, e.g.
sudo chmod g+s /mnt/transmission
You should also keep in mind that files added this way will typically only be readable by the transmission
user, as they may belong to the transmission
group, but your own default umask is likely to be 022
which means that the file will only give a 5
permission setting to group members (i.e. read and execute but no write). This can, however, easily be circumvented, e.g. by a shell script that sets a session specific umask before files are copied/moved/created.