Skip to content

Commit

Permalink
fs/coredump: prevent "" / "." / ".." core path components
Browse files Browse the repository at this point in the history
Let %h and %e print empty values as "!", "." as "!" and
".." as "!.".

This prevents hostnames and comm values that are empty or consist of one
or two dots from changing the directory level at which the corefile will
be stored.

Consider the case where someone decides to sort coredumps by hostname
with a core pattern like "/cores/%h/core.%e.%p.%t" or so.  In this
case, hostnames "" and "." would cause the coredump to land directly in
/cores, which is not what the intent behind the core pattern is, and
".." would cause the coredump to land in /.

Yeah, there probably aren't many people who do that, but I still don't
want this edgecase to be kind of broken.

It seems very unlikely that this caused security issues anywhere, so I'm
not requesting a stable backport.

[[email protected]: tweak code comment]
Signed-off-by: Jann Horn <[email protected]>
Acked-by: Kees Cook <[email protected]>
Cc: Alexander Viro <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
thejh authored and torvalds committed Jan 21, 2016
1 parent caaee62 commit ac94b6e
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions fs/coredump.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ int cn_esc_printf(struct core_name *cn, const char *fmt, ...)
ret = cn_vprintf(cn, fmt, arg);
va_end(arg);

if (ret == 0) {
/*
* Ensure that this coredump name component can't cause the
* resulting corefile path to consist of a ".." or ".".
*/
if ((cn->used - cur == 1 && cn->corename[cur] == '.') ||
(cn->used - cur == 2 && cn->corename[cur] == '.'
&& cn->corename[cur+1] == '.'))
cn->corename[cur] = '!';

/*
* Empty names are fishy and could be used to create a "//" in a
* corefile name, causing the coredump to happen one directory
* level too high. Enforce that all components of the core
* pattern are at least one character long.
*/
if (cn->used == cur)
ret = cn_printf(cn, "!");
}

for (; cur < cn->used; ++cur) {
if (cn->corename[cur] == '/')
cn->corename[cur] = '!';
Expand Down

0 comments on commit ac94b6e

Please sign in to comment.