diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-05-15 21:14:40 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-05-15 21:14:40 +0000 |
commit | 702c312cb2831ffe553edec88356e10045e393dc (patch) | |
tree | 4a2502c33d39858af039f48178358183b02c5015 /lib/libc/gen | |
parent | 58f7e38be96df800e8b4421a044937182e3679b5 (diff) |
Make path length variables size_t. This fixes the problem where
things like rm can't remove files with ridiculously long path names
that were created by some script kiddie trying in vain to exploit
something. Previously, the length was effectively constrained to
USHRT_MAX due to one of the internal structs. Also, nuke FTS_CHDIRROOT
since it never worked correctly and hasn't been documented for a
long time.
Diffstat (limited to 'lib/libc/gen')
-rw-r--r-- | lib/libc/gen/fts.3 | 6 | ||||
-rw-r--r-- | lib/libc/gen/fts.c | 120 |
2 files changed, 55 insertions, 71 deletions
diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3 index a050fb3d8b4..77ea5dbb355 100644 --- a/lib/libc/gen/fts.3 +++ b/lib/libc/gen/fts.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: fts.3,v 1.17 2000/12/24 00:30:47 aaron Exp $ +.\" $OpenBSD: fts.3,v 1.18 2001/05/15 21:14:38 millert Exp $ .\" .\" Copyright (c) 1989, 1991, 1993, 1994 .\" The Regents of the University of California. All rights reserved. @@ -115,9 +115,9 @@ typedef struct _ftsent { u_short fts_info; /* flags for FTSENT structure */ char *fts_accpath; /* access path */ char *fts_path; /* root path */ - u_short fts_pathlen; /* strlen(fts_path) */ + size_t fts_pathlen; /* strlen(fts_path) */ char *fts_name; /* file name */ - u_short fts_namelen; /* strlen(fts_name) */ + size_t fts_namelen; /* strlen(fts_name) */ short fts_level; /* depth (-1 to N) */ int fts_errno; /* file errno */ long fts_number; /* local numeric value */ diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index e28cf9bbd94..5d9c8aae5be 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fts.c,v 1.24 2000/08/24 17:04:12 deraadt Exp $ */ +/* $OpenBSD: fts.c,v 1.25 2001/05/15 21:14:39 millert Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; #else -static char rcsid[] = "$OpenBSD: fts.c,v 1.24 2000/08/24 17:04:12 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: fts.c,v 1.25 2001/05/15 21:14:39 millert Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -52,7 +52,7 @@ static char rcsid[] = "$OpenBSD: fts.c,v 1.24 2000/08/24 17:04:12 deraadt Exp $" #include <string.h> #include <unistd.h> -static FTSENT *fts_alloc __P((FTS *, char *, int)); +static FTSENT *fts_alloc __P((FTS *, char *, size_t)); static FTSENT *fts_build __P((FTS *, int)); static void fts_lfree __P((FTSENT *)); static void fts_load __P((FTS *, FTSENT *)); @@ -80,14 +80,14 @@ static int fts_safe_changedir __P((FTS *, FTSENT *, int)); FTS * fts_open(argv, options, compar) char * const *argv; - register int options; + int options; int (*compar) __P((const FTSENT **, const FTSENT **)); { - register FTS *sp; - register FTSENT *p, *root; - register int nitems; + FTS *sp; + FTSENT *p, *root; + int nitems; FTSENT *parent, *tmp; - int len; + size_t len; /* Options check. */ if (options & ~FTS_OPTIONMASK) { @@ -188,10 +188,10 @@ mem1: free(sp); static void fts_load(sp, p) FTS *sp; - register FTSENT *p; + FTSENT *p; { - register int len; - register char *cp; + size_t len; + char *cp; /* * Load the stream structure for the next traversal. Since we don't @@ -215,7 +215,7 @@ int fts_close(sp) FTS *sp; { - register FTSENT *freep, *p; + FTSENT *freep, *p; int saved_errno = 0; /* @@ -268,11 +268,11 @@ fts_close(sp) FTSENT * fts_read(sp) - register FTS *sp; + FTS *sp; { - register FTSENT *p, *tmp; - register int instr; - register char *t; + FTSENT *p, *tmp; + int instr; + char *t; int saved_errno; /* If finished or unrecoverable error, return NULL. */ @@ -373,16 +373,9 @@ next: tmp = p; * the root of the tree), and load the paths for the next root. */ if (p->fts_level == FTS_ROOTLEVEL) { - if ((sp->fts_options & FTS_CHDIRROOT)) { - if (chdir(p->fts_accpath)) { - SET(FTS_STOP); - return (NULL); - } - } else { - if (FCHDIR(sp, sp->fts_rfd)) { - SET(FTS_STOP); - return (NULL); - } + if (FCHDIR(sp, sp->fts_rfd)) { + SET(FTS_STOP); + return (NULL); } fts_load(sp, p); return (sp->fts_cur = p); @@ -437,16 +430,9 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent); * one directory. */ if (p->fts_level == FTS_ROOTLEVEL) { - if ((sp->fts_options & FTS_CHDIRROOT)) { - if (chdir(p->fts_accpath)) { - SET(FTS_STOP); - return (NULL); - } - } else { - if (FCHDIR(sp, sp->fts_rfd)) { - SET(FTS_STOP); - return (NULL); - } + if (FCHDIR(sp, sp->fts_rfd)) { + SET(FTS_STOP); + return (NULL); } } else if (p->fts_flags & FTS_SYMFOLLOW) { if (FCHDIR(sp, p->fts_symfd)) { @@ -491,10 +477,10 @@ fts_set(sp, p, instr) FTSENT * fts_children(sp, instr) - register FTS *sp; + FTS *sp; int instr; { - register FTSENT *p; + FTSENT *p; int fd; if (instr && instr != FTS_NAMEONLY) { @@ -573,17 +559,17 @@ fts_children(sp, instr) */ static FTSENT * fts_build(sp, type) - register FTS *sp; + FTS *sp; int type; { - register struct dirent *dp; - register FTSENT *p, *head; - register int nitems; + struct dirent *dp; + FTSENT *p, *head; FTSENT *cur, *tail; DIR *dirp; void *oldaddr; - int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno, - nostat, doadjust; + size_t len, maxlen; + int nitems, cderrno, descend, level, nlinks, oflag, nostat, doadjust; + int saved_errno; char *cp; /* Set current node pointer. */ @@ -685,7 +671,7 @@ fts_build(sp, type) if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) continue; - if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL) + if (!(p = fts_alloc(sp, dp->d_name, (size_t)dp->d_namlen))) goto mem1; if (dp->d_namlen >= maxlen) { /* include space for NUL */ oldaddr = sp->fts_path; @@ -714,12 +700,14 @@ mem1: saved_errno = errno; maxlen = sp->fts_pathlen - len; } - if (len + dp->d_namlen >= USHRT_MAX) { + p->fts_level = level; + p->fts_parent = sp->fts_cur; + p->fts_pathlen = len + dp->d_namlen; + if (p->fts_pathlen < len) { /* - * In an FTSENT, fts_pathlen is a u_short so it is - * possible to wraparound here. If we do, free up - * the current structure and the structures already - * allocated, then error out with ENAMETOOLONG. + * If we wrap, free up the current structure and + * the structures already allocated, then error + * out with ENAMETOOLONG. */ free(p); fts_lfree(head); @@ -729,9 +717,6 @@ mem1: saved_errno = errno; errno = ENAMETOOLONG; return (NULL); } - p->fts_level = level; - p->fts_parent = sp->fts_cur; - p->fts_pathlen = len + dp->d_namlen; #ifdef FTS_WHITEOUT if (dp->d_type == DT_WHT) @@ -831,12 +816,12 @@ mem1: saved_errno = errno; static u_short fts_stat(sp, p, follow) FTS *sp; - register FTSENT *p; + FTSENT *p; int follow; { - register FTSENT *t; - register dev_t dev; - register ino_t ino; + FTSENT *t; + dev_t dev; + ino_t ino; struct stat *sbp, sb; int saved_errno; @@ -915,9 +900,9 @@ static FTSENT * fts_sort(sp, head, nitems) FTS *sp; FTSENT *head; - register int nitems; + int nitems; { - register FTSENT **ap, *p; + FTSENT **ap, *p; /* * Construct an array of pointers to the structures and call qsort(3). @@ -953,9 +938,9 @@ static FTSENT * fts_alloc(sp, name, namelen) FTS *sp; char *name; - register int namelen; + size_t namelen; { - register FTSENT *p; + FTSENT *p; size_t len; /* @@ -990,9 +975,9 @@ fts_alloc(sp, name, namelen) static void fts_lfree(head) - register FTSENT *head; + FTSENT *head; { - register FTSENT *p; + FTSENT *p; /* Free a linked list of structures. */ while ((p = head)) { @@ -1014,19 +999,18 @@ fts_palloc(sp, more) { char *p; - sp->fts_pathlen += more + 256; /* - * Check for possible wraparound. In an FTS, fts_pathlen is - * a signed int but in an FTSENT it is an unsigned short. - * We limit fts_pathlen to USHRT_MAX to be safe in both cases. + * Check for possible wraparound. */ - if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { + more += 256; + if (sp->fts_pathlen + more < sp->fts_pathlen) { if (sp->fts_path) free(sp->fts_path); sp->fts_path = NULL; errno = ENAMETOOLONG; return (1); } + sp->fts_pathlen += more; p = realloc(sp->fts_path, sp->fts_pathlen); if (p == NULL) { if (sp->fts_path) |