Re: Unlock ip6_sysctl()

2023-05-18 Thread Florian Obser
On 2023-05-18 00:14 +02, Alexander Bluhm  wrote:
> And why is this ip6_soiikey in the kernel anyway?  I guess it is
> from a time when address configuration was done in the kernel.
> Could slaacd(8) just read /etc/soii.key?

Originally we implemented RFC 7217 for link-local addresses, too. The
value of doing that is IMO not very high and it turned out that there
are ISPs out there that calculate the clients link-local address from
the MAC address and route a /64 (or whatever) to that link-local
address. If we calculate a different link-local address IPv6 is broken.

It's pretty difficult to debug this so we removed support for it in the
kernel.

p.s. Furthermore I think link-local addresses should be generated by
userland.

-- 
In my defence, I have been left unsupervised.



Re: Unlock ip6_sysctl()

2023-05-18 Thread Claudio Jeker
On Thu, May 18, 2023 at 01:56:13AM +0300, Vitaliy Makkoveev wrote:
> > On 18 May 2023, at 01:14, Alexander Bluhm  wrote:
> > 
> > On Wed, May 17, 2023 at 12:46:02PM +0300, Vitaliy Makkoveev wrote:
> >> Introduce `ip6_soiikey_lock' rwlock(9) to protect `ip6_soiikey'. It
> >> accessed only by ip6_sysctl_soiikey() and ip6_sysctl() is the only
> >> ip6_sysctl_soiikey() caller so context switch is allowed here. Also
> >> remove unused `oldkey' from ip6_sysctl_soiikey().
> > 
> > rwlock or mutex?  As sysctl mlocks userland memory, copyin/copyout
> > cannot sleep here.  So it should be safe to use a mutex.
> 
> It is locked because context switch is strictly unwanted when you
> do copyin/copyout within foreach loops of kernel lock protected
> lists like ps_list. Really this lock is the kind of a hack. But
> since rwlocks already introduced context switch to sysctl() paths,
> we use sysctl_lock rwlock to prevent many processes to
> simultaneously lock large amount of memory. This is another hack
> in this layer. Guess, both of them will gone in the future, so
> copyin/copyout will sleep. So rwlock is better.
> 
> > 
> > And why is this ip6_soiikey in the kernel anyway?  I guess it is
> > from a time when address configuration was done in the kernel.
> > Could slaacd(8) just read /etc/soii.key?
> 
> It could, but this should be implemented in slaacd first. And this
> work is not related to (*pr_sysctl)() unlocking.
> 

Please stop changing the locking inside sysctl. It seems that the last
change introduced a regression with the result that systems lock up.
Until that is solved nothing else should be changed in this code.

-- 
:wq Claudio



Re: Unlock ip6_sysctl()

2023-05-17 Thread Vitaliy Makkoveev
> On 18 May 2023, at 01:14, Alexander Bluhm  wrote:
> 
> On Wed, May 17, 2023 at 12:46:02PM +0300, Vitaliy Makkoveev wrote:
>> Introduce `ip6_soiikey_lock' rwlock(9) to protect `ip6_soiikey'. It
>> accessed only by ip6_sysctl_soiikey() and ip6_sysctl() is the only
>> ip6_sysctl_soiikey() caller so context switch is allowed here. Also
>> remove unused `oldkey' from ip6_sysctl_soiikey().
> 
> rwlock or mutex?  As sysctl mlocks userland memory, copyin/copyout
> cannot sleep here.  So it should be safe to use a mutex.

It is locked because context switch is strictly unwanted when you
do copyin/copyout within foreach loops of kernel lock protected
lists like ps_list. Really this lock is the kind of a hack. But
since rwlocks already introduced context switch to sysctl() paths,
we use sysctl_lock rwlock to prevent many processes to
simultaneously lock large amount of memory. This is another hack
in this layer. Guess, both of them will gone in the future, so
copyin/copyout will sleep. So rwlock is better.

> 
> And why is this ip6_soiikey in the kernel anyway?  I guess it is
> from a time when address configuration was done in the kernel.
> Could slaacd(8) just read /etc/soii.key?

It could, but this should be implemented in slaacd first. And this
work is not related to (*pr_sysctl)() unlocking.

> 
>> For IPV6CTL_MRTSTATS, IPV6CTL_MRTMIF and IPV6CTL_MRTMFC cases netlock
>> could be relaxed to share netlock, but with separate diffs.
>> 
>> ok?
>> 
>> Index: sys/netinet6/in6_proto.c
>> ===
>> RCS file: /cvs/src/sys/netinet6/in6_proto.c,v
>> retrieving revision 1.112
>> diff -u -p -r1.112 in6_proto.c
>> --- sys/netinet6/in6_proto.c 23 Nov 2022 14:48:28 -  1.112
>> +++ sys/netinet6/in6_proto.c 17 May 2023 09:37:05 -
>> @@ -128,6 +128,7 @@ const struct protosw inet6sw[] = {
>> {
>>   .pr_domain = &inet6domain,
>>   .pr_protocol   = IPPROTO_IPV6,
>> +  .pr_flags = PR_MPSYSCTL,
>>   .pr_init   = ip6_init,
>>   .pr_slowtimo   = frag6_slowtimo,
>>   .pr_sysctl = ip6_sysctl
>> Index: sys/netinet6/ip6_input.c
>> ===
>> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
>> retrieving revision 1.254
>> diff -u -p -r1.254 ip6_input.c
>> --- sys/netinet6/ip6_input.c 21 Aug 2022 14:15:55 -  1.254
>> +++ sys/netinet6/ip6_input.c 17 May 2023 09:37:05 -
>> @@ -118,6 +118,7 @@ struct niqueue ip6intrq = NIQUEUE_INITIA
>> struct cpumem *ip6counters;
>> 
>> uint8_t ip6_soiikey[IP6_SOIIKEY_LEN];
>> +struct rwlock ip6_soiikey_lock = RWLOCK_INITIALIZER("soiikeylk");
>> 
>> int ip6_ours(struct mbuf **, int *, int, int);
>> int ip6_check_rh0hdr(struct mbuf *, int *);
>> @@ -1477,17 +1478,16 @@ ip6_sysctl_ip6stat(void *oldp, size_t *o
>> int
>> ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
>> {
>> -uint8_t oldkey[IP6_SOIIKEY_LEN];
>>  int error;
>> 
>>  error = suser(curproc);
>>  if (error != 0)
>>  return (error);
>> 
>> -memcpy(oldkey, ip6_soiikey, sizeof(oldkey));
>> -
>> +rw_enter_write(&ip6_soiikey_lock);
>>  error = sysctl_struct(oldp, oldlenp, newp, newlen, ip6_soiikey,
>>  sizeof(ip6_soiikey));
>> +rw_exit_write(&ip6_soiikey_lock);
>> 
>>  return (error);
>> }



Re: Unlock ip6_sysctl()

2023-05-17 Thread Alexander Bluhm
On Wed, May 17, 2023 at 12:46:02PM +0300, Vitaliy Makkoveev wrote:
> Introduce `ip6_soiikey_lock' rwlock(9) to protect `ip6_soiikey'. It
> accessed only by ip6_sysctl_soiikey() and ip6_sysctl() is the only
> ip6_sysctl_soiikey() caller so context switch is allowed here. Also
> remove unused `oldkey' from ip6_sysctl_soiikey().

rwlock or mutex?  As sysctl mlocks userland memory, copyin/copyout
cannot sleep here.  So it should be safe to use a mutex.

And why is this ip6_soiikey in the kernel anyway?  I guess it is
from a time when address configuration was done in the kernel.
Could slaacd(8) just read /etc/soii.key?

> For IPV6CTL_MRTSTATS, IPV6CTL_MRTMIF and IPV6CTL_MRTMFC cases netlock
> could be relaxed to share netlock, but with separate diffs.
> 
> ok?
> 
> Index: sys/netinet6/in6_proto.c
> ===
> RCS file: /cvs/src/sys/netinet6/in6_proto.c,v
> retrieving revision 1.112
> diff -u -p -r1.112 in6_proto.c
> --- sys/netinet6/in6_proto.c  23 Nov 2022 14:48:28 -  1.112
> +++ sys/netinet6/in6_proto.c  17 May 2023 09:37:05 -
> @@ -128,6 +128,7 @@ const struct protosw inet6sw[] = {
>  {
>.pr_domain = &inet6domain,
>.pr_protocol   = IPPROTO_IPV6,
> +  .pr_flags  = PR_MPSYSCTL,
>.pr_init   = ip6_init,
>.pr_slowtimo   = frag6_slowtimo,
>.pr_sysctl = ip6_sysctl
> Index: sys/netinet6/ip6_input.c
> ===
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.254
> diff -u -p -r1.254 ip6_input.c
> --- sys/netinet6/ip6_input.c  21 Aug 2022 14:15:55 -  1.254
> +++ sys/netinet6/ip6_input.c  17 May 2023 09:37:05 -
> @@ -118,6 +118,7 @@ struct niqueue ip6intrq = NIQUEUE_INITIA
>  struct cpumem *ip6counters;
>  
>  uint8_t ip6_soiikey[IP6_SOIIKEY_LEN];
> +struct rwlock ip6_soiikey_lock = RWLOCK_INITIALIZER("soiikeylk");
>  
>  int ip6_ours(struct mbuf **, int *, int, int);
>  int ip6_check_rh0hdr(struct mbuf *, int *);
> @@ -1477,17 +1478,16 @@ ip6_sysctl_ip6stat(void *oldp, size_t *o
>  int
>  ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
>  {
> - uint8_t oldkey[IP6_SOIIKEY_LEN];
>   int error;
>  
>   error = suser(curproc);
>   if (error != 0)
>   return (error);
>  
> - memcpy(oldkey, ip6_soiikey, sizeof(oldkey));
> -
> + rw_enter_write(&ip6_soiikey_lock);
>   error = sysctl_struct(oldp, oldlenp, newp, newlen, ip6_soiikey,
>   sizeof(ip6_soiikey));
> + rw_exit_write(&ip6_soiikey_lock);
>  
>   return (error);
>  }



Unlock ip6_sysctl()

2023-05-17 Thread Vitaliy Makkoveev
Introduce `ip6_soiikey_lock' rwlock(9) to protect `ip6_soiikey'. It
accessed only by ip6_sysctl_soiikey() and ip6_sysctl() is the only
ip6_sysctl_soiikey() caller so context switch is allowed here. Also
remove unused `oldkey' from ip6_sysctl_soiikey().

For IPV6CTL_MRTSTATS, IPV6CTL_MRTMIF and IPV6CTL_MRTMFC cases netlock
could be relaxed to share netlock, but with separate diffs.

ok?

Index: sys/netinet6/in6_proto.c
===
RCS file: /cvs/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.112
diff -u -p -r1.112 in6_proto.c
--- sys/netinet6/in6_proto.c23 Nov 2022 14:48:28 -  1.112
+++ sys/netinet6/in6_proto.c17 May 2023 09:37:05 -
@@ -128,6 +128,7 @@ const struct protosw inet6sw[] = {
 {
   .pr_domain   = &inet6domain,
   .pr_protocol = IPPROTO_IPV6,
+  .pr_flags= PR_MPSYSCTL,
   .pr_init = ip6_init,
   .pr_slowtimo = frag6_slowtimo,
   .pr_sysctl   = ip6_sysctl
Index: sys/netinet6/ip6_input.c
===
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.254
diff -u -p -r1.254 ip6_input.c
--- sys/netinet6/ip6_input.c21 Aug 2022 14:15:55 -  1.254
+++ sys/netinet6/ip6_input.c17 May 2023 09:37:05 -
@@ -118,6 +118,7 @@ struct niqueue ip6intrq = NIQUEUE_INITIA
 struct cpumem *ip6counters;
 
 uint8_t ip6_soiikey[IP6_SOIIKEY_LEN];
+struct rwlock ip6_soiikey_lock = RWLOCK_INITIALIZER("soiikeylk");
 
 int ip6_ours(struct mbuf **, int *, int, int);
 int ip6_check_rh0hdr(struct mbuf *, int *);
@@ -1477,17 +1478,16 @@ ip6_sysctl_ip6stat(void *oldp, size_t *o
 int
 ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
 {
-   uint8_t oldkey[IP6_SOIIKEY_LEN];
int error;
 
error = suser(curproc);
if (error != 0)
return (error);
 
-   memcpy(oldkey, ip6_soiikey, sizeof(oldkey));
-
+   rw_enter_write(&ip6_soiikey_lock);
error = sysctl_struct(oldp, oldlenp, newp, newlen, ip6_soiikey,
sizeof(ip6_soiikey));
+   rw_exit_write(&ip6_soiikey_lock);
 
return (error);
 }