4

I'm coding a bash script that:

  • runs some sudoed command at initialization
  • releases root permissions for security purposes (sudo -K)
  • runs an unprivilegied program
  • but needs root permissions when terminating

I'm looking for a simple & secure way to avoid asking the user its password again at script termination .

I'm thinking of a fork before sudo -K waiting to catch a term signal. I don't know if that's the most elegant/secure solution.

Here's the code:

sudo unshare -m \
  sudo -u "$USER" -g `id -g -n "$USER"` \
  bash -c \
  "sudo mount --bind \"$MOUNT_DIR\" \"$MOUNT_DIR\"; \
  sudo mount --make-private \"$MOUNT_DIR\"; \
  sudo -K; \
  <unprivilegied program here>; \
  sudo umount \"$MOUNT_DIR\""

NB: For info, this creates a private mount in a namespace that only the program will have acccess to. unshare -r is not an option to run the program in.

5

I notice that you're doing a lot of switching back and forth between the regular user and root:

  • switch to root to run unshare
  • switch back to the normal user to run bash (although it seems like you don't use any bashisms so you could as well run sh which would be more portable and possibly more lightweight)
  • switch back to root multiple times inside that bash shell to do more privileged things

I think you can simplify this and reduce the number of times to need to bounce back and forth between users and solve your problem at the same time.

sudo unshare -m sh -c '
        mount --bind "$1" "$1";
        mount --make-private "$1";
        exec sudo -u "#$SUDO_UID" -g "#$SUDO_GID" sh -c "
                sudo -K;
                <unprivilegied program here>
        "
' - "$MOUNT_DIR"

Technically, there is a root shell that is continuously running throughout the execution of the unprivileged part, but the only thing that shell is going to do is wait for the unprivileged part to complete and nothing else. But if you really want to give up your sudo privileges ahead of time and not have to ask the user to grant them again, all alternatives are also going to involve a lingering process waiting for the signal to run the umount command in some fashion or other.

As an aside, it's nice that your command is all self-contained and everything, and I kept that spirit in my suggestion, but honestly large blocks of code supplied as a command line option to sh -c are hard to write and read and maintain because of all the quoting complexities you have to worry about, and I would recommend factoring them out into their own script and running the whole thing as:

sudo unshare -m /usr/local/bin/script-that-does-the-rest-of-the-work

Also, doing that would make it easier to write your sudo rules for permitted commands, which are difficult to write using my suggestion unless you permit the user to run any command at all, which is the same as giving them full root access. In this case you'd have to permit the command unshare -m sh -c <huge block> "$MOUNT_DIR" which is a pretty challenging Cmnd_Alias to write.

  • Thanks Celada for your deep answer. Please note that I intend to run unshare inside a password-protected GNU screen session (so the full command is screen <params> sudo unshare ...) to make the program screen detachable (hidden) and reattachable (visible). Isn't there a risk that the user could get a screen with a root shell by sending commands to the screen session? – KrisWebDev Mar 6 '16 at 22:40
  • I don't see how, if your sudo rules are written strictly enough (for example, don't let the user pass an arbitrary dangerous value for "$MOUNT_DIR"). – Celada Mar 6 '16 at 22:44
  • I don't know if you saw Gilles' answer, but although I didn't mention it in my answer, I support his opinion that calling sudo -K is irrelevant. It isn't the job of your script to manage sudo's cache. If you're worried about users being able to run insecure commands as root, control it with an appropriate sudo policy. – Celada Mar 6 '16 at 22:46
  • There is no need to unmount as the mount is removed when all references to the mount namespace are lost. – Timothy Baldwin Mar 12 '17 at 16:48
  • @TimothyBaldwin: that makes sense. I am honestly not that experienced with mount namespaces and unshare. Thanks for the suggestion, I have edited it into the answer. – Celada Mar 12 '17 at 17:30

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.