Mordak | 5 years ago | on: Rust Foundation: Hello, World
Mordak's comments
Mordak | 5 years ago | on: Chromium project finds that 70% of security defects are memory safety problems
The guy who maintains it said in the reddit thread[2] about this same topic that the Google people have been sending him good PRs, which is presumably related to integrating Rust into Chrome.
[1] https://crates.io/crates/cxx [2] https://reddit.com/r/rust/comments/gpdorw/the_chromium_proje...
Mordak | 5 years ago | on: Chromium project finds that 70% of security defects are memory safety problems
We built a new project in all "modern C++". It is 100% shared_ptr, unique_ptr, std::string, RAII, etc. It initially targeted C++17 specifically to get all the "modern C++" goodness.
It segfaults. It segfaults all the time. It is entirely routine for us to run a new build through the CI process and find segfaults. We fuzz it and find dozens of segfaults. Segfaults because of uninitialized memory. Segfaults because dereferencing pointers. Segfaults because running off the end of arrays. Segfaults because trusting input from the outside world ("the length of this payload is X bytes").
This is where the "modern C++" people tell me we must be doing it wrong. But the reality is that "modern C++" isn't as safe or as foolproof as the advocates say it is. But don't take my word for it - this whole thread is about Google people coming to the same conclusion.
Meanwhile I can throw a new dev at Rust and watch them go from zero to works in a week or so, and their code doesn't segfault, doesn't panic, and actually does what it is supposed to do the first time. Code reviews are easy because I don't have to ponder the memory safety and correctness of every line of code. Reasoning about unwrap() is trivial. Finding unsafe {} is trivial (and removing it is also usually easy).
Mordak | 5 years ago | on: Re: Integrating "safe" languages into OpenBSD? (2017)
Mordak | 5 years ago | on: Re: Integrating "safe" languages into OpenBSD? (2017)
Rust and OpenBSD share a lot of technical values though so maybe this isn't surprising. Rust values safety and correctness. OpenBSD values safety and correctness. Rust values 'Just Works' with all the nice things cargo does and the whole 'fearless refactoring / concurrency' thing. OpenBSD values 'Just Works' with sane defaults and the 'batteries included' base system.
Mordak | 6 years ago | on: CBOR – Concise Binary Object Representation
FlatBuffers, Protobuf, Cap'n Proto, etc., all require an external schema configuration that you compile into a code chunk that you include into your program. Without this it is impossible to make sense of the data. In our case, the data is semi-structured and changes frequently. The prospect of maintaining a schema registry for all the data users and keeping everyone up to date and backwards compatible is enough of a burden that it was excluded.
Avro also uses schemas, but since the schema is embedded in the file it is self-describing so the reader does not need to do anything special to interpret the data. But Avro's C library is buggy and the python deserialization performance was terrible, so Avro was not selected.
Mordak | 6 years ago | on: CBOR – Concise Binary Object Representation
- Msgpack serialization and deserialization is very fast in many languages - often 100x faster then JSON
- Msgpack natively supports encoding binary data
- Msgpack has type extensions, making it trivial to represent common types in an efficient way (eg. IPv4 address, timestamps)
- Msgpack has good libraries available in many languages
If you do not care about those things (no binary data, no need for extended types, not performance critical) then JSON is just fine.
Mordak | 6 years ago | on: SCons: A Software Construction Tool
Mordak | 6 years ago | on: SCons: A Software Construction Tool
Having used both scons and waf, and also having used make, cmake and cargo, I would take any of the last three over scons or waf in a heartbeat. I think cargo is far and away the nicest to use because there is very little to actually do to build your program. Using waf or scons was always an exercise of 'I added a header file, so now I need to figure out the scons/waf API in order to tell it what to do with it'.
Mordak | 7 years ago | on: Secure CGI Applications in C on OpenBSD
The OpenBSD httpd is privilege separated and chroot()ed, and each component only pledge()s the syscalls it needs. This reduces to just the syscalls needed to do filesystem operations inside the chroot, log, and talk on the internet. In the CGI context, if your application only needs to read / write to stdio to talk to httpd, then you can limit yourself to just stdio, or if it only needs to read files then it can limit itself to just those syscalls. If your application does something outside of your pledge() (eg. exec(), because it got pwned) then the kernel will kill it.
Mordak | 7 years ago | on: OpenBSD 6.4 released
There is an in-between case where you have a console, but do not control the boot loader (so cannot boot bsd.rd) and cannot boot an iso. It sounds like maybe you are in this situation? In this case, you can still follow the upgrade directions as if you do not have a console[1]. Alternately, sometimes when I am in this situation I just download the install kernel (bsd.rd), move it where the boot loader is hard-coded to look (/bsd), and then reboot. The boot loader will boot the install kernel and you can follow the usual / common upgrade procedure on the console.
There is also autoinstall[2], which can automate the upgrade procedure for you and reduces upgrades to just rebooting into bsd.rd and waiting a bit. There is a bit of effort to create the response file, etc., so this may be overkill for a single instance but is very useful for upgrading fleets of machines quickly.
[1] https://www.openbsd.org/faq/upgrade64.html#NoInstKern [2] https://man.openbsd.org/autoinstall
Mordak | 7 years ago | on: Retguard: An improved stack protector for OpenBSD
I found that the runtime overhead was about 2% on average, but there are many factors that contribute.
Mordak | 7 years ago | on: Retguard: An improved stack protector for OpenBSD
1. We don't silently skip instrumentation. If we can't find a free register then we will force the frame setup code to the front of the function so we can get one. See the diff in PEI::calculateSaveRestoreBlocks().
2. We do spill the calculated value to the stack. This is unavoidable in many cases (non-leaf functions). It would be an optimization to not do this in leaf functions, but this would also mean finding a register that is unused throughout the function. This turns out to be a small number of functions, so we didn't pursue it for the initial implementation.
3. I'm not sure what you mean by the cookies are shared. Do you just mean that they are all in the openbsd.randomdata section? They have to live somewhere. Being able to read arbitrary memory in the openbsd.randomdata section would leak them, yes, though this doesn't seem to have been a problem for the existing stack canary, which lives in the same section. I see that RAP keeps the cookie on a register, which sounds like a neat idea. I'd be curious to see how you manage to rotate the cookie arbitrarily.
4. I'm glad you like the int3 stuffing. :-) We could always make the int3 sled longer if it turns out these rets are still accessible in gadgets that terminate on the return instruction. Have you found any?
Anyway, I'm happy to see your commentary on this. You guys do some nice work! If you have other suggestions for improvement I'd be happy to hear them. You can email me at mortimer@.
Mordak | 8 years ago | on: Meltdown fix committed to OpenBSD
> As a compromise, I allowed them to silently patch the vulnerability.
It's pretty easy to argue that OpenBSD doesn't like embargoes, but it's pretty hard to argue that they ignore embargoes and patch whenever they want to. In this specific case, the project asked and received permission to patch early. The fact that the researcher regrets this in hindsight is beside the point.
Mordak | 8 years ago | on: “Oracle laid off all Solaris tech staff in a classic silent EOL of the product”
Mordak | 8 years ago | on: Retguard: OpenBSD/Clang
Mordak | 8 years ago | on: Retguard: OpenBSD/Clang
I like SafeStack, but was disappointed to learn about the limitations with shared libraries. Some SafeStack is better than no SafeStack though, and it can probably be turned on without too much effort.
Mordak | 8 years ago | on: Retguard: OpenBSD/Clang
Actually removing c2/c3 bytes and actively reducing the gadget space is a different endeavour. There has been a bunch of academic work in this regard, with varying levels of success. Some would say it is a fool's errand to try to remove all the ROP gadgets, but that's what fools are for. Stay tuned. :-)
Mordak | 8 years ago | on: Retguard: OpenBSD/Clang
Microsoft's CFG is cool, but works on the other end to this - by protecting CALL instructions instead of RET.
Stack cookies are similar, yes. This mechanism combines two ASLR-randomized values (the caller address and the stack address) to control program flow. Stack canaries use a constant random cookie per object file to detect stack smashing. Retguard raises the bar for successful ROP attacks, just as CFG raises the bar for function pointer corruption attacks.
Full disclosure, I am the author of the clang diff that kicked this off. The appeal of this mechanism is that it is cheap enough to apply in every function, pollutes the ROP gadget space with instructions that permute the next return address, and requires attackers to have more information in order to kick off ROP chains (the address where they are writing their ROP chain). I know about some of the other stuff people are working on (CPI seems promising), and look forward to turning those things on when possible. Meanwhile, this mitigation is cheap, localized inside every function, and doesn't require any program modification in the vast majority of situations (programs that inspect stack frames without consulting the unwind info may have problems), so is fairly easy to turn on everywhere.
Mordak | 8 years ago | on: Retguard: OpenBSD/Clang
But you don't always have stack address leaks. Presently, in order to ROP you need (a) a leaked address to the space where your gadgets live and (b) the ability to write your ROP chain somewhere where the program will return into it. With this scheme, you now also need (c) the exact address where you are writing your ROP chain.
Not all info leak vulnerabilities leak arbitrary memory of the attacker's choosing. If they did, stack canaries would be pretty useless. So for those cases where a stack address leak is unavailable, this raises the bar against ROP.
- Parsing untrusted inputs. nom[1] is a joy to use, and lets you kind of effortlessly and fearlessly process random input from wherever and turn it into useful data structures. If your data is very regular or in a standard format, then serde[3] is very hard to beat if it just boils down to 'derive(Deserialize, Serialize)' on your Rust struct.
- Bulk data processing. rayon[2] makes pegging your machine easy if you have a lot of work do to, and the Rust semantics around thread safety, data ownership, and explicit copying make it kind of trivial to reason about how your data gets from input to output and tuning it to be crazy fast.
- Generic systems language. Maybe this one is personal, but I find it's more productive to write generic cli applications and whatnot in Rust over C, ruby, or python. There are some nice libs to make part of this pleasant (structopt[4]) but this really boils down to reliability. Because Rust makes it obvious where things can fail so I can deal with it I have way higher 'just works' outcomes in Rust than other languages. I might spend slightly more time making it compile, but I spend basically zero time debugging runtime failures and this is kind of indescribably amazing.
[1] https://docs.rs/nom/6.1.0/nom/index.html
[2] https://docs.rs/rayon/1.5.0/rayon/
[3] https://serde.rs/
[4] https://docs.rs/structopt/0.3.21/structopt/