summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorderaadt <>2019-05-30 13:22:48 +0000
committerderaadt <>2019-05-30 13:22:48 +0000
commitc6d26d2db7ee608499714dc433ddb9978db53cef (patch)
tree3999b27d48d4f50986817fe91828169f744596f9 /src
parent611703507e5a4b9de58cf05b58dbc23925de8d2d (diff)
downloadopenbsd-c6d26d2db7ee608499714dc433ddb9978db53cef.tar.gz
openbsd-c6d26d2db7ee608499714dc433ddb9978db53cef.tar.bz2
openbsd-c6d26d2db7ee608499714dc433ddb9978db53cef.zip
__realpath(2) appears to have improved, so re-enable the code that
checks userland-parsing vs kernel parsing, we are hoping to spot another bug..
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/realpath.c139
1 files changed, 136 insertions, 3 deletions
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
index dc8aa9af20..8f600741a1 100644
--- a/src/lib/libc/stdlib/realpath.c
+++ b/src/lib/libc/stdlib/realpath.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: realpath.c,v 1.24 2019/05/29 11:54:49 deraadt Exp $ */ 1/* $OpenBSD: realpath.c,v 1.25 2019/05/30 13:22:48 deraadt Exp $ */
2/* 2/*
3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> 3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
4 * 4 *
@@ -32,6 +32,8 @@
32#include <string.h> 32#include <string.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <limits.h> 34#include <limits.h>
35#include <syslog.h>
36#include <stdarg.h>
35 37
36/* A slightly modified copy of this file exists in libexec/ld.so */ 38/* A slightly modified copy of this file exists in libexec/ld.so */
37 39
@@ -42,8 +44,8 @@
42 * components. Returns (resolved) on success, or (NULL) on failure, 44 * components. Returns (resolved) on success, or (NULL) on failure,
43 * in which case the path which caused trouble is left in (resolved). 45 * in which case the path which caused trouble is left in (resolved).
44 */ 46 */
45char * 47static char *
46realpath(const char *path, char *resolved) 48urealpath(const char *path, char *resolved)
47{ 49{
48 const char *p; 50 const char *p;
49 char *q; 51 char *q;
@@ -51,6 +53,7 @@ realpath(const char *path, char *resolved)
51 unsigned symlinks; 53 unsigned symlinks;
52 int serrno, mem_allocated; 54 int serrno, mem_allocated;
53 ssize_t slen; 55 ssize_t slen;
56 int trailingslash = 0;
54 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; 57 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
55 58
56 if (path == NULL) { 59 if (path == NULL) {
@@ -231,3 +234,133 @@ err:
231 free(resolved); 234 free(resolved);
232 return (NULL); 235 return (NULL);
233} 236}
237
238/*
239 * Copyright (c) 2019 Bob Beck <beck@openbsd.org>
240 *
241 * Permission to use, copy, modify, and/or distribute this software for any
242 * purpose with or without fee is hereby granted, provided that the above
243 * copyright notice and this permission notice appear in all copies.
244 *
245 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
246 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
247 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
248 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
249 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
250 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
251 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
252 */
253
254int __realpath(const char *pathname, char *resolved);
255PROTO_NORMAL(__realpath);
256
257/*
258 * wrapper for kernel __realpath
259 */
260
261char *
262realpath(const char *path, char *resolved)
263{
264 char pbuf[PATH_MAX], rbuf[PATH_MAX], expected[PATH_MAX];
265 struct syslog_data sdata = SYSLOG_DATA_INIT;
266 int usererrno = 0, kernelerrno = 0, trailingslash = 0, save_errno;
267 int kernelonly = (getenv("USE_KERNEL_REALPATH") != NULL);
268 ssize_t i;
269
270 rbuf[0] = pbuf[0] = expected[0] = '\0';
271
272 if (!kernelonly) {
273 memset(expected, 0, sizeof(expected));
274 if (urealpath(path, expected) == NULL) {
275 usererrno = errno;
276 expected[0] = '\0';
277 }
278 }
279
280 if (path == NULL) {
281 kernelerrno = EINVAL;
282 goto out;
283 }
284 if (path[0] == '\0') {
285 kernelerrno = ENOENT;
286 goto out;
287 }
288 if (strlcat(pbuf, path, sizeof(pbuf)) >= sizeof(pbuf)) {
289 kernelerrno = ENAMETOOLONG;
290 goto out;
291 }
292
293 if (pbuf[strlen(pbuf) - 1] == '/')
294 trailingslash = 1;
295
296 if (__realpath(pbuf, rbuf) == -1)
297 kernelerrno = errno;
298
299 /*
300 * XXX XXX XXX
301 *
302 * The old userland implementation strips trailing slashes.
303 * According to Dr. POSIX, realpathing "/bsd" should be fine,
304 * realpathing "/bsd/" should return ENOTDIR.
305 *
306 * Similar, but *different* to the above, The old userland
307 * implementation allows for realpathing "/nonexistent" but
308 * not "/nonexistent/", Both those should return ENOENT
309 * according to POSIX.
310 *
311 * This hack should go away once we decide to match POSIX.
312 * which we should as soon as is convenient.
313 */
314 if (kernelerrno == ENOTDIR) {
315 /* Try again without the trailing slash. */
316 kernelerrno = 0;
317 for (i = strlen(pbuf); i > 1 && pbuf[i - 1] == '/'; i--)
318 pbuf[i - 1] = '\0';
319 rbuf[0] = '\0';
320 if (__realpath(pbuf, rbuf) == -1)
321 kernelerrno = errno;
322 }
323
324out:
325 if (!kernelonly) {
326 /* syslog if kernel and userland are different */
327 save_errno = errno;
328 if (strcmp(rbuf, expected) != 0 || (usererrno == 0 &&
329 kernelerrno != 0))
330 syslog_r(LOG_CRIT | LOG_CONS, &sdata,
331 "realpath '%s' -> '%s' errno %d, "
332 "expected '%s' errno %d", path, rbuf,
333 kernelerrno, expected, usererrno);
334 errno = save_errno;
335
336 /* use userland result */
337 if (usererrno) {
338 errno = usererrno;
339 return NULL;
340 }
341 else
342 errno = 0;
343 if (resolved == NULL)
344 resolved = strdup(expected);
345 else if (strlcpy(resolved, expected, PATH_MAX) >= PATH_MAX) {
346 errno = ENAMETOOLONG;
347 return NULL;
348 }
349
350 } else {
351 /* use kernel result */
352 if (kernelerrno) {
353 errno = kernelerrno;
354 return NULL;
355 }
356 else
357 errno = 0;
358 if (resolved == NULL)
359 resolved = strdup(rbuf);
360 else if (strlcpy(resolved, rbuf, PATH_MAX) >= PATH_MAX) {
361 errno = ENAMETOOLONG;
362 return NULL;
363 }
364 }
365 return (resolved);
366}