Lines 290-296
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 800-805
Link Here
|
800 |
} |
800 |
} |
801 |
|
801 |
|
802 |
static int |
802 |
static int |
|
|
803 |
uipc_finalizecontrol(struct socket *so, int flags, struct mbuf **pcontrol, |
804 |
struct thread *td) |
805 |
{ |
806 |
struct unpcb *unp, *unp2; |
807 |
int error = 0; |
808 |
bool wantcred, oneshot; |
809 |
|
810 |
unp = sotounpcb(so); |
811 |
KASSERT(unp != NULL, ("uipc_finalizecontrol: unp == NULL")); |
812 |
|
813 |
if (*pcontrol != NULL && (error = unp_internalize(pcontrol, td))) |
814 |
return (error); |
815 |
|
816 |
UNP_LINK_RLOCK(); |
817 |
unp2 = unp->unp_conn; |
818 |
UNP_LINK_RUNLOCK(); |
819 |
|
820 |
/* |
821 |
* If not connected, we're done now (might be auto-connect |
822 |
* on send, leave everything to caller). Otherwise, handle |
823 |
* one-shot credentials on stream and seqpacket sockets here. |
824 |
* |
825 |
* XXX If the send fails, we never get another chance. |
826 |
* We could restore UNP_WANTCRED if the unp_addsockcred() |
827 |
* call fails here but we can't handle the more likely |
828 |
* entire-send-fails case. Deferring clearing the flag |
829 |
* is not a great solution either. Perhaps best would be |
830 |
* to have an additional UNP_CREDS_SENT_SUCCESSFULLY flag |
831 |
* and check that here. For now, just leave it this way. |
832 |
*/ |
833 |
if (unp2 == NULL) |
834 |
return (0); |
835 |
|
836 |
oneshot = so->so_type == SOCK_SEQPACKET || |
837 |
so->so_type == SOCK_STREAM; |
838 |
if (oneshot) { |
839 |
UNP_PCB_LOCK(unp2); |
840 |
wantcred = (unp2->unp_flags & UNP_WANTCRED) != 0; |
841 |
unp2->unp_flags &= ~UNP_WANTCRED; |
842 |
UNP_PCB_UNLOCK(unp2); |
843 |
} else { |
844 |
wantcred = true; |
845 |
} |
846 |
|
847 |
if (wantcred) |
848 |
error = unp_addsockcred(pcontrol, td); |
849 |
|
850 |
return (error); |
851 |
} |
852 |
|
853 |
static int |
803 |
uipc_rcvd(struct socket *so, int flags) |
854 |
uipc_rcvd(struct socket *so, int flags) |
804 |
{ |
855 |
{ |
805 |
struct unpcb *unp, *unp2; |
856 |
struct unpcb *unp, *unp2; |
Lines 868-875
Link Here
|
868 |
error = EOPNOTSUPP; |
919 |
error = EOPNOTSUPP; |
869 |
goto release; |
920 |
goto release; |
870 |
} |
921 |
} |
871 |
if (control != NULL && (error = unp_internalize(&control, td))) |
|
|
872 |
goto release; |
873 |
if ((nam != NULL) || (flags & PRUS_EOF)) |
922 |
if ((nam != NULL) || (flags & PRUS_EOF)) |
874 |
UNP_LINK_WLOCK(); |
923 |
UNP_LINK_WLOCK(); |
875 |
else |
924 |
else |
Lines 903-911
Link Here
|
903 |
error = ENOTCONN; |
952 |
error = ENOTCONN; |
904 |
break; |
953 |
break; |
905 |
} |
954 |
} |
906 |
/* Lockless read. */ |
|
|
907 |
if (unp2->unp_flags & UNP_WANTCRED) |
908 |
control = unp_addsockcred(td, control); |
909 |
UNP_PCB_LOCK(unp); |
955 |
UNP_PCB_LOCK(unp); |
910 |
if (unp->unp_addr != NULL) |
956 |
if (unp->unp_addr != NULL) |
911 |
from = (struct sockaddr *)unp->unp_addr; |
957 |
from = (struct sockaddr *)unp->unp_addr; |
Lines 973-986
Link Here
|
973 |
so2 = unp2->unp_socket; |
1019 |
so2 = unp2->unp_socket; |
974 |
UNP_PCB_LOCK(unp2); |
1020 |
UNP_PCB_LOCK(unp2); |
975 |
SOCKBUF_LOCK(&so2->so_rcv); |
1021 |
SOCKBUF_LOCK(&so2->so_rcv); |
976 |
if (unp2->unp_flags & UNP_WANTCRED) { |
|
|
977 |
/* |
978 |
* Credentials are passed only once on SOCK_STREAM |
979 |
* and SOCK_SEQPACKET. |
980 |
*/ |
981 |
unp2->unp_flags &= ~UNP_WANTCRED; |
982 |
control = unp_addsockcred(td, control); |
983 |
} |
984 |
/* |
1022 |
/* |
985 |
* Send to paired receive port, and then reduce send buffer |
1023 |
* Send to paired receive port, and then reduce send buffer |
986 |
* hiwater marks to maintain backpressure. Wake up readers. |
1024 |
* hiwater marks to maintain backpressure. Wake up readers. |
Lines 988-996
Link Here
|
988 |
switch (so->so_type) { |
1026 |
switch (so->so_type) { |
989 |
case SOCK_STREAM: |
1027 |
case SOCK_STREAM: |
990 |
if (control != NULL) { |
1028 |
if (control != NULL) { |
991 |
if (sbappendcontrol_locked(&so2->so_rcv, m, |
1029 |
sbappendcontrol_locked(&so2->so_rcv, m, |
992 |
control)) |
1030 |
control); |
993 |
control = NULL; |
1031 |
control = NULL; |
994 |
} else |
1032 |
} else |
995 |
sbappend_locked(&so2->so_rcv, m, flags); |
1033 |
sbappend_locked(&so2->so_rcv, m, flags); |
996 |
break; |
1034 |
break; |
Lines 1011-1016
Link Here
|
1011 |
break; |
1049 |
break; |
1012 |
} |
1050 |
} |
1013 |
} |
1051 |
} |
|
|
1052 |
m = NULL; |
1014 |
|
1053 |
|
1015 |
mbcnt = so2->so_rcv.sb_mbcnt; |
1054 |
mbcnt = so2->so_rcv.sb_mbcnt; |
1016 |
sbcc = sbavail(&so2->so_rcv); |
1055 |
sbcc = sbavail(&so2->so_rcv); |
Lines 1031-1037
Link Here
|
1031 |
so->so_snd.sb_flags |= SB_STOP; |
1070 |
so->so_snd.sb_flags |= SB_STOP; |
1032 |
SOCKBUF_UNLOCK(&so->so_snd); |
1071 |
SOCKBUF_UNLOCK(&so->so_snd); |
1033 |
UNP_PCB_UNLOCK(unp2); |
1072 |
UNP_PCB_UNLOCK(unp2); |
1034 |
m = NULL; |
|
|
1035 |
break; |
1073 |
break; |
1036 |
} |
1074 |
} |
1037 |
|
1075 |
|
Lines 1164-1169
Link Here
|
1164 |
.pru_disconnect = uipc_disconnect, |
1202 |
.pru_disconnect = uipc_disconnect, |
1165 |
.pru_listen = uipc_listen, |
1203 |
.pru_listen = uipc_listen, |
1166 |
.pru_peeraddr = uipc_peeraddr, |
1204 |
.pru_peeraddr = uipc_peeraddr, |
|
|
1205 |
.pru_finalizecontrol = uipc_finalizecontrol, |
1167 |
.pru_rcvd = uipc_rcvd, |
1206 |
.pru_rcvd = uipc_rcvd, |
1168 |
.pru_send = uipc_send, |
1207 |
.pru_send = uipc_send, |
1169 |
.pru_sense = uipc_sense, |
1208 |
.pru_sense = uipc_sense, |
Lines 1186-1191
Link Here
|
1186 |
.pru_disconnect = uipc_disconnect, |
1225 |
.pru_disconnect = uipc_disconnect, |
1187 |
.pru_listen = uipc_listen, |
1226 |
.pru_listen = uipc_listen, |
1188 |
.pru_peeraddr = uipc_peeraddr, |
1227 |
.pru_peeraddr = uipc_peeraddr, |
|
|
1228 |
.pru_finalizecontrol = uipc_finalizecontrol, |
1189 |
.pru_rcvd = uipc_rcvd, |
1229 |
.pru_rcvd = uipc_rcvd, |
1190 |
.pru_send = uipc_send, |
1230 |
.pru_send = uipc_send, |
1191 |
.pru_sense = uipc_sense, |
1231 |
.pru_sense = uipc_sense, |
Lines 1208-1213
Link Here
|
1208 |
.pru_disconnect = uipc_disconnect, |
1248 |
.pru_disconnect = uipc_disconnect, |
1209 |
.pru_listen = uipc_listen, |
1249 |
.pru_listen = uipc_listen, |
1210 |
.pru_peeraddr = uipc_peeraddr, |
1250 |
.pru_peeraddr = uipc_peeraddr, |
|
|
1251 |
.pru_finalizecontrol = uipc_finalizecontrol, |
1211 |
.pru_rcvd = uipc_rcvd, |
1252 |
.pru_rcvd = uipc_rcvd, |
1212 |
.pru_send = uipc_send, |
1253 |
.pru_send = uipc_send, |
1213 |
.pru_ready = uipc_ready, |
1254 |
.pru_ready = uipc_ready, |
Lines 1808-1814
Link Here
|
1808 |
SCM_RIGHTS, SOL_SOCKET); |
1849 |
SCM_RIGHTS, SOL_SOCKET); |
1809 |
if (*controlp == NULL) { |
1850 |
if (*controlp == NULL) { |
1810 |
FILEDESC_XUNLOCK(fdesc); |
1851 |
FILEDESC_XUNLOCK(fdesc); |
1811 |
error = E2BIG; |
1852 |
error = ENOBUFS; |
1812 |
unp_freerights(fdep, newfds); |
1853 |
unp_freerights(fdep, newfds); |
1813 |
goto next; |
1854 |
goto next; |
1814 |
} |
1855 |
} |
Lines 1896-2057
Link Here
|
1896 |
UNP_DEFERRED_LOCK_INIT(); |
1937 |
UNP_DEFERRED_LOCK_INIT(); |
1897 |
} |
1938 |
} |
1898 |
|
1939 |
|
|
|
1940 |
/* |
1941 |
* Arguments passed to internalizer/transformer (ix = internal xform). |
1942 |
* The transformation function may fill in a new ix_mbuf. |
1943 |
*/ |
1944 |
struct internalize_transform_data { |
1945 |
socklen_t ix_odatalen; /* original data length in bytes */ |
1946 |
socklen_t ix_ndatalen; /* new data length, or 0 */ |
1947 |
void *ix_odata; /* original data */ |
1948 |
void *ix_ndata; /* new data area, or NULL */ |
1949 |
struct mbuf *ix_mbuf; /* mbuf for new data */ |
1950 |
struct thread *ix_td; /* calling thread */ |
1951 |
}; |
1952 |
|
1953 |
/* |
1954 |
* Internalizers. If you provide a nonzero size, we pre-allocate |
1955 |
* the ix_mbuf and you get a nonzero ndatasize and non-NULL ndata. |
1956 |
*/ |
1957 |
struct unp_scm_internalize_op { |
1958 |
socklen_t size; /* predefined output size, or 0 */ |
1959 |
int (*func)(struct internalize_transform_data *); |
1960 |
}; |
1961 |
|
1962 |
static int unp_internalize_creds(struct internalize_transform_data *); |
1963 |
static int unp_internalize_fds(struct internalize_transform_data *); |
1964 |
static int unp_internalize_timestamp(struct internalize_transform_data *); |
1965 |
static int unp_internalize_bintime(struct internalize_transform_data *); |
1966 |
|
1967 |
static struct unp_scm_internalize_op unp_internalize_ops[] = { |
1968 |
[SCM_CREDS] = { sizeof(struct cmsgcred), unp_internalize_creds }, |
1969 |
[SCM_RIGHTS] = { 0, unp_internalize_fds }, |
1970 |
[SCM_TIMESTAMP] = { sizeof(struct timeval), unp_internalize_timestamp }, |
1971 |
[SCM_BINTIME] = { sizeof(struct bintime), unp_internalize_bintime }, |
1972 |
}; |
1973 |
|
1974 |
/* |
1975 |
* Convert incoming control message from user-supplied format |
1976 |
* to internal form. |
1977 |
* |
1978 |
* Note that when we're called, *controlp is a single mbuf |
1979 |
* whose m_len is the length of the cmsg data structures |
1980 |
* that have not yet been internalized. On return, *controlp |
1981 |
* is an mbuf chain whose individual mbufs are internalized; |
1982 |
* this chain may have a different length. |
1983 |
* |
1984 |
* Caller will always m_freem(*controlp), even if we return error. |
1985 |
*/ |
1899 |
static int |
1986 |
static int |
1900 |
unp_internalize(struct mbuf **controlp, struct thread *td) |
1987 |
unp_internalize(struct mbuf **controlp, struct thread *td) |
1901 |
{ |
1988 |
{ |
1902 |
struct mbuf *control = *controlp; |
1989 |
struct unp_scm_internalize_op *op; |
1903 |
struct proc *p = td->td_proc; |
1990 |
struct internalize_transform_data ix; |
1904 |
struct filedesc *fdesc = p->p_fd; |
1991 |
struct cmsghdr *cm; |
1905 |
struct bintime *bt; |
1992 |
struct mbuf *control, *m; |
1906 |
struct cmsghdr *cm = mtod(control, struct cmsghdr *); |
1993 |
void *odata; |
1907 |
struct cmsgcred *cmcred; |
1994 |
int cmtype, error; |
1908 |
struct filedescent *fde, **fdep, *fdev; |
1995 |
socklen_t clen, size, odatalen; |
1909 |
struct file *fp; |
|
|
1910 |
struct timeval *tv; |
1911 |
int i, *fdp; |
1912 |
void *data; |
1913 |
socklen_t clen = control->m_len, datalen; |
1914 |
int error, oldfds; |
1915 |
u_int newlen; |
1916 |
|
1996 |
|
1917 |
UNP_LINK_UNLOCK_ASSERT(); |
1997 |
UNP_LINK_UNLOCK_ASSERT(); |
1918 |
|
1998 |
|
|
|
1999 |
ix.ix_td = td; /* never changes, just passed through */ |
2000 |
|
1919 |
error = 0; |
2001 |
error = 0; |
|
|
2002 |
control = *controlp; |
1920 |
*controlp = NULL; |
2003 |
*controlp = NULL; |
1921 |
while (cm != NULL) { |
2004 |
clen = control->m_len; |
1922 |
if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET |
2005 |
cm = mtod(control, struct cmsghdr *); |
1923 |
|| cm->cmsg_len > clen || cm->cmsg_len < sizeof(*cm)) { |
|
|
1924 |
error = EINVAL; |
1925 |
goto out; |
1926 |
} |
1927 |
data = CMSG_DATA(cm); |
1928 |
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; |
1929 |
|
2006 |
|
1930 |
switch (cm->cmsg_type) { |
2007 |
while (error == 0) { |
1931 |
/* |
2008 |
/* |
1932 |
* Fill in credential information. |
2009 |
* Verify current control message, and set up type |
|
|
2010 |
* and old data pointer and size values. |
1933 |
*/ |
2011 |
*/ |
1934 |
case SCM_CREDS: |
2012 |
if (clen < sizeof(*cm) || cm->cmsg_level != SOL_SOCKET || |
1935 |
*controlp = sbcreatecontrol(NULL, sizeof(*cmcred), |
2013 |
cm->cmsg_len > clen || cm->cmsg_len < sizeof(*cm)) { |
1936 |
SCM_CREDS, SOL_SOCKET); |
2014 |
error = EINVAL; |
1937 |
if (*controlp == NULL) { |
|
|
1938 |
error = ENOBUFS; |
1939 |
goto out; |
1940 |
} |
1941 |
cmcred = (struct cmsgcred *) |
1942 |
CMSG_DATA(mtod(*controlp, struct cmsghdr *)); |
1943 |
cmcred->cmcred_pid = p->p_pid; |
1944 |
cmcred->cmcred_uid = td->td_ucred->cr_ruid; |
1945 |
cmcred->cmcred_gid = td->td_ucred->cr_rgid; |
1946 |
cmcred->cmcred_euid = td->td_ucred->cr_uid; |
1947 |
cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups, |
1948 |
CMGROUP_MAX); |
1949 |
for (i = 0; i < cmcred->cmcred_ngroups; i++) |
1950 |
cmcred->cmcred_groups[i] = |
1951 |
td->td_ucred->cr_groups[i]; |
1952 |
break; |
2015 |
break; |
|
|
2016 |
} |
1953 |
|
2017 |
|
1954 |
case SCM_RIGHTS: |
2018 |
cmtype = cm->cmsg_type; |
1955 |
oldfds = datalen / sizeof (int); |
2019 |
if (cmtype < 0 || cmtype >= nitems(unp_internalize_ops)) { |
1956 |
if (oldfds == 0) |
2020 |
error = EINVAL; |
1957 |
break; |
2021 |
break; |
1958 |
/* |
2022 |
} |
1959 |
* Check that all the FDs passed in refer to legal |
2023 |
op = &unp_internalize_ops[cmtype]; |
1960 |
* files. If not, reject the entire operation. |
2024 |
if (op->func == NULL) { |
1961 |
*/ |
2025 |
error = EINVAL; |
1962 |
fdp = data; |
2026 |
break; |
1963 |
FILEDESC_SLOCK(fdesc); |
2027 |
} |
1964 |
for (i = 0; i < oldfds; i++, fdp++) { |
|
|
1965 |
fp = fget_locked(fdesc, *fdp); |
1966 |
if (fp == NULL) { |
1967 |
FILEDESC_SUNLOCK(fdesc); |
1968 |
error = EBADF; |
1969 |
goto out; |
1970 |
} |
1971 |
if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) { |
1972 |
FILEDESC_SUNLOCK(fdesc); |
1973 |
error = EOPNOTSUPP; |
1974 |
goto out; |
1975 |
} |
1976 |
|
2028 |
|
1977 |
} |
2029 |
odata = CMSG_DATA(cm); |
|
|
2030 |
odatalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)odata; |
1978 |
|
2031 |
|
1979 |
/* |
2032 |
ix.ix_odata = odata; |
1980 |
* Now replace the integer FDs with pointers to the |
2033 |
ix.ix_odatalen = odatalen; |
1981 |
* file structure and capability rights. |
|
|
1982 |
*/ |
1983 |
newlen = oldfds * sizeof(fdep[0]); |
1984 |
*controlp = sbcreatecontrol(NULL, newlen, |
1985 |
SCM_RIGHTS, SOL_SOCKET); |
1986 |
if (*controlp == NULL) { |
1987 |
FILEDESC_SUNLOCK(fdesc); |
1988 |
error = E2BIG; |
1989 |
goto out; |
1990 |
} |
1991 |
fdp = data; |
1992 |
fdep = (struct filedescent **) |
1993 |
CMSG_DATA(mtod(*controlp, struct cmsghdr *)); |
1994 |
fdev = malloc(sizeof(*fdev) * oldfds, M_FILECAPS, |
1995 |
M_WAITOK); |
1996 |
for (i = 0; i < oldfds; i++, fdev++, fdp++) { |
1997 |
fde = &fdesc->fd_ofiles[*fdp]; |
1998 |
fdep[i] = fdev; |
1999 |
fdep[i]->fde_file = fde->fde_file; |
2000 |
filecaps_copy(&fde->fde_caps, |
2001 |
&fdep[i]->fde_caps, true); |
2002 |
unp_internalize_fp(fdep[i]->fde_file); |
2003 |
} |
2004 |
FILEDESC_SUNLOCK(fdesc); |
2005 |
break; |
2006 |
|
2034 |
|
2007 |
case SCM_TIMESTAMP: |
2035 |
/* |
2008 |
*controlp = sbcreatecontrol(NULL, sizeof(*tv), |
2036 |
* If transform function gives us a fixed data |
2009 |
SCM_TIMESTAMP, SOL_SOCKET); |
2037 |
* size, allocate new mbuf here, else leave it |
2010 |
if (*controlp == NULL) { |
2038 |
* to the function. |
|
|
2039 |
*/ |
2040 |
if ((size = op->size) != 0) { |
2041 |
m = sbcreatecontrol(NULL, size, cmtype, SOL_SOCKET); |
2042 |
if (m == NULL) { |
2011 |
error = ENOBUFS; |
2043 |
error = ENOBUFS; |
2012 |
goto out; |
2044 |
break; |
2013 |
} |
2045 |
} |
2014 |
tv = (struct timeval *) |
2046 |
ix.ix_mbuf = m; |
2015 |
CMSG_DATA(mtod(*controlp, struct cmsghdr *)); |
2047 |
ix.ix_ndata = CMSG_DATA(mtod(m, struct cmsghdr *)); |
2016 |
microtime(tv); |
2048 |
ix.ix_ndatalen = size; |
2017 |
break; |
2049 |
} else { |
|
|
2050 |
ix.ix_mbuf = NULL; |
2051 |
ix.ix_ndata = NULL; |
2052 |
ix.ix_ndatalen = 0; |
2053 |
} |
2018 |
|
2054 |
|
2019 |
case SCM_BINTIME: |
2055 |
/* |
2020 |
*controlp = sbcreatecontrol(NULL, sizeof(*bt), |
2056 |
* Apply transform and append new mbuf (if any) to |
2021 |
SCM_BINTIME, SOL_SOCKET); |
2057 |
* new control chain, even on error, so that it |
2022 |
if (*controlp == NULL) { |
2058 |
* will get freed. |
2023 |
error = ENOBUFS; |
2059 |
*/ |
2024 |
goto out; |
2060 |
error = (*op->func)(&ix); |
2025 |
} |
2061 |
if ((m = ix.ix_mbuf) != NULL) { |
2026 |
bt = (struct bintime *) |
2062 |
*controlp = m; |
2027 |
CMSG_DATA(mtod(*controlp, struct cmsghdr *)); |
2063 |
controlp = &m->m_next; |
2028 |
bintime(bt); |
|
|
2029 |
break; |
2030 |
|
2031 |
default: |
2032 |
error = EINVAL; |
2033 |
goto out; |
2034 |
} |
2064 |
} |
2035 |
|
2065 |
|
2036 |
controlp = &(*controlp)->m_next; |
2066 |
/* Advance to next message. */ |
2037 |
if (CMSG_SPACE(datalen) < clen) { |
2067 |
size = CMSG_SPACE(odatalen); |
2038 |
clen -= CMSG_SPACE(datalen); |
2068 |
if (size >= clen) |
2039 |
cm = (struct cmsghdr *) |
2069 |
break; |
2040 |
((caddr_t)cm + CMSG_SPACE(datalen)); |
2070 |
cm = (struct cmsghdr *)((caddr_t)cm + size); |
2041 |
} else { |
2071 |
clen -= size; |
2042 |
clen = 0; |
|
|
2043 |
cm = NULL; |
2044 |
} |
2045 |
} |
2072 |
} |
2046 |
|
2073 |
|
2047 |
out: |
|
|
2048 |
m_freem(control); |
2074 |
m_freem(control); |
2049 |
return (error); |
2075 |
return (error); |
2050 |
} |
2076 |
} |
2051 |
|
2077 |
|
2052 |
static struct mbuf * |
2078 |
/* |
2053 |
unp_addsockcred(struct thread *td, struct mbuf *control) |
2079 |
* Internalize file descriptors ("rights"). |
|
|
2080 |
*/ |
2081 |
static int |
2082 |
unp_internalize_fds(struct internalize_transform_data *ix) |
2054 |
{ |
2083 |
{ |
|
|
2084 |
struct proc *p = ix->ix_td->td_proc; |
2085 |
struct filedesc *fdesc = p->p_fd; |
2086 |
struct filedescent *fde, **fdep, *fdev; |
2087 |
struct file *fp; |
2088 |
struct mbuf *m; |
2089 |
int i, *fdp; |
2090 |
int oldfds; |
2091 |
u_int newlen; |
2092 |
|
2093 |
KASSERT(ix->ix_ndatalen == 0, ("%s: datalen", __func__)); |
2094 |
|
2095 |
/* Round down: this is forgiving, if slightly wrong. */ |
2096 |
oldfds = ix->ix_odatalen / sizeof (int); |
2097 |
if (oldfds == 0) |
2098 |
return (0); |
2099 |
|
2100 |
/* |
2101 |
* Check that all the FDs passed in refer to legal |
2102 |
* files. If not, reject the entire operation. |
2103 |
*/ |
2104 |
fdp = ix->ix_odata; |
2105 |
FILEDESC_SLOCK(fdesc); |
2106 |
for (i = 0; i < oldfds; i++, fdp++) { |
2107 |
fp = fget_locked(fdesc, *fdp); |
2108 |
if (fp == NULL) { |
2109 |
FILEDESC_SUNLOCK(fdesc); |
2110 |
return (EBADF); |
2111 |
} |
2112 |
if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) { |
2113 |
FILEDESC_SUNLOCK(fdesc); |
2114 |
return (EOPNOTSUPP); |
2115 |
} |
2116 |
|
2117 |
} |
2118 |
|
2119 |
/* |
2120 |
* Now replace the integer FDs with pointers to the |
2121 |
* file structure and capability rights. |
2122 |
*/ |
2123 |
newlen = oldfds * sizeof(fdep[0]); |
2124 |
m = sbcreatecontrol(NULL, newlen, SCM_RIGHTS, SOL_SOCKET); |
2125 |
if (m == NULL) { |
2126 |
FILEDESC_SUNLOCK(fdesc); |
2127 |
return (ENOBUFS); |
2128 |
} |
2129 |
|
2130 |
fdp = ix->ix_odata; |
2131 |
fdep = (struct filedescent **)CMSG_DATA(mtod(m, struct cmsghdr *)); |
2132 |
fdev = malloc(sizeof(*fdev) * oldfds, M_FILECAPS, M_WAITOK); |
2133 |
for (i = 0; i < oldfds; i++, fdev++, fdp++) { |
2134 |
fde = &fdesc->fd_ofiles[*fdp]; |
2135 |
fdep[i] = fdev; |
2136 |
fdep[i]->fde_file = fde->fde_file; |
2137 |
filecaps_copy(&fde->fde_caps, &fdep[i]->fde_caps, true); |
2138 |
unp_internalize_fp(fdep[i]->fde_file); |
2139 |
} |
2140 |
FILEDESC_SUNLOCK(fdesc); |
2141 |
|
2142 |
ix->ix_mbuf = m; |
2143 |
return (0); |
2144 |
} |
2145 |
|
2146 |
static int |
2147 |
unp_internalize_creds(struct internalize_transform_data *ix) |
2148 |
{ |
2149 |
struct cmsgcred *cmcred; |
2150 |
int i, ngroups; |
2151 |
struct thread *td = ix->ix_td; |
2152 |
struct ucred *cr = td->td_ucred; |
2153 |
|
2154 |
KASSERT(ix->ix_ndatalen == sizeof(*cmcred), ("%s: datalen", __func__)); |
2155 |
cmcred = ix->ix_ndata; |
2156 |
cmcred->cmcred_pid = td->td_proc->p_pid; |
2157 |
cmcred->cmcred_uid = cr->cr_ruid; |
2158 |
cmcred->cmcred_gid = cr->cr_rgid; |
2159 |
cmcred->cmcred_euid = cr->cr_uid; |
2160 |
ngroups = MIN(cr->cr_ngroups, CMGROUP_MAX); |
2161 |
cmcred->cmcred_ngroups = ngroups; |
2162 |
for (i = 0; i < ngroups; i++) |
2163 |
cmcred->cmcred_groups[i] = cr->cr_groups[i]; |
2164 |
return (0); |
2165 |
} |
2166 |
|
2167 |
static int |
2168 |
unp_internalize_timestamp(struct internalize_transform_data *ix) |
2169 |
{ |
2170 |
struct timeval *tv; |
2171 |
|
2172 |
KASSERT(ix->ix_ndatalen == sizeof(*tv), ("%s: datalen", __func__)); |
2173 |
tv = ix->ix_ndata; |
2174 |
microtime(tv); |
2175 |
return (0); |
2176 |
} |
2177 |
|
2178 |
static int |
2179 |
unp_internalize_bintime(struct internalize_transform_data *ix) |
2180 |
{ |
2181 |
struct bintime *bt; |
2182 |
|
2183 |
KASSERT(ix->ix_ndatalen == sizeof(*bt), ("%s: datalen", __func__)); |
2184 |
bt = ix->ix_ndata; |
2185 |
bintime(bt); |
2186 |
return (0); |
2187 |
} |
2188 |
|
2189 |
static int |
2190 |
unp_addsockcred(struct mbuf **pcontrol, struct thread *td) |
2191 |
{ |
2192 |
struct mbuf *control = *pcontrol; |
2055 |
struct mbuf *m, *n, *n_prev; |
2193 |
struct mbuf *m, *n, *n_prev; |
2056 |
struct sockcred *sc; |
2194 |
struct sockcred *sc; |
2057 |
const struct cmsghdr *cm; |
2195 |
const struct cmsghdr *cm; |
Lines 2061-2067
Link Here
|
2061 |
ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX); |
2199 |
ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX); |
2062 |
m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET); |
2200 |
m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET); |
2063 |
if (m == NULL) |
2201 |
if (m == NULL) |
2064 |
return (control); |
2202 |
return (ENOBUFS); |
2065 |
|
2203 |
|
2066 |
sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *)); |
2204 |
sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *)); |
2067 |
sc->sc_uid = td->td_ucred->cr_ruid; |
2205 |
sc->sc_uid = td->td_ucred->cr_ruid; |
Lines 2095-2101
Link Here
|
2095 |
|
2233 |
|
2096 |
/* Prepend it to the head. */ |
2234 |
/* Prepend it to the head. */ |
2097 |
m->m_next = control; |
2235 |
m->m_next = control; |
2098 |
return (m); |
2236 |
*pcontrol = m; |
|
|
2237 |
return (0); |
2099 |
} |
2238 |
} |
2100 |
|
2239 |
|
2101 |
static struct unpcb * |
2240 |
static struct unpcb * |