Remove the printf() stances added in commit d4cc791f3b ("sys/rpc: UNIX
auth: Fix OOB reads on too short message").
Even if it can be helpful to know why an authentication message is
rejected, printing explanatory messages on each request attempt is
a remote log filler that could be triggered by accident, and the generic
RPC code generally does not do that. These printf() calls should be
restored only after some limiting or configuration mechanism is devised.
MFC with: d4cc791f3b ("sys/rpc: UNIX auth: Fix OOB reads on too short message")
Sponsored by: The FreeBSD Foundation
xdr_authunix_parms() does not allocate any auxiliary memory, so we can
simply support XDR_FREE by just returning TRUE.
Although there are currently no callers passing XDR_FREE, this makes us
immune to such a change in a way that doesn't cost more but is more
constructive than a mere KASSERT().
Suggested by: rmacklem
MFC after: 2 days
Sponsored by: The FreeBSD Foundation
In the inline version (_svcauth_unix()), fix multiple possible OOB reads
when the credentials part of a request is too short to contain mandatory
fields or with respect to the hostname length or number of groups it
advertises. The previously existing check was arriving too late and
relied on possibly wrong data coming from earlier OOB reads.
While here, use 'uint32_t' as the length/size type, as it is more than
enough and removes the need for conversions, explicit or implicit.
While here, factor out setting 'stat' to AUTH_BADCRED and then jumping
to 'done' on error, through the new 'badcred' label. While here,
through comments, refer to what the non-inline version is doing
(xdr_authunix_parms() in 'authunix_prot.c') and the reasons.
Reviewed by: rmacklem
Fixes: dfdcada31e ("Add the new kernel-mode NFS Lock Manager.")
MFC after: 2 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D52964
Remove local defines from 'svc_auth_unix.c' and use the new limit
macros instead.
Reviewed by: rmacklem
MFC after: 2 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D52963
Consistently with the XDR_INLINE() variant of xdr_authunix_parms()
(_svcauth_unix() in 'svc_auth_unix.c'), reject messages with credentials
having a machine name length in excess of AUTH_SYS_MAX_HOSTNAME or more
than AUTH_SYS_MAX_GROUPS supplementary groups, which do not conform to
RFC 5531. This is done mainly because we cannot store excess groups
anyway, even if at odds with the robustness principle ("be liberal in
what you accept").
While here, make sure the current code is immune to AUTH_SYS_MAX_GROUPS
changing value (in future RFCs?) even if that seems improbable.
Reviewed by: rmacklem
Fixes: dfdcada31e ("Add the new kernel-mode NFS Lock Manager.")
MFC after: 2 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D52962
As, respectively, the maximum number of "supplementary" groups and the
maximum hostname size allowed in the credentials structure for AUTH_SYS
(aka, AUTH_UNIX).
Will be used in subsequent commits.
Reviewed by: rmacklem
MFC after: 2 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D52961
When the received authentication message had more than XU_NGROUPS, we
would write group IDs beyond the end of cr_groups[] in the 'struct
xucred' being filled (as 'ngroups_max' is always greater than
XU_NGROUPS).
For robustness, prevent various OOB accesses that would result from
a change of value of XU_NGROUPS or a 'struct xucred' with an invalid
'cr_ngroups' field, even if these cases are unlikely.
Reviewed by: rmacklem
Fixes: dfdcada31e ("Add the new kernel-mode NFS Lock Manager.")
MFC after: 2 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D52960
Following the earlier removal of keyserv, none of this functionality
works since it requires keyserv.
Remove the relevant symbols from libc's Symbol.map. Leave compatibility
symbols for existing applications, but since the functions don't work
without keyserv, stub them out to return an error.
Remove some private symbols that were only used by keyserv; these don't
get compatibility symbols.
Remove the documentation for the old functions.
Remove rpc.ypupdated since it requires DES authentication.
Reviewed by: manu, des, emaste
Differential Revision: https://reviews.freebsd.org/D50442
This was a weird brain fart. Long ago I used a directory
service called Hesiod, which was written by MIT. For some
inexplicable reason, I used that name instead of Heimdal.
This patch replaces the name with a Heimdal one.
Suggested by: bjk
Fixes: e3ac01e18e ("kgssapi: Fix the kgssapi so that it can use MIT Kerberos")
Without this patch, the kgssapi uses detailed knowledge
of the internal context structure for Heimdal (up to vers 1.5).
It also does four upcalls to the gssd daemon to establish
a server side RPCSEC_GSS context.
This patch adds support for three new upcalls:
gss_init_sec_context_lucid_v1()
gss_accept_sec_context_lucid_v1()
gss_supports_lucid()
These are used to determine if the gssd can do the upcalls
and uses them to avoid needing detailed Heimdal knowledge
if they are supported.
gss_init_sec_context_lucid_v1() and
gss_accept_sec_context_lucid_v1() return the information
needed to complete the RPCSEC_GSS context.
They use gss_krb5_export_lucid_sec_context() to acquire
the information from the libraries. (MIT Kerberos supports
this and I believe newer versions of Heimdal does, as well).
This avoids the need for detailed knowledge about MIT's
internals and replaces the 2 or 4 (initiator or acceptor) upcalls
with a single upcall to create the RPCSEC_GSS context.
The old Heimdal (up to 1.5) support is left intact, but should
be removed whenever Heimdal 1.5 is removed from /usr/src.
It also modifies the Makefile so that the gssd is only built
when MK_KERBEROS_SUPPORT != "no", since it is useless without
Kerberos.
Reviewed by: cy
Differeential Revision: https://reviews.freebsd.org/D51731
Differeential Revision: https://reviews.freebsd.org/D51733
Without this patch, the kgssapi uses detailed knowledge
of the internal context structure for Heimdal (up to vers 1.5).
It also does four upcalls to the gssd daemon to establish
a server side RPCSEC_GSS context.
This patch adds support for three new upcalls:
gss_init_sec_context_lucid_v1()
gss_accept_sec_context_lucid_v1()
gss_supports_lucid()
These are used to determine if the gssd can do the upcalls
and uses them to avoid needing detailed Heimdal knowledge
if they are supported.
gss_init_sec_context_lucid_v1() and
gss_accept_sec_context_lucid_v1() return the information
needed to complete the RPCSEC_GSS context.
They use gss_krb5_export_lucid_sec_context() to acquire
the information from the libraries. (MIT Kerberos supports
this and I believe newer versions of Heimdal does, as well).
This avoids the need for detailed knowledge about MIT's
internals and replaces the 2 or 4 (initiator or acceptor) upcalls
with a single upcall to create the RPCSEC_GSS context.
The old Heimdal (up to 1.5) support is left intact, but should
be removed whenever Heimdal 1.5 is removed from /usr/src.
It also modifies the Makefile so that the gssd is only built
when MK_KERBEROS_SUPPORT != "no", since it is useless without
Kerberos.
Reviewed by: cy
Differential Revision: https://reviews.freebsd.org/D51731
Differential Revision: https://reviews.freebsd.org/D51733
As of FreeBSD 15.0, crsetgroups() *only* sets supplementary groups,
while crsetgroups_and_egid() will do both using an array of the same
style that previous versions used for crsetgroups() -- i.e., the first
element is the egid, and the remainder are supplementary groups.
Unlike the previous iteration of crsetgroups(), crsetgroups_and_egid()
is less prone to misuse as the caller must provide a default egid to use
in case the array is empty. This is particularly useful for groups
being set from data provided by userland.
Reviewed by: olce
Suggested by: olce
Differential Revision: https://reviews.freebsd.org/D51647
This is the (mostly) kernel side of de-conflating cr_gid and the
supplemental groups. The pre-existing behavior for getgroups() and
setgroups() is retained to keep the user <-> kernel boundary
functionally the same while we audit use of these syscalls, but we can
remove a lot of the internal special-casing just by reorganizing ucred
like this.
struct xucred has been altered because the cr_gid macro becomes
problematic if ucred has a real cr_gid member but xucred does not. Most
notably, they both also have cr_groups[] members, so the definition
means that we could easily have situations where we end up using the
first supplemental group as the egid in some places. We really can't
change the ABI of xucred, so instead we alias the first member to the
`cr_gid` name and maintain the status quo.
This also fixes the Linux setgroups(2)/getgroups(2) implementation to
more cleanly preserve the group set, now that we don't need to special
case cr_groups[0].
__FreeBSD_version bumped for the `struct ucred` ABI break.
For relnotes: downstreams and out-of-tree modules absolutely must fix
any references to cr_groups[0] in their code. These are almost
exclusively incorrect in the new world, and cr_gid should be used
instead. There is a cr_gid macro available in earlier FreeBSD versions
that can be used to avoid having version-dependant conditionals to refer
to the effective group id. Surrounding code may need adjusted if it
peels off the first element of cr_groups and uses the others as the
supplemental groups, since the supplemental groups start at cr_groups[0]
now if &cr_groups[0] != &cr_gid.
Relnotes: yes (see last paragraph)
Co-authored-by: olce
Differential Revision: https://reviews.freebsd.org/D51489
A future change may split cr_gid out of cr_groups[0] so that there's a
cleaner separation between the supplemental groups and the effective
group. Do the mechanical conversion where we can, and drop some
comments where we need further work because some assumptions about
cr_gid == cr_groups[0] have been made.
This should not be a functional change, but downstreams and other
out-of-tree code are advised to investigate their usage of cr_groups
sooner rather than later, as a future change will render assumptions
about these two being equivalent harmful.
Reviewed by: asomers, kib, olce
Differential Revision: https://reviews.freebsd.org/D51153
When rpc_gss_init() calls gssd upcall functions like
gssd_import_name(), clnt_nl_call() gets calls.
clnt_nl_call() requires that the currect vnet be set up.
The calling sequence looks something like:
rpc_gss_init()->gssd_import_name()->gssd_import_name_1()->
clnt_call_private()->clnt_nl_call()
(The call to rpc_gss_init() can happen from various places,
such as nfs_getauth() and clnt_vc_call().)
rpc_gss_init() does not know what socket is being
used for NFS client->server RPCs and may be called
from various places when any VOP_xxx()->RPC call
is made. As such, the calling thread might be running
within a jail. However, the gssd upcalls for the NFS
client must always be done to the gssd running outside
of any jails.
This patch sets the CURVNET to vnet0 in rpc_gss_init()
to fix the problem, since that is the vnet that always
should be used.
This must somehow be changed if NFS mounts in vnet
jails is enabled.
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D51086
When a TLS handshake fails during a NFS-over-TLS
mount attempt, the socket was left around because
it needed to be dereferenced. The dereference was
not happening in clnt_vc_destroy() because ct_closeit
was not set to TRUE.
This patch moves the code that sets ct_closeit to TRUE
up to before the rpctls_connect() call, so that ct_closeit
is set to TRUE if it fails and clnt_vc_destroy() will then
dereference the socket.
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D51084
Commit 26ee059392 replaced soshutdown()
with soclose() for the case where the RPC TLS
daemon has not removed the socket from the RB
tree during an upcall.
It turns out that soshutdown() is needed for the
"else" case, which is the case that occurs when the
daemon is stuck in SSL_accept() or SSL_connect().
This patch adds a soshutdown() call to this else case,
which unsticks the daemon when the other end does
not do the actual TLS handshake. This can occur if
the daemon is not running at the other end.
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D51083
Fixes: 26ee059392 ("rpctls_impl.c: Fix handling of socket for daemon failure")
If the client side rpc.tlsclntd is not running when a
NFS-over-TLS connection attempt is made, the socket
is left open. This results in the rpc.tlsservd daemon on
the NFS server being stuck in SSL_accept() until the
daemon is restarted.
This patch fixes this by doing soclose() on the socket
for the cases where the daemon has not acquired the
socket.
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D50961
Switch to using sys/stdarg.h for va_list type and va_* builtins.
Make an attempt to insert the include in a sensible place. Where
style(9) was followed this is easy, where it was ignored, aim for the
first block of sys/*.h headers and don't get too fussy or try to fix
other style bugs.
Reviewed by: imp
Exp-run by: antoine (PR 286274)
Pull Request: https://github.com/freebsd/freebsd-src/pull/1595
Now that the family and group are completely private to netlink_generic.c,
provide a simple and robust KPI, that would require very simple guarantees
from both KPI and the module:
* Strings are used only for family and group registration, that return ID:
uint16_t genl_register_family(const char *name, ...
uint32_t genl_register_group(uint16_t family, const char *name, ...
* Once created families and groups are guaranteed to not disappear and
be addressable by their ID.
* All subsequent calls, including deregistration shall use ID.
Reviewed by: kp
Differential Revision: https://reviews.freebsd.org/D48845
RPC calls are filtered by the Netlink system itself, but the RPC replies
are not. With legitimate use the chance of a xid collision is zero, since
global clients use global atomically updated 32-bit counter for that.
However, a malicious jail may blindly inject replies guessing the xid,
where guessing is trivial. Protect against that checking the vnet, too.
A netlink RPC client should be global. The filtering of RPC calls is done
by the nl_send_group() that would distribute the call to all subscribers
in the curvnet of clnt_nl_call() context.
Fixes: a3a6dc24f3
Fixes: 42eec5201a
With all the recent changes we don't need extra argument that specifies
what exactly the syscalls does, neither we need a copyout-able pointer,
just a pointer sized integer.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48649
At normal NFS server runtime there is not much RPC traffic from kernel to
rpc.tlsservd. But as Rick rmacklem@ explained, the notion of multiple
workers exists to handle a situation when a server reboots and it has
several hundred or thousands of TLS/TCP connections from clients. Once it
comes back up, all the clients make TCP connections and do TLS handshakes.
So cleanup the remnants of the workers, that left after the conversion of
RPC over netlink(4) transport and restore desired parallelism with help of
pthread(3).
We are processing the TLS handshakes in separate threads, one per
handshake. Number of concurrent threads is capped by hw.ncpu / 2, but this
can be overriden with -N.
Differential Revision: https://reviews.freebsd.org/D48570
Now that the conversion of rpcsec_tls/client + rpc.tlsclntd(8) to the
netlink(4) socket as RPC transport started using kernel socket pointer as
a reliable cookie, we can shave off quite a lot of complexity. We will
utilize the same kernel-generated cookie in all RPCs. And the need for
the daemon generated cookie in the form of timestamp+sequence vanishes.
We also stop passing notion of 'process position' from userland to
kernel. The TLS handshake parallelism to be reimplemented in the daemon
without any awareness about that in the kernel.
This time bump the RPC version.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48566
Now that the conversion of rpcsec_tls/client + rpc.tlsclntd(8) to the
netlink(4) socket as RPC transport started using kernel socket pointer as
a reliable cookie, we can shave off quite a lot of complexity. We will
utilize the same kernel-generated cookie in all RPCs. And the need for
the daemon generated cookie in the form of timestamp+sequence vanishes.
In the clnt_vc.c we no longer need to store the userland cookie, but we
still need to observe the TLS life cycle of the client. We observe
RPCTLS_INHANDSHAKE state, that lives for a short time when the socket had
already been fetched by the daemon with the syscall, but the RPC call is
still waiting for the reply from daemon.
This time bump the RPC version.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48564
The server part just repeats what had been done to the client. We trust
the parallelism of clnt_nl and we pass socket cookie to the daemon, which
we then expect to see in the rpctls_syscall(RPCTLS_SYSC_SRVSOCKET) to find
the corresponding socket+xprt. We reuse the same database that is used
for clients.
Note 1: this will be optimized further in a separate commit. This one is
made intentionally minimal, to ease the review process.
Note 2: this change intentionally ignores aspect of multiple workers of
rpc.tlsservd(8). This also will be addressed in a future commit.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48561
In addition to using netlink(4) socket instead of unix(4) to pass
rpctlscd_* RPC commands to rpc.tlsclntd(8), the logic of passing file
descriptor is also changed. Since clnt_nl provides us all needed
parallelism and waits on individual RPC xids, we don't need to store
socket in a global variable and serialize all communication to the daemon.
Instead, we will augment rpctlscd_connect arguments with a cookie that is
basically a pointer to socket, that we keep for the daemon. While
sleeping on the request, we will store a database of all sockets
associated with rpctlscd_connect RPCs that we have sent to userland. The
daemon then will send us back the cookie in the
rpctls_syscall(RPCTLS_SYSC_CLSOCKET) argument and we will find and return
the socket for this upcall.
This will be optimized further in a separate commit, that will also touch
clnt_vc.c and other krpc files. This commit is intentionally made minimal,
so that it is easier to understand what changes with netlink(4) transport.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48559
At the moment the only kernel service that wants to register RPC binding
in the rpcbind(8) is kernel NLM.
Kernel counterpart of the previous commit.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48557
This shall be the official transport to connect kernel side RPC clients
to userland side RPC servers. All current kernel side clients that
hijack unix(4) sockets will be converted to it. Some implementation
details are available inside new clnt_nl.c.
The complementary RPC server over netlink(4) coming in next commit.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48549
Get it implemented for mbuf based XDR. Right now all existing consumers
use only mbuf based XDR. However, future changes will require appending
data stored in an mbuf to memory buffer based XDR.
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D48547
The files svc.h and clnt.h derive from the same files that live in
/usr/include, however there is nothing really shared between the kernel
and libc RPC implementations. The kernel side files are not installed and
there is no reason to pollute them with the old definititions.
The code was disabled since the initial bulk check-in from Isilon in 2008.
Its existence poisoned grep(1) results when one would try to learn what
are the actual RPC mechanisms that are used by the modern NFC client and
server.
This fixes several bugs where some 'struct ucred' in the kernel,
constructed from user input (via nmount(2)) or obtained from other
servers (e.g., gssd(8)), could have an unfilled 'cr_groups' field and
whose 'cr_groups[0]' (or 'cr_gid', which is an alias) was later
accessed, causing an uninitialized access giving random access rights.
Use crsetgroups_fallback() to enforce a fallback group when possible.
For NFS, the chosen fallback group is that of the NFS server in the
current VNET (NFSD_VNET(nfsrv_defaultgid)).
There does not seem to be any sensible fallback available in rpc code
(sys/rpc/svc_auth.c, svc_getcred()) on AUTH_UNIX (TLS or not), so just
fail credential retrieval there. Stock NSS sources, rpc.tlsservd(8) or
rpc.tlsclntd(8) provide non-empty group lists, so will not be impacted.
Discussed with: rmacklem (by mail)
Approved by: markj (mentor)
MFC after: 3 days
Differential Revision: https://reviews.freebsd.org/D46918
xdr_void() should have type xdrproc_t, make it so.
PR: 280514
Reviewed by: brooks, dim
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D47340
Commit a16ff32f04 added support to the kernel RPC to set
TCP_USE_DDP.
However, for the unusual case of a NFSv4.1/4.2 non-NULL callback,
the xp_socket field of SVCXPRT is NULL, since it uses the same
socket as the client->server connection.
This patch adds the check for this to avoid crashes.
This only affects NFSv4.1/4.2 mounts where either pNFS or
delegations are in use.
MFC after: 3 days