[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20200223210645.34584-1-kuniyu@amazon.co.jp>
Date: Mon, 24 Feb 2020 06:06:45 +0900
From: Kuniyuki Iwashima <kuniyu@...zon.co.jp>
To: <kuniyu@...zon.co.jp>
CC: <davem@...emloft.net>, <edumazet@...gle.com>, <kuni1840@...il.com>,
<kuznet@....inr.ac.ru>, <netdev@...r.kernel.org>,
<osa-contribution-log@...zon.com>, <yoshfuji@...ux-ipv6.org>
Subject: Re: [PATCH net-next 0/3] Improve bind(addr, 0) behaviour.
From: Kuniyuki Iwashima <kuniyu@...zon.co.jp>
Date: Sat, 22 Feb 2020 10:07:49 +0900
> I also tested with two users. I am sorry about having tested in python,
> I will rewrite it in C later.
>
> Both of user-a and user-b can get the same port, but one of them failed to
> call listen().
I wrote a test in C and the result was the same.
If all of the sockets bound to the same port have SO_REUSEADDR and
SO_REUSEPORT enabled, two users can bind(), but can only one user listen().
If you would think these patches are safe, I'll respin the patches with
the correct conditon of the 3rd patch.
Thanks.
=====
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
int main(void) {
struct sockaddr_in local_addr;
uid_t euid[2] = {1001, 1002};
int fd[2], error, i, port;
int len = sizeof(local_addr);
int reuseaddr = 1, reuseport = 1;
char ip_str[16];
for (i = 0; i < 2; i++) {
if (seteuid(euid[i]) != 0)
goto error;
fd[i] = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(fd[i], SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));
setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(int));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = inet_addr("10.0.2.15");
local_addr.sin_port = 0;
error = bind(fd[i], (struct sockaddr *)&local_addr, len);
memset(&local_addr, 0, sizeof(local_addr));
getsockname(fd[i], (struct sockaddr *)&local_addr, &len);
inet_ntop(AF_INET, &local_addr.sin_addr, ip_str, sizeof(ip_str));
port = ntohs(local_addr.sin_port);
printf("euid: %d\tbound to %s:%u\n", euid[i], ip_str, port);
if (error != 0)
goto error;
if (seteuid(0) != 0)
goto error;
}
for (i = 0; i < 2; i++) {
if (seteuid(euid[i]) != 0)
goto error;
error = listen(fd[i], 5);
if (error < 0)
printf("euid: %d\tlisten failed\n", euid[i]);
else
printf("euid: %d\tlisten succeeded\n", euid[i]);
if (seteuid(0) != 0)
goto error;
}
return 0;
error:
printf("error: %d, %s\n", errno, strerror(errno));
return -1;
}
=====
===result===
# id user-a
uid=1001(user-a) gid=1001(user-a) groups=1001(user-a)
# id user-b
uid=1002(user-b) gid=1002(user-b) groups=1002(user-b)
# sysctl -w net.ipv4.ip_local_port_range="32768 32768"
[ 30.060036] ip_local_port_range: prefer different parity for start/end values.
net.ipv4.ip_local_port_range = 32768 32768
# ./seteuid
euid: 1001 bound to 10.0.2.15:32768
euid: 1002 bound to 10.0.2.15:32768
euid: 1001 listen succeeded
euid: 1002 listen failed
============
Powered by blists - more mailing lists