kicad/thirdparty/sentry-native/external/crashpad/util/posix/drop_privileges.cc

94 lines
4.0 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 2014 The Crashpad Authors
//
// 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 <ostream>
#include "base/check_op.h"
#include "build/build_config.h"
namespace crashpad {
void DropPrivileges() {
gid_t gid = getgid();
uid_t uid = getuid();
#if BUILDFLAG(IS_APPLE)
// 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, or 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 older versions of macOS, 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.
//
// The problem exists in 10.9.5 xnu-2422.115.4/bsd/kern/kern_prot.c
// setreuid(). Based on its comments, it purports to set the svuid to the new
// euid when the old svuid doesnt match one of the new ruid and euid. This
// isnt how POSIX.1-2008 says it should behave, but it should work for this
// functions purposes. In reality, setreuid() doesnt even do this: it sets
// the svuid to the old euid, which does not drop privileges when the old euid
// is different from the desired euid. The workaround of calling setuid() or
// seteuid() before setreuid() works because it sets the euid so that by the
// time setreuid() runs, the old euid is actually the value that ought to be
// set as the svuid. setregid() is similar. This bug was reported as radar
// 18987552, fixed in 10.10.3 and security updates to 10.9.5 and 10.8.5.
//
// setuid() and setgid() alone will only set the saved IDs when running as
// root. When running a setuid non-root or setgid program, they do not alter
// the saved ID, and do not effect a permanent privilege drop.
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 BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
PCHECK(setresgid(gid, gid, gid) == 0) << "setresgid";
PCHECK(setresuid(uid, uid, uid) == 0) << "setresuid";
// Dont check to see if privileges can be regained on Linux, because on
// Linux, its not as simple as ensuring that this cant 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 shouldnt be
// necessary to perform any additional checking anyway.
//
// TODO(mark): Drop CAP_SETUID and CAP_SETGID if present and non-root?
#else
#error Port this function to your system.
#endif
}
} // namespace crashpad