1 /* chroot LD_PRELOAD wrapper to safely chroot any application 2 * 3 * (C) 2004 Henrik Nordstrom <hno@marasystems.com> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject 11 * to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Usage: 25 * 26 * This application is used as a LD_PRELOAD library to make any shared 27 * executable chroot itself and drop privileges in a safe manner after 28 * any dynamic linking has taken place. 29 * 30 * A number of environment variables is used to control how the 31 * application is chrooted: 32 * 33 * CHROOT_ROOT The path to where the application is to be chrooted 34 * (required) 35 * 36 * CHROOT_USER The user to run the application as (defaults to "nobody" 37 * if not defined) 38 * 39 * LD_PRELOAD Must include this application 40 * 41 * Diagnostics: 42 * 43 * If there is any problem chrooting the application an error message is 44 * printed on stderr, and execution of the application is terminated. 45 * 46 * Compiling: 47 * 48 * g++ -fpic -shared -o chroot_safe.so chroot_safe.cpp 49 * 50 * Suggested use: 51 * 52 * #!/bin/sh 53 * if [ $# -lt 3 ]; then 54 * echo "Usage: $0 user root application ..." >&2 55 * exit 1 56 * fi 57 * CHROOT_USER="$1"; export CHROOT_USER 58 * CHROOT_ROOT="$2"; export CHROOT_ROOT 59 * shift ; shift 60 * LD_PRELOAD="/path/to/chroot_safe.so"; export LD_PRELOAD 61 * exec "$@" 62 */ 63 64 #include <sys/types.h> 65 #include <unistd.h> 66 #include <grp.h> 67 #include <pwd.h> 68 #include <string.h> 69 #include <stdlib.h> 70 #include <errno.h> 71 72 class automatic_chroot { 73 private: failure(char * msg)74 static void failure(char *msg) { 75 char *error = strerror(errno); 76 write(2, msg, strlen(msg)); 77 if (errno != 0) { 78 write(2, ": ", 2); 79 write(2, error, strlen(error)); 80 } 81 write(2, "\n", 1); 82 _exit(1); 83 } 84 public: automatic_chroot()85 automatic_chroot() { 86 unsetenv("LD_PRELOAD"); 87 char *root = getenv("CHROOT_ROOT"); 88 if (root == NULL) 89 failure("CHROOT_ROOT not defined"); 90 char *user = getenv("CHROOT_USER"); 91 if (user == NULL) 92 user = "nobody"; 93 struct passwd *pwd = getpwnam(user); 94 if (pwd == NULL) 95 failure("User not found in /etc/passwd"); 96 if (setgid(pwd->pw_gid)) 97 failure("setgid failure"); 98 if (initgroups(user, pwd->pw_gid)) 99 failure("initgroups failure"); 100 if (chdir(root)) 101 failure("chdir failure"); 102 if (chroot(".")) 103 failure("chroot failure"); 104 if (setuid(pwd->pw_uid)) 105 failure("setresuid failure"); 106 unsetenv("CHROOT_ROOT"); 107 unsetenv("CHROOT_USER"); 108 } 109 }; 110 111 static class automatic_chroot do_chroot; 112