From 70cb23477019b8739d23ead223539c7e6dfc509c Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:41:47 -0700 Subject: [TIPC]: Fixed privilege checking typo in dest_name_check(). This patch originated by Stephane Ouellette . Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 648a734e604..eaf4d6951a4 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -426,7 +426,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) return -EFAULT; - if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) + if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN))) return -EACCES; return 0; -- cgit v1.2.3-70-g09d2 From e9024f0f79c3f847a793d6a16bf4fefc6d7a4649 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:43:57 -0700 Subject: [TIPC]: Non-operation-affecting corrections to comments & function definitions. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index eaf4d6951a4..0923213fc6a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -437,7 +437,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) * @iocb: (unused) * @sock: socket structure * @m: message to send - * @total_len: (unused) + * @total_len: length of message * * Message must have an destination specified explicitly. * Used for SOCK_RDM and SOCK_DGRAM messages, @@ -538,7 +538,7 @@ exit: * @iocb: (unused) * @sock: socket structure * @m: message to send - * @total_len: (unused) + * @total_len: length of message * * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. * @@ -1386,7 +1386,7 @@ exit: /** * shutdown - shutdown socket connection * @sock: socket structure - * @how: direction to close (always treated as read + write) + * @how: direction to close (unused; always treated as read + write) * * Terminates connection (if necessary), then purges socket's receive queue. * @@ -1469,7 +1469,8 @@ restart: * Returns 0 on success, errno otherwise */ -static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) +static int setsockopt(struct socket *sock, + int lvl, int opt, char __user *ov, int ol) { struct tipc_sock *tsock = tipc_sk(sock->sk); u32 value; @@ -1525,7 +1526,8 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) * Returns 0 on success, errno otherwise */ -static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) +static int getsockopt(struct socket *sock, + int lvl, int opt, char __user *ov, int *ol) { struct tipc_sock *tsock = tipc_sk(sock->sk); int len; -- cgit v1.2.3-70-g09d2 From 6b384de853c9f05e5e6da6c95edb475b96dd2cc1 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:44:27 -0700 Subject: [TIPC]: Fixed connect() to detect a dest address that is missing or too short. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 0923213fc6a..758b2d2d2f9 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1244,7 +1244,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, if (sock->state != SS_UNCONNECTED) return -EISCONN; - if ((dst->family != AF_TIPC) || + if ((destlen < sizeof(*dst)) || (dst->family != AF_TIPC) || ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) return -EINVAL; -- cgit v1.2.3-70-g09d2 From 3388007bc4d662e50c2c01a7fb1fa2c31cea98ad Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:44:57 -0700 Subject: [TIPC]: Implied connect now saves dest name for retrieval as ancillary data. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 758b2d2d2f9..98550b90a73 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -470,6 +470,10 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, if ((tsock->p->published) || ((sock->type == SOCK_STREAM) && (total_len != 0))) return -EOPNOTSUPP; + if (dest->addrtype == TIPC_ADDR_NAME) { + tsock->p->conn_type = dest->addr.name.name.type; + tsock->p->conn_instance = dest->addr.name.name.instance; + } } if (down_interruptible(&tsock->sem)) @@ -1269,10 +1273,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, msg = buf_msg(buf); res = auto_connect(sock, tsock, msg); if (!res) { - if (dst->addrtype == TIPC_ADDR_NAME) { - tsock->p->conn_type = dst->addr.name.name.type; - tsock->p->conn_instance = dst->addr.name.name.instance; - } if (!msg_data_sz(msg)) advance_queue(tsock); } -- cgit v1.2.3-70-g09d2 From 3546c7508d7e97fd855f8ac37afdd09622fa5ce1 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:45:24 -0700 Subject: [TIPC]: Can now return destination name of form {0,x,y} via ancillary data. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 98550b90a73..361dc342f37 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -731,6 +731,7 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, u32 anc_data[3]; u32 err; u32 dest_type; + int has_name; int res; if (likely(m->msg_controllen == 0)) @@ -755,24 +756,27 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; switch (dest_type) { case TIPC_NAMED_MSG: + has_name = 1; anc_data[0] = msg_nametype(msg); anc_data[1] = msg_namelower(msg); anc_data[2] = msg_namelower(msg); break; case TIPC_MCAST_MSG: + has_name = 1; anc_data[0] = msg_nametype(msg); anc_data[1] = msg_namelower(msg); anc_data[2] = msg_nameupper(msg); break; case TIPC_CONN_MSG: + has_name = (tport->conn_type != 0); anc_data[0] = tport->conn_type; anc_data[1] = tport->conn_instance; anc_data[2] = tport->conn_instance; break; default: - anc_data[0] = 0; + has_name = 0; } - if (anc_data[0] && + if (has_name && (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) return res; -- cgit v1.2.3-70-g09d2 From bdd94789d2348e20d13c1d5e477c8cf830dd204b Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:45:53 -0700 Subject: [TIPC]: Connected send now checks socket state when retrying congested send. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 361dc342f37..9c834fc3011 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -565,15 +565,15 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, return -ERESTARTSYS; } - if (unlikely(sock->state != SS_CONNECTED)) { - if (sock->state == SS_DISCONNECTING) - res = -EPIPE; - else - res = -ENOTCONN; - goto exit; - } - do { + if (unlikely(sock->state != SS_CONNECTED)) { + if (sock->state == SS_DISCONNECTING) + res = -EPIPE; + else + res = -ENOTCONN; + goto exit; + } + res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); if (likely(res != -ELINKCONG)) { exit: -- cgit v1.2.3-70-g09d2 From 1303e8f173a8a5000ee6e2fba876fec9474ed1f6 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:46:50 -0700 Subject: [TIPC]: Stream socket send indicates partial success if data partially sent. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 9c834fc3011..8cefacb55aa 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -601,7 +601,8 @@ exit: * * Used for SOCK_STREAM data. * - * Returns the number of bytes sent on success, or errno otherwise + * Returns the number of bytes sent on success (or partial success), + * or errno if no data sent */ @@ -615,6 +616,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, char __user *curr_start; int curr_left; int bytes_to_send; + int bytes_sent; int res; if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) @@ -637,11 +639,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, * of small iovec entries into send_packet(). */ - my_msg = *m; - curr_iov = my_msg.msg_iov; - curr_iovlen = my_msg.msg_iovlen; + curr_iov = m->msg_iov; + curr_iovlen = m->msg_iovlen; my_msg.msg_iov = &my_iov; my_msg.msg_iovlen = 1; + bytes_sent = 0; while (curr_iovlen--) { curr_start = curr_iov->iov_base; @@ -652,16 +654,18 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, ? curr_left : TIPC_MAX_USER_MSG_SIZE; my_iov.iov_base = curr_start; my_iov.iov_len = bytes_to_send; - if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) - return res; + if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { + return bytes_sent ? bytes_sent : res; + } curr_left -= bytes_to_send; curr_start += bytes_to_send; + bytes_sent += bytes_to_send; } curr_iov++; } - return total_len; + return bytes_sent; } /** -- cgit v1.2.3-70-g09d2 From 499786516fc12791223f075d682a45ea1129eb04 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:47:18 -0700 Subject: [TIPC]: Improved performance of error checking during socket creation. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 8cefacb55aa..a1f22100a61 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -169,12 +169,6 @@ static int tipc_create(struct socket *sock, int protocol) struct sock *sk; u32 ref; - if ((sock->type != SOCK_STREAM) && - (sock->type != SOCK_SEQPACKET) && - (sock->type != SOCK_DGRAM) && - (sock->type != SOCK_RDM)) - return -EPROTOTYPE; - if (unlikely(protocol != 0)) return -EPROTONOSUPPORT; @@ -199,6 +193,9 @@ static int tipc_create(struct socket *sock, int protocol) sock->ops = &msg_ops; sock->state = SS_READY; break; + default: + tipc_deleteport(ref); + return -EPROTOTYPE; } sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); -- cgit v1.2.3-70-g09d2 From 4b087b28a629cc9388e42fdccdcd929deaa7ac81 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:47:44 -0700 Subject: [TIPC]: recvmsg() now returns TIPC ancillary data using correct level (SOL_TIPC) Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index a1f22100a61..abecf2d422f 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -744,10 +744,10 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, if (unlikely(err)) { anc_data[0] = err; anc_data[1] = msg_data_sz(msg); - if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) + if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data))) return res; if (anc_data[1] && - (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], + (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], msg_data(msg)))) return res; } @@ -778,7 +778,7 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, has_name = 0; } if (has_name && - (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) + (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data))) return res; return 0; -- cgit v1.2.3-70-g09d2 From a3b0a5a9d004002a9cf9cf7a9d10cf1447a73d2b Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:48:22 -0700 Subject: [TIPC]: Simplify code for returning partial success of stream send request. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index abecf2d422f..6d4d2b0063a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -969,7 +969,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, restart: if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && (flags & MSG_DONTWAIT))) { - res = (sz_copied == 0) ? -EWOULDBLOCK : 0; + res = -EWOULDBLOCK; goto exit; } @@ -1060,7 +1060,7 @@ restart: exit: up(&tsock->sem); - return res ? res : sz_copied; + return sz_copied ? sz_copied : res; } /** -- cgit v1.2.3-70-g09d2 From 51f9cc1ff8aa0866ff8fb3c06be4c64b5edbb2e8 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Sun, 25 Jun 2006 23:49:06 -0700 Subject: [TIPC]: Optimized argument validation done by connect(). Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller --- net/tipc/socket.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'net/tipc/socket.c') diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 6d4d2b0063a..32d778448a0 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -455,7 +455,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, if (unlikely(!dest)) return -EDESTADDRREQ; - if (unlikely(dest->family != AF_TIPC)) + if (unlikely((m->msg_namelen < sizeof(*dest)) || + (dest->family != AF_TIPC))) return -EINVAL; needs_conn = (sock->state != SS_READY); @@ -1245,7 +1246,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, if (sock->state == SS_READY) return -EOPNOTSUPP; - /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ + /* Issue Posix-compliant error code if socket is in the wrong state */ + if (sock->state == SS_LISTENING) return -EOPNOTSUPP; if (sock->state == SS_CONNECTING) @@ -1253,13 +1255,20 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, if (sock->state != SS_UNCONNECTED) return -EISCONN; - if ((destlen < sizeof(*dst)) || (dst->family != AF_TIPC) || - ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) + /* + * Reject connection attempt using multicast address + * + * Note: send_msg() validates the rest of the address fields, + * so there's no need to do it here + */ + + if (dst->addrtype == TIPC_ADDR_MCAST) return -EINVAL; /* Send a 'SYN-' to destination */ m.msg_name = dest; + m.msg_namelen = destlen; if ((res = send_msg(NULL, sock, &m, 0)) < 0) { sock->state = SS_DISCONNECTING; return res; -- cgit v1.2.3-70-g09d2