]> git.proxmox.com Git - swtpm.git/commitdiff
swtpm: Implement terminate parameter for ctrl channel loss
authorStefan Berger <stefanb@linux.ibm.com>
Thu, 22 Sep 2022 12:47:49 +0000 (08:47 -0400)
committerStefan Berger <stefanb@us.ibm.com>
Thu, 22 Sep 2022 17:27:38 +0000 (13:27 -0400)
Implement support for the terminate parameter for the control channel
option so that swtpm terminates once the control channel connection is
lost. The primary use case is QEMU that holds the control channel
permanently.

Resolves: https://github.com/stefanberger/swtpm/issues/753
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
man/man8/swtpm.pod
src/swtpm/common.c
src/swtpm/common.h
src/swtpm/mainloop.c
src/swtpm/mainloop.h
src/swtpm/swtpm.c
src/swtpm/swtpm_chardev.c

index 4459043cfdf9aa224f66d9845a6874a92c50b168..98b2660091a6a0fc09db32f490bc9e27403002fc 100644 (file)
@@ -126,7 +126,7 @@ For the socket interface, this option automatically assumes -t.
 
 Daemonize the process.
 
-=item B<--ctrl type=[unixio|tcp][,path=E<lt>pathE<gt>] [,port=E<lt>portE<gt>[,bindaddr=E<lt>addressE<gt>[,ifname=E<lt>ifnameE<gt>]]] [,fd=E<lt>filedescriptorE<gt>|clientfd=E<lt>filedescriptorE<gt>] [,mode=E<lt>0...E<gt>][,uid=E<lt>uidE<gt>][,gid=E<lt>gidE<gt>] >
+=item B<--ctrl type=[unixio|tcp][,path=E<lt>pathE<gt>] [,port=E<lt>portE<gt>[,bindaddr=E<lt>addressE<gt>[,ifname=E<lt>ifnameE<gt>]]] [,fd=E<lt>filedescriptorE<gt>|clientfd=E<lt>filedescriptorE<gt>] [,mode=E<lt>0...E<gt>][,uid=E<lt>uidE<gt>][,gid=E<lt>gidE<gt>][,terminate] >
 
 This option adds a control channel to the TPM. The control channel can either use a UnixIO socket with
 a given I<path> or I<filedescriptor> or it can use a TCP socket on the given I<port> or I<filedescriptor>.
@@ -135,11 +135,17 @@ can be provided as well; the default bind address is 127.0.0.1. If a link
 local IPv6 address is provided, the name of the interface to bind to must be
 provided with I<ifname>.
 
-The mode parameter allows a user to set the file mode bits of the UnixIO path.
+The I<mode> parameter allows a user to set the file mode bits of the UnixIO path.
 The mode bits value must be given as an octal number starting with a '0'.
-The default value is 0770. uid and gid set the ownership of the UnixIO socket's path.
+The default value is 0770. I<uid> and I<gid> set the ownership of the UnixIO socket's path.
 This operation requires root privileges.
 
+The I<terminate> parameter enables the automatic termination of swtpm when the
+control channel connection has been lost. This is useful in scenarios where
+the control channel connection is held permanently, such as by QEMU, and
+swtpm should terminate upon abnormal termination of the client that could
+not send a CMD_SHUTDOWN via the control channel anymore.
+
 The control channel enables out-of-band control of the TPM, such as resetting the TPM.
 
 =back
index 0903585dba89020edf89526d38db4053141c47bc..bb87f3a1cc059e7e2863e13035b46d49c460cb5a 100644 (file)
@@ -70,6 +70,7 @@
 #include "server.h"
 #include "seccomp_profile.h"
 #include "tpmlib.h"
+#include "mainloop.h"
 
 /* --log %s */
 static const OptionDesc logging_opt_desc[] = {
@@ -180,6 +181,9 @@ static const OptionDesc ctrl_opt_desc[] = {
     }, {
         .name = "gid",
         .type = OPT_TYPE_GID_T,
+    }, {
+        .name = "terminate",
+        .type = OPT_TYPE_BOOLEAN,
     },
     END_OPTION_DESC
 };
@@ -924,10 +928,13 @@ error:
  * Parse the 'ctrl' (control channel) options.
  *
  * @options: the control channel options to parse
+ * @cc: pointer for pointer to allocated ctrlchannel struct
+ * @mainloop_flags: pointer to mainloop flags to add a flag to
  *
  * Returns 0 on success, -1 on failure.
  */
-static int parse_ctrlchannel_options(char *options, struct ctrlchannel **cc)
+static int parse_ctrlchannel_options(char *options, struct ctrlchannel **cc,
+                                     uint32_t *mainloop_flags)
 {
     OptionValues *ovs = NULL;
     char *error = NULL;
@@ -1027,6 +1034,9 @@ static int parse_ctrlchannel_options(char *options, struct ctrlchannel **cc)
     if (*cc == NULL)
         goto error;
 
+    if (option_get_bool(ovs, "terminate", false))
+        *mainloop_flags |= MAIN_LOOP_FLAG_CTRL_END_ON_HUP;
+
     option_values_free(ovs);
 
     return 0;
@@ -1043,15 +1053,18 @@ error:
  * Parse and act upon the parsed 'ctrl' (control channel) options.
  *
  * @options: the control channel options to parse
+ * @cc: pointer for pointer to allocated ctrlchannel struct
+ * @mainloop_flags: pointer to mainloop flags to add a flag to
  *
  * Returns 0 on success, -1 on failure.
  */
-int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc)
+int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc,
+                               uint32_t *mainloop_flag)
 {
     if (!options)
         return 0;
 
-    if (parse_ctrlchannel_options(options, cc) < 0)
+    if (parse_ctrlchannel_options(options, cc, mainloop_flag) < 0)
         return -1;
 
     return 0;
index 720a82d7e46d9c4d71897f04d50db536e993885b..bc9418887bf3fca90dc5e78e2371fe31bd9e8227 100644 (file)
@@ -49,7 +49,8 @@ int handle_migration_key_options(char *options);
 int handle_pid_options(char *options);
 int handle_tpmstate_options(char *options);
 struct ctrlchannel;
-int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc);
+int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc,
+                               uint32_t *mainloop_flag);
 struct server;
 int handle_server_options(char *options, struct server **s);
 int handle_locality_options(char *options, uint32_t *flags);
index 34fab4286eac4f27ac016bc3f9037bf3eb7aedb9..846f02c03d535e24a9e1649484165204931295ae 100644 (file)
@@ -260,6 +260,10 @@ int mainLoop(struct mainLoopParams *mlp,
                                                     &mainloop_terminate,
                                                     &locality, &tpm_running,
                                                     mlp);
+                if (ctrlclntfd < 0 &&
+                    mlp->flags & MAIN_LOOP_FLAG_CTRL_END_ON_HUP)
+                    mainloop_terminate = true;
+
                 if (mainloop_terminate)
                     break;
             }
@@ -268,6 +272,11 @@ int mainLoop(struct mainLoopParams *mlp,
                 if (ctrlclntfd >= 0)
                     close(ctrlclntfd);
                 ctrlclntfd = -1;
+                /* unixio gets this signal, not tcp */
+                if (mlp->flags & MAIN_LOOP_FLAG_CTRL_END_ON_HUP) {
+                    mainloop_terminate = true;
+                    break;
+                }
             }
 
             if (!(pollfds[DATA_CLIENT_FD].revents & POLLIN))
index 51b89a5cfe969990efc3a509b82d3b39a44d6fe6..d58c21d2062921fef05ac537e1430973bd68a8a8 100644 (file)
@@ -50,10 +50,11 @@ extern bool tpm_running;
 
 struct mainLoopParams {
     uint32_t flags;
-#define MAIN_LOOP_FLAG_TERMINATE  (1 << 0)
-#define MAIN_LOOP_FLAG_USE_FD     (1 << 1)
-#define MAIN_LOOP_FLAG_KEEP_CONNECTION (1 << 2)
-#define MAIN_LOOP_FLAG_END_ON_HUP (1 << 3)
+#define MAIN_LOOP_FLAG_TERMINATE        (1 << 0)
+#define MAIN_LOOP_FLAG_USE_FD           (1 << 1)
+#define MAIN_LOOP_FLAG_KEEP_CONNECTION  (1 << 2)
+#define MAIN_LOOP_FLAG_END_ON_HUP       (1 << 3)
+#define MAIN_LOOP_FLAG_CTRL_END_ON_HUP  (1 << 4) /* terminate on ctrl ch. client loss (QEMU) */
 
     int fd;
     struct ctrlchannel *cc;
index da84fe59d083acb7c13a6fbfd900e521f9499879..2573404c28a78347e0b3775a61c4259b803510ea 100644 (file)
@@ -108,7 +108,7 @@ static void usage(FILE *file, const char *prgname, const char *iface)
     "-t|--terminate   : terminate the TPM once the data channel connection (TCP)\n"
     "                   has been lost\n"
     "-d|--daemon      : daemonize the TPM\n"
-    "--ctrl type=[unixio|tcp][,path=<path>][,port=<port>[,bindaddr=address[,ifname=ifname]]][,fd=<filedescriptor>|clientfd=<filedescriptor>][,mode=0...][,uid=uid][,gid=gid]\n"
+    "--ctrl type=[unixio|tcp][,path=<path>][,port=<port>[,bindaddr=address[,ifname=ifname]]][,fd=<filedescriptor>|clientfd=<filedescriptor>][,mode=0...][,uid=uid][,gid=gid][,terminate]\n"
     "                 : TPM control channel using either UnixIO or TCP sockets;\n"
     "                   the path is only valid for Unixio channels; the port must\n"
     "                   be given in case the type is TCP; the TCP socket is bound\n"
@@ -122,6 +122,7 @@ static void usage(FILE *file, const char *prgname, const char *iface)
     "                   mode allows a user to set the file mode bits of a Unixio socket;\n"
     "                   the value must be given in octal number format\n"
     "                   uid and gid set the ownership of the Unixio socket's file;\n"
+    "                   terminate terminates on ctrl channel connection loss;\n"
     "--migration-key file=<path>|fd=<fd>[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n"
     "                 : use an AES key for the encryption of the TPM's state\n"
     "                   when it is retrieved from the TPM via ioctls;\n"
@@ -469,7 +470,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
     if (tpmlib_choose_tpm_version(mlp.tpmversion) != TPM_SUCCESS)
         exit(EXIT_FAILURE);
 
-    if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc) < 0 ||
+    if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc, &mlp.flags) < 0 ||
         handle_server_options(serverdata, &server) < 0) {
         goto exit_failure;
     }
index c9855c55309c89c5e22c3e1b16a63ec2a69a8ae4..89594224fc0ddb5afbd2a080acaca91bed9b47af 100644 (file)
@@ -136,7 +136,7 @@ static void usage(FILE *file, const char *prgname, const char *iface)
     "                 : use the given character device\n"
     "-f|--fd <fd>     : use the given character device file descriptor\n"
     "-d|--daemon      : daemonize the TPM\n"
-    "--ctrl type=[unixio|tcp][,path=<path>][,port=<port>[,bindaddr=address[,ifname=ifname]]][,fd=<filedescriptor|clientfd=<filedescriptor>][,mode=0...][,uid=uid][,gid=gid]\n"
+    "--ctrl type=[unixio|tcp][,path=<path>][,port=<port>[,bindaddr=address[,ifname=ifname]]][,fd=<filedescriptor|clientfd=<filedescriptor>][,mode=0...][,uid=uid][,gid=gid][,terminate]\n"
     "                 : TPM control channel using either UnixIO or TCP sockets;\n"
     "                   the path is only valid for Unixio channels; the port must\n"
     "                   be given in case the type is TCP; the TCP socket is bound\n"
@@ -150,6 +150,7 @@ static void usage(FILE *file, const char *prgname, const char *iface)
     "                   mode allows a user to set the file mode bits of a Unixio socket;\n"
     "                   the value must be given in octal number format\n"
     "                   uid and gid set the ownership of the Unixio socket's file;\n"
+    "                   terminate terminates on ctrl channel connection loss;\n"
     "--migration-key file=<path>|fd=<fd>[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n"
     "                 : use an AES key for the encryption of the TPM's state\n"
     "                   when it is retrieved from the TPM via ioctls;\n"
@@ -550,7 +551,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
         exit(EXIT_FAILURE);
     }
 
-    if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc) < 0) {
+    if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc, &mlp.flags) < 0) {
         goto exit_failure;
     }