diff options
Diffstat (limited to 'guts/getcwd.c')
-rw-r--r-- | guts/getcwd.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/guts/getcwd.c b/guts/getcwd.c index d8f4d36..f6a8521 100644 --- a/guts/getcwd.c +++ b/guts/getcwd.c @@ -3,7 +3,7 @@ * wrap_getcwd(char *buf, size_t size) { * char * rc = NULL; */ - pseudo_debug(2, "wrap_getcwd: %p, %lu\n", + pseudo_debug(3, "wrap_getcwd: %p, %lu\n", (void *) buf, (unsigned long) size); if (!pseudo_cwd) { pseudo_diag("Asked for CWD, but don't have it!\n"); @@ -12,15 +12,26 @@ } /* emulate Linux semantics in case of non-Linux systems. */ if (!buf) { - /* if we don't have one, something's very wrong... */ + /* if we don't have a cwd, something's very wrong... */ if (!size) { - size = pseudo_cwd_len; + size = pseudo_cwd_len + 1; + if (pseudo_chroot_len && size >= pseudo_chroot_len && + !memcmp(pseudo_cwd, pseudo_chroot, pseudo_chroot_len)) { + size -= pseudo_chroot_len; + /* if cwd is precisely the same as chroot, we + * actually want a /, not an empty string + */ + if (size < 2) + size = 2; + } } if (size) { buf = malloc(size); } else { - pseudo_diag("can't figure out CWD: length %ld\n", - (unsigned long) pseudo_cwd_len); + pseudo_diag("can't figure out CWD: length %ld + 1 - %ld => %ld\n", + (unsigned long) pseudo_cwd_len, + (unsigned long) pseudo_chroot_len, + (unsigned long) size); } if (!buf) { pseudo_diag("couldn't allocate requested CWD buffer - need %ld byes\n", @@ -29,8 +40,21 @@ return NULL; } } + if (pseudo_cwd_len - (pseudo_cwd_rel - pseudo_cwd) >= size) { + pseudo_diag("only %ld bytes available, need %ld (%ld + 1 - %ld)\n", + (unsigned long) size, + (unsigned long) pseudo_cwd_len + 1 - pseudo_chroot_len, + (unsigned long) pseudo_cwd_len, + (unsigned long) pseudo_chroot_len); + errno = ENAMETOOLONG; + return NULL; + } rc = buf; - memcpy(buf, pseudo_cwd, pseudo_cwd_len + 1); + pseudo_debug(3, "getcwd: copying %d (%d + 1 - %d) characters from <%s>.\n", + (int) ((pseudo_cwd_len + 1) - pseudo_chroot_len), + pseudo_cwd_len, pseudo_chroot_len, + pseudo_cwd_rel); + memcpy(buf, pseudo_cwd_rel, (pseudo_cwd_len + 1) - (pseudo_cwd_rel - pseudo_cwd)); if (!*buf) { strcpy(buf, "/"); } |