From dfbd7cf932e9c495498be1226b3a06e65a4d9bba Mon Sep 17 00:00:00 2001 From: Paul Howarth Date: Jan 16 2013 20:42:10 +0000 Subject: Update patch for CVE-2012-6095 to cover vroot cases --- diff --git a/proftpd-1.3.4b-bug3841.patch b/proftpd-1.3.4b-bug3841.patch index a0febdd..e070d1f 100644 --- a/proftpd-1.3.4b-bug3841.patch +++ b/proftpd-1.3.4b-bug3841.patch @@ -1,6 +1,41 @@ ---- contrib/mod_sftp/fxp.c 2012/12/27 22:29:39 1.134.2.7 -+++ contrib/mod_sftp/fxp.c 2012/12/28 00:03:27 1.134.2.8 -@@ -6133,7 +6133,7 @@ +--- configure.in ++++ configure.in +@@ -1653,7 +1653,7 @@ LDFLAGS=$old_LDFLAGS + AC_PROG_GCC_TRADITIONAL + AC_TYPE_SIGNAL + AC_FUNC_VPRINTF +-AC_CHECK_FUNCS(bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp nl_langinfo) ++AC_CHECK_FUNCS(bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp mkdtemp nl_langinfo) + AC_CHECK_FUNC(gai_strerror, + AC_DEFINE(HAVE_GAI_STRERROR, 1, + [Define if you have the gai_strerror() function]), +--- configure ++++ configure +@@ -27910,7 +27910,8 @@ done + + + +-for ac_func in bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp nl_langinfo ++ ++for ac_func in bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp mkdtemp nl_langinfo + do + as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` + { echo "$as_me:$LINENO: checking for $ac_func" >&5 +--- config.h.in ++++ config.h.in +@@ -375,6 +375,9 @@ + /* Define if you have the mkdir function. */ + #undef HAVE_MKDIR + ++/* Define if you have the mkdtemp function. */ ++#undef HAVE_MKDTEMP ++ + /* Define if you have the mkstemp function. */ + #undef HAVE_MKSTEMP + +--- contrib/mod_sftp/fxp.c ++++ contrib/mod_sftp/fxp.c +@@ -6114,7 +6114,7 @@ static int fxp_handle_mkdir(struct fxp_p (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "creating directory '%s' with mode 0%o", path, (unsigned int) dir_mode); @@ -9,9 +44,9 @@ if (res < 0) { const char *reason; int xerrno = errno; ---- contrib/mod_sftp/scp.c 2012/12/13 23:05:58 1.64.2.5 -+++ contrib/mod_sftp/scp.c 2012/12/28 00:03:27 1.64.2.6 -@@ -821,7 +821,7 @@ +--- contrib/mod_sftp/scp.c ++++ contrib/mod_sftp/scp.c +@@ -820,7 +820,7 @@ static int recv_finfo(pool *p, uint32_t * recursive directory uploads via SCP? */ @@ -20,9 +55,9 @@ xerrno = errno; (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, ---- include/fsio.h 2011/05/23 20:35:35 1.28 -+++ include/fsio.h 2012/12/28 00:03:26 1.28.2.2 -@@ -125,6 +125,7 @@ +--- include/fsio.h ++++ include/fsio.h +@@ -125,6 +125,7 @@ struct fs_rec { int (*fchmod)(pr_fh_t *, int, mode_t); int (*chown)(pr_fs_t *, const char *, uid_t, gid_t); int (*fchown)(pr_fh_t *, int, uid_t, gid_t); @@ -30,7 +65,7 @@ int (*access)(pr_fs_t *, const char *, int, uid_t, gid_t, array_header *); int (*faccess)(pr_fh_t *, int, uid_t, gid_t, array_header *); int (*utimes)(pr_fs_t *, const char *, struct timeval *); -@@ -243,6 +244,7 @@ +@@ -243,6 +244,7 @@ int pr_fsio_mkdir(const char *, mode_t); int pr_fsio_rmdir(const char *); int pr_fsio_rename(const char *, const char *); int pr_fsio_rename_canon(const char *, const char *); @@ -38,7 +73,7 @@ int pr_fsio_unlink(const char *); int pr_fsio_unlink_canon(const char *); pr_fh_t *pr_fsio_open(const char *, int); -@@ -264,6 +266,7 @@ +@@ -264,6 +266,7 @@ int pr_fsio_fchmod(pr_fh_t *, mode_t); int pr_fsio_chmod_canon(const char *, mode_t); int pr_fsio_chown(const char *, uid_t, gid_t); int pr_fsio_fchown(pr_fh_t *, uid_t, gid_t); @@ -46,9 +81,38 @@ int pr_fsio_chown_canon(const char *, uid_t, gid_t); int pr_fsio_chroot(const char *); int pr_fsio_access(const char *, int, uid_t, gid_t, array_header *); ---- modules/mod_core.c 2012/12/27 00:38:37 1.413.2.2 -+++ modules/mod_core.c 2012/12/28 00:03:27 1.413.2.3 -@@ -4643,7 +4643,8 @@ +@@ -272,6 +275,11 @@ int pr_fsio_utimes(const char *, struct + int pr_fsio_futimes(pr_fh_t *, struct timeval *); + off_t pr_fsio_lseek(pr_fh_t *, off_t, int); + ++/* Set a flag determining whether to use mkdtemp(3) (if available) or not. ++ * Returns the previously-set value. ++ */ ++int pr_fsio_set_use_mkdtemp(int); ++ + /* FS-related functions */ + + char *pr_fsio_getline(char *, int, pr_fh_t *, unsigned int *); +--- modules/mod_core.c ++++ modules/mod_core.c +@@ -4306,7 +4306,7 @@ int core_chgrp(cmd_rec *cmd, char *dir, + } + cmd->argv[0] = cmd_name; + +- return pr_fsio_chown(dir, uid, gid); ++ return pr_fsio_lchown(dir, uid, gid); + } + + int core_chmod(cmd_rec *cmd, char *dir, mode_t mode) { +@@ -4583,7 +4583,6 @@ MODRET core_rmd(cmd_rec *cmd) { + MODRET core_mkd(cmd_rec *cmd) { + int res; + char *dir; +- struct stat st; + + CHECK_CMD_MIN_ARGS(cmd, 2); + +@@ -4638,7 +4637,8 @@ MODRET core_mkd(cmd_rec *cmd) { return PR_ERROR(cmd); } @@ -58,7 +122,7 @@ int xerrno = errno; (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " -@@ -4652,71 +4653,6 @@ +@@ -4652,71 +4652,6 @@ MODRET core_mkd(cmd_rec *cmd) { return PR_ERROR(cmd); } @@ -130,134 +194,9 @@ pr_response_add(R_257, _("\"%s\" - Directory successfully created"), quote_dir(cmd, dir)); ---- modules/mod_xfer.c 2011/09/24 19:54:23 1.297 -+++ modules/mod_xfer.c 2012/12/26 23:33:32 1.297.2.1 -@@ -866,27 +866,25 @@ - * requested via GroupOwner. - */ - if ((session.fsuid != (uid_t) -1) && xfer_path) { -- int err = 0, iserr = 0; -+ int res, xerrno = 0; - - PRIVS_ROOT -- if (pr_fsio_chown(xfer_path, session.fsuid, session.fsgid) == -1) { -- iserr++; -- err = errno; -- } -+ res = pr_fsio_lchown(xfer_path, session.fsuid, session.fsgid); -+ xerrno = errno; - PRIVS_RELINQUISH - -- if (iserr) { -- pr_log_pri(PR_LOG_WARNING, "chown(%s) as root failed: %s", xfer_path, -- strerror(err)); -+ if (res < 0) { -+ pr_log_pri(PR_LOG_WARNING, "lchown(%s) as root failed: %s", xfer_path, -+ strerror(xerrno)); - - } else { - if (session.fsgid != (gid_t) -1) { -- pr_log_debug(DEBUG2, "root chown(%s) to uid %lu, gid %lu successful", -+ pr_log_debug(DEBUG2, "root lchown(%s) to uid %lu, gid %lu successful", - xfer_path, (unsigned long) session.fsuid, - (unsigned long) session.fsgid); - - } else { -- pr_log_debug(DEBUG2, "root chown(%s) to uid %lu successful", xfer_path, -+ pr_log_debug(DEBUG2, "root lchown(%s) to uid %lu successful", xfer_path, - (unsigned long) session.fsuid); - } - -@@ -902,16 +900,15 @@ - * root privs aren't used, the chmod() will fail because the old owner/ - * session user doesn't have the necessary privileges to do so). - */ -- iserr = 0; -+ xerrno = 0; - PRIVS_ROOT -- if (pr_fsio_chmod(xfer_path, st.st_mode) < 0) { -- iserr++; -- } -+ res = pr_fsio_chmod(xfer_path, st.st_mode); -+ xerrno = errno; - PRIVS_RELINQUISH - -- if (iserr) { -+ if (res < 0) { - pr_log_debug(DEBUG0, "root chmod(%s) to %04o failed: %s", xfer_path, -- (unsigned int) st.st_mode, strerror(errno)); -+ (unsigned int) st.st_mode, strerror(xerrno)); - - } else { - pr_log_debug(DEBUG2, "root chmod(%s) to %04o successful", xfer_path, -@@ -921,7 +918,7 @@ - - } else if ((session.fsgid != (gid_t) -1) && xfer_path) { - register unsigned int i; -- int res, use_root_privs = TRUE; -+ int res, use_root_privs = TRUE, xerrno; - - /* Check if session.fsgid is in session.gids. If not, use root privs. */ - for (i = 0; i < session.gids->nelts; i++) { -@@ -937,18 +934,19 @@ - PRIVS_ROOT - } - -- res = pr_fsio_chown(xfer_path, (uid_t) -1, session.fsgid); -+ res = pr_fsio_lchown(xfer_path, (uid_t) -1, session.fsgid); -+ xerrno = errno; - - if (use_root_privs) { - PRIVS_RELINQUISH - } - -- if (res == -1) { -- pr_log_pri(PR_LOG_WARNING, "%schown(%s) failed: %s", -- use_root_privs ? "root " : "", xfer_path, strerror(errno)); -+ if (res < 0) { -+ pr_log_pri(PR_LOG_WARNING, "%slchown(%s) failed: %s", -+ use_root_privs ? "root " : "", xfer_path, strerror(xerrno)); - - } else { -- pr_log_debug(DEBUG2, "%schown(%s) to gid %lu successful", -+ pr_log_debug(DEBUG2, "%slchown(%s) to gid %lu successful", - use_root_privs ? "root " : "", xfer_path, - (unsigned long) session.fsgid); - -@@ -960,6 +958,7 @@ - } - - res = pr_fsio_chmod(xfer_path, st.st_mode); -+ xerrno = errno; - - if (use_root_privs) { - PRIVS_RELINQUISH -@@ -968,7 +967,7 @@ - if (res < 0) { - pr_log_debug(DEBUG0, "%schmod(%s) to %04o failed: %s", - use_root_privs ? "root " : "", xfer_path, (unsigned int) st.st_mode, -- strerror(errno)); -+ strerror(xerrno)); - } - } - } ---- src/fsio.c 2011/05/27 00:38:45 1.102 -+++ src/fsio.c 2012/12/29 00:11:49 1.102.2.3 -@@ -2,7 +2,7 @@ - * ProFTPD - FTP server daemon - * Copyright (c) 1997, 1998 Public Flood Software - * Copyright (C) 1999, 2000 MacGyver aka Habeeb J. Dihu -- * Copyright (C) 2001-2011 The ProFTPD Project -+ * Copyright (C) 2001-2012 The ProFTPD Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -25,10 +25,11 @@ - */ - - /* ProFTPD virtual/modular file-system support -- * $Id: fsio.c,v 1.102 2011/05/27 00:38:45 castaglia Exp $ -+ * $Id: fsio.c,v 1.102.2.3 2012/12/29 00:11:49 castaglia Exp $ +--- src/fsio.c ++++ src/fsio.c +@@ -29,6 +29,7 @@ */ #include "conf.h" @@ -265,7 +204,21 @@ #ifdef HAVE_SYS_STATVFS_H # include -@@ -175,6 +176,10 @@ +@@ -80,6 +81,13 @@ static unsigned char chk_fs_map = FALSE; + static char vwd[PR_TUNABLE_PATH_MAX + 1] = "/"; + static char cwd[PR_TUNABLE_PATH_MAX + 1] = "/"; + ++/* Runtime enabling/disabling of mkdtemp(3) use. */ ++#ifdef HAVE_MKDTEMP ++static int use_mkdtemp = TRUE; ++#else ++static int use_mkdtemp = FALSE; ++#endif /* HAVE_MKDTEMP */ ++ + /* Runtime enabling/disabling of encoding of paths. */ + static int use_encoding = TRUE; + +@@ -175,6 +183,10 @@ static int sys_fchown(pr_fh_t *fh, int f return fchown(fd, uid, gid); } @@ -276,10 +229,22 @@ /* We provide our own equivalent of access(2) here, rather than using * access(2) directly, because access(2) uses the real IDs, rather than * the effective IDs, of the process. -@@ -2498,6 +2503,171 @@ +@@ -2498,6 +2510,213 @@ int pr_fsio_mkdir(const char *path, mode return res; } ++int pr_fsio_set_use_mkdtemp(int value) { ++ int prev_value; ++ ++ prev_value = use_mkdtemp; ++ ++#ifdef HAVE_MKDTEMP ++ use_mkdtemp = value; ++#endif /* HAVE_MKDTEMP */ ++ ++ return prev_value; ++} ++ +/* "safe mkdir" variant of mkdir(2), uses mkdtemp(3), lchown(2), and + * rename(2) to create a directory which cannot be hijacked by a symlink + * race (hopefully) before the UserOwner/GroupOwner ownership changes are @@ -287,14 +252,10 @@ + */ +int pr_fsio_smkdir(pool *p, const char *path, mode_t mode, uid_t uid, + gid_t gid) { -+ int res; ++ int res, use_root_privs = TRUE, xerrno = 0; + char *tmpl_path; -+#ifdef HAVE_MKDTEMP -+ mode_t mask, *dir_umask; -+ char *dst_dir, *tmpl, *ptr; -+ size_t tmpl_len; -+ struct stat st; -+#endif /* HAVE_MKDTEMP */ ++ char *dst_dir, *tmpl; ++ size_t dst_dirlen, tmpl_len; + + if (path == NULL) { + errno = EINVAL; @@ -302,38 +263,60 @@ + } + +#ifdef HAVE_MKDTEMP -+ ptr = strrchr(path, '/'); -+ if (ptr == NULL) { -+ errno = EINVAL; -+ return -1; -+ } ++ if (use_mkdtemp == TRUE) { ++ char *ptr; ++ struct stat st; ++ ++ ptr = strrchr(path, '/'); ++ if (ptr == NULL) { ++ errno = EINVAL; ++ return -1; ++ } + -+ dst_dir = pstrndup(p, path, (ptr - path)); -+ res = lstat(dst_dir, &st); -+ if (res < 0) { -+ return -1; -+ } ++ if (ptr != path) { ++ dst_dirlen = (ptr - path); ++ dst_dir = pstrndup(p, path, dst_dirlen); + -+ if (!S_ISDIR(st.st_mode) && -+ !S_ISLNK(st.st_mode)) { -+ errno = EPERM; -+ return -1; -+ } ++ } else { ++ dst_dirlen = 1; ++ dst_dir = "/"; ++ } + -+ /* Allocate enough space for the temporary name: the length of the -+ * destination directory, a slash, 9 X's, 3 for the prefix, and 1 for the -+ * trailing NUL. -+ */ -+ tmpl_len = strlen(path) + 14; -+ tmpl = pcalloc(p, tmpl_len); -+ snprintf(tmpl, tmpl_len-1, "%s/dstXXXXXXXXX", dst_dir); ++ res = lstat(dst_dir, &st); ++ if (res < 0) { ++ return -1; ++ } + -+ /* Use mkdtemp(3) to create the temporary directory (in the same destination -+ * directory as the target path). -+ */ -+ tmpl_path = mkdtemp(tmpl); -+ if (tmpl_path == NULL) { -+ return -1; ++ if (!S_ISDIR(st.st_mode) && ++ !S_ISLNK(st.st_mode)) { ++ errno = EPERM; ++ return -1; ++ } ++ ++ /* Allocate enough space for the temporary name: the length of the ++ * destination directory, a slash, 9 X's, 3 for the prefix, and 1 for the ++ * trailing NUL. ++ */ ++ tmpl_len = strlen(dst_dir) + 14; ++ tmpl = pcalloc(p, tmpl_len); ++ snprintf(tmpl, tmpl_len-1, "%s/dstXXXXXXXXX", ++ dst_dirlen > 1 ? dst_dir : ""); ++ ++ /* Use mkdtemp(3) to create the temporary directory (in the same destination ++ * directory as the target path). ++ */ ++ tmpl_path = mkdtemp(tmpl); ++ if (tmpl_path == NULL) { ++ return -1; ++ } ++ ++ } else { ++ res = pr_fsio_mkdir(path, mode); ++ if (res < 0) { ++ return -1; ++ } ++ ++ tmpl_path = pstrdup(p, path); + } +#else + @@ -343,12 +326,9 @@ + } + + tmpl_path = pstrdup(p, path); -+ +#endif /* HAVE_MKDTEMP */ + + if (uid != (uid_t) -1) { -+ int xerrno; -+ + PRIVS_ROOT + res = pr_fsio_lchown(tmpl_path, uid, gid); + xerrno = errno; @@ -371,7 +351,6 @@ + + } else if (gid != (gid_t) -1) { + register unsigned int i; -+ int use_root_privs = TRUE, xerrno; + + /* Check if session.fsgid is in session.gids. If not, use root privs. */ + for (i = 0; i < session.gids->nelts; i++) { @@ -404,43 +383,59 @@ + } + } + -+#ifdef HAVE_MKDTEMP -+ /* Use chmod(2) to set the permission that we want. -+ * -+ * mkdtemp(3) creates a directory with 0700 perms; we are given the -+ * target mode (modulo the configured Umask). -+ */ -+ dir_umask = get_param_ptr(CURRENT_CONF, "DirUmask", FALSE); -+ if (dir_umask) { -+ mask = *dir_umask; ++ if (use_mkdtemp == TRUE) { ++ mode_t mask, *dir_umask; + -+ } else { -+ mask = (mode_t) 0022; -+ } ++ /* Use chmod(2) to set the permission that we want. ++ * ++ * mkdtemp(3) creates a directory with 0700 perms; we are given the ++ * target mode (modulo the configured Umask). ++ */ ++ dir_umask = get_param_ptr(CURRENT_CONF, "DirUmask", FALSE); ++ if (dir_umask) { ++ mask = *dir_umask; + -+ res = chmod(tmpl_path, mode & ~mask); -+ if (res < 0) { -+ int xerrno = errno; ++ } else { ++ mask = (mode_t) 0022; ++ } + -+ (void) rmdir(tmpl_path); ++ if (use_root_privs) { ++ PRIVS_ROOT ++ } + -+ errno = xerrno; -+ return -1; -+ } ++ res = chmod(tmpl_path, mode & ~mask); ++ xerrno = errno; + -+ /* Use rename(2) to move the temporary directory into place at the -+ * target path. -+ */ -+ res = rename(tmpl_path, path); -+ if (res < 0) { -+ int xerrno = errno; -+ -+ (void) rmdir(tmpl_path); ++ if (use_root_privs) { ++ PRIVS_RELINQUISH ++ } ++ ++ if (res < 0) { ++ pr_log_pri(PR_LOG_WARNING, "%schmod(%s) failed: %s", ++ use_root_privs ? "root " : "", tmpl_path, strerror(xerrno)); ++ ++ (void) rmdir(tmpl_path); ++ ++ errno = xerrno; ++ return -1; ++ } ++ ++ /* Use rename(2) to move the temporary directory into place at the ++ * target path. ++ */ ++ res = rename(tmpl_path, path); ++ if (res < 0) { ++ xerrno = errno; ++ ++ pr_log_pri(PR_LOG_WARNING, "renaming '%s' to '%s' failed: %s", tmpl_path, ++ path, strerror(xerrno)); ++ ++ (void) rmdir(tmpl_path); + -+ errno = xerrno; -+ return -1; ++ errno = xerrno; ++ return -1; ++ } + } -+#endif /* HAVE_MKDTEMP */ + + return 0; +} @@ -448,7 +443,7 @@ int pr_fsio_rmdir(const char *path) { int res; pr_fs_t *fs; -@@ -3357,6 +3527,33 @@ +@@ -3357,6 +3576,33 @@ int pr_fsio_fchown(pr_fh_t *fh, uid_t ui return res; } @@ -482,7 +477,7 @@ int pr_fsio_access(const char *path, int mode, uid_t uid, gid_t gid, array_header *suppl_gids) { pr_fs_t *fs; -@@ -4015,6 +4212,7 @@ +@@ -4015,6 +4261,7 @@ int init_fs(void) { root_fs->fchmod = sys_fchmod; root_fs->chown = sys_chown; root_fs->fchown = sys_fchown; @@ -490,7 +485,7 @@ root_fs->access = sys_access; root_fs->faccess = sys_faccess; root_fs->utimes = sys_utimes; -@@ -4096,6 +4294,12 @@ +@@ -4096,6 +4343,12 @@ static const char *get_fs_hooks_str(pool if (fs->chown) hooks = pstrcat(p, hooks, *hooks ? ", " : "", "chown(2)", NULL); @@ -503,3 +498,14 @@ if (fs->access) hooks = pstrcat(p, hooks, *hooks ? ", " : "", "access(2)", NULL); +--- src/Makefile.in ++++ src/Makefile.in +@@ -332,7 +332,7 @@ fsio.o: ../include/session.h ../include/ + fsio.o: ../include/throttle.h ../include/trace.h ../include/encode.h + fsio.o: ../include/compat.h ../include/proctitle.h ../include/pidfile.h + fsio.o: ../include/env.h ../include/pr-syslog.h ../include/memcache.h +-fsio.o: ../include/tpl.h ++fsio.o: ../include/tpl.h ../include/privs.h + ftpdctl.o: ../include/conf.h ../include/version.h ../config.h + ftpdctl.o: ../include/default_paths.h ../include/options.h ../include/pool.h + ftpdctl.o: ../include/str.h ../include/table.h ../include/proftpd.h diff --git a/proftpd-mod-vroot-0.9.2-bug3841.patch b/proftpd-mod-vroot-0.9.2-bug3841.patch new file mode 100644 index 0000000..0746371 --- /dev/null +++ b/proftpd-mod-vroot-0.9.2-bug3841.patch @@ -0,0 +1,101 @@ +From f2b7c3c6bc47ba547863a66d558dae7b9ed0ce63 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 13 Jan 2013 16:43:07 -0800 +Subject: [PATCH] Add use of the new pr_fsio_set_use_mkdtemp() API, to work + around issues seen with mod_vroot due to the fix for + Bug#3841. + +--- + mod_vroot.c | 35 ++++++++++++++++++++++++++++++++--- + 1 file changed, 32 insertions(+), 3 deletions(-) + +diff --git mod_vroot/mod_vroot.c mod_vroot/mod_vroot.c +index e31f11d..2fba410 100644 +--- contrib/mod_vroot.c ++++ contrib/mod_vroot.c +@@ -53,6 +53,8 @@ + static pool *vroot_dir_pool = NULL; + static pr_table_t *vroot_dirtab = NULL; + ++static int vroot_use_mkdtemp = FALSE; ++ + static unsigned int vroot_opts = 0; + #define VROOT_OPT_ALLOW_SYMLINKS 0x0001 + +@@ -777,6 +779,28 @@ + return res; + } + ++static int vroot_lchown(pr_fs_t *fs, const char *path, uid_t uid, gid_t gid) { ++ int res; ++ char vpath[PR_TUNABLE_PATH_MAX + 1]; ++ ++ if (session.curr_phase == LOG_CMD || ++ session.curr_phase == LOG_CMD_ERR || ++ (session.sf_flags & SF_ABORT) || ++ *vroot_base == '\0') { ++ /* NOTE: once stackable FS modules are supported, have this fall through ++ * to the next module in the stack. ++ */ ++ res = lchown(path, uid, gid); ++ return res; ++ } ++ ++ if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0) ++ return -1; ++ ++ res = lchown(vpath, uid, gid); ++ return res; ++} ++ + static int vroot_chroot(pr_fs_t *fs, const char *path) { + char *chroot_path = "/", *tmp = NULL; + config_rec *c; +@@ -1390,6 +1414,26 @@ + /* Command handlers + */ + ++MODRET vroot_pre_mkd(cmd_rec *cmd) { ++ if (vroot_engine == FALSE || ++ session.chroot_path == NULL) { ++ return PR_DECLINED(cmd); ++ } ++ ++ vroot_use_mkdtemp = pr_fsio_set_use_mkdtemp(FALSE); ++ return PR_DECLINED(cmd); ++} ++ ++MODRET vroot_post_mkd(cmd_rec *cmd) { ++ if (vroot_engine == FALSE || ++ session.chroot_path == NULL) { ++ return PR_DECLINED(cmd); ++ } ++ ++ pr_fsio_set_use_mkdtemp(vroot_use_mkdtemp); ++ return PR_DECLINED(cmd); ++} ++ + MODRET vroot_pre_pass(cmd_rec *cmd) { + pr_fs_t *fs = NULL; + unsigned char *use_vroot = NULL; +@@ -1433,6 +1477,7 @@ + fs->truncate = vroot_truncate; + fs->chmod = vroot_chmod; + fs->chown = vroot_chown; ++ fs->lchown = vroot_lchown; + fs->chdir = vroot_chdir; + fs->chroot = vroot_chroot; + fs->opendir = vroot_opendir; +@@ -1564,6 +1609,12 @@ + { PRE_CMD, C_PASS, G_NONE, vroot_pre_pass, FALSE, FALSE }, + { POST_CMD, C_PASS, G_NONE, vroot_post_pass, FALSE, FALSE }, + { POST_CMD_ERR, C_PASS, G_NONE, vroot_post_pass_err, FALSE, FALSE }, ++ { PRE_CMD, C_MKD, G_NONE, vroot_pre_mkd, FALSE, FALSE }, ++ { POST_CMD, C_MKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, ++ { POST_CMD_ERR, C_MKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, ++ { PRE_CMD, C_XMKD, G_NONE, vroot_pre_mkd, FALSE, FALSE }, ++ { POST_CMD, C_XMKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, ++ { POST_CMD_ERR, C_XMKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, + { 0, NULL } + }; + diff --git a/proftpd.spec b/proftpd.spec index 4384ebc..9c936e4 100644 --- a/proftpd.spec +++ b/proftpd.spec @@ -41,7 +41,7 @@ %define _hardened_build 1 #global prever rc3 -%global rpmrel 4 +%global rpmrel 5 Summary: Flexible, stable and highly-configurable FTP server Name: proftpd @@ -71,6 +71,7 @@ Patch23: proftpd-1.3.4a-bug3744.patch Patch24: proftpd-1.3.4a-bug3745.patch Patch25: proftpd-1.3.4a-bug3746.patch Patch26: proftpd-1.3.4b-bug3841.patch +Patch27: proftpd-mod-vroot-0.9.2-bug3841.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root Requires(preun): coreutils, findutils %if %{use_systemd} @@ -236,6 +237,7 @@ cp -p %{SOURCE1} proftpd.conf # Fix possible symlink race when applying UserOwner to newly created directory # http://bugs.proftpd.org/show_bug.cgi?id=3841 %patch26 +%patch27 # Avoid documentation name conflicts mv contrib/README contrib/README.contrib @@ -533,6 +535,9 @@ fi %{_mandir}/man1/ftpwho.1* %changelog +* Wed Jan 16 2013 Paul Howarth 1.3.4b-5 +- Update patch for CVE-2012-6095 to cover vroot cases + * Mon Jan 7 2013 Paul Howarth 1.3.4b-4 - Fix possible symlink race when applying UserOwner to newly created directory (CVE-2012-6095, #892715, http://bugs.proftpd.org/show_bug.cgi?id=3841)