9

I'm working on an rsync-based backup for a FreeNAS system.

Part of the backup process involves logging into the remote system that serves as the backup storage. Whenever I do that, I get the message

Could not create directory '/root/.ssh'.

I'm assuming this is due to the fact that /root is read-only, because when I try to create ~/.ssh manually, I receive:

mkdir: /root/.ssh: Read-only file system

Because of this, I have already moved the known_hosts file more appropriate for my backup process and am using -o UserKnownHostsFile to resolve any issues related to that.

However, ssh still tries to create the ~/.ssh folder when I invoke it. How can I get it to not try to create the folder?

Oliver Salzburg
  • 1,039
  • 2
  • 11
  • 23

2 Answers2

8

The solution mentioned here is good, but I was looking for one which didn't require ~/.ssh to be present or required an attempt for it to be created (running on Windows, distributing a MSYS built ssh.exe, but running on other machines without MSYS/Cygwin installed).

Unfortunately, it appears the routine is hardcoded in the source code, regardless of what value you give to UserKnownHostsFile:

    r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
        strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
    if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
#ifdef WITH_SELINUX
        ssh_selinux_setfscreatecon(buf);
#endif
        if (mkdir(buf, 0700) < 0)
            error("Could not create directory '%.200s'.",
                buf);
#ifdef WITH_SELINUX
        ssh_selinux_setfscreatecon(NULL);
#endif
    }

However, it's interesting to note that it attempts to expand the $HOME environment variable to determine the home directory. Since the buffer is around 256 bytes, we can actually bypass the if condition by overflowing the buffer (defining HOME to a string longer than 256 bytes), e.g.:

export HOME=$HOME/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././.
zinga
  • 181
  • 1
  • 1
  • Wouldn't it be easier to set `$HOME` to `/tmp` or some place where you can write? – muru Jun 09 '17 at 05:34
  • Windows doesn't have `/tmp` unfortunately, or rather, I don't know what it maps to (if it does at all). `%tmp%` is the Windows equivalent, however it needs to be converted to a MSYS-like path for it to work (eg `/c/Windows/temp` instead of `C:\Windows\temp`), which is a major pain to do in a batch file. Ideally though, I don't want it creating directories at all. – zinga Jun 09 '17 at 06:18
5

Remount the root filesystem read-write temporarily and make a symbolic link for .ssh that points somewhere where ssh can write. This way you can also do things like add ssh keys in the future, or allow new known_hosts without having to go to extra strenuous steps. And you could get rid of your -o UserKnownHostsFile option at the same time.

kurtm
  • 6,925
  • 1
  • 23
  • 21
  • 1
    +1 simple and effective. Side note another approach in the same vein is just changing the user's defined location for their home directory to be an rw mounted space. – Jimmy Hoffa Oct 25 '13 at 20:03
  • Your suggestion is probably the way to go. For some reason I assumed that `/root` might be recreated from other data at each reboot, but I never actually verified that. I'll verify this and get back to you :) – Oliver Salzburg Oct 26 '13 at 00:57
  • +oliversalzburg That would blow a hole in my idea. But you could work around that if you find out where it is re-creating `/root` from and changing the original. – kurtm Oct 26 '13 at 01:05