ceph/src/log/Log.h
Sage Weil 891d8b4754 log/Log: fix buffer overflow
If we have a long line that has to be dynamically allocated, we need to
adjust m_log_buf_pos accordingly afterward.  In particular,
_write_and_copy does this adjustment, which means the later += line_used
is not only unnecessary but very bad, since line_used is > MAX_LOG_BUF.

Simplify all of this by getting rid of _write_and_copy: if we are writing
a big chunk let's just send the whole thing to m_fd and not bother keeping
the tail of it around for later.

Fix _log_safe_write to write the passed buffer, not m_log_buf.

Replace the paranoid check with a simple assert.

Fixes: 65da5ba216
Fixes: https://github.com/ceph/ceph/pull/23422
Signed-off-by: Sage Weil <sage@redhat.com>
2018-08-06 08:51:28 -05:00

116 lines
2.4 KiB
C++

// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#ifndef __CEPH_LOG_LOG_H
#define __CEPH_LOG_LOG_H
#include <memory>
#include "common/Thread.h"
#include "EntryQueue.h"
namespace ceph {
namespace logging {
class Graylog;
class SubsystemMap;
class Entry;
class Log : private Thread
{
Log **m_indirect_this;
log_clock clock;
const SubsystemMap *m_subs;
pthread_mutex_t m_queue_mutex;
pthread_mutex_t m_flush_mutex;
pthread_cond_t m_cond_loggers;
pthread_cond_t m_cond_flusher;
pthread_t m_queue_mutex_holder;
pthread_t m_flush_mutex_holder;
EntryQueue m_new; ///< new entries
EntryQueue m_recent; ///< recent (less new) entries we've already written at low detail
std::string m_log_file;
int m_fd;
uid_t m_uid;
gid_t m_gid;
int m_fd_last_error; ///< last error we say writing to fd (if any)
int m_syslog_log, m_syslog_crash;
int m_stderr_log, m_stderr_crash;
int m_graylog_log, m_graylog_crash;
std::string m_log_stderr_prefix;
std::shared_ptr<Graylog> m_graylog;
char* m_log_buf; ///< coalescing buffer
int m_log_buf_pos; ///< where we're at within coalescing buffer
bool m_stop;
int m_max_new, m_max_recent;
bool m_inject_segv;
void *entry() override;
void _log_safe_write(const char* what, size_t write_len);
void _flush_logbuf();
void _flush(EntryQueue *q, EntryQueue *requeue, bool crash);
void _log_message(const char *s, bool crash);
public:
Log(const SubsystemMap *s);
~Log() override;
void set_flush_on_exit();
void set_coarse_timestamps(bool coarse);
void set_max_new(int n);
void set_max_recent(int n);
void set_log_file(std::string fn);
void reopen_log_file();
void chown_log_file(uid_t uid, gid_t gid);
void set_log_stderr_prefix(const std::string& p);
void flush();
void dump_recent();
void set_syslog_level(int log, int crash);
void set_stderr_level(int log, int crash);
void set_graylog_level(int log, int crash);
void start_graylog();
void stop_graylog();
std::shared_ptr<Graylog> graylog() { return m_graylog; }
Entry *create_entry(int level, int subsys, const char* msg = nullptr);
Entry *create_entry(int level, int subsys, size_t* expected_size);
void submit_entry(Entry *e);
void start();
void stop();
/// true if the log lock is held by our thread
bool is_inside_log_lock();
/// induce a segv on the next log event
void inject_segv();
void reset_segv();
};
}
}
#endif