HNHacker News
TopNewBestAskShowJobs

zrm

2,995 karma · joined July 4, 2014

submissionscomments
zrm··on New 10 GbE USB adapters are cooler, smaller, cheaper
The problem with fibre isn't the sensitivity. It's that most endpoints have a 1Gbps copper port on them and then Cat6A ports can be used with the common devices but also allow you to add or relocate 10Gbps devices without rewiring the building again.
zrm··on "cat readme.txt" is not safe if you use iTerm2
> There is almost certainly no way that writing a "magic" byte sequence to a file will cause the storage device to misinterpret it as control data and change the mapping of logical to physical blocks.

Which is also what happens if you use parameterized SQL queries. Or not what happens when one of the lower layers has a bug, like Heartbleed.

There also have been several disk firmware bugs over the years in various models where writing a specific data pattern results in corruption because the drive interprets it as an internal sequence.

zrm··on "cat readme.txt" is not safe if you use iTerm2
The header and length of the payload are control data. It's still being concatenated even if it's binary. A common way to screw that one up is to measure the "length of payload" in two different ways, for example by using the return value of strlen or strnlen when setting the length of the payload but the return value of read(2) or std::string size() when sending/writing it or vice versa. If the data unexpectedly contains an interior NULL, or was expected to be NULL terminated and isn't, strnlen will return a different value than the amount of data read into the send buffer. Then the receiver may interpret user data after the interior NULL as the next header or, when they're reversed, interpret the next header as user data from the first message and user data from the next message as the next header.

Another fun one there is that if you copy data containing an interior NULL to a buffer using snprintf and only check the return value for errors but not an unexpectedly short length, it may have copied less data into the buffer than you expect. At which point sending the entire buffer will be sending uninitialized memory.

Likewise if the user data in a specific context is required to be a specific length, so you hard-code the "length of payload" for those messages without checking that the user data is actually the required length.

This is why it needs to be programmatic. You don't declare a struct with header fields and a payload length and then leave it for the user to fill them in, you make the same function copy N bytes of data into the payload buffer and increment the payload length field by N, and then make the payload buffer and length field both modifiable only via that function, and have the send/write function use the payload length from the header instead of taking it as an argument. Or take the length argument but then error out without writing the data if it doesn't match the one in the header.

zrm··on "cat readme.txt" is not safe if you use iTerm2
> If we can get that to raise a red flag with people (and agents), people won’t be trying to put control instructions alongside user content (without considering safeguards) as much.

At a basic level there is no avoiding this. There is only one network interface in most machines and both the in-band and out-of-band data are getting serialized into it one way or another. See also WiFi preamble injection.

These things are inherently recursive. You can't even really have a single place where all the serialization happens. It's user data in JSON in an HTTP stream in a TLS record in a TCP stream in an IP packet in an ethernet frame. Then it goes into a SQL query which goes into a B-tree node which goes into a filesystem extent which goes into a RAID stripe which goes into a logical block mapped to a physical block etc. All of those have control data in the same stream under the hood.

The actual mistake is leaving people to construct the combined data stream manually rather than programmatically. Manually is concatenating the user data directly into the SQL query, programmatically is parameterized queries.

zrm··on Backblaze has stopped backing up OneDrive and Dropbox folders and maybe others
You expect the files to still be accessible using relative paths. What do you expect to happen if your cloud storage file path is 50 characters long and is mounted in a folder which is 4050 characters long when PATH_MAX is 4096?

The sync application itself can handle this using openat(2) or similar and should probably be using that regardless to avoid races.

zrm··on Running out of disk space in production
If you create the file with 'mkswap --file' it allocates the blocks. Trying to use 'swapon' with an existing sparse file won't remove the holes for you but does notice them and then refuse to use it.
zrm··on Running out of disk space in production
That's not a great idea for three different reasons: Filesystems have to do ugly things when they're almost full like split files into many small blocks and store more metadata to keep track of them all, SSDs get slower and have compromised wear leveling when they're almost full, and it makes you more likely to subject yourself to perils of fully running out which can cause random non-temporary problems even if it only happens temporarily.
zrm··on Running out of disk space in production
A good way to do this is to create a swap file, both because then you can use it as a swap file until you need to delete it and because swap files are required to not be sparse.
zrm··on Android Developer Verification
There are different governments and different subdivisions within any given government. The only thing you need to get a government that had been pushing Chat Control to do some trust busting is to get more votes.
zrm··on C++26 is done: ISO C++ standards meeting Trip Report
> First you confuse API and ABI.

I'm not confusing API with ABI. If you don't have a stable ABI then you essentially forfeit the traditional method of having every program on the system use the same copy (and therefore version) of that library, which in turn encourages them to each use a different version and facilitates API instability by making the bad thing easier.

> Second there is no practical difference between first and third-party for any sufficiently complex project.

Even when you have a large project, making use of curl or sqlite or openssl does not imply that you would like to start maintaining a private fork.

There are also many projects that are not large enough to absorb the maintenance burden of all of their external dependencies.

> Third you cannot have multiple versions of the same thing in the same program without very careful isolation and engineering.

Which is all the more reason to encourage every program on the system to use the same copy by maintaining a stable ABI. What do you do after you've encouraged everyone to include their own copy of their dependencies and therefore not care if there are many other incompatible versions, and then two of your dependencies each require a different version of a third?

> In any non-trivial project there will be complex dependency webs across different files and subprojects, and humans are notoriously bad at packaging pieces of code into sensible modules, libraries or packages, with well-defined and maintained boundaries.

This feels like arguing that people are bad at writing documentation so we should we should reduce their incentive to write it, instead of coming up with ways to make doing the good thing easier.

zrm··on C++26 is done: ISO C++ standards meeting Trip Report
> C and C++ are usually stuck in that antiquated thinking that you should build a module, package it into some libraries, install/export the library binaries and associated assets, then import those in other projects. That makes everything slow, inefficient, and widely dangerous.

It seems to me the "convenient" options are the dangerous ones.

The traditional method is for third party code to have a stable API. Newer versions add functions or fix bugs but existing functions continue to work as before. API mistakes get deprecated and alternatives offered but newly-deprecated functions remain available for 10+ years. With the result that you can link all applications against any sufficiently recent version of the library, e.g. the latest stable release, which can then be installed via the system package manager and have a manageable maintenance burden because only one version needs to be maintained.

Language package managers have a tendency to facilitate breaking changes. You "don't have to worry" about removing functions without deprecating them because anyone can just pull in the older version of the code. Except the older version is no longer maintained.

Then you're using a version of the code from a few years ago because you didn't need any of the newer features and it hadn't had any problems, until it picks up a CVE. Suddenly you have vulnerable code running in production but fixing it isn't just a matter of "apt upgrade" because no one else is going to patch the version only you were using, and the current version has several breaking changes so you can't switch to it until you integrate them into your code.

zrm··on Interoperability Can Save the Open Web (2023)
> No root certificate is decentralized.

The root certificates are pretty decentralized. There isn't just one and you can use whichever one you like for your certificate. The browsers or other clients then themselves choose which roots to trust.

The main thing that isn't very decentralized here is Google/Chrome being the one to de facto choose who gets to be root CA for the web, but then it seems like your beef should be with people using Chrome rather than people using Let's Encrypt.

> If your DNS port is closed by your ISP, you can't have people use your DNS server from the outside and then you need Google or Amazon which are not decentralized.

It's pretty uncommon for ISPs to close the DNS port and even if they did, you could then use any VPS on any hosting provider.

> Also to be selfhosted you can't just forward what root DNS servers say, you need to store all domains and their IPs in a huge database.

I suspect you're not familiar with how DNS works.

Authoritative DNS servers are only required to have a database of their own domains. If your personal domain is example.com then you only need to store the DNS records for example.com. Even if you were hosting a thousand personal domains, the database would generally be measured in megabytes.

Recursive DNS servers (like 1.1.1.1 or 8.8.8.8) aren't strictly required to store anything except for the root hints file, which is tiny. In practice they will cache responses to queries for the TTL (typically up to a day) so they can answer queries from the cache instead of needing to make another recursive query for each client request, but they aren't required to cache any specific number of records. A lot of DNS caches are designed to have a fixed-sized cache and LRU evict records when it gets full. A recursive DNS server with a 1GB cache will have reasonable performance even under high load because the most commonly accessed records will be in it and the least commonly accessed records are likely to have expired before they're requested again anyway. A much larger cache gets you only a small performance improvement.

DNS records are small so storing a very large number of them can be done on a machine with few resources. A DNS RRset is usually going to be under 100 bytes. You can fit tens of millions of them in RAM on a 4GB Raspberry Pi.

zrm··on Interoperability Can Save the Open Web (2023)
Let's Encrypt is a non-profit that defeated the certificate cartel. The main thing you get from using HTTP without it is bad security.

DNS can answer thousands of queries per second on a Raspberry Pi and crazy numbers on a single piece of old server hardware that costs less than $500.

zrm··on Interoperability Can Save the Open Web (2023)
> Use HTTP (secure is not the way to decentralize).

This doesn't seem like useful advice. If you're going to use HTTP at all there is essentially zero practical advantage in not using Let's Encrypt.

The better alternative would be to use new protocols that support alternative methods of key distribution (e.g. QR codes, trust on first use) instead of none.

> Selfhost DNS server (hard to scale in practice).

This is actually very easy to do.

zrm··on The Wyden Siren Goes Off Again: We’ll Be “Stunned” By What the NSA Is Doing
I have two younger brothers. They have the same last name, first initial, a history of having lived at the same address, and the same birth date, because they're twins.

Every time one of them goes to a particular medical facility, he has to explicitly decline having them merge their charts.

zrm··on “Microslop” filtered in the official Microsoft Copilot Discord server
https://xkcd.com/2015/
zrm··on Ggml.ai joins Hugging Face to ensure the long-term progress of Local AI
With Linux distros they typically put the web link right on the main page and have a torrent available if you go look for it, because they want you to try their distro more than they want to save some bandwidth.

Suppose HF did the opposite because the bandwidth saved is more and they're not as concerned you might download a different model from someone else.

zrm··on EU bans the destruction of unsold apparel, clothing, accessories and footwear
https://xkcd.com/1321/
zrm··on Upcoming changes to Let's Encrypt and how they affect XMPP server operators
That's assuming you're requiring the ordinary HTTPS port to be used. For that matter, why would it even need to use HTTPS? Have the peer make a TLS connection to the XMPP server to get the CA.

But it still seems like the premise is wrong. The protocol is server-to-server and the legacy concept that one of them is the "client" and needs a "client certificate" is inapplicable, so why shouldn't the protocol just specify that both peers are expected to present a "server certificate" regardless of which one initiated the connection?

zrm··on Upcoming changes to Let's Encrypt and how they affect XMPP server operators
The second one doesn't seem excessively complicated and the latency could be mitigated by caching the CA for a reasonable period of time.

But if you're going to modify the protocol anyway then why not just put it in the protocol that a "server" certificate is to be trusted even if the peer server is initiating rather than accepting the connection? That's effectively what you would be doing by trusting the "server" certificate to authenticate the chain of trust for a "client" certificate anyway.

zrm··on BirdyChat becomes first European chat app that is interoperable with WhatsApp
A probable implementation is that you bootstrap the initial key exchange using web PKI (if you want to talk to Alice@example.com then your client makes a TLS connection to example.com and asks for Alice's public key) and thereafter you use something like the Signal ratchet thing.
zrm··on cURL removes bug bounties
Triage gets outsourced because the quality of reports is low.

If filing a bad report costs money, low quality reports go down. Meanwhile anyone still doing it is funding your top notch security team because then they can thoroughly investigate the report and if it turns out to be nothing then the reporter ends up paying them for their time.

zrm··on The Going Dark initiative or ProtectEU is a Chat Control 3.0 attempt
A VPN provider could easily support Port Control Protocol / NAT-PMP without giving each VPN client its own public IPv4.
zrm··on Big GPUs don't need big PCs
> Bus width is 64 vs 384.

The bus width is the number of channels. They don't call them channels when they're soldered but 384 is already the equivalent of 6. The premise is that you would have more. Dual socket Epyc systems already have 24 channels (12 channels per socket). It costs money but so does 256GB of GDDR.

> Look at modern AM5 struggling to boot at over 6000 with more than two sticks.

The relevant number for this is the number of sticks per channel. With 16 channels and 64GB sticks you could have 1TB of RAM with only one stick per channel. Use CAMM2 instead of DIMMs and you get the same speed and capacity from 8 slots.

zrm··on Big GPUs don't need big PCs
DDR5 is ~8GT/s, GDDR6 is ~16GT/s, GDDR7 is ~32GT/s. It's faster but the difference isn't crazy and if the premise was to have a lot of slots then you could also have a lot of channels. 16 channels of DDR5-8200 would have slightly more memory bandwidth than RTX 4090.
zrm··on What Does a Database for SSDs Look Like?
To some extent the only way around that is to use non-uniform hardware though.

Suppose you have each server commit the data "to disk" but it's really a RAID controller with a battery-backed write cache or enterprise SSD with a DRAM cache and an internal capacitor to flush the cache on power failure. If they're all the same model and you find a usage pattern that will crash the firmware before it does the write, you lose the data. It's little different than having the storage node do it. If the code has a bug and they all run the same code then they all run the same bug.

zrm··on Vm.overcommit_memory=2 is the right setting for servers
> Then your memory requirements always were potentially 512GB. It may just happen to be even with that amount of allocation you may only need 64GB of actual physical storage; however, there is clearly a path for your application to suddenly require 512GB of storage.

If an allocator unconditionally maps in 512GB at once to minimize expensive reallocations, that doesn't inherently have any relationship to the maximum that could actually be used in the program.

Or suppose a generic library uses buffers that are ten times bigger than the maximum message supported by your application. Your program would deterministically never access 90% of the memory pages the library allocated.

> If your failure strategy is "just let the server fall over under pressure" then this might be fine for you.

The question is, what do you intend to happen when there is memory pressure?

If you start denying allocations, even if your program is designed to deal with that, so many others aren't that your system is likely to crash, or worse, take a trip down rarely-exercised code paths into the land of eldritch bugs.

zrm··on Vm.overcommit_memory=2 is the right setting for servers
Which is a major way turning off overcommit can cause problems. The expectation for disabling it is that if you request memory you're going to use it, which is frequently not true. So if you turn it off, your memory requirements go from, say, 64GB to 512GB.

Obviously you don't want to have to octuple your physical memory for pages that will never be used, especially these days, so the typical way around that is to allocate a lot of swap. Then the allocations that aren't actually used can be backed by swap instead of RAM.

Except then you've essentially reimplemented overcommit. Allocations report success because you have plenty of swap but if you try to really use that much the system grinds to a halt.

zrm··on Getting bitten by Intel's poor naming schemes
These have been my go-to for a while now:

https://en.wikipedia.org/wiki/List_of_Intel_Core_processors

https://en.wikipedia.org/wiki/List_of_Intel_Xeon_processors

It doesn't have the CPUID but it's a pretty good mapping of model numbers to code names and on top of that has the rest of the specs.

zrm··on Framework Raises DDR5 Memory Prices by 50% for DIY Laptops
Most people have access to the internet where you can ask people what they recommend if you don't know yourself.
← PreviousPage 2 of 33Next →