diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_if.c | 6 | ||||
-rw-r--r-- | net/bridge/br_private.h | 2 | ||||
-rw-r--r-- | net/bridge/br_stp_if.c | 9 | ||||
-rw-r--r-- | net/can/af_can.c | 9 | ||||
-rw-r--r-- | net/can/bcm.c | 4 | ||||
-rw-r--r-- | net/can/raw.c | 4 | ||||
-rw-r--r-- | net/core/dev.c | 55 | ||||
-rw-r--r-- | net/core/ethtool.c | 17 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_options.c | 6 | ||||
-rw-r--r-- | net/ipv4/raw.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 2 | ||||
-rw-r--r-- | net/irda/iriap.c | 6 | ||||
-rw-r--r-- | net/irda/irnet/irnet_ppp.c | 3 | ||||
-rw-r--r-- | net/rose/af_rose.c | 8 | ||||
-rw-r--r-- | net/rose/rose_loopback.c | 13 | ||||
-rw-r--r-- | net/rose/rose_route.c | 20 | ||||
-rw-r--r-- | net/rose/rose_subr.c | 101 | ||||
-rw-r--r-- | net/xfrm/xfrm_input.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_replay.c | 17 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 6 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 24 |
23 files changed, 201 insertions, 124 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index dce8f0009a12..718b60366dfe 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
389 | { | 389 | { |
390 | struct net_bridge_port *p; | 390 | struct net_bridge_port *p; |
391 | int err = 0; | 391 | int err = 0; |
392 | bool changed_addr; | ||
392 | 393 | ||
393 | /* Don't allow bridging non-ethernet like devices */ | 394 | /* Don't allow bridging non-ethernet like devices */ |
394 | if ((dev->flags & IFF_LOOPBACK) || | 395 | if ((dev->flags & IFF_LOOPBACK) || |
@@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
446 | list_add_rcu(&p->list, &br->port_list); | 447 | list_add_rcu(&p->list, &br->port_list); |
447 | 448 | ||
448 | spin_lock_bh(&br->lock); | 449 | spin_lock_bh(&br->lock); |
449 | br_stp_recalculate_bridge_id(br); | 450 | changed_addr = br_stp_recalculate_bridge_id(br); |
450 | br_features_recompute(br); | 451 | br_features_recompute(br); |
451 | 452 | ||
452 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 453 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
@@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
456 | 457 | ||
457 | br_ifinfo_notify(RTM_NEWLINK, p); | 458 | br_ifinfo_notify(RTM_NEWLINK, p); |
458 | 459 | ||
460 | if (changed_addr) | ||
461 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
462 | |||
459 | dev_set_mtu(br->dev, br_min_mtu(br)); | 463 | dev_set_mtu(br->dev, br_min_mtu(br)); |
460 | 464 | ||
461 | kobject_uevent(&p->kobj, KOBJ_ADD); | 465 | kobject_uevent(&p->kobj, KOBJ_ADD); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 19e2f46ed086..387013d33745 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br); | |||
497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); | 497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); |
498 | extern void br_stp_enable_port(struct net_bridge_port *p); | 498 | extern void br_stp_enable_port(struct net_bridge_port *p); |
499 | extern void br_stp_disable_port(struct net_bridge_port *p); | 499 | extern void br_stp_disable_port(struct net_bridge_port *p); |
500 | extern void br_stp_recalculate_bridge_id(struct net_bridge *br); | 500 | extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); |
501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); | 501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); |
502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, | 502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, |
503 | u16 newprio); | 503 | u16 newprio); |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 79372d4a4055..5593f5aec942 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | 204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; |
205 | 205 | ||
206 | /* called under bridge lock */ | 206 | /* called under bridge lock */ |
207 | void br_stp_recalculate_bridge_id(struct net_bridge *br) | 207 | bool br_stp_recalculate_bridge_id(struct net_bridge *br) |
208 | { | 208 | { |
209 | const unsigned char *br_mac_zero = | 209 | const unsigned char *br_mac_zero = |
210 | (const unsigned char *)br_mac_zero_aligned; | 210 | (const unsigned char *)br_mac_zero_aligned; |
@@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
222 | 222 | ||
223 | } | 223 | } |
224 | 224 | ||
225 | if (compare_ether_addr(br->bridge_id.addr, addr)) | 225 | if (compare_ether_addr(br->bridge_id.addr, addr) == 0) |
226 | br_stp_change_bridge_id(br, addr); | 226 | return false; /* no change */ |
227 | |||
228 | br_stp_change_bridge_id(br, addr); | ||
229 | return true; | ||
227 | } | 230 | } |
228 | 231 | ||
229 | /* called under bridge lock */ | 232 | /* called under bridge lock */ |
diff --git a/net/can/af_can.c b/net/can/af_can.c index 702be5a2c956..733d66f1b05a 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */ | |||
95 | * af_can socket functions | 95 | * af_can socket functions |
96 | */ | 96 | */ |
97 | 97 | ||
98 | static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 98 | int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
99 | { | 99 | { |
100 | struct sock *sk = sock->sk; | 100 | struct sock *sk = sock->sk; |
101 | 101 | ||
@@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
108 | return -ENOIOCTLCMD; | 108 | return -ENOIOCTLCMD; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | EXPORT_SYMBOL(can_ioctl); | ||
111 | 112 | ||
112 | static void can_sock_destruct(struct sock *sk) | 113 | static void can_sock_destruct(struct sock *sk) |
113 | { | 114 | { |
@@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp) | |||
698 | printk(KERN_ERR "can: protocol %d already registered\n", | 699 | printk(KERN_ERR "can: protocol %d already registered\n", |
699 | proto); | 700 | proto); |
700 | err = -EBUSY; | 701 | err = -EBUSY; |
701 | } else { | 702 | } else |
702 | proto_tab[proto] = cp; | 703 | proto_tab[proto] = cp; |
703 | 704 | ||
704 | /* use generic ioctl function if not defined by module */ | ||
705 | if (!cp->ops->ioctl) | ||
706 | cp->ops->ioctl = can_ioctl; | ||
707 | } | ||
708 | spin_unlock(&proto_tab_lock); | 705 | spin_unlock(&proto_tab_lock); |
709 | 706 | ||
710 | if (err < 0) | 707 | if (err < 0) |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 092dc88a7c64..871a0ad51025 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1569 | return size; | 1569 | return size; |
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | static struct proto_ops bcm_ops __read_mostly = { | 1572 | static const struct proto_ops bcm_ops = { |
1573 | .family = PF_CAN, | 1573 | .family = PF_CAN, |
1574 | .release = bcm_release, | 1574 | .release = bcm_release, |
1575 | .bind = sock_no_bind, | 1575 | .bind = sock_no_bind, |
@@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = { | |||
1578 | .accept = sock_no_accept, | 1578 | .accept = sock_no_accept, |
1579 | .getname = sock_no_getname, | 1579 | .getname = sock_no_getname, |
1580 | .poll = datagram_poll, | 1580 | .poll = datagram_poll, |
1581 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 1581 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
1582 | .listen = sock_no_listen, | 1582 | .listen = sock_no_listen, |
1583 | .shutdown = sock_no_shutdown, | 1583 | .shutdown = sock_no_shutdown, |
1584 | .setsockopt = sock_no_setsockopt, | 1584 | .setsockopt = sock_no_setsockopt, |
diff --git a/net/can/raw.c b/net/can/raw.c index 883e9d74fddf..649acfa7c70a 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
742 | return size; | 742 | return size; |
743 | } | 743 | } |
744 | 744 | ||
745 | static struct proto_ops raw_ops __read_mostly = { | 745 | static const struct proto_ops raw_ops = { |
746 | .family = PF_CAN, | 746 | .family = PF_CAN, |
747 | .release = raw_release, | 747 | .release = raw_release, |
748 | .bind = raw_bind, | 748 | .bind = raw_bind, |
@@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = { | |||
751 | .accept = sock_no_accept, | 751 | .accept = sock_no_accept, |
752 | .getname = raw_getname, | 752 | .getname = raw_getname, |
753 | .poll = datagram_poll, | 753 | .poll = datagram_poll, |
754 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 754 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
755 | .listen = sock_no_listen, | 755 | .listen = sock_no_listen, |
756 | .shutdown = sock_no_shutdown, | 756 | .shutdown = sock_no_shutdown, |
757 | .setsockopt = raw_setsockopt, | 757 | .setsockopt = raw_setsockopt, |
diff --git a/net/core/dev.c b/net/core/dev.c index f453370131a0..563ddc28139d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev) | |||
1140 | 1140 | ||
1141 | ASSERT_RTNL(); | 1141 | ASSERT_RTNL(); |
1142 | 1142 | ||
1143 | /* | ||
1144 | * Is it even present? | ||
1145 | */ | ||
1146 | if (!netif_device_present(dev)) | 1143 | if (!netif_device_present(dev)) |
1147 | return -ENODEV; | 1144 | return -ENODEV; |
1148 | 1145 | ||
@@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev) | |||
1151 | if (ret) | 1148 | if (ret) |
1152 | return ret; | 1149 | return ret; |
1153 | 1150 | ||
1154 | /* | ||
1155 | * Call device private open method | ||
1156 | */ | ||
1157 | set_bit(__LINK_STATE_START, &dev->state); | 1151 | set_bit(__LINK_STATE_START, &dev->state); |
1158 | 1152 | ||
1159 | if (ops->ndo_validate_addr) | 1153 | if (ops->ndo_validate_addr) |
@@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev) | |||
1162 | if (!ret && ops->ndo_open) | 1156 | if (!ret && ops->ndo_open) |
1163 | ret = ops->ndo_open(dev); | 1157 | ret = ops->ndo_open(dev); |
1164 | 1158 | ||
1165 | /* | ||
1166 | * If it went open OK then: | ||
1167 | */ | ||
1168 | |||
1169 | if (ret) | 1159 | if (ret) |
1170 | clear_bit(__LINK_STATE_START, &dev->state); | 1160 | clear_bit(__LINK_STATE_START, &dev->state); |
1171 | else { | 1161 | else { |
1172 | /* | ||
1173 | * Set the flags. | ||
1174 | */ | ||
1175 | dev->flags |= IFF_UP; | 1162 | dev->flags |= IFF_UP; |
1176 | |||
1177 | /* | ||
1178 | * Enable NET_DMA | ||
1179 | */ | ||
1180 | net_dmaengine_get(); | 1163 | net_dmaengine_get(); |
1181 | |||
1182 | /* | ||
1183 | * Initialize multicasting status | ||
1184 | */ | ||
1185 | dev_set_rx_mode(dev); | 1164 | dev_set_rx_mode(dev); |
1186 | |||
1187 | /* | ||
1188 | * Wakeup transmit queue engine | ||
1189 | */ | ||
1190 | dev_activate(dev); | 1165 | dev_activate(dev); |
1191 | } | 1166 | } |
1192 | 1167 | ||
@@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev) | |||
1209 | { | 1184 | { |
1210 | int ret; | 1185 | int ret; |
1211 | 1186 | ||
1212 | /* | ||
1213 | * Is it already up? | ||
1214 | */ | ||
1215 | if (dev->flags & IFF_UP) | 1187 | if (dev->flags & IFF_UP) |
1216 | return 0; | 1188 | return 0; |
1217 | 1189 | ||
1218 | /* | ||
1219 | * Open device | ||
1220 | */ | ||
1221 | ret = __dev_open(dev); | 1190 | ret = __dev_open(dev); |
1222 | if (ret < 0) | 1191 | if (ret < 0) |
1223 | return ret; | 1192 | return ret; |
1224 | 1193 | ||
1225 | /* | ||
1226 | * ... and announce new interface. | ||
1227 | */ | ||
1228 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1194 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
1229 | call_netdevice_notifiers(NETDEV_UP, dev); | 1195 | call_netdevice_notifiers(NETDEV_UP, dev); |
1230 | 1196 | ||
@@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head) | |||
1240 | might_sleep(); | 1206 | might_sleep(); |
1241 | 1207 | ||
1242 | list_for_each_entry(dev, head, unreg_list) { | 1208 | list_for_each_entry(dev, head, unreg_list) { |
1243 | /* | ||
1244 | * Tell people we are going down, so that they can | ||
1245 | * prepare to death, when device is still operating. | ||
1246 | */ | ||
1247 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); | 1209 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); |
1248 | 1210 | ||
1249 | clear_bit(__LINK_STATE_START, &dev->state); | 1211 | clear_bit(__LINK_STATE_START, &dev->state); |
@@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head) | |||
1272 | if (ops->ndo_stop) | 1234 | if (ops->ndo_stop) |
1273 | ops->ndo_stop(dev); | 1235 | ops->ndo_stop(dev); |
1274 | 1236 | ||
1275 | /* | ||
1276 | * Device is now down. | ||
1277 | */ | ||
1278 | |||
1279 | dev->flags &= ~IFF_UP; | 1237 | dev->flags &= ~IFF_UP; |
1280 | |||
1281 | /* | ||
1282 | * Shutdown NET_DMA | ||
1283 | */ | ||
1284 | net_dmaengine_put(); | 1238 | net_dmaengine_put(); |
1285 | } | 1239 | } |
1286 | 1240 | ||
@@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head) | |||
1309 | 1263 | ||
1310 | __dev_close_many(head); | 1264 | __dev_close_many(head); |
1311 | 1265 | ||
1312 | /* | ||
1313 | * Tell people we are down | ||
1314 | */ | ||
1315 | list_for_each_entry(dev, head, unreg_list) { | 1266 | list_for_each_entry(dev, head, unreg_list) { |
1316 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1267 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
1317 | call_netdevice_notifiers(NETDEV_DOWN, dev); | 1268 | call_netdevice_notifiers(NETDEV_DOWN, dev); |
@@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro); | |||
1371 | 1322 | ||
1372 | static int dev_boot_phase = 1; | 1323 | static int dev_boot_phase = 1; |
1373 | 1324 | ||
1374 | /* | ||
1375 | * Device change register/unregister. These are not inline or static | ||
1376 | * as we export them to the world. | ||
1377 | */ | ||
1378 | |||
1379 | /** | 1325 | /** |
1380 | * register_netdevice_notifier - register a network notifier block | 1326 | * register_netdevice_notifier - register a network notifier block |
1381 | * @nb: notifier | 1327 | * @nb: notifier |
@@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev) | |||
1477 | ASSERT_RTNL(); | 1423 | ASSERT_RTNL(); |
1478 | return raw_notifier_call_chain(&netdev_chain, val, dev); | 1424 | return raw_notifier_call_chain(&netdev_chain, val, dev); |
1479 | } | 1425 | } |
1426 | EXPORT_SYMBOL(call_netdevice_notifiers); | ||
1480 | 1427 | ||
1481 | /* When > 0 there are consumers of rx skb time stamps */ | 1428 | /* When > 0 there are consumers of rx skb time stamps */ |
1482 | static atomic_t netstamp_needed = ATOMIC_INIT(0); | 1429 | static atomic_t netstamp_needed = ATOMIC_INIT(0); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 24bd57493c0d..74ead9eca126 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev) | |||
141 | } | 141 | } |
142 | EXPORT_SYMBOL(ethtool_op_get_flags); | 142 | EXPORT_SYMBOL(ethtool_op_get_flags); |
143 | 143 | ||
144 | /* Check if device can enable (or disable) particular feature coded in "data" | ||
145 | * argument. Flags "supported" describe features that can be toggled by device. | ||
146 | * If feature can not be toggled, it state (enabled or disabled) must match | ||
147 | * hardcoded device features state, otherwise flags are marked as invalid. | ||
148 | */ | ||
149 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported) | ||
150 | { | ||
151 | u32 features = dev->features & flags_dup_features; | ||
152 | /* "data" can contain only flags_dup_features bits, | ||
153 | * see __ethtool_set_flags */ | ||
154 | |||
155 | return (features & ~supported) != (data & ~supported); | ||
156 | } | ||
157 | EXPORT_SYMBOL(ethtool_invalid_flags); | ||
158 | |||
144 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) | 159 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) |
145 | { | 160 | { |
146 | if (data & ~supported) | 161 | if (ethtool_invalid_flags(dev, data, supported)) |
147 | return -EINVAL; | 162 | return -EINVAL; |
148 | 163 | ||
149 | dev->features = ((dev->features & ~flags_dup_features) | | 164 | dev->features = ((dev->features & ~flags_dup_features) | |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 90a3ff605591..b92c86f6e9b3 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1365,9 +1365,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
1365 | err = fib_props[fa->fa_type].error; | 1365 | err = fib_props[fa->fa_type].error; |
1366 | if (err) { | 1366 | if (err) { |
1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
1368 | t->stats.semantic_match_miss++; | 1368 | t->stats.semantic_match_passed++; |
1369 | #endif | 1369 | #endif |
1370 | return 1; | 1370 | return err; |
1371 | } | 1371 | } |
1372 | if (fi->fib_flags & RTNH_F_DEAD) | 1372 | if (fi->fib_flags & RTNH_F_DEAD) |
1373 | continue; | 1373 | continue; |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 1906fa35860c..28a736f3442f 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | |||
140 | } else { | 140 | } else { |
141 | dopt->ts_needtime = 0; | 141 | dopt->ts_needtime = 0; |
142 | 142 | ||
143 | if (soffset + 8 <= optlen) { | 143 | if (soffset + 7 <= optlen) { |
144 | __be32 addr; | 144 | __be32 addr; |
145 | 145 | ||
146 | memcpy(&addr, sptr+soffset-1, 4); | 146 | memcpy(&addr, dptr+soffset-1, 4); |
147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) { | 147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) { |
148 | dopt->ts_needtime = 1; | 148 | dopt->ts_needtime = 1; |
149 | soffset += 8; | 149 | soffset += 8; |
150 | } | 150 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e837ffd3edc3..2d3c72e5bbbf 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | 569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); |
570 | if (IS_ERR(rt)) { | 570 | if (IS_ERR(rt)) { |
571 | err = PTR_ERR(rt); | 571 | err = PTR_ERR(rt); |
572 | rt = NULL; | ||
572 | goto done; | 573 | goto done; |
573 | } | 574 | } |
574 | } | 575 | } |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 7ff0343e05c7..29e48593bf22 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
663 | skb_pull(skb, (u8 *)encap - skb->data); | 663 | skb_pull(skb, (u8 *)encap - skb->data); |
664 | skb_reset_network_header(skb); | 664 | skb_reset_network_header(skb); |
665 | skb->protocol = htons(ETH_P_IPV6); | 665 | skb->protocol = htons(ETH_P_IPV6); |
666 | skb->ip_summed = 0; | 666 | skb->ip_summed = CHECKSUM_NONE; |
667 | skb->pkt_type = PACKET_HOST; | 667 | skb->pkt_type = PACKET_HOST; |
668 | 668 | ||
669 | skb_tunnel_rx(skb, reg_dev); | 669 | skb_tunnel_rx(skb, reg_dev); |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 5b743bdd89ba..36477538cea8 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, | |||
656 | n = 1; | 656 | n = 1; |
657 | 657 | ||
658 | name_len = fp[n++]; | 658 | name_len = fp[n++]; |
659 | |||
660 | IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); | ||
661 | |||
659 | memcpy(name, fp+n, name_len); n+=name_len; | 662 | memcpy(name, fp+n, name_len); n+=name_len; |
660 | name[name_len] = '\0'; | 663 | name[name_len] = '\0'; |
661 | 664 | ||
662 | attr_len = fp[n++]; | 665 | attr_len = fp[n++]; |
666 | |||
667 | IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); | ||
668 | |||
663 | memcpy(attr, fp+n, attr_len); n+=attr_len; | 669 | memcpy(attr, fp+n, attr_len); n+=attr_len; |
664 | attr[attr_len] = '\0'; | 670 | attr[attr_len] = '\0'; |
665 | 671 | ||
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 7c567b8aa89a..2bb2beb6a373 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
@@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap, | |||
105 | while(isspace(start[length - 1])) | 105 | while(isspace(start[length - 1])) |
106 | length--; | 106 | length--; |
107 | 107 | ||
108 | DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5, | ||
109 | -EINVAL, CTRL_ERROR, "Invalid nickname.\n"); | ||
110 | |||
108 | /* Copy the name for later reuse */ | 111 | /* Copy the name for later reuse */ |
109 | memcpy(ap->rname, start + 5, length - 5); | 112 | memcpy(ap->rname, start + 5, length - 5); |
110 | ap->rname[length - 5] = '\0'; | 113 | ap->rname[length - 5] = '\0'; |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 5ee0c62046a0..a80aef6e3d1f 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
978 | struct sock *make; | 978 | struct sock *make; |
979 | struct rose_sock *make_rose; | 979 | struct rose_sock *make_rose; |
980 | struct rose_facilities_struct facilities; | 980 | struct rose_facilities_struct facilities; |
981 | int n, len; | 981 | int n; |
982 | 982 | ||
983 | skb->sk = NULL; /* Initially we don't know who it's for */ | 983 | skb->sk = NULL; /* Initially we don't know who it's for */ |
984 | 984 | ||
@@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
987 | */ | 987 | */ |
988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
989 | 989 | ||
990 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | 990 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
991 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | 991 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, |
992 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 992 | &facilities)) { |
993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); | 993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); |
994 | return 0; | 994 | return 0; |
995 | } | 995 | } |
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index ae4a9d99aec7..344456206b70 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c | |||
@@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param) | |||
73 | unsigned int lci_i, lci_o; | 73 | unsigned int lci_i, lci_o; |
74 | 74 | ||
75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { | 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { |
76 | if (skb->len < ROSE_MIN_LEN) { | ||
77 | kfree_skb(skb); | ||
78 | continue; | ||
79 | } | ||
76 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 80 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
77 | frametype = skb->data[2]; | 81 | frametype = skb->data[2]; |
78 | dest = (rose_address *)(skb->data + 4); | 82 | if (frametype == ROSE_CALL_REQUEST && |
83 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || | ||
84 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
85 | ROSE_CALL_REQ_ADDR_LEN_VAL)) { | ||
86 | kfree_skb(skb); | ||
87 | continue; | ||
88 | } | ||
89 | dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
79 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; | 90 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; |
80 | 91 | ||
81 | skb_reset_transport_header(skb); | 92 | skb_reset_transport_header(skb); |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 88a77e90e7e8..08dcd2f29cdc 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
861 | unsigned int lci, new_lci; | 861 | unsigned int lci, new_lci; |
862 | unsigned char cause, diagnostic; | 862 | unsigned char cause, diagnostic; |
863 | struct net_device *dev; | 863 | struct net_device *dev; |
864 | int len, res = 0; | 864 | int res = 0; |
865 | char buf[11]; | 865 | char buf[11]; |
866 | 866 | ||
867 | #if 0 | 867 | #if 0 |
@@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
869 | return res; | 869 | return res; |
870 | #endif | 870 | #endif |
871 | 871 | ||
872 | if (skb->len < ROSE_MIN_LEN) | ||
873 | return res; | ||
872 | frametype = skb->data[2]; | 874 | frametype = skb->data[2]; |
873 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 875 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
874 | src_addr = (rose_address *)(skb->data + 9); | 876 | if (frametype == ROSE_CALL_REQUEST && |
875 | dest_addr = (rose_address *)(skb->data + 4); | 877 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || |
878 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
879 | ROSE_CALL_REQ_ADDR_LEN_VAL)) | ||
880 | return res; | ||
881 | src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF); | ||
882 | dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
876 | 883 | ||
877 | spin_lock_bh(&rose_neigh_list_lock); | 884 | spin_lock_bh(&rose_neigh_list_lock); |
878 | spin_lock_bh(&rose_route_list_lock); | 885 | spin_lock_bh(&rose_route_list_lock); |
@@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
1010 | goto out; | 1017 | goto out; |
1011 | } | 1018 | } |
1012 | 1019 | ||
1013 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | ||
1014 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | ||
1015 | |||
1016 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 1020 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
1017 | 1021 | ||
1018 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 1022 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
1023 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, | ||
1024 | &facilities)) { | ||
1019 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); | 1025 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); |
1020 | goto out; | 1026 | goto out; |
1021 | } | 1027 | } |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a2..f6c71caa94b9 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
@@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
142 | *dptr++ = ROSE_GFI | lci1; | 142 | *dptr++ = ROSE_GFI | lci1; |
143 | *dptr++ = lci2; | 143 | *dptr++ = lci2; |
144 | *dptr++ = frametype; | 144 | *dptr++ = frametype; |
145 | *dptr++ = 0xAA; | 145 | *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL; |
146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); | 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); |
147 | dptr += ROSE_ADDR_LEN; | 147 | dptr += ROSE_ADDR_LEN; |
148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); | 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); |
@@ -246,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
246 | do { | 246 | do { |
247 | switch (*p & 0xC0) { | 247 | switch (*p & 0xC0) { |
248 | case 0x00: | 248 | case 0x00: |
249 | if (len < 2) | ||
250 | return -1; | ||
249 | p += 2; | 251 | p += 2; |
250 | n += 2; | 252 | n += 2; |
251 | len -= 2; | 253 | len -= 2; |
252 | break; | 254 | break; |
253 | 255 | ||
254 | case 0x40: | 256 | case 0x40: |
257 | if (len < 3) | ||
258 | return -1; | ||
255 | if (*p == FAC_NATIONAL_RAND) | 259 | if (*p == FAC_NATIONAL_RAND) |
256 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); | 260 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); |
257 | p += 3; | 261 | p += 3; |
@@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
260 | break; | 264 | break; |
261 | 265 | ||
262 | case 0x80: | 266 | case 0x80: |
267 | if (len < 4) | ||
268 | return -1; | ||
263 | p += 4; | 269 | p += 4; |
264 | n += 4; | 270 | n += 4; |
265 | len -= 4; | 271 | len -= 4; |
266 | break; | 272 | break; |
267 | 273 | ||
268 | case 0xC0: | 274 | case 0xC0: |
275 | if (len < 2) | ||
276 | return -1; | ||
269 | l = p[1]; | 277 | l = p[1]; |
278 | if (len < 2 + l) | ||
279 | return -1; | ||
270 | if (*p == FAC_NATIONAL_DEST_DIGI) { | 280 | if (*p == FAC_NATIONAL_DEST_DIGI) { |
271 | if (!fac_national_digis_received) { | 281 | if (!fac_national_digis_received) { |
282 | if (l < AX25_ADDR_LEN) | ||
283 | return -1; | ||
272 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); | 284 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); |
273 | facilities->source_ndigis = 1; | 285 | facilities->source_ndigis = 1; |
274 | } | 286 | } |
275 | } | 287 | } |
276 | else if (*p == FAC_NATIONAL_SRC_DIGI) { | 288 | else if (*p == FAC_NATIONAL_SRC_DIGI) { |
277 | if (!fac_national_digis_received) { | 289 | if (!fac_national_digis_received) { |
290 | if (l < AX25_ADDR_LEN) | ||
291 | return -1; | ||
278 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); | 292 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); |
279 | facilities->dest_ndigis = 1; | 293 | facilities->dest_ndigis = 1; |
280 | } | 294 | } |
281 | } | 295 | } |
282 | else if (*p == FAC_NATIONAL_FAIL_CALL) { | 296 | else if (*p == FAC_NATIONAL_FAIL_CALL) { |
297 | if (l < AX25_ADDR_LEN) | ||
298 | return -1; | ||
283 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); | 299 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); |
284 | } | 300 | } |
285 | else if (*p == FAC_NATIONAL_FAIL_ADD) { | 301 | else if (*p == FAC_NATIONAL_FAIL_ADD) { |
302 | if (l < 1 + ROSE_ADDR_LEN) | ||
303 | return -1; | ||
286 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); | 304 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); |
287 | } | 305 | } |
288 | else if (*p == FAC_NATIONAL_DIGIS) { | 306 | else if (*p == FAC_NATIONAL_DIGIS) { |
307 | if (l % AX25_ADDR_LEN) | ||
308 | return -1; | ||
289 | fac_national_digis_received = 1; | 309 | fac_national_digis_received = 1; |
290 | facilities->source_ndigis = 0; | 310 | facilities->source_ndigis = 0; |
291 | facilities->dest_ndigis = 0; | 311 | facilities->dest_ndigis = 0; |
292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { | 312 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { |
293 | if (pt[6] & AX25_HBIT) | 313 | if (pt[6] & AX25_HBIT) { |
314 | if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) | ||
315 | return -1; | ||
294 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); | 316 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); |
295 | else | 317 | } else { |
318 | if (facilities->source_ndigis >= ROSE_MAX_DIGIS) | ||
319 | return -1; | ||
296 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); | 320 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); |
321 | } | ||
297 | } | 322 | } |
298 | } | 323 | } |
299 | p += l + 2; | 324 | p += l + 2; |
@@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
314 | do { | 339 | do { |
315 | switch (*p & 0xC0) { | 340 | switch (*p & 0xC0) { |
316 | case 0x00: | 341 | case 0x00: |
342 | if (len < 2) | ||
343 | return -1; | ||
317 | p += 2; | 344 | p += 2; |
318 | n += 2; | 345 | n += 2; |
319 | len -= 2; | 346 | len -= 2; |
320 | break; | 347 | break; |
321 | 348 | ||
322 | case 0x40: | 349 | case 0x40: |
350 | if (len < 3) | ||
351 | return -1; | ||
323 | p += 3; | 352 | p += 3; |
324 | n += 3; | 353 | n += 3; |
325 | len -= 3; | 354 | len -= 3; |
326 | break; | 355 | break; |
327 | 356 | ||
328 | case 0x80: | 357 | case 0x80: |
358 | if (len < 4) | ||
359 | return -1; | ||
329 | p += 4; | 360 | p += 4; |
330 | n += 4; | 361 | n += 4; |
331 | len -= 4; | 362 | len -= 4; |
332 | break; | 363 | break; |
333 | 364 | ||
334 | case 0xC0: | 365 | case 0xC0: |
366 | if (len < 2) | ||
367 | return -1; | ||
335 | l = p[1]; | 368 | l = p[1]; |
369 | |||
370 | /* Prevent overflows*/ | ||
371 | if (l < 10 || l > 20) | ||
372 | return -1; | ||
373 | |||
336 | if (*p == FAC_CCITT_DEST_NSAP) { | 374 | if (*p == FAC_CCITT_DEST_NSAP) { |
337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 375 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
338 | memcpy(callsign, p + 12, l - 10); | 376 | memcpy(callsign, p + 12, l - 10); |
@@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
355 | return n; | 393 | return n; |
356 | } | 394 | } |
357 | 395 | ||
358 | int rose_parse_facilities(unsigned char *p, | 396 | int rose_parse_facilities(unsigned char *p, unsigned packet_len, |
359 | struct rose_facilities_struct *facilities) | 397 | struct rose_facilities_struct *facilities) |
360 | { | 398 | { |
361 | int facilities_len, len; | 399 | int facilities_len, len; |
362 | 400 | ||
363 | facilities_len = *p++; | 401 | facilities_len = *p++; |
364 | 402 | ||
365 | if (facilities_len == 0) | 403 | if (facilities_len == 0 || (unsigned)facilities_len > packet_len) |
366 | return 0; | 404 | return 0; |
367 | 405 | ||
368 | while (facilities_len > 0) { | 406 | while (facilities_len >= 3 && *p == 0x00) { |
369 | if (*p == 0x00) { | 407 | facilities_len--; |
370 | facilities_len--; | 408 | p++; |
371 | p++; | 409 | |
372 | 410 | switch (*p) { | |
373 | switch (*p) { | 411 | case FAC_NATIONAL: /* National */ |
374 | case FAC_NATIONAL: /* National */ | 412 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); |
375 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); | 413 | break; |
376 | facilities_len -= len + 1; | 414 | |
377 | p += len + 1; | 415 | case FAC_CCITT: /* CCITT */ |
378 | break; | 416 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); |
379 | 417 | break; | |
380 | case FAC_CCITT: /* CCITT */ | 418 | |
381 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); | 419 | default: |
382 | facilities_len -= len + 1; | 420 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); |
383 | p += len + 1; | 421 | len = 1; |
384 | break; | 422 | break; |
385 | 423 | } | |
386 | default: | 424 | |
387 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); | 425 | if (len < 0) |
388 | facilities_len--; | 426 | return 0; |
389 | p++; | 427 | if (WARN_ON(len >= facilities_len)) |
390 | break; | 428 | return 0; |
391 | } | 429 | facilities_len -= len + 1; |
392 | } else | 430 | p += len + 1; |
393 | break; /* Error in facilities format */ | ||
394 | } | 431 | } |
395 | 432 | ||
396 | return 1; | 433 | return facilities_len == 0; |
397 | } | 434 | } |
398 | 435 | ||
399 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) | 436 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 872065ca7f8c..a026b0ef2443 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
173 | goto drop_unlock; | 173 | goto drop_unlock; |
174 | } | 174 | } |
175 | 175 | ||
176 | if (x->props.replay_window && x->repl->check(x, skb, seq)) { | 176 | if (x->repl->check(x, skb, seq)) { |
177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); | 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
178 | goto drop_unlock; | 178 | goto drop_unlock; |
179 | } | 179 | } |
@@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
190 | XFRM_SKB_CB(skb)->seq.input.low = seq; | 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; |
191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; | 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; |
192 | 192 | ||
193 | skb_dst_force(skb); | ||
194 | |||
193 | nexthdr = x->type->input(x, skb); | 195 | nexthdr = x->type->input(x, skb); |
194 | 196 | ||
195 | if (nexthdr == -EINPROGRESS) | 197 | if (nexthdr == -EINPROGRESS) |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 1aba03f449cc..47bacd8c0250 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
78 | 78 | ||
79 | spin_unlock_bh(&x->lock); | 79 | spin_unlock_bh(&x->lock); |
80 | 80 | ||
81 | skb_dst_force(skb); | ||
82 | |||
81 | err = x->type->output(x, skb); | 83 | err = x->type->output(x, skb); |
82 | if (err == -EINPROGRESS) | 84 | if (err == -EINPROGRESS) |
83 | goto out_exit; | 85 | goto out_exit; |
@@ -94,7 +96,7 @@ resume: | |||
94 | err = -EHOSTUNREACH; | 96 | err = -EHOSTUNREACH; |
95 | goto error_nolock; | 97 | goto error_nolock; |
96 | } | 98 | } |
97 | skb_dst_set(skb, dst_clone(dst)); | 99 | skb_dst_set(skb, dst); |
98 | x = dst->xfrm; | 100 | x = dst->xfrm; |
99 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 101 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
100 | 102 | ||
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f5be5b15740..f218385950ca 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
@@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x, | |||
118 | u32 diff; | 118 | u32 diff; |
119 | u32 seq = ntohl(net_seq); | 119 | u32 seq = ntohl(net_seq); |
120 | 120 | ||
121 | if (!x->props.replay_window) | ||
122 | return 0; | ||
123 | |||
121 | if (unlikely(seq == 0)) | 124 | if (unlikely(seq == 0)) |
122 | goto err; | 125 | goto err; |
123 | 126 | ||
@@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x, | |||
193 | { | 196 | { |
194 | unsigned int bitnr, nr; | 197 | unsigned int bitnr, nr; |
195 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 198 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
199 | u32 pos; | ||
196 | u32 seq = ntohl(net_seq); | 200 | u32 seq = ntohl(net_seq); |
197 | u32 diff = replay_esn->seq - seq; | 201 | u32 diff = replay_esn->seq - seq; |
198 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | 202 | |
203 | if (!replay_esn->replay_window) | ||
204 | return 0; | ||
205 | |||
206 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
199 | 207 | ||
200 | if (unlikely(seq == 0)) | 208 | if (unlikely(seq == 0)) |
201 | goto err; | 209 | goto err; |
@@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, | |||
373 | unsigned int bitnr, nr; | 381 | unsigned int bitnr, nr; |
374 | u32 diff; | 382 | u32 diff; |
375 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 383 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
384 | u32 pos; | ||
376 | u32 seq = ntohl(net_seq); | 385 | u32 seq = ntohl(net_seq); |
377 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
378 | u32 wsize = replay_esn->replay_window; | 386 | u32 wsize = replay_esn->replay_window; |
379 | u32 top = replay_esn->seq; | 387 | u32 top = replay_esn->seq; |
380 | u32 bottom = top - wsize + 1; | 388 | u32 bottom = top - wsize + 1; |
381 | 389 | ||
390 | if (!wsize) | ||
391 | return 0; | ||
392 | |||
393 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
394 | |||
382 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && | 395 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && |
383 | (replay_esn->seq < replay_esn->replay_window - 1))) | 396 | (replay_esn->seq < replay_esn->replay_window - 1))) |
384 | goto err; | 397 | goto err; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f83a3d1da81b..dd78536d40de 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
1181 | goto error; | 1181 | goto error; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | if (orig->replay_esn) { | ||
1185 | err = xfrm_replay_clone(x, orig); | ||
1186 | if (err) | ||
1187 | goto error; | ||
1188 | } | ||
1189 | |||
1184 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); | 1190 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
1185 | 1191 | ||
1186 | err = xfrm_init_state(x); | 1192 | err = xfrm_init_state(x); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index fc152d28753c..3d15d3e1b2c4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
127 | if (!rt) | 127 | if (!rt) |
128 | return 0; | 128 | return 0; |
129 | 129 | ||
130 | if (p->id.proto != IPPROTO_ESP) | ||
131 | return -EINVAL; | ||
132 | |||
130 | if (p->replay_window != 0) | 133 | if (p->replay_window != 0) |
131 | return -EINVAL; | 134 | return -EINVAL; |
132 | 135 | ||
@@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | |||
360 | return 0; | 363 | return 0; |
361 | } | 364 | } |
362 | 365 | ||
366 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | ||
367 | struct nlattr *rp) | ||
368 | { | ||
369 | struct xfrm_replay_state_esn *up; | ||
370 | |||
371 | if (!replay_esn || !rp) | ||
372 | return 0; | ||
373 | |||
374 | up = nla_data(rp); | ||
375 | |||
376 | if (xfrm_replay_state_esn_len(replay_esn) != | ||
377 | xfrm_replay_state_esn_len(up)) | ||
378 | return -EINVAL; | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
363 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | 383 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, |
364 | struct xfrm_replay_state_esn **preplay_esn, | 384 | struct xfrm_replay_state_esn **preplay_esn, |
365 | struct nlattr *rta) | 385 | struct nlattr *rta) |
@@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1766 | if (x->km.state != XFRM_STATE_VALID) | 1786 | if (x->km.state != XFRM_STATE_VALID) |
1767 | goto out; | 1787 | goto out; |
1768 | 1788 | ||
1789 | err = xfrm_replay_verify_len(x->replay_esn, rp); | ||
1790 | if (err) | ||
1791 | goto out; | ||
1792 | |||
1769 | spin_lock_bh(&x->lock); | 1793 | spin_lock_bh(&x->lock); |
1770 | xfrm_update_ae_params(x, attrs); | 1794 | xfrm_update_ae_params(x, attrs); |
1771 | spin_unlock_bh(&x->lock); | 1795 | spin_unlock_bh(&x->lock); |