mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-11 09:50:12 +00:00
Fix another unprotected instance of chdir() by extending the
fts_safe_changedir() function and using that instead for both of the chdir()s. Partially submitted by: Todd Miller <millert@OpenBSD.org>, bde
This commit is contained in:
parent
5b86eac4e5
commit
93a8551831
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=77599
@ -66,7 +66,7 @@ static void fts_padjust __P((FTS *, FTSENT *));
|
||||
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])))
|
||||
|
||||
@ -74,7 +74,6 @@ static int fts_safe_changedir __P((FTS *, FTSENT *, int));
|
||||
#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 */
|
||||
@ -278,8 +277,8 @@ FTSENT *
|
||||
fts_read(sp)
|
||||
register FTS *sp;
|
||||
{
|
||||
register FTSENT *p, *tmp;
|
||||
struct stat sb;
|
||||
register FTSENT *p, *tmp;
|
||||
register int instr;
|
||||
register char *t;
|
||||
int saved_errno;
|
||||
@ -355,7 +354,7 @@ fts_read(sp)
|
||||
* FTS_STOP or the fts_info field of the node.
|
||||
*/
|
||||
if (sp->fts_child != NULL) {
|
||||
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 != NULL;
|
||||
@ -454,22 +453,9 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
|
||||
}
|
||||
(void)_close(p->fts_symfd);
|
||||
} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
|
||||
!ISSET(FTS_NOCHDIR)) {
|
||||
if (chdir("..")) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
if (stat(".", &sb) == -1) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
} else {
|
||||
if (sb.st_ino != p->fts_parent->fts_ino ||
|
||||
sb.st_dev != p->fts_parent->fts_dev) {
|
||||
errno = ENOENT;
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
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);
|
||||
@ -656,7 +642,7 @@ fts_build(sp, type)
|
||||
*/
|
||||
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;
|
||||
@ -822,7 +808,8 @@ mem1: saved_errno = errno;
|
||||
*/
|
||||
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);
|
||||
@ -1085,10 +1072,11 @@ fts_maxarglen(argv)
|
||||
* 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;
|
||||
@ -1096,7 +1084,7 @@ fts_safe_changedir(sp, p, fd)
|
||||
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;
|
||||
|
@ -66,7 +66,7 @@ static void fts_padjust __P((FTS *, FTSENT *));
|
||||
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])))
|
||||
|
||||
@ -74,7 +74,6 @@ static int fts_safe_changedir __P((FTS *, FTSENT *, int));
|
||||
#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 */
|
||||
@ -278,8 +277,8 @@ FTSENT *
|
||||
fts_read(sp)
|
||||
register FTS *sp;
|
||||
{
|
||||
register FTSENT *p, *tmp;
|
||||
struct stat sb;
|
||||
register FTSENT *p, *tmp;
|
||||
register int instr;
|
||||
register char *t;
|
||||
int saved_errno;
|
||||
@ -355,7 +354,7 @@ fts_read(sp)
|
||||
* FTS_STOP or the fts_info field of the node.
|
||||
*/
|
||||
if (sp->fts_child != NULL) {
|
||||
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 != NULL;
|
||||
@ -454,22 +453,9 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
|
||||
}
|
||||
(void)_close(p->fts_symfd);
|
||||
} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
|
||||
!ISSET(FTS_NOCHDIR)) {
|
||||
if (chdir("..")) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
if (stat(".", &sb) == -1) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
} else {
|
||||
if (sb.st_ino != p->fts_parent->fts_ino ||
|
||||
sb.st_dev != p->fts_parent->fts_dev) {
|
||||
errno = ENOENT;
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
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);
|
||||
@ -656,7 +642,7 @@ fts_build(sp, type)
|
||||
*/
|
||||
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;
|
||||
@ -822,7 +808,8 @@ mem1: saved_errno = errno;
|
||||
*/
|
||||
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);
|
||||
@ -1085,10 +1072,11 @@ fts_maxarglen(argv)
|
||||
* 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;
|
||||
@ -1096,7 +1084,7 @@ fts_safe_changedir(sp, p, fd)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user