diff options
Diffstat (limited to 'net/tipc/socket.c')
| -rw-r--r-- | net/tipc/socket.c | 100 |
1 files changed, 58 insertions, 42 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 648a734e6044..32d778448a00 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -169,12 +169,6 @@ static int tipc_create(struct socket *sock, int protocol) | |||
| 169 | struct sock *sk; | 169 | struct sock *sk; |
| 170 | u32 ref; | 170 | u32 ref; |
| 171 | 171 | ||
| 172 | if ((sock->type != SOCK_STREAM) && | ||
| 173 | (sock->type != SOCK_SEQPACKET) && | ||
| 174 | (sock->type != SOCK_DGRAM) && | ||
| 175 | (sock->type != SOCK_RDM)) | ||
| 176 | return -EPROTOTYPE; | ||
| 177 | |||
| 178 | if (unlikely(protocol != 0)) | 172 | if (unlikely(protocol != 0)) |
| 179 | return -EPROTONOSUPPORT; | 173 | return -EPROTONOSUPPORT; |
| 180 | 174 | ||
| @@ -199,6 +193,9 @@ static int tipc_create(struct socket *sock, int protocol) | |||
| 199 | sock->ops = &msg_ops; | 193 | sock->ops = &msg_ops; |
| 200 | sock->state = SS_READY; | 194 | sock->state = SS_READY; |
| 201 | break; | 195 | break; |
| 196 | default: | ||
| 197 | tipc_deleteport(ref); | ||
| 198 | return -EPROTOTYPE; | ||
| 202 | } | 199 | } |
| 203 | 200 | ||
| 204 | sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); | 201 | sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); |
| @@ -426,7 +423,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
| 426 | 423 | ||
| 427 | if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) | 424 | if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) |
| 428 | return -EFAULT; | 425 | return -EFAULT; |
| 429 | if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) | 426 | if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN))) |
| 430 | return -EACCES; | 427 | return -EACCES; |
| 431 | 428 | ||
| 432 | return 0; | 429 | return 0; |
| @@ -437,7 +434,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
| 437 | * @iocb: (unused) | 434 | * @iocb: (unused) |
| 438 | * @sock: socket structure | 435 | * @sock: socket structure |
| 439 | * @m: message to send | 436 | * @m: message to send |
| 440 | * @total_len: (unused) | 437 | * @total_len: length of message |
| 441 | * | 438 | * |
| 442 | * Message must have an destination specified explicitly. | 439 | * Message must have an destination specified explicitly. |
| 443 | * Used for SOCK_RDM and SOCK_DGRAM messages, | 440 | * Used for SOCK_RDM and SOCK_DGRAM messages, |
| @@ -458,7 +455,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 458 | 455 | ||
| 459 | if (unlikely(!dest)) | 456 | if (unlikely(!dest)) |
| 460 | return -EDESTADDRREQ; | 457 | return -EDESTADDRREQ; |
| 461 | if (unlikely(dest->family != AF_TIPC)) | 458 | if (unlikely((m->msg_namelen < sizeof(*dest)) || |
| 459 | (dest->family != AF_TIPC))) | ||
| 462 | return -EINVAL; | 460 | return -EINVAL; |
| 463 | 461 | ||
| 464 | needs_conn = (sock->state != SS_READY); | 462 | needs_conn = (sock->state != SS_READY); |
| @@ -470,6 +468,10 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 470 | if ((tsock->p->published) || | 468 | if ((tsock->p->published) || |
| 471 | ((sock->type == SOCK_STREAM) && (total_len != 0))) | 469 | ((sock->type == SOCK_STREAM) && (total_len != 0))) |
| 472 | return -EOPNOTSUPP; | 470 | return -EOPNOTSUPP; |
| 471 | if (dest->addrtype == TIPC_ADDR_NAME) { | ||
| 472 | tsock->p->conn_type = dest->addr.name.name.type; | ||
| 473 | tsock->p->conn_instance = dest->addr.name.name.instance; | ||
| 474 | } | ||
| 473 | } | 475 | } |
| 474 | 476 | ||
| 475 | if (down_interruptible(&tsock->sem)) | 477 | if (down_interruptible(&tsock->sem)) |
| @@ -538,7 +540,7 @@ exit: | |||
| 538 | * @iocb: (unused) | 540 | * @iocb: (unused) |
| 539 | * @sock: socket structure | 541 | * @sock: socket structure |
| 540 | * @m: message to send | 542 | * @m: message to send |
| 541 | * @total_len: (unused) | 543 | * @total_len: length of message |
| 542 | * | 544 | * |
| 543 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. | 545 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. |
| 544 | * | 546 | * |
| @@ -561,15 +563,15 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 561 | return -ERESTARTSYS; | 563 | return -ERESTARTSYS; |
| 562 | } | 564 | } |
| 563 | 565 | ||
| 564 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
| 565 | if (sock->state == SS_DISCONNECTING) | ||
| 566 | res = -EPIPE; | ||
| 567 | else | ||
| 568 | res = -ENOTCONN; | ||
| 569 | goto exit; | ||
| 570 | } | ||
| 571 | |||
| 572 | do { | 566 | do { |
| 567 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
| 568 | if (sock->state == SS_DISCONNECTING) | ||
| 569 | res = -EPIPE; | ||
| 570 | else | ||
| 571 | res = -ENOTCONN; | ||
| 572 | goto exit; | ||
| 573 | } | ||
| 574 | |||
| 573 | res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); | 575 | res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); |
| 574 | if (likely(res != -ELINKCONG)) { | 576 | if (likely(res != -ELINKCONG)) { |
| 575 | exit: | 577 | exit: |
| @@ -597,7 +599,8 @@ exit: | |||
| 597 | * | 599 | * |
| 598 | * Used for SOCK_STREAM data. | 600 | * Used for SOCK_STREAM data. |
| 599 | * | 601 | * |
| 600 | * Returns the number of bytes sent on success, or errno otherwise | 602 | * Returns the number of bytes sent on success (or partial success), |
| 603 | * or errno if no data sent | ||
| 601 | */ | 604 | */ |
| 602 | 605 | ||
| 603 | 606 | ||
| @@ -611,6 +614,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 611 | char __user *curr_start; | 614 | char __user *curr_start; |
| 612 | int curr_left; | 615 | int curr_left; |
| 613 | int bytes_to_send; | 616 | int bytes_to_send; |
| 617 | int bytes_sent; | ||
| 614 | int res; | 618 | int res; |
| 615 | 619 | ||
| 616 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) | 620 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) |
| @@ -633,11 +637,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 633 | * of small iovec entries into send_packet(). | 637 | * of small iovec entries into send_packet(). |
| 634 | */ | 638 | */ |
| 635 | 639 | ||
| 636 | my_msg = *m; | 640 | curr_iov = m->msg_iov; |
| 637 | curr_iov = my_msg.msg_iov; | 641 | curr_iovlen = m->msg_iovlen; |
| 638 | curr_iovlen = my_msg.msg_iovlen; | ||
| 639 | my_msg.msg_iov = &my_iov; | 642 | my_msg.msg_iov = &my_iov; |
| 640 | my_msg.msg_iovlen = 1; | 643 | my_msg.msg_iovlen = 1; |
| 644 | bytes_sent = 0; | ||
| 641 | 645 | ||
| 642 | while (curr_iovlen--) { | 646 | while (curr_iovlen--) { |
| 643 | curr_start = curr_iov->iov_base; | 647 | curr_start = curr_iov->iov_base; |
| @@ -648,16 +652,18 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 648 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; | 652 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; |
| 649 | my_iov.iov_base = curr_start; | 653 | my_iov.iov_base = curr_start; |
| 650 | my_iov.iov_len = bytes_to_send; | 654 | my_iov.iov_len = bytes_to_send; |
| 651 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) | 655 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { |
| 652 | return res; | 656 | return bytes_sent ? bytes_sent : res; |
| 657 | } | ||
| 653 | curr_left -= bytes_to_send; | 658 | curr_left -= bytes_to_send; |
| 654 | curr_start += bytes_to_send; | 659 | curr_start += bytes_to_send; |
| 660 | bytes_sent += bytes_to_send; | ||
| 655 | } | 661 | } |
| 656 | 662 | ||
| 657 | curr_iov++; | 663 | curr_iov++; |
| 658 | } | 664 | } |
| 659 | 665 | ||
| 660 | return total_len; | 666 | return bytes_sent; |
| 661 | } | 667 | } |
| 662 | 668 | ||
| 663 | /** | 669 | /** |
| @@ -727,6 +733,7 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
| 727 | u32 anc_data[3]; | 733 | u32 anc_data[3]; |
| 728 | u32 err; | 734 | u32 err; |
| 729 | u32 dest_type; | 735 | u32 dest_type; |
| 736 | int has_name; | ||
| 730 | int res; | 737 | int res; |
| 731 | 738 | ||
| 732 | if (likely(m->msg_controllen == 0)) | 739 | if (likely(m->msg_controllen == 0)) |
| @@ -738,10 +745,10 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
| 738 | if (unlikely(err)) { | 745 | if (unlikely(err)) { |
| 739 | anc_data[0] = err; | 746 | anc_data[0] = err; |
| 740 | anc_data[1] = msg_data_sz(msg); | 747 | anc_data[1] = msg_data_sz(msg); |
| 741 | if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) | 748 | if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data))) |
| 742 | return res; | 749 | return res; |
| 743 | if (anc_data[1] && | 750 | if (anc_data[1] && |
| 744 | (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], | 751 | (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], |
| 745 | msg_data(msg)))) | 752 | msg_data(msg)))) |
| 746 | return res; | 753 | return res; |
| 747 | } | 754 | } |
| @@ -751,25 +758,28 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
| 751 | dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; | 758 | dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; |
| 752 | switch (dest_type) { | 759 | switch (dest_type) { |
| 753 | case TIPC_NAMED_MSG: | 760 | case TIPC_NAMED_MSG: |
| 761 | has_name = 1; | ||
| 754 | anc_data[0] = msg_nametype(msg); | 762 | anc_data[0] = msg_nametype(msg); |
| 755 | anc_data[1] = msg_namelower(msg); | 763 | anc_data[1] = msg_namelower(msg); |
| 756 | anc_data[2] = msg_namelower(msg); | 764 | anc_data[2] = msg_namelower(msg); |
| 757 | break; | 765 | break; |
| 758 | case TIPC_MCAST_MSG: | 766 | case TIPC_MCAST_MSG: |
| 767 | has_name = 1; | ||
| 759 | anc_data[0] = msg_nametype(msg); | 768 | anc_data[0] = msg_nametype(msg); |
| 760 | anc_data[1] = msg_namelower(msg); | 769 | anc_data[1] = msg_namelower(msg); |
| 761 | anc_data[2] = msg_nameupper(msg); | 770 | anc_data[2] = msg_nameupper(msg); |
| 762 | break; | 771 | break; |
| 763 | case TIPC_CONN_MSG: | 772 | case TIPC_CONN_MSG: |
| 773 | has_name = (tport->conn_type != 0); | ||
| 764 | anc_data[0] = tport->conn_type; | 774 | anc_data[0] = tport->conn_type; |
| 765 | anc_data[1] = tport->conn_instance; | 775 | anc_data[1] = tport->conn_instance; |
| 766 | anc_data[2] = tport->conn_instance; | 776 | anc_data[2] = tport->conn_instance; |
| 767 | break; | 777 | break; |
| 768 | default: | 778 | default: |
| 769 | anc_data[0] = 0; | 779 | has_name = 0; |
| 770 | } | 780 | } |
| 771 | if (anc_data[0] && | 781 | if (has_name && |
| 772 | (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) | 782 | (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data))) |
| 773 | return res; | 783 | return res; |
| 774 | 784 | ||
| 775 | return 0; | 785 | return 0; |
| @@ -960,7 +970,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
| 960 | restart: | 970 | restart: |
| 961 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | 971 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && |
| 962 | (flags & MSG_DONTWAIT))) { | 972 | (flags & MSG_DONTWAIT))) { |
| 963 | res = (sz_copied == 0) ? -EWOULDBLOCK : 0; | 973 | res = -EWOULDBLOCK; |
| 964 | goto exit; | 974 | goto exit; |
| 965 | } | 975 | } |
| 966 | 976 | ||
| @@ -1051,7 +1061,7 @@ restart: | |||
| 1051 | 1061 | ||
| 1052 | exit: | 1062 | exit: |
| 1053 | up(&tsock->sem); | 1063 | up(&tsock->sem); |
| 1054 | return res ? res : sz_copied; | 1064 | return sz_copied ? sz_copied : res; |
| 1055 | } | 1065 | } |
| 1056 | 1066 | ||
| 1057 | /** | 1067 | /** |
| @@ -1236,7 +1246,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1236 | if (sock->state == SS_READY) | 1246 | if (sock->state == SS_READY) |
| 1237 | return -EOPNOTSUPP; | 1247 | return -EOPNOTSUPP; |
| 1238 | 1248 | ||
| 1239 | /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ | 1249 | /* Issue Posix-compliant error code if socket is in the wrong state */ |
| 1250 | |||
| 1240 | if (sock->state == SS_LISTENING) | 1251 | if (sock->state == SS_LISTENING) |
| 1241 | return -EOPNOTSUPP; | 1252 | return -EOPNOTSUPP; |
| 1242 | if (sock->state == SS_CONNECTING) | 1253 | if (sock->state == SS_CONNECTING) |
| @@ -1244,13 +1255,20 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1244 | if (sock->state != SS_UNCONNECTED) | 1255 | if (sock->state != SS_UNCONNECTED) |
| 1245 | return -EISCONN; | 1256 | return -EISCONN; |
| 1246 | 1257 | ||
| 1247 | if ((dst->family != AF_TIPC) || | 1258 | /* |
| 1248 | ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) | 1259 | * Reject connection attempt using multicast address |
| 1260 | * | ||
| 1261 | * Note: send_msg() validates the rest of the address fields, | ||
| 1262 | * so there's no need to do it here | ||
| 1263 | */ | ||
| 1264 | |||
| 1265 | if (dst->addrtype == TIPC_ADDR_MCAST) | ||
| 1249 | return -EINVAL; | 1266 | return -EINVAL; |
| 1250 | 1267 | ||
| 1251 | /* Send a 'SYN-' to destination */ | 1268 | /* Send a 'SYN-' to destination */ |
| 1252 | 1269 | ||
| 1253 | m.msg_name = dest; | 1270 | m.msg_name = dest; |
| 1271 | m.msg_namelen = destlen; | ||
| 1254 | if ((res = send_msg(NULL, sock, &m, 0)) < 0) { | 1272 | if ((res = send_msg(NULL, sock, &m, 0)) < 0) { |
| 1255 | sock->state = SS_DISCONNECTING; | 1273 | sock->state = SS_DISCONNECTING; |
| 1256 | return res; | 1274 | return res; |
| @@ -1269,10 +1287,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1269 | msg = buf_msg(buf); | 1287 | msg = buf_msg(buf); |
| 1270 | res = auto_connect(sock, tsock, msg); | 1288 | res = auto_connect(sock, tsock, msg); |
| 1271 | if (!res) { | 1289 | if (!res) { |
| 1272 | if (dst->addrtype == TIPC_ADDR_NAME) { | ||
| 1273 | tsock->p->conn_type = dst->addr.name.name.type; | ||
| 1274 | tsock->p->conn_instance = dst->addr.name.name.instance; | ||
| 1275 | } | ||
| 1276 | if (!msg_data_sz(msg)) | 1290 | if (!msg_data_sz(msg)) |
| 1277 | advance_queue(tsock); | 1291 | advance_queue(tsock); |
| 1278 | } | 1292 | } |
| @@ -1386,7 +1400,7 @@ exit: | |||
| 1386 | /** | 1400 | /** |
| 1387 | * shutdown - shutdown socket connection | 1401 | * shutdown - shutdown socket connection |
| 1388 | * @sock: socket structure | 1402 | * @sock: socket structure |
| 1389 | * @how: direction to close (always treated as read + write) | 1403 | * @how: direction to close (unused; always treated as read + write) |
| 1390 | * | 1404 | * |
| 1391 | * Terminates connection (if necessary), then purges socket's receive queue. | 1405 | * Terminates connection (if necessary), then purges socket's receive queue. |
| 1392 | * | 1406 | * |
| @@ -1469,7 +1483,8 @@ restart: | |||
| 1469 | * Returns 0 on success, errno otherwise | 1483 | * Returns 0 on success, errno otherwise |
| 1470 | */ | 1484 | */ |
| 1471 | 1485 | ||
| 1472 | static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) | 1486 | static int setsockopt(struct socket *sock, |
| 1487 | int lvl, int opt, char __user *ov, int ol) | ||
| 1473 | { | 1488 | { |
| 1474 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 1489 | struct tipc_sock *tsock = tipc_sk(sock->sk); |
| 1475 | u32 value; | 1490 | u32 value; |
| @@ -1525,7 +1540,8 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) | |||
| 1525 | * Returns 0 on success, errno otherwise | 1540 | * Returns 0 on success, errno otherwise |
| 1526 | */ | 1541 | */ |
| 1527 | 1542 | ||
| 1528 | static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) | 1543 | static int getsockopt(struct socket *sock, |
| 1544 | int lvl, int opt, char __user *ov, int *ol) | ||
| 1529 | { | 1545 | { |
| 1530 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 1546 | struct tipc_sock *tsock = tipc_sk(sock->sk); |
| 1531 | int len; | 1547 | int len; |
