From b1288dfafbdfb64e86bf9cfa22fa0b399e44e198 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 29 Jun 2020 12:54:18 +0100 Subject: [PATCH 1/5] virtiofsd: Terminate capability list capng_updatev is a varargs function that needs a -1 to terminate it, but it was missing. In practice what seems to have been happening is that it's added the capabilities we asked for, then runs into junk on the stack, so if we're unlucky it might be adding some more, but in reality it's failing - but after adding the capabilities we asked for. Fixes: a59feb483b8 ("virtiofsd: only retain file system capabilities") Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Stefan Hajnoczi Acked-by: Vivek Goyal Message-Id: <20200629115420.98443-2-dgilbert@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 2ce7c96085..e373e3b36e 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -2598,7 +2598,9 @@ static void setup_capabilities(void) CAP_SETGID, CAP_SETUID, CAP_MKNOD, - CAP_SETFCAP); + CAP_SETFCAP, + -1); + capng_apply(CAPNG_SELECT_BOTH); cap.saved = capng_save_state(); From 55b22a60cc7ac25565a13813deba3d548cb48bd3 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 29 Jun 2020 12:54:19 +0100 Subject: [PATCH 2/5] virtiofsd: Check capability calls Check the capability calls worked. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Stefan Hajnoczi Acked-by: Vivek Goyal Message-Id: <20200629115420.98443-3-dgilbert@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index e373e3b36e..99d562046a 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -2589,7 +2589,7 @@ static void setup_capabilities(void) */ capng_setpid(syscall(SYS_gettid)); capng_clear(CAPNG_SELECT_BOTH); - capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, + if (capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, @@ -2599,11 +2599,21 @@ static void setup_capabilities(void) CAP_SETUID, CAP_MKNOD, CAP_SETFCAP, - -1); + -1)) { + fuse_log(FUSE_LOG_ERR, "%s: capng_updatev failed\n", __func__); + exit(1); + } - capng_apply(CAPNG_SELECT_BOTH); + if (capng_apply(CAPNG_SELECT_BOTH)) { + fuse_log(FUSE_LOG_ERR, "%s: capng_apply failed\n", __func__); + exit(1); + } cap.saved = capng_save_state(); + if (!cap.saved) { + fuse_log(FUSE_LOG_ERR, "%s: capng_save_state failed\n", __func__); + exit(1); + } pthread_mutex_unlock(&cap.mutex); } From 3005c099ef3c6b43213e1454296c1c6556345805 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 29 Jun 2020 12:54:20 +0100 Subject: [PATCH 3/5] virtiofsd: Allow addition or removal of capabilities Allow capabilities to be added or removed from the allowed set for the daemon; e.g. default: CapPrm: 00000000880000df CapEff: 00000000880000df -o modcaps=+sys_admin CapPrm: 00000000882000df CapEff: 00000000882000df -o modcaps=+sys_admin:-chown CapPrm: 00000000882000de CapEff: 00000000882000de Signed-off-by: Dr. David Alan Gilbert Message-Id: <20200629115420.98443-4-dgilbert@redhat.com> Acked-by: Vivek Goyal Reviewed-by: Stefan Hajnoczi Signed-off-by: Dr. David Alan Gilbert --- docs/tools/virtiofsd.rst | 5 +++ tools/virtiofsd/helper.c | 2 ++ tools/virtiofsd/passthrough_ll.c | 53 ++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index 378594c422..824e713491 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -54,6 +54,11 @@ Options * flock|no_flock - Enable/disable flock. The default is ``no_flock``. + * modcaps=CAPLIST + Modify the list of capabilities allowed; CAPLIST is a colon separated + list of capabilities, each preceded by either + or -, e.g. + ''+sys_admin:-chown''. + * log_level=LEVEL - Print only log messages matching LEVEL or more severe. LEVEL is one of ``err``, ``warn``, ``info``, or ``debug``. The default is ``info``. diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c index 00a1ef666a..3105b6c23a 100644 --- a/tools/virtiofsd/helper.c +++ b/tools/virtiofsd/helper.c @@ -174,6 +174,8 @@ void fuse_cmdline_help(void) " default: no_writeback\n" " -o xattr|no_xattr enable/disable xattr\n" " default: no_xattr\n" + " -o modcaps=CAPLIST Modify the list of capabilities\n" + " e.g. -o modcaps=+sys_admin:-chown\n" " --rlimit-nofile= set maximum number of file descriptors\n" " (0 leaves rlimit unchanged)\n" " default: min(1000000, fs.file-max - 16384)\n" diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 99d562046a..94e0de2d2b 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -145,6 +145,7 @@ struct lo_data { int posix_lock; int xattr; char *source; + char *modcaps; double timeout; int cache; int timeout_set; @@ -170,6 +171,7 @@ static const struct fuse_opt lo_opts[] = { { "no_posix_lock", offsetof(struct lo_data, posix_lock), 0 }, { "xattr", offsetof(struct lo_data, xattr), 1 }, { "no_xattr", offsetof(struct lo_data, xattr), 0 }, + { "modcaps=%s", offsetof(struct lo_data, modcaps), 0 }, { "timeout=%lf", offsetof(struct lo_data, timeout), 0 }, { "timeout=", offsetof(struct lo_data, timeout_set), 1 }, { "cache=none", offsetof(struct lo_data, cache), CACHE_NONE }, @@ -2570,9 +2572,11 @@ static void setup_mounts(const char *source) /* * Only keep whitelisted capabilities that are needed for file system operation + * The (possibly NULL) modcaps_in string passed in is free'd before exit. */ -static void setup_capabilities(void) +static void setup_capabilities(char *modcaps_in) { + char *modcaps = modcaps_in; pthread_mutex_lock(&cap.mutex); capng_restore_state(&cap.saved); @@ -2604,6 +2608,51 @@ static void setup_capabilities(void) exit(1); } + /* + * The modcaps option is a colon separated list of caps, + * each preceded by either + or -. + */ + while (modcaps) { + capng_act_t action; + int cap; + + char *next = strchr(modcaps, ':'); + if (next) { + *next = '\0'; + next++; + } + + switch (modcaps[0]) { + case '+': + action = CAPNG_ADD; + break; + + case '-': + action = CAPNG_DROP; + break; + + default: + fuse_log(FUSE_LOG_ERR, + "%s: Expecting '+'/'-' in modcaps but found '%c'\n", + __func__, modcaps[0]); + exit(1); + } + cap = capng_name_to_capability(modcaps + 1); + if (cap < 0) { + fuse_log(FUSE_LOG_ERR, "%s: Unknown capability '%s'\n", __func__, + modcaps); + exit(1); + } + if (capng_update(action, CAPNG_PERMITTED | CAPNG_EFFECTIVE, cap)) { + fuse_log(FUSE_LOG_ERR, "%s: capng_update failed for '%s'\n", + __func__, modcaps); + exit(1); + } + + modcaps = next; + } + g_free(modcaps_in); + if (capng_apply(CAPNG_SELECT_BOTH)) { fuse_log(FUSE_LOG_ERR, "%s: capng_apply failed\n", __func__); exit(1); @@ -2627,7 +2676,7 @@ static void setup_sandbox(struct lo_data *lo, struct fuse_session *se, setup_namespaces(lo, se); setup_mounts(lo->source); setup_seccomp(enable_syslog); - setup_capabilities(); + setup_capabilities(g_strdup(lo->modcaps)); } /* Set the maximum number of open file descriptors */ From 617a32f5295ee4efcc17abadcecc3cf482c98e80 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 1 Jul 2020 10:35:57 +0100 Subject: [PATCH 4/5] migration: postcopy take proper error return This function returns a boolean success and we're returning -1; lets just use the 'out' error path. Signed-off-by: Dr. David Alan Gilbert Fixes: 58b7c17e226 ("Disable mlock around incoming postcopy") Buglink: https://bugs.launchpad.net/qemu/+bug/1885720 Message-Id: <20200701093557.130096-1-dgilbert@redhat.com> Reviewed-by: Thomas Huth Signed-off-by: Dr. David Alan Gilbert --- migration/postcopy-ram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index a36402722b..bef2a3afed 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -389,7 +389,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis) */ if (munlockall()) { error_report("%s: munlockall: %s", __func__, strerror(errno)); - return -1; + goto out; } /* From fb6135807fcab4670d69663ac88e88e124348ffd Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Mon, 22 Jun 2020 11:20:37 +0800 Subject: [PATCH 5/5] migration: Count new_dirty instead of real_dirty real_dirty_pages becomes equal to total ram size after dirty log sync in ram_init_bitmaps, the reason is that the bitmap of ramblock is initialized to be all set, so old path counts them as "real dirty" at beginning. This causes wrong dirty rate and false positive throttling. Signed-off-by: Keqian Zhu Message-Id: <20200622032037.31112-1-zhukeqian1@huawei.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- include/exec/ram_addr.h | 5 +---- migration/ram.c | 8 +++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 7b5c24e928..3ef729a23c 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -442,8 +442,7 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, static inline uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, ram_addr_t start, - ram_addr_t length, - uint64_t *real_dirty_pages) + ram_addr_t length) { ram_addr_t addr; unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS); @@ -469,7 +468,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, if (src[idx][offset]) { unsigned long bits = atomic_xchg(&src[idx][offset], 0); unsigned long new_dirty; - *real_dirty_pages += ctpopl(bits); new_dirty = ~dest[k]; dest[k] |= bits; new_dirty &= bits; @@ -502,7 +500,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, start + addr + offset, TARGET_PAGE_SIZE, DIRTY_MEMORY_MIGRATION)) { - *real_dirty_pages += 1; long k = (start + addr) >> TARGET_PAGE_BITS; if (!test_and_set_bit(k, dest)) { num_dirty++; diff --git a/migration/ram.c b/migration/ram.c index 069b6e30bc..5554a7d2d8 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -859,9 +859,11 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs, /* Called with RCU critical section */ static void ramblock_sync_dirty_bitmap(RAMState *rs, RAMBlock *rb) { - rs->migration_dirty_pages += - cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length, - &rs->num_dirty_pages_period); + uint64_t new_dirty_pages = + cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length); + + rs->migration_dirty_pages += new_dirty_pages; + rs->num_dirty_pages_period += new_dirty_pages; } /**