summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbeck <beck@openbsd.org>2019-05-30 12:58:20 +0000
committerbeck <beck@openbsd.org>2019-05-30 12:58:20 +0000
commit0cdadd3f5b3fb589565215b75e8da7f43f83bd6e (patch)
tree1bf848d66a16bc2c64f1fe94810282f6a55c022b
parentNo longer need to reduce line number by one. (diff)
downloadwireguard-openbsd-0cdadd3f5b3fb589565215b75e8da7f43f83bd6e.tar.xz
wireguard-openbsd-0cdadd3f5b3fb589565215b75e8da7f43f83bd6e.zip
Correct call to vfs_getcwd_common from within __realpath
I borrowed an example usage from __getcwd poorly to begin with and then there was some other strangeness in there. diagnosed with deraadt. ok deraadt@
-rw-r--r--sys/kern/vfs_syscalls.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 5b649af01d7..379e0041881 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.315 2019/05/13 22:55:27 beck Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.316 2019/05/30 12:58:20 beck Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -875,16 +875,13 @@ sys___realpath(struct proc *p, void *v, register_t *retval)
syscallarg(char *) resolved;
} */ *uap = v;
char *pathname;
- char *cwdbuf;
char *rpbuf;
struct nameidata nd;
size_t pathlen;
- int cwdlen = MAXPATHLEN * 4;
int error = 0;
pathname = pool_get(&namei_pool, PR_WAITOK);
rpbuf = pool_get(&namei_pool, PR_WAITOK);
- cwdbuf = malloc(cwdlen, M_TEMP, M_WAITOK);
if ((error = copyinstr(SCARG(uap, pathname), pathname, MAXPATHLEN,
&pathlen)))
@@ -898,26 +895,30 @@ sys___realpath(struct proc *p, void *v, register_t *retval)
/* Get cwd for relative path if needed, prepend to rpbuf */
rpbuf[0] = '\0';
if (pathname[0] != '/') {
- char *path, *bp, *bend;
- int lenused;
+ int cwdlen = MAXPATHLEN * 4; /* for vfs_getcwd_common */
+ char *cwdbuf, *bp;
- bp = &cwdbuf[cwdlen];
- bend = bp;
- *(--bp) = '\0';
+ cwdbuf = malloc(cwdlen, M_TEMP, M_WAITOK);
- error = vfs_getcwd_common(p->p_fd->fd_cdir, NULL, &bp, path,
+ /* vfs_getcwd_common fills this in backwards */
+ bp = &cwdbuf[cwdlen - 1];
+ *bp = '\0';
+
+ error = vfs_getcwd_common(p->p_fd->fd_cdir, NULL, &bp, cwdbuf,
cwdlen/2, GETCWD_CHECK_ACCESS, p);
- if (error)
+ if (error) {
+ free(cwdbuf, M_TEMP, cwdlen);
goto end;
-
- lenused = bend - bp;
- *retval = lenused;
+ }
if (strlcpy(rpbuf, bp, MAXPATHLEN) >= MAXPATHLEN) {
+ free(cwdbuf, M_TEMP, cwdlen);
error = ENAMETOOLONG;
goto end;
}
+
+ free(cwdbuf, M_TEMP, cwdlen);
}
if (pathlen == 2 && pathname[0] == '/')
@@ -952,7 +953,6 @@ sys___realpath(struct proc *p, void *v, register_t *retval)
end:
pool_put(&namei_pool, rpbuf);
pool_put(&namei_pool, pathname);
- free(cwdbuf, M_TEMP, cwdlen);
return (error);
}