Bug 27922

Summary: FreeBSD-SA-01:40
Product: Base System Reporter: Eugene Grosbein <ports>
Component: binAssignee: Warner Losh <imp>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 3.5-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Eugene Grosbein 2001-06-07 05:00:16 UTC
A patch in FreeBSD Security Advisory FreeBSD-SA-01:40 does not apply to
3.5-STABLE. Here is a path from advisory adopted for RELENG_3 at the time of
advisory issue.

Fix: Here is a patch for 3.5-STABLE build 10 May 2001.
How to apply:

# cd /usr/src/lib/libc/gen
# patch </path/to/ftp.3S.patch
# cd ..
# make depend && make all install
# cd /usr/src/lib/libc_r
# make depend && make all install
# cd /usr/src/bin/chmod
# make depend && make all install
# cd /usr/src/bin/cp
# make depend && make all install
# cd /usr/src/bin/ls
# make depend && make all install
# cd /usr/src/bin/pax
# make depend && make all install
# cd /usr/src/bin/rm
# make depend && make all install
# cd /usr/src/usr.bin/chflags
# make depend && make all install
# cd /usr/src/usr.bin/du
# make depend && make all install
# cd /usr/src/usr.bin/find
# make depend && make all install
# cd /usr/src/libexec/ftpd
# make depend && make all install
# cd /usr/src/usr.sbin/chmod
# make depend && make all install
# cd /usr/src/usr.sbin/ckdist
# make depend && make all install
# cd /usr/src/usr.sbin/ctm
# make depend && make all install
# cd /usr/src/usr.sbin/mtree
# make depend && make all install
# cd /usr/src/usr.sbin/pkg_install
# make depend && make all install

Patch:
How-To-Repeat: 
	Exploit has been posted to security@freebsd.org mailing list.
Comment 1 Sergey N. Voronkov 2001-06-07 06:27:14 UTC
On Thu, Jun 07, 2001 at 11:52:13AM +0800, eugen@grosbein.pp.ru wrote:
> >Environment:
> FreeBSD 3.5-STABLE i386
> 
> >Description:
> 
> A patch in FreeBSD Security Advisory FreeBSD-SA-01:40 does not apply to
> 3.5-STABLE. Here is a path from advisory adopted for RELENG_3 at the time of
> advisory issue.
> 
> >How-To-Repeat:
> 
> 	Exploit has been posted to security@freebsd.org mailing list.
> 

RELENG_3 branch declared to support ONLY fixes of remote exploits (see
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=3320+0+archive/2001/
freebsd-announce/20010513.freebsd-announce).

Bye,

Serg N. Voronkov.
Comment 2 Eugene Grosbein 2001-06-07 06:47:33 UTC
> > A patch in FreeBSD Security Advisory FreeBSD-SA-01:40 does not apply to
> > 3.5-STABLE. Here is a path from advisory adopted for RELENG_3 at the time of
> > advisory issue.
> >
> > >How-To-Repeat:
> >
> >       Exploit has been posted to security@freebsd.org mailing list.
> >
> 
> RELENG_3 branch declared to support ONLY fixes of remote exploits (see
> http://docs.freebsd.org/cgi/getmsg.cgi?fetch=3320+0+archive/2001/
> freebsd-announce/20010513.freebsd-announce).

I know. It was said, if someone will supply patches for RELENG_3, they will
be consideted, so I corrected the patch.

Eugene Grosbein
Comment 3 Peter Pentchev freebsd_committer freebsd_triage 2001-06-07 07:03:54 UTC
Responsible Changed
From-To: freebsd-bugs->security-officer

Let's see if this works :)
Comment 4 Warner Losh freebsd_committer freebsd_triage 2001-06-07 07:15:54 UTC
Responsible Changed
From-To: security-officer->imp

Since someone went to the trouble of doing the patch, I'll try it with my 3.5 
tree and commit it if things compile after auditing the contents of the 
patch.
Comment 5 Eugene Grosbein 2001-06-13 10:35:06 UTC
> @@ -1086,7 +1087,7 @@
>              newfd = fd;
>              if (ISSET(FTS_NOCHDIR))
>                      return (0);
>      -       if (fd < 0 && (newfd = open(p->fts_accpath, O_RDONLY, 0)) < 0)
>      +       if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
>                      return (-1);
>              if (fstat(newfd, &sb)) {
>                      ret = -1;

I'm very sorry but this patch breaks libc_r on 3.5-STABLE.
The use of missing _open() is incorrect here, it needs to be changed back
to open(). With this one-line change the patch looks like this:

--- fts.c.orig  Sat Dec 25 15:29:45 1999
+++ fts.c       Wed Jun 13 16:17:28 2001
@@ -61,7 +61,7 @@
 static int      fts_palloc __P((FTS *, size_t));
 static FTSENT  *fts_sort __P((FTS *, FTSENT *, int));
 static u_short  fts_stat __P((FTS *, FTSENT *, int));
-static int      fts_safe_changedir __P((FTS *, FTSENT *, int));
+static int      fts_safe_changedir __P((FTS *, FTSENT *, int, char *));
 
 #define        ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' &&
!a[2])))
 
@@ -69,7 +69,6 @@
 #define        ISSET(opt)      (sp->fts_options & (opt))
 #define        SET(opt)        (sp->fts_options |= (opt))
 
-#define        CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path))
 #define        FCHDIR(sp, fd)  (!ISSET(FTS_NOCHDIR) && fchdir(fd))
 
 /* fts_build flags */
@@ -273,6 +272,7 @@
 fts_read(sp)
        register FTS *sp;
 {
+       struct stat sb;
        register FTSENT *p, *tmp;
        register int instr;
        register char *t;
@@ -349,7 +349,7 @@
                 * FTS_STOP or the fts_info field of the node.
                 */
                if (sp->fts_child) {
-                       if (fts_safe_changedir(sp, p, -1)) {
+                       if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
                                p->fts_errno = errno;
                                p->fts_flags |= FTS_DONTCHDIR;
                                for (p = sp->fts_child; p; p = p->fts_link)
@@ -446,11 +446,10 @@
                        return (NULL);
                }
                (void)close(p->fts_symfd);
-       } else if (!(p->fts_flags & FTS_DONTCHDIR)) {
-               if (CHDIR(sp, "..")) {
-                       SET(FTS_STOP);
-                       return (NULL);
-               }
+       } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+                  fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+               SET(FTS_STOP);
+               return (NULL);
        }
        p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
        return (sp->fts_cur = p);
@@ -637,7 +636,7 @@
         */
        cderrno = 0;
        if (nlinks || type == BREAD) {
-               if (fts_safe_changedir(sp, cur, dirfd(dirp))) {
+               if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
                        if (nlinks && type == BREAD)
                                cur->fts_errno = errno;
                        cur->fts_flags |= FTS_DONTCHDIR;
@@ -803,7 +802,8 @@
         */
        if (descend && (type == BCHILD || !nitems) &&
            (cur->fts_level == FTS_ROOTLEVEL ?
-           FCHDIR(sp, sp->fts_rfd) : CHDIR(sp, ".."))) {
+           FCHDIR(sp, sp->fts_rfd) :
+           fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
                cur->fts_info = FTS_ERR;
                SET(FTS_STOP);
                return (NULL);
@@ -1075,10 +1075,11 @@
  * Assumes p->fts_dev and p->fts_ino are filled in.
  */
 static int
-fts_safe_changedir(sp, p, fd)
+fts_safe_changedir(sp, p, fd, path)
        FTS *sp;
        FTSENT *p;
        int fd;
+       char *path;
 {
        int ret, oerrno, newfd;
        struct stat sb;
@@ -1086,7 +1087,7 @@
        newfd = fd;
        if (ISSET(FTS_NOCHDIR))
                return (0);
-       if (fd < 0 && (newfd = open(p->fts_accpath, O_RDONLY, 0)) < 0)
+       if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
                return (-1);
        if (fstat(newfd, &sb)) {
                ret = -1;

Eugene Grosbein
Comment 6 Max Khon freebsd_committer freebsd_triage 2001-10-11 13:08:57 UTC
State Changed
From-To: open->closed

fix committed to RELENG_3