Commit 58a9d732 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by David S. Miller

net/irda: push BKL into proto_ops

The irda driver uses the BKL implicitly in its protocol
operations. Replace the wrapped proto_ops with explicit
lock_kernel() calls makes the usage more obvious and
shrinks the size of the object code.

The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out

The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out
which data actually needs protection.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 83927ba0
...@@ -714,11 +714,14 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -714,11 +714,14 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_irda saddr; struct sockaddr_irda saddr;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk); struct irda_sock *self = irda_sk(sk);
int err;
lock_kernel();
memset(&saddr, 0, sizeof(saddr)); memset(&saddr, 0, sizeof(saddr));
if (peer) { if (peer) {
err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED) if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN; goto out;
saddr.sir_family = AF_IRDA; saddr.sir_family = AF_IRDA;
saddr.sir_lsap_sel = self->dtsap_sel; saddr.sir_lsap_sel = self->dtsap_sel;
...@@ -735,8 +738,10 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -735,8 +738,10 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
/* uaddr_len come to us uninitialised */ /* uaddr_len come to us uninitialised */
*uaddr_len = sizeof (struct sockaddr_irda); *uaddr_len = sizeof (struct sockaddr_irda);
memcpy(uaddr, &saddr, *uaddr_len); memcpy(uaddr, &saddr, *uaddr_len);
err = 0;
return 0; out:
unlock_kernel();
return err;
} }
/* /*
...@@ -748,21 +753,25 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -748,21 +753,25 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
static int irda_listen(struct socket *sock, int backlog) static int irda_listen(struct socket *sock, int backlog)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err = -EOPNOTSUPP;
IRDA_DEBUG(2, "%s()\n", __func__); IRDA_DEBUG(2, "%s()\n", __func__);
lock_kernel();
if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
(sk->sk_type != SOCK_DGRAM)) (sk->sk_type != SOCK_DGRAM))
return -EOPNOTSUPP; goto out;
if (sk->sk_state != TCP_LISTEN) { if (sk->sk_state != TCP_LISTEN) {
sk->sk_max_ack_backlog = backlog; sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN; sk->sk_state = TCP_LISTEN;
return 0; err = 0;
} }
out:
unlock_kernel();
return -EOPNOTSUPP; return err;
} }
/* /*
...@@ -783,36 +792,40 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -783,36 +792,40 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr_len != sizeof(struct sockaddr_irda)) if (addr_len != sizeof(struct sockaddr_irda))
return -EINVAL; return -EINVAL;
lock_kernel();
#ifdef CONFIG_IRDA_ULTRA #ifdef CONFIG_IRDA_ULTRA
/* Special care for Ultra sockets */ /* Special care for Ultra sockets */
if ((sk->sk_type == SOCK_DGRAM) && if ((sk->sk_type == SOCK_DGRAM) &&
(sk->sk_protocol == IRDAPROTO_ULTRA)) { (sk->sk_protocol == IRDAPROTO_ULTRA)) {
self->pid = addr->sir_lsap_sel; self->pid = addr->sir_lsap_sel;
err = -EOPNOTSUPP;
if (self->pid & 0x80) { if (self->pid & 0x80) {
IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
return -EOPNOTSUPP; goto out;
} }
err = irda_open_lsap(self, self->pid); err = irda_open_lsap(self, self->pid);
if (err < 0) if (err < 0)
return err; goto out;
/* Pretend we are connected */ /* Pretend we are connected */
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED; sk->sk_state = TCP_ESTABLISHED;
err = 0;
return 0; goto out;
} }
#endif /* CONFIG_IRDA_ULTRA */ #endif /* CONFIG_IRDA_ULTRA */
self->ias_obj = irias_new_object(addr->sir_name, jiffies); self->ias_obj = irias_new_object(addr->sir_name, jiffies);
err = -ENOMEM;
if (self->ias_obj == NULL) if (self->ias_obj == NULL)
return -ENOMEM; goto out;
err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
if (err < 0) { if (err < 0) {
kfree(self->ias_obj->name); kfree(self->ias_obj->name);
kfree(self->ias_obj); kfree(self->ias_obj);
return err; goto out;
} }
/* Register with LM-IAS */ /* Register with LM-IAS */
...@@ -820,7 +833,10 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -820,7 +833,10 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
self->stsap_sel, IAS_KERNEL_ATTR); self->stsap_sel, IAS_KERNEL_ATTR);
irias_insert_object(self->ias_obj); irias_insert_object(self->ias_obj);
return 0; err = 0;
out:
unlock_kernel();
return err;
} }
/* /*
...@@ -839,22 +855,26 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -839,22 +855,26 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
IRDA_DEBUG(2, "%s()\n", __func__); IRDA_DEBUG(2, "%s()\n", __func__);
lock_kernel();
err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0);
if (err) if (err)
return err; goto out;
err = -EINVAL;
if (sock->state != SS_UNCONNECTED) if (sock->state != SS_UNCONNECTED)
return -EINVAL; goto out;
if ((sk = sock->sk) == NULL) if ((sk = sock->sk) == NULL)
return -EINVAL; goto out;
err = -EOPNOTSUPP;
if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
(sk->sk_type != SOCK_DGRAM)) (sk->sk_type != SOCK_DGRAM))
return -EOPNOTSUPP; goto out;
err = -EINVAL;
if (sk->sk_state != TCP_LISTEN) if (sk->sk_state != TCP_LISTEN)
return -EINVAL; goto out;
/* /*
* The read queue this time is holding sockets ready to use * The read queue this time is holding sockets ready to use
...@@ -875,18 +895,20 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -875,18 +895,20 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
break; break;
/* Non blocking operation */ /* Non blocking operation */
err = -EWOULDBLOCK;
if (flags & O_NONBLOCK) if (flags & O_NONBLOCK)
return -EWOULDBLOCK; goto out;
err = wait_event_interruptible(*(sk->sk_sleep), err = wait_event_interruptible(*(sk->sk_sleep),
skb_peek(&sk->sk_receive_queue)); skb_peek(&sk->sk_receive_queue));
if (err) if (err)
return err; goto out;
} }
newsk = newsock->sk; newsk = newsock->sk;
err = -EIO;
if (newsk == NULL) if (newsk == NULL)
return -EIO; goto out;
newsk->sk_state = TCP_ESTABLISHED; newsk->sk_state = TCP_ESTABLISHED;
...@@ -894,10 +916,11 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -894,10 +916,11 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
/* Now attach up the new socket */ /* Now attach up the new socket */
new->tsap = irttp_dup(self->tsap, new); new->tsap = irttp_dup(self->tsap, new);
err = -EPERM; /* value does not seem to make sense. -arnd */
if (!new->tsap) { if (!new->tsap) {
IRDA_DEBUG(0, "%s(), dup failed!\n", __func__); IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
kfree_skb(skb); kfree_skb(skb);
return -1; goto out;
} }
new->stsap_sel = new->tsap->stsap_sel; new->stsap_sel = new->tsap->stsap_sel;
...@@ -921,8 +944,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -921,8 +944,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
newsock->state = SS_CONNECTED; newsock->state = SS_CONNECTED;
irda_connect_response(new); irda_connect_response(new);
err = 0;
return 0; out:
unlock_kernel();
return err;
} }
/* /*
...@@ -955,28 +980,34 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -955,28 +980,34 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
IRDA_DEBUG(2, "%s(%p)\n", __func__, self); IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
lock_kernel();
/* Don't allow connect for Ultra sockets */ /* Don't allow connect for Ultra sockets */
err = -ESOCKTNOSUPPORT;
if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
return -ESOCKTNOSUPPORT; goto out;
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
return 0; /* Connect completed during a ERESTARTSYS event */ err = 0;
goto out; /* Connect completed during a ERESTARTSYS event */
} }
if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
return -ECONNREFUSED; err = -ECONNREFUSED;
goto out;
} }
err = -EISCONN; /* No reconnect on a seqpacket socket */
if (sk->sk_state == TCP_ESTABLISHED) if (sk->sk_state == TCP_ESTABLISHED)
return -EISCONN; /* No reconnect on a seqpacket socket */ goto out;
sk->sk_state = TCP_CLOSE; sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
err = -EINVAL;
if (addr_len != sizeof(struct sockaddr_irda)) if (addr_len != sizeof(struct sockaddr_irda))
return -EINVAL; goto out;
/* Check if user supplied any destination device address */ /* Check if user supplied any destination device address */
if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) { if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) {
...@@ -984,7 +1015,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -984,7 +1015,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name); err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
if (err) { if (err) {
IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__); IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__);
return err; goto out;
} }
} else { } else {
/* Use the one provided by the user */ /* Use the one provided by the user */
...@@ -1000,7 +1031,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -1000,7 +1031,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
err = irda_find_lsap_sel(self, addr->sir_name); err = irda_find_lsap_sel(self, addr->sir_name);
if (err) { if (err) {
IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
return err; goto out;
} }
} else { } else {
/* Directly connect to the remote LSAP /* Directly connect to the remote LSAP
...@@ -1025,29 +1056,35 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -1025,29 +1056,35 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
self->max_sdu_size_rx, NULL); self->max_sdu_size_rx, NULL);
if (err) { if (err) {
IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
return err; goto out;
} }
/* Now the loop */ /* Now the loop */
err = -EINPROGRESS;
if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
return -EINPROGRESS; goto out;
err = -ERESTARTSYS;
if (wait_event_interruptible(*(sk->sk_sleep), if (wait_event_interruptible(*(sk->sk_sleep),
(sk->sk_state != TCP_SYN_SENT))) (sk->sk_state != TCP_SYN_SENT)))
return -ERESTARTSYS; goto out;
if (sk->sk_state != TCP_ESTABLISHED) { if (sk->sk_state != TCP_ESTABLISHED) {
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
err = sock_error(sk); err = sock_error(sk);
return err? err : -ECONNRESET; if (!err)
err = -ECONNRESET;
goto out;
} }
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
/* At this point, IrLMP has assigned our source address */ /* At this point, IrLMP has assigned our source address */
self->saddr = irttp_get_saddr(self->tsap); self->saddr = irttp_get_saddr(self->tsap);
err = 0;
return 0; out:
unlock_kernel();
return err;
} }
static struct proto irda_proto = { static struct proto irda_proto = {
...@@ -1193,6 +1230,7 @@ static int irda_release(struct socket *sock) ...@@ -1193,6 +1230,7 @@ static int irda_release(struct socket *sock)
if (sk == NULL) if (sk == NULL)
return 0; return 0;
lock_kernel();
lock_sock(sk); lock_sock(sk);
sk->sk_state = TCP_CLOSE; sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN; sk->sk_shutdown |= SEND_SHUTDOWN;
...@@ -1211,6 +1249,7 @@ static int irda_release(struct socket *sock) ...@@ -1211,6 +1249,7 @@ static int irda_release(struct socket *sock)
/* Destroy networking socket if we are the last reference on it, /* Destroy networking socket if we are the last reference on it,
* i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */
sock_put(sk); sock_put(sk);
unlock_kernel();
/* Notes on socket locking and deallocation... - Jean II /* Notes on socket locking and deallocation... - Jean II
* In theory we should put pairs of sock_hold() / sock_put() to * In theory we should put pairs of sock_hold() / sock_put() to
...@@ -1258,28 +1297,37 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1258,28 +1297,37 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
lock_kernel();
/* Note : socket.c set MSG_EOR on SEQPACKET sockets */ /* Note : socket.c set MSG_EOR on SEQPACKET sockets */
if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
MSG_NOSIGNAL)) MSG_NOSIGNAL)) {
return -EINVAL; err = -EINVAL;
goto out;
}
if (sk->sk_shutdown & SEND_SHUTDOWN) if (sk->sk_shutdown & SEND_SHUTDOWN)
goto out_err; goto out_err;
if (sk->sk_state != TCP_ESTABLISHED) if (sk->sk_state != TCP_ESTABLISHED) {
return -ENOTCONN; err = -ENOTCONN;
goto out;
}
self = irda_sk(sk); self = irda_sk(sk);
/* Check if IrTTP is wants us to slow down */ /* Check if IrTTP is wants us to slow down */
if (wait_event_interruptible(*(sk->sk_sleep), if (wait_event_interruptible(*(sk->sk_sleep),
(self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) {
return -ERESTARTSYS; err = -ERESTARTSYS;
goto out;
}
/* Check if we are still connected */ /* Check if we are still connected */
if (sk->sk_state != TCP_ESTABLISHED) if (sk->sk_state != TCP_ESTABLISHED) {
return -ENOTCONN; err = -ENOTCONN;
goto out;
}
/* Check that we don't send out too big frames */ /* Check that we don't send out too big frames */
if (len > self->max_data_size) { if (len > self->max_data_size) {
...@@ -1311,11 +1359,16 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1311,11 +1359,16 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
goto out_err; goto out_err;
} }
unlock_kernel();
/* Tell client how much data we actually sent */ /* Tell client how much data we actually sent */
return len; return len;
out_err: out_err:
return sk_stream_error(sk, msg->msg_flags, err); err = sk_stream_error(sk, msg->msg_flags, err);
out:
unlock_kernel();
return err;
} }
...@@ -1336,13 +1389,14 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1336,13 +1389,14 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s()\n", __func__); IRDA_DEBUG(4, "%s()\n", __func__);
lock_kernel();
if ((err = sock_error(sk)) < 0) if ((err = sock_error(sk)) < 0)
return err; goto out;
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err); flags & MSG_DONTWAIT, &err);
if (!skb) if (!skb)
return err; goto out;
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
copied = skb->len; copied = skb->len;
...@@ -1370,8 +1424,12 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1370,8 +1424,12 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
irttp_flow_request(self->tsap, FLOW_START); irttp_flow_request(self->tsap, FLOW_START);
} }
} }
unlock_kernel();
return copied; return copied;
out:
unlock_kernel();
return err;
} }
/* /*
...@@ -1389,15 +1447,19 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1389,15 +1447,19 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(3, "%s()\n", __func__); IRDA_DEBUG(3, "%s()\n", __func__);
lock_kernel();
if ((err = sock_error(sk)) < 0) if ((err = sock_error(sk)) < 0)
return err; goto out;
err = -EINVAL;
if (sock->flags & __SO_ACCEPTCON) if (sock->flags & __SO_ACCEPTCON)
return(-EINVAL); goto out;
err =-EOPNOTSUPP;
if (flags & MSG_OOB) if (flags & MSG_OOB)
return -EOPNOTSUPP; goto out;
err = 0;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
timeo = sock_rcvtimeo(sk, noblock); timeo = sock_rcvtimeo(sk, noblock);
...@@ -1409,7 +1471,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1409,7 +1471,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
if (skb == NULL) { if (skb == NULL) {
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
int ret = 0; err = 0;
if (copied >= target) if (copied >= target)
break; break;
...@@ -1419,25 +1481,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1419,25 +1481,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
/* /*
* POSIX 1003.1g mandates this order. * POSIX 1003.1g mandates this order.
*/ */
ret = sock_error(sk); err = sock_error(sk);
if (ret) if (err)
; ;
else if (sk->sk_shutdown & RCV_SHUTDOWN) else if (sk->sk_shutdown & RCV_SHUTDOWN)
; ;
else if (noblock) else if (noblock)
ret = -EAGAIN; err = -EAGAIN;
else if (signal_pending(current)) else if (signal_pending(current))
ret = sock_intr_errno(timeo); err = sock_intr_errno(timeo);
else if (sk->sk_state != TCP_ESTABLISHED) else if (sk->sk_state != TCP_ESTABLISHED)
ret = -ENOTCONN; err = -ENOTCONN;
else if (skb_peek(&sk->sk_receive_queue) == NULL) else if (skb_peek(&sk->sk_receive_queue) == NULL)
/* Wait process until data arrives */ /* Wait process until data arrives */
schedule(); schedule();
finish_wait(sk->sk_sleep, &wait); finish_wait(sk->sk_sleep, &wait);
if (ret) if (err)
return ret; goto out;
if (sk->sk_shutdown & RCV_SHUTDOWN) if (sk->sk_shutdown & RCV_SHUTDOWN)
break; break;
...@@ -1490,7 +1552,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1490,7 +1552,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
} }
} }
return copied; out:
unlock_kernel();
return err ? : copied;
} }
/* /*
...@@ -1508,18 +1572,23 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1508,18 +1572,23 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
lock_kernel();
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
err = -EINVAL;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
return -EINVAL; goto out;
if (sk->sk_shutdown & SEND_SHUTDOWN) { if (sk->sk_shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0); send_sig(SIGPIPE, current, 0);
return -EPIPE; err = -EPIPE;
goto out;
} }
err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED) if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN; goto out;
self = irda_sk(sk); self = irda_sk(sk);
...@@ -1536,8 +1605,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1536,8 +1605,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
skb = sock_alloc_send_skb(sk, len + self->max_header_size, skb = sock_alloc_send_skb(sk, len + self->max_header_size,
msg->msg_flags & MSG_DONTWAIT, &err); msg->msg_flags & MSG_DONTWAIT, &err);
err = -ENOBUFS;
if (!skb) if (!skb)
return -ENOBUFS; goto out;
skb_reserve(skb, self->max_header_size); skb_reserve(skb, self->max_header_size);
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
...@@ -1547,7 +1617,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1547,7 +1617,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) { if (err) {
kfree_skb(skb); kfree_skb(skb);
return err; goto out;
} }
/* /*
...@@ -1557,9 +1627,13 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1557,9 +1627,13 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
err = irttp_udata_request(self->tsap, skb); err = irttp_udata_request(self->tsap, skb);
if (err) { if (err) {
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
return err; goto out;
} }
unlock_kernel();
return len; return len;
out:
unlock_kernel();
return err;
} }
/* /*
...@@ -1581,12 +1655,15 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, ...@@ -1581,12 +1655,15 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
lock_kernel();
err = -EINVAL;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
return -EINVAL; goto out;
err = -EPIPE;
if (sk->sk_shutdown & SEND_SHUTDOWN) { if (sk->sk_shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0); send_sig(SIGPIPE, current, 0);
return -EPIPE; goto out;
} }
self = irda_sk(sk); self = irda_sk(sk);
...@@ -1594,16 +1671,18 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, ...@@ -1594,16 +1671,18 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
/* Check if an address was specified with sendto. Jean II */ /* Check if an address was specified with sendto. Jean II */
if (msg->msg_name) { if (msg->msg_name) {
struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name;
err = -EINVAL;
/* Check address, extract pid. Jean II */ /* Check address, extract pid. Jean II */
if (msg->msg_namelen < sizeof(*addr)) if (msg->msg_namelen < sizeof(*addr))
return -EINVAL; goto out;
if (addr->sir_family != AF_IRDA) if (addr->sir_family != AF_IRDA)
return -EINVAL; goto out;
pid = addr->sir_lsap_sel; pid = addr->sir_lsap_sel;
if (pid & 0x80) { if (pid & 0x80) {
IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
return -EOPNOTSUPP; err = -EOPNOTSUPP;
goto out;
} }
} else { } else {
/* Check that the socket is properly bound to an Ultra /* Check that the socket is properly bound to an Ultra
...@@ -1612,7 +1691,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, ...@@ -1612,7 +1691,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
(sk->sk_state != TCP_ESTABLISHED)) { (sk->sk_state != TCP_ESTABLISHED)) {
IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n", IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n",
__func__); __func__);
return -ENOTCONN; err = -ENOTCONN;
goto out;
} }
/* Use PID from socket */ /* Use PID from socket */
bound = 1; bound = 1;
...@@ -1631,8 +1711,9 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, ...@@ -1631,8 +1711,9 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
skb = sock_alloc_send_skb(sk, len + self->max_header_size, skb = sock_alloc_send_skb(sk, len + self->max_header_size,
msg->msg_flags & MSG_DONTWAIT, &err); msg->msg_flags & MSG_DONTWAIT, &err);
err = -ENOBUFS;
if (!skb) if (!skb)
return -ENOBUFS; goto out;
skb_reserve(skb, self->max_header_size); skb_reserve(skb, self->max_header_size);
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
...@@ -1642,16 +1723,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, ...@@ -1642,16 +1723,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) { if (err) {
kfree_skb(skb); kfree_skb(skb);
return err; goto out;
} }
err = irlmp_connless_data_request((bound ? self->lsap : NULL), err = irlmp_connless_data_request((bound ? self->lsap : NULL),
skb, pid); skb, pid);
if (err) { if (err)
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
return err; out:
} unlock_kernel();
return len; return err ? : len;
} }
#endif /* CONFIG_IRDA_ULTRA */ #endif /* CONFIG_IRDA_ULTRA */
...@@ -1665,6 +1746,8 @@ static int irda_shutdown(struct socket *sock, int how) ...@@ -1665,6 +1746,8 @@ static int irda_shutdown(struct socket *sock, int how)
IRDA_DEBUG(1, "%s(%p)\n", __func__, self); IRDA_DEBUG(1, "%s(%p)\n", __func__, self);
lock_kernel();
sk->sk_state = TCP_CLOSE; sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN; sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk); sk->sk_state_change(sk);
...@@ -1685,6 +1768,8 @@ static int irda_shutdown(struct socket *sock, int how) ...@@ -1685,6 +1768,8 @@ static int irda_shutdown(struct socket *sock, int how)
self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */
self->saddr = 0x0; /* so IrLMP assign us any link */ self->saddr = 0x0; /* so IrLMP assign us any link */
unlock_kernel();
return 0; return 0;
} }
...@@ -1700,6 +1785,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, ...@@ -1700,6 +1785,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
IRDA_DEBUG(4, "%s()\n", __func__); IRDA_DEBUG(4, "%s()\n", __func__);
lock_kernel();
poll_wait(file, sk->sk_sleep, wait); poll_wait(file, sk->sk_sleep, wait);
mask = 0; mask = 0;
...@@ -1747,18 +1833,34 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, ...@@ -1747,18 +1833,34 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
default: default:
break; break;
} }
unlock_kernel();
return mask; return mask;
} }
static unsigned int irda_datagram_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
int err;
lock_kernel();
err = datagram_poll(file, sock, wait);
unlock_kernel();
return err;
}
/* /*
* Function irda_ioctl (sock, cmd, arg) * Function irda_ioctl (sock, cmd, arg)
*/ */
static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err;
IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);
lock_kernel();
err = -EINVAL;
switch (cmd) { switch (cmd) {
case TIOCOUTQ: { case TIOCOUTQ: {
long amount; long amount;
...@@ -1766,9 +1868,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1766,9 +1868,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
if (amount < 0) if (amount < 0)
amount = 0; amount = 0;
if (put_user(amount, (unsigned int __user *)arg)) err = put_user(amount, (unsigned int __user *)arg);
return -EFAULT; break;
return 0;
} }
case TIOCINQ: { case TIOCINQ: {
...@@ -1777,15 +1878,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1777,15 +1878,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* These two are safe on a single CPU system as only user tasks fiddle here */ /* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
amount = skb->len; amount = skb->len;
if (put_user(amount, (unsigned int __user *)arg)) err = put_user(amount, (unsigned int __user *)arg);
return -EFAULT; break;
return 0;
} }
case SIOCGSTAMP: case SIOCGSTAMP:
if (sk != NULL) if (sk != NULL)
return sock_get_timestamp(sk, (struct timeval __user *)arg); err = sock_get_timestamp(sk, (struct timeval __user *)arg);
return -EINVAL; break;
case SIOCGIFADDR: case SIOCGIFADDR:
case SIOCSIFADDR: case SIOCSIFADDR:
...@@ -1797,14 +1897,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1797,14 +1897,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFNETMASK: case SIOCSIFNETMASK:
case SIOCGIFMETRIC: case SIOCGIFMETRIC:
case SIOCSIFMETRIC: case SIOCSIFMETRIC:
return -EINVAL; break;
default: default:
IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
return -ENOIOCTLCMD; err = -ENOIOCTLCMD;
} }
unlock_kernel();
/*NOTREACHED*/ return err;
return 0;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -1826,7 +1926,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon ...@@ -1826,7 +1926,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
* Set some options for the socket * Set some options for the socket
* *
*/ */
static int irda_setsockopt(struct socket *sock, int level, int optname, static int __irda_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen) char __user *optval, unsigned int optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -2084,6 +2184,18 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, ...@@ -2084,6 +2184,18 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
return 0; return 0;
} }
static int irda_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
int err;
lock_kernel();
err = __irda_setsockopt(sock, level, optname, optval, optlen);
unlock_kernel();
return err;
}
/* /*
* Function irda_extract_ias_value(ias_opt, ias_value) * Function irda_extract_ias_value(ias_opt, ias_value)
* *
...@@ -2136,7 +2248,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt, ...@@ -2136,7 +2248,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt,
/* /*
* Function irda_getsockopt (sock, level, optname, optval, optlen) * Function irda_getsockopt (sock, level, optname, optval, optlen)
*/ */
static int irda_getsockopt(struct socket *sock, int level, int optname, static int __irda_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen) char __user *optval, int __user *optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -2464,13 +2576,25 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, ...@@ -2464,13 +2576,25 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
return 0; return 0;
} }
static int irda_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
int err;
lock_kernel();
err = __irda_getsockopt(sock, level, optname, optval, optlen);
unlock_kernel();
return err;
}
static const struct net_proto_family irda_family_ops = { static const struct net_proto_family irda_family_ops = {
.family = PF_IRDA, .family = PF_IRDA,
.create = irda_create, .create = irda_create,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { static const struct proto_ops irda_stream_ops = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
...@@ -2494,7 +2618,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { ...@@ -2494,7 +2618,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.sendpage = sock_no_sendpage, .sendpage = sock_no_sendpage,
}; };
static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { static const struct proto_ops irda_seqpacket_ops = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
...@@ -2503,7 +2627,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { ...@@ -2503,7 +2627,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
.accept = irda_accept, .accept = irda_accept,
.getname = irda_getname, .getname = irda_getname,
.poll = datagram_poll, .poll = irda_datagram_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl, .compat_ioctl = irda_compat_ioctl,
...@@ -2518,7 +2642,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { ...@@ -2518,7 +2642,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.sendpage = sock_no_sendpage, .sendpage = sock_no_sendpage,
}; };
static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { static const struct proto_ops irda_dgram_ops = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
...@@ -2527,7 +2651,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { ...@@ -2527,7 +2651,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
.accept = irda_accept, .accept = irda_accept,
.getname = irda_getname, .getname = irda_getname,
.poll = datagram_poll, .poll = irda_datagram_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl, .compat_ioctl = irda_compat_ioctl,
...@@ -2543,7 +2667,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { ...@@ -2543,7 +2667,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
}; };
#ifdef CONFIG_IRDA_ULTRA #ifdef CONFIG_IRDA_ULTRA
static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { static const struct proto_ops irda_ultra_ops = {
.family = PF_IRDA, .family = PF_IRDA,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.release = irda_release, .release = irda_release,
...@@ -2552,7 +2676,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { ...@@ -2552,7 +2676,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
.accept = sock_no_accept, .accept = sock_no_accept,
.getname = irda_getname, .getname = irda_getname,
.poll = datagram_poll, .poll = irda_datagram_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl, .compat_ioctl = irda_compat_ioctl,
...@@ -2568,13 +2692,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { ...@@ -2568,13 +2692,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
}; };
#endif /* CONFIG_IRDA_ULTRA */ #endif /* CONFIG_IRDA_ULTRA */
SOCKOPS_WRAP(irda_stream, PF_IRDA);
SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
SOCKOPS_WRAP(irda_dgram, PF_IRDA);
#ifdef CONFIG_IRDA_ULTRA
SOCKOPS_WRAP(irda_ultra, PF_IRDA);
#endif /* CONFIG_IRDA_ULTRA */
/* /*
* Function irsock_init (pro) * Function irsock_init (pro)
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment