HNHacker News
TopNewBestAskShowJobs

arghwhat

9,000 karma · joined January 12, 2017

no.
submissionscomments
arghwhat··on The RCE that AMD won't fix
> We're speaking of a MITM here

We are speaking of the total attack surface.

1. When it comes to injecting invalid packets to break a parser, you can MITM TLS without problem. This is identical to the types of attack you claimed were relevant to HTTP-only, feeding invalid data that would be rejected by authentication of the signature.

2. Any server owning a domain name can have a valid TLS certificate, creating "trusted" connections, no MITM necessary. Any server in your existing mirrorlist can go rogue, any website you randomly visit might be evil. They can send you both signed but evil TLS packets, and malicious HTTP payloads.

3. Even if the server is good, it's feeding you externally obtained data that too could be evil.

There is no threat model here where you do not rely 100% on the validity of the HTTP stack and file signature checking. TLS only adds another attack surface, by running more exploitable code on your machine, without taking away any vulnerabilities in what it protects.

arghwhat··on The RCE that AMD won't fix
If you believe TLS is more fragile than PGP and plain HTTP, then I have reason to believe you have never looked at any of those wire protocols/file formats and the logic required.

Adding TLS in front of HTTP when talking to an untrusted third-party server (and yes, any standard HTTPS server is untrusted int his context), can only ever increase your attack surface. The only scenario where it reduces the attack surface is if you are connected with certificate pinning to a trusted server implementation serving only trusted payloads, and neither is the case for a package repo - that's why we have file signatures in the first place.

arghwhat··on The RCE that AMD won't fix
This statement makes no sense, TLS is a complicated protocol with implementations having had massive fun and quite public security issues, while HTTPS means you have both and need to deal with a TLS server feeing you malicious HTTP responses.

Having to harden two protocol implementations, vs. hardening just one of those.

(Having set up letsencrypt to get a valid certificate does not mean that the server is not malicious.)

arghwhat··on The RCE that AMD won't fix
You seem to have forgotten all the critical TLS bugs we had. Heartbleed ring a bell?

> An attacker doesn't get to attack client's HTTP stack without first piercing protection offered by TLS.

You misunderstand: this means more attack surface.

The attacker can mess with the far more complex and fragile TLS stack, and any attacker controlling a server or server payload can also attack the HTTP stack.

Have you recently inspected who owns and operates every single mirror in the mirror list? None of these are trusted by you or by the distro, they're just random third parties - the trust is solely in the package and index signatures of the content they're mirroring.

I'm not suggesting not using HTTPS, but it just objectively wrong to consider it to have reduced your attack surface. At the same time most of its security guarantees are insufficient and useless for this particular task, so in this case the trade-off is solely privacy for complexity.

arghwhat··on The RCE that AMD won't fix
> you're also trusting that the client's HTTP stack is parsing HTTP content correctly

This is an improvement: HTTP/1.1 alone is a trivial protocol, whereas the alternative is trusting the client's much more complicated TLS stack and its HTTP stack.

For technical reasons, unencrypted HTTP is also always the simpler (and for bulk transfers more performant) HTTP/1.1 in practice as standard HTTP/2 dictates TLS with the special non-TLS variant ("h2c") not being as commonly supported.

> for that matter, you're also trusting that the server (and any man-in-the-middle) is generating valid HTTP responses

You don't, just like you don't trust a TLS server to generate valid TLS (and tunneled HTTP) messages.

> you're also trusting that the client's response parser doesn't have a vulnerability (and not, say, ignoring some "missing closing bracket" or something)

You don't. Authentication 101 (which also applies to how TLS works), authenticity is always validated before inspecting or interacting with content. Same rules that TLS needs to follow when it authenticates its own messages.

Furthermore, TLS does nothing to protect you against a server delivering malicious files (e.g., a rogue maintainer or mirror intentionally giving you borked files).

> you're also trusting that the client is parsing the correct signature (and not, say, some other signature that was tacked-on later)

You don't, as the signature must be authentic from a trusted author (the specific maintainer of the specific package for example). The server or attacker is unable to craft valid signatures, so something "tacked-on" just gets rejected as invalid - just like if you mess with a TLS message.

> It's trivially easy to disassemble software to find vulnerabilities like those, though. So it's a lot of trust given for an untrusted software stack.

The basis of your trust is invalid and misplaced: Not only is TLS not providing additional security here, TLS is the more complex, fragile and historically vulnerable beast.

The only non-privacy risk of using non-TLS mirrors is that a MITM could keep serving you an old version of all your mirrors (which is valid and signed by the maintainers), withholding an update without you knowing. But, such MITM can also just fail your connection to a TLS mirror and then you also can't update, so no: it's just privacy.

arghwhat··on The RCE that AMD won't fix
> Potentially it's even a way for a MITM to exploit the HTTP stack, some content parser or the application's own handling. TLS stacks are a significantly harder target in comparison.

For signed payloads there is no difference, you're trusting <client>'s authentication code to read a blob, a signature and validate it according to a public key. For package managers that usually only mean trusting gpg - at the very least no less trustworthy than the many TLS and HTTP libraries out there.

arghwhat··on The RCE that AMD won't fix
They usually support both, but important to note that HTTPS is only used for privacy.

Package managers generally enforce authenticity through signed indexes and (directly or indirectly) signed packages, although be skeptical when dealing with new/minor package managers as they could have gotten this wrong.

arghwhat··on Vitamin D and Omega-3 have a larger effect on depression than antidepressants
> Some cancerous tumors produce this hormone; therefore, elevated levels measured when the patient is not pregnant may lead to a diagnosis of cancer and, if high enough, of paraneoplastic syndromes. It is unknown however whether this production is a contributing cause or an effect of carcinogenesis.

Interesting.

Well, I don't think you'll be able to avoid testicle atrophy even if it minimizes it, but the important part is understanding the tradeoff. Particularly, that adding testosterone will cause changes throughout your entire body (including, for example, shortening life expectancy a bit), and that adding other hormones to the mix will likewise cause changes around the entire body and not just one single process or organ.

But it's your body, your life, your priorities and decision. I also wouldn't consider it a good decision health-wise to take steroids to get huge, but I have no problem with someone deciding that absurd bulk is their main goal in life and worth the tradeoff.

arghwhat··on Vitamin D and Omega-3 have a larger effect on depression than antidepressants
> Insulin for example is the opposite.

You're describing entirely orthogonal issues. In case of insulin resistance, your natural production is running full blast with demand exceeding supply because the consumer stopped caring about the hormone. In case of autoimmune disease, the natural production was killed - you can neither use nor lose what is already dead, and even if some capacity was left it will either soon be killed or atrophy under external insulin, but it will not be mourned.

So no I would say it is exactly the same - "use it or lose it" - but that does not mean that there is never a reason to manually overrule your body's attempt at homeostasis through direct manipulation. It just means that there is a very significant consequence to the process.

> The body itself typically attempts to main homeostasis, but at population scales this is something that is going to have a massive range of ways it shows up.

As a somewhat sidenote, this is also why I dislike the idea of trying to classify people into "normal" and "divergent/atypical". In my eyes we're all normal people and an entirely normal aspect of being a human is that we all differ and have individually specific needs by virtue of being built by a trillion micro-meter sized workers, each with their own hand-copied version of the blueprint, only caring about the millimeter of you in their immediate vincinity and not really talking to any of the others.

arghwhat··on Vitamin D and Omega-3 have a larger effect on depression than antidepressants
> Chemistry trumps psychology

To nitpick: The mind is applied biochemistry. Psychology intervenes in the chemistry, like many other activities do. The goal of that is to solve the root cause so that your future levels will be maintained at the right level, instead of just forcing the level by sourcing the respective chemicals externally.

A good rule of thumb in biology and particular any kind of hormone production and balance is "use it or lose it" - if you start regularly receiving something externally, internal production will scale back and atrophy in response, in many cases permanently.

arghwhat··on Vitamin D and Omega-3 have a larger effect on depression than antidepressants
I believe that is indeed what they meant. The perception of being given a remedy is very powerful indeed, especially for issues ultimately linked to the mind.

That placebos can work should not be seen as undermining the severity or pain of the depression, but rather underline the power of tricking the mind into improvement.

arghwhat··on Spinning around: Please don’t – Common problems with spin locks
For reference, golang's mutex also spins by up to 4 times before parking the goroutine on a semaphore. A lot less than the 40 times in the webkit blogpost, but I would definitely consider spinning an appropriate amount before sleeping to be common practice for a generic lock. Granted, as they have a userspace scheduler things do differ a bit there, but most concepts still apply.

https://github.com/golang/go/blob/2bd7f15dd7423b6817939b199c...

https://github.com/golang/go/blob/2bd7f15dd7423b6817939b199c...

arghwhat··on Apple introduces new AirTag with longer range and improved findability
Nothing related to the attachment point.

I don't know of any third-party AirTag-compatible trackers that have UWB right now, but this applies equally to tags that are much larger than the AirTag. The rest is identical - good battery life, range, loud speaker, ...

I have a few theories on the lacking UWB:

1. Given that UWB is also super slow to roll out to Google Find, with only the Moto Tag available, there might be a technical/regulatory hurdle that manufacturers don't think is worth it

2. Apple/Google might make it a pain to be allowed to integrate with their UWB stuff

3. Cost - maybe the UWB stack is comparatively expensive, with third-party tags aiming for price brackets as low as 1/0th the cost of an AirTag

As a note, I don't know if this is because of regional differences in spectrum limits, but at least with AirTag and Moto Tag v1 EU versions, I could never get UWB to give any meaningful directions until I was already staring at the thing. Once you were in range to even consider UWB, playing a sound would be way more effective.

arghwhat··on After two years of vibecoding, I'm back to writing by hand
From an exercise standpoint, sure, but with sports there is more to it than just maximizing exercise.

If you practice judo you're definitely exercising but the goal is defeating your opponent. When biking or running you're definitely exercising but the goal is going faster or further.

From an an exercise optimization perspective you should be sitting on a spinner with a customized profile, or maybe do some entirely different motion.

If sitting on a carbon fiber bike, shaving off half a second off your multi-hour time, is what brings you joy and motivation then I say screw it to further justification. You do you. Just be mindful of others, as the path you ride isn't your property.

arghwhat··on Apple introduces new AirTag with longer range and improved findability
There are third-party tags out there compatible with both Google and Apple's network that is roughly the same size and use the same battery, yet have a giant lanyard opening in the design to fit anything.

Apple could trivially have fit a usable hole if they wanted to. They just don't want to because they get to sell accessories with that now. Also, looking cleaner on its own helps sell even if that is an entirely useless quality for a tag tha tneeds to go into a bloody case.

arghwhat··on After two years of vibecoding, I'm back to writing by hand
I do appreciate the visual of driving a forklift into the gym.

The activity would train something, but it sure wouldn't be your ability to lift.

arghwhat··on The Holy Grail of Linux Binary Compatibility: Musl and Dlopen
Dynamic libraries have been frowned upon since their inception as being a terrible solution to a non-existent problem, generally amplifying binary sizes and harming performance. Some fun quotes of quite notable characters on the matter here: https://harmful.cat-v.org/software/dynamic-linking/

In practice, a statically linked system is often smaller than a meticulously dynamically linked one - while there are many copies of common routines, programs only contain tightly packed, specifically optimized and sometimes inlined versions of the symbols they use. The space and performance gain per program is quite significant.

Modern apps and containers are another issue entirely - linking doesn't help if your issue is gigabytes of graphical assets or using a container base image that includes the entire world.

arghwhat··on I was banned from Claude for scaffolding a Claude.md file?
> And once you're banned you cant [..] make a data request

glares in GDPR

arghwhat··on What is Plan 9?
> The C language also does not specify a linked list. Go tell your developer friends that C can never use a linked list.

They would not blink because the statement is accurate. To the C language and to the C compiler, there are no linked lists - just random structs with random pointers pointing to god knows what. C does know about arrays though.

> The JavaScript spec[1] does not [specify garbage collection].

I have good reason to believe that you are not familiar with the specification, although to be fair most developers would not be familiar with its innards.

The specification spends quite a while outlining object liveness and rules for when garbage is allowed to be collected. WeakRefs, FinalizationRegistries, the KeptObjects list on the agent record, ...

Just like with Go, it is perfectly valid to have an implementation of a "garbage collector" that is a no-op that never collects anything, which means that the application will continously leak memory until it runs out and crashes as the language provides no mechanism to free memory - for Go, you can switch to this with `GOGC=off`. The specific wording from ECMA-262:

> This specification does not make any guarantees that any object or symbol will be garbage collected. Objects or symbols which are not live may be released after long periods of time, or never at all. For this reason, this specification uses the term "may" when describing behaviour triggered by garbage collection.

If you're not used to reading language specs the rest of the details can be a bit dry to extract, but the general idea is that the spec outlines automatic allocation, permission for a runtime to deallocate things that are not considered "live", and the rules under which something is considered to be "live". And importantly, it provides no means within the language to take on the task of managing memory yourself.

This is how languages specify garbage collection as the language does not want to limit you to a specific garbage collection algorithm, and only care about what the language needs to guarantee.

> [1] The standard calls itself ECMAScript, but I believe your intent here is understood.

sigh.

> For what it is worth, I also put "C can never use a garbage collector" into an LLM. It also called me out on that bullshit just the same.

more sigh. LLMs always just wag their tails when you beg the question on an opinion. They do not do critical thinking for you or have any strong opinions to give of their own.

I'm done, have a nice day.

arghwhat··on What is Plan 9?
I must admit that the ability to randomly bind on top of your "drivers" to arbitrarily overwrite functionality, whether to VPN somewhere by binding a target machine's network files, or how rio's windows were merely /dev/draw proxies and you could forward windows by just binding your own /dev/draw on the target, holds a special place in my heart. 9front, if nothing else, is fun to play with. I just don't necessarily consider it the most optimal or most performant design.

(I also have an entirely irrational love for the idea the singular /bin folder with no concept of $PATH, simply having everything you need bound on top... I hate $PATH and the gross profile scripts that go with it with a passion.)

arghwhat··on What is Plan 9?
This is actually quite an interesting topic in its own right, but not quite the discussion above, which is about whether C or Rust include a GC or is considered to "use" the GC you hand-rolled or pulled in from a library.

I wouldn't consider FilC's GC a GC in the conventional sense either, in that code compiled with Fil-C is still managed manually, with the (fully-fledged) GC effectively only serving as a way to do runtime validation and to turn what would otherwise be a UAF with undefined behavior into a well-defined and immediate panic. This aspect is in essence an alternative approach to what is done by AddressSanitizer.

I'll have to look a bit more into Fil-C though. Might be interesting to see how it compares to the usual sanitizers in practice.

arghwhat··on What is Plan 9?
Indeed, you can disregard plan9 common practice and adopt the ioctl pattern, but then you just created ioctl under a different name, having gained nothing over it.

You will still have the significant context switching overhead, and you will still need distinct write-then-read phases for any return value. Manual buffer sharing is also notably more cumbersome than having a kernel just look directly at the value, and the neat part of being able to operate these fileservers by hand from a shell is lost.

So while I don't disagree with you on a technical level, taking that approach seems like it misses the point of the plan9 paradigm entirely and converts it to a worse form of the ioctl-based approach that it is seen as a cleaner alternative to.

arghwhat··on What is Plan 9?
This feels like it's into trolling, so one last round:

The C language does not use your C code, it is your C code that uses the C language.

The tools available to C is what the language specification dictated and what the compiler implemented. For example, C might use stack memory and related CPU instructions, because the C specification described "automatic memory" and the compiler implemented it with the CPU's stack functionality. It might insert calls to "memcpy" as this function is part of the C language spec. For C++, the compiler will insert calls to constructors and destructors as the language specified them.

The C language does not specify a garbage collector so it can never use one.

You, however, can use C to write a garbage collector to manually use in your C code. C remains entirely unaware of the garbage collectors existence as it has no idea what the code you write does - it will never call it on its own and the compiler will never make any decisions based on its existence. From C's perspective, it's still just memory managed manually by your application with your logic.

In JavaScript and Go, the language specifies the presence of garbage collection and how that should work, and so any runtime is required to implement it accordingly. You can write that runtime in C, but the C code and C compiler will still not be garbage collected.

arghwhat··on What is Plan 9?
They are very different. ioctl's on a file take an operation and arguments that are often userspace pointers as the kernel can freely access any process's memory space. ctl files on the other hand are merely human-readable strings that are parsed.

Say, imagine an API where you need to provide an 1KiB string. The plan9 version would have to process the input byte for byte to sort out what the command was, then read the string to a dynamic buffer while unescaping it until it finds, say, the newline character.

The ioctl would just have an integer for the operation, and if it wanted to it could set the source page up for CoW so it didn't even have to read or copy the data at all.

Then we have to add the consideration of context switches: The traditional ioctl approach is just calling process, kernel and back. Under plan9, you must switch from calling process, to kernel, to fileserver process, to kernel, to fileserver process (repeat multiple times for multiple read calls), to kernel, and finally to calling process to complete the write. Now if you need a result you need to read a file, and so you get to repeat the entire process for the read operation!

Under Linux we're upset with the cost of the ioctl approach, and for some APIs plan to let io_uring batch up ioctls - the plan9 approach would be considered unfathomably expensive.

> The `ctl` approach is at least a proper generalization.

ioctl is already a proper generalization of "call operation on file with arguments", but because it was frowned upon originally it never really got the beauty-treatment it needed to not just be a lot of header file defines.

However, ioctl'ing a magic define is no different than writing a magic string.

arghwhat··on What is Plan 9?
> Absolutely, C also can use a garbage collector.

It is not C using the garbage collector - it is you writing a garbage collector in C. The application or library code you develop with the language is not itself a feature of the language, and the language you wrote the code in is not considered to be "using" your code.

Rust and C are unaware of any type of garbage collection, and therefore never "use" garbage collection. They just have all the bells and whistles to allow you to reference count whatever type you'd like, and in case of Rust there's just a convenient wrapper in the standard library to save you from writing a few lines of code. However, this wrapper is entirely "bolted onto the side": You can write your own Rc<T>, and there would be no notable difference to the std version.

So no, neither Rust nor C can use a garbage collector, but you can write code with garbage collection in any feature-complete language. This is importantly very different from languages that have garbage collection as a feature, like Limbo, Go, JavaScript, etc.

arghwhat··on What is Plan 9?
Rust does not have a garbage collector in any way or form. It's just automatic memory like we're used to (e.g., stack in C++), with the compiler injecting free/drop when an object goes out of scope.

What Rust brings is ownership with very extensive lifecycle tracking, but that is a guard rail that gives compile-time failures, not something that powers memory management.

(If you consider the presence of Rc<T> to make Rust garbage collected, then so is C garbage collected as developers often add refcounting to their structs.)

arghwhat··on What is Plan 9?
> The best apis are those that are hated by the developer and loved by the end users.

No, just those loved by the API consumer. Negative emotions on one end doens't do anything positive.

In the case of plan9, not everything can be described elegantly in the filesystem paradigm and a lot of things end up having really awkward "ctl" files which you write command strings to that the fileserver needs to parse. It also handicaps performance due to the number of filesystem operation roundtrips you usually end up making.

Maybe if combined with something io_uring-esque, but the complexity of that wouldn't be very plan9-esque.

arghwhat··on Is Rust faster than C?
> I don't often do this

You should have practiced better restraint then, as this was not a productive addition to the discussion.

My experience disagrees with your opinion and I see no value in engaging further.

arghwhat··on Is Rust faster than C?
I wouldn't consider implementing a B-tree in C any more "arduous" than implementing any other notable container/algorithm in C, nor would making a library be "brutal" as moving data really isn't an issue. Libraries are available if you need them.

Quite frankly, writing the same in Rust seems far, far more "arduous", and you'd only realistically be writing something using BTreeMap because someone else did the work for you.

However, being right there in std makes use much easier than searching around for an equivalent library to pull into your C codebase. That's the benefit.

arghwhat··on Is Rust faster than C?
Not really, especially as garbage collection doesn't achieve memory safety. Safety-wise, it only helps avoid UAF due to lifecycle errors.

Garbage collection is primarily just a way to handle non-trivial object lifecycles without manual effort. Parallelism happens to often bring non-trivial object lifecycles, but this is not a major problem in parallelism.

In plain C, the common pattern is trying to keep lifecycles trivial, and the moment this either doesn't make sense or isn't possible, you usually just add a reference count member:

    struct some_type {
        uint32_t refcnt;
        uint32_t otherfields;
    };

    struct some_type *some_type_ref(struct some_type *a) {
        a->refcnt++;
        return a;
    }

    void some_type_unref(struct some_type *a) {
        a->refcnt--;
        if (a->refcnt == 0) {
            free(a); // or some_type_destroy(a);
        }
    }
In both Go and C, all types used in concurrent code needs to be reviewed for thread-safety, and have appropriate serialization applied - in the C case, this just also includes the refcnt itself. And yes you could have UAF or leak if you don't call ref/unref correctly, but that' sunrelated to parallism - it's just everyday life in manual memory management land.

The issues with parallelism is the same in Go and C, that you might have invalid application states, whether due to missing serialization - e.g., forgetting to lock things appropriately or accidentally using types that are not thread safe at all - or due to business logic flaws (say, two threads both sleeping, waiting for the other one to trigger an event and wake it up).

← PreviousPage 3 of 34Next →