Re: rights(4) split? CAP_WRITE -> CAP_WRITE_DATA + CAP_WRITE_CTRL
Kyle Evans <[email protected]> Wed, 3 Jun 2026 18:48:52 -0500
| Newsgroups | gmane.os.freebsd.devel.hackers,gmane.os.freebsd.architechture |
|---|---|
| Message-ID | <[email protected]> |
On 6/3/26 15:45, Konstantin Belousov wrote: > On Wed, Jun 03, 2026 at 09:32:17AM -0500, Kyle Evans wrote: >> Sure, no objection- that was my first inclination, but I renamed it to COMPAT at the last minute to match the COMPAT_FREEBSD* nomenclature. If there aren't any complaints about the notion within the next week or so, I'll go ahead and hack something up. >> >> On 6/3/26 09:17, Mariusz Zaborski wrote: >>> Actually I would feel safer with CAP_WRITE_LEGACY. >>> >>> On Wed, 3 Jun 2026 at 16:15, Kyle Evans <[email protected] <mailto:[email protected]>> wrote: >>> >>> On 6/3/26 03:04, Mariusz Zaborski wrote: >>> > Hello, >>> > >>> > I think the idea of splitting CAP_WRITE into CAP_WRITE_DATA and CAP_WRITE_CTRL makes sense, especially for cases where a process should be able to exchange data but not transfer file descriptors. >>> > >>> > From my perspective, the biggest concern is the capability change itself. While source compatibility can largely be preserved by making CAP_WRITE an alias for CAP_WRITE_DATA | CAP_WRITE_CTRL, there is still some potential for compatibility issues with existing applications and binaries that rely on the current semantics of CAP_WRITE. >>> > >>> >>> My alternative proposal would be that we slice off two entirely new bits in index 1 and still make `CAP_WRITE` an alias, but rename the current assignment to `CAP_WRITE_COMPAT`. We don't have any precedent for it, but I'd then handle translation at the cap_rights_*(2) border and unset the new `CAP_WRITE` if `CAP_WRITE_COMPAT` is unset when limiting, and unset `CAP_WRITE_LEGACY` if *either* of the new `CAP_WRITE_*` rights are missing. >>> >>> I don't know how I feel about it, but I bet it would work. >>> >>> > Other than that, the use case seems reasonable, and being able to explicitly prohibit SCM_RIGHTS on a socketpair could be a useful hardening measure >>> > >>> > Thanks, >>> > Mariusz >>> > >>> > >>> > On Tue, 2 Jun 2026 at 20:19, Kyle Evans <[email protected] <mailto:[email protected]> <mailto:[email protected] <mailto:[email protected]>>> wrote: >>> > >>> > Hi, >>> > >>> > I'm looking at an application where it would be useful to be able to construct a socketpair(2) that can't be used to send fds over, out of an abundance of caution. The application in prison0 is effectively a broker between two jails that it hands each an end of the socketpair, then steps out of the way -- I don't see a reason to leave it capable of carrying SCM_RIGHTS. >>> > >>> > I'd like to propose splitting CAP_WRITE into CAP_WRITE_DATA and CAP_WRITE_CTRL, with CAP_WRITE being an alias for DATA|CTRL. The caveat is that I don't know if being able to revoke data but not control messages is really feasible or useful, off-hand. >>> > >>> > In any event, my plan would be to use the last bit available in rights idx 0 for the CTRL right, rename the current CAP_WRITE to CAP_WRITE_DATA, and create a new CAP_WRITE name for the two combined. There's some chance for breakage in applications that haven't been rebuilt with the new definition of CAP_WRITE, but I suspect most of them aren't attempting to send control messages. The in-kernel users of CAP_WRITE look like they could mostly be scoped down to CAP_WRITE_DATA specifically, though maybe that gets a little awkward in `flags_to_rights` mapping of O_WRONLY/O_RDWR. >>> > >>> > Thoughts? Terrible idea? > > We do not have much bits left in the caps. I would need a new bit for the > D57163 review. Using two more bits leave us without any free bit, as far > as I see. > I'm not a fan of how it's expressed, but index 1 seems to have a lot of unused bits still: /* Available bits for index 1. */ #define CAP_UNUSED1_22 CAPRIGHT(1, 0x0000000000800000ULL) /* ... */ #define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL) I probably would've spelled it as the full mask: #define CAP_UNUSED1 CAPRIGHT(1, 0x01ffffffff800000ULL) Mark circulated the notion of aliasing some bit for rights that are applied to specific file type, like CAP_PDWAIT/CAP_PDKILL and CAP_INOTIFY_* as examples. I don't really see a reason we couldn't, particularly for these types that aren't at risk of growing write(2) semantics. > There is some versioning mechanism for the cap vector, might be it could > be used.