From owner-svn-src-projects@FreeBSD.ORG Thu Nov 4 18:40:29 2010 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D340C106564A; Thu, 4 Nov 2010 18:40:29 +0000 (UTC) (envelope-from jamie@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C18A78FC12; Thu, 4 Nov 2010 18:40:29 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oA4IeTac069254; Thu, 4 Nov 2010 18:40:29 GMT (envelope-from jamie@svn.freebsd.org) Received: (from jamie@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oA4IeTZx069251; Thu, 4 Nov 2010 18:40:29 GMT (envelope-from jamie@svn.freebsd.org) Message-Id: <201011041840.oA4IeTZx069251@svn.freebsd.org> From: Jamie Gritton Date: Thu, 4 Nov 2010 18:40:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214797 - projects/jailconf/usr.sbin/jail X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Nov 2010 18:40:29 -0000 Author: jamie Date: Thu Nov 4 18:40:29 2010 New Revision: 214797 URL: http://svn.freebsd.org/changeset/base/214797 Log: Check paths for security: path must be absolute. mount paths must exist and have no symlinks beyond the jail's path itself. consolelog must exist (apart from the final component) and have no symlinks beyond the jail's path itself. Modified: projects/jailconf/usr.sbin/jail/command.c projects/jailconf/usr.sbin/jail/jail.c Modified: projects/jailconf/usr.sbin/jail/command.c ============================================================================== --- projects/jailconf/usr.sbin/jail/command.c Thu Nov 4 18:24:05 2010 (r214796) +++ projects/jailconf/usr.sbin/jail/command.c Thu Nov 4 18:40:29 2010 (r214797) @@ -68,6 +68,8 @@ static int get_user_info(struct cfjail * static void add_proc(struct cfjail *j, pid_t pid); static void clear_procs(struct cfjail *j); static struct cfjail *find_proc(pid_t pid); +static int check_path(struct cfjail *j, const char *pname, const char *path, + int isfile); static struct cfjails sleeping = TAILQ_HEAD_INITIALIZER(sleeping); static struct cfjails runnable = TAILQ_HEAD_INITIALIZER(runnable); @@ -84,7 +86,7 @@ run_command(struct cfjail *j, int *plimi struct cfstring *comstring, *s; login_cap_t *lcap; char **argv; - char *cs, *addr, *comcs; + char *cs, *addr, *comcs, *devpath; const char *jidstr, *conslog, *path, *ruleset, *term, *username; size_t comlen; pid_t pid; @@ -197,12 +199,16 @@ run_command(struct cfjail *j, int *plimi for (cs = strtok(comcs, " \t\f\v\r\n"); cs && argc < 4; cs = strtok(NULL, " \t\f\v\r\n")) argv[argc++] = cs; + if (argc == 0) + return 0; if (argc < 3) { jail_warnx(j, "%s: %s: missing information", j->intparams[comparam]->name, comstring->s); failed(j); return -1; } + if (check_path(j, j->intparams[comparam]->name, argv[1], 0) < 0) + return -1; if (down) { argv[4] = NULL; argv[3] = argv[1]; @@ -230,11 +236,14 @@ run_command(struct cfjail *j, int *plimi failed(j); return -1; } + devpath = alloca(strlen(path) + 5); + sprintf(devpath, "%s/dev", path); + if (check_path(j, "mount.devfs", devpath, 0) < 0) + return -1; if (down) { argv = alloca(3 * sizeof(char *)); *(const char **)&argv[0] = "/sbin/umount"; - argv[1] = alloca(strlen(path) + 5); - sprintf(argv[1], "%s/dev", path); + argv[1] = devpath; argv[2] = NULL; } else { argv = alloca(4 * sizeof(char *)); @@ -307,6 +316,8 @@ run_command(struct cfjail *j, int *plimi consfd = 0; if (injail && (conslog = string_param(j->intparams[IP_EXEC_CONSOLELOG]))) { + if (check_path(j, "exec.consolelog", conslog, 1) < 0) + return -1; consfd = open(conslog, O_WRONLY | O_CREAT | O_APPEND, DEFFILEMODE); if (consfd < 0) { @@ -666,3 +677,57 @@ get_user_info(struct cfjail *j, const ch } return 0; } + +/* + * Make sure a mount or consolelog path is a valid absolute pathname + * with no symlinks. + */ +static int +check_path(struct cfjail *j, const char *pname, const char *path, int isfile) +{ + struct stat st; + char *tpath, *p; + const char *jailpath; + size_t jplen; + + if (path[0] != '/') { + jail_warnx(j, "%s: %s: not an absolute pathname", + pname, path); + failed(j); + return -1; + } + /* + * Only check for symlinks in components below the jail's path, + * since that's where the security risk lies. + */ + jailpath = string_param(j->intparams[KP_PATH]); + if (jailpath == NULL) + jailpath = ""; + jplen = strlen(jailpath); + if (strncmp(path, jailpath, jplen) || path[jplen] != '/') + return 0; + tpath = alloca(strlen(path) + 1); + strcpy(tpath, path); + for (p = tpath + jplen; p != NULL; ) { + p = strchr(p + 1, '/'); + if (p) + *p = '\0'; + if (lstat(tpath, &st) < 0) { + if (errno == ENOENT && isfile && !p) + break; + jail_warnx(j, "%s: %s: %s", pname, tpath, + strerror(errno)); + failed(j); + return -1; + } + if (S_ISLNK(st.st_mode)) { + jail_warnx(j, "%s: %s is a symbolic link", + pname, tpath); + failed(j); + return -1; + } + if (p) + *p = '/'; + } + return 0; +} Modified: projects/jailconf/usr.sbin/jail/jail.c ============================================================================== --- projects/jailconf/usr.sbin/jail/jail.c Thu Nov 4 18:24:05 2010 (r214796) +++ projects/jailconf/usr.sbin/jail/jail.c Thu Nov 4 18:40:29 2010 (r214797) @@ -659,6 +659,12 @@ create_jail(struct cfjail *j) * gives. */ if ((path = string_param(j->intparams[KP_PATH]))) { + if (path[0] != '/') { + jail_warnx(j, "path %s: not an absolute pathname", + path); + failed(j); + return -1; + } if (stat(path, &st) < 0) { jail_warnx(j, "path %s: %s", path, strerror(errno)); failed(j);