#include "proxy_requests.h"
#include "proxy_async.h"
+/* We override the definition of UserPerm structure to contain internal user
+ * credentials. This is already a black box for libcephfs users, so this won't
+ * be noticed. */
+struct UserPerm {
+ uid_t uid;
+ gid_t gid;
+ uint32_t count;
+ gid_t groups[];
+};
+
/* We override the definition of the ceph_mount_info structure to contain
* internal proxy information. This is already a black box for libcephfs users,
* so this won't be noticed. */
__err; \
})
+#define PROXY_EMBED_PERMS(_client, _req, _perms) \
+ do { \
+ if (proxy_embed_perms(_client, &_req.v0.userperm, _perms)) { \
+ _req.v1.ngroups = _perms->count; \
+ CEPH_BUFF_ADD(_req, _perms->groups, \
+ sizeof(gid_t) * _perms->count); \
+ } else { \
+ _req.v1.ngroups = 0; \
+ } \
+ } while (false)
+
+static bool proxy_embed_perms(struct ceph_mount_info *cmount,
+ embedded_perms_t *embed, const UserPerm *perms)
+{
+ if ((cmount->neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) {
+ embed->uid = perms->uid;
+ embed->gid = perms->gid;
+ return true;
+ }
+
+ embed->ptr = ptr_value(perms);
+
+ return false;
+}
+
__public int ceph_chdir(struct ceph_mount_info *cmount, const char *path)
{
CEPH_REQ(ceph_chdir, req, 1, ans, 0);
unsigned want, unsigned lflags,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_create, req, 1, ans, 1);
+ CEPH_REQ(ceph_ll_create, req, 2, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.parent = ptr_value(parent);
req.v0.mode = mode;
req.v0.oflags = oflags;
req.v0.flags = lflags;
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
+
CEPH_BUFF_ADD(ans, stx, sizeof(*stx));
err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_CREATE, req, ans);
struct ceph_statx *stx, unsigned int want,
unsigned int flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_getattr, req, 0, ans, 1);
+ CEPH_REQ(ceph_ll_getattr, req, 1, ans, 1);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
req.v0.want = want;
req.v0.flags = flags;
+ PROXY_EMBED_PERMS(cmount, req, perms);
+
CEPH_BUFF_ADD(ans, stx, sizeof(*stx));
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_GETATTR, req, ans);
const char *name, void *value, size_t size,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_getxattr, req, 1, ans, 1);
+ CEPH_REQ(ceph_ll_getxattr, req, 2, ans, 1);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
req.v0.size = size;
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
CEPH_BUFF_ADD(ans, value, size);
struct Inode *newparent, const char *name,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_link, req, 1, ans, 0);
+ CEPH_REQ(ceph_ll_link, req, 2, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
req.v0.parent = ptr_value(newparent);
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LINK, req, ans);
}
char *list, size_t buf_size, size_t *list_size,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_listxattr, req, 0, ans, 1);
+ CEPH_REQ(ceph_ll_listxattr, req, 1, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.inode = ptr_value(in);
req.v0.size = buf_size;
+ PROXY_EMBED_PERMS(cmount, req, perms);
+
CEPH_BUFF_ADD(ans, list, buf_size);
err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_LISTXATTR, req, ans);
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_lookup, req, 1, ans, 1);
+ CEPH_REQ(ceph_ll_lookup, req, 2, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.parent = ptr_value(parent);
req.v0.want = want;
req.v0.flags = flags;
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
CEPH_BUFF_ADD(ans, stx, sizeof(*stx));
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_mkdir, req, 1, ans, 1);
+ CEPH_REQ(ceph_ll_mkdir, req, 2, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.parent = ptr_value(parent);
req.v0.mode = mode;
req.v0.want = want;
req.v0.flags = flags;
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
CEPH_BUFF_ADD(ans, stx, sizeof(*stx));
Inode **out, struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_mknod, req, 1, ans, 1);
+ CEPH_REQ(ceph_ll_mknod, req, 2, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.parent = ptr_value(parent);
req.v0.mode = mode;
req.v0.rdev = rdev;
req.v0.want = want;
req.v0.flags = flags;
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
CEPH_BUFF_ADD(ans, stx, sizeof(*stx));
__public int ceph_ll_open(struct ceph_mount_info *cmount, struct Inode *in,
int flags, struct Fh **fh, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_open, req, 0, ans, 0);
+ CEPH_REQ(ceph_ll_open, req, 1, ans, 0);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.inode = ptr_value(in);
req.v0.flags = flags;
+ PROXY_EMBED_PERMS(cmount, req, perms);
+
err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_OPEN, req, ans);
if (err >= 0) {
*fh = value_ptr(ans.v0.fh);
struct ceph_dir_result **dirpp,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_opendir, req, 0, ans, 0);
+ CEPH_REQ(ceph_ll_opendir, req, 1, ans, 0);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.inode = ptr_value(in);
+ PROXY_EMBED_PERMS(cmount, req, perms);
+
err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_OPENDIR, req, ans);
if (err >= 0) {
*dirpp = value_ptr(ans.v0.dir);
__public int ceph_ll_readlink(struct ceph_mount_info *cmount, struct Inode *in,
char *buf, size_t bufsize, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_readlink, req, 0, ans, 1);
+ CEPH_REQ(ceph_ll_readlink, req, 1, ans, 1);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
req.v0.size = bufsize;
+ PROXY_EMBED_PERMS(cmount, req, perms);
+
CEPH_BUFF_ADD(ans, buf, bufsize);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_READLINK, req, ans);
struct Inode *in, const char *name,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_removexattr, req, 1, ans, 0);
+ CEPH_REQ(ceph_ll_removexattr, req, 2, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_REMOVEXATTR, req, ans);
}
struct Inode *newparent, const char *newname,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_rename, req, 2, ans, 0);
+ CEPH_REQ(ceph_ll_rename, req, 3, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.old_parent = ptr_value(parent);
req.v0.new_parent = ptr_value(newparent);
+
CEPH_STR_ADD(req, v0.old_name, name);
CEPH_STR_ADD(req, v0.new_name, newname);
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_RENAME, req, ans);
}
__public int ceph_ll_rmdir(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_rmdir, req, 1, ans, 0);
+ CEPH_REQ(ceph_ll_rmdir, req, 2, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.parent = ptr_value(in);
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_RMDIR, req, ans);
}
struct ceph_statx *stx, int mask,
const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_setattr, req, 1, ans, 0);
+ CEPH_REQ(ceph_ll_setattr, req, 2, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
req.v0.mask = mask;
+
CEPH_BUFF_ADD(req, stx, sizeof(*stx));
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_SETATTR, req, ans);
}
const char *name, const void *value, size_t size,
int flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_setxattr, req, 2, ans, 0);
+ CEPH_REQ(ceph_ll_setxattr, req, 3, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.inode = ptr_value(in);
req.v0.size = size;
req.v0.flags = flags;
+
CEPH_STR_ADD(req, v0.name, name);
CEPH_BUFF_ADD(req, value, size);
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_SETXATTR, req, ans);
}
struct ceph_statx *stx, unsigned want,
unsigned flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_symlink, req, 2, ans, 1);
+ CEPH_REQ(ceph_ll_symlink, req, 3, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.parent = ptr_value(in);
req.v0.want = want;
req.v0.flags = flags;
+
CEPH_STR_ADD(req, v0.name, name);
CEPH_STR_ADD(req, v0.target, value);
+ PROXY_EMBED_PERMS(cmount, req, perms);
CEPH_BUFF_ADD(req, stx, sizeof(*stx));
__public int ceph_ll_unlink(struct ceph_mount_info *cmount, struct Inode *in,
const char *name, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_unlink, req, 1, ans, 0);
+ CEPH_REQ(ceph_ll_unlink, req, 2, ans, 0);
+
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
- req.v0.userperm.ptr = ptr_value(perms);
req.v0.parent = ptr_value(in);
+
CEPH_STR_ADD(req, v0.name, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_UNLINK, req, ans);
}
Inode **i, struct ceph_statx *stx, unsigned int want,
unsigned int flags, const UserPerm *perms)
{
- CEPH_REQ(ceph_ll_walk, req, 1, ans, 1);
+ CEPH_REQ(ceph_ll_walk, req, 2, ans, 1);
int32_t err;
- req.v0.userperm.ptr = ptr_value(perms);
+ PROTO_VERSION(&cmount->neg, req, PROXY_PROTOCOL_V1);
+
req.v0.want = want;
req.v0.flags = flags;
+
CEPH_STR_ADD(req, v0.path, name);
+ PROXY_EMBED_PERMS(cmount, req, perms);
CEPH_BUFF_ADD(ans, stx, sizeof(*stx));
{
CEPH_REQ(ceph_userperm_destroy, req, 0, ans, 0);
- req.v0.userperm = ptr_value(perms);
+ /* We need to make use of the negotiation of the global mount since we
+ * don't have access to cmount here. Both negotiations should have
+ * the same setting for the embedded perms feature. */
+ if ((global_cmount.neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) {
+ proxy_free(perms);
+ } else {
+ req.v0.userperm = ptr_value(perms);
- CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_USERPERM_DESTROY, req, ans);
+ CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_USERPERM_DESTROY, req,
+ ans);
+ }
}
__public UserPerm *ceph_userperm_new(uid_t uid, gid_t gid, int ngids,
gid_t *gidlist)
{
CEPH_REQ(ceph_userperm_new, req, 1, ans, 0);
+ UserPerm *perms;
int32_t err;
+ err = proxy_global_connect();
+ if (err < 0) {
+ errno = -err;
+ return NULL;
+ }
+
+ /* We need to make use of the negotiation of the global mount since we
+ * don't have access to cmount here. Both negotiations should have
+ * the same setting for the embedded perms feature. */
+ if ((global_cmount.neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) {
+ perms = proxy_malloc(sizeof(UserPerm) + sizeof(gid_t) * ngids);
+ if (perms == NULL) {
+ errno = -ENOMEM;
+ return NULL;
+ }
+
+ perms->uid = uid;
+ perms->gid = gid;
+ perms->count = ngids;
+ memcpy(perms->groups, gidlist, sizeof(gid_t) * ngids);
+
+ return perms;
+ }
+
req.v0.uid = uid;
req.v0.gid = gid;
req.v0.groups = ngids;
CEPH_BUFF_ADD(req, gidlist, sizeof(gid_t) * ngids);
- err = proxy_global_connect();
- if (err >= 0) {
- err = CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_USERPERM_NEW, req,
- ans);
- }
+ err = CEPH_RUN(&global_cmount, LIBCEPHFSD_OP_USERPERM_NEW, req, ans);
if (err >= 0) {
return value_ptr(ans.v0.userperm);
}
CEPH_REQ(ceph_mount_perms, req, 0, ans, 0);
int32_t err;
+ if ((cmount->neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) {
+ errno = -EOPNOTSUPP;
+ return NULL;
+ }
+
err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_MOUNT_PERMS, req, ans);
if (err < 0) {
errno = -err;