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
|
.\" @(#)unix.4 8.1 (Berkeley) 6/9/93
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd August 3, 2020
|
.Dd November 2, 2020
|
||||||
.Dt UNIX 4
|
.Dt UNIX 4
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -201,7 +201,7 @@ which can be set with
|
|||||||
.Xr setsockopt 2
|
.Xr setsockopt 2
|
||||||
and tested with
|
and tested with
|
||||||
.Xr getsockopt 2 :
|
.Xr getsockopt 2 :
|
||||||
.Bl -tag -width ".Dv LOCAL_CONNWAIT"
|
.Bl -tag -width ".Dv LOCAL_CREDS_PERSISTENT"
|
||||||
.It Dv LOCAL_CREDS
|
.It Dv LOCAL_CREDS
|
||||||
This option may be enabled on
|
This option may be enabled on
|
||||||
.Dv SOCK_DGRAM ,
|
.Dv SOCK_DGRAM ,
|
||||||
@ -287,6 +287,19 @@ such as error messages.
|
|||||||
Therefore, a message accompanied by a particular
|
Therefore, a message accompanied by a particular
|
||||||
.Fa sc_euid
|
.Fa sc_euid
|
||||||
value should not be trusted as being from that user.
|
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
|
.It Dv LOCAL_CONNWAIT
|
||||||
Used with
|
Used with
|
||||||
.Dv SOCK_STREAM
|
.Dv SOCK_STREAM
|
||||||
|
@ -1040,7 +1040,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unp2->unp_flags & UNP_WANTCRED)
|
if (unp2->unp_flags & UNP_WANTCRED_MASK)
|
||||||
control = unp_addsockcred(td, control);
|
control = unp_addsockcred(td, control);
|
||||||
if (unp->unp_addr != NULL)
|
if (unp->unp_addr != NULL)
|
||||||
from = (struct sockaddr *)unp->unp_addr;
|
from = (struct sockaddr *)unp->unp_addr;
|
||||||
@ -1094,12 +1094,13 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SOCKBUF_LOCK(&so2->so_rcv);
|
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
|
* Credentials are passed only once on SOCK_STREAM and
|
||||||
* and SOCK_SEQPACKET.
|
* 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);
|
control = unp_addsockcred(td, control);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1405,7 +1406,13 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
|
|
||||||
case LOCAL_CREDS:
|
case LOCAL_CREDS:
|
||||||
/* Unlocked read. */
|
/* 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));
|
error = sooptcopyout(sopt, &optval, sizeof(optval));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1424,28 +1431,38 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
|
|||||||
case SOPT_SET:
|
case SOPT_SET:
|
||||||
switch (sopt->sopt_name) {
|
switch (sopt->sopt_name) {
|
||||||
case LOCAL_CREDS:
|
case LOCAL_CREDS:
|
||||||
|
case LOCAL_CREDS_PERSISTENT:
|
||||||
case LOCAL_CONNWAIT:
|
case LOCAL_CONNWAIT:
|
||||||
error = sooptcopyin(sopt, &optval, sizeof(optval),
|
error = sooptcopyin(sopt, &optval, sizeof(optval),
|
||||||
sizeof(optval));
|
sizeof(optval));
|
||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#define OPTSET(bit) do { \
|
#define OPTSET(bit, exclusive) do { \
|
||||||
UNP_PCB_LOCK(unp); \
|
UNP_PCB_LOCK(unp); \
|
||||||
if (optval) \
|
if (optval) { \
|
||||||
unp->unp_flags |= bit; \
|
if ((unp->unp_flags & (exclusive)) != 0) { \
|
||||||
else \
|
UNP_PCB_UNLOCK(unp); \
|
||||||
unp->unp_flags &= ~bit; \
|
error = EINVAL; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
unp->unp_flags |= (bit); \
|
||||||
|
} else \
|
||||||
|
unp->unp_flags &= ~(bit); \
|
||||||
UNP_PCB_UNLOCK(unp); \
|
UNP_PCB_UNLOCK(unp); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
switch (sopt->sopt_name) {
|
switch (sopt->sopt_name) {
|
||||||
case LOCAL_CREDS:
|
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;
|
break;
|
||||||
|
|
||||||
case LOCAL_CONNWAIT:
|
case LOCAL_CONNWAIT:
|
||||||
OPTSET(UNP_CONNWAIT);
|
OPTSET(UNP_CONNWAIT, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1651,8 +1668,7 @@ unp_copy_peercred(struct thread *td, struct unpcb *client_unp,
|
|||||||
memcpy(&server_unp->unp_peercred, &listen_unp->unp_peercred,
|
memcpy(&server_unp->unp_peercred, &listen_unp->unp_peercred,
|
||||||
sizeof(server_unp->unp_peercred));
|
sizeof(server_unp->unp_peercred));
|
||||||
server_unp->unp_flags |= UNP_HAVEPC;
|
server_unp->unp_flags |= UNP_HAVEPC;
|
||||||
if (listen_unp->unp_flags & UNP_WANTCRED)
|
client_unp->unp_flags |= (listen_unp->unp_flags & UNP_WANTCRED_MASK);
|
||||||
client_unp->unp_flags |= UNP_WANTCRED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2853,8 +2869,12 @@ db_print_unpflags(int unp_flags)
|
|||||||
db_printf("%sUNP_HAVEPC", comma ? ", " : "");
|
db_printf("%sUNP_HAVEPC", comma ? ", " : "");
|
||||||
comma = 1;
|
comma = 1;
|
||||||
}
|
}
|
||||||
if (unp_flags & UNP_WANTCRED) {
|
if (unp_flags & UNP_WANTCRED_ALWAYS) {
|
||||||
db_printf("%sUNP_WANTCRED", comma ? ", " : "");
|
db_printf("%sUNP_WANTCRED_ALWAYS", comma ? ", " : "");
|
||||||
|
comma = 1;
|
||||||
|
}
|
||||||
|
if (unp_flags & UNP_WANTCRED_ONESHOT) {
|
||||||
|
db_printf("%sUNP_WANTCRED_ONESHOT", comma ? ", " : "");
|
||||||
comma = 1;
|
comma = 1;
|
||||||
}
|
}
|
||||||
if (unp_flags & UNP_CONNWAIT) {
|
if (unp_flags & UNP_CONNWAIT) {
|
||||||
|
@ -67,6 +67,7 @@ struct sockaddr_un {
|
|||||||
/* Socket options. */
|
/* Socket options. */
|
||||||
#define LOCAL_PEERCRED 1 /* retrieve peer credentials */
|
#define LOCAL_PEERCRED 1 /* retrieve peer credentials */
|
||||||
#define LOCAL_CREDS 2 /* pass credentials to receiver */
|
#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 */
|
#define LOCAL_CONNWAIT 4 /* connects block until accepted */
|
||||||
|
|
||||||
/* Start of reserved space for third-party socket options. */
|
/* 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
|
* to determine whether the contents should be sent to the user or
|
||||||
* not.
|
* not.
|
||||||
*/
|
*/
|
||||||
#define UNP_HAVEPC 0x001
|
#define UNP_HAVEPC 0x001
|
||||||
#define UNP_WANTCRED 0x004 /* credentials wanted */
|
#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_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()
|
* These flags are used to handle non-atomicity in connect() and bind()
|
||||||
* operations on a socket: in particular, to avoid races between multiple
|
* operations on a socket: in particular, to avoid races between multiple
|
||||||
|
Loading…
Reference in New Issue
Block a user