mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-22 04:32:21 +00:00
Compare commits
3 Commits
proposal/r
...
nova-debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
258103be08 | ||
|
|
f35cc98126 | ||
|
|
94149e4b00 |
@@ -10,9 +10,6 @@ This is a list of production adopters of Falco (in alphabetical order):
|
||||
|
||||
* [League](https://league.com/ca/) - League provides health benefits management services to help employees understand and get the most from their benefits, and employers to provide effective, efficient plans. Falco is used to monitor our deployed services on Kubernetes, protecting against malicious access to containerswhich could lead to leaks of PHI or other sensitive data. The Falco alerts are logged in Stackdriver for grouping and further analysis. In the future, we're hoping for integrations with Prometheus and AlertManager as well.
|
||||
|
||||
* [Logz.io](https://logz.io/) - Logz.io is a cloud observability platform for modern engineering teams. The Logz.io platform consists of three products — Log Management, Infrastructure Monitoring, and Cloud SIEM — that work together to unify the jobs of monitoring, troubleshooting, and security. We empower engineers to deliver better software by offering the world's most popular open source observability tools — the ELK Stack, Grafana, and Jaeger — in a single, easy to use, and powerful platform purpose-built for monitoring distributed cloud environments. Cloud SIEM supports data from multiple sources, including Falco's alerts, and offers useful rules and dashboards content to visualize and manage incidents across your systems in a unified UI.
|
||||
* https://logz.io/blog/k8s-security-with-falco-and-cloud-siem/
|
||||
|
||||
* [Preferral](https://www.preferral.com) - Preferral is a HIPAA-compliant platform for Referral Management and Online Referral Forms. Preferral streamlines the referral process for patients, specialists and their referral partners. By automating the referral process, referring practices spend less time on the phone, manual efforts are eliminated, and patients get the right care from the right specialist. Preferral leverages Falco to provide a Host Intrusion Detection System to meet their HIPPA compliance requirements.
|
||||
* https://hipaa.preferral.com/01-preferral_hipaa_compliance/
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ file(MAKE_DIRECTORY ${SYSDIG_CMAKE_WORKING_DIR})
|
||||
# To update sysdig version for the next release, change the default below
|
||||
# In case you want to test against another sysdig version just pass the variable - ie., `cmake -DSYSDIG_VERSION=dev ..`
|
||||
if(NOT SYSDIG_VERSION)
|
||||
set(SYSDIG_VERSION "422ab408c5706fbdd45432646cc197eb79459169")
|
||||
set(SYSDIG_CHECKSUM "SHA256=367db2a480bca327a46f901bcc8384f151231bcddba88c719a06cf13971f4ab5")
|
||||
set(SYSDIG_VERSION "96bd9bc560f67742738eb7255aeb4d03046b8045")
|
||||
set(SYSDIG_CHECKSUM "SHA256=766e8952a36a4198fd976b9d848523e6abe4336612188e4fc911e217d8e8a00d")
|
||||
endif()
|
||||
set(PROBE_VERSION "${SYSDIG_VERSION}")
|
||||
|
||||
|
||||
45
docker/build/install-falco.yaml
Normal file
45
docker/build/install-falco.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
kind: DaemonSet
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: falco
|
||||
namespace: falco
|
||||
labels:
|
||||
app: falco
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: falco
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: falco
|
||||
spec:
|
||||
tolerations:
|
||||
- operator: Exists
|
||||
hostPID: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: falco-init
|
||||
image: alpine
|
||||
imagePullPolicy: Always
|
||||
securityContext:
|
||||
privileged: true
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command:
|
||||
- "nsenter"
|
||||
- "-t"
|
||||
- "1"
|
||||
- "-m"
|
||||
- "--"
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- |
|
||||
#!/bin/bash
|
||||
curl -s https://falco.org/repo/falcosecurity-3672BA8F.asc | apt-key add -
|
||||
echo "deb https://dl.bintray.com/falcosecurity/deb stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list
|
||||
apt-get update -y
|
||||
apt-get -y install linux-headers-$(uname -r)
|
||||
apt-get install -y falco
|
||||
exit 0
|
||||
@@ -139,7 +139,7 @@ stdout_output:
|
||||
webserver:
|
||||
enabled: true
|
||||
listen_port: 8765
|
||||
k8s_audit_endpoint: /k8s-audit
|
||||
k8s_audit_endpoint: /k8s_audit
|
||||
ssl_enabled: false
|
||||
ssl_certificate: /etc/falco/falco.pem
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# Required engine version scoping for rules
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Summary](#summary)
|
||||
- [Motivation](#motivation)
|
||||
* [Goals](#goals)
|
||||
* [Non-Goals](#non-goals)
|
||||
* [Use cases](#use-cases)
|
||||
* [Example of rules file](#example-of-rules-file)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Summary
|
||||
|
||||
We want to be able to scope the `required_engine_version` field also for the specific rule/macro
|
||||
other than just for the currently rules file.
|
||||
|
||||
## Motivation
|
||||
|
||||
While the Falco engine and drivers evolve, new fields are added. While new fields are added,
|
||||
the upstream rules evolve too. This menas that we need a mechanism to be able to tell the users
|
||||
and the engine at load time "Hey, this rule is compatible". We currently do that at file level
|
||||
using the `required_engine_version` field.
|
||||
|
||||
While this is very handy, this also does not help users to understand what are the rules that require,
|
||||
let's say engine verison `6` instead of `5`. It's very likely that 99% of a file is compatible with engine `2` while
|
||||
in reality only one rule is not.
|
||||
|
||||
This is particularly useful for rules sharing. Users with different Falco versions can share rules containing this field
|
||||
and instead of getting `<NA>` they can be informed immediatelly about the incompatibility.
|
||||
|
||||
### Goals
|
||||
|
||||
- To add a new field `required_engine_version` scoped to the `rule` and `macro` sections.
|
||||
- The new fields take priority over the file global `required_engine_version` field.
|
||||
|
||||
### Non-Goals
|
||||
|
||||
- NONE
|
||||
|
||||
### Use cases
|
||||
|
||||
- Better understanding of what are the specific rules that need a specific engine version
|
||||
- Helps for when we want to make an API to create/delete/modify rules at runtime. In such a dynamic scenarios it's very useful for users to just know in advance if that rule is compatible
|
||||
- Makes easier to spot `<NA>` fields happening for `required_engine_version` mismatches since the incompatibility is immediately reported by the engine.
|
||||
|
||||
|
||||
### Example of rules file
|
||||
|
||||
```yaml
|
||||
- required_engine_version: 2
|
||||
|
||||
- list: cat_binaries
|
||||
items: [cat]
|
||||
|
||||
- list: cat_capable_binaries
|
||||
items: [cat_binaries]
|
||||
|
||||
- macro: is_cat
|
||||
condition: proc.name in (cat_capable_binaries)
|
||||
|
||||
- rule: open_from_cat
|
||||
required_engine_version: 4
|
||||
desc: A process named cat does an open
|
||||
condition: evt.type=open and is_cat
|
||||
output: "An open was seen (command=%proc.cmdline)"
|
||||
priority: WARNING
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
@@ -942,12 +942,6 @@
|
||||
NOTICE
|
||||
tags: [filesystem, mitre_persistence]
|
||||
|
||||
# Users should overwrite this macro to specify conditions under which a
|
||||
# write under the binary dir is ignored. For example, it may be okay to
|
||||
# install a binary in the context of a ci/cd build.
|
||||
- macro: user_known_write_below_binary_dir_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Write below binary dir
|
||||
desc: an attempt to write to any file below a set of binary directories
|
||||
condition: >
|
||||
@@ -956,7 +950,6 @@
|
||||
and not exe_running_docker_save
|
||||
and not python_running_get_pip
|
||||
and not python_running_ms_oms
|
||||
and not user_known_write_below_binary_dir_activities
|
||||
output: >
|
||||
File below a known binary directory opened for writing (user=%user.name
|
||||
command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository)
|
||||
@@ -1376,9 +1369,6 @@
|
||||
- macro: runc_writing_exec_fifo
|
||||
condition: (proc.cmdline="runc:[1:CHILD] init" and fd.name=/exec.fifo)
|
||||
|
||||
- macro: runc_writing_var_lib_docker
|
||||
condition: (proc.cmdline="runc:[1:CHILD] init" and evt.arg.filename startswith /var/lib/docker)
|
||||
|
||||
- rule: Write below root
|
||||
desc: an attempt to write to any file directly below / or /root
|
||||
condition: >
|
||||
@@ -2525,7 +2515,7 @@
|
||||
- rule: Delete Bash History
|
||||
desc: Detect bash history deletion
|
||||
condition: >
|
||||
((spawned_process and proc.name in (shred, rm, mv) and proc.args contains "bash_history") or
|
||||
((spawned_process and proc.name in (shred, rm, mv) and proc.args contains "bash_history") or
|
||||
(open_write and fd.name contains "bash_history" and evt.arg.flags contains "O_TRUNC"))
|
||||
output: >
|
||||
Shell history had been deleted or renamed (user=%user.name type=%evt.type command=%proc.cmdline fd.name=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath %container.info)
|
||||
@@ -2749,7 +2739,7 @@
|
||||
output: Packet socket was created in a container (user=%user.name command=%proc.cmdline socket_info=%evt.args container_id=%container.id container_name=%container.name image=%container.image.repository:%container.image.tag)
|
||||
priority: NOTICE
|
||||
tags: [network, mitre_discovery]
|
||||
|
||||
|
||||
# Change to (always_true) to enable rule 'Network connection outside local subnet'
|
||||
- macro: enabled_rule_network_only_subnet
|
||||
condition: (never_true)
|
||||
@@ -2765,7 +2755,7 @@
|
||||
- macro: network_local_subnet
|
||||
condition: >
|
||||
fd.rnet in (rfc_1918_addresses) or
|
||||
fd.ip = "0.0.0.0" or
|
||||
fd.ip = "0.0.0.0" or
|
||||
fd.net = "127.0.0.0/8"
|
||||
|
||||
# # How to test:
|
||||
@@ -2825,7 +2815,7 @@
|
||||
not fd.sport in (authorized_server_port)
|
||||
output: >
|
||||
Network connection outside authorized port and binary
|
||||
(command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id
|
||||
(command=%proc.cmdline connection=%fd.name user=%user.name container_id=%container.id
|
||||
image=%container.image.repository)
|
||||
priority: WARNING
|
||||
tags: [network]
|
||||
@@ -2837,46 +2827,6 @@
|
||||
Redirect stdout/stdin to network connection (user=%user.name %container.info process=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository fd.name=%fd.name fd.num=%fd.num fd.type=%fd.type fd.sip=%fd.sip)
|
||||
priority: WARNING
|
||||
|
||||
# The two Container Drift rules below will fire when a new executable is created in a container.
|
||||
# There are two ways to create executables - file is created with execution permissions or permissions change of existing file.
|
||||
# We will use a new sysdig filter, is_open_exec, to find all files creations with execution permission, and will trace all chmods in a container.
|
||||
# The use case we are targeting here is an attempt to execute code that was not shipped as part of a container (drift) -
|
||||
# an activity that might be malicious or non-compliant.
|
||||
# Two things to pay attention to:
|
||||
# 1) In most cases, 'docker cp' will not be identified, but the assumption is that if an attacker gained access to the container runtime daemon, they are already privileged
|
||||
# 2) Drift rules will be noisy in environments in which containers are built (e.g. docker build)
|
||||
|
||||
- rule: Container Drift Detected (chmod)
|
||||
desc: New executable created in a container due to chmod
|
||||
condition: >
|
||||
chmod and
|
||||
consider_all_chmods and
|
||||
container and
|
||||
not runc_writing_exec_fifo and
|
||||
not runc_writing_var_lib_docker and
|
||||
evt.rawres>=0 and
|
||||
((evt.arg.mode contains "S_IXUSR") or
|
||||
(evt.arg.mode contains "S_IXGRP") or
|
||||
(evt.arg.mode contains "S_IXOTH"))
|
||||
output: Drift detected (chmod), new executable created in a container (user=%user.name command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
|
||||
priority: ERROR
|
||||
|
||||
# ****************************************************************************
|
||||
# * "Container Drift Detected (open+create)" requires FALCO_ENGINE_VERSION 6 *
|
||||
# ****************************************************************************
|
||||
- rule: Container Drift Detected (open+create)
|
||||
desc: New executable created in a container due to open+create
|
||||
condition: >
|
||||
evt.type in (open,openat,creat) and
|
||||
evt.is_open_exec=true and
|
||||
container and
|
||||
not runc_writing_exec_fifo and
|
||||
not runc_writing_var_lib_docker and
|
||||
evt.rawres>=0
|
||||
output: Drift detected (open+create), new executable created in a container (user=%user.name command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
|
||||
priority: ERROR
|
||||
|
||||
|
||||
# Application rules have moved to application_rules.yaml. Please look
|
||||
# there if you want to enable them by adding to
|
||||
# falco_rules.local.yaml.
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
- rule: Anonymous Request Allowed
|
||||
desc: >
|
||||
Detect any request made by the anonymous user that was allowed
|
||||
condition: kevt and ka.user.name=system:anonymous and ka.auth.decision="allow" and not health_endpoint
|
||||
condition: kevt and ka.user.name=system:anonymous and ka.auth.decision!=reject and not health_endpoint
|
||||
output: Request by anonymous user allowed (user=%ka.user.name verb=%ka.verb uri=%ka.uri reason=%ka.auth.reason))
|
||||
priority: WARNING
|
||||
source: k8s_audit
|
||||
|
||||
22
userspace/README.md
Normal file
22
userspace/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Userspace
|
||||
|
||||
Here is where the main Falco engine lives.
|
||||
|
||||
There are two libraries here that are roughly seperated in the following way.are
|
||||
|
||||
### falco
|
||||
|
||||
This is the beloved `main()` function of the Falco program, as well as the logic for various falco outputs.
|
||||
|
||||
An output is just a way of delivering a Falco alert, the most simple output is the Falco stdout log.
|
||||
|
||||
### engine
|
||||
|
||||
This is the processing engine that connect the inbound stream of systemcalls to the rules engine.
|
||||
|
||||
This is the main powerhouse behind Falco, and does the assertion at runtime that compares system call events to rules.are
|
||||
|
||||
|
||||
### CMake
|
||||
|
||||
If you are adding new files to either library you must define the `.cpp` file in the associated CMakeLists.txt file such that the linker will know where to find your new file.
|
||||
@@ -16,6 +16,7 @@ set(FALCO_ENGINE_SOURCE_FILES
|
||||
falco_engine.cpp
|
||||
falco_utils.cpp
|
||||
json_evt.cpp
|
||||
prettyprint.cpp
|
||||
ruleset.cpp
|
||||
token_bucket.cpp
|
||||
formats.cpp)
|
||||
|
||||
@@ -22,6 +22,7 @@ limitations under the License.
|
||||
#include "falco_engine.h"
|
||||
#include "falco_utils.h"
|
||||
#include "falco_engine_version.h"
|
||||
#include "prettyprint.h"
|
||||
#include "config_falco_engine.h"
|
||||
|
||||
#include "formats.h"
|
||||
@@ -316,6 +317,9 @@ unique_ptr<falco_engine::rule_result> falco_engine::process_sinsp_event(sinsp_ev
|
||||
string err = "Error invoking function output: " + string(lerr);
|
||||
throw falco_exception(err);
|
||||
}
|
||||
|
||||
prettyprint::sinsp_event(ev, "Raw event just before popping to Lua");
|
||||
|
||||
res->evt = ev;
|
||||
const char *p = lua_tostring(m_ls, -3);
|
||||
res->rule = p;
|
||||
|
||||
@@ -16,9 +16,9 @@ limitations under the License.
|
||||
|
||||
// The version of rules/filter fields/etc supported by this falco
|
||||
// engine.
|
||||
#define FALCO_ENGINE_VERSION (6)
|
||||
#define FALCO_ENGINE_VERSION (5)
|
||||
|
||||
// This is the result of running "falco --list -N | sha256sum" and
|
||||
// represents the fields supported by this version of falco. It's used
|
||||
// at build time to detect a changed set of fields.
|
||||
#define FALCO_FIELDS_CHECKSUM "2f324e2e66d4b423f53600e7e0fcf2f0ff72e4a87755c490f2ae8f310aba9386"
|
||||
#define FALCO_FIELDS_CHECKSUM "ca9e75fa41fe4480cdfad8cf275cdbbc334e656569f070c066d87cbd2955c1ae"
|
||||
|
||||
82
userspace/engine/prettyprint.cpp
Normal file
82
userspace/engine/prettyprint.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (C) 2019 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "prettyprint.h"
|
||||
|
||||
/**
|
||||
* sinsp_event will pretty print a pointer to a sinsp_evt.
|
||||
*
|
||||
* This can be used for debugging an event at various times during development.
|
||||
* This should never be turned on in production. Feel free to add fields below
|
||||
* as we need them, and we can just dump an event in here whenever we need while
|
||||
* debugging.
|
||||
*
|
||||
* sinsp_events are blue because they are happy.
|
||||
*/
|
||||
void prettyprint::sinsp_event(sinsp_evt *ev, const char* note)
|
||||
{
|
||||
ev->get_type()
|
||||
prettyprint::warning();
|
||||
printf("\033[0;34m"); // Start Blue
|
||||
printf("\n*************************************************************\n");
|
||||
printf("[Sinsp Event: %s]\n\n", note);
|
||||
printf("name: %s\n", ev->get_name());
|
||||
for(uint32_t i = 0; i <= ev->get_num_params(); i++){
|
||||
}
|
||||
for(int64_t j = 0; j <= ev->get_fd_num(); j++) {
|
||||
printf("%s: %s\n", ev->get_param_name(j), ev->get_param_value_str(j, true).c_str());
|
||||
};
|
||||
// One off fields
|
||||
//printf("fdinfo: %s\n", ev->get_fd_info()->tostring_clean().c_str());
|
||||
//printf("type: %d\n", ev->get_type());
|
||||
/*
|
||||
printf("k8s.ns.name: %s\n", ev->get_param_value_str("k8s.ns.name", true).c_str());
|
||||
printf("k8s %s\n", ev->get_param_value_str("k8s", true).c_str());
|
||||
printf("container: %s\n", ev->get_param_value_str("container", true).c_str());
|
||||
printf("proc.pid: %s\n", ev->get_param_value_str("%proc.pid", true).c_str());
|
||||
printf("proc: %s\n", ev->get_param_value_str("%proc", true).c_str());
|
||||
printf("data: %s\n", ev->get_param_value_str("data", true).c_str());
|
||||
printf("cpu: %s\n", ev->get_param_value_str("cpu", true).c_str());
|
||||
printf("fd: %s\n", ev->get_param_value_str("fd", true).c_str());
|
||||
printf("fd: %s\n", ev->get_param_value_str("evt.arg.fd", true).c_str());
|
||||
printf("user: %s\n", ev->get_param_value_str("user", true).c_str());
|
||||
*/
|
||||
|
||||
printf("*************************************************************\n");
|
||||
printf("\033[0m");
|
||||
}
|
||||
|
||||
/**
|
||||
* has_alerted controls our one time preliminary alert for using pretty print which is debug only
|
||||
*/
|
||||
bool prettyprint::has_alerted = false;
|
||||
|
||||
/**
|
||||
* Warnings are red
|
||||
*/
|
||||
void prettyprint::warning() {
|
||||
if (!prettyprint::has_alerted) {
|
||||
printf("\033[0;31m"); // Start Red
|
||||
printf("\n\n");
|
||||
printf("*************************************************************\n");
|
||||
printf(" [Pretty Printing Debugging is Enabled] \n");
|
||||
printf(" This should never be used in production, by anyone, ever. \n");
|
||||
printf("*************************************************************\n");
|
||||
printf("\033[0m");
|
||||
prettyprint::has_alerted = true;
|
||||
}
|
||||
}
|
||||
|
||||
42
userspace/engine/prettyprint.h
Normal file
42
userspace/engine/prettyprint.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (C) 2019 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "sinsp.h"
|
||||
#include "filter.h"
|
||||
#include "event.h"
|
||||
|
||||
#include "gen_filter.h"
|
||||
|
||||
|
||||
#ifndef FALCO_FALCO_USERSPACE_PRETTYPRINT_H_
|
||||
#define FALCO_FALCO_USERSPACE_PRETTYPRINT_H_
|
||||
|
||||
class prettyprint {
|
||||
public:
|
||||
static void sinsp_event(sinsp_evt *ev, const char* note = "");
|
||||
|
||||
private:
|
||||
static bool has_alerted;
|
||||
static void warning();
|
||||
};
|
||||
|
||||
#endif //FALCO_FALCO_USERSPACE_PRETTYPRINT_H_
|
||||
@@ -145,6 +145,8 @@ void falco_outputs::handle_event(gen_event *ev, string &rule, string &source,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::lock_guard<std::mutex> guard(m_ls_semaphore);
|
||||
lua_getglobal(m_ls, m_lua_output_event.c_str());
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ void falco_logger::log(int priority, const string msg)
|
||||
if(gtm != NULL &&
|
||||
(strftime(buf, sizeof(buf), "%FT%T%z", gtm) != 0))
|
||||
{
|
||||
fprintf(stderr, "%s: %s", buf, copy.c_str());
|
||||
fprintf(stderr, "%s: %s", buf, msg.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -151,7 +151,7 @@ void falco_logger::log(int priority, const string msg)
|
||||
{
|
||||
tstr = "N/A";
|
||||
}
|
||||
fprintf(stderr, "%s: %s", tstr.c_str(), copy.c_str());
|
||||
fprintf(stderr, "%s: %s", tstr.c_str(), msg.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user