Module Name: src
Committed By: jdolecek
Date: Sat Feb 3 19:05:15 UTC 2024
Modified Files:
src/sys/kern: uipc_socket.c uipc_syscalls.c
src/sys/net: if_gre.c
src/sys/sys: socketvar.h
Log Message:
fix PIPE_SOCKETPAIR variant of pipe1() to apply correctly the 'flags'
passed when called via pipe2(2), fixing repeatable process hang during
compilation with 'gcc -pipe'
refactor fsocreate() to return the new socket and file pointers,
expect the caller to call fd_affix() once initialization is fully complete
use the new fsocreate() to replace the duplicate open-coded 'flags' handling
in makesocket() used for socketpair(2), and in the PIPE_SOCKETPAIR pipe1()
this also fixes lib/libc/sys/t_pipe2 pipe2_cloexec test to succeed
on PIPE_SOCKETPAIR kernel
fixes PR kern/55690
To generate a diff of this commit:
cvs rdiff -u -r1.307 -r1.308 src/sys/kern/uipc_socket.c
cvs rdiff -u -r1.210 -r1.211 src/sys/kern/uipc_syscalls.c
cvs rdiff -u -r1.184 -r1.185 src/sys/net/if_gre.c
cvs rdiff -u -r1.167 -r1.168 src/sys/sys/socketvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/uipc_socket.c
diff -u src/sys/kern/uipc_socket.c:1.307 src/sys/kern/uipc_socket.c:1.308
--- src/sys/kern/uipc_socket.c:1.307 Thu Nov 2 10:31:55 2023
+++ src/sys/kern/uipc_socket.c Sat Feb 3 19:05:14 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_socket.c,v 1.307 2023/11/02 10:31:55 martin Exp $ */
+/* $NetBSD: uipc_socket.c,v 1.308 2024/02/03 19:05:14 jdolecek Exp $ */
/*
* Copyright (c) 2002, 2007, 2008, 2009, 2023 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.307 2023/11/02 10:31:55 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.308 2024/02/03 19:05:14 jdolecek Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -568,44 +568,51 @@ socreate(int dom, struct socket **aso, i
/*
* fsocreate: create a socket and a file descriptor associated with it.
+ * Returns the allocated file structure in *fpp, but the descriptor
+ * is not visible yet for the process.
+ * Caller is responsible for calling fd_affix() for the returned *fpp once
+ * it's socket initialization is finished successfully, or fd_abort() if it's
+ * initialization fails.
+ *
*
- * => On success, write file descriptor to fdout and return zero.
- * => On failure, return non-zero; *fdout will be undefined.
+ * => On success, write file descriptor to *fdout and *fpp and return zero.
+ * => On failure, return non-zero; *fdout and *fpp will be undefined.
*/
int
-fsocreate(int domain, struct socket **sop, int type, int proto, int *fdout)
+fsocreate(int domain, struct socket **sop, int type, int proto, int *fdout,
+ file_t **fpp, struct socket *lockso)
{
lwp_t *l = curlwp;
int error, fd, flags;
struct socket *so;
- struct file *fp;
+ file_t *fp;
+
+ flags = type & SOCK_FLAGS_MASK;
+ type &= ~SOCK_FLAGS_MASK;
+ error = socreate(domain, &so, type, proto, l, lockso);
+ if (error) {
+ return error;
+ }
if ((error = fd_allocfile(&fp, &fd)) != 0) {
+ soclose(so);
return error;
}
- flags = type & SOCK_FLAGS_MASK;
fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
fp->f_flag = FREAD|FWRITE|((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
fp->f_type = DTYPE_SOCKET;
fp->f_ops = &socketops;
-
- type &= ~SOCK_FLAGS_MASK;
- error = socreate(domain, &so, type, proto, l, NULL);
- if (error) {
- fd_abort(curproc, fp, fd);
- return error;
- }
if (flags & SOCK_NONBLOCK) {
so->so_state |= SS_NBIO;
}
fp->f_socket = so;
- fd_affix(curproc, fp, fd);
if (sop != NULL) {
*sop = so;
}
*fdout = fd;
+ *fpp = fp;
return error;
}
Index: src/sys/kern/uipc_syscalls.c
diff -u src/sys/kern/uipc_syscalls.c:1.210 src/sys/kern/uipc_syscalls.c:1.211
--- src/sys/kern/uipc_syscalls.c:1.210 Thu Nov 2 10:31:55 2023
+++ src/sys/kern/uipc_syscalls.c Sat Feb 3 19:05:14 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_syscalls.c,v 1.210 2023/11/02 10:31:55 martin Exp $ */
+/* $NetBSD: uipc_syscalls.c,v 1.211 2024/02/03 19:05:14 jdolecek Exp $ */
/*-
* Copyright (c) 2008, 2009, 2023 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.210 2023/11/02 10:31:55 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.211 2024/02/03 19:05:14 jdolecek Exp $");
#ifdef _KERNEL_OPT
#include "opt_pipe.h"
@@ -111,10 +111,12 @@ sys___socket30(struct lwp *l, const stru
syscallarg(int) protocol;
} */
int fd, error;
+ file_t *fp;
error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
- SCARG(uap, protocol), &fd);
+ SCARG(uap, protocol), &fd, &fp, NULL);
if (error == 0) {
+ fd_affix(l->l_proc, fp, fd);
*retval = fd;
}
return error;
@@ -402,34 +404,6 @@ do_sys_connect(struct lwp *l, int fd, st
return error;
}
-static int
-makesocket(struct lwp *l, file_t **fp, int *fd, int flags, int type,
- int domain, int proto, struct socket *soo)
-{
- struct socket *so;
- int error;
-
- if ((error = socreate(domain, &so, type, proto, l, soo)) != 0) {
- return error;
- }
- if (flags & SOCK_NONBLOCK) {
- so->so_state |= SS_NBIO;
- }
-
- if ((error = fd_allocfile(fp, fd)) != 0) {
- soclose(so);
- return error;
- }
- fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
- (*fp)->f_flag = FREAD|FWRITE|
- ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
- ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
- (*fp)->f_type = DTYPE_SOCKET;
- (*fp)->f_ops = &socketops;
- (*fp)->f_socket = so;
- return 0;
-}
-
int
sys_socketpair(struct lwp *l, const struct sys_socketpair_args *uap,
register_t *retval)
@@ -449,16 +423,14 @@ sys_socketpair(struct lwp *l, const stru
int domain = SCARG(uap, domain);
int proto = SCARG(uap, protocol);
- error = makesocket(l, &fp1, &fd, flags, type, domain, proto, NULL);
+ error = fsocreate(domain, &so1, type|flags, proto, &fd, &fp1, NULL);
if (error)
return error;
- so1 = fp1->f_socket;
sv[0] = fd;
- error = makesocket(l, &fp2, &fd, flags, type, domain, proto, so1);
+ error = fsocreate(domain, &so2, type|flags, proto, &fd, &fp2, so1);
if (error)
goto out;
- so2 = fp2->f_socket;
sv[1] = fd;
solock(so1);
@@ -1297,33 +1269,36 @@ pipe1(struct lwp *l, int *fildes, int fl
{
file_t *rf, *wf;
struct socket *rso, *wso;
- int fd, error;
- proc_t *p;
+ int error, soflags = 0;
+ unsigned rfd, wfd;
+ proc_t *p = l->l_proc;
if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
return EINVAL;
- p = curproc;
- if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)
- return error;
- if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso)) != 0)
+ if (flags & O_CLOEXEC)
+ soflags |= SOCK_CLOEXEC;
+ if (flags & O_NONBLOCK)
+ soflags |= SOCK_NONBLOCK;
+ if (flags & O_NOSIGPIPE)
+ soflags |= SOCK_NOSIGPIPE;
+
+ error = fsocreate(AF_LOCAL, &rso, SOCK_STREAM|soflags, 0, &rfd, &rf,
+ NULL);
+ if (error)
goto free1;
+ error = fsocreate(AF_LOCAL, &wso, SOCK_STREAM|soflags, 0, &wfd, &wf,
+ rso);
+ if (error)
+ goto free2;
+
+ /* make sure the descriptors are uni-directional */
+ rf->f_type = rf->f_type & ~(FWRITE);
+ wf->f_type = wf->f_type & ~(FREAD);
+
/* remember this socket pair implements a pipe */
- wso->so_state |= SS_ISAPIPE;
rso->so_state |= SS_ISAPIPE;
- if ((error = fd_allocfile(&rf, &fd)) != 0)
- goto free2;
- fildes[0] = fd;
- rf->f_flag = FREAD | flags;
- rf->f_type = DTYPE_SOCKET;
- rf->f_ops = &socketops;
- rf->f_socket = rso;
- if ((error = fd_allocfile(&wf, &fd)) != 0)
- goto free3;
- wf->f_flag = FWRITE | flags;
- wf->f_type = DTYPE_SOCKET;
- wf->f_ops = &socketops;
- wf->f_socket = wso;
- fildes[1] = fd;
+ wso->so_state |= SS_ISAPIPE;
+
solock(wso);
/*
* Pipes must be readable when there is at least 1
@@ -1342,19 +1317,22 @@ pipe1(struct lwp *l, int *fildes, int fl
wso->so_snd.sb_lowat = PIPE_BUF;
error = unp_connect2(wso, rso);
sounlock(wso);
+
if (error != 0)
- goto free4;
- fd_affix(p, wf, fildes[1]);
- fd_affix(p, rf, fildes[0]);
+ goto free3;
+
+ fd_affix(p, wf, wfd);
+ fd_affix(p, rf, rfd);
+ fildes[0] = rfd;
+ fildes[1] = wfd;
return (0);
- free4:
- fd_abort(p, wf, fildes[1]);
free3:
- fd_abort(p, rf, fildes[0]);
- free2:
(void)soclose(wso);
- free1:
+ fd_abort(p, wf, wfd);
+ free2:
(void)soclose(rso);
+ fd_abort(p, rf, rfd);
+ free1:
return error;
}
#endif /* PIPE_SOCKETPAIR */
Index: src/sys/net/if_gre.c
diff -u src/sys/net/if_gre.c:1.184 src/sys/net/if_gre.c:1.185
--- src/sys/net/if_gre.c:1.184 Sat Sep 3 02:47:59 2022
+++ src/sys/net/if_gre.c Sat Feb 3 19:05:14 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: if_gre.c,v 1.184 2022/09/03 02:47:59 thorpej Exp $ */
+/* $NetBSD: if_gre.c,v 1.185 2024/02/03 19:05:14 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.184 2022/09/03 02:47:59 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.185 2024/02/03 19:05:14 jdolecek Exp $");
#ifdef _KERNEL_OPT
#include "opt_atalk.h"
@@ -435,6 +435,7 @@ static int
gre_socreate(struct gre_softc *sc, const struct gre_soparm *sp, int *fdout)
{
int fd, rc;
+ file_t *fp;
struct socket *so;
struct sockaddr_big sbig;
sa_family_t af;
@@ -443,15 +444,12 @@ gre_socreate(struct gre_softc *sc, const
GRE_DPRINTF(sc, "enter\n");
af = sp->sp_src.ss_family;
- rc = fsocreate(af, NULL, sp->sp_type, sp->sp_proto, &fd);
+ rc = fsocreate(af, &so, sp->sp_type, sp->sp_proto, &fd, &fp, NULL);
if (rc != 0) {
GRE_DPRINTF(sc, "fsocreate failed\n");
return rc;
}
- if ((rc = fd_getsock(fd, &so)) != 0)
- return rc;
-
memcpy(&sbig, &sp->sp_src, sizeof(sp->sp_src));
if ((rc = sobind(so, (struct sockaddr *)&sbig, curlwp)) != 0) {
GRE_DPRINTF(sc, "sobind failed\n");
@@ -484,10 +482,11 @@ gre_socreate(struct gre_softc *sc, const
rc = 0;
}
out:
- if (rc != 0)
- fd_close(fd);
- else {
- fd_putfile(fd);
+ if (rc != 0) {
+ soclose(so);
+ fd_abort(curproc, fp, fd);
+ } else {
+ fd_affix(curproc, fp, fd);
*fdout = fd;
}
Index: src/sys/sys/socketvar.h
diff -u src/sys/sys/socketvar.h:1.167 src/sys/sys/socketvar.h:1.168
--- src/sys/sys/socketvar.h:1.167 Thu Nov 2 10:31:55 2023
+++ src/sys/sys/socketvar.h Sat Feb 3 19:05:14 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: socketvar.h,v 1.167 2023/11/02 10:31:55 martin Exp $ */
+/* $NetBSD: socketvar.h,v 1.168 2024/02/03 19:05:14 jdolecek Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -306,7 +306,8 @@ int soconnect(struct socket *, struct so
int soconnect2(struct socket *, struct socket *);
int socreate(int, struct socket **, int, int, struct lwp *,
struct socket *);
-int fsocreate(int, struct socket **, int, int, int *);
+int fsocreate(int, struct socket **, int, int, int *, file_t **,
+ struct socket *);
int sodisconnect(struct socket *);
void sofree(struct socket *);
int sogetopt(struct socket *, struct sockopt *);