public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Stefano Brivio <sbrivio@redhat.com>
To: Michal Privoznik <mprivozn@redhat.com>
Cc: passt-dev@passt.top
Subject: Re: [PATCH 2/2] conf, log: Introduce --log-fd option
Date: Tue, 6 Jun 2023 22:59:10 +0200	[thread overview]
Message-ID: <20230606225910.228dd2e0@elisabeth> (raw)
In-Reply-To: <24c5ae1d4a44e6c3e32cc5e909dacd714b45e3b5.1686037337.git.mprivozn@redhat.com>

On Tue,  6 Jun 2023 13:41:30 +0200
Michal Privoznik <mprivozn@redhat.com> wrote:

> 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.

Right... that's exactly the part that worries me (even though I
understand and appreciate the compatibility argument).

> 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;

We use a reverse christmas tree convention for ordering local
variables (like Linux kernel network code does), rationale:
consistency, plus:
  https://hisham.hm/2018/06/16/when-listing-repeated-things-make-pyramids/

>  	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) {

We should probably ftruncate() the referenced file to zero bytes, here,
because otherwise we're not guaranteeing the rotation with fallocate()
later.

> +		if (set_cloexec(logfd) < 0)
> +			die("Could not set CLOEXEC flag on logfd", strerror(errno));

Using errno from set_cloexec() is a bit fragile, in case somebody ever
adds something else to that function.

By the way, this,

> +		log_file = logfd;
> +	} else {
> +		log_file = open(path, O_CREAT | O_TRUNC | O_APPEND | O_RDWR | O_CLOEXEC,
> +				S_IRUSR | S_IWUSR);

this,

> +		if (log_file == -1)
> +			die("Couldn't open log file %s: %s", path, strerror(errno));

and this now exceed 80 columns.

-- 
Stefano


  reply	other threads:[~2023-06-06 20:59 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 ` [PATCH 2/2] conf, log: Introduce --log-fd option Michal Privoznik
2023-06-06 20:59   ` Stefano Brivio [this message]
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=20230606225910.228dd2e0@elisabeth \
    --to=sbrivio@redhat.com \
    --cc=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).