The SIOCDIFADDR{,_IN6} ioctls take an ifreq structure object, not an ifaliasreq/in_aliasreq/in6_aliasreq structure object, as their argument. As opposed to ifaliasreq/in_aliasreq/in6_aliasreq used by SIOCAIFADDR{,_IN6}, the ifreq/in6_ifreq structures used by the SIOCDIFADDR{,_IN6} ioctls do not include a separate field for a broadcast address and other values required to add an address to a network interface with SIOCAIFADDR{,_IN6}. Whilst this issue is not specific to CHERI-extended architectures, it was first observed on CheriBSD running on Arm Morello. The incorrect calls using the in6_aliasreq object result in CHERI capability violations. A pointer to the ifra_addr field in in6_aliasreq cast to the ifru_addr union member of in6_ifreq results in bounds being set to the union's larger size. Such bounds exceed the bounds of of in6_aliasreq object and the bounds-setting instruction clears a tag of the object's capability.
Details
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
Looks good to me, just needs slight tweaking of the commit message.
I'd be tempted to leave out the second paragraph explaining how CHERI objects to this because it's still wrong on non-CHERI hardware (even if it does just work) but I'll leave that up to you.
sys/net/if.c | ||
---|---|---|
1044 | It's not clear to me why we're removing the broadaddr assignment here. At the very least that needs to be explained in the commit message too. A little further digging leads me to believe it's because ifra_broadaddr is a separate field in ifaliasreq but in the union in ifreq. It's also not used in in_difaddr_ioctl(), so I think this is correct too, but I'd still like to see it explained in the commit message. |
I'd like to keep the note on how CHERI can identify such issues. However, I updated the commit message to clarify the issue is not specific to CHERI-extended architectures.
sys/net/if.c | ||
---|---|---|
1044 | I updated the commit message to explain SIOCDIFADDR does not require a broadcast address to remove an address from an interface. |