[libvirt] Per-guest configurable user/group for QEMU processes

Hi, I'm starting working on an improvement for libvirt to be able to support per-guest configurable user and group IDs for QEMU processes. Currently, libvirt uses a configurable pair of user and group, which is defined in qemu.conf, for all qemu processes when running in privileged mode. This topic was already commented in qemu mailing list (http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00758.html) but, as this requires changes in libvirt API, I'd like to discuss what would be the best solution for it. A solution (as proposed in the link above) would be to extend the security driver model to allow multiple drivers. In this case, an example of the XML definition would be: ... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> ... I don't know if this is a clean solution because the usual option would be to enclose the block above in a "<seclabels>" tag. But as this would break the actual API, it's not viable. Another option is to expose the stack security driver that already exists internally in libvirt (maybe extending it to support more than two security drivers): ... <seclabel type='stack'> <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> </seclabel> ... In that case, a nested seclabel only would be allowed when type='stack'. Independently of how multiple security drivers can be expressed in the XML, another problem would be how functions as virDomainGetSecurityLabel should behave. A third option is to just not support multiple security drivers and include a new tag for DAC: ... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <dac process='102:102' image='102:102'/> ... Please let me know your opinions about this topic. Regards, Marcelo

On Thu, Feb 23, 2012 at 05:41:27PM -0200, Marcelo Cerri wrote:
Hi,
I'm starting working on an improvement for libvirt to be able to support per-guest configurable user and group IDs for QEMU processes. Currently, libvirt uses a configurable pair of user and group, which is defined in qemu.conf, for all qemu processes when running in privileged mode.
This topic was already commented in qemu mailing list (http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00758.html) but, as this requires changes in libvirt API, I'd like to discuss what would be the best solution for it.
A solution (as proposed in the link above) would be to extend the security driver model to allow multiple drivers. In this case, an example of the XML definition would be:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> ...
I don't know if this is a clean solution because the usual option would be to enclose the block above in a "<seclabels>" tag. But as this would break the actual API, it's not viable.
While it is true that we would ordinarily have an enclosing tag like <seclabels>, there's no serious problem not having it. Just having two (or more) <seclabel> elements in a row is just fine, given our backwards compatibility requirements. So I think this option is just fine.
Another option is to expose the stack security driver that already exists internally in libvirt (maybe extending it to support more than two security drivers):
... <seclabel type='stack'> <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> </seclabel> ...
In that case, a nested seclabel only would be allowed when type='stack'.
This option has some backwards compatibility problems, because any existing app querying the SELinux data would now break the moment libvirt was upgraded, so we can't do that route.
Independently of how multiple security drivers can be expressed in the XML, another problem would be how functions as virDomainGetSecurityLabel should behave.
A third option is to just not support multiple security drivers and include a new tag for DAC:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <dac process='102:102' image='102:102'/> ...
This is just <seclabel> reinvented by another name, so I don't want to see that. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 02/23/2012 05:47 PM, Daniel P. Berrange wrote:
On Thu, Feb 23, 2012 at 05:41:27PM -0200, Marcelo Cerri wrote:
Hi,
I'm starting working on an improvement for libvirt to be able to support per-guest configurable user and group IDs for QEMU processes. Currently, libvirt uses a configurable pair of user and group, which is defined in qemu.conf, for all qemu processes when running in privileged mode.
This topic was already commented in qemu mailing list (http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00758.html) but, as this requires changes in libvirt API, I'd like to discuss what would be the best solution for it.
A solution (as proposed in the link above) would be to extend the security driver model to allow multiple drivers. In this case, an example of the XML definition would be:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> ...
I don't know if this is a clean solution because the usual option would be to enclose the block above in a "<seclabels>" tag. But as this would break the actual API, it's not viable.
While it is true that we would ordinarily have an enclosing tag like<seclabels>, there's no serious problem not having it. Just having two (or more)<seclabel> elements in a row is just fine, given our backwards compatibility requirements.
So I think this option is just fine.
I agree that this is a good solution, considering the XML compatibility. But, what about virDomainGetSecurityLabel? It could access the first security label or ignore the DAC driver (and maybe another function could be added to access the whole list of seclabels), but it doesn't seem to be the best solution.
Another option is to expose the stack security driver that already exists internally in libvirt (maybe extending it to support more than two security drivers):
... <seclabel type='stack'> <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> </seclabel> ...
In that case, a nested seclabel only would be allowed when type='stack'.
This option has some backwards compatibility problems, because any existing app querying the SELinux data would now break the moment libvirt was upgraded, so we can't do that route.
Independently of how multiple security drivers can be expressed in the XML, another problem would be how functions as virDomainGetSecurityLabel should behave.
A third option is to just not support multiple security drivers and include a new tag for DAC:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <dac process='102:102' image='102:102'/> ...
This is just<seclabel> reinvented by another name, so I don't want to see that.
I agree with you, that is just a seclabel reinvented by another name. But the idea here is to keep just a single seclabel exposed by the API (as it's now). So, it would not require changes in virDomainGetSecurityLabel.
Regards, Daniel

On Thu, Feb 23, 2012 at 06:38:45PM -0200, Marcelo Cerri wrote:
On 02/23/2012 05:47 PM, Daniel P. Berrange wrote:
On Thu, Feb 23, 2012 at 05:41:27PM -0200, Marcelo Cerri wrote:
Hi,
I'm starting working on an improvement for libvirt to be able to support per-guest configurable user and group IDs for QEMU processes. Currently, libvirt uses a configurable pair of user and group, which is defined in qemu.conf, for all qemu processes when running in privileged mode.
This topic was already commented in qemu mailing list (http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00758.html) but, as this requires changes in libvirt API, I'd like to discuss what would be the best solution for it.
A solution (as proposed in the link above) would be to extend the security driver model to allow multiple drivers. In this case, an example of the XML definition would be:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> ...
I don't know if this is a clean solution because the usual option would be to enclose the block above in a "<seclabels>" tag. But as this would break the actual API, it's not viable.
While it is true that we would ordinarily have an enclosing tag like<seclabels>, there's no serious problem not having it. Just having two (or more)<seclabel> elements in a row is just fine, given our backwards compatibility requirements.
So I think this option is just fine.
I agree that this is a good solution, considering the XML compatibility. But, what about virDomainGetSecurityLabel? It could access the first security label or ignore the DAC driver (and maybe another function could be added to access the whole list of seclabels), but it doesn't seem to be the best solution.
We can just keep virDomainGetSecurityLabel()/virNodeGetSecurityModel as only ever handling the primary security driver. Then add some new APIs which are more general int virNodeGetSecurityModelCount(virConnectPtr conn); int virNodeGetSecurityModelList(virConnectPtr conn, virSecurityModelPtr models, int nmodels); int virDomainGetSecurityLabelList(virDomainptr dom, virSecuriyLabelptr labels, int nlabels); Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Great. I think it is a good approach. The lack of an enclosing tag still bothers me. But, as you said, there's no serious problem not having it and I can live with that :) I believe the primary driver should be defined in qemu.conf, so I would like to replace the "security_driver" config with two new configs: primary_security_driver and additional_security_drivers. The last one would contain a list of security divers separated by commas, for example: primary_security_driver = "apparmor" additional_security_divers = "dac,another_driver" For device seclabel's, I intend to add a "model" attribute to specify which security driver is being overriding (if it's not given, the primary driver is considered). <domain ...> ... <devices> <disk type='file' device='disk'> <source file='/path/to/image1'> <seclabel relabel='no' model='dac'/> </source> ... </disk> <disk type='file' device='disk'> <source file='/path/to/image2'> <seclabel relabel='yes' model="selinux"> <label> system_u:object_r:shared_content_t:s0 </label> </seclabel> </source> ... </disk> ... </devices> <seclabel type='dynamic' model='selinux'> <baselabel>text</baselabel> </seclabel> <seclabel type='static' model='dac'> <label>501:501</label> <imagelabel>501:501</imagelabel> </seclabel> </domain> What do you think? Regards, Marcelo On 02/23/2012 07:34 PM, Daniel P. Berrange wrote:
On Thu, Feb 23, 2012 at 06:38:45PM -0200, Marcelo Cerri wrote:
On 02/23/2012 05:47 PM, Daniel P. Berrange wrote:
On Thu, Feb 23, 2012 at 05:41:27PM -0200, Marcelo Cerri wrote:
Hi,
I'm starting working on an improvement for libvirt to be able to support per-guest configurable user and group IDs for QEMU processes. Currently, libvirt uses a configurable pair of user and group, which is defined in qemu.conf, for all qemu processes when running in privileged mode.
This topic was already commented in qemu mailing list (http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00758.html) but, as this requires changes in libvirt API, I'd like to discuss what would be the best solution for it.
A solution (as proposed in the link above) would be to extend the security driver model to allow multiple drivers. In this case, an example of the XML definition would be:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> ...
I don't know if this is a clean solution because the usual option would be to enclose the block above in a "<seclabels>" tag. But as this would break the actual API, it's not viable.
While it is true that we would ordinarily have an enclosing tag like<seclabels>, there's no serious problem not having it. Just having two (or more)<seclabel> elements in a row is just fine, given our backwards compatibility requirements.
So I think this option is just fine.
I agree that this is a good solution, considering the XML compatibility. But, what about virDomainGetSecurityLabel? It could access the first security label or ignore the DAC driver (and maybe another function could be added to access the whole list of seclabels), but it doesn't seem to be the best solution.
We can just keep virDomainGetSecurityLabel()/virNodeGetSecurityModel as only ever handling the primary security driver.
Then add some new APIs which are more general
int virNodeGetSecurityModelCount(virConnectPtr conn); int virNodeGetSecurityModelList(virConnectPtr conn, virSecurityModelPtr models, int nmodels); int virDomainGetSecurityLabelList(virDomainptr dom, virSecuriyLabelptr labels, int nlabels);
Regards, Daniel

On Mon, 27 Feb 2012 12:48:55 -0300 Marcelo Cerri <mhcerri@linux.vnet.ibm.com> wrote: Just one more point. I'd like to validate the direction that I'm getting. I updated the XML parse and replaced the "seclabel" member in virDomainDef with: size_t nseclabels; virSecurityLabelDefPtr *seclabels; I also added a "model" field in virSecurityLabelDef to identify the sec driver. So, my idea is to replace any access to the seclabel with a search by the model name. So, for example, instead of using secdef = def->seclabels; I'll use: secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); virDomainDefGetSecurityLabelDef will search for a seclabel with the given model/name. I'm having to update too many parts in the code and I'd like to save some time if this is not the right direction. Regards, Marcelo
Great. I think it is a good approach. The lack of an enclosing tag still bothers me. But, as you said, there's no serious problem not having it and I can live with that :)
I believe the primary driver should be defined in qemu.conf, so I would like to replace the "security_driver" config with two new configs: primary_security_driver and additional_security_drivers. The last one would contain a list of security divers separated by commas, for example:
primary_security_driver = "apparmor" additional_security_divers = "dac,another_driver"
For device seclabel's, I intend to add a "model" attribute to specify which security driver is being overriding (if it's not given, the primary driver is considered).
<domain ...> ... <devices> <disk type='file' device='disk'> <source file='/path/to/image1'> <seclabel relabel='no' model='dac'/> </source> ... </disk> <disk type='file' device='disk'> <source file='/path/to/image2'> <seclabel relabel='yes' model="selinux"> <label> system_u:object_r:shared_content_t:s0 </label> </seclabel> </source> ... </disk> ... </devices> <seclabel type='dynamic' model='selinux'> <baselabel>text</baselabel> </seclabel> <seclabel type='static' model='dac'> <label>501:501</label> <imagelabel>501:501</imagelabel> </seclabel> </domain>
What do you think?
Regards, Marcelo
On 02/23/2012 07:34 PM, Daniel P. Berrange wrote:
On Thu, Feb 23, 2012 at 06:38:45PM -0200, Marcelo Cerri wrote:
On 02/23/2012 05:47 PM, Daniel P. Berrange wrote:
On Thu, Feb 23, 2012 at 05:41:27PM -0200, Marcelo Cerri wrote:
Hi,
I'm starting working on an improvement for libvirt to be able to support per-guest configurable user and group IDs for QEMU processes. Currently, libvirt uses a configurable pair of user and group, which is defined in qemu.conf, for all qemu processes when running in privileged mode.
This topic was already commented in qemu mailing list (http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00758.html) but, as this requires changes in libvirt API, I'd like to discuss what would be the best solution for it.
A solution (as proposed in the link above) would be to extend the security driver model to allow multiple drivers. In this case, an example of the XML definition would be:
... <seclabel type='dynamic' model='selinux'> <label>system_u:system_r:svirt_t:s0:c633,c712</label> <imagelabel>system_u:object_r:svirt_image_t:s0:c633,c712</imagelabel> </seclabel> <seclabel type='dynamic' model='dac'> <label>102:102</label> <imagelabel>102:102</imagelabel> </seclabel> ...
I don't know if this is a clean solution because the usual option would be to enclose the block above in a "<seclabels>" tag. But as this would break the actual API, it's not viable.
While it is true that we would ordinarily have an enclosing tag like<seclabels>, there's no serious problem not having it. Just having two (or more)<seclabel> elements in a row is just fine, given our backwards compatibility requirements.
So I think this option is just fine.
I agree that this is a good solution, considering the XML compatibility. But, what about virDomainGetSecurityLabel? It could access the first security label or ignore the DAC driver (and maybe another function could be added to access the whole list of seclabels), but it doesn't seem to be the best solution.
We can just keep virDomainGetSecurityLabel()/virNodeGetSecurityModel as only ever handling the primary security driver.
Then add some new APIs which are more general
int virNodeGetSecurityModelCount(virConnectPtr conn); int virNodeGetSecurityModelList(virConnectPtr conn, virSecurityModelPtr models, int nmodels); int virDomainGetSecurityLabelList(virDomainptr dom, virSecuriyLabelptr labels, int nlabels);
Regards, Daniel
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Wed, Mar 07, 2012 at 02:35:38PM -0300, Marcelo Henrique Cerri wrote:
On Mon, 27 Feb 2012 12:48:55 -0300 Marcelo Cerri <mhcerri@linux.vnet.ibm.com> wrote:
Just one more point. I'd like to validate the direction that I'm getting.
I updated the XML parse and replaced the "seclabel" member in virDomainDef with:
size_t nseclabels; virSecurityLabelDefPtr *seclabels;
I also added a "model" field in virSecurityLabelDef to identify the sec driver. So, my idea is to replace any access to the seclabel with a search by the model name. So, for example, instead of using
secdef = def->seclabels;
I'll use:
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
virDomainDefGetSecurityLabelDef will search for a seclabel with the given model/name.
I'm having to update too many parts in the code and I'd like to save some time if this is not the right direction.
I think this sounds like a reasonable approach to me. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
Marcelo Cerri
-
Marcelo Henrique Cerri