Live data from Hacker News

size_t-to-int vulnerability in Linux’s filesystem layer

openwall.com

241–250 of 280 posts

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#241

Why does the compiler not warn if you use a 64 bit unsigned integer when a 32 bit signed integer is required?

You actually can pass -Wconversion to a compiler, but it's one of those things that's going to generate a lot of noise and not be a vulnerability 99% of the time. It's not an easy solved problem, because if you annoy developers with noise they stop caring.

It’s an easily solved problem if you turn on these warnings from the start. It’s not though if your program contains a million of these potential vulnerabilities already.

Should we be afraid developers will stop caring? Did they even care in the first place?

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#242
post #238
post #198

Earlier quoted context omitted.

The Linux kernel doesn't have an actual path limit. Nor does Solaris. PATH_MAX is 4096 in glibc and musl libc because setting to it to something like INT_MAX or ULONG_MAX would break a lot of existing code that uses PATH_MAX to size buffers. (Though Solaris does define it as INT_MAX, IIRC.) OTOH, because of the lack of a hard limit there's also code that relies (if accidentally) on paths longer than PATH_MAX.

Linux does have a limit, at least for some system calls: $ strace -e trace=file perl -e 'open(FH, "

I stand corrected. It seems that Linux copies the entire path into a kernel-allocated buffer (see getname and getname_flags in fs/namei.c as called by various syscalls in fs/open.c), rejecting paths longer than PATH_MAX.

EDIT: And on Solaris PATH_MAX is 1024 and (AFAICT) Solaris also copies paths into kernel space. It seems I was confusing things with NL_TEXTMAX, which is INT_MAX on glibc (but not Solaris).

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#243
post #198

Earlier quoted context omitted.

This fix to me reduces the performance for nothing. In Linux (or most general on any UNIX system that I saw) a path should not be longer (total) than PATH_MAX, that is typically defined to 4096 bytes. What is the point on allocating something statically at this point? And yes, I know that really that is only a limit of the system call path lenght, and in theory you can work with longer paths (by changing the current…

The Linux kernel doesn't have an actual path limit. Nor does Solaris. PATH_MAX is 4096 in glibc and musl libc because setting to it to something like INT_MAX or ULONG_MAX would break a lot of existing code that uses PATH_MAX to size buffers. (Though Solaris does define it as INT_MAX, IIRC.) OTOH, because of the lack of a hard limit there's also code that relies (if accidentally) on paths longer than PATH_MAX.

https://eklitzke.org/path-max-is-tricky

The Linux kernel defines upper limits for NAME_MAX (255) and PATH_MAX (4096).

The glibc doesn't enforce this limit because it was originally written to run on GNU HURD which I guess doesn't have these limits.

But systemd only runs on glibc on Linux. So I don't see why it doesn't at least sanity check the length of absolute paths with PATH_MAX...

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#244
post #237

Earlier quoted context omitted.

> The filesystem doesn't support it. Remember that Linux supports hierarchical mounts! You can mount anything at any depth of directory nesting. Even if it were true that MAX_PATH were an FS limitation, you could still nest mounts and encounter absolute paths exceeding MAX_PATH. MAX_PATH is simply the length in bytes of the longest string you should expect system calls to accept as a path parameter. > I use Linux com…

> It sounds like using systemd is a terrible idea for memory-constrained devices, so you really don’t want to see it in the embedded world. On the other hand, proper event-driven init system (instead of horrible shell scripts with all sorts of fragile "sleep"s and other hacks) sounds sexy for an embedded system. I sometimes get annoyed how home routers, NAS, etc. are slow to boot up Though the embedded systems I refe…

Is there a list of init systems that aren't made of shell scripts? Epoch is the only one I found.

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#245
post #101

Earlier quoted context omitted.

-Wall -Wextra -Wpedantic does not enable all diagnostics. This is GNU's idea of "all". Contrast to Clang's -Weverything, which will.

The reason for this decision is so that compiler upgrades with -Wall and -Werror don't break builds. I can see the reason behind it, but I feel that this behavior is something you opt into when you use -Werror.

Is -Werror really supposed to not break builds?

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#246

Earlier quoted context omitted.

GCC's -Wconversion has some issues. For example, good luck getting gcc to /not/ emit a warning for this code, in C or C++. I have yet to find the appropriate cast to avoid a warning. Clang does not warn for this. typedef struct { unsigned value : 4; } S; void foo(S* s, unsigned value) { // error: conversion from 'unsigned int' to 'unsigned char:4' may change value s->value = value; } I mean, I guess I can see the rat…

Does it still warn if you do `s->value = value & 0x0F`? That seems like a reasonable alternative to pragmas if it works.

Thanks, that fixed it!

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#247
post #153

Earlier quoted context omitted.

It's generally dangerous to restart PID1 in an enviroment where, by definition, something happened to PID1 that it wasn't expecting. The state of the system is now unreliable, and it's exactly the sort of unreliable in exactly the right place that tends to lead to whopping security issues. Far too easy to end up with "Crash PID1 with 'blah blah blah', then when it restarts it ends up doing bad things X & Y".

Perhaps a distinction here can be made between running as a server OS and a desktop OS. In a server I generally want a crash immediately. But on a desktop I'd rather it limp along and give me a chance to finish writing my Hackernews post.

Basically, there's no solution at this level of granularity. One can also argue that the desktop is where the most important stuff is that we least want hacked, e.g., your family photos, documents, other stuff with a high priority of not being backed up, so we must treat security even higher than a server at this point.

I call these the "already lost" situations. You've already lost, we're just arguing about how to distribute the lossage. While those discussions aren't completely pointless, it is important to keep it clear in our head we're arguing about how to pick up the bodies at a crash site and not how to prevent the crash in the first place; it's a different mindset.

Despite some moderately-justified mockery in the other messages in this thread, the answer really is "just don't crash and have secure code here", which is to say, "don't lose". It's exceeding hard to write and it's a very high bar, but at the same time, it's very difficult to imagine how to secure a single system when you can't even stipulate a core of trusted software exists. If you don't even have a foundation, you're not going to build a secure structure. In this case, by "secure" I don't just mean security, but also, functionality and everything else.

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#248
post #49
post #7

This kind of issue is the reason why some more modern languages like Rust or Go do not have implicit narrowing conversions. For instance, on Rust, trying to simply pass an usize (Rust's equivalent of size_t) to a function which expects an i32 (Rust's equivalent of int) will not compile; the programmer has to write "size as i32" (Rust's equivalent of "(int) size"), which makes it explicit that it might truncate the va…

I wish clippy had a lint against downcasts specifically. I aso like that rust has no “int” type

It does, you just need to enable it. There are a bunch of other cast-related lints as well that are allow by default.

https://rust-lang.github.io/rust-clippy/v0.0.212/#cast_possi...

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#249

Earlier quoted context omitted.

No, the point was you want don't get a warning and it will silently wrap. You can scroll up if you've forgotten. And it is false. My default configuration C++ project created in Clion shows it very clearly, and even pesters to use int32/int64 over int/long. But as usual the default fallback when you're wrong about C++ is "uh yeah but lotta footguns amirite" As if there aren't enough that we need to start making them…

And yet RedHat's recommended compiler flags for GCC [0], for example, do not appear to catch the wrapping assignment in the above example code. 0: https://developers.redhat.com/blog/2018/03/21/compiler-and-l...

Ah yes, of course the goalpost was "you need to customize your settings to catch it" above.

Now that the default in the most beginner friendly of IDEs catches it, the goalpost is "my pet source of customization designed with C++98 in mind doesn't catch this"

Of course, even your pet source of customization caught up: https://developers.redhat.com/blog/2021/04/06/get-started-wi...

Re: size_t-to-int vulnerability in Linux’s filesystem layer

#250

Earlier quoted context omitted.

Linux apparently provides a similarly named set of sized integer types to Rust, ie: s8 u8 s16 u16 s32 u32 s64 u64 But of course getting C programmers to use these integer types rather than the ones they grew up with isn't easy.

I don't think that stops C's implicit conversions either, does it?

It doesn't. They are in the end just typedefs to the basic types like int, long, etc.
Post reply on HN