From 8f7e1b6e60345a99bf24b620d767a37ace6be54c Mon Sep 17 00:00:00 2001 From: yezengruan Date: Tue, 5 Jul 2022 10:28:11 +0800 Subject: [PATCH] Addressed potential symlink attack issue (CVE-2020-28407) --- ...er-size-indicator-against-expected-s.patch | 2 +- ...s.patch => 0001-Disable-broken-tests.patch | 0 ...e-files-atomically-using-file-renami.patch | 164 ++++++++++++++ ...h-to-open-from-fopen-for-writing-cer.patch | 77 +++++++ ...low-symlinks-when-opening-lockfile-C.patch | 32 +++ ...open-from-fopen-for-the-pidfile-CVE-.patch | 103 +++++++++ ...ot-fopen-when-accessing-statefile-CV.patch | 211 ++++++++++++++++++ swtpm.spec | 16 +- 8 files changed, 600 insertions(+), 5 deletions(-) rename CVE-2022-23645.patch => 0000-swtpm-Check-header-size-indicator-against-expected-s.patch (96%) rename Disable-broken-tests.patch => 0001-Disable-broken-tests.patch (100%) create mode 100644 0002-swtpm-Write-state-files-atomically-using-file-renami.patch create mode 100644 0003-swtpm_cert-Switch-to-open-from-fopen-for-writing-cer.patch create mode 100644 0004-swtpm-Do-not-follow-symlinks-when-opening-lockfile-C.patch create mode 100644 0005-swtpm-Switch-to-open-from-fopen-for-the-pidfile-CVE-.patch create mode 100644 0006-swtpm-Use-open-not-fopen-when-accessing-statefile-CV.patch diff --git a/CVE-2022-23645.patch b/0000-swtpm-Check-header-size-indicator-against-expected-s.patch similarity index 96% rename from CVE-2022-23645.patch rename to 0000-swtpm-Check-header-size-indicator-against-expected-s.patch index 705d2c5..7d6b4d7 100644 --- a/CVE-2022-23645.patch +++ b/0000-swtpm-Check-header-size-indicator-against-expected-s.patch @@ -4,7 +4,7 @@ Date: Wed, 16 Feb 2022 11:17:47 -0500 Subject: [PATCH] swtpm: Check header size indicator against expected size (CID 375869) -This fix addresses Coverity issue CID 375869. +This fix addresses Coverity issue CID 375869 (CVE-2022-23645). Check the header size indicated in the header of the state against the expected size and return an error code in case the header size indicator diff --git a/Disable-broken-tests.patch b/0001-Disable-broken-tests.patch similarity index 100% rename from Disable-broken-tests.patch rename to 0001-Disable-broken-tests.patch diff --git a/0002-swtpm-Write-state-files-atomically-using-file-renami.patch b/0002-swtpm-Write-state-files-atomically-using-file-renami.patch new file mode 100644 index 0000000..be3cbbf --- /dev/null +++ b/0002-swtpm-Write-state-files-atomically-using-file-renami.patch @@ -0,0 +1,164 @@ +From b3a5dde7f5a8874084f978ea698a749d858e769a Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Fri, 2 Oct 2020 16:29:18 -0400 +Subject: [PATCH 1/5] swtpm: Write state files atomically using file renaming + +To support writing state files atomically we first write into +a temporary file and then rename it. + +Signed-off-by: Stefan Berger +--- + src/swtpm/swtpm_nvfile.c | 59 ++++++++++++++++++++++++++++++---------- + 1 file changed, 45 insertions(+), 14 deletions(-) + +diff --git a/src/swtpm/swtpm_nvfile.c b/src/swtpm/swtpm_nvfile.c +index 6f3f937..3b928d0 100644 +--- a/src/swtpm/swtpm_nvfile.c ++++ b/src/swtpm/swtpm_nvfile.c +@@ -132,7 +132,8 @@ static unsigned char *g_ivec; + static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, + size_t bufsize, + uint32_t tpm_number, +- const char *name); ++ const char *name, ++ bool is_tempfile); + + static TPM_RESULT SWTPM_NVRAM_EncryptData(const encryptionkey *key, + tlv_data *td, +@@ -312,7 +313,7 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + if (rc == 0) { + /* map name to the rooted filename */ + rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), +- tpm_number, name); ++ tpm_number, name, false); + } + + if (rc == 0) { +@@ -473,6 +474,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + uint32_t lrc; + int irc; + FILE *file = NULL; ++ char tmpfile[FILENAME_MAX]; /* rooted temporary file */ + char filename[FILENAME_MAX]; /* rooted file name from name */ + unsigned char *filedata = NULL; + uint32_t filedata_length = 0; +@@ -484,16 +486,24 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + if (rc == 0) { + /* map name to the rooted filename */ + rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), +- tpm_number, name); ++ tpm_number, name, false); + } ++ ++ if (rc == 0) { ++ /* map name to the rooted temporary file */ ++ rc = SWTPM_NVRAM_GetFilenameForName(tmpfile, sizeof(tmpfile), ++ tpm_number, name, true); ++ } ++ ++ + if (rc == 0) { + /* open the file */ +- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", filename); +- file = fopen(filename, "wb"); /* closed @1 */ ++ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile); ++ file = fopen(tmpfile, "wb"); /* closed @1 */ + if (file == NULL) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " +- "write failed, %s\n", filename, strerror(errno)); ++ "write failed, %s\n", tmpfile, strerror(errno)); + rc = TPM_FAIL; + } + } +@@ -502,7 +512,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + if (fchmod(fileno(file), tpmstate_get_mode()) < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Could not fchmod %s : %s\n", +- filename, strerror(errno)); ++ tmpfile, strerror(errno)); + rc = TPM_FAIL; + } + } +@@ -548,7 +558,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + } + } + if (file != NULL) { +- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", filename); ++ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile); + irc = fclose(file); /* @1 */ + if (irc != 0) { + logprintf(STDERR_FILENO, +@@ -556,12 +566,24 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + rc = TPM_FAIL; + } + else { +- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", filename); ++ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", tmpfile); ++ } ++ } ++ ++ if (rc == 0 && file != NULL) { ++ irc = rename(tmpfile, filename); ++ if (irc != 0) { ++ logprintf(STDERR_FILENO, ++ "SWTPM_NVRAM_StoreData: Error (fatal) renaming file: %s\n", ++ strerror(errno)); ++ rc = TPM_FAIL; ++ } else { ++ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Renamed file to %s\n", filename); + } + } + + if (rc != 0 && file != NULL) { +- unlink(filename); ++ unlink(tmpfile); + } + + tlv_data_free(td, td_len); +@@ -585,12 +607,16 @@ TPM_RESULT SWTPM_NVRAM_StoreData(const unsigned char *data, + The filename is of the form: + + state_directory/tpm_number.name ++ ++ A temporary filename used to write to may be created. It shold be rename()'d to ++ the non-temporary filename. + */ + + static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */ + size_t bufsize, + uint32_t tpm_number, +- const char *name) /* input: abstract name */ ++ const char *name, /* input: abstract name */ ++ bool is_tempfile) /* input: is temporary file? */ + { + TPM_RESULT res = TPM_SUCCESS; + int n; +@@ -606,8 +632,13 @@ static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, /* outpu + break; + } + +- n = snprintf(filename, bufsize, "%s/tpm%s-%02lx.%s", +- state_directory, suffix, (unsigned long)tpm_number, name); ++ if (is_tempfile) { ++ n = snprintf(filename, bufsize, "%s/TMP%s-%02lx.%s", ++ state_directory, suffix, (unsigned long)tpm_number, name); ++ } else { ++ n = snprintf(filename, bufsize, "%s/tpm%s-%02lx.%s", ++ state_directory, suffix, (unsigned long)tpm_number, name); ++ } + if ((size_t)n > bufsize) { + res = TPM_FAIL; + } +@@ -638,7 +669,7 @@ TPM_RESULT SWTPM_NVRAM_DeleteName(uint32_t tpm_number, + TPM_DEBUG(" SWTPM_NVRAM_DeleteName: Name %s\n", name); + /* map name to the rooted filename */ + rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), +- tpm_number, name); ++ tpm_number, name, false); + if (rc == 0) { + irc = remove(filename); + if ((irc != 0) && /* if the remove failed */ +-- +2.27.0 + diff --git a/0003-swtpm_cert-Switch-to-open-from-fopen-for-writing-cer.patch b/0003-swtpm_cert-Switch-to-open-from-fopen-for-writing-cer.patch new file mode 100644 index 0000000..b7894bb --- /dev/null +++ b/0003-swtpm_cert-Switch-to-open-from-fopen-for-writing-cer.patch @@ -0,0 +1,77 @@ +From ba12415fca1a3891a1386698eab09735a025d7ea Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Sun, 8 Nov 2020 21:40:35 -0500 +Subject: [PATCH 2/5] swtpm_cert: Switch to open() from fopen() for writing + certificate + +Switch to open from fopen() and make sure we do not follow symlinks. + +Signed-off-by: Stefan Berger +--- + src/swtpm_cert/ek-cert.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/src/swtpm_cert/ek-cert.c b/src/swtpm_cert/ek-cert.c +index 651d60f..0e0b4b1 100644 +--- a/src/swtpm_cert/ek-cert.c ++++ b/src/swtpm_cert/ek-cert.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + + #include + +@@ -995,7 +996,7 @@ main(int argc, char *argv[]) + unsigned long long serial = 1; + time_t now; + int err; +- FILE *cert_file; ++ int cert_file_fd; + const char *subject = NULL; + const char *error = NULL; + int days = 365; +@@ -1675,8 +1676,9 @@ if (_err != GNUTLS_E_SUCCESS) { \ + ? GNUTLS_X509_FMT_PEM + : GNUTLS_X509_FMT_DER, &out); + if (cert_filename) { +- cert_file = fopen(cert_filename, "wb"); +- if (cert_file == NULL) { ++ cert_file_fd = open(cert_filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, ++ S_IRUSR|S_IWUSR); ++ if (cert_file_fd < 0) { + fprintf(stderr, "Could not open %s for writing the certificate: %s\n", + cert_filename, + strerror(errno)); +@@ -1691,22 +1693,22 @@ if (_err != GNUTLS_E_SUCCESS) { \ + }, + .tag = htobe16(TCG_TAG_PCCLIENT_FULL_CERT), + }; +- if (sizeof(hdr) != fwrite(&hdr, 1, sizeof(hdr), cert_file)) { ++ if (sizeof(hdr) != write(cert_file_fd, &hdr, sizeof(hdr))) { + fprintf(stderr, "Could not write certificate header: %s\n", + strerror(errno)); +- fclose(cert_file); ++ close(cert_file_fd); + unlink(cert_filename); + goto cleanup; + } + } +- if (out.size != fwrite(out.data, 1, out.size, cert_file)) { ++ if ((ssize_t)out.size != write(cert_file_fd, out.data, out.size)) { + fprintf(stderr, "Could not write certificate into file: %s\n", + strerror(errno)); +- fclose(cert_file); ++ close(cert_file_fd); + unlink(cert_filename); + goto cleanup; + } +- fclose(cert_file); ++ close(cert_file_fd); + } else { + fprintf(stdout, "%s\n", out.data); + } +-- +2.27.0 + diff --git a/0004-swtpm-Do-not-follow-symlinks-when-opening-lockfile-C.patch b/0004-swtpm-Do-not-follow-symlinks-when-opening-lockfile-C.patch new file mode 100644 index 0000000..98510ed --- /dev/null +++ b/0004-swtpm-Do-not-follow-symlinks-when-opening-lockfile-C.patch @@ -0,0 +1,32 @@ +From 15a0b58ca43ccbae26d1a1e7718d7d8bd2c2add2 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Sun, 8 Nov 2020 21:45:40 -0500 +Subject: [PATCH 3/5] swtpm: Do not follow symlinks when opening lockfile + (CVE-2020-28407) + +This patch addresses CVE-2020-28407. + +Prevent us from following symliks when we open the lockfile +for writing. + +Signed-off-by: Stefan Berger +--- + src/swtpm/swtpm_nvfile.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/swtpm/swtpm_nvfile.c b/src/swtpm/swtpm_nvfile.c +index 3b928d0..8a6621b 100644 +--- a/src/swtpm/swtpm_nvfile.c ++++ b/src/swtpm/swtpm_nvfile.c +@@ -210,7 +210,7 @@ static TPM_RESULT SWTPM_NVRAM_Lock_Lockfile(const char *directory, + return TPM_FAIL; + } + +- *fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC, 0660); ++ *fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0660); + if (*fd < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_Lock_Lockfile: Could not open lockfile: %s\n", +-- +2.27.0 + diff --git a/0005-swtpm-Switch-to-open-from-fopen-for-the-pidfile-CVE-.patch b/0005-swtpm-Switch-to-open-from-fopen-for-the-pidfile-CVE-.patch new file mode 100644 index 0000000..fedcc02 --- /dev/null +++ b/0005-swtpm-Switch-to-open-from-fopen-for-the-pidfile-CVE-.patch @@ -0,0 +1,103 @@ +From 934603eb6adb2d646364132bbac7bdb30ccb97bf Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Sun, 8 Nov 2020 22:21:23 -0500 +Subject: [PATCH 4/5] swtpm: Switch to open() from fopen() for the pidfile + (CVE-2020-28407) + +This patch addresses CVE-2020-28407. + +Use the open() call rather than the fopen() call when creating a pidfile. +Also prevent us from following symbolic links when opening the pidfile for +writing. + +Signed-off-by: Stefan Berger +--- + src/swtpm/pidfile.c | 41 ++++++++++++++++++++++++++--------------- + 1 file changed, 26 insertions(+), 15 deletions(-) + +diff --git a/src/swtpm/pidfile.c b/src/swtpm/pidfile.c +index f9d18ad..afca5b0 100644 +--- a/src/swtpm/pidfile.c ++++ b/src/swtpm/pidfile.c +@@ -37,11 +37,13 @@ + + #include "config.h" + ++#include ++#include ++#include + #include + #include + #include + #include +-#include + + #include "pidfile.h" + #include "logging.h" +@@ -77,40 +79,49 @@ int pidfile_set_fd(int newpidfilefd) + */ + int pidfile_write(pid_t pid) + { +- FILE *f; ++ int fd; ++ char buffer[32]; ++ ssize_t nwritten; + + if (g_pidfile) { +- f = fopen(g_pidfile, "w+"); ++ fd = open(g_pidfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, ++ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + } else if (pidfilefd >= 0) { +- f = fdopen(pidfilefd, "w"); +- if (f) { +- g_pidfile = fd_to_filename(pidfilefd); +- if (!g_pidfile) +- goto error; +- } ++ fd = pidfilefd; ++ g_pidfile = fd_to_filename(pidfilefd); ++ if (!g_pidfile) ++ goto error; + } else { + return 0; + } + +- if (!f) { ++ if (fd < 0) { + logprintf(STDERR_FILENO, "Could not open pidfile %s : %s\n", + g_pidfile, strerror(errno)); + goto error; + } + +- if (fprintf(f, "%d", pid) < 0) { ++ if (snprintf(buffer, sizeof(buffer), "%d", pid) >= (int)sizeof(buffer)) { ++ logprintf(STDERR_FILENO, "Could not write pid to buffer\n"); ++ goto error_close; ++ } ++ ++ nwritten = write_full(fd, buffer, strlen(buffer)); ++ if (nwritten < 0 || nwritten != (ssize_t)strlen(buffer)) { + logprintf(STDERR_FILENO, "Could not write to pidfile : %s\n", + strerror(errno)); +- goto error; ++ goto error_close; + } + +- fclose(f); ++ close(fd); + + return 0; + ++error_close: ++ if (fd != pidfilefd) ++ close(fd); ++ + error: +- if (f) +- fclose(f); + return -1; + } + +-- +2.27.0 + diff --git a/0006-swtpm-Use-open-not-fopen-when-accessing-statefile-CV.patch b/0006-swtpm-Use-open-not-fopen-when-accessing-statefile-CV.patch new file mode 100644 index 0000000..fb7c3d7 --- /dev/null +++ b/0006-swtpm-Use-open-not-fopen-when-accessing-statefile-CV.patch @@ -0,0 +1,211 @@ +From 44eacbca5bdb4baba226551a60a4e2e474b491cc Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Sun, 8 Nov 2020 21:41:54 -0500 +Subject: [PATCH 5/5] swtpm: Use open() (not fopen()) when accessing statefile + (CVE-2020-28407) + +This patch addresses CVE-2020-28407. + +Use the open() call rather than the fopen() call when accessing +the statefile and make sure we do not follow symlinks using O_NOFOLLOW. + +The modification does not allow an attacker to create a symbolic link +with the name of the temporary file (TMP2-00.permall for TPM 2) and +have this point to a valueable file and swtpm ends up overwriting the +file. The success of the attack depends on the attacker having access +to the TPM's state directory (--tpmstate dir=...). + +Signed-off-by: Stefan Berger +--- + src/swtpm/swtpm_nvfile.c | 67 +++++++++++++--------------------------- + 1 file changed, 21 insertions(+), 46 deletions(-) + +diff --git a/src/swtpm/swtpm_nvfile.c b/src/swtpm/swtpm_nvfile.c +index 8a6621b..12f10b9 100644 +--- a/src/swtpm/swtpm_nvfile.c ++++ b/src/swtpm/swtpm_nvfile.c +@@ -88,6 +88,7 @@ + #include "tpmstate.h" + #include "tpmlib.h" + #include "tlv.h" ++#include "utils.h" + + /* local structures */ + typedef struct { +@@ -295,16 +296,16 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + const char *name) + { + TPM_RESULT rc = 0; +- long lrc; + size_t src; + int irc; +- FILE *file = NULL; ++ int fd = -1; + char filename[FILENAME_MAX]; /* rooted file name from name */ + unsigned char *decrypt_data = NULL; + uint32_t decrypt_length; + uint32_t dataoffset = 0; + uint8_t hdrversion = 0; + uint16_t hdrflags; ++ struct stat statbuf; + + TPM_DEBUG(" SWTPM_NVRAM_LoadData: From file %s\n", name); + *data = NULL; +@@ -318,8 +319,8 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + + if (rc == 0) { + TPM_DEBUG(" SWTPM_NVRAM_LoadData: Opening file %s\n", filename); +- file = fopen(filename, "rb"); /* closed @1 */ +- if (file == NULL) { /* if failure, determine cause */ ++ fd = open(filename, O_RDONLY); /* closed @1 */ ++ if (fd < 0) { /* if failure, determine cause */ + if (errno == ENOENT) { + TPM_DEBUG("SWTPM_NVRAM_LoadData: No such file %s\n", + filename); +@@ -335,7 +336,7 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + } + + if (rc == 0) { +- if (fchmod(fileno(file), tpmstate_get_mode()) < 0) { ++ if (fchmod(fd, tpmstate_get_mode()) < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Could not fchmod %s : %s\n", + filename, strerror(errno)); +@@ -345,34 +346,16 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + + /* determine the file length */ + if (rc == 0) { +- irc = fseek(file, 0L, SEEK_END); /* seek to end of file */ ++ irc = fstat(fd, &statbuf); + if (irc == -1L) { + logprintf(STDERR_FILENO, +- "SWTPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n", ++ "SWTPM_NVRAM_LoadData: Error (fatal) fstat'ing %s, %s\n", + filename, strerror(errno)); + rc = TPM_FAIL; + } + } + if (rc == 0) { +- lrc = ftell(file); /* get position in the stream */ +- if (lrc == -1L) { +- logprintf(STDERR_FILENO, +- "SWTPM_NVRAM_LoadData: Error (fatal) ftell'ing %s, %s\n", +- filename, strerror(errno)); +- rc = TPM_FAIL; +- } +- else { +- *length = (uint32_t)lrc; /* save the length */ +- } +- } +- if (rc == 0) { +- irc = fseek(file, 0L, SEEK_SET); /* seek back to the beginning of the file */ +- if (irc == -1L) { +- logprintf(STDERR_FILENO, +- "SWTPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n", +- filename, strerror(errno)); +- rc = TPM_FAIL; +- } ++ *length = statbuf.st_size; /* save the length */ + } + /* allocate a buffer for the actual data */ + if ((rc == 0) && *length != 0) { +@@ -387,7 +370,7 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + } + /* read the contents of the file into the data buffer */ + if ((rc == 0) && *length != 0) { +- src = fread(*data, 1, *length, file); ++ src = read(fd, *data, *length); + if (src != *length) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal), data read of %u " +@@ -396,9 +379,9 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ + } + } + /* close the file */ +- if (file != NULL) { ++ if (fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closing file %s\n", filename); +- irc = fclose(file); /* @1 */ ++ irc = close(fd); /* @1 */ + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_LoadData: Error (fatal) closing file %s\n", +@@ -473,7 +456,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + TPM_RESULT rc = 0; + uint32_t lrc; + int irc; +- FILE *file = NULL; ++ int fd = -1; + char tmpfile[FILENAME_MAX]; /* rooted temporary file */ + char filename[FILENAME_MAX]; /* rooted file name from name */ + unsigned char *filedata = NULL; +@@ -499,8 +482,9 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + if (rc == 0) { + /* open the file */ + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile); +- file = fopen(tmpfile, "wb"); /* closed @1 */ +- if (file == NULL) { ++ fd = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, ++ tpmstate_get_mode()); /* closed @1 */ ++ if (fd < 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " + "write failed, %s\n", tmpfile, strerror(errno)); +@@ -508,15 +492,6 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + } + } + +- if (rc == 0) { +- if (fchmod(fileno(file), tpmstate_get_mode()) < 0) { +- logprintf(STDERR_FILENO, +- "SWTPM_NVRAM_StoreData: Could not fchmod %s : %s\n", +- tmpfile, strerror(errno)); +- rc = TPM_FAIL; +- } +- } +- + if (rc == 0) { + if (encrypt && SWTPM_NVRAM_Has_FileKey()) { + td_len = 3; +@@ -549,7 +524,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + /* write the data to the file */ + if (rc == 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Writing %u bytes of data\n", length); +- lrc = fwrite(filedata, 1, filedata_length, file); ++ lrc = write_full(fd, filedata, filedata_length); + if (lrc != filedata_length) { + logprintf(STDERR_FILENO, + "TPM_NVRAM_StoreData: Error (fatal), data write " +@@ -557,9 +532,9 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + rc = TPM_FAIL; + } + } +- if (file != NULL) { ++ if (fd >= 0) { + TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile); +- irc = fclose(file); /* @1 */ ++ irc = close(fd); /* @1 */ + if (irc != 0) { + logprintf(STDERR_FILENO, + "SWTPM_NVRAM_StoreData: Error (fatal) closing file\n"); +@@ -570,7 +545,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + } + } + +- if (rc == 0 && file != NULL) { ++ if (rc == 0 && fd >= 0) { + irc = rename(tmpfile, filename); + if (irc != 0) { + logprintf(STDERR_FILENO, +@@ -582,7 +557,7 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, + } + } + +- if (rc != 0 && file != NULL) { ++ if (rc != 0 && fd >= 0) { + unlink(tmpfile); + } + +-- +2.27.0 + diff --git a/swtpm.spec b/swtpm.spec index 94fed95..26212f2 100644 --- a/swtpm.spec +++ b/swtpm.spec @@ -12,12 +12,17 @@ Summary: TPM Emulator Name: swtpm Version: 0.3.3 -Release: 4 +Release: 5 License: BSD Url: http://github.com/stefanberger/swtpm Source0: %{url}/archive/%{gitcommit}/%{name}-%{gitshortcommit}.tar.gz -Patch0: CVE-2022-23645.patch -Patch1: Disable-broken-tests.patch +Patch00: 0000-swtpm-Check-header-size-indicator-against-expected-s.patch +Patch01: 0001-Disable-broken-tests.patch +Patch02: 0002-swtpm-Write-state-files-atomically-using-file-renami.patch +Patch03: 0003-swtpm_cert-Switch-to-open-from-fopen-for-writing-cer.patch +Patch04: 0004-swtpm-Do-not-follow-symlinks-when-opening-lockfile-C.patch +Patch05: 0005-swtpm-Switch-to-open-from-fopen-for-the-pidfile-CVE-.patch +Patch06: 0006-swtpm-Use-open-not-fopen-when-accessing-statefile-CV.patch BuildRequires: automake BuildRequires: autoconf @@ -165,11 +170,14 @@ fi %attr( 755, tss, tss) %{_localstatedir}/lib/swtpm-localca %changelog +* Thu Jun 30 2022 yezengruan - 0.3.3-5 +- Addressed potential symlink attack issue (CVE-2020-28407) + * Thu Mar 17 2022 liyanan - 0.3.3-4 - Disable broken test * Wed Mar 9 2022 yaoxin - 0.3.3-3 -- Fix CVE-2022-23645 +- swtpm: Check header size indicator against expected size (CVE-2022-23645) * Tue Sep 15 2020 jiangfangjie - 0.3.3-2 - update spec file and disable test case pkcs11 -- Gitee