mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge branch 'bug11946'
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
o Minor bugfixes (sandbox):
|
||||
|
||||
- Handle failures in getpwnam()/getpwuid() when running with the
|
||||
User option set and the Linux syscall sandbox enabled. Fixes bug
|
||||
11946; bugfix on 0.2.5.1-alpha.
|
||||
+105
-4
@@ -1702,6 +1702,107 @@ log_credential_status(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
/** Cached struct from the last getpwname() call we did successfully. */
|
||||
static struct passwd *passwd_cached = NULL;
|
||||
|
||||
/** Helper: copy a struct passwd object.
|
||||
*
|
||||
* We only copy the fields pw_uid, pw_gid, pw_name, pw_dir. Tor doesn't use
|
||||
* any others, and I don't want to run into incompatibilities.
|
||||
*/
|
||||
static struct passwd *
|
||||
tor_passwd_dup(const struct passwd *pw)
|
||||
{
|
||||
struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
|
||||
if (pw->pw_name)
|
||||
new_pw->pw_name = tor_strdup(pw->pw_name);
|
||||
if (pw->pw_dir)
|
||||
new_pw->pw_dir = tor_strdup(pw->pw_dir);
|
||||
new_pw->pw_uid = pw->pw_uid;
|
||||
new_pw->pw_gid = pw->pw_gid;
|
||||
|
||||
return new_pw;
|
||||
}
|
||||
|
||||
/** Helper: free one of our cached 'struct passwd' values. */
|
||||
static void
|
||||
tor_passwd_free(struct passwd *pw)
|
||||
{
|
||||
if (!pw)
|
||||
return;
|
||||
|
||||
tor_free(pw->pw_name);
|
||||
tor_free(pw->pw_dir);
|
||||
tor_free(pw);
|
||||
}
|
||||
|
||||
/** Wrapper around getpwnam() that caches result. Used so that we don't need
|
||||
* to give the sandbox access to /etc/passwd.
|
||||
*
|
||||
* The following fields alone will definitely be copied in the output: pw_uid,
|
||||
* pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
|
||||
*
|
||||
* When called with a NULL argument, this function clears storage associated
|
||||
* with static variables it uses.
|
||||
**/
|
||||
const struct passwd *
|
||||
tor_getpwnam(const char *username)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
if (username == NULL) {
|
||||
tor_passwd_free(passwd_cached);
|
||||
passwd_cached = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((pw = getpwnam(username))) {
|
||||
tor_passwd_free(passwd_cached);
|
||||
passwd_cached = tor_passwd_dup(pw);
|
||||
log_notice(LD_GENERAL, "Caching new entry %s for %s",
|
||||
passwd_cached->pw_name, username);
|
||||
return pw;
|
||||
}
|
||||
|
||||
/* Lookup failed */
|
||||
if (! passwd_cached || ! passwd_cached->pw_name)
|
||||
return NULL;
|
||||
|
||||
if (! strcmp(username, passwd_cached->pw_name))
|
||||
return passwd_cached;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Wrapper around getpwnam() that can use cached result from
|
||||
* tor_getpwnam(). Used so that we don't need to give the sandbox access to
|
||||
* /etc/passwd.
|
||||
*
|
||||
* The following fields alone will definitely be copied in the output: pw_uid,
|
||||
* pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
|
||||
*/
|
||||
const struct passwd *
|
||||
tor_getpwuid(uid_t uid)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
if ((pw = getpwuid(uid))) {
|
||||
return pw;
|
||||
}
|
||||
|
||||
/* Lookup failed */
|
||||
if (! passwd_cached)
|
||||
return NULL;
|
||||
|
||||
if (uid == passwd_cached->pw_uid)
|
||||
return passwd_cached;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** Call setuid and setgid to run as <b>user</b> and switch to their
|
||||
* primary group. Return 0 on success. On failure, log and return -1.
|
||||
*/
|
||||
@@ -1709,7 +1810,7 @@ int
|
||||
switch_id(const char *user)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct passwd *pw = NULL;
|
||||
const struct passwd *pw = NULL;
|
||||
uid_t old_uid;
|
||||
gid_t old_gid;
|
||||
static int have_already_switched_id = 0;
|
||||
@@ -1730,7 +1831,7 @@ switch_id(const char *user)
|
||||
old_gid = getgid();
|
||||
|
||||
/* Lookup the user and group information, if we have a problem, bail out. */
|
||||
pw = getpwnam(user);
|
||||
pw = tor_getpwnam(user);
|
||||
if (pw == NULL) {
|
||||
log_warn(LD_CONFIG, "Error setting configured user: %s not found", user);
|
||||
return -1;
|
||||
@@ -1901,10 +2002,10 @@ tor_disable_debugger_attach(void)
|
||||
char *
|
||||
get_user_homedir(const char *username)
|
||||
{
|
||||
struct passwd *pw;
|
||||
const struct passwd *pw;
|
||||
tor_assert(username);
|
||||
|
||||
if (!(pw = getpwnam(username))) {
|
||||
if (!(pw = tor_getpwnam(username))) {
|
||||
log_err(LD_CONFIG,"User \"%s\" not found.", username);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -633,6 +633,11 @@ int switch_id(const char *user);
|
||||
char *get_user_homedir(const char *username);
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
const struct passwd *tor_getpwnam(const char *username);
|
||||
const struct passwd *tor_getpwuid(uid_t uid);
|
||||
#endif
|
||||
|
||||
int get_parent_directory(char *fname);
|
||||
char *make_path_absolute(char *fname);
|
||||
|
||||
|
||||
+5
-5
@@ -1871,7 +1871,7 @@ check_private_dir(const char *dirname, cpd_check_t check,
|
||||
char *f;
|
||||
#ifndef _WIN32
|
||||
int mask;
|
||||
struct passwd *pw = NULL;
|
||||
const struct passwd *pw = NULL;
|
||||
uid_t running_uid;
|
||||
gid_t running_gid;
|
||||
#else
|
||||
@@ -1918,7 +1918,7 @@ check_private_dir(const char *dirname, cpd_check_t check,
|
||||
if (effective_user) {
|
||||
/* Look up the user and group information.
|
||||
* If we have a problem, bail out. */
|
||||
pw = getpwnam(effective_user);
|
||||
pw = tor_getpwnam(effective_user);
|
||||
if (pw == NULL) {
|
||||
log_warn(LD_CONFIG, "Error setting configured user: %s not found",
|
||||
effective_user);
|
||||
@@ -1932,13 +1932,13 @@ check_private_dir(const char *dirname, cpd_check_t check,
|
||||
}
|
||||
|
||||
if (st.st_uid != running_uid) {
|
||||
struct passwd *pw = NULL;
|
||||
const struct passwd *pw = NULL;
|
||||
char *process_ownername = NULL;
|
||||
|
||||
pw = getpwuid(running_uid);
|
||||
pw = tor_getpwuid(running_uid);
|
||||
process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>");
|
||||
|
||||
pw = getpwuid(st.st_uid);
|
||||
pw = tor_getpwuid(st.st_uid);
|
||||
|
||||
log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
|
||||
"%s (%d). Perhaps you are running Tor as the wrong user?",
|
||||
|
||||
+2
-2
@@ -1017,7 +1017,7 @@ connection_listener_new(const struct sockaddr *listensockaddr,
|
||||
tor_socket_t s = TOR_INVALID_SOCKET; /* the socket we're going to make */
|
||||
or_options_t const *options = get_options();
|
||||
#if defined(HAVE_PWD_H) && defined(HAVE_SYS_UN_H)
|
||||
struct passwd *pw = NULL;
|
||||
const struct passwd *pw = NULL;
|
||||
#endif
|
||||
uint16_t usePort = 0, gotPort = 0;
|
||||
int start_reading = 0;
|
||||
@@ -1157,7 +1157,7 @@ connection_listener_new(const struct sockaddr *listensockaddr,
|
||||
}
|
||||
#ifdef HAVE_PWD_H
|
||||
if (options->User) {
|
||||
pw = getpwnam(options->User);
|
||||
pw = tor_getpwnam(options->User);
|
||||
if (pw == NULL) {
|
||||
log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.",
|
||||
address, options->User);
|
||||
|
||||
+1
-1
@@ -1492,7 +1492,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
|
||||
*answer = tor_strdup("");
|
||||
#else
|
||||
int myUid = geteuid();
|
||||
struct passwd *myPwEntry = getpwuid(myUid);
|
||||
const struct passwd *myPwEntry = tor_getpwuid(myUid);
|
||||
|
||||
if (myPwEntry) {
|
||||
*answer = tor_strdup(myPwEntry->pw_name);
|
||||
|
||||
@@ -2548,6 +2548,9 @@ tor_free_all(int postfork)
|
||||
free_cell_pool();
|
||||
if (!postfork) {
|
||||
tor_tls_free_all();
|
||||
#ifndef _WIN32
|
||||
tor_getpwnam(NULL);
|
||||
#endif
|
||||
}
|
||||
/* stuff in main.c */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user