diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2009-08-31 07:35:42 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2009-08-31 08:29:35 +0000 |
commit | fd16ce4706d108cc9e35140095edaa28394396aa (patch) | |
tree | aaa04b8e25b25aa64dee13ea85f7cecf866233b0 /main/linux-grsec | |
parent | 8bdd83b2b95988041898a40d9476832c049fb8ad (diff) | |
download | aports-fd16ce4706d108cc9e35140095edaa28394396aa.tar.bz2 aports-fd16ce4706d108cc9e35140095edaa28394396aa.tar.xz |
main/*-grsec: updated grsec kernel to 200908281917
Diffstat (limited to 'main/linux-grsec')
-rw-r--r-- | main/linux-grsec/APKBUILD | 9 | ||||
-rw-r--r-- | main/linux-grsec/grsecurity-2.1.14-2.6.30.5-200908281917.patch (renamed from main/linux-grsec/grsecurity-2.1.14-2.6.30.5-200908261614.patch) | 137 | ||||
-rw-r--r-- | main/linux-grsec/linux-nbma-mroute-v4-2.6.30.diff | 258 |
3 files changed, 131 insertions, 273 deletions
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD index caac111b88..9543b34651 100644 --- a/main/linux-grsec/APKBUILD +++ b/main/linux-grsec/APKBUILD @@ -4,7 +4,7 @@ _flavor=grsec pkgname=linux-${_flavor} pkgver=2.6.30.5 _kernver=2.6.30 -pkgrel=0 +pkgrel=1 pkgdesc="Linux kernel with grsecurity" url=http://grsecurity.net depends="mkinitfs" @@ -13,8 +13,7 @@ _config=${config:-kernelconfig} install="$pkgname.post-install $pkgname.post-upgrade" source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2 ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2 - grsecurity-2.1.14-2.6.30.5-200908261614.patch - linux-nbma-mroute-v4-2.6.30.diff + grsecurity-2.1.14-2.6.30.5-200908281917.patch net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch $_config " @@ -30,6 +29,7 @@ _prepare() { fi for i in ../*.diff ../*.patch; do + [ -f $i ] || continue msg "Applying $i..." patch -p1 -N < $i || return 1 done @@ -112,7 +112,6 @@ dev() { md5sums="7a80058a6382e5108cdb5554d1609615 linux-2.6.30.tar.bz2 47841c7ff5c81a7b349a79f2fa8e9138 patch-2.6.30.5.bz2 -a725c0779f365787127c71810877586d grsecurity-2.1.14-2.6.30.5-200908261614.patch -7420c0b1095335990313656b114e1379 linux-nbma-mroute-v4-2.6.30.diff +dee5a6292fb12018eb3bd3d014f89407 grsecurity-2.1.14-2.6.30.5-200908281917.patch ca05fd252783b82e01610e775cf56498 net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch ede34b2613f54cf1eae8f37a61d0e085 kernelconfig" diff --git a/main/linux-grsec/grsecurity-2.1.14-2.6.30.5-200908261614.patch b/main/linux-grsec/grsecurity-2.1.14-2.6.30.5-200908281917.patch index f653790e89..cc232fbe5d 100644 --- a/main/linux-grsec/grsecurity-2.1.14-2.6.30.5-200908261614.patch +++ b/main/linux-grsec/grsecurity-2.1.14-2.6.30.5-200908281917.patch @@ -2937,7 +2937,7 @@ diff -urNp linux-2.6.30.5/arch/sparc/Makefile linux-2.6.30.5/arch/sparc/Makefile diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_32.c linux-2.6.30.5/arch/sparc/mm/fault_32.c --- linux-2.6.30.5/arch/sparc/mm/fault_32.c 2009-07-24 17:47:51.000000000 -0400 -+++ linux-2.6.30.5/arch/sparc/mm/fault_32.c 2009-07-30 09:48:09.913853340 -0400 ++++ linux-2.6.30.5/arch/sparc/mm/fault_32.c 2009-08-27 21:11:25.299108429 -0400 @@ -21,6 +21,9 @@ #include <linux/interrupt.h> #include <linux/module.h> @@ -2948,7 +2948,7 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_32.c linux-2.6.30.5/arch/sparc/mm/ #include <asm/system.h> #include <asm/page.h> -@@ -167,6 +170,249 @@ static unsigned long compute_si_addr(str +@@ -167,6 +170,264 @@ static unsigned long compute_si_addr(str return safe_compute_effective_address(regs, insn); } @@ -3150,6 +3150,21 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_32.c linux-2.6.30.5/arch/sparc/mm/ + regs->npc = addr+4; + return 3; + } ++ ++ /* PaX: newer glibc/binutils generate sethi/jmp instead of save/call */ ++ if ((save & 0xFFC00000U) == 0x05000000U && ++ (call & 0xFFFFE000U) == 0x85C0A000U && ++ nop == 0x01000000U) ++ { ++ unsigned long addr; ++ ++ addr = (save & 0x003FFFFFU) << 10; ++ regs->u_regs[UREG_G2] = addr; ++ addr += (((call | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); ++ regs->pc = addr; ++ regs->npc = addr+4; ++ return 3; ++ } + } + } while (0); + @@ -3198,7 +3213,7 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_32.c linux-2.6.30.5/arch/sparc/mm/ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, unsigned long address) { -@@ -231,6 +477,24 @@ good_area: +@@ -231,6 +492,24 @@ good_area: if(!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { @@ -3225,7 +3240,7 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_32.c linux-2.6.30.5/arch/sparc/mm/ goto bad_area; diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/fault_64.c --- linux-2.6.30.5/arch/sparc/mm/fault_64.c 2009-07-24 17:47:51.000000000 -0400 -+++ linux-2.6.30.5/arch/sparc/mm/fault_64.c 2009-07-30 09:48:09.913853340 -0400 ++++ linux-2.6.30.5/arch/sparc/mm/fault_64.c 2009-08-27 21:11:25.310208001 -0400 @@ -20,6 +20,9 @@ #include <linux/kprobes.h> #include <linux/kdebug.h> @@ -3236,7 +3251,7 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ #include <asm/page.h> #include <asm/pgtable.h> -@@ -249,6 +252,367 @@ static void noinline bogus_32bit_fault_a +@@ -249,6 +252,404 @@ static void noinline bogus_32bit_fault_a show_regs(regs); } @@ -3320,6 +3335,10 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ + regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; + addr = regs->u_regs[UREG_G1]; + addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); ++ ++ if (test_thread_flag(TIF_32BIT)) ++ addr &= 0xFFFFFFFFUL; ++ + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; @@ -3335,6 +3354,10 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ + unsigned long addr; + + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); ++ ++ if (test_thread_flag(TIF_32BIT)) ++ addr &= 0xFFFFFFFFUL; ++ + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; @@ -3360,6 +3383,10 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; + addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); ++ ++ if (test_thread_flag(TIF_32BIT)) ++ addr &= 0xFFFFFFFFUL; ++ + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; @@ -3503,6 +3530,9 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ + else + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + ++ if (test_thread_flag(TIF_32BIT)) ++ addr &= 0xFFFFFFFFUL; ++ + err = get_user(save, (unsigned int *)addr); + err |= get_user(call, (unsigned int *)(addr+4)); + err |= get_user(nop, (unsigned int *)(addr+8)); @@ -3556,6 +3586,25 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ + regs->tnpc = addr+4; + return 3; + } ++ ++ /* PaX: newer glibc/binutils generate sethi/jmp instead of save/call */ ++ if ((save & 0xFFC00000U) == 0x05000000U && ++ (call & 0xFFFFE000U) == 0x85C0A000U && ++ nop == 0x01000000U) ++ { ++ unsigned long addr; ++ ++ addr = (save & 0x003FFFFFU) << 10; ++ regs->u_regs[UREG_G2] = addr; ++ addr += (((call | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); ++ ++ if (test_thread_flag(TIF_32BIT)) ++ addr &= 0xFFFFFFFFUL; ++ ++ regs->tpc = addr; ++ regs->tnpc = addr+4; ++ return 3; ++ } + } + } while (0); + @@ -3574,6 +3623,9 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ + { + unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); + ++ if (test_thread_flag(TIF_32BIT)) ++ dl_resolve &= 0xFFFFFFFFUL; ++ + regs->u_regs[UREG_RETPC] = regs->tpc; + regs->tpc = dl_resolve; + regs->tnpc = dl_resolve+4; @@ -3604,7 +3656,7 @@ diff -urNp linux-2.6.30.5/arch/sparc/mm/fault_64.c linux-2.6.30.5/arch/sparc/mm/ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; -@@ -315,6 +679,29 @@ asmlinkage void __kprobes do_sparc64_fau +@@ -315,6 +716,29 @@ asmlinkage void __kprobes do_sparc64_fau if (!vma) goto bad_area; @@ -11293,7 +11345,7 @@ diff -urNp linux-2.6.30.5/arch/x86/kernel/vmi_32.c linux-2.6.30.5/arch/x86/kerne * to convert VMI_IRET to a call instead of a jump; so we have diff -urNp linux-2.6.30.5/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.30.5/arch/x86/kernel/vmlinux_32.lds.S --- linux-2.6.30.5/arch/x86/kernel/vmlinux_32.lds.S 2009-07-24 17:47:51.000000000 -0400 -+++ linux-2.6.30.5/arch/x86/kernel/vmlinux_32.lds.S 2009-07-30 09:48:09.962543704 -0400 ++++ linux-2.6.30.5/arch/x86/kernel/vmlinux_32.lds.S 2009-08-27 21:11:25.322527521 -0400 @@ -15,6 +15,20 @@ #include <asm/page_types.h> #include <asm/cache.h> @@ -11523,7 +11575,7 @@ diff -urNp linux-2.6.30.5/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.30.5/arch/x + .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) { + MODULES_VADDR = .; + BYTE(0) -+ . += (6 * 1024 * 1024); ++ . += (8 * 1024 * 1024); + . = ALIGN(PMD_SIZE); + MODULES_END = . - 1; + } @@ -40886,7 +40938,7 @@ diff -urNp linux-2.6.30.5/mm/memory.c linux-2.6.30.5/mm/memory.c * Dumping its contents makes post-mortem fully interpretable later diff -urNp linux-2.6.30.5/mm/mempolicy.c linux-2.6.30.5/mm/mempolicy.c --- linux-2.6.30.5/mm/mempolicy.c 2009-07-24 17:47:51.000000000 -0400 -+++ linux-2.6.30.5/mm/mempolicy.c 2009-07-30 09:48:10.145161384 -0400 ++++ linux-2.6.30.5/mm/mempolicy.c 2009-08-28 19:17:19.665274493 -0400 @@ -551,6 +551,10 @@ static int mbind_range(struct vm_area_st struct vm_area_struct *next; int err; @@ -40933,7 +40985,32 @@ diff -urNp linux-2.6.30.5/mm/mempolicy.c linux-2.6.30.5/mm/mempolicy.c if (end == start) return 0; -@@ -2290,7 +2315,7 @@ int show_numa_map(struct seq_file *m, vo +@@ -1142,6 +1167,14 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pi + if (!mm) + return -EINVAL; + ++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP ++ if (mm != current->mm && ++ (mm->pax_flags & MF_PAX_RANDMMAP || mm->pax_flags & MF_PAX_SEGMEXEC)) { ++ err = -EPERM; ++ goto out; ++ } ++#endif ++ + /* + * Check if this process has the right to modify the specified + * process. The right exists if the process has administrative +@@ -1151,8 +1184,7 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pi + rcu_read_lock(); + tcred = __task_cred(task); + if (cred->euid != tcred->suid && cred->euid != tcred->uid && +- cred->uid != tcred->suid && cred->uid != tcred->uid && +- !capable(CAP_SYS_NICE)) { ++ cred->uid != tcred->suid && !capable(CAP_SYS_NICE)) { + rcu_read_unlock(); + err = -EPERM; + goto out; +@@ -2290,7 +2322,7 @@ int show_numa_map(struct seq_file *m, vo if (file) { seq_printf(m, " file="); @@ -40942,6 +41019,34 @@ diff -urNp linux-2.6.30.5/mm/mempolicy.c linux-2.6.30.5/mm/mempolicy.c } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { seq_printf(m, " heap"); } else if (vma->vm_start <= mm->start_stack && +diff -urNp linux-2.6.30.5/mm/migrate.c linux-2.6.30.5/mm/migrate.c +--- linux-2.6.30.5/mm/migrate.c 2009-07-24 17:47:51.000000000 -0400 ++++ linux-2.6.30.5/mm/migrate.c 2009-08-28 19:16:52.585127596 -0400 +@@ -1085,6 +1085,14 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, + if (!mm) + return -EINVAL; + ++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP ++ if (mm != current->mm && ++ (mm->pax_flags & MF_PAX_RANDMMAP || mm->pax_flags & MF_PAX_SEGMEXEC)) { ++ err = -EPERM; ++ goto out; ++ } ++#endif ++ + /* + * Check if this process has the right to modify the specified + * process. The right exists if the process has administrative +@@ -1094,8 +1102,7 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, + rcu_read_lock(); + tcred = __task_cred(task); + if (cred->euid != tcred->suid && cred->euid != tcred->uid && +- cred->uid != tcred->suid && cred->uid != tcred->uid && +- !capable(CAP_SYS_NICE)) { ++ cred->uid != tcred->suid && !capable(CAP_SYS_NICE)) { + rcu_read_unlock(); + err = -EPERM; + goto out; diff -urNp linux-2.6.30.5/mm/mlock.c linux-2.6.30.5/mm/mlock.c --- linux-2.6.30.5/mm/mlock.c 2009-07-24 17:47:51.000000000 -0400 +++ linux-2.6.30.5/mm/mlock.c 2009-07-30 11:10:49.799565380 -0400 @@ -43474,6 +43579,18 @@ diff -urNp linux-2.6.30.5/net/ipv4/inet_hashtables.c linux-2.6.30.5/net/ipv4/ine if (tw) { inet_twsk_deschedule(tw, death_row); inet_twsk_put(tw); +diff -urNp linux-2.6.30.5/net/ipv4/ip_output.c linux-2.6.30.5/net/ipv4/ip_output.c +--- linux-2.6.30.5/net/ipv4/ip_output.c 2009-07-24 17:47:51.000000000 -0400 ++++ linux-2.6.30.5/net/ipv4/ip_output.c 2009-08-28 18:54:39.383265912 -0400 +@@ -814,6 +814,8 @@ int ip_append_data(struct sock *sk, + inet->cork.addr = ipc->addr; + } + rt = *rtp; ++ if (unlikely(rt == NULL)) ++ return -EFAULT; + /* + * We steal reference to this route, caller should not release it + */ diff -urNp linux-2.6.30.5/net/ipv4/netfilter/nf_nat_snmp_basic.c linux-2.6.30.5/net/ipv4/netfilter/nf_nat_snmp_basic.c --- linux-2.6.30.5/net/ipv4/netfilter/nf_nat_snmp_basic.c 2009-07-24 17:47:51.000000000 -0400 +++ linux-2.6.30.5/net/ipv4/netfilter/nf_nat_snmp_basic.c 2009-07-30 09:48:10.155784268 -0400 diff --git a/main/linux-grsec/linux-nbma-mroute-v4-2.6.30.diff b/main/linux-grsec/linux-nbma-mroute-v4-2.6.30.diff deleted file mode 100644 index 636d807a53..0000000000 --- a/main/linux-grsec/linux-nbma-mroute-v4-2.6.30.diff +++ /dev/null @@ -1,258 +0,0 @@ -diff --git a/include/linux/mroute.h b/include/linux/mroute.h -index 0d45b4e..406ef6f 100644 ---- a/include/linux/mroute.h -+++ b/include/linux/mroute.h -@@ -33,7 +33,7 @@ - #define SIOCGETSGCNT (SIOCPROTOPRIVATE+1) - #define SIOCGETRPF (SIOCPROTOPRIVATE+2) - --#define MAXVIFS 32 -+#define MAXVIFS 256 - typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */ - typedef unsigned short vifi_t; - #define ALL_VIFS ((vifi_t)(-1)) -@@ -66,6 +66,7 @@ struct vifctl { - #define VIFF_TUNNEL 0x1 /* IPIP tunnel */ - #define VIFF_SRCRT 0x2 /* NI */ - #define VIFF_REGISTER 0x4 /* register vif */ -+#define VIFF_NBMA 0x10 - - /* - * Cache manipulation structures for mrouted and PIMd -diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c -index 13e9dd3..43c988b 100644 ---- a/net/ipv4/ipmr.c -+++ b/net/ipv4/ipmr.c -@@ -105,6 +105,31 @@ static struct net_protocol pim_protocol; - - static struct timer_list ipmr_expire_timer; - -+static __be32 ipmr_get_skb_nbma(struct sk_buff *skb) -+{ -+ union { -+ char addr[MAX_ADDR_LEN]; -+ __be32 inaddr; -+ } u; -+ -+ if (dev_parse_header(skb, u.addr) != 4) -+ return INADDR_ANY; -+ -+ return u.inaddr; -+} -+ -+static int ip_mr_match_vif_skb(struct vif_device *vif, struct sk_buff *skb) -+{ -+ if (vif->dev != skb->dev) -+ return 0; -+ -+ if (vif->flags & VIFF_NBMA) -+ return ipmr_get_skb_nbma(skb) == vif->remote; -+ -+ return 1; -+} -+ -+ - /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ - - static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) -@@ -470,6 +495,7 @@ static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) - return err; - } - break; -+ case VIFF_NBMA: - case 0: - dev = ip_dev_find(net, vifc->vifc_lcl_addr.s_addr); - if (!dev) -@@ -504,7 +530,7 @@ static int vif_add(struct net *net, struct vifctl *vifc, int mrtsock) - v->pkt_in = 0; - v->pkt_out = 0; - v->link = dev->ifindex; -- if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER)) -+ if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER|VIFF_NBMA)) - v->link = dev->iflink; - - /* And finish update writing critical data */ -@@ -1212,12 +1238,15 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) - { - struct ip_options * opt = &(IPCB(skb)->opt); - -- IP_INC_STATS_BH(dev_net(skb->dst->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); -+ IP_INC_STATS_BH(dev_net(skb->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); - - if (unlikely(opt->optlen)) - ip_forward_options(skb); - -- return dst_output(skb); -+ if (skb->dst != NULL) -+ return dst_output(skb); -+ else -+ return dev_queue_xmit(skb); - } - - /* -@@ -1230,7 +1259,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) - const struct iphdr *iph = ip_hdr(skb); - struct vif_device *vif = &net->ipv4.vif_table[vifi]; - struct net_device *dev; -- struct rtable *rt; -+ struct net_device *fromdev = skb->dev; -+ struct rtable *rt = NULL; - int encap = 0; - - if (vif->dev == NULL) -@@ -1257,6 +1287,19 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) - if (ip_route_output_key(net, &rt, &fl)) - goto out_free; - encap = sizeof(struct iphdr); -+ dev = rt->u.dst.dev; -+ } else if (vif->flags&VIFF_NBMA) { -+ /* Fixme, we should take tunnel source address from the -+ * tunnel device binding if it exists */ -+ struct flowi fl = { .oif = vif->link, -+ .nl_u = { .ip4_u = -+ { .daddr = vif->remote, -+ .tos = RT_TOS(iph->tos) } }, -+ .proto = IPPROTO_GRE }; -+ if (ip_route_output_key(&init_net, &rt, &fl)) -+ goto out_free; -+ encap = LL_RESERVED_SPACE(rt->u.dst.dev); -+ dev = vif->dev; - } else { - struct flowi fl = { .oif = vif->link, - .nl_u = { .ip4_u = -@@ -1265,34 +1308,39 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) - .proto = IPPROTO_IPIP }; - if (ip_route_output_key(net, &rt, &fl)) - goto out_free; -+ dev = rt->u.dst.dev; - } - -- dev = rt->u.dst.dev; -+ if (!(vif->flags & VIFF_NBMA)) { -+ if (skb->len+encap > dst_mtu(&rt->u.dst) && (ntohs(iph->frag_off) & IP_DF)) { -+ /* Do not fragment multicasts. Alas, IPv4 does not -+ allow to send ICMP, so that packets will disappear -+ to blackhole. -+ */ - -- if (skb->len+encap > dst_mtu(&rt->u.dst) && (ntohs(iph->frag_off) & IP_DF)) { -- /* Do not fragment multicasts. Alas, IPv4 does not -- allow to send ICMP, so that packets will disappear -- to blackhole. -- */ -- -- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS); -- ip_rt_put(rt); -- goto out_free; -+ IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS); -+ goto out_free_rt; -+ } - } - - encap += LL_RESERVED_SPACE(dev) + rt->u.dst.header_len; - -- if (skb_cow(skb, encap)) { -- ip_rt_put(rt); -- goto out_free; -- } -+ if (skb_cow(skb, encap)) -+ goto out_free_rt; - - vif->pkt_out++; - vif->bytes_out += skb->len; - - dst_release(skb->dst); -- skb->dst = &rt->u.dst; -+ if (vif->flags & VIFF_NBMA) { -+ ip_rt_put(rt); -+ skb->dst = NULL; -+ rt = NULL; -+ } else { -+ skb->dst = &rt->u.dst; -+ } - ip_decrease_ttl(ip_hdr(skb)); -+ skb->dev = dev; - - /* FIXME: forward and output firewalls used to be called here. - * What do we do with netfilter? -- RR */ -@@ -1301,6 +1349,10 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) - /* FIXME: extra output firewall step used to be here. --RR */ - vif->dev->stats.tx_packets++; - vif->dev->stats.tx_bytes += skb->len; -+ } else if (vif->flags & VIFF_NBMA) { -+ if (dev_hard_header(skb, dev, ntohs(skb->protocol), -+ &vif->remote, NULL, 4) < 0) -+ goto out_free_rt; - } - - IPCB(skb)->flags |= IPSKB_FORWARDED; -@@ -1316,21 +1368,30 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) - * not mrouter) cannot join to more than one interface - it will - * result in receiving multiple packets. - */ -- NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, dev, -+ NF_HOOK(PF_INET, NF_INET_FORWARD, skb, fromdev, dev, - ipmr_forward_finish); - return; - -+out_free_rt: -+ if (rt != NULL) -+ ip_rt_put(rt); - out_free: - kfree_skb(skb); - return; - } - --static int ipmr_find_vif(struct net_device *dev) -+static int ipmr_find_vif(struct net_device *dev, __be32 nbma_origin) - { - struct net *net = dev_net(dev); - int ct; - for (ct = net->ipv4.maxvif-1; ct >= 0; ct--) { -- if (net->ipv4.vif_table[ct].dev == dev) -+ if (net->ipv4.vif_table[ct].dev != dev) -+ continue; -+ -+ if (net->ipv4.vif_table[ct].flags & VIFF_NBMA) { -+ if (net->ipv4.vif_table[ct].remote == nbma_origin) -+ break; -+ } else if (nbma_origin == INADDR_ANY) - break; - } - return ct; -@@ -1351,7 +1412,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local - /* - * Wrong interface: drop packet and (maybe) send PIM assert. - */ -- if (net->ipv4.vif_table[vif].dev != skb->dev) { -+ if (!ip_mr_match_vif_skb(&net->ipv4.vif_table[vif], skb)) { - int true_vifi; - - if (skb->rtable->fl.iif == 0) { -@@ -1370,7 +1431,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local - } - - cache->mfc_un.res.wrong_if++; -- true_vifi = ipmr_find_vif(skb->dev); -+ true_vifi = ipmr_find_vif(skb->dev, ipmr_get_skb_nbma(skb)); - - if (true_vifi >= 0 && net->ipv4.mroute_do_assert && - /* pimsm uses asserts, when switching from RPT to SPT, -@@ -1479,7 +1540,7 @@ int ip_mr_input(struct sk_buff *skb) - skb = skb2; - } - -- vif = ipmr_find_vif(skb->dev); -+ vif = ipmr_find_vif(skb->dev, ipmr_get_skb_nbma(skb)); - if (vif >= 0) { - int err = ipmr_cache_unresolved(net, vif, skb); - read_unlock(&mrt_lock); -@@ -1663,7 +1724,7 @@ int ipmr_get_route(struct net *net, - } - - dev = skb->dev; -- if (dev == NULL || (vif = ipmr_find_vif(dev)) < 0) { -+ if (dev == NULL || (vif = ipmr_find_vif(dev, INADDR_ANY)) < 0) { - read_unlock(&mrt_lock); - return -ENODEV; - } |