Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/gen Fix problem reported by Kris Kennaway <kris@obs...



details:   https://anonhg.NetBSD.org/src/rev/99808faba19f
branches:  trunk
changeset: 510773:99808faba19f
user:      christos <christos%NetBSD.org@localhost>
date:      Tue Jun 05 17:05:11 2001 +0000

description:
Fix problem reported by Kris Kennaway <kris%obsecurity.org@localhost>; In
the default case fts(3) uses chdir("..") to ascend the tree. The
sequence of chdir's can be intercepted by a malicious user who
moves a subtree that fts is currently traversing to a higher level,
thus making fts operate outside it's original starting directory.

diffstat:

 lib/libc/gen/__fts13.c |  33 +++++++++++++++++++++++++++++----
 1 files changed, 29 insertions(+), 4 deletions(-)

diffs (54 lines):

diff -r 8fa99c1b59bb -r 99808faba19f lib/libc/gen/__fts13.c
--- a/lib/libc/gen/__fts13.c    Tue Jun 05 17:04:24 2001 +0000
+++ b/lib/libc/gen/__fts13.c    Tue Jun 05 17:05:11 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: __fts13.c,v 1.32 2000/11/05 20:05:29 christos Exp $    */
+/*     $NetBSD: __fts13.c,v 1.33 2001/06/05 17:05:11 christos Exp $    */
 
 /*-
  * Copyright (c) 1990, 1993, 1994
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)fts.c      8.6 (Berkeley) 8/14/94";
 #else
-__RCSID("$NetBSD: __fts13.c,v 1.32 2000/11/05 20:05:29 christos Exp $");
+__RCSID("$NetBSD: __fts13.c,v 1.33 2001/06/05 17:05:11 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -494,8 +494,33 @@
                        return (NULL);
                }
                (void)close(p->fts_symfd);
-       } else if (!(p->fts_flags & FTS_DONTCHDIR)) {
-               if (CHDIR(sp, "..")) {
+       } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+               !ISSET(FTS_NOCHDIR)) {
+               int fd;
+               struct STAT sb;
+
+               if ((fd = open("..", O_RDONLY)) == -1) {
+                       SET(FTS_STOP);
+                       return (NULL);
+               }
+               if (fstat(fd, &sb) == -1) {
+                       saved_errno = errno;
+                       (void)close(fd);
+                       errno = saved_errno;
+                       SET(FTS_STOP);
+                       return (NULL);
+               }
+               if (sb.st_ino != p->fts_parent->fts_ino ||
+                   sb.st_dev != p->fts_parent->fts_dev) {
+                       (void)close(fd);
+                       errno = ENOENT;
+                       SET(FTS_STOP);
+                       return (NULL);
+               }
+               if (fchdir(fd) == -1) {
+                       saved_errno = errno;
+                       (void)close(fd);
+                       errno = saved_errno;
                        SET(FTS_STOP);
                        return (NULL);
                }



Home | Main Index | Thread Index | Old Index