Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159168193
D57423.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D57423.diff
View Options
diff --git a/lib/libsys/getsockopt.2 b/lib/libsys/getsockopt.2
--- a/lib/libsys/getsockopt.2
+++ b/lib/libsys/getsockopt.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 21, 2026
+.Dd June 3, 2026
.Dt GETSOCKOPT 2
.Os
.Sh NAME
@@ -192,6 +192,7 @@
.It Dv SO_NO_OFFLOAD Ta "disables protocol offloads"
.It Dv SO_NO_DDP Ta "disables direct data placement offload"
.It Dv SO_SPLICE Ta "splice two sockets together"
+.It Dv SO_PASSRIGHTS Ta "enables passing of SCM_RIGHTS over unix(4) sockets"
.El
.Pp
.Dv SO_DEBUG
diff --git a/lib/libsys/send.2 b/lib/libsys/send.2
--- a/lib/libsys/send.2
+++ b/lib/libsys/send.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 27, 2020
+.Dd June 3, 2026
.Dt SEND 2
.Os
.Sh NAME
@@ -250,6 +250,15 @@
socket was jailed and the source
address specified in the IP header did not match the IP
address bound to the prison.
+.It Bq Er EPERM
+The
+.Fa msg
+contained an
+.Dv SCM_RIGHTS
+control message, and the receiving
+.Xr unix 4
+socket is configured to reject new
+.Dv SCM_RIGHTS .
.It Bq Er EPIPE
The socket is unable to send anymore data
.Dv ( SBS_CANTSENDMORE
@@ -265,7 +274,8 @@
.Xr select 2 ,
.Xr socket 2 ,
.Xr write 2 ,
-.Xr CMSG_DATA 3
+.Xr CMSG_DATA 3 ,
+.Xr unix 4
.Sh HISTORY
The
.Fn send
diff --git a/share/man/man4/unix.4 b/share/man/man4/unix.4
--- a/share/man/man4/unix.4
+++ b/share/man/man4/unix.4
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 31, 2024
+.Dd June 3, 2026
.Dt UNIX 4
.Os
.Sh NAME
@@ -163,9 +163,20 @@
is passed in the
.Xr recvmsg 2
call.
+.Pp
Descriptors that are awaiting delivery, or that are
purposely not received, are automatically closed by the system
when the destination socket is closed.
+The receiving socket can reject
+.Dv SCM_RIGHTS
+at the
+.Xr sendmsg 2
+call with the socket option
+.Dv SO_PASSRIGHTS ,
+which can be set with
+.Xr setsockopt 2
+and tested with
+.Xr getsockopt 2 .
.Pp
Credentials of the sending process can be transmitted explicitly using a
control message of type
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -303,9 +303,10 @@
static void unp_discard(struct file *);
static void unp_freerights(struct filedescent **, int);
static int unp_internalize(struct mbuf *, struct mchain *,
- struct thread *);
+ struct thread *, int *);
static void unp_internalize_fp(struct file *);
-static int unp_externalize(struct mbuf *, struct mbuf **, int);
+static int unp_externalize(const struct socket *, struct mbuf *,
+ struct mbuf **, int);
static int unp_externalize_fp(struct file *);
static void unp_addsockcred(struct thread *, struct mchain *, int);
static void unp_process_defers(void * __unused, int);
@@ -527,6 +528,7 @@
UNP_PCB_LOCK_INIT(unp);
unp->unp_socket = so;
so->so_pcb = unp;
+ so->so_options |= SO_PASSRIGHTS;
refcount_init(&unp->unp_refcount, 1);
unp->unp_mode = ACCESSPERMS;
@@ -1112,7 +1114,7 @@
struct mchain mc, cmc;
size_t resid, sent;
bool nonblock, eor, aio;
- int error;
+ int error, needsopts;
MPASS((uio0 != NULL && m == NULL) || (m != NULL && uio0 == NULL));
MPASS(m == NULL || c == NULL);
@@ -1128,9 +1130,11 @@
cmc = MCHAIN_INITIALIZER(&cmc);
sent = 0;
aio = false;
+ needsopts = 0;
if (m == NULL) {
- if (c != NULL && (error = unp_internalize(c, &cmc, td)))
+ if (c != NULL &&
+ (error = unp_internalize(c, &cmc, td, &needsopts)))
goto out;
/*
* This function may read more data from the uio than it would
@@ -1176,6 +1180,14 @@
if (__predict_false((error = uipc_lock_peer(so, &unp2)) != 0))
goto out3;
+ /* Check for SO_PASS* flags */
+ so2 = unp2->unp_socket;
+ if ((so2->so_options & needsopts) != needsopts) {
+ error = EPERM;
+ UNP_PCB_UNLOCK(unp2);
+ goto out3;
+ }
+
if (unp2->unp_flags & UNP_WANTCRED_MASK) {
/*
* Credentials are passed only once on SOCK_STREAM and
@@ -1193,7 +1205,6 @@
* observe the SBS_CANTRCVMORE and our sorele() will finalize peer's
* socket destruction.
*/
- so2 = unp2->unp_socket;
soref(so2);
UNP_PCB_UNLOCK(unp2);
sb = &so2->so_rcv;
@@ -1560,7 +1571,7 @@
* is fine that we need to perform pretty complex
* operation here to reconstruct the buffer.
*/
- error = unp_externalize(control, controlp, flags);
+ error = unp_externalize(so, control, controlp, flags);
control = m_free(control);
if (__predict_false(error && control != NULL)) {
struct mchain cmc;
@@ -1959,11 +1970,11 @@
struct mbuf *f;
u_int cc, ctl, mbcnt;
u_int dcc __diagused, dctl __diagused, dmbcnt __diagused;
- int error;
+ int error, needsopts;
MPASS((uio != NULL && m == NULL) || (m != NULL && uio == NULL));
- error = 0;
+ error = needsopts = 0;
f = NULL;
if (__predict_false(flags & MSG_OOB)) {
@@ -1983,7 +1994,8 @@
f = m_gethdr(M_WAITOK, MT_SONAME);
cc = m->m_pkthdr.len;
mbcnt = MSIZE + m->m_pkthdr.memlen;
- if (c != NULL && (error = unp_internalize(c, &cmc, td)))
+ if (c != NULL &&
+ (error = unp_internalize(c, &cmc, td, &needsopts)))
goto out;
} else {
struct mchain mc;
@@ -2049,6 +2061,13 @@
}
}
+ /* Check for SO_PASS* flags */
+ so2 = unp2->unp_socket;
+ if ((so2->so_options & needsopts) != needsopts) {
+ error = EPERM;
+ goto out4;
+ }
+
if (unp2->unp_flags & UNP_WANTCRED_MASK)
unp_addsockcred(td, &cmc, unp2->unp_flags);
if (unp->unp_addr != NULL)
@@ -2117,7 +2136,6 @@
* would accumulate counters from all connected buffers potentially
* having sb_ccc > sb_hiwat or sb_mbcnt > sb_mbmax.
*/
- so2 = unp2->unp_socket;
sb = (addr == NULL) ? &so->so_snd : &so2->so_rcv;
SOCK_RECVBUF_LOCK(so2);
if (uipc_dgram_sbspace(sb, cc + ctl, mbcnt)) {
@@ -2143,6 +2161,7 @@
}
}
+out4:
if (addr != NULL)
unp_disconnect(unp, unp2);
else
@@ -2345,7 +2364,7 @@
* without MT_DATA mbufs.
*/
while (m != NULL && m->m_type == MT_CONTROL) {
- error = unp_externalize(m, controlp, flags);
+ error = unp_externalize(so, m, controlp, flags);
m = m_free(m);
if (error != 0) {
SOCK_IO_RECV_UNLOCK(so);
@@ -3494,7 +3513,8 @@
}
static int
-unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
+unp_externalize(const struct socket *so, struct mbuf *control,
+ struct mbuf **controlp, int flags)
{
struct thread *td = curthread; /* XXX */
struct cmsghdr *cm = mtod(control, struct cmsghdr *);
@@ -3526,8 +3546,17 @@
goto next;
fdep = data;
- /* If we're not outputting the descriptors free them. */
- if (error || controlp == NULL) {
+ /*
+ * If we're not outputting the descriptors, free them.
+ *
+ * In the case of having revoked SCM_PASSRIGHTS, the
+ * receiver must have toggled it before trying to
+ * receive control messages- we'll take that as a signal
+ * that they didn't want these, but they raced against
+ * the sender trying to pass files anyways.
+ */
+ if (error || controlp == NULL ||
+ (so->so_options & SO_PASSRIGHTS) == 0) {
unp_freerights(fdep, newfds);
goto next;
}
@@ -3672,7 +3701,8 @@
}
static int
-unp_internalize(struct mbuf *control, struct mchain *mc, struct thread *td)
+unp_internalize(struct mbuf *control, struct mchain *mc, struct thread *td,
+ int *needsopts)
{
struct proc *p;
struct filedesc *fdesc;
@@ -3728,6 +3758,7 @@
break;
case SCM_RIGHTS:
+ *needsopts |= SO_PASSRIGHTS;
oldfds = datalen / sizeof (int);
if (oldfds == 0)
continue;
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -147,6 +147,7 @@
#define SO_NO_DDP 0x00008000 /* disable direct data placement */
#define SO_REUSEPORT_LB 0x00010000 /* reuse with load balancing */
#define SO_RERROR 0x00020000 /* keep track of receive errors */
+#define SO_PASSRIGHTS 0x00040000 /* unix(4) accepts SCM_RIGHTS */
/*
* Additional options, not kept in so_options.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jun 11, 9:07 PM (4 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33858980
Default Alt Text
D57423.diff (7 KB)
Attached To
Mode
D57423: unix: implement basic SO_PASSRIGHTS functionality
Attached
Detach File
Event Timeline
Log In to Comment