View | Details | Raw Unified | Return to bug 181741 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/kern/uipc_sockbuf.c (-16 / +5 lines)
Lines 876-898 sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, Link Here
876
	return (retval);
876
	return (retval);
877
}
877
}
878
878
879
int
879
void
880
sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
880
sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
881
    struct mbuf *control)
881
    struct mbuf *control)
882
{
882
{
883
	struct mbuf *m, *n, *mlast;
883
	struct mbuf *m, *mlast;
884
	int space;
885
884
886
	SOCKBUF_LOCK_ASSERT(sb);
885
	SOCKBUF_LOCK_ASSERT(sb);
887
886
888
	if (control == 0)
889
		panic("sbappendcontrol_locked");
890
	space = m_length(control, &n) + m_length(m0, NULL);
891
892
	if (space > sbspace(sb))
893
		return (0);
894
	m_clrprotoflags(m0);
887
	m_clrprotoflags(m0);
895
	n->m_next = m0;			/* concatenate data to control */
888
	m_last(control)->m_next = m0;	/* concatenate data to control */
896
889
897
	SBLASTRECORDCHK(sb);
890
	SBLASTRECORDCHK(sb);
898
891
Lines 906-923 sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, Link Here
906
	SBLASTMBUFCHK(sb);
899
	SBLASTMBUFCHK(sb);
907
900
908
	SBLASTRECORDCHK(sb);
901
	SBLASTRECORDCHK(sb);
909
	return (1);
910
}
902
}
911
903
912
int
904
void
913
sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
905
sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
914
{
906
{
915
	int retval;
916
917
	SOCKBUF_LOCK(sb);
907
	SOCKBUF_LOCK(sb);
918
	retval = sbappendcontrol_locked(sb, m0, control);
908
	sbappendcontrol_locked(sb, m0, control);
919
	SOCKBUF_UNLOCK(sb);
909
	SOCKBUF_UNLOCK(sb);
920
	return (retval);
921
}
910
}
922
911
923
/*
912
/*
(-)b/sys/kern/uipc_socket.c (-1 / +19 lines)
Lines 1061-1066 sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, Link Here
1061
	KASSERT(so->so_proto->pr_flags & PR_ATOMIC,
1061
	KASSERT(so->so_proto->pr_flags & PR_ATOMIC,
1062
	    ("sosend_dgram: !PR_ATOMIC"));
1062
	    ("sosend_dgram: !PR_ATOMIC"));
1063
1063
1064
	if (so->so_proto->pr_usrreqs->pru_finalizecontrol &&
1065
	    (error = (*so->so_proto->pr_usrreqs->pru_finalizecontrol)(so,
1066
	        flags, &control, td)))
1067
		goto out;
1068
1064
	if (uio != NULL)
1069
	if (uio != NULL)
1065
		resid = uio->uio_resid;
1070
		resid = uio->uio_resid;
1066
	else
1071
	else
Lines 1125-1134 sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, Link Here
1125
	 * problem and need fixing.
1130
	 * problem and need fixing.
1126
	 */
1131
	 */
1127
	space = sbspace(&so->so_snd);
1132
	space = sbspace(&so->so_snd);
1133
	SOCKBUF_UNLOCK(&so->so_snd);
1128
	if (flags & MSG_OOB)
1134
	if (flags & MSG_OOB)
1129
		space += 1024;
1135
		space += 1024;
1136
	if (clen > space) {
1137
		error = EMSGSIZE;
1138
		goto out;
1139
	}
1130
	space -= clen;
1140
	space -= clen;
1131
	SOCKBUF_UNLOCK(&so->so_snd);
1132
	if (resid > space) {
1141
	if (resid > space) {
1133
		error = EMSGSIZE;
1142
		error = EMSGSIZE;
1134
		goto out;
1143
		goto out;
Lines 1222-1227 sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, Link Here
1222
	int clen = 0, error, dontroute;
1231
	int clen = 0, error, dontroute;
1223
	int atomic = sosendallatonce(so) || top;
1232
	int atomic = sosendallatonce(so) || top;
1224
1233
1234
	if (so->so_proto->pr_usrreqs->pru_finalizecontrol &&
1235
	    (error = (*so->so_proto->pr_usrreqs->pru_finalizecontrol)(so,
1236
	        flags, &control, td)))
1237
		goto out;
1238
1225
	if (uio != NULL)
1239
	if (uio != NULL)
1226
		resid = uio->uio_resid;
1240
		resid = uio->uio_resid;
1227
	else
1241
	else
Lines 1314-1319 restart: Link Here
1314
			goto restart;
1328
			goto restart;
1315
		}
1329
		}
1316
		SOCKBUF_UNLOCK(&so->so_snd);
1330
		SOCKBUF_UNLOCK(&so->so_snd);
1331
		if (clen > space) {
1332
			error = EMSGSIZE;
1333
			goto release;
1334
		}
1317
		space -= clen;
1335
		space -= clen;
1318
		do {
1336
		do {
1319
			if (uio == NULL) {
1337
			if (uio == NULL) {
(-)b/sys/kern/uipc_usrreq.c (-24 / +53 lines)
Lines 290-296 static int unp_internalize(struct mbuf **, struct thread *); Link Here
290
static void	unp_internalize_fp(struct file *);
290
static void	unp_internalize_fp(struct file *);
291
static int	unp_externalize(struct mbuf *, struct mbuf **, int);
291
static int	unp_externalize(struct mbuf *, struct mbuf **, int);
292
static int	unp_externalize_fp(struct file *);
292
static int	unp_externalize_fp(struct file *);
293
static struct mbuf	*unp_addsockcred(struct thread *, struct mbuf *);
293
static int	unp_addsockcred(struct mbuf **, struct thread *);
294
static void	unp_process_defers(void * __unused, int);
294
static void	unp_process_defers(void * __unused, int);
295
295
296
/*
296
/*
Lines 789-794 uipc_peeraddr(struct socket *so, struct sockaddr **nam) Link Here
789
}
789
}
790
790
791
static int
791
static int
792
uipc_finalizecontrol(struct socket *so, int flags, struct mbuf **pcontrol,
793
    struct thread *td)
794
{
795
	struct unpcb *unp, *unp2;
796
	int error = 0;
797
798
	unp = sotounpcb(so);
799
	KASSERT(unp != NULL, ("uipc_finalizecontrol: unp == NULL"));
800
801
	unp2 = unp->unp_conn;
802
803
	if (*pcontrol != NULL && (error = unp_internalize(pcontrol, td)))
804
		return (error);
805
806
	/* Lockless read, ignore when not connected. */
807
	if (unp2 && unp2->unp_flags & UNP_WANTCRED) {
808
		switch (so->so_type) {
809
		case SOCK_SEQPACKET:
810
		case SOCK_STREAM:
811
			/* Credentials are passed only once on streams */
812
			UNP_PCB_LOCK(unp2);
813
			if (unp2->unp_flags & UNP_WANTCRED) {
814
				unp2->unp_flags &= ~UNP_WANTCRED;
815
				error = unp_addsockcred(pcontrol, td);
816
			}
817
			UNP_PCB_UNLOCK(unp2);
818
			break;
819
		case SOCK_DGRAM:
820
			error = unp_addsockcred(pcontrol, td);
821
			break;
822
		}
823
	}
824
825
	return (error);
826
}
827
828
static int
792
uipc_rcvd(struct socket *so, int flags)
829
uipc_rcvd(struct socket *so, int flags)
793
{
830
{
794
	struct unpcb *unp, *unp2;
831
	struct unpcb *unp, *unp2;
Lines 857-864 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, Link Here
857
		error = EOPNOTSUPP;
894
		error = EOPNOTSUPP;
858
		goto release;
895
		goto release;
859
	}
896
	}
860
	if (control != NULL && (error = unp_internalize(&control, td)))
861
		goto release;
862
	if ((nam != NULL) || (flags & PRUS_EOF))
897
	if ((nam != NULL) || (flags & PRUS_EOF))
863
		UNP_LINK_WLOCK();
898
		UNP_LINK_WLOCK();
864
	else
899
	else
Lines 892-900 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, Link Here
892
			error = ENOTCONN;
927
			error = ENOTCONN;
893
			break;
928
			break;
894
		}
929
		}
895
		/* Lockless read. */
896
		if (unp2->unp_flags & UNP_WANTCRED)
897
			control = unp_addsockcred(td, control);
898
		UNP_PCB_LOCK(unp);
930
		UNP_PCB_LOCK(unp);
899
		if (unp->unp_addr != NULL)
931
		if (unp->unp_addr != NULL)
900
			from = (struct sockaddr *)unp->unp_addr;
932
			from = (struct sockaddr *)unp->unp_addr;
Lines 962-975 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, Link Here
962
		so2 = unp2->unp_socket;
994
		so2 = unp2->unp_socket;
963
		UNP_PCB_LOCK(unp2);
995
		UNP_PCB_LOCK(unp2);
964
		SOCKBUF_LOCK(&so2->so_rcv);
996
		SOCKBUF_LOCK(&so2->so_rcv);
965
		if (unp2->unp_flags & UNP_WANTCRED) {
966
			/*
967
			 * Credentials are passed only once on SOCK_STREAM
968
			 * and SOCK_SEQPACKET.
969
			 */
970
			unp2->unp_flags &= ~UNP_WANTCRED;
971
			control = unp_addsockcred(td, control);
972
		}
973
		/*
997
		/*
974
		 * Send to paired receive port, and then reduce send buffer
998
		 * Send to paired receive port, and then reduce send buffer
975
		 * hiwater marks to maintain backpressure.  Wake up readers.
999
		 * hiwater marks to maintain backpressure.  Wake up readers.
Lines 977-985 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, Link Here
977
		switch (so->so_type) {
1001
		switch (so->so_type) {
978
		case SOCK_STREAM:
1002
		case SOCK_STREAM:
979
			if (control != NULL) {
1003
			if (control != NULL) {
980
				if (sbappendcontrol_locked(&so2->so_rcv, m,
1004
				sbappendcontrol_locked(&so2->so_rcv, m,
981
				    control))
1005
				    control);
982
					control = NULL;
1006
				control = NULL;
983
			} else
1007
			} else
984
				sbappend_locked(&so2->so_rcv, m, flags);
1008
				sbappend_locked(&so2->so_rcv, m, flags);
985
			break;
1009
			break;
Lines 1000-1005 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, Link Here
1000
			break;
1024
			break;
1001
			}
1025
			}
1002
		}
1026
		}
1027
		m = NULL;
1003
1028
1004
		mbcnt = so2->so_rcv.sb_mbcnt;
1029
		mbcnt = so2->so_rcv.sb_mbcnt;
1005
		sbcc = sbavail(&so2->so_rcv);
1030
		sbcc = sbavail(&so2->so_rcv);
Lines 1020-1026 uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, Link Here
1020
			so->so_snd.sb_flags |= SB_STOP;
1045
			so->so_snd.sb_flags |= SB_STOP;
1021
		SOCKBUF_UNLOCK(&so->so_snd);
1046
		SOCKBUF_UNLOCK(&so->so_snd);
1022
		UNP_PCB_UNLOCK(unp2);
1047
		UNP_PCB_UNLOCK(unp2);
1023
		m = NULL;
1024
		break;
1048
		break;
1025
	}
1049
	}
1026
1050
Lines 1144-1149 static struct pr_usrreqs uipc_usrreqs_dgram = { Link Here
1144
	.pru_disconnect =	uipc_disconnect,
1168
	.pru_disconnect =	uipc_disconnect,
1145
	.pru_listen =		uipc_listen,
1169
	.pru_listen =		uipc_listen,
1146
	.pru_peeraddr =		uipc_peeraddr,
1170
	.pru_peeraddr =		uipc_peeraddr,
1171
	.pru_finalizecontrol =	uipc_finalizecontrol,
1147
	.pru_rcvd =		uipc_rcvd,
1172
	.pru_rcvd =		uipc_rcvd,
1148
	.pru_send =		uipc_send,
1173
	.pru_send =		uipc_send,
1149
	.pru_sense =		uipc_sense,
1174
	.pru_sense =		uipc_sense,
Lines 1166-1171 static struct pr_usrreqs uipc_usrreqs_seqpacket = { Link Here
1166
	.pru_disconnect =	uipc_disconnect,
1191
	.pru_disconnect =	uipc_disconnect,
1167
	.pru_listen =		uipc_listen,
1192
	.pru_listen =		uipc_listen,
1168
	.pru_peeraddr =		uipc_peeraddr,
1193
	.pru_peeraddr =		uipc_peeraddr,
1194
	.pru_finalizecontrol =	uipc_finalizecontrol,
1169
	.pru_rcvd =		uipc_rcvd,
1195
	.pru_rcvd =		uipc_rcvd,
1170
	.pru_send =		uipc_send,
1196
	.pru_send =		uipc_send,
1171
	.pru_sense =		uipc_sense,
1197
	.pru_sense =		uipc_sense,
Lines 1188-1193 static struct pr_usrreqs uipc_usrreqs_stream = { Link Here
1188
	.pru_disconnect =	uipc_disconnect,
1214
	.pru_disconnect =	uipc_disconnect,
1189
	.pru_listen =		uipc_listen,
1215
	.pru_listen =		uipc_listen,
1190
	.pru_peeraddr =		uipc_peeraddr,
1216
	.pru_peeraddr =		uipc_peeraddr,
1217
	.pru_finalizecontrol =	uipc_finalizecontrol,
1191
	.pru_rcvd =		uipc_rcvd,
1218
	.pru_rcvd =		uipc_rcvd,
1192
	.pru_send =		uipc_send,
1219
	.pru_send =		uipc_send,
1193
	.pru_ready =		uipc_ready,
1220
	.pru_ready =		uipc_ready,
Lines 1787-1793 unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) Link Here
1787
			    SCM_RIGHTS, SOL_SOCKET);
1814
			    SCM_RIGHTS, SOL_SOCKET);
1788
			if (*controlp == NULL) {
1815
			if (*controlp == NULL) {
1789
				FILEDESC_XUNLOCK(fdesc);
1816
				FILEDESC_XUNLOCK(fdesc);
1790
				error = E2BIG;
1817
				error = ENOBUFS;
1791
				unp_freerights(fdep, newfds);
1818
				unp_freerights(fdep, newfds);
1792
				goto next;
1819
				goto next;
1793
			}
1820
			}
Lines 1964-1970 unp_internalize(struct mbuf **controlp, struct thread *td) Link Here
1964
			    SCM_RIGHTS, SOL_SOCKET);
1991
			    SCM_RIGHTS, SOL_SOCKET);
1965
			if (*controlp == NULL) {
1992
			if (*controlp == NULL) {
1966
				FILEDESC_SUNLOCK(fdesc);
1993
				FILEDESC_SUNLOCK(fdesc);
1967
				error = E2BIG;
1994
				error = ENOBUFS;
1968
				goto out;
1995
				goto out;
1969
			}
1996
			}
1970
			fdp = data;
1997
			fdp = data;
Lines 2028-2036 out: Link Here
2028
	return (error);
2055
	return (error);
2029
}
2056
}
2030
2057
2031
static struct mbuf *
2058
static int
2032
unp_addsockcred(struct thread *td, struct mbuf *control)
2059
unp_addsockcred(struct mbuf **pcontrol, struct thread *td)
2033
{
2060
{
2061
	struct mbuf *control = *pcontrol;
2034
	struct mbuf *m, *n, *n_prev;
2062
	struct mbuf *m, *n, *n_prev;
2035
	struct sockcred *sc;
2063
	struct sockcred *sc;
2036
	const struct cmsghdr *cm;
2064
	const struct cmsghdr *cm;
Lines 2040-2046 unp_addsockcred(struct thread *td, struct mbuf *control) Link Here
2040
	ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX);
2068
	ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX);
2041
	m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET);
2069
	m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET);
2042
	if (m == NULL)
2070
	if (m == NULL)
2043
		return (control);
2071
		return (ENOBUFS);
2044
2072
2045
	sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *));
2073
	sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *));
2046
	sc->sc_uid = td->td_ucred->cr_ruid;
2074
	sc->sc_uid = td->td_ucred->cr_ruid;
Lines 2074-2080 unp_addsockcred(struct thread *td, struct mbuf *control) Link Here
2074
2102
2075
	/* Prepend it to the head. */
2103
	/* Prepend it to the head. */
2076
	m->m_next = control;
2104
	m->m_next = control;
2077
	return (m);
2105
	*pcontrol = m;
2106
	return (0);
2078
}
2107
}
2079
2108
2080
static struct unpcb *
2109
static struct unpcb *
(-)b/sys/sys/protosw.h (+2 lines)
Lines 200-205 struct pr_usrreqs { Link Here
200
	int	(*pru_listen)(struct socket *so, int backlog,
200
	int	(*pru_listen)(struct socket *so, int backlog,
201
		    struct thread *td);
201
		    struct thread *td);
202
	int	(*pru_peeraddr)(struct socket *so, struct sockaddr **nam);
202
	int	(*pru_peeraddr)(struct socket *so, struct sockaddr **nam);
203
	int	(*pru_finalizecontrol)(struct socket *so, int flags, struct mbuf **pcontrol,
204
		    struct thread *td);
203
	int	(*pru_rcvd)(struct socket *so, int flags);
205
	int	(*pru_rcvd)(struct socket *so, int flags);
204
	int	(*pru_rcvoob)(struct socket *so, struct mbuf *m, int flags);
206
	int	(*pru_rcvoob)(struct socket *so, struct mbuf *m, int flags);
205
	int	(*pru_send)(struct socket *so, int flags, struct mbuf *m,
207
	int	(*pru_send)(struct socket *so, int flags, struct mbuf *m,
(-)b/sys/sys/sockbuf.h (-4 / +2 lines)
Lines 146-154 int sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, Link Here
146
	    struct mbuf *m0, struct mbuf *control);
146
	    struct mbuf *m0, struct mbuf *control);
147
int	sbappendaddr_nospacecheck_locked(struct sockbuf *sb,
147
int	sbappendaddr_nospacecheck_locked(struct sockbuf *sb,
148
	    const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control);
148
	    const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control);
149
int	sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
149
void	sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
150
	    struct mbuf *control);
150
	    struct mbuf *control);
151
int	sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
151
void	sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
152
	    struct mbuf *control);
152
	    struct mbuf *control);
153
void	sbappendrecord(struct sockbuf *sb, struct mbuf *m0);
153
void	sbappendrecord(struct sockbuf *sb, struct mbuf *m0);
154
void	sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0);
154
void	sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0);
155
- 
156
--
157
sys/kern/uipc_socket.c | 43 +++++++++++++++++++++++++++++++------------
155
sys/kern/uipc_socket.c | 43 +++++++++++++++++++++++++++++++------------
158
sys/kern/uipc_usrreq.c | 10 ++++++++++
156
sys/kern/uipc_usrreq.c | 10 ++++++++++
159
2 files changed, 41 insertions(+), 12 deletions(-)
157
2 files changed, 41 insertions(+), 12 deletions(-)
(-)b/sys/kern/uipc_socket.c (-12 / +31 lines)
Lines 1049-1054 sodisconnect(struct socket *so) Link Here
1049
1049
1050
#define	SBLOCKWAIT(f)	(((f) & MSG_DONTWAIT) ? 0 : SBL_WAIT)
1050
#define	SBLOCKWAIT(f)	(((f) & MSG_DONTWAIT) ? 0 : SBL_WAIT)
1051
1051
1052
/*
1053
 * Like sbspace(&so->so_snd), but allow extra room for  MSG_OOB.
1054
 *
1055
 * It's not clear whether the magic 1024 number is sensible, but
1056
 * at least it's now in only one place.
1057
 */
1058
static inline int
1059
sosend_space(struct socket *so, int flags)
1060
{
1061
	long space;
1062
1063
	space = sbspace(&so->so_snd);
1064
	if (flags & MSG_OOB)
1065
		space += 1024;
1066
	return (space);
1067
}
1068
1052
int
1069
int
1053
sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio,
1070
sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio,
1054
    struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
1071
    struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
Lines 1086-1093 sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, Link Here
1086
	    (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0;
1103
	    (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0;
1087
	if (td != NULL)
1104
	if (td != NULL)
1088
		td->td_ru.ru_msgsnd++;
1105
		td->td_ru.ru_msgsnd++;
1106
	/*
1107
	 * NB: Original user supplied control message may have
1108
	 * fit and we may have made it too big when we finalized
1109
	 * it, which will have us return EMSGSIZE below.  This
1110
	 * seems rude, but it is at least functional: the user
1111
	 * can try sending smaller control values (mainly, fewer
1112
	 * fd's at a time, as those are the ones that expand to
1113
	 * twice their size on I32LP64 systems).
1114
	 */
1089
	if (control != NULL)
1115
	if (control != NULL)
1090
		clen = control->m_len;
1116
		clen = m_length(control, NULL);
1091
1117
1092
	SOCKBUF_LOCK(&so->so_snd);
1118
	SOCKBUF_LOCK(&so->so_snd);
1093
	if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
1119
	if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
Lines 1125-1138 sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, Link Here
1125
		}
1151
		}
1126
	}
1152
	}
1127
1153
1128
	/*
1154
	space = sosend_space(so, flags);
1129
	 * Do we need MSG_OOB support in SOCK_DGRAM?  Signs here may be a
1130
	 * problem and need fixing.
1131
	 */
1132
	space = sbspace(&so->so_snd);
1133
	SOCKBUF_UNLOCK(&so->so_snd);
1155
	SOCKBUF_UNLOCK(&so->so_snd);
1134
	if (flags & MSG_OOB)
1135
		space += 1024;
1136
	if (clen > space) {
1156
	if (clen > space) {
1137
		error = EMSGSIZE;
1157
		error = EMSGSIZE;
1138
		goto out;
1158
		goto out;
Lines 1261-1267 sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, Link Here
1261
	if (td != NULL)
1281
	if (td != NULL)
1262
		td->td_ru.ru_msgsnd++;
1282
		td->td_ru.ru_msgsnd++;
1263
	if (control != NULL)
1283
	if (control != NULL)
1264
		clen = control->m_len;
1284
		clen = m_length(control, NULL);
1265
1285
1266
	error = sblock(&so->so_snd, SBLOCKWAIT(flags));
1286
	error = sblock(&so->so_snd, SBLOCKWAIT(flags));
1267
	if (error)
1287
	if (error)
Lines 1305-1313 restart: Link Here
1305
				goto release;
1325
				goto release;
1306
			}
1326
			}
1307
		}
1327
		}
1308
		space = sbspace(&so->so_snd);
1328
		space = sosend_space(so, flags);
1309
		if (flags & MSG_OOB)
1329
		/* NB: control msg is implicitly atomic */
1310
			space += 1024;
1311
		if ((atomic && resid > so->so_snd.sb_hiwat) ||
1330
		if ((atomic && resid > so->so_snd.sb_hiwat) ||
1312
		    clen > so->so_snd.sb_hiwat) {
1331
		    clen > so->so_snd.sb_hiwat) {
1313
			SOCKBUF_UNLOCK(&so->so_snd);
1332
			SOCKBUF_UNLOCK(&so->so_snd);
(-)b/sys/kern/uipc_usrreq.c (-2 / +10 lines)
Lines 1902-1907 unp_init(void) Link Here
1902
	UNP_DEFERRED_LOCK_INIT();
1902
	UNP_DEFERRED_LOCK_INIT();
1903
}
1903
}
1904
1904
1905
/*
1906
 * Convert incoming control message from user-supplied format
1907
 * to internal form.
1908
 *
1909
 * Note that when we're called, *controlp is a single mbuf
1910
 * whose m_len is the length of the cmsg data structures
1911
 * that have not yet been internalized.  On return, *controlp
1912
 * is an mbuf chain whose individual mbufs are internalized;
1913
 * this chain may have a different length.
1914
 */
1905
static int
1915
static int
1906
unp_internalize(struct mbuf **controlp, struct thread *td)
1916
unp_internalize(struct mbuf **controlp, struct thread *td)
1907
{
1917
{
1908
- 
1909
--
1910
sys/kern/uipc_usrreq.c | 52 ++++++++++++++++++++++++++++++++------------------
1918
sys/kern/uipc_usrreq.c | 52 ++++++++++++++++++++++++++++++++------------------
1911
1 file changed, 33 insertions(+), 19 deletions(-)
1919
1 file changed, 33 insertions(+), 19 deletions(-)
(-)b/sys/kern/uipc_usrreq.c (-21 / +33 lines)
Lines 794-827 uipc_finalizecontrol(struct socket *so, int flags, struct mbuf **pcontrol, Link Here
794
{
794
{
795
	struct unpcb *unp, *unp2;
795
	struct unpcb *unp, *unp2;
796
	int error = 0;
796
	int error = 0;
797
	bool wantcred, oneshot;
797
798
798
	unp = sotounpcb(so);
799
	unp = sotounpcb(so);
799
	KASSERT(unp != NULL, ("uipc_finalizecontrol: unp == NULL"));
800
	KASSERT(unp != NULL, ("uipc_finalizecontrol: unp == NULL"));
800
801
801
	unp2 = unp->unp_conn;
802
803
	if (*pcontrol != NULL && (error = unp_internalize(pcontrol, td)))
802
	if (*pcontrol != NULL && (error = unp_internalize(pcontrol, td)))
804
		return (error);
803
		return (error);
805
804
806
	/* Lockless read, ignore when not connected. */
805
	UNP_LINK_RLOCK();
807
	if (unp2 && unp2->unp_flags & UNP_WANTCRED) {
806
	unp2 = unp->unp_conn;
808
		switch (so->so_type) {
807
	UNP_LINK_RUNLOCK();
809
		case SOCK_SEQPACKET:
808
810
		case SOCK_STREAM:
809
	/*
811
			/* Credentials are passed only once on streams */
810
	 * If not connected, we're done now (might be auto-connect
812
			UNP_PCB_LOCK(unp2);
811
	 * on send, leave everything to caller).  Otherwise, handle
813
			if (unp2->unp_flags & UNP_WANTCRED) {
812
	 * one-shot credentials on stream and seqpacket sockets here.
814
				unp2->unp_flags &= ~UNP_WANTCRED;
813
	 *
815
				error = unp_addsockcred(pcontrol, td);
814
	 * XXX If the send fails, we never get another chance.
816
			}
815
	 * We could restore UNP_WANTCRED if the unp_addsockcred()
817
			UNP_PCB_UNLOCK(unp2);
816
	 * call fails here but we can't handle the more likely
818
			break;
817
	 * entire-send-fails case.  Deferring clearing the flag
819
		case SOCK_DGRAM:
818
	 * is not a great solution either.  Perhaps best would be
820
			error = unp_addsockcred(pcontrol, td);
819
	 * to have an additional UNP_CREDS_SENT_SUCCESSFULLY flag
821
			break;
820
	 * and check that here.  For now, just leave it this way.
822
		}
821
	 */
822
	if (unp2 == NULL)
823
		return (0);
824
825
	oneshot = so->so_type == SOCK_SEQPACKET ||
826
	    so->so_type == SOCK_STREAM;
827
	if (oneshot) {
828
		UNP_PCB_LOCK(unp2);
829
		wantcred = (unp2->unp_flags & UNP_WANTCRED) != 0;
830
		unp2->unp_flags &= ~UNP_WANTCRED;
831
		UNP_PCB_UNLOCK(unp2);
832
	} else {
833
		wantcred = true;
823
	}
834
	}
824
835
836
	if (wantcred)
837
		error = unp_addsockcred(pcontrol, td);
838
825
	return (error);
839
	return (error);
826
}
840
}
827
841
828
- 
829
--
830
sys/kern/uipc_usrreq.c | 338 +++++++++++++++++++++++++++++++------------------
842
sys/kern/uipc_usrreq.c | 338 +++++++++++++++++++++++++++++++------------------
831
1 file changed, 212 insertions(+), 126 deletions(-)
843
1 file changed, 212 insertions(+), 126 deletions(-)
(-)b/sys/kern/uipc_usrreq.c (-127 / +212 lines)
Lines 1917-1922 unp_init(void) Link Here
1917
}
1917
}
1918
1918
1919
/*
1919
/*
1920
 * Arguments passed to internalizer/transformer (ix = internal xform).
1921
 * The transformation function may fill in a new ix_mbuf.
1922
 */
1923
struct internalize_transform_data {
1924
	socklen_t	ix_odatalen;	/* original data length in bytes */
1925
	socklen_t	ix_ndatalen;	/* new data length, or 0 */
1926
	void		*ix_odata;	/* original data */
1927
	void 		*ix_ndata;	/* new data area, or NULL */
1928
	struct mbuf	*ix_mbuf;	/* mbuf for new data */
1929
	struct thread	*ix_td;		/* calling thread */
1930
};
1931
1932
/*
1933
 * Internalizers.  If you provide a nonzero size, we pre-allocate
1934
 * the ix_mbuf and you get a nonzero ndatasize and non-NULL ndata.
1935
 */
1936
struct unp_scm_internalize_op {
1937
	socklen_t size;		/* predefined output size, or 0 */
1938
	int	(*func)(struct internalize_transform_data *);
1939
};
1940
1941
static int unp_internalize_creds(struct internalize_transform_data *);
1942
static int unp_internalize_fds(struct internalize_transform_data *);
1943
static int unp_internalize_timestamp(struct internalize_transform_data *);
1944
static int unp_internalize_bintime(struct internalize_transform_data *);
1945
1946
static struct unp_scm_internalize_op unp_internalize_ops[] = {
1947
	[SCM_CREDS] = { sizeof(struct cmsgcred), unp_internalize_creds },
1948
	[SCM_RIGHTS] = { 0, unp_internalize_fds },
1949
	[SCM_TIMESTAMP] = { sizeof(struct timeval), unp_internalize_timestamp },
1950
	[SCM_BINTIME] = { sizeof(struct bintime), unp_internalize_bintime },
1951
};
1952
1953
/*
1920
 * Convert incoming control message from user-supplied format
1954
 * Convert incoming control message from user-supplied format
1921
 * to internal form.
1955
 * to internal form.
1922
 *
1956
 *
Lines 1925-2084 unp_init(void) Link Here
1925
 * that have not yet been internalized.  On return, *controlp
1959
 * that have not yet been internalized.  On return, *controlp
1926
 * is an mbuf chain whose individual mbufs are internalized;
1960
 * is an mbuf chain whose individual mbufs are internalized;
1927
 * this chain may have a different length.
1961
 * this chain may have a different length.
1962
 *
1963
 * Caller will always m_freem(*controlp), even if we return error.
1928
 */
1964
 */
1929
static int
1965
static int
1930
unp_internalize(struct mbuf **controlp, struct thread *td)
1966
unp_internalize(struct mbuf **controlp, struct thread *td)
1931
{
1967
{
1932
	struct mbuf *control = *controlp;
1968
	struct unp_scm_internalize_op *op;
1933
	struct proc *p = td->td_proc;
1969
	struct internalize_transform_data ix;
1934
	struct filedesc *fdesc = p->p_fd;
1970
	struct cmsghdr *cm;
1935
	struct bintime *bt;
1971
	struct mbuf *control, *m;
1936
	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1972
	void *odata;
1937
	struct cmsgcred *cmcred;
1973
	int cmtype, error;
1938
	struct filedescent *fde, **fdep, *fdev;
1974
	socklen_t clen, size, odatalen;
1939
	struct file *fp;
1940
	struct timeval *tv;
1941
	int i, *fdp;
1942
	void *data;
1943
	socklen_t clen = control->m_len, datalen;
1944
	int error, oldfds;
1945
	u_int newlen;
1946
1975
1947
	UNP_LINK_UNLOCK_ASSERT();
1976
	UNP_LINK_UNLOCK_ASSERT();
1948
1977
1978
	ix.ix_td = td;		/* never changes, just passed through */
1979
1949
	error = 0;
1980
	error = 0;
1981
	control = *controlp;
1950
	*controlp = NULL;
1982
	*controlp = NULL;
1951
	while (cm != NULL) {
1983
	clen = control->m_len;
1952
		if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET
1984
	cm = mtod(control, struct cmsghdr *);
1953
		    || cm->cmsg_len > clen || cm->cmsg_len < sizeof(*cm)) {
1954
			error = EINVAL;
1955
			goto out;
1956
		}
1957
		data = CMSG_DATA(cm);
1958
		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1959
1985
1960
		switch (cm->cmsg_type) {
1986
	while (error == 0) {
1961
		/*
1987
		/*
1962
		 * Fill in credential information.
1988
		 * Verify current control message, and set up type
1989
		 * and old data pointer and size values.
1963
		 */
1990
		 */
1964
		case SCM_CREDS:
1991
		if (clen < sizeof(*cm) || cm->cmsg_level != SOL_SOCKET ||
1965
			*controlp = sbcreatecontrol(NULL, sizeof(*cmcred),
1992
		    cm->cmsg_len > clen || cm->cmsg_len < sizeof(*cm)) {
1966
			    SCM_CREDS, SOL_SOCKET);
1993
			error = EINVAL;
1967
			if (*controlp == NULL) {
1968
				error = ENOBUFS;
1969
				goto out;
1970
			}
1971
			cmcred = (struct cmsgcred *)
1972
			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
1973
			cmcred->cmcred_pid = p->p_pid;
1974
			cmcred->cmcred_uid = td->td_ucred->cr_ruid;
1975
			cmcred->cmcred_gid = td->td_ucred->cr_rgid;
1976
			cmcred->cmcred_euid = td->td_ucred->cr_uid;
1977
			cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups,
1978
			    CMGROUP_MAX);
1979
			for (i = 0; i < cmcred->cmcred_ngroups; i++)
1980
				cmcred->cmcred_groups[i] =
1981
				    td->td_ucred->cr_groups[i];
1982
			break;
1994
			break;
1995
		}
1983
1996
1984
		case SCM_RIGHTS:
1997
		cmtype = cm->cmsg_type;
1985
			oldfds = datalen / sizeof (int);
1998
		if (cmtype < 0 || cmtype >= nitems(unp_internalize_ops)) {
1986
			if (oldfds == 0)
1999
			error = EINVAL;
1987
				break;
1988
			/*
1989
			 * Check that all the FDs passed in refer to legal
1990
			 * files.  If not, reject the entire operation.
1991
			 */
1992
			fdp = data;
1993
			FILEDESC_SLOCK(fdesc);
1994
			for (i = 0; i < oldfds; i++, fdp++) {
1995
				fp = fget_locked(fdesc, *fdp);
1996
				if (fp == NULL) {
1997
					FILEDESC_SUNLOCK(fdesc);
1998
					error = EBADF;
1999
					goto out;
2000
				}
2001
				if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
2002
					FILEDESC_SUNLOCK(fdesc);
2003
					error = EOPNOTSUPP;
2004
					goto out;
2005
				}
2006
2007
			}
2008
2009
			/*
2010
			 * Now replace the integer FDs with pointers to the
2011
			 * file structure and capability rights.
2012
			 */
2013
			newlen = oldfds * sizeof(fdep[0]);
2014
			*controlp = sbcreatecontrol(NULL, newlen,
2015
			    SCM_RIGHTS, SOL_SOCKET);
2016
			if (*controlp == NULL) {
2017
				FILEDESC_SUNLOCK(fdesc);
2018
				error = ENOBUFS;
2019
				goto out;
2020
			}
2021
			fdp = data;
2022
			fdep = (struct filedescent **)
2023
			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
2024
			fdev = malloc(sizeof(*fdev) * oldfds, M_FILECAPS,
2025
			    M_WAITOK);
2026
			for (i = 0; i < oldfds; i++, fdev++, fdp++) {
2027
				fde = &fdesc->fd_ofiles[*fdp];
2028
				fdep[i] = fdev;
2029
				fdep[i]->fde_file = fde->fde_file;
2030
				filecaps_copy(&fde->fde_caps,
2031
				    &fdep[i]->fde_caps, true);
2032
				unp_internalize_fp(fdep[i]->fde_file);
2033
			}
2034
			FILEDESC_SUNLOCK(fdesc);
2035
			break;
2000
			break;
2036
2001
		}
2037
		case SCM_TIMESTAMP:
2002
		op = &unp_internalize_ops[cmtype];
2038
			*controlp = sbcreatecontrol(NULL, sizeof(*tv),
2003
		if (op->func == NULL) {
2039
			    SCM_TIMESTAMP, SOL_SOCKET);
2004
			error = EINVAL;
2040
			if (*controlp == NULL) {
2041
				error = ENOBUFS;
2042
				goto out;
2043
			}
2044
			tv = (struct timeval *)
2045
			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
2046
			microtime(tv);
2047
			break;
2005
			break;
2006
		}
2048
2007
2049
		case SCM_BINTIME:
2008
		odata = CMSG_DATA(cm);
2050
			*controlp = sbcreatecontrol(NULL, sizeof(*bt),
2009
		odatalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)odata;
2051
			    SCM_BINTIME, SOL_SOCKET);
2010
2052
			if (*controlp == NULL) {
2011
		ix.ix_odata = odata;
2012
		ix.ix_odatalen = odatalen;
2013
2014
		/*
2015
		 * If transform function gives us a fixed data
2016
		 * size, allocate new mbuf here, else leave it
2017
		 * to the function.
2018
		 */
2019
		if ((size = op->size) != 0) {
2020
			m = sbcreatecontrol(NULL, size, cmtype, SOL_SOCKET);
2021
			if (m == NULL) {
2053
				error = ENOBUFS;
2022
				error = ENOBUFS;
2054
				goto out;
2023
				break;
2055
			}
2024
			}
2056
			bt = (struct bintime *)
2025
			ix.ix_mbuf = m;
2057
			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
2026
			ix.ix_ndata = CMSG_DATA(mtod(m, struct cmsghdr *));
2058
			bintime(bt);
2027
			ix.ix_ndatalen = size;
2059
			break;
2028
		} else {
2060
2029
			ix.ix_mbuf = NULL;
2061
		default:
2030
			ix.ix_ndata = NULL;
2062
			error = EINVAL;
2031
			ix.ix_ndatalen = 0;
2063
			goto out;
2064
		}
2032
		}
2065
2033
2066
		controlp = &(*controlp)->m_next;
2034
		/*
2067
		if (CMSG_SPACE(datalen) < clen) {
2035
		 * Apply transform and append new mbuf (if any) to
2068
			clen -= CMSG_SPACE(datalen);
2036
		 * new control chain, even on error, so that it
2069
			cm = (struct cmsghdr *)
2037
		 * will get freed.
2070
			    ((caddr_t)cm + CMSG_SPACE(datalen));
2038
		 */
2071
		} else {
2039
		error = (*op->func)(&ix);
2072
			clen = 0;
2040
		if ((m = ix.ix_mbuf) != NULL) {
2073
			cm = NULL;
2041
			*controlp = m;
2042
			controlp = &m->m_next;
2074
		}
2043
		}
2044
2045
		/* Advance to next message. */
2046
		size = CMSG_SPACE(odatalen);
2047
		if (size >= clen)
2048
			break;
2049
		cm = (struct cmsghdr *)((caddr_t)cm + size);
2050
		clen -= size;
2075
	}
2051
	}
2076
2052
2077
out:
2078
	m_freem(control);
2053
	m_freem(control);
2079
	return (error);
2054
	return (error);
2080
}
2055
}
2081
2056
2057
/*
2058
 * Internalize file descriptors ("rights").
2059
 */
2060
static int
2061
unp_internalize_fds(struct internalize_transform_data *ix)
2062
{
2063
	struct proc *p = ix->ix_td->td_proc;
2064
	struct filedesc *fdesc = p->p_fd;
2065
	struct filedescent *fde, **fdep, *fdev;
2066
	struct file *fp;
2067
	struct mbuf *m;
2068
	int i, *fdp;
2069
	int oldfds;
2070
	u_int newlen;
2071
2072
	KASSERT(ix->ix_ndatalen == 0, ("%s: datalen", __func__));
2073
2074
	/* Round down: this is forgiving, if slightly wrong. */
2075
	oldfds = ix->ix_odatalen / sizeof (int);
2076
	if (oldfds == 0)
2077
		return (0);
2078
2079
	/*
2080
	 * Check that all the FDs passed in refer to legal
2081
	 * files.  If not, reject the entire operation.
2082
	 */
2083
	fdp = ix->ix_odata;
2084
	FILEDESC_SLOCK(fdesc);
2085
	for (i = 0; i < oldfds; i++, fdp++) {
2086
		fp = fget_locked(fdesc, *fdp);
2087
		if (fp == NULL) {
2088
			FILEDESC_SUNLOCK(fdesc);
2089
			return (EBADF);
2090
		}
2091
		if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
2092
			FILEDESC_SUNLOCK(fdesc);
2093
			return (EOPNOTSUPP);
2094
		}
2095
2096
	}
2097
2098
	/*
2099
	 * Now replace the integer FDs with pointers to the
2100
	 * file structure and capability rights.
2101
	 */
2102
	newlen = oldfds * sizeof(fdep[0]);
2103
	m = sbcreatecontrol(NULL, newlen, SCM_RIGHTS, SOL_SOCKET);
2104
	if (m == NULL) {
2105
		FILEDESC_SUNLOCK(fdesc);
2106
		return (ENOBUFS);
2107
	}
2108
2109
	fdp = ix->ix_odata;
2110
	fdep = (struct filedescent **)CMSG_DATA(mtod(m, struct cmsghdr *));
2111
	fdev = malloc(sizeof(*fdev) * oldfds, M_FILECAPS, M_WAITOK);
2112
	for (i = 0; i < oldfds; i++, fdev++, fdp++) {
2113
		fde = &fdesc->fd_ofiles[*fdp];
2114
		fdep[i] = fdev;
2115
		fdep[i]->fde_file = fde->fde_file;
2116
		filecaps_copy(&fde->fde_caps, &fdep[i]->fde_caps, true);
2117
		unp_internalize_fp(fdep[i]->fde_file);
2118
	}
2119
	FILEDESC_SUNLOCK(fdesc);
2120
2121
	ix->ix_mbuf = m;
2122
	return (0);
2123
}
2124
2125
static int
2126
unp_internalize_creds(struct internalize_transform_data *ix)
2127
{
2128
	struct cmsgcred *cmcred;
2129
	int i, ngroups;
2130
	struct thread *td = ix->ix_td;
2131
	struct ucred *cr = td->td_ucred;
2132
2133
	KASSERT(ix->ix_ndatalen == sizeof(*cmcred), ("%s: datalen", __func__));
2134
	cmcred = ix->ix_ndata;
2135
	cmcred->cmcred_pid = td->td_proc->p_pid;
2136
	cmcred->cmcred_uid = cr->cr_ruid;
2137
	cmcred->cmcred_gid = cr->cr_rgid;
2138
	cmcred->cmcred_euid = cr->cr_uid;
2139
	ngroups = MIN(cr->cr_ngroups, CMGROUP_MAX);
2140
	cmcred->cmcred_ngroups = ngroups;
2141
	for (i = 0; i < ngroups; i++)
2142
		cmcred->cmcred_groups[i] = cr->cr_groups[i];
2143
	return (0);
2144
}
2145
2146
static int
2147
unp_internalize_timestamp(struct internalize_transform_data *ix)
2148
{
2149
	struct timeval *tv;
2150
2151
	KASSERT(ix->ix_ndatalen == sizeof(*tv), ("%s: datalen", __func__));
2152
	tv = ix->ix_ndata;
2153
	microtime(tv);
2154
	return (0);
2155
}
2156
2157
static int
2158
unp_internalize_bintime(struct internalize_transform_data *ix)
2159
{
2160
	struct bintime *bt;
2161
2162
	KASSERT(ix->ix_ndatalen == sizeof(*bt), ("%s: datalen", __func__));
2163
	bt = ix->ix_ndata;
2164
	bintime(bt);
2165
	return (0);
2166
}
2167
2082
static int
2168
static int
2083
unp_addsockcred(struct mbuf **pcontrol, struct thread *td)
2169
unp_addsockcred(struct mbuf **pcontrol, struct thread *td)
2084
{
2170
{
2085
- 

Return to bug 181741