tools/virtiofsd: xattr name mappings: Map server xattr names
Map xattr names coming from the server, i.e. the host filesystem; currently this is only from listxattr. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Message-Id: <20201023165812.36028-4-dgilbert@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
4f088dbf98
commit
6409cf19ca
@ -2229,6 +2229,44 @@ static int xattr_map_client(const struct lo_data *lo, const char *client_name,
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For use with listxattr where the server fs gives us a name and we may need
|
||||||
|
* to sanitize this for the client.
|
||||||
|
* Returns a pointer to the result in *out_name
|
||||||
|
* This is always the original string or the current string with some prefix
|
||||||
|
* removed; no reallocation is done.
|
||||||
|
* Returns 0 on success
|
||||||
|
* Can return -ENODATA to indicate the name should be dropped from the list.
|
||||||
|
*/
|
||||||
|
static int xattr_map_server(const struct lo_data *lo, const char *server_name,
|
||||||
|
const char **out_name)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
for (i = 0; i < lo->xattr_map_nentries; i++) {
|
||||||
|
const XattrMapEntry *cur_entry = lo->xattr_map_list + i;
|
||||||
|
|
||||||
|
if ((cur_entry->flags & XATTR_MAP_FLAG_SERVER) &&
|
||||||
|
(strstart(server_name, cur_entry->prepend, &end))) {
|
||||||
|
if (cur_entry->flags & XATTR_MAP_FLAG_BAD) {
|
||||||
|
return -ENODATA;
|
||||||
|
}
|
||||||
|
if (cur_entry->flags & XATTR_MAP_FLAG_OK) {
|
||||||
|
*out_name = server_name;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cur_entry->flags & XATTR_MAP_FLAG_PREFIX) {
|
||||||
|
/* Remove prefix */
|
||||||
|
*out_name = end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENODATA;
|
||||||
|
}
|
||||||
|
|
||||||
static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
|
static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
@ -2383,8 +2421,60 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lo->xattr_map_list) {
|
||||||
|
/*
|
||||||
|
* Map the names back, some attributes might be dropped,
|
||||||
|
* some shortened, but not increased, so we shouldn't
|
||||||
|
* run out of room.
|
||||||
|
*/
|
||||||
|
size_t out_index, in_index;
|
||||||
|
out_index = 0;
|
||||||
|
in_index = 0;
|
||||||
|
while (in_index < ret) {
|
||||||
|
const char *map_out;
|
||||||
|
char *in_ptr = value + in_index;
|
||||||
|
/* Length of current attribute name */
|
||||||
|
size_t in_len = strlen(value + in_index) + 1;
|
||||||
|
|
||||||
|
int mapret = xattr_map_server(lo, in_ptr, &map_out);
|
||||||
|
if (mapret != -ENODATA && mapret != 0) {
|
||||||
|
/* Shouldn't happen */
|
||||||
|
saverr = -mapret;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (mapret == 0) {
|
||||||
|
/* Either unchanged, or truncated */
|
||||||
|
size_t out_len;
|
||||||
|
if (map_out != in_ptr) {
|
||||||
|
/* +1 copies the NIL */
|
||||||
|
out_len = strlen(map_out) + 1;
|
||||||
|
} else {
|
||||||
|
/* No change */
|
||||||
|
out_len = in_len;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Move result along, may still be needed for an unchanged
|
||||||
|
* entry if a previous entry was changed.
|
||||||
|
*/
|
||||||
|
memmove(value + out_index, map_out, out_len);
|
||||||
|
|
||||||
|
out_index += out_len;
|
||||||
|
}
|
||||||
|
in_index += in_len;
|
||||||
|
}
|
||||||
|
ret = out_index;
|
||||||
|
if (ret == 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
fuse_reply_buf(req, value, ret);
|
fuse_reply_buf(req, value, ret);
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* xattrmap only ever shortens the result,
|
||||||
|
* so we don't need to do anything clever with the
|
||||||
|
* allocation length here.
|
||||||
|
*/
|
||||||
fuse_reply_xattr(req, ret);
|
fuse_reply_xattr(req, ret);
|
||||||
}
|
}
|
||||||
out_free:
|
out_free:
|
||||||
|
Loading…
Reference in New Issue
Block a user