diff --git a/configure.ac b/configure.ac index 969baed8357dbc..3a82fbfeb7dda9 100644 --- a/configure.ac +++ b/configure.ac @@ -932,6 +932,9 @@ AC_CHECK_FUNC([fallocate], [AC_DEFINE([CEPH_HAVE_FALLOCATE], [], [fallocate(2) is supported])], []) +# getgrouplist +AC_CHECK_FUNCS([getgrouplist]) + # # Test for time-related `struct stat` members. # diff --git a/src/client/Client.cc b/src/client/Client.cc index 0d85db29ce8c0d..a966b170211667 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -90,6 +90,11 @@ using namespace std; #include "include/assert.h" #include "include/stat.h" +#if HAVE_GETGROUPLIST +#include +#include +#endif + #undef dout_prefix #define dout_prefix *_dout << "client." << whoami << " " @@ -4392,11 +4397,49 @@ int Client::check_permissions(Inode *in, int flags, int uid, int gid) return sgid_count; } } +#if HAVE_GETGROUPLIST + else { + // use PAM to get the group list + // initial number of group entries, defaults to posix standard of 16 + // PAM implementations may provide more than 16 groups.... + sgid_count = 16; + sgids = (gid_t*)malloc(sgid_count * sizeof(gid_t)); + if (sgids == NULL) { + ldout(cct, 3) << "allocating group memory failed" << dendl; + return -EACCES; + } + struct passwd *pw; + pw = getpwuid(uid); + if (pw == NULL) { + ldout(cct, 3) << "getting user entry failed" << dendl; + return -EACCES; + } + while (1) { + if (getgrouplist(pw->pw_name, gid, sgids, &sgid_count) == -1) { + // we need to resize the group list and try again + void *_realloc = NULL; + if ((_realloc = realloc(sgids, sgid_count * sizeof(gid_t))) == NULL) { + ldout(cct, 3) << "allocating group memory failed" << dendl; + free(sgids); + return -EACCES; + } + sgids = (gid_t*)_realloc; + continue; + } + // list was successfully retrieved + break; + } + } +#endif + // check permissions before doing anything else + int ret = 0; if (uid != 0 && !in->check_mode(uid, gid, sgids, sgid_count, flags)) { - return -EACCES; + ret = -EACCES; } - return 0; + if (sgids) + free(sgids); + return ret; } vinodeno_t Client::_get_vino(Inode *in)