Skip to content

Commit

Permalink
virtiofsd: add --syslog command-line option
Browse files Browse the repository at this point in the history
Sometimes collecting output from stderr is inconvenient or does not fit
within the overall logging architecture.  Add syslog(3) support for
cases where stderr cannot be used.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
dgilbert: Reworked as a logging function
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
  • Loading branch information
stefanhaRH authored and dagrh committed Jan 23, 2020
1 parent 3db2876 commit f185621
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 13 deletions.
1 change: 1 addition & 0 deletions tools/virtiofsd/fuse_lowlevel.h
Expand Up @@ -1795,6 +1795,7 @@ struct fuse_cmdline_opts {
int show_version;
int show_help;
int print_capabilities;
int syslog;
unsigned int max_idle_threads;
};

Expand Down
2 changes: 2 additions & 0 deletions tools/virtiofsd/helper.c
Expand Up @@ -54,6 +54,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("--syslog", syslog),
FUSE_OPT_END
};

Expand Down Expand Up @@ -138,6 +139,7 @@ void fuse_cmdline_help(void)
" -V --version print version\n"
" --print-capabilities print vhost-user.json\n"
" -d -o debug enable debug output (implies -f)\n"
" --syslog log to syslog (default stderr)\n"
" -f foreground operation\n"
" --daemonize run in background\n"
" -o max_idle_threads the maximum number of idle worker "
Expand Down
50 changes: 47 additions & 3 deletions tools/virtiofsd/passthrough_ll.c
Expand Up @@ -58,6 +58,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/xattr.h>
#include <syslog.h>
#include <unistd.h>

#include "passthrough_helpers.h"
Expand Down Expand Up @@ -138,6 +139,7 @@ static const struct fuse_opt lo_opts[] = {
{ "norace", offsetof(struct lo_data, norace), 1 },
FUSE_OPT_END
};
static bool use_syslog = false;

static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64_t n);

Expand Down Expand Up @@ -2262,11 +2264,12 @@ static void setup_mounts(const char *source)
* Lock down this process to prevent access to other processes or files outside
* source directory. This reduces the impact of arbitrary code execution bugs.
*/
static void setup_sandbox(struct lo_data *lo, struct fuse_session *se)
static void setup_sandbox(struct lo_data *lo, struct fuse_session *se,
bool enable_syslog)
{
setup_namespaces(lo, se);
setup_mounts(lo->source);
setup_seccomp();
setup_seccomp(enable_syslog);
}

/* Raise the maximum number of open file descriptors */
Expand Down Expand Up @@ -2298,6 +2301,42 @@ static void setup_nofile_rlimit(void)
}
}

static void log_func(enum fuse_log_level level, const char *fmt, va_list ap)
{
if (use_syslog) {
int priority = LOG_ERR;
switch (level) {
case FUSE_LOG_EMERG:
priority = LOG_EMERG;
break;
case FUSE_LOG_ALERT:
priority = LOG_ALERT;
break;
case FUSE_LOG_CRIT:
priority = LOG_CRIT;
break;
case FUSE_LOG_ERR:
priority = LOG_ERR;
break;
case FUSE_LOG_WARNING:
priority = LOG_WARNING;
break;
case FUSE_LOG_NOTICE:
priority = LOG_NOTICE;
break;
case FUSE_LOG_INFO:
priority = LOG_INFO;
break;
case FUSE_LOG_DEBUG:
priority = LOG_DEBUG;
break;
}
vsyslog(priority, fmt, ap);
} else {
vfprintf(stderr, fmt, ap);
}
}

int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
Expand Down Expand Up @@ -2336,6 +2375,11 @@ int main(int argc, char *argv[])
if (fuse_parse_cmdline(&args, &opts) != 0) {
return 1;
}
fuse_set_log_func(log_func);
use_syslog = opts.syslog;
if (use_syslog) {
openlog("virtiofsd", LOG_PID, LOG_DAEMON);
}
if (opts.show_help) {
printf("usage: %s [options]\n\n", argv[0]);
fuse_cmdline_help();
Expand Down Expand Up @@ -2424,7 +2468,7 @@ int main(int argc, char *argv[])
/* Must be before sandbox since it wants /proc */
setup_capng();

setup_sandbox(&lo, se);
setup_sandbox(&lo, se, opts.syslog);

/* Block until ctrl+c or fusermount -u */
ret = virtio_loop(se);
Expand Down
32 changes: 23 additions & 9 deletions tools/virtiofsd/seccomp.c
Expand Up @@ -107,11 +107,28 @@ static const int syscall_whitelist[] = {
SCMP_SYS(writev),
};

void setup_seccomp(void)
/* Syscalls used when --syslog is enabled */
static const int syscall_whitelist_syslog[] = {
SCMP_SYS(sendto),
};

static void add_whitelist(scmp_filter_ctx ctx, const int syscalls[], size_t len)
{
scmp_filter_ctx ctx;
size_t i;

for (i = 0; i < len; i++) {
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0) != 0) {
fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d failed\n",
syscalls[i]);
exit(1);
}
}
}

void setup_seccomp(bool enable_syslog)
{
scmp_filter_ctx ctx;

#ifdef SCMP_ACT_KILL_PROCESS
ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);
/* Handle a newer libseccomp but an older kernel */
Expand All @@ -126,13 +143,10 @@ void setup_seccomp(void)
exit(1);
}

for (i = 0; i < G_N_ELEMENTS(syscall_whitelist); i++) {
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
syscall_whitelist[i], 0) != 0) {
fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d",
syscall_whitelist[i]);
exit(1);
}
add_whitelist(ctx, syscall_whitelist, G_N_ELEMENTS(syscall_whitelist));
if (enable_syslog) {
add_whitelist(ctx, syscall_whitelist_syslog,
G_N_ELEMENTS(syscall_whitelist_syslog));
}

/* libvhost-user calls this for post-copy migration, we don't need it */
Expand Down
4 changes: 3 additions & 1 deletion tools/virtiofsd/seccomp.h
Expand Up @@ -9,6 +9,8 @@
#ifndef VIRTIOFSD_SECCOMP_H
#define VIRTIOFSD_SECCOMP_H

void setup_seccomp(void);
#include <stdbool.h>

void setup_seccomp(bool enable_syslog);

#endif /* VIRTIOFSD_SECCOMP_H */

0 comments on commit f185621

Please sign in to comment.