summaryrefslogtreecommitdiffstats
path: root/net/x25
diff options
context:
space:
mode:
Diffstat (limited to 'net/x25')
-rw-r--r--net/x25/af_x25.c41
-rw-r--r--net/x25/x25_dev.c6
-rw-r--r--net/x25/x25_link.c6
-rw-r--r--net/x25/x25_out.c13
4 files changed, 35 insertions, 31 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index ebaaa7242..9af3a0e3d 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -20,6 +20,9 @@
* 2000-22-03 Daniela Squassoni Allowed disabling/enabling of
* facilities negotiation and increased
* the throughput upper limit.
+ * 2000-27-08 Arnaldo C. Melo s/suser/capable/ + micro cleanups
+ * 2000-04-09 Henner Eisen Set sock->state in x25_accept().
+ * Fixed x25_output() related skb leakage.
*/
#include <linux/config.h>
@@ -402,10 +405,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
if (put_user(len, optlen))
return -EFAULT;
- if (copy_to_user(optval, &val, len))
- return -EFAULT;
-
- return 0;
+ return copy_to_user(optval, &val, len) ? -EFAULT : 0;
}
static int x25_listen(struct socket *sock, int backlog)
@@ -723,6 +723,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
kfree_skb(skb);
sk->ack_backlog--;
newsock->sk = newsk;
+ newsock->state = SS_CONNECTED;
return 0;
}
@@ -973,7 +974,11 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
if (msg->msg_flags & MSG_OOB) {
skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb);
} else {
- x25_output(sk, skb);
+ err = x25_output(sk, skb);
+ if(err){
+ len = err;
+ kfree_skb(skb);
+ }
}
x25_kick(sk);
@@ -1067,9 +1072,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
- if (put_user(amount, (unsigned int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (unsigned int *)arg);
}
case TIOCINQ: {
@@ -1078,18 +1081,14 @@ static int x25_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 */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (unsigned int *)arg))
- return -EFAULT;
- return 0;
+ return put_user(amount, (unsigned int *)arg);
}
case SIOCGSTAMP:
if (sk != NULL) {
if (sk->stamp.tv_sec == 0)
return -ENOENT;
- if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
}
return -EINVAL;
@@ -1114,15 +1113,13 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return x25_subscr_ioctl(cmd, (void *)arg);
case SIOCX25SSUBSCRIP:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
return x25_subscr_ioctl(cmd, (void *)arg);
case SIOCX25GFACILITIES: {
struct x25_facilities facilities;
facilities = sk->protinfo.x25->facilities;
- if (copy_to_user((void *)arg, &facilities, sizeof(facilities)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0;
}
case SIOCX25SFACILITIES: {
@@ -1148,9 +1145,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCX25GCALLUSERDATA: {
struct x25_calluserdata calluserdata;
calluserdata = sk->protinfo.x25->calluserdata;
- if (copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0;
}
case SIOCX25SCALLUSERDATA: {
@@ -1166,9 +1161,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCX25GCAUSEDIAG: {
struct x25_causediag causediag;
causediag = sk->protinfo.x25->causediag;
- if (copy_to_user((void *)arg, &causediag, sizeof(causediag)))
- return -EFAULT;
- return 0;
+ return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0;
}
default:
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 1808361a6..d986022fb 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -14,6 +14,7 @@
*
* History
* X.25 001 Jonathan Naylor Started coding.
+ * 2000-09-04 Henner Eisen Prevent freeing a dangling skb.
*/
#include <linux/config.h>
@@ -78,12 +79,13 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
return x25_rx_call_request(skb, neigh, lci);
/*
- * Its not a Call Request, nor is it a control frame, throw it awa
+ * Its not a Call Request, nor is it a control frame.
+ * Let caller throw it away.
*/
/*
x25_transmit_clear_request(neigh, lci, 0x0D);
*/
- kfree_skb(skb);
+ printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x\n",frametype);
return 0;
}
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 34d065b83..d6b878371 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -17,6 +17,7 @@
* X.25 002 Jonathan Naylor New timer architecture.
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation.
+ * 2000-09-04 Henner Eisen dev_hold() / dev_put() for x25_neigh.
*/
#include <linux/config.h>
@@ -292,6 +293,7 @@ void x25_link_device_up(struct net_device *dev)
init_timer(&x25_neigh->t20timer);
+ dev_hold(dev);
x25_neigh->dev = dev;
x25_neigh->state = X25_LINK_STATE_0;
x25_neigh->extended = 0;
@@ -349,8 +351,10 @@ void x25_link_device_down(struct net_device *dev)
neigh = x25_neigh;
x25_neigh = x25_neigh->next;
- if (neigh->dev == dev)
+ if (neigh->dev == dev){
x25_remove_neigh(neigh);
+ dev_put(dev);
+ }
}
}
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index 24fdf4d47..077f2c0b4 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -15,6 +15,7 @@
* History
* X.25 001 Jonathan Naylor Started coding.
* X.25 002 Jonathan Naylor New timer architecture.
+ * 2000-09-04 Henner Eisen Prevented x25_output() skb leakage.
*/
#include <linux/config.h>
@@ -56,7 +57,7 @@ static int x25_pacsize_to_bytes(unsigned int pacsize)
/*
* This is where all X.25 information frames pass;
*/
-void x25_output(struct sock *sk, struct sk_buff *skb)
+int x25_output(struct sock *sk, struct sk_buff *skb)
{
struct sk_buff *skbn;
unsigned char header[X25_EXT_MIN_LEN];
@@ -73,9 +74,12 @@ void x25_output(struct sock *sk, struct sk_buff *skb)
frontlen = skb_headroom(skb);
while (skb->len > 0) {
- if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL)
- return;
-
+ if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL){
+ int unsent = skb->len - header_len;
+ SOCK_DEBUG(sk, "x25_output: framgent allocation failed, err=%d, %d bytes unsent\n", err, unsent);
+ return err;
+ }
+
skb_reserve(skbn, frontlen);
len = (max_len > skb->len) ? skb->len : max_len;
@@ -102,6 +106,7 @@ void x25_output(struct sock *sk, struct sk_buff *skb)
} else {
skb_queue_tail(&sk->write_queue, skb);
}
+ return 0;
}
/*