Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hammer: client: added permission check based on getgrouplist #6604

Merged
6 commits merged into from Mar 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions configure.ac
Expand Up @@ -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.
#
Expand Down
52 changes: 47 additions & 5 deletions src/client/Client.cc
Expand Up @@ -90,6 +90,11 @@ using namespace std;
#include "include/assert.h"
#include "include/stat.h"

#if HAVE_GETGROUPLIST
#include <grp.h>
#include <pwd.h>
#endif

#undef dout_prefix
#define dout_prefix *_dout << "client." << whoami << " "

Expand Down Expand Up @@ -4386,17 +4391,54 @@ int Client::check_permissions(Inode *in, int flags, int uid, int gid)
gid_t *sgids = NULL;
int sgid_count = 0;
if (getgroups_cb) {
sgid_count = getgroups_cb(callback_handle, uid, &sgids);
if (sgid_count < 0) {
sgid_count = getgroups_cb(callback_handle, &sgids);
if (sgid_count > 0) {
ldout(cct, 3) << "getgroups failed!" << dendl;
return sgid_count;
}
}
#if HAVE_GETGROUPLIST
if (sgid_count <= 0) {
// 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)
Expand Down
2 changes: 1 addition & 1 deletion src/client/Client.h
Expand Up @@ -138,7 +138,7 @@ typedef void (*client_dentry_callback_t)(void *handle, vinodeno_t dirino,
vinodeno_t ino, string& name);
typedef int (*client_remount_callback_t)(void *handle);

typedef int (*client_getgroups_callback_t)(void *handle, uid_t uid, gid_t **sgids);
typedef int (*client_getgroups_callback_t)(void *handle, gid_t **sgids);
typedef void(*client_switch_interrupt_callback_t)(void *req, void *data);

struct client_callback_args {
Expand Down