diff options
Diffstat (limited to 'net/tipc/socket.c')
| -rw-r--r-- | net/tipc/socket.c | 49 |
1 files changed, 27 insertions, 22 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 9329919fb07f..d5d70eb230b5 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -37,6 +37,7 @@ #include <linux/rhashtable.h> #include <linux/sched/signal.h> +#include <linux/uio.h> #include <trace/events/sock.h> #include "core.h" @@ -501,6 +502,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, tipc_set_sk_state(sk, TIPC_OPEN); if (tipc_sk_insert(tsk)) { sk_free(sk); + sock->sk = NULL; pr_warn("Socket create failed; port number exhausted\n"); return -EINVAL; } @@ -794,7 +796,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock, __poll_t revents = 0; sock_poll_wait(file, sock, wait); - trace_tipc_sk_poll(sk, NULL, TIPC_DUMP_ALL, " "); + trace_tipc_sk_poll(sk, NULL, TIPC_DUMP_NONE, " "); if (sk->sk_shutdown & RCV_SHUTDOWN) revents |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM; @@ -1362,6 +1364,9 @@ static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, __skb_queue_tail(xmitq, skb); return; } else if (mtyp == CONN_ACK) { + if (tsk->snt_unacked < msg_conn_ack(hdr)) + goto exit; + was_cong = tsk_conn_cong(tsk); tipc_sk_push_backlog(tsk, msg_nagle_ack(hdr)); tsk->snt_unacked -= msg_conn_ack(hdr); @@ -1931,7 +1936,7 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, if (likely(!err)) { int offset = skb_cb->bytes_read; - copy = min_t(int, dlen - offset, buflen); + copy = min_t(size_t, dlen - offset, buflen); rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy); if (unlikely(rc)) goto exit; @@ -2063,7 +2068,7 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m, /* Copy data if msg ok, otherwise return error/partial data */ if (likely(!err)) { offset = skb_cb->bytes_read; - copy = min_t(int, dlen - offset, buflen - copied); + copy = min_t(size_t, dlen - offset, buflen - copied); rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy); if (unlikely(rc)) break; @@ -2452,17 +2457,17 @@ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, atomic_set(dcnt, 0); lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt); if (likely(!sk_add_backlog(sk, skb, lim))) { - trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_ALL, + trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_SK_BKLGQ, "bklg & rcvq >90% allocated!"); continue; } - trace_tipc_sk_dump(sk, skb, TIPC_DUMP_ALL, "err_overload!"); + trace_tipc_sk_dump(sk, skb, TIPC_DUMP_SK_BKLGQ, "err_overload!"); /* Overload => reject message back to sender */ onode = tipc_own_addr(sock_net(sk)); sk_drops_inc(sk); if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) { - trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_ALL, + trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_SK_BKLGQ, "@sk_enqueue!"); __skb_queue_tail(xmitq, skb); } @@ -3220,8 +3225,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, * @sock: socket structure * @lvl: option level * @opt: option identifier - * @ov: receptacle for option value - * @ol: receptacle for length of option value + * @sopt: socket option container (input buffer length, output value/length) * * For stream sockets only, returns 0 length result for all IPPROTO_TCP options * (to ease compatibility). @@ -3229,22 +3233,22 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, * Return: 0 on success, errno otherwise */ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, - char __user *ov, int __user *ol) + sockopt_t *sopt) { struct sock *sk = sock->sk; struct tipc_sock *tsk = tipc_sk(sk); struct tipc_service_range seq; int len, scope; + int res = 0; u32 value; - int res; - if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) - return put_user(0, ol); + if (lvl == IPPROTO_TCP && sock->type == SOCK_STREAM) { + sopt->optlen = 0; + return 0; + } if (lvl != SOL_TIPC) return -ENOPROTOOPT; - res = get_user(len, ol); - if (res) - return res; + len = sopt->optlen; lock_sock(sk); @@ -3260,7 +3264,6 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, break; case TIPC_CONN_TIMEOUT: value = tsk->conn_timeout; - /* no need to set "res", since already 0 at this point */ break; case TIPC_NODE_RECVQ_DEPTH: value = 0; /* was tipc_queue_size, now obsolete */ @@ -3284,15 +3287,17 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, release_sock(sk); if (res) - return res; /* "get" failed */ + return res; if (len < sizeof(value)) return -EINVAL; - if (copy_to_user(ov, &value, sizeof(value))) + if (copy_to_iter(&value, sizeof(value), &sopt->iter_out) != + sizeof(value)) return -EFAULT; + sopt->optlen = sizeof(value); - return put_user(sizeof(value), ol); + return 0; } static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) @@ -3365,7 +3370,7 @@ static const struct proto_ops msg_ops = { .listen = sock_no_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, - .getsockopt = tipc_getsockopt, + .getsockopt_iter = tipc_getsockopt, .sendmsg = tipc_sendmsg, .recvmsg = tipc_recvmsg, .mmap = sock_no_mmap, @@ -3385,7 +3390,7 @@ static const struct proto_ops packet_ops = { .listen = tipc_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, - .getsockopt = tipc_getsockopt, + .getsockopt_iter = tipc_getsockopt, .sendmsg = tipc_send_packet, .recvmsg = tipc_recvmsg, .mmap = sock_no_mmap, @@ -3405,7 +3410,7 @@ static const struct proto_ops stream_ops = { .listen = tipc_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, - .getsockopt = tipc_getsockopt, + .getsockopt_iter = tipc_getsockopt, .sendmsg = tipc_sendstream, .recvmsg = tipc_recvstream, .mmap = sock_no_mmap, |
