FS#60669 - [gitea] systemd service hardening

Attached to Project: Community Packages
Opened by Bruno Pagani (ArchangeGabriel) - Thursday, 01 November 2018, 14:07 GMT
Last edited by Jelle van der Waa (jelly) - Sunday, 03 September 2023, 09:59 GMT
Task Type Feature Request
Category Packages
Status Closed
Assigned To Bruno Pagani (ArchangeGabriel)
Architecture All
Severity Medium
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 1
Private No

Details

They are three things we need to investigate:

1. Further restricting syscall (currently only using the very generic @system-service).
2. Possible use of RestrictNamespaces?
3. Why setting SecureBits=noroot-locked results in:
```
Failed to set process secure bits: Operation not permitted
Failed at step SECUREBITS spawning /usr/bin/gitea: Operation not permitted
Main process exited, code=exited, status=213/SECUREBITS
```

I’m opening this ticket so that we keep track of this.
This task depends upon

Closed by  Jelle van der Waa (jelly)
Sunday, 03 September 2023, 09:59 GMT
Reason for closing:  Implemented
Additional comments about closing:  Some hardening has been implemented.
Comment by Julien Nicoulaud (nicoulaj) - Thursday, 01 November 2018, 21:55 GMT
I use gitea with builtin SSH server on port 22 (to have pretty clone URLs), and while hardening the service is nice, it broke my use case.

I did some quick and dirty testing to disable some rules in the service file and setcap CAP_NET_BIND_SERVICE:
```
AmbientCapabilities=CAP_NET_BIND_SERVICE
#CapabilityBoundingSet=
#NoNewPrivileges=True
#PrivateUsers=true
#PrivateDevices=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectControlGroups=yes
#ProtectKernelTunables=true
#ProtectKernelModules=yes
ReadWritePaths=/etc/gitea/app.ini /var/lib/gitea
#LockPersonality=true
#MemoryDenyWriteExecute=true
#RestrictRealtime=true
#SystemCallArchitectures=native
#SystemCallFilter=@system-service
```

(not sure what can be done about this, just wanted to make you aware of this use case while you are working on this)
Comment by Bruno Pagani (ArchangeGabriel) - Thursday, 01 November 2018, 22:11 GMT
Well the case of needing to bind (whether that would be for SSH or HTTP/HTTPS on standard ports) is indeed not well handled. I think the best way to work around this is to add documentation on the Wiki page for the required drop-in in those cases.

You don’t need to comment so many options btw, AmbientCapabilities=CAP_NET_BIND_SERVICE (and maybe the same for CapabilityBoundingSet=) should be enough.

That being said, you don’t need to use the builtin SSH server on port 22 to have pretty clone URLs, you can just use the normal sshd service on your system. But maybe you don’t run it on port 22?
Comment by Julien Nicoulaud (nicoulaj) - Thursday, 01 November 2018, 23:36 GMT
Yes, my sshd does not listen on port 22, an old habit. Also I wanted to keep things separate so I used the gitea builtin server, but maybe I should reconsider this.

A cleaner solution in `/etc/systemd/system/gitea.service.d/override.conf`:

[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
PrivateUsers=false

If I don't override PrivateUsers, gitea can't bind the port. I can add this to the wiki.
Comment by Bruno Pagani (ArchangeGabriel) - Friday, 02 November 2018, 11:47 GMT
Right “If this mode is enabled, all unit processes are run without privileges in the host user namespace (regardless if the unit's own user/group is "root" or not). Specifically this means that the process will have zero process capabilities on the host's user namespace, but full capabilities within the service's user namespace. Settings such as CapabilityBoundingSet= will affect only the latter, and there's no way to acquire additional capabilities in the host's user namespace.”.

I’ve added the override to the wiki. ;) Maybe we should move the SSH setup to its own section, and have the built-in SSH setup described there too.
Comment by Julien Nicoulaud (nicoulaj) - Friday, 02 November 2018, 12:33 GMT
LGTM, thanks for your work on this!
Comment by Gregory Van der Steen (Addow) - Monday, 05 November 2018, 15:12 GMT
@ArchangeGabriel, I have some news on my use case. We discussed in already in the comments of the gitea-bin AUR package.

I ran into two different problems and fixed them:
- Overriding PrivateUsers to false, fixed the first problem, as you mentioned in the comments and in the wiki (forgot to take a look at).
- I had to reset the SystemCallFilter and switch from whitelist to blacklist again, since the @system-service call filter was only recently introduced (systemd 2.39, June 2018). I am stuck at a slightly older systemd version. Overriding the SystemCallFilter is enough, so I can fully migrate from AUR to community version.
=> Commit: https://github.com/systemd/systemd/commit/705268414f6ba6aa96c56d6c39b5ebf74426e847#diff-163053d4ffcb73ea2816b74099583b2a

Just to inform you about the status of my particular issue.
Comment by Bruno Pagani (ArchangeGabriel) - Monday, 05 November 2018, 15:18 GMT
OK, so this should not be an issue for users on the latest version of systemd, i.e. supported one.

Note that regarding SystemCallFilter, the idea is to reduce the white list as much as possible using at least less groups than what is included in @system-service (and ideally whitelisting only required calls, but that is a lot of work). I did not do so yet because this requires a lot of time to investigate what is required, something I don’t have currently.
Comment by Gregory Van der Steen (Addow) - Monday, 05 November 2018, 16:02 GMT
Correct. I assume it's not an issue as of systemd v239.
Is it an option to add systemd (239.0+) as a dependency or optional dependency to make users aware?
Or is it a convention for a rolling-release OS like Arch?
Comment by Bruno Pagani (ArchangeGabriel) - Monday, 05 November 2018, 16:07 GMT
Hum well yes, on a rolling-release distro you are expected to use the latest available package in the repo. Anything else is not supported.
Comment by K.R. Zentner (krzentner) - Saturday, 01 December 2018, 04:51 GMT
I would recommend not setting ProtectHome=true, since gitea assumes that it can create ~/.ssh:
https://github.com/go-gitea/gitea/blob/master/modules/setting/setting.go#L859

This leads to a rather unobvious crash-on-start.

It's possible there's a feasible workaround, but after a few hours of debugging, the simplest solution I've found is to just disable ProtectHome. There shouldn't be anything important in /home/git/ on most systems besides .ssh/authorized_keys anyways, and gitea needs to be able to write that file.
Comment by Bruno Pagani (ArchangeGabriel) - Saturday, 01 December 2018, 12:20 GMT Comment by Mathijs van de Nes (mvdnes) - Saturday, 01 December 2018, 15:35 GMT
I encountered some errors due to ProtectSystem=strict.
On the admin dashboard, the option 'Resynchronize pre-receive, update and post-receive hooks of all repositories.' failed due to the file system of my git root being read-only to the gitea process.
By using ProtectSystem=full, this problem went away.
Comment by Bruno Pagani (ArchangeGabriel) - Saturday, 01 December 2018, 20:47 GMT
Where is your git root located? If you didn’t use the default location, you have to whitelist it in ReadWritePaths using e.g. a drop-in addition to the service.
Comment by Mathijs van de Nes (mvdnes) - Sunday, 02 December 2018, 09:08 GMT
Yes, it is in a custom location, on a different mount. Using a custom ReadWritePaths instead of ProtectSystem also did the trick. Thanks.
Comment by Bruno Pagani (ArchangeGabriel) - Sunday, 23 December 2018, 10:15 GMT
OK, since we now use a dedicated gitea user, issues with non-configuration of the git user such as krzentner one should go away.

@mvdnes: If you could extend the wiki page regarding configuring another repo location under “Tips and tricks”, that would be welcome.
Comment by Ouack Ouack (B3l3tte) - Tuesday, 28 April 2020, 14:24 GMT
I had an issue with service hardening that I reported here : https://github.com/go-gitea/gitea/issues/11231
I am too not binding ssh to port 22.
I am currently trying the override systemd conf. I am using systemd 245.5-2 and gitea 1.11.4-2.
Comment by Guillaume (Guillaume) - Saturday, 12 September 2020, 09:55 GMT
Currently, the ARM packages (which are based on this one) have a serious problem due to the syscall hardening (core is dumped by cat, resulting in post-receive hook not getting any parameters). This is due to the fact that SystemCallErrorNumber is not specified in gitea.service. If SystemCallErrorNumber=EPERM is added, all seems fine.

Info:
https://github.com/go-gitea/gitea/issues/9792
https://wiki.archlinux.org/index.php/Gitea#Process_dumped_core_on_ArchLinux_ARM
Comment by Bruno Pagani (ArchangeGabriel) - Sunday, 25 July 2021, 02:40 GMT
I’ve added some new hardening bits to the service file, currently in [community-testing], please try and report.
Comment by Buggy McBugFace (bugbot) - Tuesday, 08 August 2023, 19:11 GMT
This is an automated comment as this bug is open for more then 2 years. Please reply if you still experience this bug otherwise this issue will be closed after 1 month.

Loading...