diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2020-05-01 23:10:22 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2020-05-01 23:10:22 +0100 |
| commit | 6897541d902218b31eef2e8eabc74fa56618f9b3 (patch) | |
| tree | 1b8d5416976ccc3841d3bd4c4170e7a255958c27 /tools/virtiofsd/helper.c | |
| parent | 1c47613588ccff44422d4bdeea0dc36a0a308ec7 (diff) | |
| parent | 66502bbca37ca7a3bfa57e82cfc03b89a7a11eae (diff) | |
| download | focaccia-qemu-6897541d902218b31eef2e8eabc74fa56618f9b3.tar.gz focaccia-qemu-6897541d902218b31eef2e8eabc74fa56618f9b3.zip | |
Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-virtiofs-20200501' into staging
virtiofsd: Pull 2020-05-01 (includes CVE fix) This set includes a security fix, other fixes and improvements. Security fix: The security fix is for CVE-2020-10717 where, on low RAM hosts, the guest can potentially exceed the maximum fd limit. This fix adds some more configuration so that the user can explicitly set the limit. Fixes: Recursive mounting of the exported directory is now used in the sandbox, such that if there was a mount underneath present at the time the virtiofsd was started, that mount is also visible to the guest; in the existing code, only mounts that happened after startup were visible. Security improvements: The jailing for /proc/self/fd is improved - but it's something that shouldn't be accessible anyway. Most capabilities are now dropped at startup; again this shouldn't change any behaviour but is extra protection. # gpg: Signature made Fri 01 May 2020 20:06:46 BST # gpg: using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7 # gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full] # Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7 * remotes/dgilbert-gitlab/tags/pull-virtiofs-20200501: virtiofsd: drop all capabilities in the wait parent process virtiofsd: only retain file system capabilities virtiofsd: Show submounts virtiofsd: jail lo->proc_self_fd virtiofsd: stay below fs.file-max sysctl value (CVE-2020-10717) virtiofsd: add --rlimit-nofile=NUM option Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tools/virtiofsd/helper.c')
| -rw-r--r-- | tools/virtiofsd/helper.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c index 819c2bc13c..00a1ef666a 100644 --- a/tools/virtiofsd/helper.c +++ b/tools/virtiofsd/helper.c @@ -23,6 +23,8 @@ #include <stdlib.h> #include <string.h> #include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> #include <unistd.h> #define FUSE_HELPER_OPT(t, p) \ @@ -53,6 +55,7 @@ static const struct fuse_opt fuse_helper_opts[] = { FUSE_HELPER_OPT("subtype=", nodefault_subtype), FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads), + FUSE_HELPER_OPT("--rlimit-nofile=%lu", rlimit_nofile), FUSE_HELPER_OPT("--syslog", syslog), FUSE_HELPER_OPT_VALUE("log_level=debug", log_level, FUSE_LOG_DEBUG), FUSE_HELPER_OPT_VALUE("log_level=info", log_level, FUSE_LOG_INFO), @@ -171,6 +174,10 @@ void fuse_cmdline_help(void) " default: no_writeback\n" " -o xattr|no_xattr enable/disable xattr\n" " default: no_xattr\n" + " --rlimit-nofile=<num> set maximum number of file descriptors\n" + " (0 leaves rlimit unchanged)\n" + " default: min(1000000, fs.file-max - 16384)\n" + " if the current rlimit is lower\n" ); } @@ -191,11 +198,51 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key, } } +static unsigned long get_default_rlimit_nofile(void) +{ + g_autofree gchar *file_max_str = NULL; + const rlim_t reserved_fds = 16384; /* leave at least this many fds free */ + rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */ + rlim_t file_max; + struct rlimit rlim; + + /* + * Reduce max_fds below the system-wide maximum, if necessary. This + * ensures there are fds available for other processes so we don't + * cause resource exhaustion. + */ + if (!g_file_get_contents("/proc/sys/fs/file-max", &file_max_str, + NULL, NULL)) { + fuse_log(FUSE_LOG_ERR, "can't read /proc/sys/fs/file-max\n"); + exit(1); + } + file_max = g_ascii_strtoull(file_max_str, NULL, 10); + if (file_max < 2 * reserved_fds) { + fuse_log(FUSE_LOG_ERR, + "The fs.file-max sysctl is too low (%lu) to allow a " + "reasonable number of open files.\n", + (unsigned long)file_max); + exit(1); + } + max_fds = MIN(file_max - reserved_fds, max_fds); + + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n"); + exit(1); + } + + if (rlim.rlim_cur >= max_fds) { + return 0; /* we have more fds available than required! */ + } + return max_fds; +} + int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts) { memset(opts, 0, sizeof(struct fuse_cmdline_opts)); opts->max_idle_threads = 10; + opts->rlimit_nofile = get_default_rlimit_nofile(); opts->foreground = 1; if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) == |