{"action":"created","issue":{"url":"https://api.github.com/repos/NixOS/nixpkgs/issues/7220","repository_url":"https://api.github.com/repos/NixOS/nixpkgs","labels_url":"https://api.github.com/repos/NixOS/nixpkgs/issues/7220/labels{/name}","comments_url":"https://api.github.com/repos/NixOS/nixpkgs/issues/7220/comments","events_url":"https://api.github.com/repos/NixOS/nixpkgs/issues/7220/events","html_url":"https://github.com/NixOS/nixpkgs/issues/7220","id":66684519,"number":7220,"title":"RFC: Harden(ed) NixOS","user":{"login":"thoughtpolice","id":3416,"avatar_url":"https://avatars.githubusercontent.com/u/3416?v=3","gravatar_id":"","url":"https://api.github.com/users/thoughtpolice","html_url":"https://github.com/thoughtpolice","followers_url":"https://api.github.com/users/thoughtpolice/followers","following_url":"https://api.github.com/users/thoughtpolice/following{/other_user}","gists_url":"https://api.github.com/users/thoughtpolice/gists{/gist_id}","starred_url":"https://api.github.com/users/thoughtpolice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thoughtpolice/subscriptions","organizations_url":"https://api.github.com/users/thoughtpolice/orgs","repos_url":"https://api.github.com/users/thoughtpolice/repos","events_url":"https://api.github.com/users/thoughtpolice/events{/privacy}","received_events_url":"https://api.github.com/users/thoughtpolice/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/0.kind:%20enhancement","name":"0.kind: enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/1.severity:%20mass-rebuild","name":"1.severity: mass-rebuild","color":"e11d21"},{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/1.severity:%20security","name":"1.severity: security","color":"e11d21"},{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/2.status:%20work-in-progress","name":"2.status: work-in-progress","color":"e6e6e6"},{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/6.topic:%20grsecurity","name":"6.topic: grsecurity","color":"fef2c0"},{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/6.topic:%20kernel","name":"6.topic: kernel","color":"fef2c0"},{"url":"https://api.github.com/repos/NixOS/nixpkgs/labels/6.topic:%20nixos","name":"6.topic: nixos","color":"fef2c0"}],"state":"closed","locked":false,"assignee":{"login":"thoughtpolice","id":3416,"avatar_url":"https://avatars.githubusercontent.com/u/3416?v=3","gravatar_id":"","url":"https://api.github.com/users/thoughtpolice","html_url":"https://github.com/thoughtpolice","followers_url":"https://api.github.com/users/thoughtpolice/followers","following_url":"https://api.github.com/users/thoughtpolice/following{/other_user}","gists_url":"https://api.github.com/users/thoughtpolice/gists{/gist_id}","starred_url":"https://api.github.com/users/thoughtpolice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thoughtpolice/subscriptions","organizations_url":"https://api.github.com/users/thoughtpolice/orgs","repos_url":"https://api.github.com/users/thoughtpolice/repos","events_url":"https://api.github.com/users/thoughtpolice/events{/privacy}","received_events_url":"https://api.github.com/users/thoughtpolice/received_events","type":"User","site_admin":false},"assignees":[{"login":"thoughtpolice","id":3416,"avatar_url":"https://avatars.githubusercontent.com/u/3416?v=3","gravatar_id":"","url":"https://api.github.com/users/thoughtpolice","html_url":"https://github.com/thoughtpolice","followers_url":"https://api.github.com/users/thoughtpolice/followers","following_url":"https://api.github.com/users/thoughtpolice/following{/other_user}","gists_url":"https://api.github.com/users/thoughtpolice/gists{/gist_id}","starred_url":"https://api.github.com/users/thoughtpolice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thoughtpolice/subscriptions","organizations_url":"https://api.github.com/users/thoughtpolice/orgs","repos_url":"https://api.github.com/users/thoughtpolice/repos","events_url":"https://api.github.com/users/thoughtpolice/events{/privacy}","received_events_url":"https://api.github.com/users/thoughtpolice/received_events","type":"User","site_admin":false}],"milestone":null,"comments":68,"created_at":"2015-04-06T19:26:00Z","updated_at":"2016-10-07T16:30:36Z","closed_at":"2016-08-31T18:59:26Z","body":"(Spurred by some conversation in #7212, so I decided to write down my thoughts.)\r\n\r\nCurrently, NixOS and Nixpkgs have a lot of areas in which the security story can improve. While I think we're well positioned to take care of many of these, it's going to take some work, and others we'll need to reach consensus on. (The Good News is that many other people have gone down this road, so we have some good things to learn from)\r\n\r\nAs a rough starting point, I have identified roughly 5 major areas to look for future enhancements, with my personal suggestions on what we might want to do.\r\n\r\n## Binary hardening\r\n\r\nAs inspired by #7212, currently, NixOS doesn't default to enabling any hardening capabilities in GCC. There are an array of things we can do here to mitigate exploitability, that we can either enforce as a GCC spec file, or as part of `NIX_CFLAGS`/`gcc-wrapper`. Here are a few of them:\r\n\r\n  - Static compile-time enhancements via `-D_FORTIFY_SOURCE=2` to improve protections for various built in string/buffer functions.\r\n  - Position-independent-executables to help defend against things like ROP-based code exploitation attacks via `-pie -fPIC` (PIEs are essentially just shared-objects-in-disguise much like transformers are robots-in-disguise).\r\n  - `-fno-strict-overflow` protects against the compiler optimizing away arithmetic overflow tests, which can happen when it gets particularly aggressive about undefined behavior.\r\n  - Stack protection via `-fstack-protector*`.\r\n    - The default `-fstack-protector` protects functions with calls to things like `alloca` or ones that allocate more than 8 bytes of stack data. This buffer size can be controlled via `--ssp-buffer-size`, for example `--ssp-buffer-size=1` triggers on *any* stack allocations..\r\n    - GCC 4.9 also supports `-fstack-protector-strong`, which implies more coverage than `-fstack-protector` by default.\r\n    - There is also `-fstack-protector-all` which does this for *all* functions. I am pretty sure this implies `--ssp-buffer-size=1`, but I'm not 100%.\r\n  - PLT/GOT protection: we need `-z relro` to mark dynamic relocations by the dynamic linker as read-only after `ld.so` resolves them. However, we also need `-z now` in order to force non-lazy resolution of relocations so the linker resolves them all at startup: otherwise they are performed on demand, and not marked as read-only until resolved (by which point an attacker could have used an arbitrary write to overwrite the relocation).\r\n\r\n**Suggestion**: default all expressions to `-fstack-protector-all --ssp-buffer-size=1 -D_FORTIFY_SOURCE=2 -pie -fPIC -z relro -z now -fno-strict-overflow` as part of `cc/ld`. In other words, the whole gamut. For example, `mkDerivation` could support `disableHardeningOptions = true;` to disable options in specific expressions.\r\n\r\n**Implications**: actually, fairly large in theory. These all in conjunction can have a significant penalty to things like startup time (due to resolving dynamic symbols up front), or execution speed. In particular, `-fstack-protect-all` is going to be costly (I wouldn't say beyond utility, but probably a good 20% speed loss at least). Also, PIE is going to really, really hurt performance on `i686-linux`, because PIE steals a register from the pathetic 32bit register set. Just PIE alone will have a significant impact on 32bit users, and `-fstack-protect-all` will add insult to injury.\r\n\r\nReally, only benchmarking these things will tell us. I'd estimate the hit for these doesn't matter for a significant amount of software (common things like `systemd`, `coreutils`, anything that is `setuid`, etc). But a lot of things that are sort of nebulous middle grounds can be discussed on a maintainer-by-maintainer basis, I suppose (e.g. networking services are both performance *and* security critical, so we may want something better here).\r\n\r\n## Binary determinism\r\n\r\nThis is issue #2281. I've had this on my queue to finish integrating for a while now; with my new machine this can hopefully be a reality soon enough... Unfortunately as we didn't make the cut for GSoC 2015, there won't be any sponsored work on this. There is still the issue of GCC PGO determinism too, which does not have a clear consensus, but the large majority of the work is elsewhere.\r\n\r\n\r\n**Suggestion**: I get off my ass and merge this.\r\n\r\n## Service hardening\r\n\r\nCurrently, very few of our NixOS services try to take advantage of any security or isolation features that can be offered e.g. by `systemd`. Basic examples that are probably worthy of spreading around the tree:\r\n\r\n  - `PrivateTmp`, since a lot of services are probably fine with their own `/tmp` mount. (unless they do something weird like use it for cross service IPC, which is now handled by `/run`).\r\n  - `DevicePolicy`, which can restrict access to `/dev` (lots of them could get by with e.g. `\"closed\"`)\r\n  - `InaccessibleDirectories`, `ReadOnlyDirectories`, and `ReadWriteDirectories` (for example, some would never need access to `/home`, while others like `tarsnap` could always restrict themselves to `ReadOnlyDirectories=/` with a specific `ReadWriteDirectories` for the cache).\r\n  - `NoNewPrivileges`, which automatically sets `prctl(PR_SET_NO_NEW_PRIVS)` for daemons. Again, useful for services like `tarsnap` or logging services (but care is needed if e.g. things invoke `setuid` programs like `ping`).\r\n\r\n**Suggestion**: We begin enhancing services with these and encouraging maintainers of modules to do the same. Honestly this can probably be done pretty easily and fairly incrementally by maintainers or any interested newcomers.\r\n\r\nWe should pay attention to upstream systemd units or units from other distributions here too, since they'll have figured out some of this, too.\r\n\r\n## Kernel enhancements\r\n\r\nKernel security enhancements mostly come from one thing and one thing only (IMO): grsecurity. The good news is that grsecurity support mostly works with my module, and of course it's possible to go out of band with your own custom `linuxPackages`.\r\n\r\nOne thing is that we don't currently offer prebuilt grsecurity packages. Hydra actually builds them, but there's no way for the module to automagically select the right one. This should be fixed. Futhermore, the binary builds and module need some clean up (e.g. `RANDSTACK` is actually completely useless for pre-built binaries since the random offset can be known by any attacker, so `RANDSTACK` should always imply a local kernel build.)\r\n\r\nAlso, my grsecurity module could use a bit of work. Unfortunately it's split up in several places due to needing build/module support, but I do think this could be cleaned up/refactored a bit.\r\n\r\nThere are other things to consider, too. For example, there are kernel patches floating around to do various other things; it would be really nice, for example, if we could have a patch to randomize the MAC address assigned by the kernel - this would be good for my laptop and could be controlled by a boot switch for the kernel.\r\n\r\n**Suggestion**: Well, it mostly works I guess.\r\n\r\n## MAC/RBAC\r\n\r\nNixOS currently doesn't offer any form of policy enforcement in the place of MAC systems. There are a lot to choose from, but it basically comes down to AppArmor vs SELinux. Right now there's nobody really supporting either, so in lieu of this, the support that *does* exist is geared towards AppArmor. AppArmor isn't as expressive as SELinux, but it's a hell of a lot simpler and the policies are far easier to maintain. I think this is pretty important to get people to write policies.\r\n\r\nThe good news is the actual infrastructure is there: apparmor is packaged and works. There are even NixOS modules for it, but nothing really uses it. This is pretty easy though: we can begin clipping apparmor policies from upstream packages and places like Ubuntu.\r\n\r\n**Suggestion**: We should just start writing policies, and enforce AppArmor by default on NixOS. This is the best way to ensure people keep using it, IMO.\r\n\r\n### Sidenote: `gradm`\r\n\r\nThe story is better for grsecurity users: you get `gradm` which is a totally badass RBAC system. The unfortunate news is that last time I tried it, `gradm` was buggy on my 3.4 kernel, and I didn't take the time to find a way to reconcile things like wanting NixOS modules to declare RBAC policies with the self-learning mode. In practice it may just be best to instead have services that activate/deactivate the learning mode via `systemd`, or just do nothing at all and expect users to enforce it themselves.\r\n\r\n------------------------------------\r\n\r\n## Small-form categorized TODO list\r\n\r\n  - Binary hardening\r\n    - [ ] Enhance `gcc` to support transparent hardening.\r\n      - Option 1: Add these things to `NIX_CFLAGS`, might work OK.\r\n      - Option 2: Hack GCC. Hardened Gentoo does *not* use spec files, but there is an overlay that [patches GCC](https://gitweb.gentoo.org/proj/hardened-gccpatchset.git/tree/gcc-4.8.0/piepatch/40_all_gcc48_config_esp.patch) to automatically add the aforementioned options automatically. This does not imply `-D_FORTIFY_SOURCE=2` as far as I can tell, but that one *can* be added to `NIX_CFLAGS` most likely or `gcc-wrapper`.\r\n      - Note: `-D_FORTIFY_SOURCE=2` is, IIRC, only available at `-O2` or above, so *that* can be annoying if we don't deal with it in `gcc-wrapper`. Or we could just patch the stupid warnings it emits out of GCC, too.\r\n    - [ ] Implement RELRO/NOW binding (`-z relro` & `-z now`), as well as `-fno-strict-overflow`. \r\n    - [ ] Enable PIE. **NOTE**: Large 32bit performance implication.\r\n    - [ ] Decide on stack protector settings. **NOTE**: Performance implications.\r\n    - [ ] Default to hardened binaries and extend `mkDerivation` to allow opt-out.\r\n  - Binary determinism\r\n    - [ ] Merge #2281 upstream and make sure `system_tarball_pc` remains deterministic.\r\n    - [ ] Q: What to do about GCC PGO?\r\n  - Service hardening\r\n    - [ ] Enhance services, make them harder, better, faster, stronger (and hopefully more isolated).\r\n    - [ ] We should cross reference our services with upstream ones; many times an upstream will have a better one, or a distro will (such as ArchLinux).\r\n  - Kernel enhancements (grsec)\r\n    - [ ] Disable RANDSTACK on pre-built images (useless).\r\n    - [ ] Cleanup layout; split between nixpkgs, build-support, nixos. Can probably be refactored.\r\n    - [ ] Make the `grsecurity` module serve prebuilt images.\r\n  - MAC/RBAC\r\n    - [ ] Cut over to AppArmor 2.9 by default.\r\n    - [ ] Enable by default on NixOS.\r\n    - [ ] Enhance policy coverage for services.\r\n    - [ ] **(gradm)** Make sure it actually works.\r\n    - [ ] **(gradm)** Decide on learning mode support (or none if we decide to give up here).\r\n\r\nCC: @wizeman @domenkozar @peti @edolstra"},"comment":{"url":"https://api.github.com/repos/NixOS/nixpkgs/issues/comments/252298830","html_url":"https://github.com/NixOS/nixpkgs/issues/7220#issuecomment-252298830","issue_url":"https://api.github.com/repos/NixOS/nixpkgs/issues/7220","id":252298830,"user":{"login":"joachifm","id":41977,"avatar_url":"https://avatars.githubusercontent.com/u/41977?v=3","gravatar_id":"","url":"https://api.github.com/users/joachifm","html_url":"https://github.com/joachifm","followers_url":"https://api.github.com/users/joachifm/followers","following_url":"https://api.github.com/users/joachifm/following{/other_user}","gists_url":"https://api.github.com/users/joachifm/gists{/gist_id}","starred_url":"https://api.github.com/users/joachifm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joachifm/subscriptions","organizations_url":"https://api.github.com/users/joachifm/orgs","repos_url":"https://api.github.com/users/joachifm/repos","events_url":"https://api.github.com/users/joachifm/events{/privacy}","received_events_url":"https://api.github.com/users/joachifm/received_events","type":"User","site_admin":false},"created_at":"2016-10-07T16:30:36Z","updated_at":"2016-10-07T16:30:36Z","body":"@sorokin a temporary workaround is to use`hardeningDisable=\"stack-protector\" cc foo.c`, see https://github.com/NixOS/nixpkgs/issues/18995."}}
{"actor":{"display_login":"joachifm"}}