mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
Add DropPrivileges().
DropPrivileges() is used in exception_port_tool, so that when it is installed as a setuid executable, it only uses elevated privileges to obtain a task port for its -p option, and then relinquishes those privileges. It is difficult to provide a test for this function, because it must be running setuid or setgid in order to do anything interesting. However, the function contains its own CHECKs to verify that it behaves properly. R=rsesek@chromium.org Review URL: https://codereview.chromium.org/727053002
This commit is contained in:
parent
de3c46c6b3
commit
49d7fdba9a
@ -34,6 +34,7 @@
|
||||
#include "util/mach/mach_extensions.h"
|
||||
#include "util/mach/symbolic_constants_mach.h"
|
||||
#include "util/mach/task_for_pid.h"
|
||||
#include "util/posix/drop_privileges.h"
|
||||
#include "util/stdlib/string_number_conversion.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -503,6 +504,10 @@ int ExceptionPortToolMain(int argc, char* argv[]) {
|
||||
alternate_task_owner.reset(options.alternate_task);
|
||||
}
|
||||
|
||||
// This tool may have been installed as a setuid binary so that TaskForPID()
|
||||
// could succeed. Drop any privileges now that they’re no longer necessary.
|
||||
DropPrivileges();
|
||||
|
||||
MachSendRightPool mach_send_right_pool;
|
||||
|
||||
// Show bootstrap services requested.
|
||||
|
73
util/posix/drop_privileges.cc
Normal file
73
util/posix/drop_privileges.cc
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2014 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 <unistd.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
void DropPrivileges() {
|
||||
gid_t gid = getgid();
|
||||
uid_t uid = getuid();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Based on the POSIX.1-2008 2013 edition documentation for setreuid() and
|
||||
// setregid(), setreuid() and setregid() alone should be sufficient to drop
|
||||
// privileges. The standard specifies that the saved ID should be set to the
|
||||
// effective ID whenever the real ID is not -1, and whenever the effective ID
|
||||
// is set not equal to the real ID. This code never specifies -1, so the
|
||||
// setreuid() and setregid() alone should work according to the standard.
|
||||
//
|
||||
// In practice, on Mac OS X, setuid() and setgid() (or seteuid() and
|
||||
// setegid()) must be called first, otherwise, setreuid() and setregid() do
|
||||
// not alter the saved IDs, leaving open the possibility for future privilege
|
||||
// escalation. This bug is filed as radar 18987552.
|
||||
gid_t egid = getegid();
|
||||
PCHECK(setgid(gid) == 0) << "setgid";
|
||||
PCHECK(setregid(gid, gid) == 0) << "setregid";
|
||||
|
||||
uid_t euid = geteuid();
|
||||
PCHECK(setuid(uid) == 0) << "setuid";
|
||||
PCHECK(setreuid(uid, uid) == 0) << "setreuid";
|
||||
|
||||
if (uid != 0) {
|
||||
// Because the setXid()+setreXid() interface to change IDs is fragile,
|
||||
// ensure that privileges cannot be regained. This can only be done if the
|
||||
// real user ID (and now the effective user ID as well) is not root, because
|
||||
// root always has permission to change identity.
|
||||
if (euid != uid) {
|
||||
CHECK_EQ(seteuid(euid), -1);
|
||||
}
|
||||
if (egid != gid) {
|
||||
CHECK_EQ(setegid(egid), -1);
|
||||
}
|
||||
}
|
||||
#elif defined(OS_LINUX)
|
||||
PCHECK(setresgid(gid, gid, gid) == 0) << "setresgid";
|
||||
PCHECK(setresuid(uid, uid, uid) == 0) << "setresuid";
|
||||
|
||||
// Don’t check to see if privileges can be regained on Linux, because on
|
||||
// Linux, it’s not as simple as ensuring that this can’t be done if non-root.
|
||||
// Instead, the ability to change user and group IDs are controlled by the
|
||||
// CAP_SETUID and CAP_SETGID capabilities, which may be granted to non-root
|
||||
// processes. Since the setresXid() interface is well-defined, it shouldn’t be
|
||||
// necessary to perform any additional checking anyway.
|
||||
#else
|
||||
#error Port this function to your system.
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
40
util/posix/drop_privileges.h
Normal file
40
util/posix/drop_privileges.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef CRASHPAD_UTIL_POSIX_DROP_PRIVILEGES_H_
|
||||
#define CRASHPAD_UTIL_POSIX_DROP_PRIVILEGES_H_
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief Permanently drops privileges conferred by being a setuid or setgid
|
||||
//! executable.
|
||||
//!
|
||||
//! The effective user ID and saved set-user ID are set to the real user ID,
|
||||
//! negating any effects of being a setuid executable. The effective group ID
|
||||
//! and saved set-group ID are set to the real group ID, negating any effects of
|
||||
//! being a setgid executable. Because the saved set-user ID and saved set-group
|
||||
//! ID are reset, there is no way to restore the prior privileges, and the drop
|
||||
//! is permanent.
|
||||
//!
|
||||
//! This function drops privileges correctly when running setuid root and in
|
||||
//! other circumstances, including when running setuid non-root. If the program
|
||||
//! is not a setuid or setgid executable, this function has no effect.
|
||||
//!
|
||||
//! No changes are made to the supplementary group list, which is normally not
|
||||
//! altered for setuid or setgid executables.
|
||||
void DropPrivileges();
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_UTIL_POSIX_DROP_PRIVILEGES_H_
|
@ -84,6 +84,8 @@
|
||||
'numeric/in_range_cast.h',
|
||||
'numeric/int128.h',
|
||||
'numeric/safe_assignment.h',
|
||||
'posix/drop_privileges.cc',
|
||||
'posix/drop_privileges.h',
|
||||
'posix/process_info.h',
|
||||
'posix/process_info_mac.cc',
|
||||
'posix/symbolic_constants_posix.cc',
|
||||
|
Loading…
x
Reference in New Issue
Block a user