SFTP Chroot

lattera lattera at gmail.com
Wed Nov 18 13:30:13 EST 2009


Hi all,

Today, I was tasked at work with setting up a chroot SFTP server on a 64bit
Arch Linux server. I naturally turned to Arch Linux's wiki article on the
subject (http://wiki.archlinux.org/index.php/SFTP-chroot) and the directions
were very clear. However, the directions did not work. I kept getting a
"Write failed: Broken pipe" error after attempting to connect. Upon digging
through the code for OpenSSH 5.3p1 , I found this snippet of code, starting
at line 1399 of session.c and ending at line 1452:


/*
>  * Chroot into a directory after checking it for safety: all path
> components
>  * must be root-owned directories with strict permissions.
>  */
> static void
> safely_chroot(const char *path, uid_t uid)
> {
>     const char *cp;
>     char component[MAXPATHLEN];
>     struct stat st;
>
>     if (*path != '/')
>         fatal("chroot path does not begin at root");
>     if (strlen(path) >= sizeof(component))
>         fatal("chroot path too long");
>
>     /*
>      * Descend the path, checking that each component is a
>      * root-owned directory with strict permissions.
>      */
>     for (cp = path; cp != NULL;) {
>         if ((cp = strchr(cp, '/')) == NULL)
>             strlcpy(component, path, sizeof(component));
>         else {
>             cp++;
>             memcpy(component, path, cp - path);
>             component[cp - path] = '\0';
>         }
>
>         debug3("%s: checking '%s'", __func__, component);
>
>         if (stat(component, &st) != 0)
>             fatal("%s: stat(\"%s\"): %s", __func__,
>                 component, strerror(errno));
>         if (st.st_uid != 0 || (st.st_mode & 022) != 0)
>             fatal("bad ownership or modes for chroot "
>                 "directory %s\"%s\"",
>                 cp == NULL ? "" : "component ", component);
>         if (!S_ISDIR(st.st_mode))
>             fatal("chroot path %s\"%s\" is not a directory",
>                 cp == NULL ? "" : "component ", component);
>
>     }
>
>     if (chdir(path) == -1)
>         fatal("Unable to chdir to chroot path \"%s\": "
>             "%s", path, strerror(errno));
>     if (chroot(path) == -1)
>         fatal("chroot(\"%s\"): %s", path, strerror(errno));
>     if (chdir("/") == -1)
>         fatal("%s: chdir(/) after chroot: %s",
>             __func__, strerror(errno));
>     verbose("Changed root directory to \"%s\"", path);
> }
>

Why should all the directory tree be root-owned and have that set of
permissions? This is preventing me from setting the chroot to /home/<user>
and be done with it, like that wiki article suggests. If there is no
security concern, I would like to remove the offending code (the for loop).
I will probably do this anyways for the project I'm working on, but I am
unsure if the public as a whole could benefit from such a change.

Thanks for taking the time to respond,

Shawn


More information about the openssh-unix-dev mailing list