1 # Address Space Layout Randomisation 2 3 Briefly, see: `psecflags(1)`, `security-flags(5)` 4 5 ## Administration 6 7 ASLR is implemented via process security-flags (which we introduce), there are 8 four sets of flags per-process: The effective, inheritable, upper, and lower 9 sets (see `security-flags(5)`). The effective set is immutable, it can only 10 change when the process calls `exec(2)`, at which point the effective set is 11 replaced by the inheritable set (with one exception). Security flags are 12 inherited upon `fork(2)` (but the inheritable set is not promoted until 13 `exec(2)`, as mentioned). The upper and lower sets bound the permitted values 14 of the inheritable set. 15 16 This is such that a given execution of an executable has a constant set of 17 security-flags, which simplifies things for everyone. 18 19 This unfortunately means that to enable ASLR fully system-wide, requires a 20 reboot or at least restart of a majority of services. 21 22 The system-wide ASLR flag is an SMF property on the new service 23 `svc:/system/process-security`, which contains `default`, `upper`, and `lower` 24 property groups, with one boolean property per implemented flag (see, again, 25 `security-flags(5)`). These will only affect services (and their children) 26 started via SMF after the values have been changed. 27 28 Per-process setting (and inspecting) of security-flags is done via 29 `psecflags(1)`. 30 31 Per-service setting of security-flags is achievable by the `security_flags` 32 property on the service `method_context`. A `default` pseudo-flag specifies 33 the flags from `svc:/system/process-security`, and flags can be 34 added/subtracted from there much the same as with `privileges(5)`. 35 36 ## Privilege 37 38 A process may change the security-flags of any process to which it could send 39 a signal with `kill(2)`, as long as the process also has the 40 `PRIV_PROC_SECFLAGS` privilege. This privilege is granted by default, but is 41 not a `basic` privilege. If you have configured custom privileges for certain 42 users or services, they will not automatically gain the new 43 `PRIV_PROC_SECFLAGS` (unfortunately). 44 45 ## Executable tagging 46 47 There is a somewhat compatible property of dynamic executables, `DT_SUNW_ASLR` 48 which controls the ASLR behaviour of a given executable. If this dynamic tag 49 has a value of 1, ASLR is always enabled for an execution of this process. If 50 the tag has a value of 0, ASLR is never enabled for an execution of this 51 process. The default is to inherit the ASLR flag as normal. 52 53 This allows a process for which ASLR is known to be problematic to explicitly 54 forbid it, and for processes of special sensitivity to mandate it. 55 56 This is controlled via the `-z aslr` flag to `ld(1)`. 57 58 59 ## Per-zone configuration 60 61 The default security flags for a zone, and the upper and lower limits, may be 62 specified with the security-flags resource in zonecfg(1M). These are applied 63 to every process in NGZs (unlike the GZ, where there are a small number of 64 processes we must miss) 65 66 67 ## Missing bits/Problems/Worries 68 69 ### The stack skewing may skew too much of the stack 70 71 At present, we skew the absolute base of the stack, which means the gap 72 between a user stack frame and the process environment is constant. I have 73 this vague memory that that's sub-par, and that we want to skew the stack 74 _after_ the environment, etc. I could be entirely wrong about that though. 75 76 ### We skew each mapping separately 77 78 Some systems calculate a random skew for the various parts of a process at 79 execution time, and apply that same skew to each mapping. That obviously 80 minimises the performance impact of this significantly for processes that 81 perform many mappings. 82 83 Due to some unfortunate aspects of how we manage the user address space and 84 mappings, we don't do that right now. We calculate a separate random skew for 85 each mapping we attempt. 86 87 ### The way we skew mappings is problematic 88 89 The user address space is currently managed somewhat unfortunately (from our 90 point of view, at least). When attempting a mapping we first determine the 91 highest gap into which the requested mapping can fit, and then we place the 92 mapping at the highest address in that gap. This is how we manage user 93 fragmentation. 94 95 The current ASLR implementation works in basically the same way. We still 96 find the highest gap into which the given mapping may fit, and choose the 97 highest address at which it may fit. The only difference is that we then slew 98 it backward by a random (but co-aligned), amount. 99 100 This is obviously not as random as it could be, but is the easiest way I've 101 found in the current code base for introducing uncertainty while also 102 preserving any attempt at preventing unbounded user fragmentation. 103 104 It is not impossible to imagine a long-lived process that makes many mappings 105 being in a position where mappings later in its life are 100% predictable 106 given this implementation, however. In fact, I think it is fairly likely. 107 108 I think the most at risk would be a process which makes many mappings, and 109 uses `dlopen(3c)` at unpredictable times (rather than, as is most common, during 110 setup). Dynamic objects tend to have strict (and high) alignment requirements 111 which in such a process are likely to only be fulfillable at a single location 112 in the address space gap we choose, and thus be entirely predictable. 113 114 ### Randomisation of executable base addresses requires PIE 115 116 To randomise the executable base address, we need position independent 117 executables, which appears like it would turn into a whole separate project 118 (though perhaps not too large a project). That code isn't here, so the 119 executable base is fixed. 120 121 This means that rather than return-to-libc one could return-to-executable 122 trivially and successfully, I think. (That would include using the 123 executable's PLT to vector yourself to libc. Should the executable have a PLT 124 entry for something useful to you).