[libvirt] [PATCH 2/6] tpm: Add support for external swtpm TPM emulator
Stefan Berger
stefanb at linux.vnet.ibm.com
Fri Apr 6 14:49:23 UTC 2018
On 04/06/2018 10:12 AM, Daniel P. Berrangé wrote:
> On Fri, Apr 06, 2018 at 07:23:49AM -0400, Stefan Berger wrote:
>> On 04/06/2018 04:26 AM, Daniel P. Berrangé wrote:
>>> On Thu, Apr 05, 2018 at 05:56:02PM -0400, Stefan Berger wrote:
>>>> This patch adds support for an external swtpm TPM emulator. The XML for
>>>> this type of TPM looks as follows:
>>>>
>>>> <tpm model='tpm-tis'>
>>>> <backend type='emulator'/>
>>>> </tpm>
>
>
>
>>>> + cmd = virCommandNew(swtpm_path);
>>>> + if (!cmd)
>>>> + goto error;
>>>> +
>>>> + virCommandClearCaps(cmd);
>>>> +
>>>> + virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL);
>>>> + virCommandAddArgFormat(cmd, "type=unixio,path=%s,mode=0600",
>>>> + tpm->data.emulator.source.data.nix.path);
>>>> +
>>>> + virCommandAddArg(cmd, "--tpmstate");
>>>> + virCommandAddArgFormat(cmd, "dir=%s", storagepath);
>>>> +
>>>> + virCommandAddArg(cmd, "--log");
>>>> + virCommandAddArgFormat(cmd, "file=%s", logfile);
>>>> +
>>>> + /* allow process to open logfile by root before dropping privileges */
>>>> + virCommandAllowCap(cmd, CAP_DAC_OVERRIDE);
>>> Why can't we get have the log file be owned by the user that
>>> swtpm runs as, instead of root ?
>> I would have to look at this particular capability again. I initially wanted
>> to put the swtpm's log file also into /var/log/libvirt/qemu. It works nice
>> of course when running swtpm as 'root' but not so much when running it as
>> 'tss':
>>
>> root at localhost tmp]$ sudo ls -l /var/log/libvirt/ | grep qemu
>> drwx------. 2 root root 20480 Apr 5 16:14 qemu
> Yeah the logs are owned by root these days, because they're not written by
> qemu itself, instead virtlogd owns it.
[root at localhost log]# ls -lZ | grep libvirt
drwx------. 6 root root
system_u:object_r:virt_log_t:s0 4096 Mar 1 2017 libvirt
Even /var/log/libvirt would not be accessible for the tss users.
>
>> So where do we put the swtpm's log files? /var/log/libvirt/swtpm?
> Yeah, probably best to have a separate directory
It would have to be /var/log/swtpm unless we change the permissions on
/var/log/libvirt ... ?
>> Iirc the CAP_DAC_OVERRIDE became necessary when swtpm tries to append to the
>> log that 'tss' owns but now libvirt runs it as 'root'. I think that was the
>> reason I added it. One way to solve this would be to chown() the files
>> before starting swtpm. Is that the solution?
> I'd think a separate dir is best
>
>>
>>>> + if (swtpm_user > 0) {
>>>> + virCommandAddArg(cmd, "--runas");
>>>> + virCommandAddArgFormat(cmd, "%u", swtpm_user);
>>>> + virCommandAllowCap(cmd, CAP_SETGID);
>>>> + virCommandAllowCap(cmd, CAP_SETUID);
>>>> + }
>>> Then we could tell virCommand to set the UID/GID before it even
>>> executes this, and not use -runas, thus avoiding the need to
>>> allow theses capabilities.
>> And the directory it writes the logs in would have to have ownership of
>> either root:root or tss:root (or tss:tss), depending on how libvirt is
>> currently configured? Again chown() the dir before starting?
>>
>>>
>>>> +/*
>>>> + * virTPMStopEmulator
>>>> + * @tpm: TPM definition
>>>> + * @vmuuid: the UUID of the VM
>>>> + * @verbose: whether to report errors
>>>> + *
>>>> + * Gracefully stop the swptm
>>>> + */
>>>> +void
>>>> +virTPMStopEmulator(virDomainTPMDefPtr tpm, const unsigned char *vmuuid,
>>>> + bool verbose)
>>>> +{
>>>> + virCommandPtr cmd;
>>>> + int exitstatus;
>>>> + char *pathname;
>>>> + char *errbuf = NULL;
>>>> +
>>>> + (void)vmuuid;
>>>> + if (virTPMEmulatorInit() < 0)
>>>> + return;
>>>> +
>>>> + if (!(pathname = virTPMCreateEmulatorSocket(vmuuid)))
>>>> + return;
>>>> +
>>>> + cmd = virCommandNew(swtpm_ioctl);
>>>> + if (!cmd) {
>>>> + VIR_FREE(pathname);
>>>> + return;
>>>> + }
>>>> +
>>>> + virCommandAddArgList(cmd, "--unix", pathname, "-s", NULL);
>>>> +
>>>> + virCommandSetErrorBuffer(cmd, &errbuf);
>>>> +
>>>> + if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
>>>> + if (verbose)
>>>> + VIR_ERROR(_("Could not run swtpm_ioctl -s '%s'."
>>>> + " existstatus: %d\nstderr: %s"),
>>>> + swtpm_ioctl, exitstatus, errbuf);
>>>> + }
>>>> +
>>>> + virCommandFree(cmd);
>>> I would feel better if we just directly killed the process - with
>>> this approach if something goes wrong with swtpm it may never
>>> respond to this request and stay running.
>> swtpm can write a pidfile. I am only adding this later in this series.
>> Problem is with --daemon libvirt doesn't know the pid of the swtpm anymore.
> The other option is to not use --daemon, and let libvirt write the pid
> file, but that introduces the race with socket path creation again
> which is not good.
Sounds like we should leave this as it is? Unless swtpm was broken,
there shouldn't be a reason why the we wouldn't be able to shut down
swtpm by sending a command to it. The socket and its directory must not
have disappeared of course.
Stefan
>
>
> Regards,
> Daniel
More information about the libvir-list
mailing list