crashpad/util/misc/paths_linux.cc
Mark Mentovai 4688351623 “Promote” test::Paths::Executable() to Paths::Executable()
This supports the “double handler” or “double handler with low
probability” models from https://crashpad.chromium.org/bug/143.

For crashpad_handler to be become its own client, it needs access to its
own executable path to pass to CrashpadClient::StartHandler(). This was
formerly available in the test-only test::Paths::Executable(). Bring
that function’s implementation to the non-test Paths::Executable() in
util/misc, and rename test::Paths to test::TestPaths to avoid future
confusion.

test::TestPaths must still be used to access TestDataRoot(), which does
not make any sense to non-test code.

test::TestPaths::Executable() is retained for use by tests, which most
likely prefer the fatal semantics of that function. Paths::Executable()
is not fatal because for the purposes of implementing the double
handler, a failure to locate the executable path (which may happen on
some systems in deeply-nested directory hierarchies) shouldn’t cause the
initial crashpad_handler to abort, even if it does prevent a second
crashpad_handler from being started.

Bug: crashpad:143
Test: crashpad_util_test Paths.*, crashpad_test_test TestPaths.*
Change-Id: I9f75bf61839ce51e33c9f7c0d7031cebead6a156
Reviewed-on: https://chromium-review.googlesource.com/466346
Reviewed-by: Scott Graham <scottmg@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
2017-04-03 18:58:01 +00:00

62 lines
2.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2016 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "util/misc/paths.h"
#include <limits.h>
#include <unistd.h>
#include <algorithm>
#include <string>
#include "base/logging.h"
namespace crashpad {
// static
bool Paths::Executable(base::FilePath* path) {
// Linux does not provide a straightforward way to size the buffer before
// calling readlink(). Normally, the st_size field returned by lstat() could
// be used, but this is usually zero for things in /proc.
//
// The /proc filesystem does not provide any way to read “exe” links for
// pathnames longer than a page. See linux-4.9.20/fs/proc/base.c
// do_proc_readlink(), which allocates a single page to receive the path
// string. Coincidentally, the page size and PATH_MAX are normally the same
// value, although neither is strictly a limit on the length of a pathname.
//
// On Android, the smaller of the page size and PATH_MAX actually does serve
// as an effective limit on the length of an executables pathname. See
// Android 7.1.1 bionic/linker/linker.cpp get_executable_path(), which aborts
// via __libc_fatal() if the “exe” link cant be read into a PATH_MAX-sized
// buffer.
std::string exe_path(std::max(getpagesize(), PATH_MAX),
std::string::value_type());
ssize_t exe_path_len =
readlink("/proc/self/exe", &exe_path[0], exe_path.size());
if (exe_path_len < 0) {
PLOG(ERROR) << "readlink";
return false;
} else if (static_cast<size_t>(exe_path_len) >= exe_path.size()) {
LOG(ERROR) << "readlink";
return false;
}
exe_path.resize(exe_path_len);
*path = base::FilePath(exe_path);
return true;
}
} // namespace crashpad