/* SPDX-License-Identifier: LGPL-2.1+ */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
+#include "config.h"
+
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <syslog.h>
#include <unistd.h>
+#include "lxc.h"
+
#include "caps.h"
-#include "config.h"
#include "file_utils.h"
#include "log.h"
-#include "lxccontainer.h"
#include "memory_utils.h"
#include "utils.h"
-#ifndef HAVE_STRLCPY
-#include "include/strlcpy.h"
+#if !HAVE_STRLCPY
+#include "strlcpy.h"
#endif
#if HAVE_DLOG
#define LXC_LOG_TIME_SIZE ((INTTYPE_TO_STRLEN(uint64_t)) * 2)
int lxc_log_fd = -EBADF;
-static int syslog_enable = 0;
-int lxc_quiet_specified;
-int lxc_log_use_global_fd;
+static bool wants_syslog = false;
+static int lxc_quiet_specified;
+bool lxc_log_use_global_fd = false;
static int lxc_loglevel_specified;
static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
return LOG_NOTICE;
}
-static const char *lxc_log_get_container_name()
+static const char *lxc_log_get_container_name(void)
{
#ifndef NO_LXC_CONF
if (current_config && !log_vmname)
return log_vmname;
}
+int lxc_log_get_fd(void)
+{
+ int fd_log = -EBADF;
+
+#ifndef NO_LXC_CONF
+ if (current_config && !lxc_log_use_global_fd)
+ fd_log = current_config->logfd;
+#endif
+ if (fd_log < 0)
+ fd_log = lxc_log_fd;
+
+ return fd_log;
+}
+
static char *lxc_log_get_va_msg(struct lxc_log_event *event)
{
__do_free char *msg = NULL;
__do_free char *msg = NULL;
const char *log_container_name;
- if (!syslog_enable)
+ if (!wants_syslog)
return 0;
log_container_name = lxc_log_get_container_name();
seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60));
/* Make string from nanoseconds. */
- ret = snprintf(nanosec, sizeof(nanosec), "%"PRId64, (int64_t)time->tv_nsec);
- if (ret < 0 || (size_t)ret >= sizeof(nanosec))
+ ret = strnprintf(nanosec, sizeof(nanosec), "%"PRId64, (int64_t)time->tv_nsec);
+ if (ret < 0)
return ret_errno(EIO);
/*
* Create final timestamp for the log and shorten nanoseconds to 3
* digit precision.
*/
- ret = snprintf(buf, bufsize,
+ ret = strnprintf(buf, bufsize,
"%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64
"%02" PRId64 "%02" PRId64 ".%.3s",
year, month, day, hours, minutes, seconds, nanosec);
- if (ret < 0 || (size_t)ret >= bufsize)
+ if (ret < 0)
return ret_errno(EIO);
return 0;
if (ret)
return ret;
+ /*
+ * We allow truncation here which is why we use snprintf() directly
+ * instead of strnprintf().
+ */
n = snprintf(buffer, sizeof(buffer),
"%s%s%s %s %-8s %s - %s:%s:%d - ",
log_prefix,
__do_free char *n = NULL;
char *e, *p;
+ if (is_empty_string(name))
+ return ret_errno(EINVAL);
+
/* Make copy of the string since we'll be modifying it. */
n = strdup(name);
if (!n)
continue;
*p = '\0';
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ret = lxc_unpriv(mkdir(n, 0755));
+#else
+ if (RUN_ON_OSS_FUZZ || is_in_comm("fuzz-lxc-") > 0)
+ ret = errno = EEXIST;
+ else
+ ret = lxc_unpriv(mkdir(n, 0755));
+#endif /*!FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
*p = '/';
if (ret && errno != EEXIST)
return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", n);
static int log_open(const char *name)
{
+ int newfd = -EBADF;
__do_close int fd = -EBADF;
- int newfd;
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0660));
+#else
+ if (!RUN_ON_OSS_FUZZ && is_in_comm("fuzz-lxc-") <= 0)
+ fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0660));
+#endif /* !FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
if (fd < 0)
return log_error_errno(-errno, errno, "Failed to open log file \"%s\"", name);
newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDERR_FILENO);
if (newfd < 0)
return log_error_errno(-errno, errno, "Failed to dup log fd %d", fd);
-
return newfd;
}
return ret_set_errno(NULL, ENOMEM);
if (use_dir)
- ret = snprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
+ ret = strnprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
else
- ret = snprintf(p, len, "%s/%s.log", lxcpath, name);
- if (ret < 0 || (size_t)ret >= len)
+ ret = strnprintf(p, len, "%s/%s.log", lxcpath, name);
+ if (ret < 0)
return ret_set_errno(NULL, EIO);
return move_ptr(p);
if (lxc_log_fd >= 0)
lxc_log_close();
- if (!fname)
+ if (is_empty_string(fname))
return ret_errno(EINVAL);
if (strlen(fname) == 0) {
log_vmname = strdup(log->name);
if (log->file) {
- if (strcmp(log->file, "none") == 0)
+ if (strequal(log->file, "none"))
return 0;
ret = __lxc_log_set_file(log->file, 1);
if (ret < 0)
return log_error_errno(-1, errno, "Failed to enable logfile");
- lxc_log_use_global_fd = 1;
+ lxc_log_use_global_fd = true;
} else {
/* if no name was specified, there nothing to do */
if (!log->name)
log->lxcpath = LOGPATH;
/* try LOGPATH if lxcpath is the default for the privileged containers */
- if (!geteuid() && strcmp(LXCPATH, log->lxcpath) == 0)
+ if (!geteuid() && strequal(LXCPATH, log->lxcpath))
ret = _lxc_log_set_file(log->name, NULL, 0);
/* try in lxcpath */
return 0;
}
-inline void lxc_log_enable_syslog(void)
+void lxc_log_syslog_enable(void)
+{
+ wants_syslog = true;
+}
+
+void lxc_log_syslog_disable(void)
{
- syslog_enable = 1;
+ wants_syslog = false;
}
/*
return 0;
}
-inline int lxc_log_get_level(void)
+int lxc_log_get_level(void)
{
- return lxc_log_category_lxc.priority;
+ int level = LXC_LOG_LEVEL_NOTSET;
+
+#ifndef NO_LXC_CONF
+ if (current_config)
+ level = current_config->loglevel;
+#endif
+ if (level == LXC_LOG_LEVEL_NOTSET)
+ level = lxc_log_category_lxc.priority;
+
+ return level;
}
bool lxc_log_has_valid_level(void)
if (*fd >= 0)
close_prot_errno_disarm(*fd);
+ if (is_empty_string(fname))
+ return ret_errno(EINVAL);
+
if (build_dir(fname))
return -errno;
*fd = log_open(fname);
if (*fd < 0)
return -errno;
-
return 0;
}
return log_prefix;
}
-inline void lxc_log_options_no_override()
+inline void lxc_log_options_no_override(void)
{
lxc_quiet_specified = 1;
lxc_loglevel_specified = 1;