[libvirt] [PATCH v2] Added new attribute accessmode to filesystem element

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@linux.vnet.ibm.com> --- 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

On Thu, Oct 14, 2010 at 04:41:51PM +0530, Harsh Prateek Bora wrote:
This patch introduces new attribute to filesystem element to support customizable access mode for mount type. Valid accessmode are: passthrough, mapped and squash. [...] @@ -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; + }
if non-NULL this was never freed because of a missing VIR_FREE(accessmode); in the clanup: section of that routine. otherwise, ACK. I was just a bit worried that if no model was given we always assume passthrough, but since that's what the QEMu backend implementation did so far and this doesn't affect other drivers, that's fine. Applied and pushed with that small change, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On 10/14/2010 06:40 PM, Daniel Veillard wrote:
On Thu, Oct 14, 2010 at 04:41:51PM +0530, Harsh Prateek Bora wrote:
This patch introduces new attribute to filesystem element to support customizable access mode for mount type. Valid accessmode are: passthrough, mapped and squash. [...] @@ -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; + }
if non-NULL this was never freed because of a missing VIR_FREE(accessmode); in the clanup: section of that routine.
otherwise, ACK. I was just a bit worried that if no model was given we always assume passthrough, but since that's what the QEMu backend implementation did so far and this doesn't affect other drivers, that's fine.
Applied and pushed with that small change,
thanks !
Thanks very much ! :)
Daniel

On 10/14/2010 07:10 AM, Daniel Veillard wrote:
otherwise, ACK. I was just a bit worried that if no model was given we always assume passthrough, but since that's what the QEMu backend implementation did so far and this doesn't affect other drivers, that's fine.
Applied and pushed with that small change,
Oops, you reverted the .gnulib submodule with that commit. I'm pushing the obvious fix to restore it to the state before that patch. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
participants (4)
-
Daniel Veillard
-
Eric Blake
-
Harsh Bora
-
Harsh Prateek Bora