unix(4): Add SOL_LOCAL:LOCAL_CREDS_PERSISTENT
This option is intended to be semantically identical to Linux's SOL_SOCKET:SO_PASSCRED. For now, it is mutually exclusive with the pre-existing sockopt SOL_LOCAL:LOCAL_CREDS. Reviewed by: markj (penultimate version) Differential Revision: https://reviews.freebsd.org/D27011
This commit is contained in:
parent
a98f03786e
commit
2de07e4096
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=367287
@ -28,7 +28,7 @@
|
||||
.\" @(#)unix.4 8.1 (Berkeley) 6/9/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 3, 2020
|
||||
.Dd November 2, 2020
|
||||
.Dt UNIX 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -201,7 +201,7 @@ which can be set with
|
||||
.Xr setsockopt 2
|
||||
and tested with
|
||||
.Xr getsockopt 2 :
|
||||
.Bl -tag -width ".Dv LOCAL_CONNWAIT"
|
||||
.Bl -tag -width ".Dv LOCAL_CREDS_PERSISTENT"
|
||||
.It Dv LOCAL_CREDS
|
||||
This option may be enabled on
|
||||
.Dv SOCK_DGRAM ,
|
||||
@ -287,6 +287,19 @@ such as error messages.
|
||||
Therefore, a message accompanied by a particular
|
||||
.Fa sc_euid
|
||||
value should not be trusted as being from that user.
|
||||
.It Dv LOCAL_CREDS_PERSISTENT
|
||||
This option is similar to
|
||||
.Dv LOCAL_CREDS ,
|
||||
except that socket credentials are passed on every read from a
|
||||
.Dv SOCK_STREAM
|
||||
or
|
||||
.Dv SOCK_SEQPACKET
|
||||
socket, instead of just the first read.
|
||||
The
|
||||
.Dv LOCAL_CREDS
|
||||
and
|
||||
.Dv LOCAL_CREDS_PERSISTENT
|
||||
options are mutually exclusive.
|
||||
.It Dv LOCAL_CONNWAIT
|
||||
Used with
|
||||
.Dv SOCK_STREAM
|
||||
|
@ -1040,7 +1040,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
break;
|
||||
}
|
||||
|
||||
if (unp2->unp_flags & UNP_WANTCRED)
|
||||
if (unp2->unp_flags & UNP_WANTCRED_MASK)
|
||||
control = unp_addsockcred(td, control);
|
||||
if (unp->unp_addr != NULL)
|
||||
from = (struct sockaddr *)unp->unp_addr;
|
||||
@ -1094,12 +1094,13 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
break;
|
||||
}
|
||||
SOCKBUF_LOCK(&so2->so_rcv);
|
||||
if (unp2->unp_flags & UNP_WANTCRED) {
|
||||
if (unp2->unp_flags & UNP_WANTCRED_MASK) {
|
||||
/*
|
||||
* Credentials are passed only once on SOCK_STREAM
|
||||
* and SOCK_SEQPACKET.
|
||||
* Credentials are passed only once on SOCK_STREAM and
|
||||
* SOCK_SEQPACKET (LOCAL_CREDS => WANTCRED_ONESHOT), or
|
||||
* forever (LOCAL_CREDS_PERSISTENT => WANTCRED_ALWAYS).
|
||||
*/
|
||||
unp2->unp_flags &= ~UNP_WANTCRED;
|
||||
unp2->unp_flags &= ~UNP_WANTCRED_ONESHOT;
|
||||
control = unp_addsockcred(td, control);
|
||||
}
|
||||
|
||||
@ -1405,7 +1406,13 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
|
||||
|
||||
case LOCAL_CREDS:
|
||||
/* Unlocked read. */
|
||||
optval = unp->unp_flags & UNP_WANTCRED ? 1 : 0;
|
||||
optval = unp->unp_flags & UNP_WANTCRED_ONESHOT ? 1 : 0;
|
||||
error = sooptcopyout(sopt, &optval, sizeof(optval));
|
||||
break;
|
||||
|
||||
case LOCAL_CREDS_PERSISTENT:
|
||||
/* Unlocked read. */
|
||||
optval = unp->unp_flags & UNP_WANTCRED_ALWAYS ? 1 : 0;
|
||||
error = sooptcopyout(sopt, &optval, sizeof(optval));
|
||||
break;
|
||||
|
||||
@ -1424,28 +1431,38 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
|
||||
case SOPT_SET:
|
||||
switch (sopt->sopt_name) {
|
||||
case LOCAL_CREDS:
|
||||
case LOCAL_CREDS_PERSISTENT:
|
||||
case LOCAL_CONNWAIT:
|
||||
error = sooptcopyin(sopt, &optval, sizeof(optval),
|
||||
sizeof(optval));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
#define OPTSET(bit) do { \
|
||||
#define OPTSET(bit, exclusive) do { \
|
||||
UNP_PCB_LOCK(unp); \
|
||||
if (optval) \
|
||||
unp->unp_flags |= bit; \
|
||||
else \
|
||||
unp->unp_flags &= ~bit; \
|
||||
if (optval) { \
|
||||
if ((unp->unp_flags & (exclusive)) != 0) { \
|
||||
UNP_PCB_UNLOCK(unp); \
|
||||
error = EINVAL; \
|
||||
break; \
|
||||
} \
|
||||
unp->unp_flags |= (bit); \
|
||||
} else \
|
||||
unp->unp_flags &= ~(bit); \
|
||||
UNP_PCB_UNLOCK(unp); \
|
||||
} while (0)
|
||||
|
||||
switch (sopt->sopt_name) {
|
||||
case LOCAL_CREDS:
|
||||
OPTSET(UNP_WANTCRED);
|
||||
OPTSET(UNP_WANTCRED_ONESHOT, UNP_WANTCRED_ALWAYS);
|
||||
break;
|
||||
|
||||
case LOCAL_CREDS_PERSISTENT:
|
||||
OPTSET(UNP_WANTCRED_ALWAYS, UNP_WANTCRED_ONESHOT);
|
||||
break;
|
||||
|
||||
case LOCAL_CONNWAIT:
|
||||
OPTSET(UNP_CONNWAIT);
|
||||
OPTSET(UNP_CONNWAIT, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1651,8 +1668,7 @@ unp_copy_peercred(struct thread *td, struct unpcb *client_unp,
|
||||
memcpy(&server_unp->unp_peercred, &listen_unp->unp_peercred,
|
||||
sizeof(server_unp->unp_peercred));
|
||||
server_unp->unp_flags |= UNP_HAVEPC;
|
||||
if (listen_unp->unp_flags & UNP_WANTCRED)
|
||||
client_unp->unp_flags |= UNP_WANTCRED;
|
||||
client_unp->unp_flags |= (listen_unp->unp_flags & UNP_WANTCRED_MASK);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2853,8 +2869,12 @@ db_print_unpflags(int unp_flags)
|
||||
db_printf("%sUNP_HAVEPC", comma ? ", " : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (unp_flags & UNP_WANTCRED) {
|
||||
db_printf("%sUNP_WANTCRED", comma ? ", " : "");
|
||||
if (unp_flags & UNP_WANTCRED_ALWAYS) {
|
||||
db_printf("%sUNP_WANTCRED_ALWAYS", comma ? ", " : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (unp_flags & UNP_WANTCRED_ONESHOT) {
|
||||
db_printf("%sUNP_WANTCRED_ONESHOT", comma ? ", " : "");
|
||||
comma = 1;
|
||||
}
|
||||
if (unp_flags & UNP_CONNWAIT) {
|
||||
|
@ -67,6 +67,7 @@ struct sockaddr_un {
|
||||
/* Socket options. */
|
||||
#define LOCAL_PEERCRED 1 /* retrieve peer credentials */
|
||||
#define LOCAL_CREDS 2 /* pass credentials to receiver */
|
||||
#define LOCAL_CREDS_PERSISTENT 3 /* pass credentials to receiver */
|
||||
#define LOCAL_CONNWAIT 4 /* connects block until accepted */
|
||||
|
||||
/* Start of reserved space for third-party socket options. */
|
||||
|
@ -107,10 +107,13 @@ struct unpcb {
|
||||
* to determine whether the contents should be sent to the user or
|
||||
* not.
|
||||
*/
|
||||
#define UNP_HAVEPC 0x001
|
||||
#define UNP_WANTCRED 0x004 /* credentials wanted */
|
||||
#define UNP_HAVEPC 0x001
|
||||
#define UNP_WANTCRED_ALWAYS 0x002 /* credentials wanted always */
|
||||
#define UNP_WANTCRED_ONESHOT 0x004 /* credentials wanted once */
|
||||
#define UNP_CONNWAIT 0x008 /* connect blocks until accepted */
|
||||
|
||||
#define UNP_WANTCRED_MASK (UNP_WANTCRED_ONESHOT | UNP_WANTCRED_ALWAYS)
|
||||
|
||||
/*
|
||||
* These flags are used to handle non-atomicity in connect() and bind()
|
||||
* operations on a socket: in particular, to avoid races between multiple
|
||||
|
Loading…
Reference in New Issue
Block a user