mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
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) {
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
out_free:
|
||||
|
Loading…
Reference in New Issue
Block a user