public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Mickaël Salaün" <mic@digikod.net>
To: Matthieu Buffet <matthieu@buffet.re>
Cc: "Günther Noack" <gnoack@google.com>,
	"Konstantin Meskhidze" <konstantin.meskhidze@huawei.com>,
	"Ivanov Mikhail" <ivanov.mikhail1@huawei-partners.com>,
	linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	"Tahera Fahimi" <fahimitahera@gmail.com>
Subject: Re: [PATCH v3 1/3] samples/landlock: Fix port parsing in sandboxer
Date: Tue, 22 Oct 2024 20:50:15 +0200	[thread overview]
Message-ID: <20241022.Xi2Wiemeehai@digikod.net> (raw)
In-Reply-To: <20241019151534.1400605-2-matthieu@buffet.re>

Thanks! I pushed the three patches in my -next branch with minor
changes.

On Sat, Oct 19, 2024 at 05:15:32PM +0200, Matthieu Buffet wrote:
> If you want to specify that no port can be bind()ed, you would think
> (looking quickly at both help message and code) that setting LL_TCP_BIND=""
> would do it.
> 
> However the code splits on ":" then applies atoi(), which does not allow
> checking for errors. Passing an empty string returns 0, which is
> interpreted as "allow bind(0)", which means bind to any ephemeral port.
> This bug occurs whenever passing an empty string or when leaving a
> trailing/leading colon, making it impossible to completely deny bind().
> 
> To reproduce:
> export LL_FS_RO="/" LL_FS_RW="" LL_TCP_BIND=""
> ./sandboxer strace -e bind nc -n -vvv -l -p 0
> Executing the sandboxed command...
> bind(3, {sa_family=AF_INET, sin_port=htons(0),
>      sin_addr=inet_addr("0.0.0.0")}, 16) = 0
> Listening on 0.0.0.0 37629
> 
> Use strtoull(3) instead, which allows error checking. Check that the entire
> string has been parsed correctly without overflows/underflows, but not
> that the __u64 (the type of struct landlock_net_port_attr.port)
> is a valid __u16 port: that is already done by the kernel.
> 
> Fixes: 5e990dcef12e ("samples/landlock: Support TCP restrictions")
> Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
> ---
>  samples/landlock/sandboxer.c | 32 ++++++++++++++++++++++++++++++--
>  1 file changed, 30 insertions(+), 2 deletions(-)
> 
> diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c
> index f847e832ba14..4cbef9d2f15b 100644
> --- a/samples/landlock/sandboxer.c
> +++ b/samples/landlock/sandboxer.c
> @@ -60,6 +60,25 @@ static inline int landlock_restrict_self(const int ruleset_fd,
>  #define ENV_SCOPED_NAME "LL_SCOPED"
>  #define ENV_DELIMITER ":"
>  
> +static int str2num(const char *numstr, __u64 *num_dst)
> +{
> +	char *endptr = NULL;
> +	int err = 0;
> +	__u64 num;
> +
> +	errno = 0;
> +	num = strtoull(numstr, &endptr, 10);
> +	if (errno != 0)
> +		err = errno;
> +	/* Was the string empty, or not entirely parsed successfully? */
> +	else if ((*numstr == '\0') || (*endptr != '\0'))

We cannot pass "0 " but we can still pass " 0".  I'm good with that
though.

> +		err = EINVAL;
> +	else
> +		*num_dst = num;
> +
> +	return err;
> +}
> +
>  static int parse_path(char *env_path, const char ***const path_list)
>  {
>  	int i, num_paths = 0;
> @@ -160,7 +179,6 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
>  	char *env_port_name, *env_port_name_next, *strport;
>  	struct landlock_net_port_attr net_port = {
>  		.allowed_access = allowed_access,
> -		.port = 0,
>  	};
>  
>  	env_port_name = getenv(env_var);
> @@ -171,7 +189,17 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
>  
>  	env_port_name_next = env_port_name;
>  	while ((strport = strsep(&env_port_name_next, ENV_DELIMITER))) {
> -		net_port.port = atoi(strport);
> +		__u64 port;
> +
> +		if (strcmp(strport, "") == 0)
> +			continue;
> +
> +		if (str2num(strport, &port)) {
> +			fprintf(stderr, "Failed to parse port at \"%s\"\n",
> +				strport);
> +			goto out_free_name;
> +		}
> +		net_port.port = port;
>  		if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
>  				      &net_port, 0)) {
>  			fprintf(stderr,
> -- 
> 2.39.5
> 
> 

  reply	other threads:[~2024-10-22 18:50 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-19 15:15 [PATCH v3 0/3] samples/landlock: Fix port parsing in sandboxer Matthieu Buffet
2024-10-19 15:15 ` [PATCH v3 1/3] " Matthieu Buffet
2024-10-22 18:50   ` Mickaël Salaün [this message]
2024-10-19 15:15 ` [PATCH v3 2/3] samples/landlock: Refactor help message Matthieu Buffet
2024-10-19 15:15 ` [PATCH v3 3/3] samples/landlock: Clarify option parsing behaviour Matthieu Buffet
2024-10-22 18:50   ` Mickaël Salaün

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=20241022.Xi2Wiemeehai@digikod.net \
    --to=mic@digikod.net \
    --cc=fahimitahera@gmail.com \
    --cc=gnoack@google.com \
    --cc=ivanov.mikhail1@huawei-partners.com \
    --cc=konstantin.meskhidze@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=matthieu@buffet.re \
    /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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox