From: Xavi Hernandez Date: Sat, 26 Jul 2025 18:13:38 +0000 (+0200) Subject: libcephfs_proxy: extend the protocol to support embedded permissions X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cde17574cf4c0e81e7eeab9874d1f319fdf4d89a;p=ceph.git libcephfs_proxy: extend the protocol to support embedded permissions This patch adds the changes to the protocol definition to support sending the user credentials along with the request that requires it. Using protocol version 1, instead of sending a pointer to a previously allocated UserPerm structure, the caller will embed the uid, gid and the list of additional groups in the request itself. Signed-off-by: Xavi Hernandez --- diff --git a/src/libcephfs_proxy/libcephfs_proxy.c b/src/libcephfs_proxy/libcephfs_proxy.c index 907161213a8..6b898d06dee 100644 --- a/src/libcephfs_proxy/libcephfs_proxy.c +++ b/src/libcephfs_proxy/libcephfs_proxy.c @@ -267,7 +267,7 @@ __public int ceph_ll_create(struct ceph_mount_info *cmount, Inode *parent, CEPH_REQ(ceph_ll_create, req, 1, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(parent); req.v0.mode = mode; req.v0.oflags = oflags; @@ -316,7 +316,7 @@ __public int ceph_ll_getattr(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_getattr, req, 0, ans, 1); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.want = want; req.v0.flags = flags; @@ -332,7 +332,7 @@ __public int ceph_ll_getxattr(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_getxattr, req, 1, ans, 1); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.size = size; CEPH_STR_ADD(req, v0.name, name); @@ -348,7 +348,7 @@ __public int ceph_ll_link(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_link, req, 1, ans, 0); - req.v0.userperm = ptr_value(perms); + 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); @@ -363,7 +363,7 @@ __public int ceph_ll_listxattr(struct ceph_mount_info *cmount, struct Inode *in, CEPH_REQ(ceph_ll_listxattr, req, 0, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.size = buf_size; @@ -385,7 +385,7 @@ __public int ceph_ll_lookup(struct ceph_mount_info *cmount, Inode *parent, CEPH_REQ(ceph_ll_lookup, req, 1, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(parent); req.v0.want = want; req.v0.flags = flags; @@ -456,7 +456,7 @@ __public int ceph_ll_mkdir(struct ceph_mount_info *cmount, Inode *parent, CEPH_REQ(ceph_ll_mkdir, req, 1, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(parent); req.v0.mode = mode; req.v0.want = want; @@ -481,7 +481,7 @@ __public int ceph_ll_mknod(struct ceph_mount_info *cmount, Inode *parent, CEPH_REQ(ceph_ll_mknod, req, 1, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(parent); req.v0.mode = mode; req.v0.rdev = rdev; @@ -505,7 +505,7 @@ __public int ceph_ll_open(struct ceph_mount_info *cmount, struct Inode *in, CEPH_REQ(ceph_ll_open, req, 0, ans, 0); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.flags = flags; @@ -524,7 +524,7 @@ __public int ceph_ll_opendir(struct ceph_mount_info *cmount, struct Inode *in, CEPH_REQ(ceph_ll_opendir, req, 0, ans, 0); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); err = CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_OPENDIR, req, ans); @@ -563,7 +563,7 @@ __public int ceph_ll_readlink(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_readlink, req, 0, ans, 1); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.size = bufsize; @@ -588,7 +588,7 @@ __public int ceph_ll_removexattr(struct ceph_mount_info *cmount, { CEPH_REQ(ceph_ll_removexattr, req, 1, ans, 0); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); CEPH_STR_ADD(req, v0.name, name); @@ -602,7 +602,7 @@ __public int ceph_ll_rename(struct ceph_mount_info *cmount, { CEPH_REQ(ceph_ll_rename, req, 2, ans, 0); - req.v0.userperm = ptr_value(perms); + 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); @@ -626,7 +626,7 @@ __public int ceph_ll_rmdir(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_rmdir, req, 1, ans, 0); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(in); CEPH_STR_ADD(req, v0.name, name); @@ -639,7 +639,7 @@ __public int ceph_ll_setattr(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_setattr, req, 1, ans, 0); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.mask = mask; CEPH_BUFF_ADD(req, stx, sizeof(*stx)); @@ -653,7 +653,7 @@ __public int ceph_ll_setxattr(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_setxattr, req, 2, ans, 0); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.inode = ptr_value(in); req.v0.size = size; req.v0.flags = flags; @@ -683,7 +683,7 @@ __public int ceph_ll_symlink(struct ceph_mount_info *cmount, Inode *in, CEPH_REQ(ceph_ll_symlink, req, 2, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(in); req.v0.want = want; req.v0.flags = flags; @@ -705,7 +705,7 @@ __public int ceph_ll_unlink(struct ceph_mount_info *cmount, struct Inode *in, { CEPH_REQ(ceph_ll_unlink, req, 1, ans, 0); - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.parent = ptr_value(in); CEPH_STR_ADD(req, v0.name, name); @@ -719,7 +719,7 @@ __public int ceph_ll_walk(struct ceph_mount_info *cmount, const char *name, CEPH_REQ(ceph_ll_walk, req, 1, ans, 1); int32_t err; - req.v0.userperm = ptr_value(perms); + req.v0.userperm.ptr = ptr_value(perms); req.v0.want = want; req.v0.flags = flags; CEPH_STR_ADD(req, v0.path, name); diff --git a/src/libcephfs_proxy/libcephfsd.c b/src/libcephfs_proxy/libcephfsd.c index cc5a538fa73..46b35d44e20 100644 --- a/src/libcephfs_proxy/libcephfsd.c +++ b/src/libcephfs_proxy/libcephfsd.c @@ -81,6 +81,29 @@ static int32_t send_error(proxy_client_t *client, int32_t error) #define TRACE(_fmt, _args...) do { } while (0) #endif +static int32_t validate_perms(proxy_client_t *client, embedded_perms_t *embed, + uint32_t count, const gid_t *groups, + UserPerm **pperms, bool *embedded) +{ + UserPerm *perms; + + if ((client->neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) == 0) { + *embedded = false; + return ptr_check(&client->random, embed->ptr, (void **)pperms); + } + + perms = ceph_userperm_new(embed->uid, embed->gid, count, + (gid_t *)groups); + if (perms == NULL) { + return -ENOMEM; + } + + *embedded = true; + *pperms = perms; + + return 0; +} + static int32_t libcephfsd_version(proxy_client_t *client, proxy_req_t *req, const void *data, int32_t data_size) { @@ -107,6 +130,10 @@ static int32_t libcephfsd_userperm_new(proxy_client_t *client, proxy_req_t *req, UserPerm *userperm; int32_t err; + if ((client->neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) { + return -EOPNOTSUPP; + } + userperm = ceph_userperm_new(req->userperm_new.v0.uid, req->userperm_new.v0.gid, req->userperm_new.v0.groups, @@ -131,6 +158,10 @@ static int32_t libcephfsd_userperm_destroy(proxy_client_t *client, UserPerm *perms; int32_t err; + if ((client->neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) { + return -EOPNOTSUPP; + } + err = ptr_check(&global_random, req->userperm_destroy.v0.userperm, (void **)&perms); @@ -367,6 +398,12 @@ static int32_t libcephfsd_ll_lookup(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; uint32_t want, flags; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_lookup, v0.name, data); + data = (const char *)data + req->ll_lookup.v0.name; err = ptr_check(&client->random, req->ll_lookup.v0.cmount, (void **)&mount); @@ -375,13 +412,13 @@ static int32_t libcephfsd_ll_lookup(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_lookup.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_lookup.v0.userperm, + req->ll_lookup.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { want = req->ll_lookup.v0.want; flags = req->ll_lookup.v0.flags; - name = CEPH_STR_GET(req->ll_lookup, v0.name, data); CEPH_BUFF_ADD(ans, &stx, sizeof(stx)); @@ -407,6 +444,10 @@ static int32_t libcephfsd_ll_lookup(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -499,17 +540,23 @@ static int32_t libcephfsd_ll_walk(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; uint32_t want, flags; int32_t err; + bool embedded; + + embedded = false; + + path = CEPH_STR_GET(req->ll_walk, v0.path, data); + data = (const char *)data + req->ll_walk.v0.path; err = ptr_check(&client->random, req->ll_walk.v0.cmount, (void **)&mount); if (err >= 0) { - err = ptr_check(&global_random, req->ll_walk.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_walk.v0.userperm, + req->ll_walk.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { want = req->ll_walk.v0.want; flags = req->ll_walk.v0.flags; - path = CEPH_STR_GET(req->ll_walk, v0.path, data); CEPH_BUFF_ADD(ans, &stx, sizeof(stx)); @@ -523,6 +570,10 @@ static int32_t libcephfsd_ll_walk(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -652,6 +703,9 @@ static int32_t libcephfsd_ll_open(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; struct Fh *fh; int32_t flags, err; + bool embedded; + + embedded = false; err = ptr_check(&client->random, req->ll_open.v0.cmount, (void **)&mount); @@ -660,8 +714,9 @@ static int32_t libcephfsd_ll_open(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_open.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_open.v0.userperm, + req->ll_open.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { flags = req->ll_open.v0.flags; @@ -676,6 +731,10 @@ static int32_t libcephfsd_ll_open(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -692,6 +751,12 @@ static int32_t libcephfsd_ll_create(proxy_client_t *client, proxy_req_t *req, mode_t mode; uint32_t want, flags; int32_t oflags, err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_create, v0.name, data); + data = (const char *)data + req->ll_create.v0.name; err = ptr_check(&client->random, req->ll_create.v0.cmount, (void **)&mount); @@ -700,15 +765,15 @@ static int32_t libcephfsd_ll_create(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_create.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_create.v0.userperm, + req->ll_create.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { mode = req->ll_create.v0.mode; oflags = req->ll_create.v0.oflags; want = req->ll_create.v0.want; flags = req->ll_create.v0.flags; - name = CEPH_STR_GET(req->ll_create, v0.name, data); CEPH_BUFF_ADD(ans, &stx, sizeof(stx)); @@ -726,6 +791,10 @@ static int32_t libcephfsd_ll_create(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -742,6 +811,12 @@ static int32_t libcephfsd_ll_mknod(proxy_client_t *client, proxy_req_t *req, mode_t mode; uint32_t want, flags; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_mknod, v0.name, data); + data = (const char *)data + req->ll_mknod.v0.name; err = ptr_check(&client->random, req->ll_mknod.v0.cmount, (void **)&mount); @@ -750,15 +825,15 @@ static int32_t libcephfsd_ll_mknod(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_mknod.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_mknod.v0.userperm, + req->ll_mknod.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { mode = req->ll_mknod.v0.mode; rdev = req->ll_mknod.v0.rdev; want = req->ll_mknod.v0.want; flags = req->ll_mknod.v0.flags; - name = CEPH_STR_GET(req->ll_mknod, v0.name, data); CEPH_BUFF_ADD(ans, &stx, sizeof(stx)); @@ -774,6 +849,10 @@ static int32_t libcephfsd_ll_mknod(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -809,6 +888,14 @@ static int32_t libcephfsd_ll_rename(proxy_client_t *client, proxy_req_t *req, const char *old_name, *new_name; UserPerm *perms; int32_t err; + bool embedded; + + embedded = false; + + old_name = CEPH_STR_GET(req->ll_rename, v0.old_name, data); + data = (const char *)data + req->ll_rename.v0.old_name; + new_name = CEPH_STR_GET(req->ll_rename, v0.new_name, data); + data = (const char *)data + req->ll_rename.v0.new_name; err = ptr_check(&client->random, req->ll_rename.v0.cmount, (void **)&mount); @@ -821,20 +908,21 @@ static int32_t libcephfsd_ll_rename(proxy_client_t *client, proxy_req_t *req, (void **)&new_parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_rename.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_rename.v0.userperm, + req->ll_rename.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { - old_name = CEPH_STR_GET(req->ll_rename, v0.old_name, data); - new_name = CEPH_STR_GET(req->ll_rename, v0.new_name, - (const char *)data + req->ll_rename.v0.old_name); - err = ceph_ll_rename(proxy_cmount(mount), old_parent, old_name, new_parent, new_name, perms); TRACE("ceph_ll_rename(%p, %p, '%s', %p, '%s', %p) -> %d", mount, old_parent, old_name, new_parent, new_name, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -960,6 +1048,12 @@ static int32_t libcephfsd_ll_link(proxy_client_t *client, proxy_req_t *req, const char *name; UserPerm *perms; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_link, v0.name, data); + data = (const char *)data + req->ll_link.v0.name; err = ptr_check(&client->random, req->ll_link.v0.cmount, (void **)&mount); @@ -972,18 +1066,21 @@ static int32_t libcephfsd_ll_link(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_link.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_link.v0.userperm, + req->ll_link.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { - name = CEPH_STR_GET(req->ll_link, v0.name, data); - err = ceph_ll_link(proxy_cmount(mount), inode, parent, name, perms); TRACE("ceph_ll_link(%p, %p, %p, '%s', %p) -> %d", mount, inode, parent, name, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -996,6 +1093,12 @@ static int32_t libcephfsd_ll_unlink(proxy_client_t *client, proxy_req_t *req, const char *name; UserPerm *perms; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_unlink, v0.name, data); + data = (const char *)data + req->ll_unlink.v0.name; err = ptr_check(&client->random, req->ll_unlink.v0.cmount, (void **)&mount); @@ -1004,17 +1107,20 @@ static int32_t libcephfsd_ll_unlink(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_unlink.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_unlink.v0.userperm, + req->ll_unlink.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { - name = CEPH_STR_GET(req->ll_unlink, v0.name, data); - err = ceph_ll_unlink(proxy_cmount(mount), parent, name, perms); TRACE("ceph_ll_unlink(%p, %p, '%s', %p) -> %d", mount, parent, name, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1028,6 +1134,9 @@ static int32_t libcephfsd_ll_getattr(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; uint32_t want, flags; int32_t err; + bool embedded; + + embedded = false; err = ptr_check(&client->random, req->ll_getattr.v0.cmount, (void **)&mount); @@ -1036,8 +1145,9 @@ static int32_t libcephfsd_ll_getattr(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_getattr.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_getattr.v0.userperm, + req->ll_getattr.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { want = req->ll_getattr.v0.want; @@ -1051,6 +1161,10 @@ static int32_t libcephfsd_ll_getattr(proxy_client_t *client, proxy_req_t *req, want, flags, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1062,6 +1176,9 @@ static int32_t libcephfsd_ll_setattr(proxy_client_t *client, proxy_req_t *req, struct Inode *inode; UserPerm *perms; int32_t mask, err; + bool embedded; + + embedded = false; err = ptr_check(&client->random, req->ll_setattr.v0.cmount, (void **)&mount); @@ -1070,8 +1187,9 @@ static int32_t libcephfsd_ll_setattr(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_setattr.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_setattr.v0.userperm, + req->ll_setattr.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { mask = req->ll_setattr.v0.mask; @@ -1082,6 +1200,10 @@ static int32_t libcephfsd_ll_setattr(proxy_client_t *client, proxy_req_t *req, mask, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1149,6 +1271,9 @@ static int32_t libcephfsd_ll_listxattr(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; size_t size; int32_t err; + bool embedded; + + embedded = false; err = ptr_check(&client->random, req->ll_listxattr.v0.cmount, (void **)&mount); @@ -1157,8 +1282,9 @@ static int32_t libcephfsd_ll_listxattr(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_listxattr.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_listxattr.v0.userperm, + req->ll_listxattr.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { size = req->ll_listxattr.v0.size; @@ -1176,6 +1302,10 @@ static int32_t libcephfsd_ll_listxattr(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1189,6 +1319,12 @@ static int32_t libcephfsd_ll_getxattr(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; size_t size; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_getxattr, v0.name, data); + data = (const char *)data + req->ll_getxattr.v0.name; err = ptr_check(&client->random, req->ll_getxattr.v0.cmount, (void **)&mount); @@ -1197,12 +1333,12 @@ static int32_t libcephfsd_ll_getxattr(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_getxattr.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_getxattr.v0.userperm, + req->ll_getxattr.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { size = req->ll_getxattr.v0.size; - name = CEPH_STR_GET(req->ll_getxattr, v0.name, data); if (size > client->buffer_size) { size = client->buffer_size; @@ -1217,6 +1353,10 @@ static int32_t libcephfsd_ll_getxattr(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1230,6 +1370,15 @@ static int32_t libcephfsd_ll_setxattr(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; size_t size; int32_t flags, err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_setxattr, v0.name, data); + data = (const char *)data + req->ll_setxattr.v0.name; + value = data; + size = req->ll_setxattr.v0.size; + data = (const char *)data + size; err = ptr_check(&client->random, req->ll_setxattr.v0.cmount, (void **)&mount); @@ -1238,13 +1387,11 @@ static int32_t libcephfsd_ll_setxattr(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_setxattr.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_setxattr.v0.userperm, + req->ll_setxattr.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { - name = CEPH_STR_GET(req->ll_setxattr, v0.name, data); - value = (const char *)data + req->ll_setxattr.v0.name; - size = req->ll_setxattr.v0.size; flags = req->ll_setxattr.v0.flags; err = ceph_ll_setxattr(proxy_cmount(mount), inode, name, value, @@ -1253,6 +1400,10 @@ static int32_t libcephfsd_ll_setxattr(proxy_client_t *client, proxy_req_t *req, inode, name, value, flags, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1266,6 +1417,12 @@ static int32_t libcephfsd_ll_removexattr(proxy_client_t *client, const char *name; UserPerm *perms; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_removexattr, v0.name, data); + data = (const char *)data + req->ll_removexattr.v0.name; err = ptr_check(&client->random, req->ll_removexattr.v0.cmount, (void **)&mount); @@ -1274,18 +1431,21 @@ static int32_t libcephfsd_ll_removexattr(proxy_client_t *client, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_removexattr.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_removexattr.v0.userperm, + req->ll_removexattr.v1.ngroups, data, + &perms, &embedded); } if (err >= 0) { - name = CEPH_STR_GET(req->ll_removexattr, v0.name, data); - err = ceph_ll_removexattr(proxy_cmount(mount), inode, name, perms); TRACE("ceph_ll_removexattr(%p, %p, '%s', %p) -> %d", mount, inode, name, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1298,6 +1458,9 @@ static int32_t libcephfsd_ll_readlink(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; size_t size; int32_t err; + bool embedded; + + embedded = false; err = ptr_check(&client->random, req->ll_readlink.v0.cmount, (void **)&mount); @@ -1306,8 +1469,9 @@ static int32_t libcephfsd_ll_readlink(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_readlink.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_readlink.v0.userperm, + req->ll_readlink.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { size = req->ll_readlink.v0.size; @@ -1321,6 +1485,10 @@ static int32_t libcephfsd_ll_readlink(proxy_client_t *client, proxy_req_t *req, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1335,6 +1503,14 @@ static int32_t libcephfsd_ll_symlink(proxy_client_t *client, proxy_req_t *req, const char *name, *value; uint32_t want, flags; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_symlink, v0.name, data); + data = (const char *)data + req->ll_symlink.v0.name; + value = CEPH_STR_GET(req->ll_symlink, v0.target, data); + data = (const char *)data + req->ll_symlink.v0.target; err = ptr_check(&client->random, req->ll_symlink.v0.cmount, (void **)&mount); @@ -1343,13 +1519,11 @@ static int32_t libcephfsd_ll_symlink(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_symlink.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_symlink.v0.userperm, + req->ll_symlink.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { - name = CEPH_STR_GET(req->ll_symlink, v0.name, data); - value = CEPH_STR_GET(req->ll_symlink, v0.target, - (const char *)data + req->ll_symlink.v0.name); want = req->ll_symlink.v0.want; flags = req->ll_symlink.v0.flags; @@ -1367,6 +1541,10 @@ static int32_t libcephfsd_ll_symlink(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1379,6 +1557,9 @@ static int32_t libcephfsd_ll_opendir(proxy_client_t *client, proxy_req_t *req, struct ceph_dir_result *dirp; UserPerm *perms; int32_t err; + bool embedded; + + embedded = false; err = ptr_check(&client->random, req->ll_opendir.v0.cmount, (void **)&mount); @@ -1387,8 +1568,9 @@ static int32_t libcephfsd_ll_opendir(proxy_client_t *client, proxy_req_t *req, (void **)&inode); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_opendir.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_opendir.v0.userperm, + req->ll_opendir.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { @@ -1401,6 +1583,10 @@ static int32_t libcephfsd_ll_opendir(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1416,6 +1602,12 @@ static int32_t libcephfsd_ll_mkdir(proxy_client_t *client, proxy_req_t *req, mode_t mode; uint32_t want, flags; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_mkdir, v0.name, data); + data = (const char *)data + req->ll_mkdir.v0.name; err = ptr_check(&client->random, req->ll_mkdir.v0.cmount, (void **)&mount); if (err >= 0) { @@ -1423,14 +1615,14 @@ static int32_t libcephfsd_ll_mkdir(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_mkdir.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_mkdir.v0.userperm, + req->ll_mkdir.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { mode = req->ll_mkdir.v0.mode; want = req->ll_mkdir.v0.want; flags = req->ll_mkdir.v0.flags; - name = CEPH_STR_GET(req->ll_mkdir, v0.name, data); CEPH_BUFF_ADD(ans, &stx, sizeof(stx)); @@ -1445,6 +1637,10 @@ static int32_t libcephfsd_ll_mkdir(proxy_client_t *client, proxy_req_t *req, } } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1457,6 +1653,12 @@ static int32_t libcephfsd_ll_rmdir(proxy_client_t *client, proxy_req_t *req, const char *name; UserPerm *perms; int32_t err; + bool embedded; + + embedded = false; + + name = CEPH_STR_GET(req->ll_rmdir, v0.name, data); + data = (const char *)data + req->ll_rmdir.v0.name; err = ptr_check(&client->random, req->ll_rmdir.v0.cmount, (void **)&mount); @@ -1465,17 +1667,20 @@ static int32_t libcephfsd_ll_rmdir(proxy_client_t *client, proxy_req_t *req, (void **)&parent); } if (err >= 0) { - err = ptr_check(&global_random, req->ll_rmdir.v0.userperm, - (void **)&perms); + err = validate_perms(client, &req->ll_rmdir.v0.userperm, + req->ll_rmdir.v1.ngroups, data, &perms, + &embedded); } if (err >= 0) { - name = CEPH_STR_GET(req->ll_rmdir, v0.name, data); - err = ceph_ll_rmdir(proxy_cmount(mount), parent, name, perms); TRACE("ceph_ll_rmdir(%p, %p, '%s', %p) -> %d", mount, parent, name, perms, err); } + if (embedded) { + ceph_userperm_destroy(perms); + } + return CEPH_COMPLETE(client, err, ans); } @@ -1511,6 +1716,10 @@ static int32_t libcephfsd_mount_perms(proxy_client_t *client, proxy_req_t *req, UserPerm *perms; int32_t err; + if ((client->neg.v1.enabled & PROXY_FEAT_EMBEDDED_PERMS) != 0) { + return -EOPNOTSUPP; + } + err = ptr_check(&client->random, req->mount_perms.v0.cmount, (void **)&mount); if (err >= 0) { diff --git a/src/libcephfs_proxy/proxy.h b/src/libcephfs_proxy/proxy.h index 8b2ea8abfcf..6cbfe2a98b9 100644 --- a/src/libcephfs_proxy/proxy.h +++ b/src/libcephfs_proxy/proxy.h @@ -20,6 +20,8 @@ #define PROXY_SOCKET "/run/libcephfsd.sock" #define PROXY_SOCKET_ENV "LIBCEPHFSD_SOCKET" +#define field_size(_type, _field) sizeof(((_type *)0)->_field) + #define offset_of(_type, _field) ((uintptr_t) & ((_type *)0)->_field) #define container_of(_ptr, _type, _field) \ @@ -29,11 +31,15 @@ enum { /* Support for ceph_ll_nonblocking_readv_writev */ PROXY_FEAT_ASYNC_IO = 0x00000001, + /* Support for embedding the user credentials inside the request itself + * instead of using ceph_userperm_new/ceph_userperm_destroy */ + PROXY_FEAT_EMBEDDED_PERMS = 0x00000002, + /* Mask of all features requiring the asynchronous callback handling. */ PROXY_FEAT_ASYNC_CBK = 0x00000001, /* Mask of all supported/known features. */ - PROXY_FEAT_ALL = 0x00000001 + PROXY_FEAT_ALL = 0x00000003 }; struct _list; diff --git a/src/libcephfs_proxy/proxy_link.h b/src/libcephfs_proxy/proxy_link.h index ec7dbc2ecda..2dd851c7f15 100644 --- a/src/libcephfs_proxy/proxy_link.h +++ b/src/libcephfs_proxy/proxy_link.h @@ -17,9 +17,10 @@ /* Known versions for communication protocol. */ #define PROXY_PROTOCOL_V0 0 +#define PROXY_PROTOCOL_V1 1 /* The maximum supported protocol version. */ -#define PROXY_LINK_PROTOCOL_VERSION PROXY_PROTOCOL_V0 +#define PROXY_LINK_PROTOCOL_VERSION PROXY_PROTOCOL_V1 /* Version 0 structure will be used to handle legacy clients that don't support * negotiation. */ diff --git a/src/libcephfs_proxy/proxy_requests.h b/src/libcephfs_proxy/proxy_requests.h index 293af4202c3..44238f81b65 100644 --- a/src/libcephfs_proxy/proxy_requests.h +++ b/src/libcephfs_proxy/proxy_requests.h @@ -38,11 +38,26 @@ __ptr; \ }) -#define CEPH_DATA(_name, _data, _data_count) \ - proxy_##_name##_##_data##_t _data; \ +#define PROTO_VERSION_SIZE_EXPAND(_data, _ver) \ + (offset_of(__typeof__(_data), v##_ver) + \ + field_size(__typeof__(_data), v##_ver)) + +#define PROTO_VERSION_SIZE(_data, _ver) PROTO_VERSION_SIZE_EXPAND(_data, _ver) + +#define PROTO_VERSION(_neg, _data, _ver) \ + do { \ + if ((_neg)->v2.protocol >= (_ver)) { \ + _data##_iov[0].iov_len = PROTO_VERSION_SIZE(_data, \ + _ver); \ + } \ + } while (false) + +#define CEPH_DATA(_name, _data, _data_count) \ + proxy_##_name##_##_data##_t _data; \ struct iovec _data##_iov[(_data_count) + 1]; \ - int32_t _data##_count = 0; \ - CEPH_BUFF_ADD(_data, &_data, sizeof(_data)) + int32_t _data##_count = 0; \ + CEPH_BUFF_ADD(_data, &_data, \ + PROTO_VERSION_SIZE(_data, PROXY_PROTOCOL_V0)) #define CEPH_REQ(_name, _req, _req_count, _ans, _ans_count) \ CEPH_DATA(_name, _req, _req_count); \ @@ -127,6 +142,14 @@ enum { LIBCEPHFSD_CBK_TOTAL_OPS }; +typedef union { + uint64_t ptr; + struct { + uint32_t uid; + uint32_t gid; + }; +} embedded_perms_t; + #define PROTO_REQ(_fields...) _fields #define PROTO_ANS(_fields...) _fields #define PROTO_CBK(_fields...) _fields @@ -320,12 +343,15 @@ PROTO_CALL(ceph_ll_lookup, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; uint32_t want; uint32_t flags; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -378,11 +404,14 @@ PROTO_CALL(ceph_ll_walk, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint32_t want; uint32_t flags; uint16_t path; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -448,10 +477,13 @@ PROTO_CALL(ceph_ll_open, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; int32_t flags; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -464,7 +496,7 @@ PROTO_CALL(ceph_ll_create, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; mode_t mode; int32_t oflags; @@ -472,6 +504,9 @@ PROTO_CALL(ceph_ll_create, uint32_t flags; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -485,7 +520,7 @@ PROTO_CALL(ceph_ll_mknod, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; mode_t mode; dev_t rdev; @@ -493,6 +528,9 @@ PROTO_CALL(ceph_ll_mknod, uint32_t flags; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -518,12 +556,15 @@ PROTO_CALL(ceph_ll_rename, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t old_parent; uint64_t new_parent; uint16_t old_name; uint16_t new_name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -581,11 +622,14 @@ PROTO_CALL(ceph_ll_link, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; uint64_t parent; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -597,10 +641,13 @@ PROTO_CALL(ceph_ll_unlink, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -612,11 +659,14 @@ PROTO_CALL(ceph_ll_getattr, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; uint32_t want; uint32_t flags; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -628,10 +678,13 @@ PROTO_CALL(ceph_ll_setattr, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; int32_t mask; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -673,10 +726,13 @@ PROTO_CALL(ceph_ll_listxattr, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; size_t size; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -689,11 +745,14 @@ PROTO_CALL(ceph_ll_getxattr, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; size_t size; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -705,12 +764,15 @@ PROTO_CALL(ceph_ll_setxattr, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; size_t size; int32_t flags; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -722,10 +784,13 @@ PROTO_CALL(ceph_ll_removexattr, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -737,10 +802,13 @@ PROTO_CALL(ceph_ll_readlink, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; size_t size; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -752,13 +820,16 @@ PROTO_CALL(ceph_ll_symlink, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; uint32_t want; uint32_t flags; uint16_t name; uint16_t target; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -771,9 +842,12 @@ PROTO_CALL(ceph_ll_opendir, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t inode; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -786,13 +860,16 @@ PROTO_CALL(ceph_ll_mkdir, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; mode_t mode; uint32_t want; uint32_t flags; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0, @@ -805,10 +882,13 @@ PROTO_CALL(ceph_ll_rmdir, PROTO_REQ( PROTO_VER(v0, uint64_t cmount; - uint64_t userperm; + embedded_perms_t userperm; uint64_t parent; uint16_t name; ); + PROTO_VER(v1, + uint32_t ngroups; + ); ), PROTO_ANS( PROTO_VER(v0,