1. 9
  1.  

  2. 4

    First, to call itself a process could [simply] execute /proc/self/exe, which is a in-memory representation of the process.

    There’s no such representation available as a file. /proc/self/exe is just a symlink to the executable that was used to create the process.

    Because of that, it’s OK to overwrite the command’s arguments, including os.Args[0]. No harm will be made, as the executable is not read from the disk.

    You can always call a process with whatever args[0] you like. No harm would be done.

    1. 4

      Although /proc/self/exe looks like a symbolic link, it behaves differently if you open it. It’s actually more like a hard link to the original file. You can rename or delete the original file, and still open it via /proc/self/exe.

      1. -4

        No harm will be made, as the executable is not read from the disk.

        the executable is definitely read from the disk

        Again, this was only possible because we are executing /proc/self/exe instead of loading the executable from disk again.

        no

        The kernel already has open file descriptors for all running processes, so the child process will be based on the in-memory representation of the parent.

        no that’s not how it works, and file descriptors aren’t magic objects that cache all the data in memory

        The executable could even be removed from the disk and the child would still be executed.

        that’s because it won’t actually be removed if it’s still used, not because there’s a copy in memory

        <3 systems engineering blog posts written by people who didn’t take unix101

        1. 12

          Instead of telling people they are idiots, please use this opportunity to correct the mistakes that the others made. It’ll make you feel good, and not make the others feel bad. Let’s prop up everyone, And not just sit there flexing muscles.

          1. 3

            Sorry for disappointing you :)

            I got that (wrongly) from a code comment in Moby (please check my comment above) and didn’t check the facts.

            1. 2

              I’m not saying that the OP was correct, I’m just saying that:

              /proc/self/exe is just a symlink to the executable

              ,,, is also not completely correct.

          2. 3

            Thanks for pointing out my mistakes! I just fixed the text.

            I made some bad assumptions when I read this comment [1] in from from Docker and failed to validate it. Sorry.

            By the way, is it just by bad English or that comment is actually wrong as well?

            [1] https://github.com/moby/moby/blob/48c3df015d3118b92032b7bdbf105b5e7617720d/pkg/reexec/command_linux.go#L18

            1. 1

              that comment is actually wrong as well?

              I don’t think it’s strictly correct, but for the purpose of the code in question it is accurate. That is, /proc/self/exe points to the executable file that was used to launch “this” process - even if it has moved or been deleted - and this most likely matches the “in memory” image of the program executable; but I don’t believe that’s guaranteed.

              If you want to test and make sure, try a program which opens its own executable for writing and trashes the contents, and then execute /proc/self/exe. I’m pretty sure you’ll find it crashes.

              1. 3

                but I don’t believe that’s guaranteed.

                I think it’s guaranteed on local file systems as a consequence of other behavior. I don’t think you can open a file for writing when it’s executing – you should get ETXTBSY when you try to do that. That means that as long as you’re pointing at the original binary, nobody has modified it.

                I don’t think that holds on NFS, though.

                1. 1

                  If you want to test and make sure, try a program which opens its own executable for writing and trashes the contents, and then execute /proc/self/exe. I’m pretty sure you’ll find it crashes

                  Actually, scratch that. You won’t be able to write to the executable since you’ll get ETXTBUSY when you try to open it. So, for pretty much all intents and purposes, the comment is correct.

                  1. 1

                    Interesting. Thank you for your insights.

                    In order to satisfy my curiosity, I created this small program [1] that calls /proc/self/exe infinitely and prints the result of readlink.

                    When I run the program and then delete its binary (i.e., the binary that /proc/self/exe points to), the program keeps successfully calling itself. The only difference is that now /proc/self/exe points to /my/path/proc (deleted).

                    [1] https://gist.github.com/bertinatto/5769867b5e838a773b38e57d2fd5ce13

              2. 1

                One interesting behavior of execing /proc/self/exe is that it doesn’t play well with in place upgrades. As others have mentioned it’s a hard link to the original file.