codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / util / capability.cpp
blob19374ec382055fbdd0422285a538a45fb35d0d7a
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #if !defined(SKIP_USER_CHANGE)
19 #include "hphp/util/capability.h"
20 #include "hphp/util/logger.h"
21 #include <folly/String.h>
22 #include <linux/types.h>
23 #include <sys/capability.h>
24 #include <sys/prctl.h>
25 #include <sys/types.h>
26 #include <pwd.h>
27 #include <grp.h>
29 namespace HPHP {
30 ///////////////////////////////////////////////////////////////////////////////
32 static bool setInitialCapabilities() {
33 cap_t cap_d = cap_init();
34 if (cap_d != nullptr) {
35 cap_value_t cap_list[] = {CAP_NET_BIND_SERVICE, CAP_SYS_RESOURCE,
36 CAP_SETUID, CAP_SETGID, CAP_SYS_NICE};
37 cap_clear(cap_d);
39 if (cap_set_flag(cap_d, CAP_PERMITTED, 5, cap_list, CAP_SET) < 0 ||
40 cap_set_flag(cap_d, CAP_EFFECTIVE, 5, cap_list, CAP_SET) < 0) {
41 Logger::Error("cap_set_flag failed");
42 return false;
45 if (cap_set_proc(cap_d) == -1) {
46 Logger::Error("cap_set_proc failed");
47 return false;
50 if (cap_free(cap_d) == -1) {
51 Logger::Error("cap_free failed");
52 return false;
55 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
56 Logger::Error("prctl(PR_SET_KEEPCAPS) failed");
57 return false;
59 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
60 return true;
62 return false;
65 static bool setMinimalCapabilities() {
66 cap_t cap_d = cap_init();
68 if (cap_d != nullptr) {
69 cap_value_t cap_list[] = {CAP_NET_BIND_SERVICE, CAP_SYS_RESOURCE,
70 CAP_SYS_NICE};
72 cap_clear(cap_d);
74 if (cap_set_flag(cap_d, CAP_PERMITTED, 3, cap_list, CAP_SET) < 0 ||
75 cap_set_flag(cap_d, CAP_EFFECTIVE, 3, cap_list, CAP_SET) < 0) {
76 Logger::Error("cap_set_flag failed");
77 return false;
80 if (cap_set_proc(cap_d) == -1) {
81 Logger::Error("cap_set_proc failed");
82 return false;
85 if (cap_free(cap_d) == -1) {
86 Logger::Error("cap_free failed");
87 return false;
90 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
91 return true;
93 return false;
96 bool Capability::ChangeUnixUser(uid_t uid) {
97 if (setInitialCapabilities()) {
98 struct passwd *pw;
100 if ((pw = getpwuid(uid)) == nullptr) {
101 Logger::Error("unable to getpwuid(%d): %s", uid,
102 folly::errnoStr(errno).c_str());
103 return false;
106 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
107 Logger::Error("unable to drop supplementary group privs: %s",
108 folly::errnoStr(errno).c_str());
109 return false;
112 if (pw->pw_gid == 0 || setgid(pw->pw_gid) < 0) {
113 Logger::Error("unable to drop gid privs: %s",
114 folly::errnoStr(errno).c_str());
115 return false;
118 if (uid == 0 || setuid(uid) < 0) {
119 Logger::Error("unable to drop uid privs: %s",
120 folly::errnoStr(errno).c_str());
121 return false;
124 if (!setMinimalCapabilities()) {
125 Logger::Error("unable to set minimal server capabiltiies");
126 return false;
128 return true;
130 return false;
133 bool Capability::ChangeUnixUser(const std::string &username) {
134 if (!username.empty()) {
135 struct passwd *pw = getpwnam(username.c_str());
136 if (pw && pw->pw_uid) {
137 return ChangeUnixUser(pw->pw_uid);
140 return false;
143 bool Capability::SetDumpable() {
144 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
145 Logger::Error("Unable to make process dumpable: %s",
146 folly::errnoStr(errno).c_str());
149 return true;
152 ///////////////////////////////////////////////////////////////////////////////
155 #endif