|
Lines 433-438
linux_to_bsd_cmsg_type(int cmsg_type)
Link Here
|
| 433 |
switch (cmsg_type) { |
433 |
switch (cmsg_type) { |
| 434 |
case LINUX_SCM_RIGHTS: |
434 |
case LINUX_SCM_RIGHTS: |
| 435 |
return (SCM_RIGHTS); |
435 |
return (SCM_RIGHTS); |
|
|
436 |
case LINUX_SCM_CREDENTIALS: |
| 437 |
return (SCM_CREDS); |
| 436 |
} |
438 |
} |
| 437 |
return (-1); |
439 |
return (-1); |
| 438 |
} |
440 |
} |
|
Lines 444-449
bsd_to_linux_cmsg_type(int cmsg_type)
Link Here
|
| 444 |
switch (cmsg_type) { |
446 |
switch (cmsg_type) { |
| 445 |
case SCM_RIGHTS: |
447 |
case SCM_RIGHTS: |
| 446 |
return (LINUX_SCM_RIGHTS); |
448 |
return (LINUX_SCM_RIGHTS); |
|
|
449 |
case SCM_CREDS: |
| 450 |
return (LINUX_SCM_CREDENTIALS); |
| 447 |
} |
451 |
} |
| 448 |
return (-1); |
452 |
return (-1); |
| 449 |
} |
453 |
} |
|
Lines 472-478
bsd_to_linux_msghdr(const struct msghdr
Link Here
|
| 472 |
lhdr->msg_iov = PTROUT(bhdr->msg_iov); |
476 |
lhdr->msg_iov = PTROUT(bhdr->msg_iov); |
| 473 |
lhdr->msg_iovlen = bhdr->msg_iovlen; |
477 |
lhdr->msg_iovlen = bhdr->msg_iovlen; |
| 474 |
lhdr->msg_control = PTROUT(bhdr->msg_control); |
478 |
lhdr->msg_control = PTROUT(bhdr->msg_control); |
| 475 |
lhdr->msg_controllen = bhdr->msg_controllen; |
479 |
/* msg_controllen skipped */ |
| 476 |
/* msg_flags skipped */ |
480 |
/* msg_flags skipped */ |
| 477 |
return (0); |
481 |
return (0); |
| 478 |
} |
482 |
} |
|
Lines 1092-1097
static int
Link Here
|
| 1092 |
linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) |
1096 |
linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) |
| 1093 |
{ |
1097 |
{ |
| 1094 |
struct cmsghdr *cmsg; |
1098 |
struct cmsghdr *cmsg; |
|
|
1099 |
struct cmsgcred cmcred; |
| 1095 |
struct mbuf *control; |
1100 |
struct mbuf *control; |
| 1096 |
struct msghdr msg; |
1101 |
struct msghdr msg; |
| 1097 |
struct l_cmsghdr linux_cmsg; |
1102 |
struct l_cmsghdr linux_cmsg; |
|
Lines 1099-1104
linux_sendmsg(struct thread *td, struct
Link Here
|
| 1099 |
struct l_msghdr linux_msg; |
1104 |
struct l_msghdr linux_msg; |
| 1100 |
struct iovec *iov; |
1105 |
struct iovec *iov; |
| 1101 |
socklen_t datalen; |
1106 |
socklen_t datalen; |
|
|
1107 |
struct sockaddr *sa; |
| 1108 |
sa_family_t sa_family; |
| 1102 |
void *data; |
1109 |
void *data; |
| 1103 |
int error; |
1110 |
int error; |
| 1104 |
|
1111 |
|
|
Lines 1128-1134
linux_sendmsg(struct thread *td, struct
Link Here
|
| 1128 |
if (error) |
1135 |
if (error) |
| 1129 |
return (error); |
1136 |
return (error); |
| 1130 |
|
1137 |
|
|
|
1138 |
control = NULL; |
| 1139 |
cmsg = NULL; |
| 1140 |
|
| 1131 |
if (msg.msg_control != NULL) { |
1141 |
if (msg.msg_control != NULL) { |
|
|
1142 |
error = kern_getsockname(td, args->s, &sa, &datalen); |
| 1143 |
if (error) |
| 1144 |
goto bad; |
| 1145 |
sa_family = sa->sa_family; |
| 1146 |
free(sa, M_SONAME); |
| 1147 |
|
| 1132 |
error = ENOBUFS; |
1148 |
error = ENOBUFS; |
| 1133 |
cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO); |
1149 |
cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO); |
| 1134 |
control = m_get(M_WAIT, MT_CONTROL); |
1150 |
control = m_get(M_WAIT, MT_CONTROL); |
|
Lines 1147-1164
linux_sendmsg(struct thread *td, struct
Link Here
|
| 1147 |
goto bad; |
1163 |
goto bad; |
| 1148 |
|
1164 |
|
| 1149 |
/* |
1165 |
/* |
| 1150 |
* Now we support only SCM_RIGHTS, so return EINVAL |
1166 |
* Now we support only SCM_RIGHTS and SCM_CRED, |
| 1151 |
* in any other cmsg_type |
1167 |
* so return EINVAL in any other cmsg_type |
| 1152 |
*/ |
1168 |
*/ |
| 1153 |
if ((cmsg->cmsg_type = |
1169 |
cmsg->cmsg_type = |
| 1154 |
linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1) |
1170 |
linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type); |
| 1155 |
goto bad; |
|
|
| 1156 |
cmsg->cmsg_level = |
1171 |
cmsg->cmsg_level = |
| 1157 |
linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level); |
1172 |
linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level); |
|
|
1173 |
if (cmsg->cmsg_type == -1 |
| 1174 |
|| cmsg->cmsg_level != SOL_SOCKET) |
| 1175 |
goto bad; |
| 1176 |
|
| 1177 |
/* |
| 1178 |
* Some applications (e.g. pulseaudio) attempt to |
| 1179 |
* send ancillary data even if the underlying protocol |
| 1180 |
* doesn't support it which is not allowed in the |
| 1181 |
* FreeBSD system call interface. |
| 1182 |
*/ |
| 1183 |
if (sa_family != AF_UNIX) |
| 1184 |
continue; |
| 1158 |
|
1185 |
|
|
|
1186 |
data = LINUX_CMSG_DATA(ptr_cmsg); |
| 1159 |
datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ; |
1187 |
datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ; |
|
|
1188 |
|
| 1189 |
switch (cmsg->cmsg_type) |
| 1190 |
{ |
| 1191 |
case SCM_RIGHTS: |
| 1192 |
break; |
| 1193 |
|
| 1194 |
case SCM_CREDS: |
| 1195 |
data = &cmcred; |
| 1196 |
datalen = sizeof(cmcred); |
| 1197 |
|
| 1198 |
/* |
| 1199 |
* The lower levels will fill in the structure |
| 1200 |
*/ |
| 1201 |
bzero(data, datalen); |
| 1202 |
break; |
| 1203 |
} |
| 1204 |
|
| 1160 |
cmsg->cmsg_len = CMSG_LEN(datalen); |
1205 |
cmsg->cmsg_len = CMSG_LEN(datalen); |
| 1161 |
data = LINUX_CMSG_DATA(ptr_cmsg); |
|
|
| 1162 |
|
1206 |
|
| 1163 |
error = ENOBUFS; |
1207 |
error = ENOBUFS; |
| 1164 |
if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg)) |
1208 |
if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg)) |
|
Lines 1166-1174
linux_sendmsg(struct thread *td, struct
Link Here
|
| 1166 |
if (!m_append(control, datalen, (c_caddr_t) data)) |
1210 |
if (!m_append(control, datalen, (c_caddr_t) data)) |
| 1167 |
goto bad; |
1211 |
goto bad; |
| 1168 |
} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg))); |
1212 |
} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg))); |
| 1169 |
} else { |
1213 |
|
| 1170 |
control = NULL; |
1214 |
if (m_length(control, NULL) == 0) { |
| 1171 |
cmsg = NULL; |
1215 |
m_freem(control); |
|
|
1216 |
control = NULL; |
| 1217 |
} |
| 1172 |
} |
1218 |
} |
| 1173 |
|
1219 |
|
| 1174 |
msg.msg_iov = iov; |
1220 |
msg.msg_iov = iov; |
|
Lines 1193-1201
static int
Link Here
|
| 1193 |
linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) |
1239 |
linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) |
| 1194 |
{ |
1240 |
{ |
| 1195 |
struct cmsghdr *cm; |
1241 |
struct cmsghdr *cm; |
|
|
1242 |
struct cmsgcred *cmcred; |
| 1196 |
struct msghdr msg; |
1243 |
struct msghdr msg; |
| 1197 |
struct l_cmsghdr *linux_cmsg = NULL; |
1244 |
struct l_cmsghdr *linux_cmsg = NULL; |
| 1198 |
socklen_t datalen, outlen, clen; |
1245 |
struct l_ucred linux_ucred; |
|
|
1246 |
socklen_t datalen, outlen; |
| 1199 |
struct l_msghdr linux_msg; |
1247 |
struct l_msghdr linux_msg; |
| 1200 |
struct iovec *iov, *uiov; |
1248 |
struct iovec *iov, *uiov; |
| 1201 |
struct mbuf *control = NULL; |
1249 |
struct mbuf *control = NULL; |
|
Lines 1252-1290
linux_recvmsg(struct thread *td, struct
Link Here
|
| 1252 |
goto bad; |
1300 |
goto bad; |
| 1253 |
} |
1301 |
} |
| 1254 |
|
1302 |
|
| 1255 |
if (control) { |
1303 |
outbuf = PTRIN(linux_msg.msg_control); |
|
|
1304 |
outlen = 0; |
| 1256 |
|
1305 |
|
|
|
1306 |
if (control) { |
| 1257 |
linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO); |
1307 |
linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO); |
| 1258 |
outbuf = PTRIN(linux_msg.msg_control); |
|
|
| 1259 |
cm = mtod(control, struct cmsghdr *); |
| 1260 |
outlen = 0; |
| 1261 |
clen = control->m_len; |
| 1262 |
|
1308 |
|
| 1263 |
while (cm != NULL) { |
1309 |
msg.msg_control = mtod(control, struct cmsghdr *); |
|
|
1310 |
msg.msg_controllen = control->m_len; |
| 1311 |
|
| 1312 |
cm = CMSG_FIRSTHDR(&msg); |
| 1264 |
|
1313 |
|
| 1265 |
if ((linux_cmsg->cmsg_type = |
1314 |
while (cm != NULL) { |
| 1266 |
bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1) |
1315 |
linux_cmsg->cmsg_type = |
|
|
1316 |
bsd_to_linux_cmsg_type(cm->cmsg_type); |
| 1317 |
linux_cmsg->cmsg_level = |
| 1318 |
bsd_to_linux_sockopt_level(cm->cmsg_level); |
| 1319 |
if (linux_cmsg->cmsg_type == -1 |
| 1320 |
|| cm->cmsg_level != SOL_SOCKET) |
| 1267 |
{ |
1321 |
{ |
| 1268 |
error = EINVAL; |
1322 |
error = EINVAL; |
| 1269 |
goto bad; |
1323 |
goto bad; |
| 1270 |
} |
1324 |
} |
|
|
1325 |
|
| 1271 |
data = CMSG_DATA(cm); |
1326 |
data = CMSG_DATA(cm); |
| 1272 |
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; |
1327 |
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; |
| 1273 |
|
1328 |
|
| 1274 |
switch (linux_cmsg->cmsg_type) |
1329 |
switch (cm->cmsg_type) |
| 1275 |
{ |
1330 |
{ |
| 1276 |
case LINUX_SCM_RIGHTS: |
1331 |
case SCM_RIGHTS: |
| 1277 |
if (outlen + LINUX_CMSG_LEN(datalen) > |
|
|
| 1278 |
linux_msg.msg_controllen) { |
| 1279 |
if (outlen == 0) { |
| 1280 |
error = EMSGSIZE; |
| 1281 |
goto bad; |
| 1282 |
} else { |
| 1283 |
linux_msg.msg_flags |= |
| 1284 |
LINUX_MSG_CTRUNC; |
| 1285 |
goto out; |
| 1286 |
} |
| 1287 |
} |
| 1288 |
if (args->flags & LINUX_MSG_CMSG_CLOEXEC) { |
1332 |
if (args->flags & LINUX_MSG_CMSG_CLOEXEC) { |
| 1289 |
fds = datalen / sizeof(int); |
1333 |
fds = datalen / sizeof(int); |
| 1290 |
fdp = data; |
1334 |
fdp = data; |
|
Lines 1295-1305
linux_recvmsg(struct thread *td, struct
Link Here
|
| 1295 |
} |
1339 |
} |
| 1296 |
} |
1340 |
} |
| 1297 |
break; |
1341 |
break; |
|
|
1342 |
|
| 1343 |
case SCM_CREDS: |
| 1344 |
/* |
| 1345 |
* Currently LOCAL_CREDS is never in |
| 1346 |
* effect for Linux so no need to worry |
| 1347 |
* about sockcred |
| 1348 |
*/ |
| 1349 |
if (datalen != sizeof (*cmcred)) { |
| 1350 |
error = EMSGSIZE; |
| 1351 |
goto bad; |
| 1352 |
} |
| 1353 |
cmcred = (struct cmsgcred *)data; |
| 1354 |
bzero(&linux_ucred, sizeof(linux_ucred)); |
| 1355 |
linux_ucred.pid = cmcred->cmcred_pid; |
| 1356 |
linux_ucred.uid = cmcred->cmcred_uid; |
| 1357 |
linux_ucred.gid = cmcred->cmcred_gid; |
| 1358 |
data = &linux_ucred; |
| 1359 |
datalen = sizeof(linux_ucred); |
| 1360 |
break; |
| 1361 |
} |
| 1362 |
|
| 1363 |
if (outlen + LINUX_CMSG_LEN(datalen) > |
| 1364 |
linux_msg.msg_controllen) { |
| 1365 |
if (outlen == 0) { |
| 1366 |
error = EMSGSIZE; |
| 1367 |
goto bad; |
| 1368 |
} else { |
| 1369 |
linux_msg.msg_flags |= |
| 1370 |
LINUX_MSG_CTRUNC; |
| 1371 |
goto out; |
| 1372 |
} |
| 1298 |
} |
1373 |
} |
| 1299 |
|
1374 |
|
| 1300 |
linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen); |
1375 |
linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen); |
| 1301 |
linux_cmsg->cmsg_level = |
|
|
| 1302 |
bsd_to_linux_sockopt_level(cm->cmsg_level); |
| 1303 |
|
1376 |
|
| 1304 |
error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ); |
1377 |
error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ); |
| 1305 |
if (error) |
1378 |
if (error) |
|
Lines 1312-1329
linux_recvmsg(struct thread *td, struct
Link Here
|
| 1312 |
|
1385 |
|
| 1313 |
outbuf += LINUX_CMSG_ALIGN(datalen); |
1386 |
outbuf += LINUX_CMSG_ALIGN(datalen); |
| 1314 |
outlen += LINUX_CMSG_LEN(datalen); |
1387 |
outlen += LINUX_CMSG_LEN(datalen); |
| 1315 |
linux_msg.msg_controllen = outlen; |
|
|
| 1316 |
|
1388 |
|
| 1317 |
if (CMSG_SPACE(datalen) < clen) { |
1389 |
cm = CMSG_NXTHDR(&msg, cm); |
| 1318 |
clen -= CMSG_SPACE(datalen); |
|
|
| 1319 |
cm = (struct cmsghdr *) |
| 1320 |
((caddr_t)cm + CMSG_SPACE(datalen)); |
| 1321 |
} else |
| 1322 |
cm = NULL; |
| 1323 |
} |
1390 |
} |
| 1324 |
} |
1391 |
} |
| 1325 |
|
1392 |
|
| 1326 |
out: |
1393 |
out: |
|
|
1394 |
linux_msg.msg_controllen = outlen; |
| 1327 |
error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg)); |
1395 |
error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg)); |
| 1328 |
|
1396 |
|
| 1329 |
bad: |
1397 |
bad: |