On 10/14/2010 04:38 PM, Daniel P. Berrange wrote:
On Thu, Oct 14, 2010 at 04:24:45PM +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.
>
> 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(a)linux.vnet.ibm.com>
> ---
> docs/schemas/domain.rng | 7 +++++++
> src/conf/domain_conf.c | 30 ++++++++++++++++++++++++++++--
> src/conf/domain_conf.h | 11 +++++++++++
> src/qemu/qemu_conf.c | 10 ++++++++--
> 4 files changed, 54 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..68c8441 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_SECURITY_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..0961d8a 100644
> --- a/src/qemu/qemu_conf.c
> +++ b/src/qemu/qemu_conf.c
> @@ -2783,11 +2783,17 @@ 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_SQUASH) {
> + virBufferAddLit(&opt, ",security_model=none");
> + } else {
> + virBufferAddLit(&opt, ",security_model=%s",
> + virDomainFSAccessModeTypeToString(fs->accessmode));
> + }
> virBufferVSprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX,
fs->info.alias);
> virBufferVSprintf(&opt, ",path=%s", fs->src);
ACK, this gets my vote now.
Thanks Daniel, but extremely sorry that v1 has few errors which i missed
in hurry, just sent v2 (tested).
Regards,
Harsh
Daniel