Re: Add IP address ioctl (SIOCAIFADDR) from jail is called with host credentials

From: Alexander Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 28 Jun 2023 21:59:16 UTC

On Wed, 28 Jun 2023, at 6:30 AM, Shivank Garg wrote:
> Hi Alexander,
> 
> Thanks for replying.
> I think it would mean struct prison info is lost, when it reaches ioctl code, Is there some way we can get jail id?
Yes, you should add the hook to the netlink handler.
> 
> Another question I have: prison_check_ip4 still relies on checking struct prison for flags and ip addr. 
> https://github.com/freebsd/freebsd-src/blob/6927176113ee775983952edb3c201fed6be318d3/sys/netinet/in_jail.c#L319
> How do we handle these cases?
I’ll take a look on the weekend. It may indeed be a problem with nested jails.
> 
>  It used to work for VNET jails inet calls sometime back when I wrote mac_ipacl: https://reviews.freebsd.org/D20967
> - MAC policy to limit jail privilege to set its IP address. We were planning to merge this code in 14.0. Is there something we can
> do regarding it?
Yep, sure! I’ll try to further decouple ioctl handler and the actual address modification code so the ioctl hook wont’t get called in the netlink handler.
> Thanks,
> Shivank
> 
> On Wed, 28 Jun 2023 at 04:05, Alexander Chernikov <melifaro@freebsd.org> wrote:
>> __
>> 
>> 
>> On Fri, 23 Jun 2023, at 10:27 AM, Alexander Chernikov wrote:
>>> 
>>> 
>>> On Fri, 23 Jun 2023, at 7:53 AM, Shivank Garg wrote:
>>>> Hi,
>>>> 
>>>> I want to check credentials of the thread setting the IP address with SIOCAIFADDR ioctl.
>>>> If the thread is jailed (jailed(td_ucred) == 1), I'm applying some checks on ip address.
>>>> 
>>>> My expectation was that (cred->cr_prison != &prison0) for an ifconfig call made by the jail.
>>> If you’re using -head, it’s a bit more complicated. ifconfig(8) uses rtnetlink(4) interfaces to communicate with the kernel. Privilege check is done in Netlink:  https://github.com/freebsd/freebsd-src/blob/764464af49688e74fd6d803df0404ca4726dd460/sys/netlink/route/iface.c#L1472 . After that, (as of now) netlink calls ioctl code from its own kernel thread, which may be the reason of the behavior you’re observing.
>> Apparently the previous message was not delivered everywhere.
>>>> However, it is showing me some weird behavior. Here are the logs for a tweaked kernel:
>>>> 
>>>> @@ -339,7 +343,7 @@ in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
>>>>                 return (EADDRNOTAVAIL);
>>>>         struct ucred *cred = (td != NULL) ? td->td_ucred : NULL;
>>>> -
>>>> +       printf("in_control jailed? %d jid %d prison_owns_vnet? %d\n",jailed(cred),cred->cr_prison->pr_id,prison_owns_vnet(cred));
>>>> 
>>>> # jexec 1 ifconfig epair0b inet 169.254.123.101/24 up
>>>> 
>>>> Dmesg logs:
>>>> *[256] in_control jailed? 0 jid 0 prison_owns_vnet? 1*
>>>> 
>>>> Cred value indicates host and jail is 0 but the PR_VNET flag is set.
>>>> 
>>>> Is this behavior expected? or something going wrong - what's the next debug step?
>>>> 
>>>> I greatly appreciate your help!
>>>> 
>>>> Thanks,
>>>> Shivank
>>> 
>>> /Alexander
>>> 
>> 
>> /Alexander

/Alexander