public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Michal Privoznik <mprivozn@redhat.com>
To: passt-dev@passt.top
Subject: [PATCH 2/2] conf, log: Introduce --log-fd option
Date: Tue,  6 Jun 2023 13:41:30 +0200	[thread overview]
Message-ID: <24c5ae1d4a44e6c3e32cc5e909dacd714b45e3b5.1686037337.git.mprivozn@redhat.com> (raw)
In-Reply-To: <cover.1686037337.git.mprivozn@redhat.com>

So far, users/mgmt apps can use --log-file to specify log output.
This has a downside though - they have to set up permissions so
that passt/pasta can open the file. But we can do a bit better:
allow mgmt apps pass an pre-opened FD and write all log messages
into it.

This then allows the log file to be readable by very few users
(root:root even) or reside in a path which would be otherwise
inaccessible.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 conf.c  | 29 +++++++++++++++++++++++++----
 log.c   | 17 ++++++++++++-----
 log.h   |  2 +-
 passt.1 |  5 +++++
 4 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/conf.c b/conf.c
index ffff235..59d0a8e 100644
--- a/conf.c
+++ b/conf.c
@@ -744,6 +744,7 @@ static void usage(const char *name)
 	info(   "  -e, --stderr		Log to stderr too");
 	info(   "    default: log to system logger only if started from a TTY");
 	info(   "  -l, --log-file PATH	Log (only) to given file");
+	info(	"  --log-fd FD		Log (only) to given file descriptor");
 	info(   "  --log-size BYTES	Maximum size of log file");
 	info(   "    default: 1 MiB");
 	info(   "  --runas UID|UID:GID 	Run as given UID, GID, which can be");
@@ -1181,6 +1182,7 @@ void conf(struct ctx *c, int argc, char **argv)
 		{"config-net",	no_argument,		NULL,		17 },
 		{"no-copy-routes", no_argument,		NULL,		18 },
 		{"no-copy-addrs", no_argument,		NULL,		19 },
+		{"log-fd", required_argument,		NULL,		20 },
 		{ 0 },
 	};
 	struct get_bound_ports_ns_arg ns_ports_arg = { .c = c };
@@ -1192,7 +1194,7 @@ void conf(struct ctx *c, int argc, char **argv)
 	struct in_addr *dns4 = c->ip4.dns;
 	unsigned int ifi4 = 0, ifi6 = 0;
 	const char *optstring;
-	int name, ret, b, i;
+	int name, ret, b, i, logfd = -1;
 	size_t logsize = 0;
 	uid_t uid;
 	gid_t gid;
@@ -1358,6 +1360,22 @@ void conf(struct ctx *c, int argc, char **argv)
 
 			warn("--no-copy-addrs will be dropped soon");
 			c->no_copy_addrs = 1;
+			break;
+		case 20:
+			if (logfile)
+				die("Either --log-file or --log-fd");
+
+			if (c->force_stderr)
+				die("Can't log to both stderr and file");
+
+			if (logfd >= 0)
+				die("Multiple --log-fd options given");
+
+			errno = 0;
+			logfd = strtol(optarg, NULL, 0);
+			if (logfd < 0 || errno)
+				die("Invalid --log-fd: %s", optarg);
+
 			break;
 		case 'd':
 			if (c->debug)
@@ -1369,7 +1387,7 @@ void conf(struct ctx *c, int argc, char **argv)
 			c->debug = 1;
 			break;
 		case 'e':
-			if (logfile)
+			if (logfile || logfd >= 0)
 				die("Can't log to both file and stderr");
 
 			if (c->force_stderr)
@@ -1381,6 +1399,9 @@ void conf(struct ctx *c, int argc, char **argv)
 			if (c->force_stderr)
 				die("Can't log to both stderr and file");
 
+			if (logfd >= 0)
+				die("Either --log-file or --log-fd");
+
 			if (logfile)
 				die("Multiple --log-file options given");
 
@@ -1659,9 +1680,9 @@ void conf(struct ctx *c, int argc, char **argv)
 
 	conf_ugid(runas, &uid, &gid);
 
-	if (logfile) {
+	if (logfile || logfd >= 0) {
 		logfile_init(c->mode == MODE_PASST ? "passt" : "pasta",
-			     logfile, logsize);
+			     logfile, logfd, logsize);
 	}
 
 	nl_sock_init(c, false);
diff --git a/log.c b/log.c
index 3a3d101..28929a7 100644
--- a/log.c
+++ b/log.c
@@ -174,9 +174,10 @@ void passt_vsyslog(int pri, const char *format, va_list ap)
  * logfile_init() - Open log file and write header with PID, version, path
  * @name:	Identifier for header: passt or pasta
  * @path:	Path to log file
+ * @logfd:	Pre-opened log file descriptor (if >= 0)
  * @size:	Maximum size of log file: log_cut_size is calculatd here
  */
-void logfile_init(const char *name, const char *path, size_t size)
+void logfile_init(const char *name, const char *path, int logfd, size_t size)
 {
 	char nl = '\n', exe[PATH_MAX] = { 0 };
 	int n;
@@ -186,10 +187,16 @@ void logfile_init(const char *name, const char *path, size_t size)
 		exit(EXIT_FAILURE);
 	}
 
-	log_file = open(path, O_CREAT | O_TRUNC | O_APPEND | O_RDWR | O_CLOEXEC,
-			S_IRUSR | S_IWUSR);
-	if (log_file == -1)
-		die("Couldn't open log file %s: %s", path, strerror(errno));
+	if (logfd >= 0) {
+		if (set_cloexec(logfd) < 0)
+			die("Could not set CLOEXEC flag on logfd", strerror(errno));
+		log_file = logfd;
+	} else {
+		log_file = open(path, O_CREAT | O_TRUNC | O_APPEND | O_RDWR | O_CLOEXEC,
+				S_IRUSR | S_IWUSR);
+		if (log_file == -1)
+			die("Couldn't open log file %s: %s", path, strerror(errno));
+	}
 
 	log_size = size ? size : LOGFILE_SIZE_DEFAULT;
 
diff --git a/log.h b/log.h
index 3aab29d..d96359a 100644
--- a/log.h
+++ b/log.h
@@ -30,7 +30,7 @@ void trace_init(int enable);
 	} while (0)
 
 void __openlog(const char *ident, int option, int facility);
-void logfile_init(const char *name, const char *path, size_t size);
+void logfile_init(const char *name, const char *path, int logfd, size_t size);
 void passt_vsyslog(int pri, const char *format, va_list ap);
 void logfile_write(int pri, const char *format, va_list ap);
 void __setlogmask(int mask);
diff --git a/passt.1 b/passt.1
index 1ad4276..ee5abbb 100644
--- a/passt.1
+++ b/passt.1
@@ -101,6 +101,11 @@ terminal, and to both system logger and standard error otherwise.
 .BR \-l ", " \-\-log-file " " \fIPATH\fR
 Log to file \fIPATH\fR, not to standard error, and not to the system logger.
 
+.TP
+.BR \-l ", " \-\-log-fd " " \fIFD\fR
+Log to pre-opened file descriptor \fIFD\fR, not to standard error, and not to
+the system logger.
+
 .TP
 .BR \-\-log-size " " \fISIZE\fR
 Limit log file size to \fISIZE\fR bytes. When the log file is full, make room
-- 
@@ -101,6 +101,11 @@ terminal, and to both system logger and standard error otherwise.
 .BR \-l ", " \-\-log-file " " \fIPATH\fR
 Log to file \fIPATH\fR, not to standard error, and not to the system logger.
 
+.TP
+.BR \-l ", " \-\-log-fd " " \fIFD\fR
+Log to pre-opened file descriptor \fIFD\fR, not to standard error, and not to
+the system logger.
+
 .TP
 .BR \-\-log-size " " \fISIZE\fR
 Limit log file size to \fISIZE\fR bytes. When the log file is full, make room
-- 
2.39.3


  parent reply	other threads:[~2023-06-06 11:41 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-06 11:41 [PATCH 0/2] Introduce --log-fd option Michal Privoznik
2023-06-06 11:41 ` [PATCH 1/2] util: Introduce set_cloexec() Michal Privoznik
2023-06-06 20:59   ` Stefano Brivio
2023-06-06 11:41 ` Michal Privoznik [this message]
2023-06-06 20:59   ` [PATCH 2/2] conf, log: Introduce --log-fd option Stefano Brivio
2023-06-06 20:58 ` [PATCH 0/2] " Stefano Brivio
2023-06-07 11:38   ` Michal Prívozník
2023-06-07 14:42     ` Stefano Brivio
2023-06-08 11:51       ` Michal Prívozník
2023-06-13  3:12         ` Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=24c5ae1d4a44e6c3e32cc5e909dacd714b45e3b5.1686037337.git.mprivozn@redhat.com \
    --to=mprivozn@redhat.com \
    --cc=passt-dev@passt.top \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).