diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index d30615419b4d..5f03e4ea65bf 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -91,7 +91,7 @@ int x25_parse_address_block(struct sk_buff *skb, | |||
91 | int needed; | 91 | int needed; |
92 | int rc; | 92 | int rc; |
93 | 93 | ||
94 | if (skb->len < 1) { | 94 | if (!pskb_may_pull(skb, 1)) { |
95 | /* packet has no address block */ | 95 | /* packet has no address block */ |
96 | rc = 0; | 96 | rc = 0; |
97 | goto empty; | 97 | goto empty; |
@@ -100,7 +100,7 @@ int x25_parse_address_block(struct sk_buff *skb, | |||
100 | len = *skb->data; | 100 | len = *skb->data; |
101 | needed = 1 + (len >> 4) + (len & 0x0f); | 101 | needed = 1 + (len >> 4) + (len & 0x0f); |
102 | 102 | ||
103 | if (skb->len < needed) { | 103 | if (!pskb_may_pull(skb, needed)) { |
104 | /* packet is too short to hold the addresses it claims | 104 | /* packet is too short to hold the addresses it claims |
105 | to hold */ | 105 | to hold */ |
106 | rc = -1; | 106 | rc = -1; |
@@ -295,7 +295,8 @@ static struct sock *x25_find_listener(struct x25_address *addr, | |||
295 | * Found a listening socket, now check the incoming | 295 | * Found a listening socket, now check the incoming |
296 | * call user data vs this sockets call user data | 296 | * call user data vs this sockets call user data |
297 | */ | 297 | */ |
298 | if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) { | 298 | if (x25_sk(s)->cudmatchlength > 0 && |
299 | skb->len >= x25_sk(s)->cudmatchlength) { | ||
299 | if((memcmp(x25_sk(s)->calluserdata.cuddata, | 300 | if((memcmp(x25_sk(s)->calluserdata.cuddata, |
300 | skb->data, | 301 | skb->data, |
301 | x25_sk(s)->cudmatchlength)) == 0) { | 302 | x25_sk(s)->cudmatchlength)) == 0) { |
@@ -951,14 +952,27 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
951 | * | 952 | * |
952 | * Facilities length is mandatory in call request packets | 953 | * Facilities length is mandatory in call request packets |
953 | */ | 954 | */ |
954 | if (skb->len < 1) | 955 | if (!pskb_may_pull(skb, 1)) |
955 | goto out_clear_request; | 956 | goto out_clear_request; |
956 | len = skb->data[0] + 1; | 957 | len = skb->data[0] + 1; |
957 | if (skb->len < len) | 958 | if (!pskb_may_pull(skb, len)) |
958 | goto out_clear_request; | 959 | goto out_clear_request; |
959 | skb_pull(skb,len); | 960 | skb_pull(skb,len); |
960 | 961 | ||
961 | /* | 962 | /* |
963 | * Ensure that the amount of call user data is valid. | ||
964 | */ | ||
965 | if (skb->len > X25_MAX_CUD_LEN) | ||
966 | goto out_clear_request; | ||
967 | |||
968 | /* | ||
969 | * Get all the call user data so it can be used in | ||
970 | * x25_find_listener and skb_copy_from_linear_data up ahead. | ||
971 | */ | ||
972 | if (!pskb_may_pull(skb, skb->len)) | ||
973 | goto out_clear_request; | ||
974 | |||
975 | /* | ||
962 | * Find a listener for the particular address/cud pair. | 976 | * Find a listener for the particular address/cud pair. |
963 | */ | 977 | */ |
964 | sk = x25_find_listener(&source_addr,skb); | 978 | sk = x25_find_listener(&source_addr,skb); |
@@ -1166,6 +1180,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1166 | * byte of the user data is the logical value of the Q Bit. | 1180 | * byte of the user data is the logical value of the Q Bit. |
1167 | */ | 1181 | */ |
1168 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { | 1182 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1183 | if (!pskb_may_pull(skb, 1)) | ||
1184 | goto out_kfree_skb; | ||
1185 | |||
1169 | qbit = skb->data[0]; | 1186 | qbit = skb->data[0]; |
1170 | skb_pull(skb, 1); | 1187 | skb_pull(skb, 1); |
1171 | } | 1188 | } |
@@ -1244,7 +1261,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1244 | struct x25_sock *x25 = x25_sk(sk); | 1261 | struct x25_sock *x25 = x25_sk(sk); |
1245 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; | 1262 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name; |
1246 | size_t copied; | 1263 | size_t copied; |
1247 | int qbit; | 1264 | int qbit, header_len = x25->neighbour->extended ? |
1265 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN; | ||
1266 | |||
1248 | struct sk_buff *skb; | 1267 | struct sk_buff *skb; |
1249 | unsigned char *asmptr; | 1268 | unsigned char *asmptr; |
1250 | int rc = -ENOTCONN; | 1269 | int rc = -ENOTCONN; |
@@ -1265,6 +1284,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1265 | 1284 | ||
1266 | skb = skb_dequeue(&x25->interrupt_in_queue); | 1285 | skb = skb_dequeue(&x25->interrupt_in_queue); |
1267 | 1286 | ||
1287 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
1288 | goto out_free_dgram; | ||
1289 | |||
1268 | skb_pull(skb, X25_STD_MIN_LEN); | 1290 | skb_pull(skb, X25_STD_MIN_LEN); |
1269 | 1291 | ||
1270 | /* | 1292 | /* |
@@ -1285,10 +1307,12 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1285 | if (!skb) | 1307 | if (!skb) |
1286 | goto out; | 1308 | goto out; |
1287 | 1309 | ||
1310 | if (!pskb_may_pull(skb, header_len)) | ||
1311 | goto out_free_dgram; | ||
1312 | |||
1288 | qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; | 1313 | qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT; |
1289 | 1314 | ||
1290 | skb_pull(skb, x25->neighbour->extended ? | 1315 | skb_pull(skb, header_len); |
1291 | X25_EXT_MIN_LEN : X25_STD_MIN_LEN); | ||
1292 | 1316 | ||
1293 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { | 1317 | if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) { |
1294 | asmptr = skb_push(skb, 1); | 1318 | asmptr = skb_push(skb, 1); |