• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / swtpm / #2824

13 May 2025 12:34PM UTC coverage: 72.964% (-0.5%) from 73.462%
#2824

push

travis-ci

web-flow
Merge c2b02e9b2 into 1544c99ca

7033 of 9639 relevant lines covered (72.96%)

13748.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.87
/src/swtpm/common.c
1
/*
2
 * common.c -- Common code for swtpm and swtpm_cuse
3
 *
4
 * (c) Copyright IBM Corporation 2014, 2015, 2019.
5
 *
6
 * Author: Stefan Berger <stefanb@us.ibm.com>
7
 *
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions are
12
 * met:
13
 *
14
 * Redistributions of source code must retain the above copyright notice,
15
 * this list of conditions and the following disclaimer.
16
 *
17
 * Redistributions in binary form must reproduce the above copyright
18
 * notice, this list of conditions and the following disclaimer in the
19
 * documentation and/or other materials provided with the distribution.
20
 *
21
 * Neither the names of the IBM Corporation nor the names of its
22
 * contributors may be used to endorse or promote products derived from
23
 * this software without specific prior written permission.
24
 *
25
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
 */
37

38
#include "config.h"
39

40
#define _GNU_SOURCE
41
#include <stdio.h>
42
#include <string.h>
43
#include <errno.h>
44
#include <unistd.h>
45
#include <sys/types.h>
46
#include <pwd.h>
47
#include <stdlib.h>
48
#include <sys/stat.h>
49
#include <sys/un.h>
50
#include <netinet/in.h>
51
#include <sys/socket.h>
52
#include <arpa/inet.h>
53
#include <net/if.h>
54

55
#ifdef WITH_SECCOMP
56
# include <seccomp.h>
57
#endif
58

59
#include <libtpms/tpm_error.h>
60

61
#include "common.h"
62
#include "options.h"
63
#include "key.h"
64
#include "locality.h"
65
#include "logging.h"
66
#include "swtpm_nvstore.h"
67
#include "pidfile.h"
68
#include "tpmstate.h"
69
#include "ctrlchannel.h"
70
#include "server.h"
71
#include "seccomp_profile.h"
72
#include "tpmlib.h"
73
#include "mainloop.h"
74

75
/* --log %s */
76
static const OptionDesc logging_opt_desc[] = {
77
    {
78
        .name = "file",
79
        .type = OPT_TYPE_STRING,
80
    }, {
81
        .name = "fd",
82
        .type = OPT_TYPE_INT,
83
    }, {
84
        .name = "level",
85
        .type = OPT_TYPE_UINT,
86
    }, {
87
        .name = "prefix",
88
        .type = OPT_TYPE_STRING,
89
    }, {
90
        .name = "truncate",
91
        .type = OPT_TYPE_BOOLEAN,
92
    },
93
    END_OPTION_DESC
94
};
95

96
/* --key %s */
97
static const OptionDesc key_opt_desc[] = {
98
    {
99
        .name = "file",
100
        .type = OPT_TYPE_STRING,
101
    }, {
102
        .name = "mode",
103
        .type = OPT_TYPE_STRING,
104
    }, {
105
        .name = "format",
106
        .type = OPT_TYPE_STRING,
107
    }, {
108
        .name = "remove",
109
        .type = OPT_TYPE_BOOLEAN,
110
    }, {
111
        .name = "pwdfile",
112
        .type = OPT_TYPE_STRING,
113
    }, {
114
        .name = "kdf",
115
        .type = OPT_TYPE_STRING,
116
    }, {
117
        .name = "fd",
118
        .type = OPT_TYPE_INT,
119
    }, {
120
        .name = "pwdfd",
121
        .type = OPT_TYPE_INT,
122
    },
123
    END_OPTION_DESC
124
};
125

126
/* --pid %s */
127
static const OptionDesc pid_opt_desc[] = {
128
    {
129
        .name = "file",
130
        .type = OPT_TYPE_STRING,
131
    }, {
132
        .name = "fd",
133
        .type = OPT_TYPE_INT,
134
    },
135
    END_OPTION_DESC
136
};
137

138
/* --state %s */
139
static const OptionDesc tpmstate_opt_desc[] = {
140
    {
141
        .name = "dir",
142
        .type = OPT_TYPE_STRING,
143
    }, {
144
        .name = "mode",
145
        .type = OPT_TYPE_MODE_T,
146
    }, {
147
        .name = "backend-uri",
148
        .type = OPT_TYPE_STRING,
149
    },
150
    END_OPTION_DESC
151
};
152

153
static const OptionDesc ctrl_opt_desc[] = {
154
    {
155
        .name = "type",
156
        .type = OPT_TYPE_STRING,
157
    }, {
158
        .name = "path",
159
        .type = OPT_TYPE_STRING,
160
    }, {
161
        .name = "port",
162
        .type = OPT_TYPE_INT,
163
    }, {
164
        .name = "bindaddr",
165
        .type = OPT_TYPE_STRING,
166
    }, {
167
        .name = "ifname",
168
        .type = OPT_TYPE_STRING,
169
    }, {
170
        .name = "fd",
171
        .type = OPT_TYPE_INT,
172
    }, {
173
        .name = "clientfd",
174
        .type = OPT_TYPE_INT,
175
    }, {
176
        .name = "mode",
177
        .type = OPT_TYPE_MODE_T,
178
    }, {
179
        .name = "uid",
180
        .type = OPT_TYPE_UID_T,
181
    }, {
182
        .name = "gid",
183
        .type = OPT_TYPE_GID_T,
184
    }, {
185
        .name = "terminate",
186
        .type = OPT_TYPE_BOOLEAN,
187
    },
188
    END_OPTION_DESC
189
};
190

191
static const OptionDesc server_opt_desc[] = {
192
    {
193
        .name = "type",
194
        .type = OPT_TYPE_STRING,
195
    }, {
196
        .name = "path",
197
        .type = OPT_TYPE_STRING,
198
    }, {
199
        .name = "port",
200
        .type = OPT_TYPE_INT,
201
    }, {
202
        .name = "bindaddr",
203
        .type = OPT_TYPE_STRING,
204
    }, {
205
        .name = "ifname",
206
        .type = OPT_TYPE_STRING,
207
    }, {
208
        .name = "fd",
209
        .type = OPT_TYPE_INT,
210
    }, {
211
        .name = "disconnect",
212
        .type = OPT_TYPE_BOOLEAN,
213
    }, {
214
        .name = "mode",
215
        .type = OPT_TYPE_MODE_T,
216
    }, {
217
        .name = "uid",
218
        .type = OPT_TYPE_UID_T,
219
    }, {
220
        .name = "gid",
221
        .type = OPT_TYPE_GID_T,
222
    },
223
    END_OPTION_DESC
224
};
225

226
static const OptionDesc locality_opt_desc[] = {
227
    {
228
        .name = "reject-locality-4",
229
        .type = OPT_TYPE_BOOLEAN,
230
    }, {
231
        .name = "allow-set-locality",
232
        .type = OPT_TYPE_BOOLEAN,
233
    },
234
    END_OPTION_DESC
235
};
236

237
static const OptionDesc flags_opt_desc[] = {
238
    {
239
        .name = "not-need-init",
240
        .type = OPT_TYPE_BOOLEAN,
241
    }, {
242
        .name = "startup-none",
243
        .type = OPT_TYPE_BOOLEAN,
244
    }, {
245
        .name = "startup-clear",
246
        .type = OPT_TYPE_BOOLEAN,
247
    }, {
248
        .name = "startup-state",
249
        .type = OPT_TYPE_BOOLEAN,
250
    }, {
251
        .name = "startup-deactivated",
252
        .type = OPT_TYPE_BOOLEAN,
253
    }, {
254
        .name = "disable-auto-shutdown",
255
        .type = OPT_TYPE_BOOLEAN,
256
    },
257
    END_OPTION_DESC
258
};
259

260
#ifdef WITH_SECCOMP
261
static const OptionDesc seccomp_opt_desc[] = {
262
    {
263
        .name = "action",
264
        .type = OPT_TYPE_STRING,
265
    },
266
    END_OPTION_DESC
267
};
268
#endif
269

270
static const OptionDesc migration_opt_desc[] = {
271
    {
272
        .name = "incoming",
273
        .type = OPT_TYPE_BOOLEAN,
274
    }, {
275
        .name = "release-lock-outgoing",
276
        .type = OPT_TYPE_BOOLEAN,
277
    },
278
    END_OPTION_DESC
279
};
280

281
/*
282
 * handle_log_options:
283
 * Parse and act upon the parsed log options. Initialize the logging.
284
 * @options: the log options
285
 *
286
 * Returns 0 on success, -1 on failure.
287
 */
288
int
289
handle_log_options(char *options)
691✔
290
{
291
    char *error = NULL;
691✔
292
    const char *logfile = NULL, *logprefix = NULL;
691✔
293
    int logfd;
691✔
294
    unsigned int loglevel;
691✔
295
    bool logtruncate;
691✔
296
    OptionValues *ovs = NULL;
691✔
297

298
    if (!options)
691✔
299
        return 0;
300

301
    ovs = options_parse(options, logging_opt_desc, &error);
187✔
302
    if (!ovs) {
187✔
303
        logprintf(STDERR_FILENO, "Error parsing logging options: %s\n",
×
304
                  error);
305
        free(error);
×
306
        return -1;
×
307
    }
308
    logfile = option_get_string(ovs, "file", NULL);
187✔
309
    logfd = option_get_int(ovs, "fd", -1);
187✔
310
    loglevel = option_get_uint(ovs, "level", 0);
187✔
311
    logprefix = option_get_string(ovs, "prefix", NULL);
187✔
312
    logtruncate = option_get_bool(ovs, "truncate", false);
187✔
313
    if (logfile && (log_init(logfile, logtruncate) < 0)) {
187✔
314
        logprintf(STDERR_FILENO,
×
315
                  "Could not open logfile for writing: %s\n",
316
                  strerror(errno));
×
317
        goto error;
×
318
    } else if (logfd >= 0 && (log_init_fd(logfd) < 0)) {
187✔
319
        logprintf(STDERR_FILENO,
×
320
                  "Could not access logfile using fd %d: %s\n",
321
                  logfd, strerror(errno));
×
322
        goto error;
×
323
    }
324
    if ((logfile || logfd) && !loglevel)
187✔
325
        loglevel = 1;
326

327
    if (log_set_prefix(logprefix) < 0) {
187✔
328
        logprintf(STDERR_FILENO,
×
329
                  "Could not set logging prefix. Out of memory?\n");
330
        goto error;
×
331
    }
332
    if (log_set_level(loglevel) < 0) {
187✔
333
        logprintf(STDERR_FILENO,
×
334
                  "Could not set log level. Out of memory?");
335
        goto error;
×
336
    }
337

338
    option_values_free(ovs);
187✔
339

340
    return 0;
187✔
341

342
error:
×
343
    option_values_free(ovs);
×
344

345
    return -1;
×
346
}
347

348
/*
349
 * parse_key_options:
350
 * Parse and act upon the parsed key options.
351
 *
352
 * @options: the key options to parse
353
 * @key: buffer to hold the key
354
 * @maxkeylen: size of the buffer (= max. size the key can have)
355
 * @keylen: the length of the parsed key
356
 * @encmode: the encryption mode as determined from the options
357
 *
358
 * Returns 0 on success, -1 on failure.
359
 */
360
static int
361
parse_key_options(char *options, unsigned char *key, size_t maxkeylen,
136✔
362
                  size_t *keylen, enum encryption_mode *encmode)
363
{
364
    OptionValues *ovs = NULL;
136✔
365
    char *error = NULL;
136✔
366
    const char *keyfile = NULL;
136✔
367
    const char *pwdfile = NULL;
136✔
368
    const char *tmp;
136✔
369
    enum key_format keyformat;
136✔
370
    enum kdf_identifier kdfid;
136✔
371
    size_t mode_keylength;
136✔
372
    int ret;
136✔
373
    int keyfile_fd = -1;
136✔
374
    int pwdfile_fd = -1;
136✔
375

376
    ovs = options_parse(options, key_opt_desc, &error);
136✔
377
    if (!ovs) {
136✔
378
        logprintf(STDERR_FILENO, "Error parsing key options: %s\n",
×
379
                  error);
380
        goto error;
×
381
    }
382

383
    keyfile = option_get_string(ovs, "file", NULL);
136✔
384
    keyfile_fd = option_get_int(ovs, "fd", -1);
136✔
385
    pwdfile = option_get_string(ovs, "pwdfile", NULL);
136✔
386
    pwdfile_fd = option_get_int(ovs, "pwdfd", -1);
136✔
387
    if (!keyfile && keyfile_fd == -1 && !pwdfile && pwdfile_fd == -1) {
136✔
388
        logprintf(STDERR_FILENO,
×
389
                  "Either file=, fd=, pwdfile=, or pwdfd= is required for key option\n");
390
        goto error;
×
391
    }
392

393
    tmp = option_get_string(ovs, "format", NULL);
136✔
394
    keyformat = key_format_from_string(tmp ? tmp : "hex");
242✔
395
    if (keyformat == KEY_FORMAT_UNKNOWN)
136✔
396
        goto error;
×
397

398
    tmp = option_get_string(ovs, "mode", NULL);
136✔
399
    *encmode = encryption_mode_from_string(tmp ? tmp : "aes-128-cbc",
192✔
400
                                           &mode_keylength);
401
    if (*encmode == ENCRYPTION_MODE_UNKNOWN) {
136✔
402
        logprintf(STDERR_FILENO, "Unknown encryption mode '%s'.\n", tmp);
×
403
        goto error;
×
404
    }
405

406
    if (mode_keylength > maxkeylen) {
136✔
407
        /* program error ... */
408
        logprintf(STDERR_FILENO,
×
409
                  "Requested key size %zu larger than supported size %zu.\n",
410
                  mode_keylength, maxkeylen);
411
        goto error;
×
412
    }
413

414
    if (keyfile != NULL) {
136✔
415
        if (key_load_key(keyfile, keyformat,
36✔
416
                         key, keylen, mode_keylength) < 0)
417
            goto error;
×
418
    } else if (keyfile_fd >= 0) {
100✔
419
        if (key_load_key_fd(keyfile_fd, keyformat,
7✔
420
                            key, keylen, mode_keylength) < 0)
421
            goto error;
×
422
    } else {
423
        tmp = option_get_string(ovs, "kdf", "pbkdf2");
93✔
424
        kdfid = kdf_identifier_from_string(tmp);
93✔
425
        if (kdfid == KDF_IDENTIFIER_UNKNOWN) {
93✔
426
            logprintf(STDERR_FILENO, "Unknown kdf '%s'.\n", tmp);
×
427
            goto error;
×
428
        }
429
        /* no key file, so must be pwdfile or pwdfile_fd */
430
        if (pwdfile) {
93✔
431
            if (key_from_pwdfile(pwdfile, key, keylen,
86✔
432
                                 mode_keylength, kdfid) < 0)
433
                goto error;
×
434
        } else {
435
            if (key_from_pwdfile_fd(pwdfile_fd, key, keylen,
7✔
436
                                    mode_keylength, kdfid) < 0)
437
                goto error;
×
438
        }
439
    }
440

441
    if (option_get_bool(ovs, "remove", false)) {
136✔
442
        if (keyfile)
30✔
443
            unlink(keyfile);
20✔
444
        if (pwdfile)
30✔
445
            unlink(pwdfile);
10✔
446
    }
447

448
    ret = 0;
449

450
exit:
136✔
451
    option_values_free(ovs);
136✔
452
    if (keyfile_fd >= 0)
136✔
453
        close(keyfile_fd);
7✔
454
    if (pwdfile_fd >= 0)
136✔
455
        close(pwdfile_fd);
7✔
456

457
    return ret;
136✔
458

459
error:
×
460
    ret = -1;
×
461
    free(error);
×
462

463
    goto exit;
×
464
}
465

466
/*
467
 * handle_key_options:
468
 * Parse and act upon the parsed key options. Set global values related
469
 * to the options found.
470
 * @options: the key options to parse
471
 *
472
 * Returns 0 on success, -1 on failure.
473
 */
474
int
475
handle_key_options(char *options)
400✔
476
{
477
    enum encryption_mode encmode = ENCRYPTION_MODE_UNKNOWN;
400✔
478
    unsigned char key[256/8];
400✔
479
    size_t maxkeylen = sizeof(key);
400✔
480
    size_t keylen;
400✔
481
    int ret = 0;
400✔
482

483
    if (!options)
400✔
484
        return 0;
485

486
    if (parse_key_options(options, key, maxkeylen, &keylen, &encmode) < 0) {
106✔
487
        ret = -1;
×
488
        goto error;
×
489
    }
490

491
    if (SWTPM_NVRAM_Set_FileKey(key, keylen, encmode) != TPM_SUCCESS) {
106✔
492
        ret = -1;
×
493
        goto error;
×
494
    }
495

496
error:
106✔
497
    /* Wipe to ensure we don't leave a key on the stack */
498
    memset(key, 0, maxkeylen);
106✔
499
    return ret;
106✔
500
}
501

502
/*
503
 * handle_migration_key_options:
504
 * Parse and act upon the parsed key options. Set global values related
505
 * to the options found.
506
 * @options: the key options to parse
507
 *
508
 * Returns 0 on success, -1 on failure.
509
 */
510
int
511
handle_migration_key_options(char *options)
400✔
512
{
513
    enum encryption_mode encmode = ENCRYPTION_MODE_UNKNOWN;
400✔
514
    unsigned char key[256/8];
400✔
515
    size_t maxkeylen = sizeof(key);
400✔
516
    size_t keylen;
400✔
517
    int ret = 0;
400✔
518

519
    if (!options)
400✔
520
        return 0;
521

522
    if (parse_key_options(options, key, maxkeylen, &keylen, &encmode) < 0) {
30✔
523
        ret = -1;
×
524
        goto error;
×
525
    }
526

527
    if (SWTPM_NVRAM_Set_MigrationKey(key, keylen, encmode) != TPM_SUCCESS) {
30✔
528
        ret = -1;
×
529
        goto error;
×
530
    }
531

532
error:
30✔
533
    /* Wipe to ensure we don't leave a key on the stack */
534
    memset(key, 0, maxkeylen);
30✔
535
    return ret;
30✔
536
}
537

538
/*
539
 * parse_pid_options:
540
 * Parse and act upon the parsed 'pid' options.
541
 *
542
 * @options: the 'pid' options to parse
543
 * @pidfile: Point to pointer for pidfile
544
 * @pidfilefd: Pointer to file descriptor for pidfile
545
 *
546
 * Returns 0 on success, -1 on failure.
547
 */
548
static int
549
parse_pid_options(char *options, char **pidfile, int *pidfilefd)
126✔
550
{
551
    OptionValues *ovs = NULL;
126✔
552
    char *error = NULL;
126✔
553
    const char *filename = NULL;
126✔
554
    struct stat stat;
126✔
555

556
    ovs = options_parse(options, pid_opt_desc, &error);
126✔
557
    if (!ovs) {
126✔
558
        logprintf(STDERR_FILENO, "Error parsing pid options: %s\n",
×
559
                  error);
560
        goto error;
×
561
    }
562

563
    filename = option_get_string(ovs, "file", NULL);
126✔
564
    *pidfilefd = option_get_int(ovs, "fd", -1);
126✔
565
    if (!filename && *pidfilefd < 0) {
126✔
566
        logprintf(STDERR_FILENO,
×
567
                  "The file or fd parameter is required for the pid option.\n");
568
        goto error;
×
569
    }
570

571
    if (filename) {
126✔
572
        *pidfile = strdup(filename);
126✔
573
        if (!*pidfile) {
126✔
574
            logprintf(STDERR_FILENO, "Out of memory.");
×
575
            goto error;
×
576
        }
577
    } else {
578
        if (fstat(*pidfilefd, &stat) < 0 || !S_ISREG(stat.st_mode)) {
×
579
            logprintf(STDERR_FILENO,
×
580
                      "Bad filedescriptor %d for pid file\n", *pidfilefd);
581
            goto error;
×
582
        }
583
    }
584

585
    option_values_free(ovs);
126✔
586

587
    return 0;
126✔
588

589
error:
×
590
    option_values_free(ovs);
×
591
    if (*pidfilefd >= 0)
×
592
        close(*pidfilefd);
×
593
    free(error);
×
594

595
    return -1;
×
596
}
597

598
/*
599
 * handle_pidfile_options:
600
 * Parse and act upon the parse pidfile options.
601
 *
602
 * @options: the pidfile options to parse
603
 *
604
 * Returns 0 on success, -1 on failure.
605
 */
606
int
607
handle_pid_options(char *options)
400✔
608
{
609
    char *pidfile = NULL;
400✔
610
    int pidfilefd = -1;
400✔
611
    int ret = 0;
400✔
612

613
    if (!options)
400✔
614
        return 0;
615

616
    if (parse_pid_options(options, &pidfile, &pidfilefd) < 0)
126✔
617
        return -1;
618

619
    if (pidfile && pidfile_set(pidfile) < 0)
126✔
620
        ret = -1;
621
    else if (pidfile_set_fd(pidfilefd) < 0)
126✔
622
        ret = -1;
×
623

624
    free(pidfile);
126✔
625

626
    return ret;
126✔
627
}
628

629
/*
630
 * parse_tpmstate_options:
631
 * Parse and act upon the parsed 'tpmstate' options.
632
 *
633
 * @options: the 'pid' options to parse
634
 * @tpmstatedir: Point to pointer for tpmstatedir
635
 * @mode: the mode of the TPM's state files
636
 * @tpmbackend_uri: Point to pointer for backend URI
637
 *
638
 * Returns 0 on success, -1 on failure.
639
 */
640
static int
641
parse_tpmstate_options(char *options, char **tpmstatedir, mode_t *mode,
212✔
642
                       char **tpmbackend_uri)
643
{
644
    OptionValues *ovs = NULL;
212✔
645
    char *error = NULL;
212✔
646
    const char *directory = NULL;
212✔
647
    const char *backend_uri = NULL;
212✔
648

649
    ovs = options_parse(options, tpmstate_opt_desc, &error);
212✔
650
    if (!ovs) {
212✔
651
        logprintf(STDERR_FILENO, "Error parsing tpmstate options: %s\n",
×
652
                  error);
653
        goto error;
×
654
    }
655

656
    directory = option_get_string(ovs, "dir", NULL);
212✔
657
    *mode = option_get_mode_t(ovs, "mode", 0640);
212✔
658
    backend_uri = option_get_string(ovs, "backend-uri", NULL);
212✔
659

660
    if (directory) {
212✔
661
        *tpmstatedir = strdup(directory);
63✔
662
        if (!*tpmstatedir) {
63✔
663
            logprintf(STDERR_FILENO, "Out of memory.");
×
664
            goto error;
×
665
        }
666
    } else if (backend_uri) {
149✔
667
        *tpmbackend_uri = strdup(backend_uri);
149✔
668
        if (!*tpmbackend_uri) {
149✔
669
            logprintf(STDERR_FILENO, "Out of memory.");
×
670
            goto error;
×
671
        }
672
    } else {
673
        logprintf(STDERR_FILENO,
×
674
                  "The dir or backend-uri parameters is required "
675
                  "for the tpmstate option.\n");
676
        goto error;
×
677
    }
678

679
    option_values_free(ovs);
212✔
680

681
    return 0;
212✔
682

683
error:
×
684
    free(error);
×
685
    option_values_free(ovs);
×
686

687
    return -1;
×
688
}
689

690
/*
691
 * handle_tpmstate_options:
692
 * Parse and act upon the parsed 'tpmstate' options.
693
 *
694
 * @options: the tpmstate options to parse
695
 *
696
 * Returns 0 on success, -1 on failure.
697
 */
698
int
699
handle_tpmstate_options(char *options)
481✔
700
{
701
    char *tpmstatedir = NULL;
481✔
702
    char *tpmbackend_uri = NULL;
481✔
703
    char *temp_uri = NULL;
481✔
704
    int ret = 0;
481✔
705
    mode_t mode;
481✔
706

707
    if (!options)
481✔
708
        return 0;
709

710
    if (parse_tpmstate_options(options, &tpmstatedir, &mode,
212✔
711
                               &tpmbackend_uri) < 0) {
712
        ret = -1;
×
713
        goto error;
×
714
    }
715

716
    if (tpmstatedir) {
212✔
717
        /* Default tpmstate store dir backend */
718
        if (asprintf(&temp_uri, "dir://%s", tpmstatedir) < 0) {
63✔
719
            logprintf(STDERR_FILENO,
×
720
                      "Could not asprintf TPM backend uri\n");
721
            ret = -1;
×
722
            temp_uri = NULL;
×
723
            goto error;
×
724
        }
725

726
        if (tpmstate_set_backend_uri(temp_uri) < 0 ||
126✔
727
            tpmstate_set_mode(mode) < 0) {
63✔
728
            ret = -1;
×
729
            goto error;
×
730
        }
731
    } else {
732
        if (tpmstate_set_backend_uri(tpmbackend_uri) < 0) {
149✔
733
            ret = -1;
×
734
            goto error;
×
735
        }
736
        if ((strncmp(tpmbackend_uri, "dir://", 6) == 0 ||
149✔
737
            strncmp(tpmbackend_uri, "file://", 7)) &&
149✔
738
            tpmstate_set_mode(mode) < 0) {
139✔
739
            ret = -1;
×
740
            goto error;
×
741
        }
742
    }
743

744
error:
149✔
745
    free(tpmstatedir);
212✔
746
    free(tpmbackend_uri);
212✔
747
    free(temp_uri);
212✔
748

749
    return ret;
212✔
750
}
751

752
/*
753
 * unixio_open_socket: Open a UnixIO socket and return file descriptor
754
 *
755
 * @path: UnixIO socket path
756
 * @perm: UnixIO socket permissions
757
 * @uid: uid to set the ownership of the UnixIO socket path to
758
 * @gid: gid to set the ownership of the UnixIO socket path to
759
 */
760
static int unixio_open_socket(const char *path, mode_t perm,
205✔
761
                              uid_t uid, gid_t gid)
762
{
763
    struct sockaddr_un su;
205✔
764
    int fd = -1, n;
205✔
765
    size_t len;
205✔
766

767
    su.sun_family = AF_UNIX;
205✔
768
    len = sizeof(su.sun_path);
205✔
769
    n = snprintf(su.sun_path, len, "%s", path);
205✔
770
    if (n < 0) {
205✔
771
        logprintf(STDERR_FILENO, "Could not nsprintf path to UnixIO socket\n");
×
772
        return -1;
×
773
    }
774
    if (n >= (int)len) {
205✔
775
        logprintf(STDERR_FILENO, "Path for UnioIO socket is too long\n");
×
776
        return -1;
×
777
    }
778

779
    unlink(su.sun_path);
205✔
780

781
    fd = socket(AF_UNIX, SOCK_STREAM, 0);
205✔
782
    if (fd < 0) {
205✔
783
        logprintf(STDERR_FILENO, "Could not open UnixIO socket\n");
×
784
        return -1;
×
785
    }
786

787
    len = strlen(su.sun_path) + sizeof(su.sun_family) + 1;
205✔
788
    n = bind(fd, (struct sockaddr *)&su, len);
205✔
789
    if (n < 0) {
205✔
790
        logprintf(STDERR_FILENO, "Could not open UnixIO socket: %s\n",
×
791
                  strerror(errno));
×
792
        goto error;
×
793
    }
794

795
    if (chmod(su.sun_path, perm) < 0) {
205✔
796
        logprintf(STDERR_FILENO,
×
797
                  "Could not change permssions on UnixIO socket: %s\n",
798
                  strerror(errno));
×
799
        goto error;
×
800
    }
801

802
    if ((uid != (uid_t)-1 || gid != (gid_t)-1) &&
206✔
803
        chown(su.sun_path, uid, gid) < 0) {
1✔
804
        logprintf(STDERR_FILENO,
×
805
                  "Could not change ownership of UnixIO socket to "
806
                  "%u:%u %s\n", uid, gid, strerror(errno));
×
807
        goto error;
×
808
    }
809

810
    n = listen(fd, 1);
205✔
811
    if (n < 0) {
205✔
812
        logprintf(STDERR_FILENO, "Cannot listen on UnixIO socket: %s\n",
×
813
                  strerror(errno));
×
814
        goto error;
×
815
    }
816

817
    return fd;
818

819
error:
×
820
    close(fd);
×
821

822
    return -1;
×
823
}
824

825
/*
826
 * tcp_open_socket: Open a TCP port and return the file descriptor
827
 *
828
 * @port: port number
829
 * @bindadddr: the address to bind the socket to
830
 */
831
static int tcp_open_socket(unsigned short port, const char *bindaddr,
215✔
832
                           const char *ifname)
833
{
834
    int fd = -1, n, af, opt;
215✔
835
    struct sockaddr_in si;
215✔
836
    struct sockaddr_in6 si6;
215✔
837
    struct sockaddr *sa;
215✔
838
    socklen_t sa_len;
215✔
839
    void *dst;
215✔
840

841
    if (index(bindaddr, ':')) {
215✔
842
        af = AF_INET6;
1✔
843

844
        memset(&si6, 0, sizeof(si6));
1✔
845
        si6.sin6_family = af;
1✔
846
        si6.sin6_port = htons(port);
1✔
847

848
        dst = &si6.sin6_addr.s6_addr;
1✔
849
        sa = (struct sockaddr *)&si6;
1✔
850
        sa_len = sizeof(si6);
1✔
851
    } else {
852
        af = AF_INET;
214✔
853

854
        si.sin_family = af;
214✔
855
        si.sin_port = htons(port);
214✔
856
        memset(&si.sin_zero, 0, sizeof(si.sin_zero));
214✔
857

858
        dst = &si.sin_addr.s_addr;
214✔
859
        sa = (struct sockaddr *)&si;
214✔
860
        sa_len = sizeof(si);
214✔
861
    }
862

863
    n = inet_pton(af, bindaddr, dst);
215✔
864
    if (n <= 0) {
215✔
865
        logprintf(STDERR_FILENO, "Could not parse the bind address '%s'\n",
×
866
                  bindaddr);
867
        return -1;
×
868
    }
869

870
    if (af == AF_INET6) {
215✔
871
        if (IN6_IS_ADDR_LINKLOCAL(&si6.sin6_addr)) {
1✔
872
            if (!ifname) {
×
873
                logprintf(STDERR_FILENO,
×
874
                          "Missing interface name for link local address\n");
875
                return -1;
×
876
            }
877
            n = if_nametoindex(ifname);
×
878
            if (!n) {
×
879
                logprintf(STDERR_FILENO,
×
880
                          "Could not convert interface name '%s' to "
881
                          "index: %s\n",
882
                          ifname, strerror(errno));
×
883
                return -1;
×
884
            }
885
            si6.sin6_scope_id = n;
×
886
        }
887
    }
888

889
    fd = socket(af, SOCK_STREAM, 0);
215✔
890
    if (fd < 0) {
215✔
891
        logprintf(STDERR_FILENO, "Could not open TCP socket\n");
×
892
        return -1;
×
893
    }
894

895
    opt = 1;
215✔
896
    n = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
215✔
897
    if (n < 0) {
215✔
898
        logprintf(STDERR_FILENO,
×
899
                  "Could not set socket option SO_REUSEADDR: %s\n",
900
                  strerror(errno));
×
901
        goto error;
×
902
    }
903

904
    n = bind(fd, sa, sa_len);
215✔
905
    if (n < 0) {
215✔
906
        logprintf(STDERR_FILENO, "Could not open TCP socket: %s\n",
×
907
                  strerror(errno));
×
908
        goto error;
×
909
    }
910

911
    n = listen(fd, 1);
215✔
912
    if (n < 0) {
215✔
913
        logprintf(STDERR_FILENO, "Cannot listen on TCP socket: %s\n",
×
914
                  strerror(errno));
×
915
        goto error;
×
916
    }
917

918
    return fd;
919

920
error:
×
921
    close(fd);
×
922

923
    return -1;
×
924
}
925

926
/*
927
 * parse_ctrlchannel_options:
928
 * Parse the 'ctrl' (control channel) options.
929
 *
930
 * @options: the control channel options to parse
931
 * @cc: pointer for pointer to allocated ctrlchannel struct
932
 * @mainloop_flags: pointer to mainloop flags to add a flag to
933
 *
934
 * Returns 0 on success, -1 on failure.
935
 */
936
static int parse_ctrlchannel_options(char *options, struct ctrlchannel **cc,
284✔
937
                                     uint32_t *mainloop_flags)
938
{
939
    OptionValues *ovs = NULL;
284✔
940
    char *error = NULL;
284✔
941
    const char *type, *path, *bindaddr, *ifname;
284✔
942
    int fd, clientfd, port;
284✔
943
    struct stat stat;
284✔
944
    mode_t mode;
284✔
945
    uid_t uid;
284✔
946
    gid_t gid;
284✔
947

948
    ovs = options_parse(options, ctrl_opt_desc, &error);
284✔
949
    if (!ovs) {
284✔
950
        logprintf(STDERR_FILENO, "Error parsing ctrl options: %s\n", error);
×
951
        goto error;
×
952
    }
953

954
    type = option_get_string(ovs, "type", NULL);
284✔
955
    if (!type) {
284✔
956
        logprintf(STDERR_FILENO,
×
957
                  "Missing type parameter for control channel\n");
958
        goto error;
×
959
    }
960

961
    if (!strcmp(type, "unixio")) {
284✔
962
        path = option_get_string(ovs, "path", NULL);
216✔
963
        fd = option_get_int(ovs, "fd", -1);
216✔
964
        clientfd = option_get_int(ovs, "clientfd", -1);
216✔
965
        mode = option_get_mode_t(ovs, "mode", 0770);
216✔
966
        uid = option_get_uid_t(ovs, "uid", -1);
216✔
967
        gid = option_get_gid_t(ovs, "gid", -1);
216✔
968
        if (fd >= 0) {
216✔
969
            if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) {
×
970
               logprintf(STDERR_FILENO,
×
971
                         "Bad filedescriptor %d for UnixIO control channel\n",
972
                         fd);
973
               goto error;
×
974
            }
975

976
            *cc = ctrlchannel_new(fd, false, NULL);
×
977
        } else if (clientfd >= 0) {
216✔
978
            if (fstat(clientfd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) {
73✔
979
               logprintf(STDERR_FILENO,
×
980
                         "Bad filedescriptor %d for UnixIO client control"
981
                         " channel\n", clientfd);
982
               goto error;
×
983
            }
984

985
            *cc = ctrlchannel_new(clientfd, true, NULL);
73✔
986
        } else if (path) {
143✔
987
            fd = unixio_open_socket(path, mode, uid, gid);
143✔
988
            if (fd < 0)
143✔
989
                goto error;
×
990

991
            *cc = ctrlchannel_new(fd, false, path);
143✔
992
        } else {
993
            logprintf(STDERR_FILENO,
×
994
                      "Missing path and fd options for UnixIO "
995
                      "control channel\n");
996
            goto error;
×
997
        }
998
    } else if (!strcmp(type, "tcp")) {
68✔
999
        port = option_get_int(ovs, "port", -1);
68✔
1000
        fd = option_get_int(ovs, "fd", -1);
68✔
1001
        if (fd >= 0) {
68✔
1002
            if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) {
×
1003
               logprintf(STDERR_FILENO,
×
1004
                         "Bad filedescriptor %d for TCP control channel\n", fd);
1005
               goto error;
×
1006
            }
1007

1008
            *cc = ctrlchannel_new(fd, false, NULL);
×
1009
        } else if (port >= 0) {
68✔
1010
            if (port >= 0x10000) {
68✔
1011
                logprintf(STDERR_FILENO,
×
1012
                          "TCP control channel port outside valid range\n");
1013
                goto error;
×
1014
            }
1015

1016
            bindaddr = option_get_string(ovs, "bindaddr", "127.0.0.1");
68✔
1017
            ifname = option_get_string(ovs, "ifname", NULL);
68✔
1018

1019
            fd = tcp_open_socket(port, bindaddr, ifname);
68✔
1020
            if (fd < 0)
68✔
1021
                goto error;
×
1022

1023
            *cc = ctrlchannel_new(fd, false, NULL);
68✔
1024
        } else {
1025
            logprintf(STDERR_FILENO,
×
1026
                      "Missing port and fd options for TCP control channel\n");
1027
            goto error;
×
1028
        }
1029
    } else {
1030
        logprintf(STDERR_FILENO, "Unsupport control channel type: %s\n", type);
×
1031
        goto error;
×
1032
    }
1033

1034
    if (*cc == NULL)
284✔
1035
        goto error;
×
1036

1037
    if (option_get_bool(ovs, "terminate", false))
284✔
1038
        *mainloop_flags |= MAIN_LOOP_FLAG_CTRL_END_ON_HUP;
4✔
1039

1040
    option_values_free(ovs);
284✔
1041

1042
    return 0;
284✔
1043

1044
error:
×
1045
    free(error);
×
1046
    option_values_free(ovs);
×
1047

1048
    return -1;
×
1049
}
1050

1051
/*
1052
 * handle_ctrlchannel_options:
1053
 * Parse and act upon the parsed 'ctrl' (control channel) options.
1054
 *
1055
 * @options: the control channel options to parse
1056
 * @cc: pointer for pointer to allocated ctrlchannel struct
1057
 * @mainloop_flags: pointer to mainloop flags to add a flag to
1058
 *
1059
 * Returns 0 on success, -1 on failure.
1060
 */
1061
int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc,
362✔
1062
                               uint32_t *mainloop_flag)
1063
{
1064
    if (!options)
362✔
1065
        return 0;
1066

1067
    if (parse_ctrlchannel_options(options, cc, mainloop_flag) < 0)
284✔
1068
        return -1;
×
1069

1070
    return 0;
1071
}
1072

1073
/*
1074
 * parse_server_options:
1075
 * Parse the 'server' options.
1076
 *
1077
 * @options: the server options to parse
1078
 *
1079
 * Returns 0 on success, -1 on failure.
1080
 */
1081
static int parse_server_options(char *options, struct server **c)
281✔
1082
{
1083
    OptionValues *ovs = NULL;
281✔
1084
    char *error = NULL;
281✔
1085
    const char *bindaddr, *ifname;
281✔
1086
    const char *type, *path;
281✔
1087
    int fd, port;
281✔
1088
    struct stat stat;
281✔
1089
    unsigned int flags = 0;
281✔
1090
    mode_t mode;
281✔
1091
    uid_t uid;
281✔
1092
    gid_t gid;
281✔
1093

1094
    *c = NULL;
281✔
1095

1096
    ovs = options_parse(options, server_opt_desc, &error);
281✔
1097
    if (!ovs) {
281✔
1098
        logprintf(STDERR_FILENO, "Error parsing server options: %s\n", error);
×
1099
        goto error;
×
1100
    }
1101

1102
    type = option_get_string(ovs, "type", "tcp");
281✔
1103

1104
    if (option_get_bool(ovs, "disconnect", false))
281✔
1105
        flags |= SERVER_FLAG_DISCONNECT;
121✔
1106

1107
    if (!strcmp(type, "unixio")) {
281✔
1108
        path = option_get_string(ovs, "path", NULL);
62✔
1109
        fd = option_get_int(ovs, "fd", -1);
62✔
1110
        mode = option_get_mode_t(ovs, "mode", 0770);
62✔
1111
        uid = option_get_uid_t(ovs, "uid", -1);
62✔
1112
        gid = option_get_gid_t(ovs, "gid", -1);
62✔
1113
        if (fd >= 0) {
62✔
1114
            if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) {
×
1115
               logprintf(STDERR_FILENO,
×
1116
                         "Bad filedescriptor %d for UnixIO control channel\n",
1117
                         fd);
1118
               goto error;
×
1119
            }
1120

1121
            *c = server_new(fd, flags, NULL);
×
1122
        } else if (path) {
62✔
1123
            fd = unixio_open_socket(path, mode, uid, gid);
62✔
1124
            if (fd < 0)
62✔
1125
                goto error;
×
1126

1127
            *c = server_new(fd, flags, path);
62✔
1128
        } else {
1129
            logprintf(STDERR_FILENO,
×
1130
                      "Missing path and file descriptor option for UnixIO "
1131
                      "socket\n");
1132
            goto error;
×
1133
        }
1134
    } else if (!strcmp(type, "tcp")) {
219✔
1135
        fd = option_get_int(ovs, "fd", -1);
219✔
1136
        if (fd >= 0) {
219✔
1137
            if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) {
72✔
1138
               logprintf(STDERR_FILENO,
×
1139
                         "Bad filedescriptor %d for TCP socket\n", fd);
1140
               goto error;
×
1141
            }
1142

1143
            flags |= SERVER_FLAG_FD_GIVEN;
72✔
1144

1145
            *c = server_new(fd, flags, NULL);
72✔
1146
        } else {
1147
            port = option_get_int(ovs, "port", -1);
147✔
1148
            if (port == -1) {
147✔
1149
                const char *port_str = getenv("TPM_PORT");
3✔
1150
                if (!port_str || sscanf(port_str, "%d", &port) == -1)
3✔
1151
                    port = -1;
×
1152
            }
1153
            if (port < 0) {
147✔
1154
                logprintf(STDERR_FILENO,
×
1155
                      "No valid port number provided for TCP socket.\n");
1156
                goto error;
×
1157
            }
1158
            if (port >= 0x10000) {
147✔
1159
                logprintf(STDERR_FILENO,
×
1160
                          "TCP socket port outside valid range\n");
1161
                goto error;
×
1162
            }
1163

1164
            bindaddr = option_get_string(ovs, "bindaddr", "127.0.0.1");
147✔
1165
            ifname = option_get_string(ovs, "ifname", NULL);
147✔
1166

1167
            fd = tcp_open_socket(port, bindaddr, ifname);
147✔
1168
            if (fd < 0)
147✔
1169
                goto error;
×
1170

1171
            *c = server_new(fd, flags, NULL);
147✔
1172
        }
1173
    } else {
1174
        logprintf(STDERR_FILENO, "Unsupport socket type: %s\n", type);
×
1175
        goto error;
×
1176
    }
1177

1178
    if (*c == NULL)
281✔
1179
        goto error;
×
1180

1181
    option_values_free(ovs);
281✔
1182

1183
    return 0;
281✔
1184

1185
error:
×
1186
    if (*c) {
×
1187
        server_free(*c);
×
1188
        *c = NULL;
×
1189
    }
1190
    option_values_free(ovs);
×
1191
    free(error);
×
1192

1193
    return -1;
×
1194
}
1195

1196
/*
1197
 * handle_server_options:
1198
 * Parse and act upon the parsed 'server' options.
1199
 *
1200
 * @options: the server options to parse
1201
 *
1202
 * Returns 0 on success, -1 on failure.
1203
 */
1204
int handle_server_options(char *options, struct server **c)
359✔
1205
{
1206
    if (!options)
359✔
1207
        return 0;
1208

1209
    if (parse_server_options(options, c) < 0)
281✔
1210
        return -1;
×
1211

1212
    return 0;
1213
}
1214

1215
static int parse_locality_options(char *options, uint32_t *flags)
1216
{
1217
    OptionValues *ovs = NULL;
×
1218
    char *error = NULL;
×
1219

1220
    ovs = options_parse(options, locality_opt_desc, &error);
×
1221
    if (!ovs) {
×
1222
        logprintf(STDERR_FILENO, "Error parsing locality options: %s\n", error);
×
1223
        goto error;
×
1224
    }
1225

1226
    if (option_get_bool(ovs, "reject-locality-4", false))
×
1227
        *flags |= LOCALITY_FLAG_REJECT_LOCALITY_4;
×
1228
    if (option_get_bool(ovs, "allow-set-locality", false))
×
1229
        *flags |= LOCALITY_FLAG_ALLOW_SETLOCALITY;
×
1230

1231
    option_values_free(ovs);
×
1232

1233
    return 0;
×
1234

1235
error:
×
1236
    option_values_free(ovs);
×
1237
    free(error);
×
1238

1239
    return -1;
×
1240
}
1241

1242
/*
1243
 * handle_locality_options:
1244
 * Parse the 'locality' options.
1245
 *
1246
 * @options: the locality options to parse
1247
 *
1248
 * Returns 0 on success, -1 on failure.
1249
 */
1250
int handle_locality_options(char *options, uint32_t *flags)
403✔
1251
{
1252
    *flags = 0;
403✔
1253

1254
    if (!options)
403✔
1255
        return 0;
1256

1257
    if (parse_locality_options(options, flags) < 0)
×
1258
        return -1;
×
1259

1260
    return 0;
1261
}
1262

1263
static int parse_flags_options(char *options, bool *need_init_cmd,
95✔
1264
                               uint16_t *startupType, bool *disable_auto_shutdown)
1265
{
1266
    OptionValues *ovs = NULL;
95✔
1267
    char *error = NULL;
95✔
1268

1269
    ovs = options_parse(options, flags_opt_desc, &error);
95✔
1270
    if (!ovs) {
95✔
1271
        logprintf(STDERR_FILENO, "Error parsing flags options: %s\n", error);
×
1272
        goto error;
×
1273
    }
1274

1275
    if (option_get_bool(ovs, "not-need-init", false))
95✔
1276
        *need_init_cmd = false;
94✔
1277
    if (option_get_bool(ovs, "disable-auto-shutdown", false))
95✔
1278
        *disable_auto_shutdown = true;
×
1279

1280
    if (option_get_bool(ovs, "startup-clear", false))
95✔
1281
        *startupType = TPM_ST_CLEAR;
81✔
1282
    else if (option_get_bool(ovs, "startup-state", false))
14✔
1283
        *startupType = TPM_ST_STATE;
×
1284
    else if (option_get_bool(ovs, "startup-deactivated", false))
14✔
1285
        *startupType = TPM_ST_DEACTIVATED;
×
1286
    else if (option_get_bool(ovs, "startup-none", false))
14✔
1287
        *startupType = _TPM_ST_NONE;
×
1288

1289
    if (*startupType != _TPM_ST_NONE)
95✔
1290
        *need_init_cmd = false;
81✔
1291

1292
    option_values_free(ovs);
95✔
1293

1294
    return 0;
95✔
1295

1296
error:
×
1297
    option_values_free(ovs);
×
1298
    free(error);
×
1299

1300
    return -1;
×
1301
}
1302

1303
/*
1304
 * handle_flags_options:
1305
 * Parse the 'flags' options.
1306
 *
1307
 * @options: the flags options to parse
1308
 *
1309
 * Returns 0 on success, -1 on failure.
1310
 */
1311
int handle_flags_options(char *options, bool *need_init_cmd,
400✔
1312
                         uint16_t *startupType, bool *disable_auto_shutdown)
1313
{
1314
    if (!options)
400✔
1315
        return 0;
1316

1317
    if (parse_flags_options(options, need_init_cmd, startupType,
95✔
1318
                            disable_auto_shutdown) < 0)
1319
        return -1;
×
1320

1321
    return 0;
1322
}
1323

1324
#ifdef WITH_SECCOMP
1325
static int parse_seccomp_options(char *options, unsigned int *seccomp_action)
10✔
1326
{
1327
    OptionValues *ovs = NULL;
10✔
1328
    char *error = NULL;
10✔
1329
    const char *action;
10✔
1330

1331
    ovs = options_parse(options, seccomp_opt_desc, &error);
10✔
1332
    if (!ovs) {
10✔
1333
        logprintf(STDERR_FILENO, "Error parsing seccomp options: %s\n", error);
×
1334
        goto error;
×
1335
    }
1336

1337
    action = option_get_string(ovs, "action", "kill");
10✔
1338
    if (!strcmp(action, "kill")) {
10✔
1339
        *seccomp_action = SWTPM_SECCOMP_ACTION_KILL;
×
1340
#ifdef SCMP_ACT_LOG
1341
    } else if (!strcmp(action, "log")) {
10✔
1342
        *seccomp_action = SWTPM_SECCOMP_ACTION_LOG;
×
1343
#endif
1344
    } else if (!strcmp(action, "none")) {
10✔
1345
        *seccomp_action = SWTPM_SECCOMP_ACTION_NONE;
10✔
1346
    } else {
1347
        logprintf(STDERR_FILENO,
×
1348
                  "Unsupported seccomp log action %s\n", action);
1349
        goto error;
×
1350
    }
1351

1352
    option_values_free(ovs);
10✔
1353

1354
    return 0;
10✔
1355

1356
error:
×
1357
    option_values_free(ovs);
×
1358
    free(error);
×
1359

1360
    return -1;
×
1361
}
1362

1363
/*
1364
 * handle_seccomp_options:
1365
 * Parse the 'seccomp' options.
1366
 *
1367
 * @options: the flags options to parse
1368
 * @seccomp_action: the action to take when 
1369
 *
1370
 * Returns 0 on success, -1 on failure.
1371
 */
1372
int handle_seccomp_options(char *options, unsigned int *seccomp_action)
400✔
1373
{
1374
    *seccomp_action = SWTPM_SECCOMP_ACTION_KILL;
400✔
1375

1376
    if (!options)
400✔
1377
        return 0;
1378

1379
    if (parse_seccomp_options(options, seccomp_action) < 0)
10✔
1380
        return -1;
×
1381

1382
    return 0;
1383
}
1384
#endif /* WITH_SECCOMP */
1385

1386
static int parse_migration_options(char *options, bool *incoming_migration,
10✔
1387
                                   bool *release_lock_outgoing)
1388
{
1389
    OptionValues *ovs = NULL;
10✔
1390
    char *error = NULL;
10✔
1391

1392
    ovs = options_parse(options, migration_opt_desc, &error);
10✔
1393
    if (!ovs) {
10✔
1394
        logprintf(STDERR_FILENO, "Error parsing migration options: %s\n", error);
×
1395
        goto error;
×
1396
    }
1397

1398
    *incoming_migration = option_get_bool(ovs, "incoming", false);
10✔
1399
    *release_lock_outgoing = option_get_bool(ovs, "release-lock-outgoing",
10✔
1400
                                             false);
1401

1402
    option_values_free(ovs);
10✔
1403

1404
    return 0;
10✔
1405

1406
error:
×
1407
    option_values_free(ovs);
×
1408
    free(error);
×
1409

1410
    return -1;
×
1411
}
1412

1413
/*
1414
 * handle_migration_options:
1415
 * Parse the 'migration' options.
1416
 *
1417
 * @options: the migration options to parse
1418
 * @incoming_migration: whether there's an incoming migration
1419
 * @release_lock_outgoing: whether to release NVRAM lock on outgoing migration
1420
 *
1421
 * Return 0 on success, -1 on failure.
1422
 */
1423
int handle_migration_options(char *options, bool *incoming_migration,
400✔
1424
                             bool *release_lock_outgoing)
1425
{
1426
    *incoming_migration = false;
400✔
1427

1428
    if (!options)
400✔
1429
        return 0;
1430

1431
    if (parse_migration_options(options, incoming_migration,
10✔
1432
                                release_lock_outgoing) < 0)
1433
        return -1;
×
1434

1435
    return 0;
1436
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc