<div dir="ltr">Daniel,<div>We have addressed the comments you had provided. The patch rebased to 1.3.4 is attached. Appreciate you taking the time to review it.<br><div class="gmail_extra"><br clear="all"><div><div data-smartmail="gmail_signature">raghuram</div></div>
<br><div class="gmail_quote">On Tue, May 10, 2016 at 4:15 AM, Daniel P. Berrange <span dir="ltr"><<a href="mailto:berrange@redhat.com" target="_blank">berrange@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>On Thu, Apr 14, 2016 at 07:47:23PM +0000, Randy Aybar (raybar) wrote:<br>
> First time RFC/mailing list/community submission/etc. so please<br>
> forgive if not in the appropriate format.<br>
<br>
</span>Thanks for taking the time to submit this, and sorry for not giving<br>
feedback on it sooner. Next time feel free to send "ping" responses<br>
if you've not had feedback on a patch after a week or so and you<br>
want to remind people!<br>
<span><br>
<br>
> I. Introduction<br>
><br>
> Libvirt currently has support for two of the various Linux security modules<br>
> (LSM), AppArmor and SELinux. While these work well enough for most cases, there<br>
> are others in which a platform may require less complexity and overhead.<br>
><br>
> Smack LSM (<a href="http://schaufler-ca.com/description_from_the_linux_source_tree" rel="noreferrer" target="_blank">http://schaufler-ca.com/description_from_the_linux_source_tree</a>)<br>
> intrinsically provides access control with much more simplicity while<br>
> remaining secure. A subject-object model is adapted with an access type<br>
> relationship to determine if permissions or granted or denied.<br>
<br>
</span>Yep, we're more than happy to accept patches to support any LSM module<br>
that is in the mainline kernel tree, as we're aware not everyone uses<br>
SELinux / AppArmor<br>
<span><br>
> Initial findings on the topic yielded us to a research paper worked on by<br>
> students at Beijing University of Posts and Telecommunications. As part of the<br>
> paper's objective to create a lightweight approach to secure deployment of<br>
> virtual machines in the cloud, a Smack security driver was implemented for use<br>
> with QEMU-based virtual machines spawned by using the Libvirt API. After<br>
> contacting the authors of the papers, they were more than willing to share the<br>
> source code.<br>
<br>
</span>'sharing the source code' can mean many different things to different<br>
people. Can you just confirm explicitly that they gave their permission<br>
for their contributions being licensed under the "LGPLv2.1 or later"<br>
which libvirt uses.<br></blockquote>







<p><font color="#ff0000"><span>I can confirm that the intent of the authors from BUPT (who wrote an initial version </span>of the smack driver for 1.1.4) is to upstream the code. However, they did not do it for various reasons. Their contributions are included in the copyright header of all files. They are also ‘cced and can explicitly state their intent if required. </font></p><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<span>







<p>> The Smack driver was initially derived from parts of the SELinux<br></p>
> and AppArmor drivers as noted by the authors and uses the Libsmack library to<br>
> assign Smack labels when needed.<br>
<br>
</span>Ok, libsmack.so is under the LGPLv2.1 which should be ok.<br>
<span><br>
> Another thing to note is that the Smack security driver itself depends on a security<br>
> interface when fully enforced with namespaces. This interface is brought in<br>
> by the Linux kernel in 4.3 but our team has backported and tested Libvirt with version<br>
> 3.19 kernel. Details on why this was necessary found below in LXC container<br>
> changes. Link that references the change in the kernel:<br>
><br>
> <a href="https://lwn.net/Articles/660675/" rel="noreferrer" target="_blank">https://lwn.net/Articles/660675/</a><br>
<br>
</span>Ok, we should probably document that security requirement, probably in the<br>
docs/<a href="http://drvlxc.html.in" rel="noreferrer" target="_blank">drvlxc.html.in</a> file.<br>
<span><br></span></blockquote>







<div><font color="#ff0000">Updated docs/<a href="http://drvlxc.html.in" target="_blank">drvlxc.html.in</a> with the above note</font></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>
> i. LXC Container (src/lxc/lxc_container.c)<br>
><br>
> a. Reordering of dropping capabilities and setting up security labeling<br>
><br>
> Upon forking into a new user namespace (lxcContainerSetID), the child process no<br>
> longer has the ability to override LSM and access folders that have been previously assigned<br>
> Smack labels. This is important to note since after entering the namespace, the child<br>
> still needs to share mount devpts and pivot root however the process does not<br>
> take on the container's label until much after this setup. Thus a suggestion to<br>
> move the set process label (virSecurityManagerSetProcessLabel) after setting namespaces is made.<br>
><br>
> Dropping capabilities was also moved after sending the continue signal to the<br>
> parent. We had come across an issue as well with setting up FDs and the<br>
> container would fail to start.<br>
<br>
</span>Yep that's fine - there's no particular reason for the current ordering - its<br>
just historically chosen.<br>
<span><br>
><br>
> b. Adding a call to set the child's process label (virSecurityManagerSetChildProcessLabel)<br>
><br>
> When the child process is spawned from lxcContainerStart, although it has full<br>
> capabilities in its own namespace (after SetUID), it is unable to change its own security<br>
> context (label). Currently the only workaround is to incorporate an<br>
> upcoming patch to the Smack LSM (kernel base) that allows an unprivileged<br>
> process to change its context only if the label its trying to acquire exists in<br>
> a predefined list held by the parent.<br>
><br>
> With the patch in place, the LXC driver needs to ensure that the label makes it<br>
> to the list of the parent so that the child can continue to take on the context<br>
> which brings a change to lxcContainerStart.<br>
><br>
> Although the SetChildProcessLabel is a hook that is primarily used by QEMU, we<br>
> decided to use it as the name best fit the operation being performed.<br>
> A check is implemented to ensure that it only continues if Smack is the driver<br>
> being used since this does not need to occur in the other LSMs.<br>
><br>
> Within the Smack driver itself, the hook also performs a check to see if LXC is<br>
> used otherwise skip the block pertaining to LXC. In the LXC code, it checks<br>
> to see if the Smack relabel-self interface exists and if namespaces is being<br>
> used to continue. The label is written with a simple write call to the file. The<br>
> logic is allowed to flow into the QEMU portion since no command is passed in,<br>
> the function acts as a noop and safely exits.<br>
><br>
> Any comments for improvement on the logic handled in this change are highly<br>
> appreciated!<br>
<br>
</span>So you moved the cal to SetProcessLabel to quite early in the<br>
lxcContainerChild() method, and then added a second call to<br>
SetChildProcessLabel right before virCommandExec().<br>
<br>
With SELinux there's no functional difference between the<br>
SetProcessLabel and SetChildProcessLabel - both end up<br>
calling setexeccon_raw() which tells SELinux to change the<br>
label when execve() is called.<br>
<br>
There might be a difference for AppArmor, but if there is,<br>
I wouldn't be surprised if it doesn't matter.<br>
<br>
IOW, I think we can probably just remove the SetProcessLabel<br>
call entirely, and only ever call SetChildProcessLabel<br>
for all drivers.<br>
<span><br></span></blockquote>







<p><font color="#ff0000"><span>For SMACK, if we remove SetProcessLabel the init process of the container </span><span>does not get labelled and hence the container won’t stand up properly. So we </span>had to leave that in. </font></p><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>
<br>
> ii. LXC Controller (src/lxc/lxc_controller.c)<br>
><br>
> a. Add logic to label the special devices created under<br>
> (/var/run/libvirt/lxc/container.XXX)<br>
><br>
> The following function calls setup the appropriate special devices such as<br>
> ttys, ptmx, null, etc. (/dev)<br>
><br>
> virLXCControllerSetupDev<br>
> virLXCControllerPopulateDevices<br>
> virLXCControllerSetupDevPTS<br>
> virLXCControllerSetupConsoles<br>
><br>
> It was decided to add the call to do a label operation in these functions due to<br>
> the fact that chown'ing also happened at these locations and wanted to provide<br>
> some uniformity in that sense. Since the security hook to label these are no-op<br>
> in all but the Smack driver it's just a straightforward call with the usual<br>
> check to see if it succeeded.<br>
<br>
</span>Yep, that makes sense.<br>
<span><br>
> iii. Security Drivers (src/security)<br>
><br>
> Changes to security driver model include an additional hook to apply a security<br>
> label by passing in a string. Although there exists functions made for applying<br>
> security labels, complications arose from using either.<br>
><br>
> The first of these is SetImageLabel which requires to pass in a virStorageSource<br>
> that holds the string. LXC does not make use of this data structure and<br>
> initializing one for the sake of a string did not seem feasible due to the<br>
> numerous and differing members the struct consisted of.<br>
<br>
</span>Agreed.<br>
<div><div><br>
> The second function major function to apply security labels is SetImageFDLabel<br>
> which uses a file descriptor rather than a string text. While this approach<br>
> seemed more promising there were hurdles that came across while attempting to<br>
> label items. A file descriptor would be needed to be opened for each special<br>
> device available. However devices like tty could not be opened without being<br>
> issued as a controlling tty by the process. Note that a workaround was attempted<br>
> to change the open call to include the O_PATH flag and obtain the path by looking up the<br>
> location the FD pointed to in the process's list of file descriptors within<br>
> /proc. While this change worked for the tty case, it was dismissed due to the<br>
> additional changes that may have been needed to the other security drivers as we<br>
> were targeting to minimize the changes. This solution may be revisited upon further<br>
> testing and review.<br>
><br>
> a. Update Definitions for DAC, Stack, AppArmor, SELinux, Smack,<br>
> driver base (security_driver.h), and driver manager (security_manager.c,h)<br>
><br>
> Changes here involve updated the driver's definitions to include the new hook,<br>
> virSecurityDomainSetImagePathLabel. All drivers except Smack implement this by<br>
> just returning 0 to not disrupt the flow in a non-Smack setup.<br>
><br>
> b. Updates to Smack driver to support namespaces with LXC<br>
><br>
> Already described include changes to implement the extra hook to label a file<br>
> using a path as well as SetChildProcessLabel wihthin the driver to<br>
> include the process of adding a label to the approved list via relabel-self.<br>
><br>
> The driver itself was cleaned up a bit and refactored to eliminate the use of<br>
> excessive amount of helper functions and rely on the API provided by the<br>
> libsmack library. Function names were refactored to match the style of the<br>
> SELinux driver (after the dropping of an extra "Security" in the function's<br>
> name).<br>
><br>
> iv. Support for entering namespaces in Smack (src/libvirt-lxc.c)<br>
><br>
> A small addition was made to enable support for Smack using the<br>
> lxc-enter-namespace and was merely a mirror of the other security drivers<br>
> included in this file. Smack in this case uses libsmack API call to label the<br>
> process entering the namespace.<br>
<br>
</div></div><span>> This patch has been created for patching Libvirt 1.3.1 base source code.<br>
<br>
</span>Generally we like to have patches created against current GIT master<br>
revision. Could you rebase to master when addressing feedback.<br>
<div><div><br></div></div></blockquote>







<div><font color="#ff0000">The patch rebased to 1.3.4 is pasted at the end of this thread. It is also attached for better readability.</font></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div><div>
> diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> index 047ad3b..12d0bb8 100644<br>
> --- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> @@ -253,6 +253,7 @@ LIBVIRT_CHECK_READLINE<br>
>  LIBVIRT_CHECK_SANLOCK<br>
>  LIBVIRT_CHECK_SASL<br>
>  LIBVIRT_CHECK_SELINUX<br>
> +LIBVIRT_CHECK_SMACK<br>
>  LIBVIRT_CHECK_SSH2<br>
>  LIBVIRT_CHECK_SYSTEMD_DAEMON<br>
>  LIBVIRT_CHECK_UDEV<br>
> @@ -1535,6 +1536,27 @@ if test "$with_apparmor" = "no"; then<br>
>  fi<br>
>  AM_CONDITIONAL([WITH_APPARMOR_PROFILES], [test "$with_apparmor_profiles" != "no"])<br>
><br>
> +AC_ARG_WITH([secdriver-smack],<br>
> +  [AS_HELP_STRING([--with-secdriver-smack],<br>
> +    [use Smack security driver @<:@default=check@:>@])],<br>
> +  [],<br>
> +  [with_secdriver_smack=check])<br>
> +<br>
> +if test "$with_smack" != "yes" ; then<br>
> +  if test "$with_secdriver_smack" = "check" ; then<br>
> +    with_secdriver_smack=no<br>
> +  fi<br>
> +  if test "$with_secdriver_smack" != "no" ; then<br>
> +    AC_MSG_ERROR([You must install the Smack development package in order to compile libvirt])<br>
> +  fi<br>
> +elif test "with_secdriver_smack" != "no" ; then<br>
> +  with_secdriver_smack=yes<br>
> +  AC_DEFINE_UNQUOTED([WITH_SECDRIVER_SMACK], 1, [whether Smack security driver is available])<br>
> +fi<br>
> +AM_CONDITIONAL([WITH_SECDRIVER_SMACK], [test "$with_secdriver_smack" != "no"])<br>
<br>
</div></div>I realize you just copied existing pattern for apparmor, but<br>
could you ignore that existing pattern, and just move this<br>
block of code into the LIBVIRT_CHECK_SMACK fnuction you<br>
created too.<br>
<span><br>
<br>
> +AC_DEFUN([LIBVIRT_CHECK_SMACK],[<br>
> +  LIBVIRT_CHECK_LIB([SMACK], [smack],<br>
> +                    [smack_set_label_for_self], [sys/smack.h])<br>
> +<br>
> +  AC_ARG_WITH([smack_mount],<br>
> +    [AS_HELP_STRING([--with-smack-mount],<br>
> +      [set Smack mount point @<:@default=check@:>@])],<br>
> +    [],<br>
> +    [with_smack_mount=check])<br>
> +<br>
> +  if test "$with_smack" = "yes"; then<br>
> +    AC_MSG_CHECKING([Smack mount point])<br>
> +    if test "$with_smack_mount" = "check" || test -z "$with_smack_mount"; then<br>
> +      if test -d /sys/fs/smackfs ; then<br>
> +        SMACK_MOUNT=/sys/fs/smackfs<br>
> +      else<br>
> +        SMACK_MOUNT=/smack<br>
> +      fi<br>
<br>
</span>Do any distros exist which use /smack as a path - I know that<br>
/selinux was used in Fedora/RHEL for a long time, but now<br>
uses /sys/fs/selinux.  If we don't need to support /smack<br>
we should just fix /sys/fs/smackfs as the standard location<br>
<span><br>
<br>
> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c<br>
> index c5a70a1..71203aa 100644<br>
> --- a/src/lxc/lxc_container.c<br>
> +++ b/src/lxc/lxc_container.c<br>
</span><span>> @@ -2206,6 +2209,10 @@ static int lxcContainerChild(void *data)<br>
>      if (lxcContainerSetID(vmDef) < 0)<br>
>          goto cleanup;<br>
><br>
> +    VIR_DEBUG("Setting up security labeling");<br>
> +    if (virSecurityManagerSetProcessLabel(argv->securityDriver, vmDef) < 0)<br>
> +        goto cleanup;<br>
> +<br>
<br>
</span>As mentioned earlier, I think you can just drop this....<br>
<div><div><br>
>      root = virDomainGetFilesystemForTarget(vmDef, "/");<br>
><br>
>      if (argv->nttyPaths) {<br>
> @@ -2254,20 +2261,12 @@ static int lxcContainerChild(void *data)<br>
>          goto cleanup;<br>
>      }<br>
><br>
> -    /* drop a set of root capabilities */<br>
> -    if (lxcContainerDropCapabilities(vmDef, !!hasReboot) < 0)<br>
> -        goto cleanup;<br>
> -<br>
>      if (lxcContainerSendContinue(argv->handshakefd) < 0) {<br>
>          virReportSystemError(errno, "%s",<br>
>                              _("Failed to send continue signal to controller"));<br>
>          goto cleanup;<br>
>      }<br>
><br>
> -    VIR_DEBUG("Setting up security labeling");<br>
> -    if (virSecurityManagerSetProcessLabel(argv->securityDriver, vmDef) < 0)<br>
> -        goto cleanup;<br>
> -<br>
>      VIR_DEBUG("Setting up inherited FDs");<br>
>      VIR_FORCE_CLOSE(argv->handshakefd);<br>
>      VIR_FORCE_CLOSE(argv->monitor);<br>
> @@ -2275,6 +2274,10 @@ static int lxcContainerChild(void *data)<br>
>                               argv->npassFDs, argv->passFDs) < 0)<br>
>          goto cleanup;<br>
><br>
> +    /* drop a set of root capabilities */<br>
> +    if (lxcContainerDropCapabilities(vmDef, !!hasReboot) < 0)<br>
> +        goto cleanup;<br>
> +<br>
>      ret = 0;<br>
>   cleanup:<br>
>      VIR_FREE(ttyPath);<br>
> @@ -2389,6 +2392,16 @@ int lxcContainerStart(virDomainDefPtr def,<br>
>          if (userns_supported()) {<br>
>              VIR_DEBUG("Enable user namespace");<br>
>              cflags |= CLONE_NEWUSER;<br>
> +#ifdef WITH_SMACK<br>
> +            if(STREQ(virSecurityManagerGetModel(securityDriver),"smack") &&<br>
> +               virSecurityManagerSetChildProcessLabel(securityDriver,<br>
> +                                                      def,<br>
> +                                                      NULL) < 0) {<br>
<br>
</div></div>And remove the check for GetModel() == "smack" - just let all drivers<br>
use this codepath - though it would hae to be outside the userns_supported()<br>
check<br>
<span><br>
> +                   virReportError(VIR_ERR_INTERNAL_ERROR,<br>
> +                               _("Failed to send label to relabel interface."));<br>
> +                   return -1;<br>
> +             }<br>
> +#endif<br>
>          } else {<br>
>              virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",<br>
>                             _("Kernel doesn't support user namespace"));<br>
<br>
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c<br>
> index 438103a..37080b8 100644<br>
> --- a/src/lxc/lxc_controller.c<br>
> +++ b/src/lxc/lxc_controller.c<br>
<br>
</span><span>> @@ -1476,6 +1479,9 @@ static int virLXCControllerSetupDev(virLXCControllerPtr ctrl)<br>
><br>
>      if (lxcContainerChown(ctrl->def, dev) < 0)<br>
>          goto cleanup;<br>
> +<br>
> +    if (virSecurityManagerSetImagePathLabel(ctrl->securityManager,ctrl->def,dev) < 0)<br>
> +        goto cleanup;<br>
<br>
</span>BTW, there should always be a space after a ',' in an argument list.<br>
If you run 'make syntax-check' it should warn you about style mistakes<br>
like this.<br>
<span><br>
<br>
><br>
>      ret = 0;<br>
>   cleanup:<br>
> @@ -1525,6 +1531,11 @@ static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl)<br>
>          if (lxcContainerChown(ctrl->def, path) < 0)<br>
>              goto cleanup;<br>
><br>
> +        if (virSecurityManagerSetImagePathLabel(ctrl->securityManager,<br>
> +                                                ctrl->def,<br>
> +                                                path) < 0)<br>
> +            goto cleanup;<br>
> +<br>
>          VIR_FREE(path);<br>
>      }<br>
><br>
> @@ -2183,6 +2194,14 @@ virLXCControllerSetupDevPTS(virLXCControllerPtr ctrl)<br>
>          (lxcContainerChown(ctrl->def, devpts) < 0))<br>
>          goto cleanup;<br>
><br>
> +    if ((virSecurityManagerSetImagePathLabel(ctrl->securityManager,<br>
> +                                        ctrl->def,<br>
> +                                        ctrl->devptmx)) < 0 ||<br>
<br>
</span>This has for whitespace at the end of lines - again just run<br>
'make syntax-check' and fix any problems it reports. Generally<br>
you want to align parameters on each line with the '('<br>
<div><div><br>
<br>
<br>
<br>
> diff --git a/src/security/security_smack.c b/src/security/security_smack.c<br>
> new file mode 100644<br>
> index 0000000..50301ad<br>
> --- /dev/null<br>
> +++ b/src/security/security_smack.c<br>
> @@ -0,0 +1,1519 @@<br>
> +/*<br>
> + * Copyright (C) 2015 Cisco Systems, Inc.<br>
> + *<br>
> + * This library is free software; you can redistribute it and/or<br>
> + * modify it under the terms of the GNU Lesser General Public<br>
> + * License as published by the Free Software Foundation; either<br>
> + * version 2.1 of the License, or (at your option) any later version.<br>
> + *<br>
> + * This library is distributed in the hope that it will be useful,<br>
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
> + * Lesser General Public License for more details.<br>
> + *<br>
> + * You should have received a copy of the GNU Lesser General Public<br>
> + * License along with this library.  If not, see<br>
> + * <<a href="http://www.gnu.org/licenses/" rel="noreferrer" target="_blank">http://www.gnu.org/licenses/</a>>.<br>
> + *<br>
> + * Author:<br>
> + *   Hongliang Liang <<a href="mailto:hliang@bupt.edu.cn" target="_blank">hliang@bupt.edu.cn</a>><br>
> + *   Changyao Han <<a href="mailto:changyao@bupt.edu.cn" target="_blank">changyao@bupt.edu.cn</a>><br>
> + *<br>
> + * Updated to libvirt v1.2.15: (Original was written for libvirt v1.1.4)<br>
> + *   Raghuram S. Sudhaakar <<a href="mailto:rsudhaak@cisco.com" target="_blank">rsudhaak@cisco.com</a>><br>
> + *   Randy Aybar <<a href="mailto:raybar@cisco.com" target="_blank">raybar@cisco.com</a>><br>
> + *<br>
> + *   Based on security_selinux.c by James Morris <<a href="mailto:jmorris@namei.org" target="_blank">jmorris@namei.org</a>><br>
> + *   and security_apparmor.c by Jamie Strandboge <<a href="mailto:jamie@canonical.com" target="_blank">jamie@canonical.com</a>><br>
> + *<br>
> + *   Smack scurity driver.<br>
> + *<br>
> + */<br>
<br>
<br>
</div></div><span>> +static int<br>
> +virSecuritySmackGetPIDLabel(pid_t pid, char **label)<br>
> +{<br>
> +<br>
> +      char *result;<br>
> +      int fd;<br>
> +      int ret;<br>
> +      char *path;<br>
> +<br>
> +      result = calloc(SMACK_LABEL_LEN + 1, 1);<br>
> +      if (result == NULL)<br>
> +               return -1;<br>
<br>
</span>Use of 'calloc' / 'malloc' / 'free' etc is not allowed in<br>
libvirt - use VIR_ALLOC, VIR_FREE, etc<br>
<br>
   <a href="http://libvirt.org/hacking.html#memalloc" rel="noreferrer" target="_blank">http://libvirt.org/hacking.html#memalloc</a><br>
<br>
<br>
Also, please only indent lines by 4 spaces at a time - not 8.<br>
<br>
There's tips here on how to configure emacs or vim to indent<br>
correctly for libvirt:<br>
<br>
   <a href="http://libvirt.org/hacking.html#indent" rel="noreferrer" target="_blank">http://libvirt.org/hacking.html#indent</a><br>
<span><br>
> +      ret = virAsprintf(&path, "/proc/%d/attr/current", pid);<br>
> +      if (ret < 0)<br>
> +               return -1;<br>
> +      fd = open(path, O_RDONLY);<br>
> +      VIR_FREE(path);<br>
> +      if (fd < 0) {<br>
> +               free(result);<br>
> +               return -1;<br>
> +      }<br>
> +      ret = read(fd, result, SMACK_LABEL_LEN);<br>
> +      VIR_FORCE_CLOSE(fd);<br>
> +      if (ret < 0) {<br>
> +               free(result);<br>
> +               return -1;<br>
> +      }<br>
> +      *label = result;<br>
> +      return ret;<br>
> +<br>
> +}<br>
<br>
</span>You could replace the open/read/close code here with a simple<br>
virFileReadAll() call.<br>
<div><div><br>
> +int<br>
> +virSecuritySmackSockCreate(const char *label, const char *attr)<br>
> +{<br>
> +      int fd;<br>
> +      int ret = -1;<br>
> +      long int tid;<br>
> +      char *path;<br>
> +      tid = syscall(SYS_gettid);<br>
> +      VIR_DEBUG("/proc/self/task/%ld/attr/%s", tid, attr);<br>
> +      ret = virAsprintf(&path, "/proc/self/task/%ld/attr/%s", tid, attr);<br>
> +      if (ret < 0)<br>
> +               return -1;<br>
> +<br>
> +      VIR_DEBUG("virSecuritySmackSockCreate pid is in %d", getpid());<br>
> +      VIR_DEBUG("real user ID is in %d", getuid());<br>
> +      VIR_DEBUG("effective user ID is in %d", geteuid());<br>
> +      VIR_DEBUG("label from self %s", label);<br>
> +      VIR_DEBUG("location /proc/self/attr/%s", attr);<br>
> +<br>
> +      if (label) {<br>
> +               fd = open(path, O_WRONLY | O_CLOEXEC);<br>
> +               VIR_DEBUG("open file %s", path);<br>
> +               VIR_FREE(path);<br>
> +               if (fd < 0) {<br>
> +                             VIR_DEBUG("open fail");<br>
> +                             return -1;<br>
> +               }<br>
> +               VIR_DEBUG("open success");<br>
> +               do {<br>
> +                             ret = write(fd, label, strlen(label) + 1);<br>
> +               } while (ret < 0 && errno == EINTR);<br>
<br>
</div></div>You can use virFileWriteStr() to write a string to a file.<br>
<span><br>
> +      }<br>
> +      else {<br>
> +               fd = open(path, O_TRUNC);<br>
> +               VIR_FREE(path);<br>
> +               if (fd < 0)<br>
> +                             return -1;<br>
> +               ret = 0;<br>
> +      }<br>
> +<br>
> +      close(fd);<br>
<br>
</span>Use VIR_CLOSE or VIR_FORCE_CLOSE<br>
<span><br>
> +<br>
> +      return (ret < 0) ? -1 : 0;<br>
> +<br>
> +}<br>
> +<br>
<br>
<br>
<br>
</span>Broadly speaking this looks like a reasonable design. Biggest thing todo<br>
is rebase to current git master & run 'make syntax-check' to fix all<br>
the problems it shows, as that'll make it nicer to review again.<br>
<br>
Regards,<br>
Daniel<br>
<span><font color="#888888">--<br>
|: <a href="http://berrange.com" rel="noreferrer" target="_blank">http://berrange.com</a>      -o-    <a href="http://www.flickr.com/photos/dberrange/" rel="noreferrer" target="_blank">http://www.flickr.com/photos/dberrange/</a> :|<br>
|: <a href="http://libvirt.org" rel="noreferrer" target="_blank">http://libvirt.org</a>              -o-             <a href="http://virt-manager.org" rel="noreferrer" target="_blank">http://virt-manager.org</a> :|<br>
|: <a href="http://autobuild.org" rel="noreferrer" target="_blank">http://autobuild.org</a>       -o-         <a href="http://search.cpan.org/~danberr/" rel="noreferrer" target="_blank">http://search.cpan.org/~danberr/</a> :|<br>
|: <a href="http://entangle-photo.org" rel="noreferrer" target="_blank">http://entangle-photo.org</a>       -o-       <a href="http://live.gnome.org/gtk-vnc" rel="noreferrer" target="_blank">http://live.gnome.org/gtk-vnc</a> :|<br>
</font></span></blockquote></div><br></div><div class="gmail_extra"><br></div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">I+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackRestoreDiskLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          virDomainDiskDefPtr disk)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     return virSecuritySmackRestoreImageLabelInt(mgr, def, disk->src, false);</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetImageLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          virStorageSourcePtr src)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!seclabel->relabel)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (src->type == VIR_STORAGE_TYPE_NETWORK)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("set disk image security label before");</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (setxattr(src->path, "security.SMACK64", seclabel->imagelabel,</div><div class="gmail_extra">+                    strlen(seclabel->imagelabel) + 1, 0) < 0)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("disk image %s", src->path);</div><div class="gmail_extra">+     VIR_DEBUG("set disk image security label after");</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackRestoreImageLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          virStorageSourcePtr src)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     return virSecuritySmackRestoreImageLabelInt(mgr, def, src, false);</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetDaemonSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+                                                virDomainDefPtr vm)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+</div><div class="gmail_extra">+    return 0;</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+     char *label = NULL;</div><div class="gmail_extra">+     int ret = -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(vm, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->label == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label driver mismatch: "</div><div class="gmail_extra">+                          "'%s' model configured for domain, but "</div><div class="gmail_extra">+                          "hypervisor driver is '%s'."),</div><div class="gmail_extra">+                     seclabel->model, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (smack_new_label_from_self(&label) == -1) {</div><div class="gmail_extra">+          virReportSystemError(errno,</div><div class="gmail_extra">+                     _("unable to get current process context '%s'"), seclabel->label);</div><div class="gmail_extra">+          goto done;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("SmackSetSecurityDaemonSocketLabel is in %d", getpid());</div><div class="gmail_extra">+     VIR_DEBUG("label from self %s", label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (virSecuritySmackSockCreate(label, "sockincreate") == -1) {</div><div class="gmail_extra">+          virReportSystemError(errno,</div><div class="gmail_extra">+                     _("unable to set socket smack label '%s'"), seclabel->label);</div><div class="gmail_extra">+          goto done;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     ret = 0;</div><div class="gmail_extra">+ done:</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_FREE(label);</div><div class="gmail_extra">+     return ret;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr vm)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+    return 0;</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(vm, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->label == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label driver mismatch: "</div><div class="gmail_extra">+                          "'%s' model configured for domain, but "</div><div class="gmail_extra">+                          "hypervisor driver is '%s'."),</div><div class="gmail_extra">+                     seclabel->model, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("Setting VM %s socket label %s", vm->name, seclabel->label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (virSecuritySmackSockCreate(seclabel->label, "sockoutcreate") == -1) {</div><div class="gmail_extra">+          virReportSystemError(errno,</div><div class="gmail_extra">+                     _("unable to set socket smack label '%s'"),</div><div class="gmail_extra">+                     seclabel->label);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+    return 0;</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->label == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label driver mismatch: "</div><div class="gmail_extra">+                          "'%s' model configured for domain, but "</div><div class="gmail_extra">+                          "hypervisor driver is '%s'."),</div><div class="gmail_extra">+                     seclabel->model, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("clear sock label");</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (virSecuritySmackSockCreate(NULL, "sockincreate") == -1 ||</div><div class="gmail_extra">+            virSecuritySmackSockCreate(NULL, "sockoutcreate") == -1) {</div><div class="gmail_extra">+          virReportSystemError(errno,</div><div class="gmail_extra">+                     _("unable to clear socket smack label '%s'"),</div><div class="gmail_extra">+                     seclabel->label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+/*</div><div class="gmail_extra">+*Current called in qemuStartVMDaemon to setup a 'label'. We make the</div><div class="gmail_extra">+*label based on UUID.</div><div class="gmail_extra">+*this is called on 'start'with RestoreSecurityLabel being called on</div><div class="gmail_extra">+*shutdown</div><div class="gmail_extra">+ */</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackGenLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">+          virDomainDefPtr def)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     int ret = -1;</div><div class="gmail_extra">+     char *label_name = NULL;</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return ret;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("label=%s", virSecurityManagerGetDriver(mgr));</div><div class="gmail_extra">+     if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&</div><div class="gmail_extra">+                seclabel->label) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR, "%s",</div><div class="gmail_extra">+                     _("security label already defined for VM"));</div><div class="gmail_extra">+          return ret;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->imagelabel) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR, "%s",</div><div class="gmail_extra">+                     _("security image label already defined for VM"));</div><div class="gmail_extra">+          return ret;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->model &&</div><div class="gmail_extra">+                STRNEQ(seclabel->model, SECURITY_SMACK_NAME)) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label model %s is not supported with smack"),</div><div class="gmail_extra">+                     seclabel->model);</div><div class="gmail_extra">+          return ret;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("type=%d", seclabel->type);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if ((label_name = virSecuritySmackGetLabelName(def)) == NULL)</div><div class="gmail_extra">+          return ret;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {</div><div class="gmail_extra">+</div><div class="gmail_extra">+          /*set process label*/</div><div class="gmail_extra">+          if (VIR_STRDUP(seclabel->label, label_name) < 0)</div><div class="gmail_extra">+                goto cleanup;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     /*set imagelabel the same as label*/</div><div class="gmail_extra">+     if (VIR_STRDUP(seclabel->imagelabel, label_name) < 0)</div><div class="gmail_extra">+          goto cleanup;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!seclabel->model &&</div><div class="gmail_extra">+                VIR_STRDUP(seclabel->model, SECURITY_SMACK_NAME) < 0)</div><div class="gmail_extra">+          goto cleanup;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     ret = 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+ cleanup:</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (ret != 0) {</div><div class="gmail_extra">+          if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC)</div><div class="gmail_extra">+                VIR_FREE(seclabel->label);</div><div class="gmail_extra">+          VIR_FREE(seclabel->imagelabel);</div><div class="gmail_extra">+          if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&</div><div class="gmail_extra">+                     !seclabel->baselabel)</div><div class="gmail_extra">+                VIR_FREE(seclabel->model);</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_FREE(label_name);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("model=%s label=%s imagelabel=%s",</div><div class="gmail_extra">+                NULLSTR(seclabel->model),</div><div class="gmail_extra">+                NULLSTR(seclabel->label),</div><div class="gmail_extra">+                NULLSTR(seclabel->imagelabel));</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return ret;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          pid_t pid ATTRIBUTE_UNUSED)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     /*Security label is based UUID,*/</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+/*</div><div class="gmail_extra">+*Called on VM shutdown and destroy.</div><div class="gmail_extra">+*/</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {</div><div class="gmail_extra">+          VIR_FREE(seclabel->label);</div><div class="gmail_extra">+          VIR_FREE(seclabel->model);</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+     VIR_FREE(seclabel->imagelabel);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+/* Seen with 'virsh dominfo <vm>'. This function only called if the VM is</div><div class="gmail_extra">+* running.</div><div class="gmail_extra">+*/</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          pid_t pid,</div><div class="gmail_extra">+          virSecurityLabelPtr sec)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+</div><div class="gmail_extra">+     char *label_name = NULL;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (virSecuritySmackGetPIDLabel(pid, &label_name) == -1) {</div><div class="gmail_extra">+          virReportSystemError(errno,</div><div class="gmail_extra">+                     _("unable to get PID %d security label"),</div><div class="gmail_extra">+                     pid);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (strlen(label_name) >= VIR_SECURITY_LABEL_BUFLEN) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label exceeds "</div><div class="gmail_extra">+                          "maximum length: %d"),</div><div class="gmail_extra">+                     VIR_SECURITY_LABEL_BUFLEN - 1);</div><div class="gmail_extra">+          VIR_FREE(label_name);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     label_name = virStrcpy(sec->label, label_name, VIR_SECURITY_LABEL_BUFLEN);</div><div class="gmail_extra">+     VIR_FREE(label_name);</div><div class="gmail_extra">+     /*Smack default enforced*/</div><div class="gmail_extra">+     sec->enforcing = 1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return label_name == NULL ? -1 : 0;</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->label == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (STRNEQ(SECURITY_SMACK_NAME, seclabel->model)) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label driver mismatch: "</div><div class="gmail_extra">+                          "\'%s\' model configured for domain, but "</div><div class="gmail_extra">+                          "hypervisor driver is \'%s\'."),</div><div class="gmail_extra">+                     seclabel->model, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (smack_set_label_for_self(seclabel->label) < 0) {</div><div class="gmail_extra">+          virReportError(errno,</div><div class="gmail_extra">+                     _("unable to set security label '%s'"),</div><div class="gmail_extra">+                     seclabel->label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetChildProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          virCommandPtr cmd)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+    int rlbl;</div><div class="gmail_extra">+     char *smackfs_path = NULL;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->label == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (STRNEQ(SECURITY_SMACK_NAME, seclabel->model)) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("security label driver mismatch: "</div><div class="gmail_extra">+                          "\'%s\' model configured for domain, but "</div><div class="gmail_extra">+                          "hypervisor driver is \'%s\'."),</div><div class="gmail_extra">+                     seclabel->model, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+    /*</div><div class="gmail_extra">+     * Send label to relabel-self interface to allow child to label</div><div class="gmail_extra">+     * its self once it finishes setting up. Apply only if interface is</div><div class="gmail_extra">+     * available and user namespace is enabled.</div><div class="gmail_extra">+     */</div><div class="gmail_extra">+</div><div class="gmail_extra">+    if (STREQ(virSecurityManagerGetDriver(mgr), "LXC")) {</div><div class="gmail_extra">+</div><div class="gmail_extra">+        if (!def->idmap.nuidmap)</div><div class="gmail_extra">+            return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+        VIR_DEBUG("Applying label %s to relabel-self interface.", seclabel->label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+        if (virAsprintf(&smackfs_path, "%s/relabel-self", smack_smackfs_path()) < 0) {</div><div class="gmail_extra">+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",</div><div class="gmail_extra">+                            _("Unable to obtain path for smackfs. Is smack enabled? "));</div><div class="gmail_extra">+            return -1;</div><div class="gmail_extra">+        }</div><div class="gmail_extra">+</div><div class="gmail_extra">+        rlbl = open(smackfs_path, O_WRONLY);</div><div class="gmail_extra">+</div><div class="gmail_extra">+        if (rlbl < 0) {</div><div class="gmail_extra">+            virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                            _("Could not open relabel interface \'%s\' for writing. Is it "</div><div class="gmail_extra">+                                "enabled in the kernel?"),</div><div class="gmail_extra">+                            smackfs_path);</div><div class="gmail_extra">+            return -1;</div><div class="gmail_extra">+        }</div><div class="gmail_extra">+</div><div class="gmail_extra">+        if (safewrite(rlbl, seclabel->label, strlen(seclabel->label)) < 0) {</div><div class="gmail_extra">+            virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                            _("Could not write to relabel interface \'%s\'."),</div><div class="gmail_extra">+                            smackfs_path);</div><div class="gmail_extra">+            return -1;</div><div class="gmail_extra">+        }</div><div class="gmail_extra">+</div><div class="gmail_extra">+        VIR_FORCE_CLOSE(rlbl);</div><div class="gmail_extra">+    }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     /* save in cmd to be set after fork/before child process is exec'ed */</div><div class="gmail_extra">+     virCommandSetSmackLabel(cmd, seclabel->label);</div><div class="gmail_extra">+     VIR_DEBUG("save smack label in cmd %s", seclabel->label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetAllLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          const char *stdin_path)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+</div><div class="gmail_extra">+     size_t i;</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!seclabel->relabel)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("set image security label before");</div><div class="gmail_extra">+</div><div class="gmail_extra">+     for (i = 0; i < def->ndisks; i++) {</div><div class="gmail_extra">+         if (def->disks[i]->src->type == VIR_STORAGE_TYPE_DIR) {</div><div class="gmail_extra">+             VIR_WARN("Unable to relabel directory tree %s for disk %s",</div><div class="gmail_extra">+                     def->disks[i]->src->path, def->disks[i]->dst);</div><div class="gmail_extra">+             continue;</div><div class="gmail_extra">+         }</div><div class="gmail_extra">+</div><div class="gmail_extra">+         VIR_DEBUG("set image security label");</div><div class="gmail_extra">+</div><div class="gmail_extra">+         if (virSecuritySmackSetImageLabel(mgr,</div><div class="gmail_extra">+                     def, def->disks[i]->src) < 0)</div><div class="gmail_extra">+             return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("set image security label after");</div><div class="gmail_extra">+</div><div class="gmail_extra">+     for (i = 0; i< def->nhostdevs; i++) {</div><div class="gmail_extra">+          if (virSecuritySmackSetHostdevLabel(mgr,</div><div class="gmail_extra">+                          def,</div><div class="gmail_extra">+                          def->hostdevs[i],</div><div class="gmail_extra">+                          NULL) < 0)</div><div class="gmail_extra">+                return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (stdin_path) {</div><div class="gmail_extra">+         if (setxattr(stdin_path, "security.SMACK64", seclabel->imagelabel,</div><div class="gmail_extra">+                     strlen(seclabel->imagelabel) + 1, 0)< 0 &&</div><div class="gmail_extra">+                 virFileIsSharedFS(stdin_path) != 1)</div><div class="gmail_extra">+             return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackRestoreAllLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          bool migrated ATTRIBUTE_UNUSED)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     size_t i;</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     VIR_DEBUG("Restoring security label on %s", def->name);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!seclabel->relabel)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     for (i = 0; i < def->ndisks; i++) {</div><div class="gmail_extra">+</div><div class="gmail_extra">+          if (virSecuritySmackRestoreImageLabelInt(mgr,</div><div class="gmail_extra">+                          def,</div><div class="gmail_extra">+                          def->disks[i]->src,</div><div class="gmail_extra">+                          migrated) < 0)</div><div class="gmail_extra">+</div><div class="gmail_extra">+                return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          const char *savefile)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!seclabel->relabel)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return virSecuritySmackSetPathLabel(savefile, seclabel->imagelabel);</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackRestoreSavedStateLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          const char *savefile)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!seclabel->relabel)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return virSecuritySmackRestoreFileLabel(mgr, savefile);</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          int fd)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->imagelabel == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return virSecuritySmackSetFileLabel(fd, seclabel->imagelabel);</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetImagePathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+                       virDomainDefPtr def,</div><div class="gmail_extra">+                       const char *path)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+        return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->imagelabel == NULL)</div><div class="gmail_extra">+        return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (virSecuritySmackSetPathLabel(path, seclabel->imagelabel) < 0)</div><div class="gmail_extra">+        return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return 0;</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra">+virSecuritySmackSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def,</div><div class="gmail_extra">+          int fd)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     struct stat buf;</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);</div><div class="gmail_extra">+     if (seclabel == NULL)</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (seclabel->label == NULL)</div><div class="gmail_extra">+          return 0;</div><div class="gmail_extra">+</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (fstat(fd, &buf) < 0) {</div><div class="gmail_extra">+          virReportSystemError(errno, _("cannot stat tap fd %d"), fd);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if ((buf.st_mode & S_IFMT) != S_IFCHR) {</div><div class="gmail_extra">+          virReportError(VIR_ERR_INTERNAL_ERROR,</div><div class="gmail_extra">+                     _("tap fd %d is not character device"), fd);</div><div class="gmail_extra">+          return -1;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return virSecuritySmackSetFileLabel(fd, seclabel->label);</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static char *</div><div class="gmail_extra">+virSecuritySmackGetSecurityMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          virDomainDefPtr def)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     char *opts = NULL;</div><div class="gmail_extra">+     virSecurityLabelDefPtr seclabel;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if ((seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME))) {</div><div class="gmail_extra">+         if (!seclabel->imagelabel) {</div><div class="gmail_extra">+             if (!seclabel->label)</div><div class="gmail_extra">+                 seclabel->imagelabel = virSecuritySmackGetLabelName(def);</div><div class="gmail_extra">+             else</div><div class="gmail_extra">+                 seclabel->imagelabel = seclabel->label;</div><div class="gmail_extra">+         }</div><div class="gmail_extra">+         if (seclabel->imagelabel &&</div><div class="gmail_extra">+                 virAsprintf(&opts,</div><div class="gmail_extra">+                     ",smackfsdef=\"%s\"",</div><div class="gmail_extra">+                     (const char*) seclabel->imagelabel) < 0)</div><div class="gmail_extra">+             return NULL;</div><div class="gmail_extra">+     }</div><div class="gmail_extra">+</div><div class="gmail_extra">+     if (!opts && VIR_STRDUP(opts, "") < 0)</div><div class="gmail_extra">+          return NULL;</div><div class="gmail_extra">+</div><div class="gmail_extra">+     return opts;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static const char *</div><div class="gmail_extra">+virSecuritySmackGetBaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+          int virtType ATTRIBUTE_UNUSED)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+     return NULL;</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+virSecurityDriver virSecurityDriverSmack = {</div><div class="gmail_extra">+     .privateDataLen                        = 0,</div><div class="gmail_extra">+     .name                               = SECURITY_SMACK_NAME,</div><div class="gmail_extra">+     .probe                              = virSecuritySmackSecurityDriverProbe,</div><div class="gmail_extra">+     .open                               = virSecuritySmackSecurityDriverOpen,</div><div class="gmail_extra">+     .close                              = virSecuritySmackSecurityDriverClose,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .getModel                           = virSecuritySmackSecurityDriverGetModel,</div><div class="gmail_extra">+     .getDOI                             = virSecuritySmackSecurityDriverGetDOI,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSecurityVerify               = virSecuritySmackSecurityVerify,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSecurityDiskLabel         = virSecuritySmackSetDiskLabel,</div><div class="gmail_extra">+     .domainRestoreSecurityDiskLabel     = virSecuritySmackRestoreDiskLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSecurityImageLabel        = virSecuritySmackSetImageLabel,</div><div class="gmail_extra">+     .domainRestoreSecurityImageLabel    = virSecuritySmackRestoreImageLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSecurityDaemonSocketLabel = virSecuritySmackSetDaemonSocketLabel,</div><div class="gmail_extra">+     .domainSetSecuritySocketLabel       = virSecuritySmackSetSocketLabel,</div><div class="gmail_extra">+     .domainClearSecuritySocketLabel     = virSecuritySmackClearSocketLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainGenSecurityLabel             = virSecuritySmackGenLabel,</div><div class="gmail_extra">+     .domainReserveSecurityLabel         = virSecuritySmackReserveLabel,</div><div class="gmail_extra">+     .domainReleaseSecurityLabel         = virSecuritySmackReleaseLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainGetSecurityProcessLabel      = virSecuritySmackGetProcessLabel,</div><div class="gmail_extra">+     .domainSetSecurityProcessLabel      = virSecuritySmackSetProcessLabel,</div><div class="gmail_extra">+     .domainSetSecurityChildProcessLabel = virSecuritySmackSetChildProcessLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSecurityAllLabel          = virSecuritySmackSetAllLabel,</div><div class="gmail_extra">+     .domainRestoreSecurityAllLabel      = virSecuritySmackRestoreAllLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSecurityHostdevLabel      = virSecuritySmackSetHostdevLabel,</div><div class="gmail_extra">+     .domainRestoreSecurityHostdevLabel  = virSecuritySmackRestoreHostdevLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSavedStateLabel           = virSecuritySmackSetSavedStateLabel,</div><div class="gmail_extra">+     .domainRestoreSavedStateLabel       = virSecuritySmackRestoreSavedStateLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainSetSecurityImageFDLabel      = virSecuritySmackSetImageFDLabel,</div><div class="gmail_extra">+     .domainSetSecurityImagePathLabel    = virSecuritySmackSetImagePathLabel,</div><div class="gmail_extra">+     .domainSetSecurityTapFDLabel        = virSecuritySmackSetTapFDLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .domainGetSecurityMountOptions      = virSecuritySmackGetSecurityMountOptions,</div><div class="gmail_extra">+</div><div class="gmail_extra">+     .getBaseLabel                       = virSecuritySmackGetBaseLabel,</div><div class="gmail_extra">+</div><div class="gmail_extra">+};</div><div class="gmail_extra">diff --git a/src/security/security_smack.h b/src/security/security_smack.h</div><div class="gmail_extra">new file mode 100644</div><div class="gmail_extra">index 0000000..3d9fad9</div><div class="gmail_extra">--- /dev/null</div><div class="gmail_extra">+++ b/src/security/security_smack.h</div><div class="gmail_extra">@@ -0,0 +1,37 @@</div><div class="gmail_extra">+/*</div><div class="gmail_extra">+ * Copyright (C) 2015 Cisco Systems, Inc.</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ * This library is free software; you can redistribute it and/or</div><div class="gmail_extra">+ * modify it under the terms of the GNU Lesser General Public</div><div class="gmail_extra">+ * License as published by the Free Software Foundation; either</div><div class="gmail_extra">+ * version 2.1 of the License, or (at your option) any later version.</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ * This library is distributed in the hope that it will be useful,</div><div class="gmail_extra">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</div><div class="gmail_extra">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</div><div class="gmail_extra">+ * Lesser General Public License for more details.</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ * You should have received a copy of the GNU Lesser General Public</div><div class="gmail_extra">+ * License along with this library.  If not, see</div><div class="gmail_extra">+ * <<a href="http://www.gnu.org/licenses/" target="_blank">http://www.gnu.org/licenses/</a>>.</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ * Author:</div><div class="gmail_extra">+ *   Hongliang Liang <<a href="mailto:hliang@bupt.edu" target="_blank">hliang@bupt.edu</a>,cn></div><div class="gmail_extra">+ *   Changyao Han <<a href="mailto:changyao@bupt.edu.cn" target="_blank">changyao@bupt.edu.cn</a>></div><div class="gmail_extra">+ *   Raghuram S. Sudhaakar <<a href="mailto:rssudhaakar@gmail.com" target="_blank">rssudhaakar@gmail.com</a>></div><div class="gmail_extra">+ *   Randy Aybar <<a href="mailto:raybar@cisco.com" target="_blank">raybar@cisco.com</a>></div><div class="gmail_extra">+ */</div><div class="gmail_extra">+</div><div class="gmail_extra">+#ifndef __VIR_SECURITY_SMACK_H__</div><div class="gmail_extra">+# define __VIR_SECURITY_SMACK_H__</div><div class="gmail_extra">+</div><div class="gmail_extra">+# include "security_driver.h"</div><div class="gmail_extra">+</div><div class="gmail_extra">+int virSecuritySmackSockCreate(const char *label, const char *attr);</div><div class="gmail_extra">+</div><div class="gmail_extra">+</div><div class="gmail_extra">+extern virSecurityDriver virSecurityDriverSmack;</div><div class="gmail_extra">+</div><div class="gmail_extra">+# define SMACK_PREFIX "smack-"</div><div class="gmail_extra">+</div><div class="gmail_extra">+#endif /* __VIR_SECURITY_SMACK_H__ */</div><div class="gmail_extra">diff --git a/src/security/security_stack.c b/src/security/security_stack.c</div><div class="gmail_extra">index 3ea2751..e30f003 100644</div><div class="gmail_extra">--- a/src/security/security_stack.c</div><div class="gmail_extra">+++ b/src/security/security_stack.c</div><div class="gmail_extra">@@ -495,6 +495,14 @@ virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra"> }</div><div class="gmail_extra"> </div><div class="gmail_extra"> static int</div><div class="gmail_extra">+virSecurityStackSetImagePathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+                                  virDomainDefPtr vm ATTRIBUTE_UNUSED,</div><div class="gmail_extra">+                                  const char *path ATTRIBUTE_UNUSED)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+    return 0;</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+static int</div><div class="gmail_extra"> virSecurityStackSetTapFDLabel(virSecurityManagerPtr mgr,</div><div class="gmail_extra">                               virDomainDefPtr vm,</div><div class="gmail_extra">                               int fd)</div><div class="gmail_extra">@@ -659,6 +667,7 @@ virSecurityDriver virSecurityDriverStack = {</div><div class="gmail_extra">     .domainRestoreSavedStateLabel       = virSecurityStackRestoreSavedStateLabel,</div><div class="gmail_extra"> </div><div class="gmail_extra">     .domainSetSecurityImageFDLabel      = virSecurityStackSetImageFDLabel,</div><div class="gmail_extra">+    .domainSetSecurityImagePathLabel    = virSecurityStackSetImagePathLabel,</div><div class="gmail_extra">     .domainSetSecurityTapFDLabel        = virSecurityStackSetTapFDLabel,</div><div class="gmail_extra"> </div><div class="gmail_extra">     .domainGetSecurityMountOptions      = virSecurityStackGetMountOptions,</div><div class="gmail_extra">diff --git a/src/util/vircommand.c b/src/util/vircommand.c</div><div class="gmail_extra">index 027cb64..cdcb3a2 100644</div><div class="gmail_extra">--- a/src/util/vircommand.c</div><div class="gmail_extra">+++ b/src/util/vircommand.c</div><div class="gmail_extra">@@ -41,6 +41,9 @@</div><div class="gmail_extra"> #if defined(WITH_SECDRIVER_APPARMOR)</div><div class="gmail_extra"> # include <sys/apparmor.h></div><div class="gmail_extra"> #endif</div><div class="gmail_extra">+#if defined(WITH_SECDRIVER_SMACK)</div><div class="gmail_extra">+# include <sys/smack.h></div><div class="gmail_extra">+#endif</div><div class="gmail_extra"> </div><div class="gmail_extra"> #define __VIR_COMMAND_PRIV_H_ALLOW__</div><div class="gmail_extra"> #include "vircommandpriv.h"</div><div class="gmail_extra">@@ -134,6 +137,10 @@ struct _virCommand {</div><div class="gmail_extra"> #if defined(WITH_SECDRIVER_APPARMOR)</div><div class="gmail_extra">     char *appArmorProfile;</div><div class="gmail_extra"> #endif</div><div class="gmail_extra">+#if defined(WITH_SECDRIVER_SMACK)</div><div class="gmail_extra">+    char *smackLabel;</div><div class="gmail_extra">+#endif</div><div class="gmail_extra">+</div><div class="gmail_extra">     int mask;</div><div class="gmail_extra"> };</div><div class="gmail_extra"> </div><div class="gmail_extra">@@ -722,6 +729,30 @@ virExec(virCommandPtr cmd)</div><div class="gmail_extra">     }</div><div class="gmail_extra"> # endif</div><div class="gmail_extra"> </div><div class="gmail_extra">+# if defined(WITH_SECDRIVER_SMACK)</div><div class="gmail_extra">+    if (cmd->smackLabel) {</div><div class="gmail_extra">+        VIR_DEBUG("Setting child security label to %s", cmd->smackLabel);</div><div class="gmail_extra">+</div><div class="gmail_extra">+        if (smack_set_label_for_self(cmd->smackLabel) < 0) {</div><div class="gmail_extra">+            virReportSystemError(errno,</div><div class="gmail_extra">+                                 _("unable to set Smack label '%s' "</div><div class="gmail_extra">+                                   "for '%s'"),</div><div class="gmail_extra">+                                 cmd->smackLabel, cmd->args[0]);</div><div class="gmail_extra">+            goto fork_error;</div><div class="gmail_extra">+        }</div><div class="gmail_extra">+    }</div><div class="gmail_extra">+# endif</div><div class="gmail_extra">+</div><div class="gmail_extra">+/*</div><div class="gmail_extra">+ *    if (smack_new_label_from_self(&label) == -1)</div><div class="gmail_extra">+ *    {</div><div class="gmail_extra">+ *            goto fork_error;</div><div class="gmail_extra">+ *    }</div><div class="gmail_extra">+ *    VIR_DEBUG("smack label is %s",label);</div><div class="gmail_extra">+ *    free(label);</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ */</div><div class="gmail_extra">     /* The steps above may need to do something privileged, so we delay</div><div class="gmail_extra">      * setuid and clearing capabilities until the last minute.</div><div class="gmail_extra">      */</div><div class="gmail_extra">@@ -1197,6 +1228,35 @@ virCommandSetAppArmorProfile(virCommandPtr cmd,</div><div class="gmail_extra"> }</div><div class="gmail_extra"> </div><div class="gmail_extra"> </div><div class="gmail_extra">+</div><div class="gmail_extra">+/**</div><div class="gmail_extra">+ * virCommandSetSmackLabel:</div><div class="gmail_extra">+ * @cmd: the command to modify</div><div class="gmail_extra">+ * @label: the Smack label to use for the child process</div><div class="gmail_extra">+ *</div><div class="gmail_extra">+ * Saves a copy of @label to use when setting the Smack context</div><div class="gmail_extra">+ * label (write to /proc/self/attr/current ) after the child process has</div><div class="gmail_extra">+ * been started. If Smack isn't compiled into libvirt, or if label is</div><div class="gmail_extra">+ * NULL, nothing will be done.</div><div class="gmail_extra">+ */</div><div class="gmail_extra">+void</div><div class="gmail_extra">+virCommandSetSmackLabel(virCommandPtr cmd,</div><div class="gmail_extra">+                          const char *label ATTRIBUTE_UNUSED)</div><div class="gmail_extra">+</div><div class="gmail_extra">+{</div><div class="gmail_extra">+    if (!cmd || cmd->has_error)</div><div class="gmail_extra">+         return;</div><div class="gmail_extra">+</div><div class="gmail_extra">+#if defined(WITH_SECDRIVER_SMACK)</div><div class="gmail_extra">+    VIR_FREE(cmd->smackLabel);</div><div class="gmail_extra">+    if (VIR_STRDUP_QUIET(cmd->smackLabel, label) < 0)</div><div class="gmail_extra">+        cmd->has_error = ENOMEM;</div><div class="gmail_extra">+#endif</div><div class="gmail_extra">+     return;</div><div class="gmail_extra">+</div><div class="gmail_extra">+}</div><div class="gmail_extra">+</div><div class="gmail_extra">+</div><div class="gmail_extra"> /**</div><div class="gmail_extra">  * virCommandDaemonize:</div><div class="gmail_extra">  * @cmd: the command to modify</div><div class="gmail_extra">@@ -2796,6 +2856,9 @@ virCommandFree(virCommandPtr cmd)</div><div class="gmail_extra"> #if defined(WITH_SECDRIVER_APPARMOR)</div><div class="gmail_extra">     VIR_FREE(cmd->appArmorProfile);</div><div class="gmail_extra"> #endif</div><div class="gmail_extra">+#if defined(WITH_SECDRIVER_SMACK)</div><div class="gmail_extra">+    VIR_FREE(cmd->smackLabel);</div><div class="gmail_extra">+#endif</div><div class="gmail_extra"> </div><div class="gmail_extra">     VIR_FREE(cmd);</div><div class="gmail_extra"> }</div><div class="gmail_extra">diff --git a/src/util/vircommand.h b/src/util/vircommand.h</div><div class="gmail_extra">index 198da2f..dfc8a65 100644</div><div class="gmail_extra">--- a/src/util/vircommand.h</div><div class="gmail_extra">+++ b/src/util/vircommand.h</div><div class="gmail_extra">@@ -88,6 +88,9 @@ void virCommandSetSELinuxLabel(virCommandPtr cmd,</div><div class="gmail_extra"> void virCommandSetAppArmorProfile(virCommandPtr cmd,</div><div class="gmail_extra">                                   const char *profile);</div><div class="gmail_extra"> </div><div class="gmail_extra">+void virCommandSetSmackLabel(virCommandPtr cmd,</div><div class="gmail_extra">+                               const char *label);</div><div class="gmail_extra">+</div><div class="gmail_extra"> void virCommandDaemonize(virCommandPtr cmd);</div><div class="gmail_extra"> </div><div class="gmail_extra"> void virCommandNonblockingFDs(virCommandPtr cmd);</div><div><br></div></div></div></div>