Date: Sun, 2 Feb 2003 18:37:38 +0100 From: Johan Karlsson <johan@freebsd.org> To: audit@freebsd.org, Sheldon Hearn <sheldonh@starjuice.net> Subject: realpath(3) improvement Message-ID: <20030202173738.GA759@numeri.campus.luth.se>
next in thread | raw e-mail | index | archive | help
--FL5UXtIhxfXey3p5 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi I intend to commit the attached patch to realpath(3) unless there are objections. Currently realpath(3) return an error if current directory is unreadable. k@numeri ~/realpathtes >ll total 8 drwxr-xr-x 3 k staff 512 Feb 2 17:52 ./ drwxr-xr-x 55 k staff 3584 Feb 2 17:44 ../ d-wx--x--x 3 k staff 512 Feb 2 16:29 realpathtest/ k@numeri ~/realpathtes >cd realpathtest/ k@numeri ~/realpathtes/realpathtest >/bin/realpath home realpath: .: Permission denied k@numeri ~/realpathtes/realpathtest > With the attached patch one get k@numeri ~/realpathtes/realpathtest >/home/builds/home/k/FreeBSD-src/current/src/bin/realpath/realpath /home /home k@numeri ~/realpathtes/realpathtest > The problem is in libc not in bin/realpath. The patch to correct this is from PR 12244. The attached patch also changes realpath(3) to use strlcpy instead of strncpy (submitted by imp@). Accordning to strncpy(3) it is preferable to use strlcpy when portablility isn't an issue. I would like to know if this is ok to commit as well. Please have a look at the attached patch and let me know if you find any problems with it. Take care /Johan K -- Johan Karlsson mailto:johan@FreeBSD.org --FL5UXtIhxfXey3p5 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="realpath.c.diff" Index: lib/libc/stdlib/realpath.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdlib/realpath.c,v retrieving revision 1.12 diff -u -r1.12 realpath.c --- lib/libc/stdlib/realpath.c 15 Jan 2003 21:22:55 -0000 1.12 +++ lib/libc/stdlib/realpath.c 2 Feb 2003 17:01:49 -0000 @@ -65,13 +65,19 @@ { struct stat sb; int fd, n, rootd, serrno; - char *p, *q, wbuf[PATH_MAX]; + char *p, *q, scwd[PATH_MAX], wbuf[PATH_MAX]; int symlinks = 0; - /* Save the starting point. */ + /* + * Save the starting point: + * First, try open()/fchdir() method and, if this fails, + * then try getcwd()/chdir(). + */ if ((fd = _open(".", O_RDONLY)) < 0) { - (void)strcpy(resolved, "."); - return (NULL); + if (getcwd(scwd, PATH_MAX) == 0) { + (void)strcpy(resolved, "."); + return (NULL); + } } /* @@ -82,8 +88,7 @@ * if it is a directory, then change to that directory. * get the current directory name and append the basename. */ - (void)strncpy(resolved, path, PATH_MAX - 1); - resolved[PATH_MAX - 1] = '\0'; + (void)strlcpy(resolved, path, PATH_MAX); loop: q = strrchr(resolved, '/'); if (q != NULL) { @@ -98,7 +103,7 @@ q = resolved; } if (chdir(q) < 0) - goto err1; + goto err; } else p = resolved; @@ -107,17 +112,17 @@ if (S_ISLNK(sb.st_mode)) { if (++symlinks > MAXSYMLINKS) { errno = ELOOP; - goto err1; + goto err; } n = readlink(p, resolved, PATH_MAX - 1); if (n < 0) - goto err1; + goto err; resolved[n] = '\0'; goto loop; } if (S_ISDIR(sb.st_mode)) { if (chdir(p) < 0) - goto err1; + goto err; p = ""; } } @@ -128,7 +133,7 @@ */ (void)strcpy(wbuf, p); if (getcwd(resolved, PATH_MAX) == 0) - goto err1; + goto err; /* * Join the two strings together, ensuring that the right thing @@ -142,26 +147,38 @@ if (*wbuf) { if (strlen(resolved) + strlen(wbuf) + rootd + 1 > PATH_MAX) { errno = ENAMETOOLONG; - goto err1; + goto err; } if (rootd == 0) (void)strcat(resolved, "/"); (void)strcat(resolved, wbuf); } - /* Go back to where we came from. */ - if (fchdir(fd) < 0) { - serrno = errno; - goto err2; + /* + * Go back to where we came from. If fd < 0, we are using the + * getcwd()/chdir() method; else, we are using open()/fchdir(). + */ + if (fd < 0) { + if (chdir(scwd) < 0) + return (NULL); + } else if (fchdir(fd) < 0) { + serrno = errno; + (void)_close(fd); + errno = serrno; + return (NULL); } /* It's okay if the close fails, what's an fd more or less? */ (void)_close(fd); return (resolved); -err1: serrno = errno; - (void)fchdir(fd); -err2: (void)_close(fd); +err: serrno = errno; + if (fd < 0) + (void)chdir(scwd); + else { + (void)fchdir(fd); + (void)_close(fd); + } errno = serrno; return (NULL); } --FL5UXtIhxfXey3p5-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030202173738.GA759>