Hacker Newsnew | past | comments | ask | show | jobs | submit | maple3142's commentslogin

If you are given a shell with `docker run -it --rm alpine:3 sh`, can you read the /etc/shadow on the host without kernel exploit? Assuming the docker and kernel are sufficiently update-to-date (e.g. latest Docker on Debian Stable).


No.

The "root" you get in docker is not actually root outside of the namespace the container in running in.

Assuming no bugs in the kernel, it should not be able to do anything more than the UID that it's mapped from.


Does Docker use user namespaces by default? Otherwise root in the container is actually root on the host, from what I read. Correct me if I'm wrong.

(Privileges are still limited by seccomp filters blocking some syscalls, and there's SELinux to block some other stuff, but it's still the actual root user without user namespaces, I think?)


That's right. Docker still runs without user namespaces by default, which means that root is the same user inside and outside of the container. This does open up attack surface and configuration footguns.

Confinement still leverages dropping some root caps, seccomp, various other namespaces, etc.


I don't think this is true, otherwise you could just load a kernel module into the host kernel from a container.


Root is not just one thing on modern Linux, almost all in-kernel privilege checks are now gated via (slightly) more fine-grained capabilities and the default capability set for Docker containers disallows module loading (CAP_SYS_MODULE) and the relevant syscalls (namely (f)init_module) are also blocked with seccomp.

People still should use user namespaces (and tools like Podman and Incus do by default) but basic stuff like that is not the reason.


It is very possible to load a kernel module into the host from a container.

https://stackoverflow.com/questions/33013539/docker-loading-...


FYI, looks like you are shadowbanned.


Presumably Docker's seccomp profile [1] blocks the init_module system call which is used by insmod [2]. Although, looking at the default profile, it seems to explicitly allow it - but maybe only if you have CAP_SYS_MODULE, which I think means running Docker with "--cap-add=SYS_MODULE".

[1] https://docs.docker.com/engine/security/seccomp/

[2] https://tldp.org/HOWTO/Module-HOWTO/x627.html


There are a million ways to load a kernel module from inside of a container into the host kernel (ie: to trigger a load), but seccomp/ linux caps will block the direct ways (as another commenter notes).


At least podman does if running rootless, I assume docker supports rootless operation as well.

Not sure about running rootful though. I don't really use rootful containers personally.


Hmm. Either I've lost my mind, or you're running a different Docker than me, or you're thinking of some strange scenario such as a Mac where docker is actually inside a VM, or you're wrong.

While there is a feature to do with UID mapping, it doesn't actually work/isn't usable/nobody uses it in current docker iirc.

Therefore root in the container very much is root on the host.


UID mapping is how rootless docker works, so tons of people are using it


Is this a correct understanding of UB in C? A program P has a set of inputs A that do not trigger UB, and a complementary set of inputs B that do trigger UB. A correct compiler compiles P into an executable P'. For all inputs in A, P' should behave the same as P. However, for any input in B, the is absolutely no requirements on the behavior of P'.


Intuitively yes - the program will be compiled as if B-inputs are never passed to the program, and that can include eliminating code that tries to detect B-inputs.


This is a description of an imaginary compiler, evoked by the ANSI/ISO standards documents, which has never existed and will never exist. To understand what the program will do, you just have to understand the compiler behavior on your target platforms. A helpful intuition pump is: imagine the ANSI/ISO specifications simply do not exist; now what? Well, you just continue your engineering practice, the way you would for any of the myriad languages that never even had a post hoc standards document.


> just

That word is carrying a lot of weight here. Compilers are unbelievably complex these days, and it's impossible for any one human to fully understand the entire compilation process, including the effects of any arbitrary combination of compiler flags.

Any assumptions you have about what the compiler does in the face of UB will collapse on the next patch release of that compiler, or the moment somebody changes the compiler flags, or the moment somebody tries to compile the code for a slightly different OS, not to mention architecture.

There is no other way to understand what C compilers do than reading the standard.


Yet the standard does not tell you what the compilers do.

Linux works on a wide variety of platforms. It also relies on those platforms behaving predictably with respect to what the standard leaves undefined.

This description of ISO UB as a totally insane wonderland of random, malevolent semantics just doesn't describe reality.


Up until the compilers do something to your code that you don’t understand.


yeah then I have to learn how it works and what it assumes and how I can control it and maybe switch to a more well behaved compiler if it's truly insane


Every bug is the result of an imaginary computer that doesn't work exactly like my computer does and triggers a bug in my code. The code works on my machine, so this imaginary computer never existed and will never exist.

Signed vs unsigned chars, and the accompanying extension rules, have already bitten me switching between x86/ARM compilers. Confused the hell out of me when I was just starting out with C.

If you're going to interpret C as in "C on amd64, running on Linux 7.0 on an Arrow Lake Intel processor" then yes, you can get away with a lot of UB. That mitigates the problem but doesn't make it go away.


Not imaginary. Eliding checks on nullptr and integer overflow were both implemented, shipped, miscompiled the linux kernel and grew flags to disable them. I expect there are more if one goes looking.


Well yeah that just means some aspects of the imaginary compiler were in some configurations approximated by some historical compiler versions and were in some cases rejected by the community (which cares about sane semantics even for behavior left undefined by ANSI/ISO) and in some cases left in as defaults but made trivially configurable for anyone who wants to define the undefined behavior.


GCC -O1 and clang -O1 will both optimize this function under the assumption that inputs that cause signed integer overflow are never passed:

    int will_overflow(int a, int b) {
        int sum = a + b;
        if (b > 0 && sum < a)
            return 1;
        return 0;
    }


Right, good example, and both GCC and Clang offer well understood parameters for deciding, per compilation unit, what behavior you want for signed overflow (-fwrapv, -fno-strict-overflow, etc), so in reality it's quite far from spooky arbitrary nasal demons.


Wouldn’t be better to check both inputs before against the max value of that type instead of actually doing the overflow?


There are lots of better ways of doing this, but knowing why this one is bad/wrong requires the mental model described upthread.

(But also, what you describe would be incorrect, since two <MAX values can add to a value that is >MAX, and overflow)


> But also, what you describe would be incorrect, since two <MAX values can add to a value that is >MAX, and overflow

I was maybe unclear. I meant, if you know a sum can introduce overflow (because you have a check right after), why not check the inputs before doing the sum, instead of checking the sum?


You can do something like

       (y > 0 && x > INT_MAX - y) 
    || (y < 0 && x < INT_MIN - y)
and hope the optimizer turns it back into just checking the result. Or you use -fwrapv to concretize the ISO ambiguity and specify the natural two's complement semantics, checking overflow with the classic Hacker's Delight formula;

    ((x ^ s) & (y ^ s)) < 0

But the best way is to use the intrinsic __builtin_add_overflow or, depending on compiler support, its C23 standardization via <stdckdint.h> and ckd_add etc.


Yes, that's a good summary.


Will third party apps like bank apps be able to detect whether advanced mode is enabled or not, like how they currently detect if developer options is enabled?


That I'm not currently sure of.


I think the problem is simply that css is too restricted that you can style a fixed piece of html in any way you want. In practice, achieving some desired layout require changing the html structure. The missing layer would be something that can change the structure of html like js or xslt. In modern frontend development you already have data defined in some json, and html + css combined together is the presentation layer that can't really be separated.


This wouldn't work if the script is meant to be sourced (to set environment variables) isn't it?


No, it doesn't.

The way I actually have things setup, in case it helps. I don't change my default shell. I actually default to pretty much working within tmux. So, I kept my default shell to what the OS brings, then in my tmux config, I have,

    # set shell
    set -g default-shell /opt/homebrew/bin/fish
This means, that when I start my terminal, it drops me to zsh (macOS default). Then when I run tmux, it opens fish. The nice thing is that I inherit the environment of zsh.

I have my .zshrc and my .bashrc sourcing a .shellrc file which contains most of my env stuff. This keeps random utilities that write to .bashrc and zshrc working within fish too.


I think `zsh -l` start a login shell, which does not load zshrc so oh-my-zsh don't get initialized. Try `zsh -ic exit` and it should load zshrc before executing exit.

That said, the time of `zsh -ic exit` isn't really meaningful metric for measuring the performance of an interactive shell. See https://github.com/romkatv/zsh-bench#how-not-to-benchmark for details.


Valid points, I learned something new today. Thanks, you were right. If using -ic flags I am getting around 300 ms... Interesting how I never noticed, guess I don't open many terminal during the day


I don't think it is generally possible to escape from a docker container in default configuration (e.g. `docker run --rm -it alpine:3 sh`) if you have a reasonably update-to-date kernel from your distro. AFAIK a lot of kernel lpe use features like unprivileged user ns and io_uring which is not available in container by default, and truly unprivileged kernel lpe seems to be sufficient rare.


The kernel policy is that any distro that isn't using a rolling release kernel is unpatched and vulnerable, so "reasonably up-to-date" is going to lean heavily on what you consider "reasonable".

LPEs abound - unprivileged user ns was a whole gateway that was closed, io-uring was hot for a while, ebpf is another great target, and I'm sure more and more will be found every year as has been the case. Seccomp and unprivileged containers etc make a huge different to stomp out a lot of the attack surface, you can decide how comfortable you are with that though.


>The kernel policy is that any distro that isn't using a rolling release kernel is unpatched and vulnerable, so "reasonably up-to-date" is going to lean heavily on what you consider "reasonable".

I would expect major distributions to have embargoed CVE access specifically to prevent this issue.


Nope, that is not the case. For one thing, upstream doesn't issue CVEs and doesn't really care about CVEs or consider them valid. For another, they forbid or severely limit embargos.


To be honest, there are two ways to solve the problem of xkcd 2347, either putting efforts into the very small library or just stop depending on it. Both solutions are fine to me and Google apparent just choose the latter one here.


If not depending on a library is an option, then you dont really have an xkcd 2347 problem. The entire point of that comic is that some undermaintained dependencies are critical, without reasonable alternatives.


Except it's not Google whose "products" stop working by removing that dependency.


If being used in a CTF counts, then running latest docker with no extra privilege and non-root user on a reasonably up-to-date kernel meets the definition of secure I think. At least for what I have seen, this kind of infrastructure is pretty common in CTF.


For python specifically, the uuid4 function does use the randomness from os.urandom, which is supposed to be cryptographically random on most platforms.


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

Search: