-
Notifications
You must be signed in to change notification settings - Fork 387
Validate untrusted user input #7807
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate untrusted user input #7807
Conversation
9c04e7c
to
6afa9c0
Compare
6afa9c0
to
b54f37a
Compare
ced98df
to
f3fd668
Compare
I'm not sure we need the last commit. I'm trying to say that neither fixed boundary (100kb) nor a boundary depending on ARG_MAX actually fix the problem which's being reported. So maybe it would be better to say that we don't run on systems with buggy |
f3fd668
to
8a3e609
Compare
93974a6
to
303b38c
Compare
303b38c
to
91e2076
Compare
getenv() return values cannot be trusted, because an attacker might set them. For instance, we shouldn't expect, that getenv() returns a value of some sane size. Another problem is that getenv() returns a pointer to one of `char **environ` members, which might change upon next setenv(). Introduce a wrapper, getenv_safe(), which returns the value only when it fits in a buffer of a specified size, and copies the value onto the buffer. Use this wrapper everywhere in our code. Below's a slightly decorated output of `grep -rwn getenv ./src --include *.c --include *.h --include *.cc --include *.cpp --include *.hpp --exclude *.lua.c` as of 2022-10-14. `-` marks invalid occurences (comments, for example), `*` marks the places that are already guarded before this patch, `X` mars the places guarded in this patch, and `^` marks places fixed in the next commit: NO_WRAP ``` * ./src/lib/core/coio_file.c:509: const char *tmpdir = getenv("TMPDIR"); X ./src/lib/core/errinj.c:75: const char *env_value = getenv(inj->name); - ./src/proc_title.c:202: * that might try to hang onto a getenv() result.) - ./src/proc_title.c:241: * is mandatory to flush internal libc caches on getenv/setenv X ./src/systemd.c:54: sd_unix_path = getenv("NOTIFY_SOCKET"); * ./src/box/module_cache.c:300: const char *tmpdir = getenv("TMPDIR"); X ./src/box/sql/os_unix.c:1441: azDirs[0] = getenv("SQL_TMPDIR"); X ./src/box/sql/os_unix.c:1446: azDirs[1] = getenv("TMPDIR"); * ./src/box/lua/console.c:394: const char *envvar = getenv("TT_CONSOLE_HIDE_SHOW_PROMPT"); ^ ./src/box/lua/console.lua:771: local home_dir = os.getenv('HOME') ^ ./src/box/lua/load_cfg.lua:1007: local raw_value = os.getenv(env_var_name) X ./src/lua/init.c:575: const char *path = getenv(envname); X ./src/lua/init.c:592: const char *home = getenv("HOME"); * ./src/find_path.c:77: snprintf(buf, sizeof(buf) - 1, "%s", getenv("_")); ``` NO_WRAP Part-of tarantool#7797 NO_DOC=security
Closes tarantool#7797 NO_DOC=security fix NO_TEST=security fix
91e2076
to
904b754
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In reflection of several compromises we agreed upon, the patchset looks okay for me.
Please backport to 2.10 and 1.10 as well |
Why 1.10? We backport fixes needed for the security certification only to 2.10 AFAIK. |
I thought we backport security fixes everywhere where bugfixes go. This is not only for certification, this is a real problem, which's getting fixed. But ok, up to you. |
To the best of my knowledge, we don't backport all fixes to 1.10 - only those that were specifically requested by our customers. |
I see, thanks. |
getenv() is bad: it returns a pointer to the environment, which might be changed by a following call to setenv(), making the value pointed to longer and leading to buffer overflows. See tarantool/tarantool#7807
getenv() is bad: it returns a pointer to the environment, which might be changed by a following call to setenv(), making the value pointed to longer and leading to buffer overflows. See tarantool/tarantool#7807
As seen in error reports from TNT-601,
getopt_long
,getopt
andrealpath
are subject to internal buffer overflows (at least they used to be some time ago).The suggestion is to either not use them, or provide them with correct input.
Speaking of
realpath
, we have 2 places that use it:Both these places provide a valid input buffer of size PATH_MAX, which should be fine: https://stackoverflow.com/questions/4109638/what-is-the-safe-alternative-to-realpath
Speaking of getopt:
Some googling reveals that one has to limit
argc
and all of theargv[i]
lengths to some "sane" value. What value is considered sane remains unknown. After some discussion in this PR (see below), it was decided to not try and patch getopt usage, since the only buggy getopt implementation known belongs to Solaris 2.5 from 1997.The problem with
getenv
is of other nature: it might return string of arbitrary length and content, which can't be trusted. The relevant CWE (not CVE) is CWE-807 and CWE-20.Here are our
getenv
usages:Most of them are already treated correctly (that is, getenv output is either passed to snprintf or
strcmp
-ed to a static fixed size string). The ones, that weren't treated correctly are fixed in this patchset, including the ones insrc/lua/*
andsrc/box/lua*
.Please note, that TNT-601 also reports some findings in
extra/*
folder. There areextra/lemon.c
,extra/bin2c.c
andextra/txt2c.c
. AFAICS these are all our building utilities and we are not concerned with their security. Please, correct me if I'm wrong.Closes #7797