Hacker News new | past | comments | ask | show | jobs | submit | theamk's comments login

Wouldn't the safest thing, security-wise, to fail fast on bare 0ah?

As a web server, you may not know which intermediate proxies did the request traverse before arriving to your port. Given that request smuggling is a thing, failing fast with no further parsing on any protocol deviations seems to be the most secure thing.


I mean the safest thing would be to send an RST as soon as you see a SYN for 80/tcp.

That would have a severe downside of not letting your customers access your website.

Fast-abort on bare-0ah will still be compatible with all browsers and major http clients, thus providing extra mitigations practically for free.


Wouldn't not replying at all be the safest?

No one is talking about Microsoft and whatever it does on its platform, the parent comment is about network protocols (HTTP, SMTP and so on..).

I understand that it is tempting to blame Microsoft for \r\n proliferation, but it does not seem to be the case - the \r\n is comes from the era of teletypes and physical VT terminals. You can still see the original "NL" in action (move down only, do not go back to start of line) on any Unix system by typing "(stty raw; ls)" in a throw-away terminal.


I was thinking about how one would change io_uring design to be compatible with seccomp, and came up with a very simple one:

A new io_uring fd comes with all operations disabled by default. User has to call "io_uring_register(fd, ENABLE_OP, op)" before operation is used for the first time. Then seccomp filter can easily filter enable_op calls to prohibit certain operations.

It could even be added now in backward-compatible way - add a new feature to io_uring_setup that enables it. Then one could set seccomp filter to only accept setup requests with this feature set, and deny all others. Together, this should allow cooperating programs to pass seccomp filter, while programs that won't register ops could not use seccomp at all.


I agree and think your approach would work, but I need to point out that seccomp BPF filters can also match on syscall arguments. For example, you can allow fcntl(F_DUPFD, …) but deny fcntl(F_SETLEASE, …). For some syscalls (fcntl, ioctl, setsockopt, …), this is rather important.

emacs is a really bad comparison, given that it has million of functions and is infinitely customizable. It's slow performance has been subject of many jokes back in the 1970's [0] ("EMACS: Eight Megabytes And Constantly Swapping")

You should at least compare it to "nano" editor, or even better, it's predecessor "pico".

[0] https://github.com/emacs-mirror/emacs/blob/master/etc/JOKES#...


It's interesting that the virtual machine is neither very fast nor it is memory efficient. If you really want to have max speed + portability, it's hard to beat restricted subset of C, especially since almost every platform has highly optimized compiler. Something like:

"Code must conform to C89 with -nostdlib, and can only link to libuxn (that we wrote). And use uxn_main() instead of main(), as libuxn defines main. No binary dependencies allowed, all source files must be in project directory, and only uxn build system can be used"

The the authors would only need to write libuxn for each platform they support, which is certainly easier and faster than writing a whole emulator.

But I am guessing this solution did not satisfy other criteria, perhaps things like "playful" and "build from first principles". It's a pity though - distributing apps in source code form instead of emulator binary would make them much more modifiable by end users.


One of the authors talks about using C with SDL or libdraw here: https://news.ycombinator.com/item?id=31715080

Since they were on a boat with a Raspberry Pi and not much battery power or internet, in addition to execution speed and portability, they were probably also concerned with:

- speed of compilation and linking (on small machines like Raspberry Pi)

- binary size of anything that might have to be updated or shared over the internet

- having to troubleshooting emergent issues without the ability to lookup documentation or download updates or tools from the internet

In this situation, a simpler language on a simpler VM is probably going to be faster to develop with than compiling/linking a subset of C, and after the initial implementation of the VM, might present less opportunity for an unintended interaction of leaky abstractions in your libuxn and your toolchain to ruin your day on a day when you don't have internet connectivity to check Stackoverflow or to update some buggy dependency.


Interesting comment, thanks for finding it!

I have a raspberry pi 2 (one of the first one, very low) and tried compiling orca.c on it with gcc. It took 7 seconds and produced 38KB executable. This is more than what I expected, but it's still pretty reasonable. However, I can see how this can be annoying with very rapid iteration cycles.

(Btw, building alone (no linking) takes 5.4 sec, so compilation time dominates. And optimized build (-O3) was over a minute. Not something to be done as part of development.)

But then I remembered about lighter compilers, and tried 'tcc'. This was substantially faster - just 0.6 seconds for the whole process! I think this is very reasonable, and for newer Pi's it would be even faster.

Also note that my idea was to forgo standard libraries and only link to libuxn (and only include uxn.h). This theoretical libuxn will have the same role as UXN virtual machine - written only once, and then frozen in stone, with no updates. This will take care of large binary sizes - if you are only linking to libuxn there are no updates to download. And there is no need to lookup documentation or consult stack overflow, as you are only allowed to link to libuxn, no third-party libraries.

Will such limited environment be inconvenient? Somewhat, but less that full-blown VM. Will it take effort to write and maintain libuxn on all platforms? Yes, but less effort than full-blown VM. Won't libuxn have some bugs requiring updates? Likely, but I bet it will have fewer bugs than full-blown VM.

As for other things (updating binary over internet, shareing


There's an effort to port uxn to DuskOS (https://duskos.org/). The goal here isn't to be maximally performant or memory efficient (though at this point, running uxn on DuskOS on certain architecture is faster than the mainline uxn implementation).

Rather, these are computing platforms to maximize usefulness in the event of a societal collapse.

That is why there is a handbook of uxn opscode made to include hand gestures (https://wiki.xxiivv.com/site/uxntal_opcodes.html), so that computing and transmission of computing can continue even with the loss of the computing hardware or documentation.


Dusks OS badly needs a ZMachine interpreter. The number of software running on DuskOS would skyrocket. From a Tetris implementation to tons of libre IF (and games) such as SpiritWrak, All Thing Devours, Reversi, ...

https://jxself.org/git/


I don't get it.. DuskOS mentions "it runs plenty fast on an old Pentium 75 MHz with 16mb of RAM." - that's a lot! I'd expect something geared for "civilization collapse" to be compatible with smaller embedded micros, like 80 KB RAM of esp8266 and 500 KB of RAM of ESP32.

I remember programming on 286 and 386 machines with 33 Mhz and 2-4 MB of RAM, and it was perfectly usable with Pascal and even C (although C was annoyingly slow, a few seconds per build). If your idea of old machine is Pentium with a _whole megabyte_ of RAM, or even more (gasp!), you don't need to pay Forth penalty, you can have normal languages with good ergonomics.


The smaller embedded micros are the target of CollapseOS, which is folded into DuskOS. The stage DuskOS is targeting is when we stop being able to have the ability to make new computers and new chips, and we start looking to salvage old ones laying around. There is also recovering knowledge from disks.

Infocom also took the VM approach and I can still play their games years later, and it worked out for them in the short term too.

Simple C code from 1990 still works, as long as it does not depend on non-standard libraries.

Imagine how cool it would be if old games were distributed in source code form, so that anyone can modify and "remix" it as much as they want with a simple text editor?

This was impossible back in 1990s, but today we can get a C compiler (tcc) which takes less than 1 megabyte of space and compiles+links a game in less than a second. As long as you don't depend on too many third-party libraries, you can ship C code, compile the game on each start and user won't even notice!


Infocom's games require little CPU by their nature, and most of the memory is spent on graphics.

Cloudflare dropped captchas back in 2022 [0], now it's just a checkbox that you check and it lets you it (or does not).

And this mean that my ancient android tablets can no longer visit many cloudflare-enabled sites.. I have a very mixed feelings about this:

I hate that my tablets are no longer usable so I want less Cloudflare;

but also when I visit websites (on modern computers) which provide traditional captchas where you click on picture of hydrants, I hate this even more and think: move to Cloudflare already, so I can stop doing this nonsense!

[0] https://news.ycombinator.com/item?id=33007370


The checkboxes are also captchas.

but there are more user-friendly captchas than the hydrants, which on average could be better that a total block on the tablets?

total block on _old_ tablets - Android 4.4 specifically, and I am sure many people on HN would be horrified to see those anywhere close to internet. New tablets are fine.

As for "more user-friendly captchas" - I have seen some of those (like AliExpress' slider) but I doubt they will work as well as hydrants. And with new AI startups (1) slurping all the data on the web and (2) writing realistic-looking spam messages, I am sure anti-bot measures would be more important than ever.


Would other chat systems do it better somehow? Which ones?

I'd imagine that "system supports private messages; I cannot link to them in public channels, copy-paste is the only way to share" is pretty universal. Even IRC and ICQ operated this way.


I used Zulip at a previous job some years ago and was pretty happy with it. I honestly don't remember whether it had a better strategy for DMs in particular, but the general policy of "everything is a thread" seemed to solve a lot of problems.

That would only work if you never deal with legacy (pre-utf8 data), or if you are American and all your legacy data in ASCII.

If you are actually dealing with legacy data, you want your programs to not care about encodings at all.

File names are sequence of bytes... if it's not a valid UTF-8, why would program even care? A C program from 1980 can print "Cannot open file x<ff><ff>.txt" without known what encoding it, why can't Python do this today without lots of hoops? Sure, the terminal might not show this, but user will likely redirect errors to file anyway and use the right tools to view it.

File contents are sequence of bytes. Every national encoding keeps 0-31 range as control characters, and most of them (except systems like Shift-JIS) keep lower half as well. Which means a program should be able to parse .ini file which says "name=<ff><ff>", store <ff><ff> into a string variable, and later print "Parsing section <ff><ff>" to stdout - all without ever knowning which encoding this is.

There are very few operations which _really_ care about encoding (text rendering, case-insensitive matching, column alignment) and they need careful handling and full-blown unicode libraries anyway, with megabytes of data tables. Forcing all other strings to be UTF-8 just for the sake of it is counterproductive and makes national language support much harder.


Disagree. I do this kind of code all the time:

   try:
      something()
   except:
      log_tons_of_debug_info()
      raise
and I am very glad that I get my debug info works even if I press Ctrl-C or someone calls sys.exit().

Just noting it here: your code is incorrect. In case of a KeyboardInterrupt error and another error raised by `log_tons_of_debug_info()` (there's no error free code, right?), KeyboardInterrupt would end up being masked (it would go into the __context__ attribute of another error). The program won't abort its execution. And it's just one example out of many where it's critical to not mask error types.

Correct code would be:

   try:
      something()
   except BaseException as ex:
      try:
          log_tons_of_debug_info()
      finally:
          raise ex
But really, you don't want to mess with BaseExceptions at all, so just do `except Exception` instead of a bare `except:`.

Why wouldn't I want to mess with BaseExceptions? They are not magic, and add only 3 classes to the list:

SystemExit - You _definitely_ want to catch this one for logging. If a library (not top-level app) calls `sys.exit` you at least want to know what's happening, if anything so you can talk to author and get them to use proper exception types.

KeyboardInterrupt - I normally want to catch this one as well. If the program was taking too long and I hit Ctrl-C to stop it, I _do_ want to see all the debug output. And if I don't, for some reason, there is always Ctrl-\ which kills python immediately and unconditionally.

GeneratorExit - this one is tricky and I agree that in a lot of cases, you don't want to print logs on it. But it also very rare - it only appears in async functions (emitted by yield), and never propagated to caller. So as long as you are not doing async, you can simply ignore it, which covers majority of the the code I write.


Because accidentally masking some BaseExceptions like `asyncio.CancelledError` can lead to things like memory/resource leaks and potentially your production app going down in pretty hard to debug ways.

well, yeah, you don't want to mask any of those. Thats why all my examples talk about logging + re-raising.

> Just noting it here: your code is incorrect. In case of a KeyboardInterrupt error and another error raised by `log_tons_of_debug_info()` (there's no error free code, right?), KeyboardInterrupt would end up being masked (it would go into the __context__ attribute of another error).

Your snippet has the opposite problem: if ex is a regular Exception, but then KeyboardInterrupt is raised by `log_tons_of_debug_info()`, then your snippet would mask that by re-raising ex in its place. I think the original snippet is probably better on balance, even ignoring difference in code complexity.


I dunno, this just usually means I’m going to hold control and mash C, hopefully I can get my interrupt to occur inside your except

Signals are non-reentrant.

That's unecessary, because of the 'raise' statement. This construct effectively only hooks exceptions, it doesn't swallow them.

You know about Ctrl-\, right? Kills python right away, no exceptions or anything.

(there is also coredump but most distros disable or hide them, so it's not a problem in practice)


Anyone reading your code is going to assume this is a bug. The PEP is right that explicit is better than implicit. You should write `except BaseException` (whether or not this PEP is approved).

"except:" is explicit enough and "except BaseException" is redundant.

Moreover I think there is a real risk people are going to write "except Exception:" instead, which breaks in the fringe case an exception that derives from BaseException (enforced by interpreter) but not from Exception is thrown.

Even if catch Exception is what users usually mean, changing code from "catch (BaseException):" to "catch Exception:" may break some code if improperly reviewed.

It's also not worth breaking production code over this.


> "except:" is explicit enough and "except BaseException" is redundant.

Take that up with the consensus view of the python community, as reflected by python linters in their default configuration, almost all of which warn on bare except.

The debate in the PEP is whether this should be a syntax error. The debate about whether it is good style is over though.

> It's also not worth breaking production code over this.

Agreed.


> Take that up with the consensus view of the python community, as reflected by python linters in their default configuration, almost all of which warn on bare except.

I don't fully agree on it being a purely a style issue (though the warnings from linters are wholly justified). From what I understand, "except:" is a code smell because you don't actually want to catch BaseException instead of just Exception.

Linters wouldn't have warned about it if it meant "except Exception:". The real issue, IMO, is the fact non-exceptions (Ctrl-C, generator exit, program exit code, etc.) have been crammed into the exception system.


>which breaks in the fringe case an exception that derives from BaseException (enforced by interpreter) but not from Exception is thrown.

For many users, in many cases, this would be fixing the code rather than breaking it.

Forcing people to write either `except BaseException:` or `except Exception:` means forcing them to think about which one they actually mean. This is a good thing, just like the enforcement of proper separation between bytes and text is a good thing.


Only if they don't understand what 'raise' means. It's obvious this construct is just injecting some additional information in a passing exception, there's no issue if it catches everything.

> It's obvious this construct is just injecting some additional information in a passing exception

There is a good chance it will fail to do that. See elsewhere in this thread.


It will change exception class if logging function will fail... I wouldn't call this "good chance", those kinds of things are pretty unlikely in my experience.

Bare except + reraise is a very common Python pattern, so no, it won't be assumed to be a bug. This was actually one of the major points in the discussion of the PEP that led to its rejection.

No one would anyone would object if this was a "best practice" or "linter rule".

It's the enforcement by compiler, which will break lots of existing code, that makes people unhappy.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: