From fb937635f5b84b13eb12e62cfe3a7bd2e4b4a445 Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Tue, 16 Jul 2019 21:52:53 -0700 Subject: [PATCH] Eagerly initialize sysconf variables Previously s3fs had races updating these shared variables. Found via ThreadSanitizer. --- src/s3fs.cpp | 2 ++ src/s3fs_util.cpp | 70 +++++++++++++++++++++++------------------------ src/s3fs_util.h | 1 + 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/s3fs.cpp b/src/s3fs.cpp index adef173..7aee21c 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -5091,6 +5091,8 @@ int main(int argc, char* argv[]) xmlInitParser(); LIBXML_TEST_VERSION + init_sysconf_vars(); + // get program name - emulate basename program_name.assign(argv[0]); size_t found = program_name.find_last_of('/'); diff --git a/src/s3fs_util.cpp b/src/s3fs_util.cpp index 7e4416e..81cad68 100644 --- a/src/s3fs_util.cpp +++ b/src/s3fs_util.cpp @@ -53,6 +53,9 @@ using namespace std; //------------------------------------------------------------------- std::string mount_prefix; +static size_t max_password_size; +static size_t max_group_name_length; + //------------------------------------------------------------------- // Utility //------------------------------------------------------------------- @@ -459,36 +462,48 @@ AutoLock::~AutoLock() } } +void init_sysconf_vars() +{ + // SUSv4tc1 says the following about _SC_GETGR_R_SIZE_MAX and + // _SC_GETPW_R_SIZE_MAX: + // Note that sysconf(_SC_GETGR_R_SIZE_MAX) may return -1 if + // there is no hard limit on the size of the buffer needed to + // store all the groups returned. + + long res = sysconf(_SC_GETPW_R_SIZE_MAX); + if(0 > res){ + if (errno != 0){ + S3FS_PRN_WARN("could not get max pw length."); + abort(); + } + res = 1024; // default initial length + } + max_password_size = res; + + res = sysconf(_SC_GETGR_R_SIZE_MAX); + if(0 > res) { + if (errno != 0) { + S3FS_PRN_ERR("could not get max name length."); + abort(); + } + res = 1024; // default initial length + } + max_group_name_length = res; +} + //------------------------------------------------------------------- // Utility for UID/GID //------------------------------------------------------------------- // get user name from uid string get_username(uid_t uid) { - static size_t maxlen = 0; // set once + size_t maxlen = max_password_size; int result; char* pbuf; struct passwd pwinfo; struct passwd* ppwinfo = NULL; // make buffer - if(0 == maxlen){ - long res = sysconf(_SC_GETPW_R_SIZE_MAX); - if(0 > res){ - // SUSv4tc1 says the following about _SC_GETGR_R_SIZE_MAX and - // _SC_GETPW_R_SIZE_MAX: - // Note that sysconf(_SC_GETGR_R_SIZE_MAX) may return -1 if - // there is no hard limit on the size of the buffer needed to - // store all the groups returned. - if (errno != 0){ - S3FS_PRN_WARN("could not get max pw length."); - maxlen = 0; - return string(""); - } - res = 1024; // default initial length - } - maxlen = res; - } pbuf = new char[maxlen]; // get pw information while(ERANGE == (result = getpwuid_r(uid, &pwinfo, pbuf, maxlen, &ppwinfo))){ @@ -515,30 +530,13 @@ string get_username(uid_t uid) int is_uid_include_group(uid_t uid, gid_t gid) { - static size_t maxlen = 0; // set once + size_t maxlen = max_group_name_length; int result; char* pbuf; struct group ginfo; struct group* pginfo = NULL; // make buffer - if(0 == maxlen){ - long res = sysconf(_SC_GETGR_R_SIZE_MAX); - if(0 > res) { - // SUSv4tc1 says the following about _SC_GETGR_R_SIZE_MAX and - // _SC_GETPW_R_SIZE_MAX: - // Note that sysconf(_SC_GETGR_R_SIZE_MAX) may return -1 if - // there is no hard limit on the size of the buffer needed to - // store all the groups returned. - if (errno != 0) { - S3FS_PRN_ERR("could not get max name length."); - maxlen = 0; - return -ERANGE; - } - res = 1024; // default initial length - } - maxlen = res; - } pbuf = new char[maxlen]; // get group information while(ERANGE == (result = getgrgid_r(gid, &ginfo, pbuf, maxlen, &pginfo))){ diff --git a/src/s3fs_util.h b/src/s3fs_util.h index b5ad12e..14c76f6 100644 --- a/src/s3fs_util.h +++ b/src/s3fs_util.h @@ -111,6 +111,7 @@ MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, b MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir = false); void free_mvnodes(MVNODE *head); +void init_sysconf_vars(); std::string get_username(uid_t uid); int is_uid_include_group(uid_t uid, gid_t gid);