diff options
author | Dan McDonald <danmcd@joyent.com> | 2021-03-19 11:38:16 -0400 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2021-03-19 11:38:16 -0400 |
commit | a1ce764f98e19204e95ee78d66746478d10ea59c (patch) | |
tree | b210134e2dd21bde06dae97ddebffce293b3d39d /usr/src/uts/common/syscall/getcwd.c | |
parent | 1d684b54ff06842338ae5e57f8873ec9b9d24df3 (diff) | |
parent | fc1e9305ae86a296023d90240041e860548ba1bd (diff) | |
download | illumos-joyent-a1ce764f98e19204e95ee78d66746478d10ea59c.tar.gz |
[illumos-gate merge]
commit fc1e9305ae86a296023d90240041e860548ba1bd
13627 chown(2) mixes up chown() and fchown()
commit 173f6047c6877d03cbb55428e6ec95f07c9cbb83
13622 Memory leak in coretemp_create_sensor
commit 1b1c4b089b04ffa47f04c2923dc78c7fcafcf964
13575 loader: use display pixel density for font autoselection
commit 5fbc1fe0da7f34cf8155bf7624c94583cc98e47c
13526 cmd/availdevs always rebuilds
commit b2761fb273089c452ca34297d7ab4a1d1c1f1012
13599 ahci(7d) requires alias for HP AHCI SATA controller
commit 6edc7986d8c0034d072afac8b25477b983bf8f55
13586 getcwd() should accept a 0 length argument (fix mandoc)
commit d6f391ef39bc41c64e16ac5d7b10c1c8d5b1761e
4149 ksh head builtin does not like newlines
commit aa15372140b6b509a26742fd85fe78dd77d9a642
13586 getcwd() should accept a 0 length argument
commit f38f28fdbc29b3c5020295a6c6cb1ac52e949978
13574 loader.efi: efifb_gop_get_edid() is broken
commit 8781de92560745751daa24953330574a84de46e6
13632 smntemp doesn't need smntemp alias
commit 7eb8c88abb70697edf48045434d2c18bb82ad2e7
9620 getcwd() syscall has unbounded memory allocation
commit f9bbf53b825c087ef99dd9b3e51570ec68a51463
12558 Builtin command "printf" of ksh93 does not behave as specified
commit 4162633a7c5961f388fdc51bcecb3016104b359f
3782 ksh93's builtin chown fails with numeric ids
Diffstat (limited to 'usr/src/uts/common/syscall/getcwd.c')
-rw-r--r-- | usr/src/uts/common/syscall/getcwd.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/usr/src/uts/common/syscall/getcwd.c b/usr/src/uts/common/syscall/getcwd.c index b0c9b83d8b..4c83278314 100644 --- a/usr/src/uts/common/syscall/getcwd.c +++ b/usr/src/uts/common/syscall/getcwd.c @@ -22,10 +22,9 @@ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2021 OmniOS Community Edition (OmniOSce) Association. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/copyops.h> #include <sys/errno.h> #include <sys/kmem.h> @@ -44,31 +43,49 @@ getcwd(char *buf, size_t buflen) size_t kbuflen; /* + * If the buffer cannot accommodate one character and nul terminator, + * it is too small. + */ + if (buflen < 2) + return (set_errno(ERANGE)); + + /* * The user should be able to specify any size buffer, but we don't want * to arbitrarily allocate huge kernel buffers just because the user * requests it. So we'll start with MAXPATHLEN (which should hold any - * normal path), and only increase it if we fail with ERANGE. + * normal path), and only increase it if we fail with + * ERANGE / ENAMETOOLONG. + * + * To protect against unbounded memory usage, cap to kmem_max_cached. + * This is far bigger than the length of any practical path on the + * system, and avoids allocating memory from the kmem_oversized arena. */ kbuflen = MIN(buflen, MAXPATHLEN); - for (;;) { + while (kbuflen <= kmem_max_cached) { kbuf = kmem_alloc(kbuflen, KM_SLEEP); if (((err = dogetcwd(kbuf, kbuflen)) == 0) && - (copyout(kbuf, buf, strlen(kbuf) + 1) != 0)) + (copyout(kbuf, buf, strlen(kbuf) + 1) != 0)) { err = EFAULT; + } kmem_free(kbuf, kbuflen); - if (err == ENAMETOOLONG) { + /* + * dogetcwd() inconsistently returns ERANGE or ENAMETOOLONG + * depending on whether it calls dirtopath() and then whether + * the subsequent operations run out of space whilst + * evaluating a cached vnode path or otherwise. + */ + if (err == ENAMETOOLONG || err == ERANGE) { + /* For some reason, getcwd() uses ERANGE. */ + err = ERANGE; /* * If the user's buffer really was too small, give up. - * For some reason, getcwd() uses ERANGE for this case. */ - if (kbuflen == buflen) { - err = ERANGE; + if (kbuflen == buflen) break; - } kbuflen = MIN(kbuflen * 2, buflen); } else { break; |