I have 2 files: /MyDir/a and /MyDir/MySubDir/b and am running a bash script, to which I want to add code to make file /a point to file /b, but only in the current process and its descendants.

In hopes of making /MyDir/a point to /MyDir/MySubDir/b in the context of only the current process (not including its descendants, yet) I tried to first make the current process run in its own mount namespace by running a small C program in my script that performs


and then

mount --bind /MyDir/MySubDir/b /MyDir/a.

Unfortunately, this didn't work as I expected since the mount was still visible by other processes, despite the system call reporting success.

In another attempt, I tried to make the mount from the C code by calling

mount("/MyDir/a", "/MyDir/MySubDir/b", "ext3", MS_BIND, null)

But this didn't work as the mount didn't take effect at all (despite the call reporting success).

Is there a way of making /MyDir/a point to /MyDir/MySubDir/b in the context of only the current process and its descendants using a bash script?

I also read a little about chroot, but this applies only to the / directory... Is there anything similar to chroot that applies only to a particular subdirectory?

Thanks for your time!

  • commands executed as the root user, right? – A.B May 18 '18 at 21:31
  • Yes, that's right – Ben S. May 18 '18 at 22:39
  • "But this didn't work as the mount didn't take effect at all" How did you check this? How are your C program and the shell command mount related? Did you execve() from the C program to the shell? – Hauke Laging May 18 '18 at 22:44
  • This writing and reading was done within the C program? – Hauke Laging May 18 '18 at 22:50
  • No, the writing was done by vi, before any mount operations, and reading was done by cat from within the bash script – Ben S. May 18 '18 at 22:59

A shell-only solution would be:

For interactive shell:

# unshare --mount
# mount --bind /MyDir/MySubDir/b /MyDir/a

non-interactively, before a script that doesn't have to know about these settings:

# unshare --mount sh -c 'mount --bind /MyDir/MySubDir/b /MyDir/a; exec somethingelse'

The unshare manpage also warns about shared subtree mounts . If you have to disable them, consider adding for example --make-private to mount.

As Hauke told, you have to be sure to not leave the namespace just after having created it, because it will disappear.

If needed there's a method to maintain a namespace without process. Since it involves mount, it's just a bit more tricky for a mount namespace. Here's an interactive example for this:

shell1# unshare --mount
shell1# echo $$

shell2# : > /root/mntreference
shell2# mount --bind /proc/12345/ns/mnt /root/mntreference

Now as long as this reference is kept mounted, the namespace won't disappear even if there's no process using it anymore. Using nsenter --mount=/root/mntreference will enter it, so you can easily run additional scripts in it.

Using the equivalent in C shouldn't be a problem.

  • No need to use exec with unshare: unshare --mount bash is enough. Then the mount --bind can simply be done in the shell. – Hauke Laging May 19 '18 at 9:21
  • Indeed, that was for a "one liner". I removed exec where useless (kept one exec, no need to have an useless sh staying around) – A.B May 19 '18 at 11:39

Unfortunately you still haven't explained how the C program and the script are related.

A possible (and here probable) reason for the problem is: You call the C program from the script but the namespace change is effective only within the C program (and possible children). After that program exists the situation is unchanged for all following commands.

You should start a shell from the C program by calling execve() for the intended shell.

  • The C program is indeed called from within the script. Now I understand why it didn't work. – Ben S. May 18 '18 at 23:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.