/
githubmirror
/
swtpm
Обзор
Документация
Войти
/
githubmirror
/
swtpm
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v0.8.0
src/swtpm/utils.c
348 строк
9 KB
Jennifer Herbert
swtpm: Add a chroot option
25 авг 2022, 17:04
25 авг 2022, 17:04
68e5428
Код
Авторство
О чём код?
/* * utils.s -- utilities * * (c) Copyright IBM Corporation 2014, 2015, 2019. * * Author: Stefan Berger <stefanb@us.ibm.com> * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include <grp.h> #include <pwd.h> #include <fcntl.h> #include <unistd.h> #include <limits.h> #include <stdlib.h> #include <string.h> #include <errno.h> #if defined __APPLE__ #include <fcntl.h> #include <sys/param.h> #endif #include "utils.h" #include "logging.h" #include "tpmlib.h" #include "swtpm_debug.h" void uninstall_sighandlers() { if (signal(SIGTERM, SIG_DFL) == SIG_ERR) logprintf(STDERR_FILENO, "Could not uninstall signal handler for SIGTERM.\n"); if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) logprintf(STDERR_FILENO, "Could not uninstall signal handler for SIGPIPE.\n"); } int install_sighandlers(int pipefd[2], sighandler_t handler) { if (pipe(pipefd) < 0) { logprintf(STDERR_FILENO, "Error: Could not open pipe.\n"); goto err_exit; } if (signal(SIGTERM, handler) == SIG_ERR) { logprintf(STDERR_FILENO, "Could not install signal handler for SIGTERM.\n"); goto err_close_pipe; } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { logprintf(STDERR_FILENO, "Could not install signal handler for SIGPIPE.\n"); goto err_close_pipe; } return 0; err_close_pipe: close(pipefd[0]); pipefd[0] = -1; close(pipefd[1]); pipefd[1] = -1; err_exit: return -1; } int change_process_owner(const char *user) { struct passwd *passwd; long int uid, gid; char *endptr = NULL; uid = strtoul(user, &endptr, 10); if (*endptr != '\0') { /* a string */ passwd = getpwnam(user); if (!passwd) { logprintf(STDERR_FILENO, "Error: User '%s' does not exist.\n", user); return -14; } if (initgroups(passwd->pw_name, passwd->pw_gid) < 0) { logprintf(STDERR_FILENO, "Error: initgroups(%s, %d) failed.\n", passwd->pw_name, passwd->pw_gid); return -10; } gid = passwd->pw_gid; uid = passwd->pw_uid; } else { /* an integer */ if ((unsigned long int)uid > UINT_MAX) { logprintf(STDERR_FILENO, "Error: uid %s outside valid range.\n", user); return -13; } gid = uid; } if (setgid(gid) < 0) { logprintf(STDERR_FILENO, "Error: setgid(%d) failed.\n", gid); return -11; } if (setuid(uid) < 0) { logprintf(STDERR_FILENO, "Error: setuid(%d) failed.\n", uid); return -12; } return 0; } int do_chroot(const char *path) { if (chroot(path) < 0) { logprintf(STDERR_FILENO, "chroot failed: %s\n", strerror(errno)); return -1; } if (chdir("/") < 0) { logprintf(STDERR_FILENO, "chdir failed: %s\n", strerror(errno)); return -1; } return 0; } void tpmlib_debug_libtpms_parameters(TPMLIB_TPMVersion tpmversion) { switch (tpmversion) { case TPMLIB_TPM_VERSION_1_2: TPM_DEBUG("TPM 1.2: Compiled for %u auth, %u transport, " "and %u DAA session slots\n", tpmlib_get_tpm_property(TPMPROP_TPM_MIN_AUTH_SESSIONS), tpmlib_get_tpm_property(TPMPROP_TPM_MIN_TRANS_SESSIONS), tpmlib_get_tpm_property(TPMPROP_TPM_MIN_DAA_SESSIONS)); TPM_DEBUG("TPM 1.2: Compiled for %u key slots, %u owner evict slots\n", tpmlib_get_tpm_property(TPMPROP_TPM_KEY_HANDLES), tpmlib_get_tpm_property(TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES)); TPM_DEBUG("TPM 1.2: Compiled for %u counters, %u saved sessions\n", tpmlib_get_tpm_property(TPMPROP_TPM_MIN_COUNTERS), tpmlib_get_tpm_property(TPMPROP_TPM_MIN_SESSION_LIST)); TPM_DEBUG("TPM 1.2: Compiled for %u family, " "%u delegate table entries\n", tpmlib_get_tpm_property(TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN), tpmlib_get_tpm_property(TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN)); TPM_DEBUG("TPM 1.2: Compiled for %u total NV, %u savestate, " "%u volatile space\n", tpmlib_get_tpm_property(TPMPROP_TPM_MAX_NV_SPACE), tpmlib_get_tpm_property(TPMPROP_TPM_MAX_SAVESTATE_SPACE), tpmlib_get_tpm_property(TPMPROP_TPM_MAX_VOLATILESTATE_SPACE)); #if 0 TPM_DEBUG("TPM1.2: Compiled for %u NV defined space\n", tpmlib_get_tpm_property(TPMPROP_TPM_MAX_NV_DEFINED_SIZE)); #endif break; case TPMLIB_TPM_VERSION_2: break; } } char *fd_to_filename(int fd) { #if defined __linux__ char buffer[64]; char *path; snprintf(buffer, sizeof(buffer), "/proc/self/fd/%d", fd); path = realpath(buffer, NULL); if (!path) { logprintf(STDERR_FILENO, "Could not read %s: %s\n", buffer, strerror(errno)); return NULL; } return path; #elif defined __APPLE__ char *path = malloc(MAXPATHLEN); if (!path) { logprintf(STDERR_FILENO, "Out of memory.\n"); return NULL; } if (fcntl(fd, F_GETPATH, path) < 0) { logprintf(STDERR_FILENO, "fcntl for F_GETPATH failed: %\n", strerror(errno)); free(path); return NULL; } return path; #else (void)fd; logprintf(STDERR_FILENO, "Cannot convert file descriptor to filename on this platform.\n"); return NULL; #endif } /* * write_full: Write all bytes of a buffer into the file descriptor * and handle partial writes on the way. * * @fd: file descriptor to write to * @buffer: buffer * @buflen: length of buffer * * Returns -1 in case not all bytes could be transferred, number of * bytes written otherwise (must be equal to buflen). */ ssize_t write_full(int fd, const void *buffer, size_t buflen) { size_t written = 0; ssize_t n; while (written < buflen) { n = write(fd, buffer, buflen - written); if (n == 0) return -1; if (n < 0) { if (errno == EINTR) continue; return -1; } written += n; buffer += n; } return written; } /* * writev_full: Write all bytes of an iovec into the file descriptor * and handle partial writes on the way. * @fd: file descriptor to write to * @iov: pointer to iov * @iovcnt: length of iov array * * Returns -1 in case not all bytes could be transferred, number of * bytes written otherwise (must be equal to buflen). */ ssize_t writev_full(int fd, const struct iovec *iov, int iovcnt) { int i; size_t off; unsigned char *buf; ssize_t n; size_t bytecount = 0; size_t numbufs = 0; size_t lastidx = -1; for (i = 0; i < iovcnt; i++) { if (iov[i].iov_len) { bytecount += iov[i].iov_len; numbufs++; lastidx = i; } } if (numbufs == 1) return write_full(fd, iov[lastidx].iov_base, iov[lastidx].iov_len); buf = malloc(bytecount); if (!buf) { errno = ENOMEM; return -1; } off = 0; for (i = 0; i < iovcnt; i++) { if (!iov[i].iov_len) continue; memcpy(&buf[off], iov[i].iov_base, iov[i].iov_len); off += iov[i].iov_len; } n = write_full(fd, buf, off); free(buf); return n; } /* * read_einter: Read bytes from a file descriptor into a buffer * and handle EINTR. Perform one read(). * * @fd: file descriptor to read from * @buffer: buffer * @buflen: length of buffer * * Returns -1 in case an error occurred, number of bytes read otherwise. */ ssize_t read_eintr(int fd, void *buffer, size_t buflen) { ssize_t n; while (true) { n = read(fd, buffer, buflen); if (n < 0) { if (errno == EINTR) continue; return -1; } return n; } }