Page MenuHomeFreeBSD

jail: Properly restrict the child jail's IPv[46] addresses
ClosedPublic

Authored by zlei on Dec 25 2022, 6:05 PM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Apr 24, 1:25 PM
Unknown Object (File)
Mar 19 2024, 3:15 PM
Unknown Object (File)
Mar 19 2024, 3:07 PM
Unknown Object (File)
Feb 7 2024, 8:14 AM
Unknown Object (File)
Dec 23 2023, 1:21 AM
Unknown Object (File)
Dec 11 2023, 10:45 PM
Unknown Object (File)
Nov 24 2023, 9:35 PM
Unknown Object (File)
Oct 1 2023, 4:05 AM
Subscribers

Details

Summary

Fixes: eb8dcdeac22d jail: network epoch protection for IP address lists

Test Plan

Run the following script:

#!/bin/sh

ifconfig lo0 inet 172.16.0.1/32 alias
ifconfig lo0 inet 172.16.0.2/32 alias
ifconfig lo0 inet 172.16.0.3/32 alias
ifconfig lo0 inet6 2001:db8::1/128 alias
ifconfig lo0 inet6 2001:db8::2/128 alias
ifconfig lo0 inet6 2001:db8::3/128 alias

jail -c name=parent host.hostname=parent path=/ persist children.max=1 ip4.addr=172.16.0.1 ip4.addr=172.16.0.2 ip6.addr=2001:db8::1 ip6.addr=2001:db8::2
jexec parent /bin/sh -s stdin << EOF
  jail -c name=c1 host.hostname=c1 path=/ persist ip4=inherit ip6=inherit
  sleep 1
  jls -j c1
  jexec c1 ifconfig lo0
EOF

sleep 1

jail -m name=parent ip4.addr=172.16.0.3 ip4.addr=172.16.0.1 ip6.addr=2001:db8::3 ip6.addr=2001:db8::1

sleep 1

echo "After modifying parent jail..."
jls -j parent.c1
jexec parent.c1 ifconfig lo0

Then verify the output:

   JID  IP Address      Hostname                      Path
     8  172.16.0.1      c1                            /
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
	options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
	inet6 2001:db8::1 prefixlen 128
	inet6 2001:db8::2 prefixlen 128
	inet 172.16.0.1 netmask 0xffffffff
	inet 172.16.0.2 netmask 0xffffffff
	groups: lo
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
After modifying parent jail...
   JID  IP Address      Hostname                      Path
     8  172.16.0.3      c1                            /
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
	options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
	inet6 2001:db8::1 prefixlen 128
	inet6 2001:db8::3 prefixlen 128
	inet 172.16.0.1 netmask 0xffffffff
	inet 172.16.0.3 netmask 0xffffffff
	groups: lo
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

Can also verify via DDB show prison

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

It would be nice to have the test script similar to the one in the testing section in our auto tests/.
Jails are complex beasts, so increasing the covered code scope would help detect regressions faster

sys/kern/kern_jail.c
817

Would be good to have a comment on why the first address is skipped.
Also: why ips is kept the same?

sys/kern/kern_jail.c
817

Would be good to have a comment on why the first address is skipped.

I think that is the same with my explains in D37871 .

Also: why ips is kept the same?

I'll dig into this.
The logic prior eb8dcdeac22da compares IP address count of prison with its parent, before copying the parent's IP address list

It would be nice to have the test script similar to the one in the testing section in our auto tests/.
Jails are complex beasts, so increasing the covered code scope would help detect regressions faster

I agree!

zlei marked an inline comment as done.Dec 28 2022, 5:17 PM
zlei added inline comments.
sys/kern/kern_jail.c
803

While test jail -m to modify parent jail, kernel panics when child jail does not have either IPv4 or IPv6 addresses.

So there're two bugs.

  1. IPv[46] addresses inherited from parent is wrong
  2. kernel panics when child jail does not have either IPv4 or IPv6 addresses.

@melifaro Shall I fix the second bug separately ?

817

Also: why ips is kept the same?

It works as intended.

Well if there's no user settings, i.e. ip4=inherit or ip6=inherit, then it is safe to copy all addresses from parent to child.

ips is set previously ips = (pr->pr_flags & pr_families[af].ip_flag) ? pip->ips : ppip->ips; .
If there's no user settings, ips == ppip->ips.

If new != NULL, then it is always allocated outside with the size of parent jail's ip adresses.

sys/kern/kern_jail.c
803

While test jail -m to modify parent jail, kernel panics when child jail does not have either IPv4 or IPv6 addresses.

So there're two bugs.

  1. IPv[46] addresses inherited from parent is wrong
  2. kernel panics when child jail does not have either IPv4 or IPv6 addresses.

@melifaro Shall I fix the second bug separately ?

On second thought, I think it deserves.

melifaro added inline comments.
sys/kern/kern_jail.c
803

Whatever is more convenient to you :-)

803

Re panics: was it always the case, or is this something recent?

817

Ack. Thank you for the clarification!

849

Wow. Thank you for catching this!

This revision is now accepted and ready to land.Dec 28 2022, 5:57 PM
zlei marked an inline comment as done.Dec 29 2022, 3:55 PM
zlei added inline comments.
sys/kern/kern_jail.c
803

Re panics: was it always the case, or is this something recent?

It is introduced by eb8dcdeac22d .

zlei marked 4 inline comments as done.Dec 30 2022, 4:21 AM
zlei added inline comments.
sys/kern/kern_jail.c
803

Re panics: was it always the case, or is this something recent?

It is introduced by eb8dcdeac22d .

See D37906 .

As suggested in D37871 maybe use PR_IP(pip, 0) instead of (pip + 1). That will clearly show that we are copying address arrays not the header structure. However, this is just suggestion, I don't insist on it.

I also second suggestion to combine D37871 and D37872 into one.

As suggested in D37871 maybe use PR_IP(pip, 0) instead of (pip + 1). That will clearly show that we are copying address arrays not the header structure. However, this is just suggestion, I don't insist on it.

This is same with D37871.

I also second suggestion to combine D37871 and D37872 into one.

@kp
I've never done that before. Is it a commit with two Differential Revision metadata fields?

In D37872#863490, @zlei wrote:

@kp
I've never done that before. Is it a commit with two Differential Revision metadata fields?

That's probably the best way, yes. I doubt that the server-side hooks will do the right thing though, so you may end up having to close one or both reviews manually.