This patch introduces new attribute to filesystem element to support customizable access mode for mount type. Valid accessmode are: passthrough, mapped and squash. Usage: <filesystem type='mount' accessmode='passthrough'> <source dir='/export/to/guest'/> <target dir='mount_tag'/> </filesystem> Here is the detailed explanation on these access modes: Access mode: mapped -------------------- Fileserver intercepts and maps all the file object create requests. Files on the fileserver will be created with Fileserver's user credentials and the client-user's credentials are stored in extended attributes. During getattr() server extracts the client-user's credentials from extended attributes and sends to the client. This adds a great deal of security in the cloud environments where the guest's(client) user space is kept completely isolated from host's user space. Access mode : passthrough -------------------------- In this security model, Fileserver passes down all requests to the underlying filesystem. File system objects on the fileserver will be created with client-user's credentials. This is done by setting setuid()/setgid() during creation or chmod/chown after file creation. At the end of create protocol request, files on the fileserver will be owned by cleint-user's uid/gid. This model mimic's current NFSv3 level of security. Access mode: squash -------------------- In 'squash' mode, the (filesystem) server attempts to preserve user/group ownership from guest, however: - If the server is running as root this mode is equivalent to passthrough. - If the server is running as non-root, all files just have uid/gid matching the server process. Note: This patch is based on Daniel's patch to support 9pfs. It shall be applied after applying Daniel's patch to support 9pfs. Signed-off-by: Harsh Prateek Bora <harsh@xxxxxxxxxxxxxxxxxx> --- v2: - fixed compilation errors missed in v1. docs/schemas/domain.rng | 7 +++++++ src/conf/domain_conf.c | 30 ++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 11 +++++++++++ src/qemu/qemu_conf.c | 11 +++++++++-- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index ccb8cf3..c0e5149 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -761,6 +761,13 @@ </choice> <optional> <ref name="address"/> + <attribute name="accessmode"> + <choice> + <value>passthrough</value> + <value>mapped</value> + <value>squash</value> + </choice> + </attribute> </optional> </element> </define> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e05d5d7..991b284 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -161,6 +161,12 @@ VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST, "file", "template") +VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST, + "passthrough", + "mapped", + "squash") + + VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, "user", "ethernet", @@ -1847,6 +1853,7 @@ virDomainFSDefParseXML(xmlNodePtr node, char *type = NULL; char *source = NULL; char *target = NULL; + char *accessmode = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -1864,6 +1871,17 @@ virDomainFSDefParseXML(xmlNodePtr node, def->type = VIR_DOMAIN_FS_TYPE_MOUNT; } + accessmode = virXMLPropString(node, "accessmode"); + if (accessmode) { + if ((def->accessmode = virDomainFSAccessModeTypeFromString(accessmode)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown accessmode '%s'"), accessmode); + goto error; + } + } else { + def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH; + } + cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { @@ -5602,6 +5620,7 @@ virDomainFSDefFormat(virBufferPtr buf, int flags) { const char *type = virDomainFSTypeToString(def->type); + const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode); if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -5609,9 +5628,16 @@ virDomainFSDefFormat(virBufferPtr buf, return -1; } + if (!accessmode) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected accessmode %d"), def->accessmode); + return -1; + } + + virBufferVSprintf(buf, - " <filesystem type='%s'>\n", - type); + " <filesystem type='%s' accessmode='%s'>\n", + type, accessmode); if (def->src) { switch (def->type) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7195c04..0668ce5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -236,10 +236,20 @@ enum virDomainFSType { VIR_DOMAIN_FS_TYPE_LAST }; +/* Filesystem mount access mode */ +enum virDomainFSAccessMode { + VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH, + VIR_DOMAIN_FS_ACCESSMODE_MAPPED, + VIR_DOMAIN_FS_ACCESSMODE_SQUASH, + + VIR_DOMAIN_FS_ACCESSMODE_LAST +}; + typedef struct _virDomainFSDef virDomainFSDef; typedef virDomainFSDef *virDomainFSDefPtr; struct _virDomainFSDef { int type; + int accessmode; char *src; char *dst; unsigned int readonly : 1; @@ -1167,6 +1177,7 @@ VIR_ENUM_DECL(virDomainDiskErrorPolicy) VIR_ENUM_DECL(virDomainController) VIR_ENUM_DECL(virDomainControllerModel) VIR_ENUM_DECL(virDomainFS) +VIR_ENUM_DECL(virDomainFSAccessMode) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChrDevice) VIR_ENUM_DECL(virDomainChrChannelTarget) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 18a302a..110b9e2 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -2783,11 +2783,18 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs, if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("can only passthrough directories")); + _("only supports mount filesystem type")); goto error; } - virBufferAddLit(&opt, "local,security_model=passthrough"); + virBufferAddLit(&opt, "local"); + if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_MAPPED) { + virBufferAddLit(&opt, ",security_model=mapped"); + } else if(fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) { + virBufferAddLit(&opt, ",security_model=passthrough"); + } else if(fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) { + virBufferAddLit(&opt, ",security_model=none"); + } virBufferVSprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias); virBufferVSprintf(&opt, ",path=%s", fs->src); -- 1.7.1.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list