static bool drop_privileges(const char *user_name)
{
- struct passwd *user_info = getpwnam(user_name);
- if (!user_info) {
- _E("getpwnam() error: %m");
+ bool result = false;
+
+ size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (buflen == (size_t)-1)
+ buflen = 16384; // based on documentation
+
+ char *buf = malloc(buflen);
+ if (buf == NULL) {
+ _E("Can not allocate memory for passwd record: %m");
return false;
}
+ struct passwd user_info, *pwresult;
+ int s = getpwnam_r(user_name, &user_info, buf, buflen, &pwresult);
+
+ if (pwresult == NULL) {
+ if (s == 0)
+ _E("User %s not found", user_name);
+ else
+ _E("Error while getting user passwd record: %m");
+ goto exit;
+ }
+
if (!set_caps(CAP_PERMITTED))
- return false;
+ goto exit;
/*
* setuid() clears capabilities, so we need to set PR_SET_KEEPCAPS and
*/
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
_E("prctl(PR_SET_KEEPCAPS) error: %m");
- return false;
+ goto exit;
}
- if (!set_groups(user_name, user_info->pw_gid))
- return false;
+ if (!set_groups(user_name, user_info.pw_gid))
+ goto exit;
- if (setuid(user_info->pw_uid) == -1) {
+ if (setuid(user_info.pw_uid) == -1) {
_E("setuid() error: %m\n");
- return false;
+ goto exit;
}
if (!set_caps(CAP_EFFECTIVE))
- return false;
+ goto exit;
if (!set_caps(CAP_INHERITABLE))
- return false;
+ goto exit;
- return true;
+ result = true;
+exit:
+ free(buf);
+ return result;
}
int main(int argc, char *argv[])