Skip to content

Commit aed5a83

Browse files
committed
Merge branch 'net-2.6-misc-20080605a' of git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-fix
2 parents a660447 + 9596cc8 commit aed5a83

File tree

17 files changed

+146
-97
lines changed

17 files changed

+146
-97
lines changed

include/net/addrconf.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ extern void addrconf_join_solict(struct net_device *dev,
9494
extern void addrconf_leave_solict(struct inet6_dev *idev,
9595
struct in6_addr *addr);
9696

97+
static inline unsigned long addrconf_timeout_fixup(u32 timeout,
98+
unsigned unit)
99+
{
100+
if (timeout == 0xffffffff)
101+
return ~0UL;
102+
103+
/*
104+
* Avoid arithmetic overflow.
105+
* Assuming unit is constant and non-zero, this "if" statement
106+
* will go away on 64bit archs.
107+
*/
108+
if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
109+
return LONG_MAX / unit;
110+
111+
return timeout;
112+
}
113+
114+
static inline int addrconf_finite_timeout(unsigned long timeout)
115+
{
116+
return ~timeout;
117+
}
118+
97119
/*
98120
* IPv6 Address Label subsystem (addrlabel.c)
99121
*/

include/net/sctp/structs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,8 @@ struct sctp_af {
548548
struct dst_entry *(*get_dst) (struct sctp_association *asoc,
549549
union sctp_addr *daddr,
550550
union sctp_addr *saddr);
551-
void (*get_saddr) (struct sctp_association *asoc,
551+
void (*get_saddr) (struct sctp_sock *sk,
552+
struct sctp_association *asoc,
552553
struct dst_entry *dst,
553554
union sctp_addr *daddr,
554555
union sctp_addr *saddr);

include/net/transp_v6.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ extern int datagram_recv_ctl(struct sock *sk,
4040
struct msghdr *msg,
4141
struct sk_buff *skb);
4242

43-
extern int datagram_send_ctl(struct msghdr *msg,
43+
extern int datagram_send_ctl(struct net *net,
44+
struct msghdr *msg,
4445
struct flowi *fl,
4546
struct ipv6_txoptions *opt,
4647
int *hlimit, int *tclass);

include/net/udp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ extern void udp_err(struct sk_buff *, u32);
135135

136136
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
137137
struct msghdr *msg, size_t len);
138+
extern void udp_flush_pending_frames(struct sock *sk);
138139

139140
extern int udp_rcv(struct sk_buff *skb);
140141
extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);

net/ipv4/tunnel4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static int tunnel64_rcv(struct sk_buff *skb)
9797
{
9898
struct xfrm_tunnel *handler;
9999

100-
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
100+
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
101101
goto drop;
102102

103103
for (handler = tunnel64_handlers; handler; handler = handler->next)

net/ipv4/udp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ void udp_err(struct sk_buff *skb, u32 info)
420420
/*
421421
* Throw away all pending data and cancel the corking. Socket is locked.
422422
*/
423-
static void udp_flush_pending_frames(struct sock *sk)
423+
void udp_flush_pending_frames(struct sock *sk)
424424
{
425425
struct udp_sock *up = udp_sk(sk);
426426

@@ -430,6 +430,7 @@ static void udp_flush_pending_frames(struct sock *sk)
430430
ip_flush_pending_frames(sk);
431431
}
432432
}
433+
EXPORT_SYMBOL(udp_flush_pending_frames);
433434

434435
/**
435436
* udp4_hwcsum_outgoing - handle outgoing HW checksumming

net/ipv6/addrconf.c

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,13 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
731731
onlink = -1;
732732

733733
spin_lock(&ifa->lock);
734-
lifetime = min_t(unsigned long,
735-
ifa->valid_lft, 0x7fffffffUL/HZ);
734+
735+
lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ);
736+
/*
737+
* Note: Because this address is
738+
* not permanent, lifetime <
739+
* LONG_MAX / HZ here.
740+
*/
736741
if (time_before(expires,
737742
ifa->tstamp + lifetime * HZ))
738743
expires = ifa->tstamp + lifetime * HZ;
@@ -1722,7 +1727,6 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
17221727
__u32 valid_lft;
17231728
__u32 prefered_lft;
17241729
int addr_type;
1725-
unsigned long rt_expires;
17261730
struct inet6_dev *in6_dev;
17271731

17281732
pinfo = (struct prefix_info *) opt;
@@ -1764,28 +1768,23 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
17641768
* 2) Configure prefixes with the auto flag set
17651769
*/
17661770

1767-
if (valid_lft == INFINITY_LIFE_TIME)
1768-
rt_expires = ~0UL;
1769-
else if (valid_lft >= 0x7FFFFFFF/HZ) {
1771+
if (pinfo->onlink) {
1772+
struct rt6_info *rt;
1773+
unsigned long rt_expires;
1774+
17701775
/* Avoid arithmetic overflow. Really, we could
17711776
* save rt_expires in seconds, likely valid_lft,
17721777
* but it would require division in fib gc, that it
17731778
* not good.
17741779
*/
1775-
rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ);
1776-
} else
1777-
rt_expires = valid_lft * HZ;
1780+
if (HZ > USER_HZ)
1781+
rt_expires = addrconf_timeout_fixup(valid_lft, HZ);
1782+
else
1783+
rt_expires = addrconf_timeout_fixup(valid_lft, USER_HZ);
17781784

1779-
/*
1780-
* We convert this (in jiffies) to clock_t later.
1781-
* Avoid arithmetic overflow there as well.
1782-
* Overflow can happen only if HZ < USER_HZ.
1783-
*/
1784-
if (HZ < USER_HZ && ~rt_expires && rt_expires > 0x7FFFFFFF / USER_HZ)
1785-
rt_expires = 0x7FFFFFFF / USER_HZ;
1785+
if (addrconf_finite_timeout(rt_expires))
1786+
rt_expires *= HZ;
17861787

1787-
if (pinfo->onlink) {
1788-
struct rt6_info *rt;
17891788
rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
17901789
dev->ifindex, 1);
17911790

@@ -1794,7 +1793,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
17941793
if (valid_lft == 0) {
17951794
ip6_del_rt(rt);
17961795
rt = NULL;
1797-
} else if (~rt_expires) {
1796+
} else if (addrconf_finite_timeout(rt_expires)) {
17981797
/* not infinity */
17991798
rt->rt6i_expires = jiffies + rt_expires;
18001799
rt->rt6i_flags |= RTF_EXPIRES;
@@ -1803,9 +1802,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
18031802
rt->rt6i_expires = 0;
18041803
}
18051804
} else if (valid_lft) {
1806-
int flags = RTF_ADDRCONF | RTF_PREFIX_RT;
18071805
clock_t expires = 0;
1808-
if (~rt_expires) {
1806+
int flags = RTF_ADDRCONF | RTF_PREFIX_RT;
1807+
if (addrconf_finite_timeout(rt_expires)) {
18091808
/* not infinity */
18101809
flags |= RTF_EXPIRES;
18111810
expires = jiffies_to_clock_t(rt_expires);
@@ -2027,7 +2026,7 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg)
20272026
* Manual configuration of address on an interface
20282027
*/
20292028
static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
2030-
int plen, __u8 ifa_flags, __u32 prefered_lft,
2029+
unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
20312030
__u32 valid_lft)
20322031
{
20332032
struct inet6_ifaddr *ifp;
@@ -2036,9 +2035,13 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
20362035
int scope;
20372036
u32 flags;
20382037
clock_t expires;
2038+
unsigned long timeout;
20392039

20402040
ASSERT_RTNL();
20412041

2042+
if (plen > 128)
2043+
return -EINVAL;
2044+
20422045
/* check the lifetime */
20432046
if (!valid_lft || prefered_lft > valid_lft)
20442047
return -EINVAL;
@@ -2052,22 +2055,23 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
20522055

20532056
scope = ipv6_addr_scope(pfx);
20542057

2055-
if (valid_lft == INFINITY_LIFE_TIME) {
2056-
ifa_flags |= IFA_F_PERMANENT;
2057-
flags = 0;
2058-
expires = 0;
2059-
} else {
2060-
if (valid_lft >= 0x7FFFFFFF/HZ)
2061-
valid_lft = 0x7FFFFFFF/HZ;
2058+
timeout = addrconf_timeout_fixup(valid_lft, HZ);
2059+
if (addrconf_finite_timeout(timeout)) {
2060+
expires = jiffies_to_clock_t(timeout * HZ);
2061+
valid_lft = timeout;
20622062
flags = RTF_EXPIRES;
2063-
expires = jiffies_to_clock_t(valid_lft * HZ);
2063+
} else {
2064+
expires = 0;
2065+
flags = 0;
2066+
ifa_flags |= IFA_F_PERMANENT;
20642067
}
20652068

2066-
if (prefered_lft == 0)
2067-
ifa_flags |= IFA_F_DEPRECATED;
2068-
else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
2069-
(prefered_lft != INFINITY_LIFE_TIME))
2070-
prefered_lft = 0x7FFFFFFF/HZ;
2069+
timeout = addrconf_timeout_fixup(prefered_lft, HZ);
2070+
if (addrconf_finite_timeout(timeout)) {
2071+
if (timeout == 0)
2072+
ifa_flags |= IFA_F_DEPRECATED;
2073+
prefered_lft = timeout;
2074+
}
20712075

20722076
ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
20732077

@@ -2095,12 +2099,15 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
20952099
}
20962100

20972101
static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx,
2098-
int plen)
2102+
unsigned int plen)
20992103
{
21002104
struct inet6_ifaddr *ifp;
21012105
struct inet6_dev *idev;
21022106
struct net_device *dev;
21032107

2108+
if (plen > 128)
2109+
return -EINVAL;
2110+
21042111
dev = __dev_get_by_index(net, ifindex);
21052112
if (!dev)
21062113
return -ENODEV;
@@ -3169,26 +3176,28 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
31693176
{
31703177
u32 flags;
31713178
clock_t expires;
3179+
unsigned long timeout;
31723180

31733181
if (!valid_lft || (prefered_lft > valid_lft))
31743182
return -EINVAL;
31753183

3176-
if (valid_lft == INFINITY_LIFE_TIME) {
3177-
ifa_flags |= IFA_F_PERMANENT;
3178-
flags = 0;
3179-
expires = 0;
3180-
} else {
3181-
if (valid_lft >= 0x7FFFFFFF/HZ)
3182-
valid_lft = 0x7FFFFFFF/HZ;
3184+
timeout = addrconf_timeout_fixup(valid_lft, HZ);
3185+
if (addrconf_finite_timeout(timeout)) {
3186+
expires = jiffies_to_clock_t(timeout * HZ);
3187+
valid_lft = timeout;
31833188
flags = RTF_EXPIRES;
3184-
expires = jiffies_to_clock_t(valid_lft * HZ);
3189+
} else {
3190+
expires = 0;
3191+
flags = 0;
3192+
ifa_flags |= IFA_F_PERMANENT;
31853193
}
31863194

3187-
if (prefered_lft == 0)
3188-
ifa_flags |= IFA_F_DEPRECATED;
3189-
else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
3190-
(prefered_lft != INFINITY_LIFE_TIME))
3191-
prefered_lft = 0x7FFFFFFF/HZ;
3195+
timeout = addrconf_timeout_fixup(prefered_lft, HZ);
3196+
if (addrconf_finite_timeout(timeout)) {
3197+
if (timeout == 0)
3198+
ifa_flags |= IFA_F_DEPRECATED;
3199+
prefered_lft = timeout;
3200+
}
31923201

31933202
spin_lock_bh(&ifp->lock);
31943203
ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;

net/ipv6/datagram.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,8 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
496496
return 0;
497497
}
498498

499-
int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
499+
int datagram_send_ctl(struct net *net,
500+
struct msghdr *msg, struct flowi *fl,
500501
struct ipv6_txoptions *opt,
501502
int *hlimit, int *tclass)
502503
{
@@ -509,7 +510,6 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
509510

510511
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
511512
int addr_type;
512-
struct net_device *dev = NULL;
513513

514514
if (!CMSG_OK(msg, cmsg)) {
515515
err = -EINVAL;
@@ -522,6 +522,9 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
522522
switch (cmsg->cmsg_type) {
523523
case IPV6_PKTINFO:
524524
case IPV6_2292PKTINFO:
525+
{
526+
struct net_device *dev = NULL;
527+
525528
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) {
526529
err = -EINVAL;
527530
goto exit_f;
@@ -535,32 +538,32 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
535538
fl->oif = src_info->ipi6_ifindex;
536539
}
537540

538-
addr_type = ipv6_addr_type(&src_info->ipi6_addr);
541+
addr_type = __ipv6_addr_type(&src_info->ipi6_addr);
539542

540-
if (addr_type == IPV6_ADDR_ANY)
541-
break;
543+
if (fl->oif) {
544+
dev = dev_get_by_index(net, fl->oif);
545+
if (!dev)
546+
return -ENODEV;
547+
} else if (addr_type & IPV6_ADDR_LINKLOCAL)
548+
return -EINVAL;
542549

543-
if (addr_type & IPV6_ADDR_LINKLOCAL) {
544-
if (!src_info->ipi6_ifindex)
545-
return -EINVAL;
546-
else {
547-
dev = dev_get_by_index(&init_net, src_info->ipi6_ifindex);
548-
if (!dev)
549-
return -ENODEV;
550-
}
551-
}
552-
if (!ipv6_chk_addr(&init_net, &src_info->ipi6_addr,
553-
dev, 0)) {
554-
if (dev)
555-
dev_put(dev);
556-
err = -EINVAL;
557-
goto exit_f;
550+
if (addr_type != IPV6_ADDR_ANY) {
551+
int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL;
552+
if (!ipv6_chk_addr(net, &src_info->ipi6_addr,
553+
strict ? dev : NULL, 0))
554+
err = -EINVAL;
555+
else
556+
ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr);
558557
}
558+
559559
if (dev)
560560
dev_put(dev);
561561

562-
ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr);
562+
if (err)
563+
goto exit_f;
564+
563565
break;
566+
}
564567

565568
case IPV6_FLOWINFO:
566569
if (cmsg->cmsg_len < CMSG_LEN(4)) {

net/ipv6/ip6_flowlabel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
354354
msg.msg_control = (void*)(fl->opt+1);
355355
flowi.oif = 0;
356356

357-
err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk);
357+
err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, &junk);
358358
if (err)
359359
goto done;
360360
err = -EINVAL;

0 commit comments

Comments
 (0)