From 2120b89b0f61f287467d2b25f75cc7ad16c0d4bc Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 17 Mar 2020 14:55:45 +0100 Subject: [PATCH] lxc_user_nic: don't depend on MAP_FIXED as this breaks on sparc. Closes #3262. Signed-off-by: Christian Brauner --- src/lxc/Makefile.am | 1 + src/lxc/cmd/lxc_user_nic.c | 89 ++++++++++++-------------------------- src/lxc/file_utils.c | 35 ++++++++++----- src/lxc/file_utils.h | 3 ++ 4 files changed, 56 insertions(+), 72 deletions(-) diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index e486f91b3..2f850135a 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -399,6 +399,7 @@ lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \ network.c network.h \ parse.c parse.h \ raw_syscalls.c raw_syscalls.h \ + file_utils.c file_utils.h \ string_utils.c string_utils.h \ syscall_wrappers.h lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c \ diff --git a/src/lxc/cmd/lxc_user_nic.c b/src/lxc/cmd/lxc_user_nic.c index 7a2e47011..47048456d 100644 --- a/src/lxc/cmd/lxc_user_nic.c +++ b/src/lxc/cmd/lxc_user_nic.c @@ -3,7 +3,6 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif -#include #include #include #include @@ -32,6 +31,7 @@ #include "compiler.h" #include "config.h" +#include "file_utils.h" #include "log.h" #include "memory_utils.h" #include "network.h" @@ -77,7 +77,7 @@ static int open_and_lock(const char *path) int ret; struct flock lk; - fd = open(path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR); + fd = open(path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | O_CLOEXEC); if (fd < 0) { CMD_SYSERROR("Failed to open \"%s\"\n", path); return -1; @@ -592,40 +592,35 @@ struct entry_line { static bool cull_entries(int fd, char *name, char *net_type, char *net_link, char *net_dev, bool *found_nicname) { + __do_free char *buf = NULL; __do_free struct entry_line *entry_lines = NULL; - int i, ret; - char *buf, *buf_end, *buf_start; - struct stat sb; int n = 0; + size_t length = 0; + int ret; + char *buf_end, *buf_start; bool found, keep; - ret = fstat(fd, &sb); + ret = fd_to_buf(fd, &buf, &length); if (ret < 0) { - CMD_SYSERROR("Failed to fstat\n"); + CMD_SYSERROR("Failed to read database file\n"); return false; } - - if (!sb.st_size) + if (lseek(fd, 0, SEEK_SET) < 0) return false; - buf = lxc_strmmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (buf == MAP_FAILED) { - CMD_SYSERROR("Failed to establish shared memory mapping\n"); + if (length == 0) return false; - } buf_start = buf; - buf_end = buf + sb.st_size; + buf_end = buf + length; while ((buf_start = find_line(buf_start, buf_end, name, net_type, net_link, net_dev, &(bool){true}, &found, &keep))) { struct entry_line *newe; newe = realloc(entry_lines, sizeof(*entry_lines) * (n + 1)); - if (!newe) { - lxc_strmunmap(buf, sb.st_size); + if (!newe) return false; - } if (found) *found_nicname = true; @@ -643,7 +638,7 @@ static bool cull_entries(int fd, char *name, char *net_type, char *net_link, buf_start = buf; - for (i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { if (!entry_lines[i].keep) continue; @@ -653,12 +648,7 @@ static bool cull_entries(int fd, char *name, char *net_type, char *net_link, buf_start++; } - ret = ftruncate(fd, buf_start - buf); - lxc_strmunmap(buf, sb.st_size); - if (ret < 0) - CMD_SYSERROR("Failed to set new file size\n"); - - return true; + return ftruncate(fd, buf_start - buf) == 0; } static int count_entries(char *buf, off_t len, char *name, char *net_type, char *net_link) @@ -685,14 +675,13 @@ static int count_entries(char *buf, off_t len, char *name, char *net_type, char static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid, char *intype, char *br, int allowed, char **cnic) { - __do_free char *newline = NULL; + __do_free char *buf = NULL, *newline = NULL; + size_t length = 0; int ret; size_t slen; char *owner; char nicname[IFNAMSIZ]; - struct stat sb; struct alloted_s *n; - char *buf = NULL; uid_t uid; for (n = names; n != NULL; n = n->next) @@ -703,34 +692,27 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid, owner = names->name; - ret = fstat(fd, &sb); + ret = fd_to_buf(fd, &buf, &length); if (ret < 0) { - CMD_SYSERROR("Failed to fstat\n"); - return NULL; + CMD_SYSERROR("Failed to read database file\n"); + return false; } + if (lseek(fd, 0, SEEK_SET) < 0) + return false; - if (sb.st_size > 0) { - buf = lxc_strmmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (buf == MAP_FAILED) { - CMD_SYSERROR("Failed to establish shared memory mapping\n"); - return NULL; - } - + if (length > 0) { owner = NULL; for (n = names; n != NULL; n = n->next) { int count; - count = count_entries(buf, sb.st_size, n->name, intype, br); + count = count_entries(buf, length, n->name, intype, br); if (count >= n->allowed) continue; owner = n->name; break; } - - lxc_strmunmap(buf, sb.st_size); } if (!owner) @@ -787,30 +769,13 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid, return NULL; } - /* Note that the file needs to be truncated to the size **without** the - * \0 byte! Files are not \0-terminated! - */ - ret = ftruncate(fd, sb.st_size + slen); + if (lxc_pwrite_nointr(fd, newline, slen, length) != slen) + CMD_SYSERROR("Failed to append new entry \"%s\" to database file", newline); + + ret = ftruncate(fd, length + slen); if (ret < 0) CMD_SYSERROR("Failed to truncate file\n"); - buf = lxc_strmmap(NULL, sb.st_size + slen, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (buf == MAP_FAILED) { - CMD_SYSERROR("Failed to establish shared memory mapping\n"); - - if (lxc_netdev_delete_by_name(nicname) != 0) - usernic_error("Error unlinking %s\n", nicname); - - return NULL; - } - - /* Note that the memory needs to be moved in the buffer **without** the - * \0 byte! Files are not \0-terminated! - */ - memmove(buf + sb.st_size, newline, slen); - lxc_strmunmap(buf, sb.st_size + slen); - return strdup(nicname); } diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c index ab445751b..1689cbaa7 100644 --- a/src/lxc/file_utils.c +++ b/src/lxc/file_utils.c @@ -133,6 +133,17 @@ ssize_t lxc_write_nointr(int fd, const void *buf, size_t count) return ret; } +ssize_t lxc_pwrite_nointr(int fd, const void *buf, size_t count, off_t offset) +{ + ssize_t ret; + + do { + ret = pwrite(fd, buf, count, offset); + } while (ret < 0 && errno == EINTR); + + return ret; +} + ssize_t lxc_send_nointr(int sockfd, void *buf, size_t len, int flags) { ssize_t ret; @@ -400,37 +411,39 @@ int fd_to_fd(int from, int to) return 0; } -static char *fd_to_buf(int fd, size_t *length) +int fd_to_buf(int fd, char **buf, size_t *length) { __do_free char *copy = NULL; if (!length) - return NULL; + return 0; *length = 0; for (;;) { ssize_t bytes_read; - char buf[4096]; + char chunk[4096]; char *old = copy; - bytes_read = lxc_read_nointr(fd, buf, sizeof(buf)); + bytes_read = lxc_read_nointr(fd, chunk, sizeof(chunk)); if (bytes_read < 0) - return NULL; + return 0; if (!bytes_read) break; copy = must_realloc(old, (*length + bytes_read) * sizeof(*old)); - memcpy(copy + *length, buf, bytes_read); + memcpy(copy + *length, chunk, bytes_read); *length += bytes_read; } - return move_ptr(copy); + *buf = move_ptr(copy); + return 0; } char *file_to_buf(const char *path, size_t *length) { __do_close int fd = -EBADF; + char *buf = NULL; if (!length) return NULL; @@ -439,7 +452,10 @@ char *file_to_buf(const char *path, size_t *length) if (fd < 0) return NULL; - return fd_to_buf(fd, length); + if (fd_to_buf(fd, &buf, length) < 0) + return NULL; + + return buf; } FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer) @@ -470,8 +486,7 @@ FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer) __do_free char *buf = NULL; size_t len = 0; - buf = fd_to_buf(fd, &len); - if (!buf) + if (fd_to_buf(fd, &buf, &len) < 0) return NULL; f = fmemopen(buf, len, mode); diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h index 8b31b976e..6d5dbf68d 100644 --- a/src/lxc/file_utils.h +++ b/src/lxc/file_utils.h @@ -24,6 +24,8 @@ extern int lxc_read_from_file(const char *filename, void *buf, size_t count); /* send and receive buffers completely */ extern ssize_t lxc_write_nointr(int fd, const void *buf, size_t count); +extern ssize_t lxc_pwrite_nointr(int fd, const void *buf, size_t count, + off_t offset); extern ssize_t lxc_send_nointr(int sockfd, void *buf, size_t len, int flags); extern ssize_t lxc_read_nointr(int fd, void *buf, size_t count); extern ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count, @@ -49,6 +51,7 @@ extern FILE *fopen_cloexec(const char *path, const char *mode); extern ssize_t lxc_sendfile_nointr(int out_fd, int in_fd, off_t *offset, size_t count); extern char *file_to_buf(const char *path, size_t *length); +extern int fd_to_buf(int fd, char **buf, size_t *length); extern int fd_to_fd(int from, int to); extern int lxc_open_dirfd(const char *dir); extern FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer); -- 2.47.2