Netdev List
 help / color / mirror / Atom feed
* Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Andrew Morton @ 2005-05-16  9:59 UTC (permalink / raw)
  To: netdev; +Cc: hejianj, linuxppc64-dev, Anton Blanchard


Might be a bug in the e100 driver, might not be.

I assume this is the

	BUG_ON(skb->list != NULL);

in __kfree_skb(), although the line number is off-by-one, and the
.__kfree_skb+0x188/0x240 would tend to contradict that.  Anton, can you
help work out where we went splat please?

tx timeouts are fairly rare events, so this might not be a recently-added
bug.

Do we know if it is repeatable?



Begin forwarded message:

Date: Mon, 16 May 2005 02:44:04 -0700
From: bugme-daemon@osdl.org
To: bugme-new@lists.osdl.org
Subject: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4


http://bugme.osdl.org/show_bug.cgi?id=4628

           Summary: Test server hang while running rhr (network) test on
                    RHEL4 with kernel 2.6.12-rc1-mm4
    Kernel Version: 2.6.12-rc1 with mm4 patch
            Status: NEW
          Severity: normal
             Owner: anton@samba.org
         Submitter: hejianj@cn.ibm.com
                CC: hanwenb@cn.ibm.com,mridge@us.ibm.com,rende@cn.ibm.com,wa
                    ngjs@cn.ibm.com


Distribution:
RHEL4 with kernel 2.6.12-rc1-mm4

Hardware Environment:
IBM OpenPower( CHRP IBM,9124-720 )

Software Environment:
RHEL4
RHR: rhr2-rhel4-1.0-14a.noarch.rpm

Problem Description:
The test server hang while running rhr (network) test on RHEL4 with kernel 
2.6.12-rc1-mm4.

Steps to reproduce:
1. Download kernel 2.6.12-rc1 and 2.6.12-rc1-mm4 patch from kernel.org, then 
build the kernel on OpenPower 720
2. Download rhr2-rhel4-1.0-14a.noarch.rpm from rhn.redhat.com and install it on 
the test machine.
3. Configure and run the rhr test via invoking redhat-ready.

Additional information:
Here is the backtrace from xmon.

3:mon> e
cpu 0x3: Vector: 700 (Program Check) at [c00000000ffe7920]
    pc: c00000000029632c: .__kfree_skb+0x188/0x240
    lr: c000000000296328: .__kfree_skb+0x184/0x240
    sp: c00000000ffe7ba0
   msr: 8000000000029032
  current = 0xc000000107f94040
  paca    = 0xc000000000431c00
    pid   = 0, comm = swapper
kernel BUG in __kfree_skb at net/core/skbuff.c:282!

3:mon> t
[c00000000ffe7c40] d0000000000ebac4 .e100_rx_clean_list+0xa0/0x144 [e100]
[c00000000ffe7ce0] d0000000000ed6dc .e100_tx_timeout+0x7c/0xb0 [e100]
[c00000000ffe7d70] c0000000002b87bc .dev_watchdog+0xc8/0x154
[c00000000ffe7e00] c00000000006d6b4 .run_timer_softirq+0x180/0x298
[c00000000ffe7ed0] c0000000000667d8 .__do_softirq+0xdc/0x1b8
[c00000000ffe7f90] c000000000014bf0 .call_do_softirq+0x14/0x24
[c000000086b43860] c0000000000102c4 .do_softirq+0x98/0xac
[c000000086b438f0] c0000000000669cc .irq_exit+0x70/0x8c
[c000000086b43970] c000000000011fb8 .timer_interrupt+0x398/0x47c
[c000000086b43a90] c00000000000a2b4 decrementer_common+0xb4/0x100
--- Exception: 901 (Decrementer) at c000000000010554 .dedicated_idle+0x114/0x280
[c000000086b43e80] c0000000000108c8 .cpu_idle+0x3c/0x54
[c000000086b43f00] c00000000003cc8c .start_secondary+0x108/0x148
[c000000086b43f90] c00000000000bd84 .enable_64b_mode+0x0/0x28

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

^ permalink raw reply

* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Jian Jun He @ 2005-05-16 10:41 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Anton Blanchard, linuxppc64-dev, netdev, Dang En Ren,
	Jia Sen Wang, Lei CDL Wang
In-Reply-To: <20050516025901.4b26ccf3.akpm@osdl.org>


[-- Attachment #1.1: Type: text/plain, Size: 5101 bytes --]



This is a reproducible defect.
At first, I can't believe that the server will suspend. But I retested the
rhr and the server hung up again. So I captured the backtrace from xmon.

BTW, the e100 driver version is 3.3.6-k2.


To Andrew:
Re-send the mail with CC list. Thanks.


Best Regards!

Jian Jun He

CSDL, Beijing
Email: hejianj@cn.ibm.com



                                                                       
             Andrew Morton                                             
             <akpm@osdl.org>                                           
                                                                        To
             2005-05-16 17:59          netdev@oss.sgi.com              
                                                                        cc
                                       Jian Jun He/China/Contr/IBM@IBMCN,
                                       linuxppc64-dev@lists.linuxppc.org,
                                       Anton Blanchard <anton@samba.org>
                                                                   Subject
                                       Fw: [Bugme-new] [Bug 4628] New: 
                                       Test server hang while running rhr
                                       (network) test on RHEL4 with kernel
                                       2.6.12-rc1-mm4                  
                                                                       
                                                                       
                                                                       
                                                                       
                                                                       
                                                                       





Might be a bug in the e100 driver, might not be.

I assume this is the

             BUG_ON(skb->list != NULL);

in __kfree_skb(), although the line number is off-by-one, and the
.__kfree_skb+0x188/0x240 would tend to contradict that.  Anton, can you
help work out where we went splat please?

tx timeouts are fairly rare events, so this might not be a recently-added
bug.

Do we know if it is repeatable?



Begin forwarded message:

Date: Mon, 16 May 2005 02:44:04 -0700
From: bugme-daemon@osdl.org
To: bugme-new@lists.osdl.org
Subject: [Bugme-new] [Bug 4628] New: Test server hang while running rhr
(network) test on RHEL4 with kernel 2.6.12-rc1-mm4


http://bugme.osdl.org/show_bug.cgi?id=4628

           Summary: Test server hang while running rhr (network) test on
                    RHEL4 with kernel 2.6.12-rc1-mm4
    Kernel Version: 2.6.12-rc1 with mm4 patch
            Status: NEW
          Severity: normal
             Owner: anton@samba.org
         Submitter: hejianj@cn.ibm.com
                CC:
hanwenb@cn.ibm.com,mridge@us.ibm.com,rende@cn.ibm.com,wa
                    ngjs@cn.ibm.com


Distribution:
RHEL4 with kernel 2.6.12-rc1-mm4

Hardware Environment:
IBM OpenPower( CHRP IBM,9124-720 )

Software Environment:
RHEL4
RHR: rhr2-rhel4-1.0-14a.noarch.rpm

Problem Description:
The test server hang while running rhr (network) test on RHEL4 with kernel
2.6.12-rc1-mm4.

Steps to reproduce:
1. Download kernel 2.6.12-rc1 and 2.6.12-rc1-mm4 patch from kernel.org,
then
build the kernel on OpenPower 720
2. Download rhr2-rhel4-1.0-14a.noarch.rpm from rhn.redhat.com and install
it on
the test machine.
3. Configure and run the rhr test via invoking redhat-ready.

Additional information:
Here is the backtrace from xmon.

3:mon> e
cpu 0x3: Vector: 700 (Program Check) at [c00000000ffe7920]
    pc: c00000000029632c: .__kfree_skb+0x188/0x240
    lr: c000000000296328: .__kfree_skb+0x184/0x240
    sp: c00000000ffe7ba0
   msr: 8000000000029032
  current = 0xc000000107f94040
  paca    = 0xc000000000431c00
    pid   = 0, comm = swapper
kernel BUG in __kfree_skb at net/core/skbuff.c:282!

3:mon> t
[c00000000ffe7c40] d0000000000ebac4 .e100_rx_clean_list+0xa0/0x144 [e100]
[c00000000ffe7ce0] d0000000000ed6dc .e100_tx_timeout+0x7c/0xb0 [e100]
[c00000000ffe7d70] c0000000002b87bc .dev_watchdog+0xc8/0x154
[c00000000ffe7e00] c00000000006d6b4 .run_timer_softirq+0x180/0x298
[c00000000ffe7ed0] c0000000000667d8 .__do_softirq+0xdc/0x1b8
[c00000000ffe7f90] c000000000014bf0 .call_do_softirq+0x14/0x24
[c000000086b43860] c0000000000102c4 .do_softirq+0x98/0xac
[c000000086b438f0] c0000000000669cc .irq_exit+0x70/0x8c
[c000000086b43970] c000000000011fb8 .timer_interrupt+0x398/0x47c
[c000000086b43a90] c00000000000a2b4 decrementer_common+0xb4/0x100
--- Exception: 901 (Decrementer) at c000000000010554
.dedicated_idle+0x114/0x280
[c000000086b43e80] c0000000000108c8 .cpu_idle+0x3c/0x54
[c000000086b43f00] c00000000003cc8c .start_secondary+0x108/0x148
[c000000086b43f90] c00000000000bd84 .enable_64b_mode+0x0/0x28

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

[-- Attachment #1.2: Type: text/html, Size: 6934 bytes --]

[-- Attachment #2: graycol.gif --]
[-- Type: image/gif, Size: 105 bytes --]

[-- Attachment #3: pic29038.gif --]
[-- Type: image/gif, Size: 1255 bytes --]

[-- Attachment #4: ecblank.gif --]
[-- Type: image/gif, Size: 45 bytes --]

^ permalink raw reply

* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Herbert Xu @ 2005-05-16 11:00 UTC (permalink / raw)
  To: Andrew Morton; +Cc: netdev, hejianj, linuxppc64-dev, anton, jgarzik
In-Reply-To: <20050516025901.4b26ccf3.akpm@osdl.org>

Andrew Morton <akpm@osdl.org> wrote:
> 
> Might be a bug in the e100 driver, might not be.
> 
> I assume this is the
> 
>        BUG_ON(skb->list != NULL);

It certainly is a bug in e100.

e100_tx_timeout -> e100_down -> e100_rx_clean_list

is racing against

e100_poll -> e100_rx_clean -> e100_rx_indicate

e100_rx_clean/e100_rx_indicate takes an skb off the RX ring and
while it's being processed e100_rx_clean_list comes along and
frees it.

>From a quick check similar problems may exist in other drivers that
have lockless ->poll() functions with RX rings.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] [SCHED] Fix unlock spinlock in error path
From: Catalin(ux aka Dino) BOIE @ 2005-05-16 13:01 UTC (permalink / raw)
  To: netdev; +Cc: davem

[-- Attachment #1: Type: TEXT/PLAIN, Size: 394 bytes --]

Hello!

In act_api.c::tcf_action_copy_stats, in error path (get_stats
returns < 0), the spinlock taken in gnet_stats_start_copy_compat
or gnet_stats_start_copy is not unlocked.

The attached patch fixes this.

Please, apply.

Thank you very much!

Signed-off-by: Catalin(ux aka Dino) BOIE <catab at umbrella.ro>

---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/

[-- Attachment #2: Type: TEXT/PLAIN, Size: 587 bytes --]

--- linux/net/sched/act_api.c	2005-03-02 09:38:33.000000000 +0200
+++ tovbug/net/sched/act_api.c	2005-04-15 13:27:54.000000000 +0300
@@ -401,7 +401,7 @@ int tcf_action_copy_stats(struct sk_buff
 
 	if (a->ops != NULL && a->ops->get_stats != NULL)
 		if (a->ops->get_stats(skb, a) < 0)
-			goto errout;
+			goto errout_stop_stats;
 
 	if (gnet_stats_copy_basic(&d, &h->bstats) < 0 ||
 #ifdef CONFIG_NET_ESTIMATOR
@@ -415,6 +415,9 @@ int tcf_action_copy_stats(struct sk_buff
 
 	return 0;
 
+errout_stop_stats:
+	gnet_stats_finish_copy(&d);
+
 errout:
 	return -1;
 }

^ permalink raw reply

* Re: [PATCH] [SCHED] Fix unlock spinlock in error path
From: Thomas Graf @ 2005-05-16 13:49 UTC (permalink / raw)
  To: Catalin(ux aka Dino) BOIE; +Cc: netdev, davem
In-Reply-To: <Pine.LNX.4.62.0505161555080.13294@webhosting.rdsbv.ro>

* Catalin(ux aka Dino) BOIE <Pine.LNX.4.62.0505161555080.13294@webhosting.rdsbv.ro> 2005-05-16 16:01
> In act_api.c::tcf_action_copy_stats, in error path (get_stats
> returns < 0), the spinlock taken in gnet_stats_start_copy_compat
> or gnet_stats_start_copy is not unlocked.

This is on purpose, get_stats() is nothing more than a placeholder
at the moment for something that should really be called dump_stats()
and have struct gnet_dump as one of its arguments. The unlocking
must be done in the internal error handling and if we ever have an
operation that could fail between _start() and _stop() for
another reason we'll need a gnet_stats_abort() (skb_trim()'ing
properly) to avoid double unlocking. But since there is no
user of this API yet it doesn't make sense to bloat the code.

^ permalink raw reply

* Re: patch tulip-natsemi-dp83840a-phy-fix.patch added to -mm tree
From: Jeff Garzik @ 2005-05-16 16:46 UTC (permalink / raw)
  To: Grant Grundler; +Cc: akpm, T-Bone, varenet, Linux Kernel, Netdev
In-Reply-To: <20050516050843.GA20107@colo.lackof.org>

Simply ensure that tulip_select_media() is always called from a process 
context. Then can you delay all you want.  Several of the calls are 
already this way, so that leaves two cases:

1) called from timer context, from the media poll timer

2) called from spin_lock_irqsave() context, in the ->tx_timeout hook.

The first case can be fixed by moved all the timer code to a workqueue. 
  Then when the existing timer fires, kick the workqueue.

The second case can be fixed by kicking the workqueue upon tx_timeout 
(which is the reason why I did not suggest queue_delayed_work() use).

See, it's not rocket science :)

	Jeff

^ permalink raw reply

* [KJ] [PATCH] Use pci_set_dma_mask() instead of direct assignment of DMA mask
From: Tobias Klauser @ 2005-05-16 17:15 UTC (permalink / raw)
  To: kernel-janitors; +Cc: akpm, netdev, jgarzik

[-- Attachment #1: Type: text/plain, Size: 1253 bytes --]

The amd8111e driver directly assigns the DMA mask to the dma_mask
member of the struct pci_dev instead of using pci_set_dma_mask(). This
makes the call to pci_dma_supported() redundant as pci_set_dma_mask()
does this check.

I do not own this device so I only compile-tested this patch.

Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>

diff -urpN -X dontdiff linux-2.6.12-rc4/drivers/net/amd8111e.c linux-2.6.12-rc4~dma_mask/drivers/net/amd8111e.c
--- linux-2.6.12-rc4/drivers/net/amd8111e.c	2005-05-07 21:53:51.000000000 +0200
+++ linux-2.6.12-rc4~dma_mask/drivers/net/amd8111e.c	2005-05-16 19:11:30.349802984 +0200
@@ -87,6 +87,7 @@ Revision History:
 #include <linux/if_vlan.h>
 #include <linux/ctype.h>	
 #include <linux/crc32.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -2002,12 +2003,11 @@ static int __devinit amd8111e_probe_one(
 	}
 
 	/* Initialize DMA */
-	if(!pci_dma_supported(pdev, 0xffffffff)){
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) < 0) {
 		printk(KERN_ERR "amd8111e: DMA not supported,"
 			"exiting.\n");
-		goto  err_free_reg;
-	} else
-		pdev->dma_mask = 0xffffffff;
+		goto err_free_reg;
+	}
 	
 	reg_addr = pci_resource_start(pdev, 0);
 	reg_len = pci_resource_len(pdev, 0);

[-- Attachment #2: Type: text/plain, Size: 167 bytes --]

_______________________________________________
Kernel-janitors mailing list
Kernel-janitors@lists.osdl.org
http://lists.osdl.org/mailman/listinfo/kernel-janitors

^ permalink raw reply

* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Ganesh Venkatesan @ 2005-05-16 17:43 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Andrew Morton, netdev, hejianj, linuxppc64-dev, anton, jgarzik
In-Reply-To: <E1DXdL8-0005mE-00@gondolin.me.apana.org.au>

Jian:

Could you try the e100 from
http://prdownloads.sourceforge.net/e1000/e100-3.4.8.tar.gz?download?
This (e100 3.4.8) has a fix for the problem you've encountered.
Specifically this driver uses netif_poll_{enable|disable} to avoid the
race.

 static int e100_up(struct nic *nic)
 {
@@ -1688,13 +1753,18 @@ static int e100_up(struct nic *nic)
        if((err = e100_hw_init(nic)))
                goto err_clean_cbs;
        e100_set_multicast_list(nic->netdev);
-       e100_start_receiver(nic);
+       e100_start_receiver(nic, 0);
        mod_timer(&nic->watchdog, jiffies);
        if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ,
                nic->netdev->name, nic->netdev)))
                goto err_no_irq;
-       e100_enable_irq(nic);
        netif_wake_queue(nic->netdev);
+#ifdef CONFIG_E100_NAPI
+       netif_poll_enable(nic->netdev);
+       /* enable ints _after_ enabling poll, preventing a race between
+        * disable ints+schedule */
+#endif
+       e100_enable_irq(nic);
        return 0;

 err_no_irq:
@@ -1708,11 +1778,15 @@ err_rx_clean_list:

 static void e100_down(struct nic *nic)
 {
+#ifdef CONFIG_E100_NAPI
+       /* wait here for poll to complete */
+       netif_poll_disable(nic->netdev);
+#endif
+       netif_stop_queue(nic->netdev);
        e100_hw_reset(nic);
        free_irq(nic->pdev->irq, nic->netdev);
        del_timer_sync(&nic->watchdog);
        netif_carrier_off(nic->netdev);
-       netif_stop_queue(nic->netdev);
        e100_clean_cbs(nic);
        e100_rx_clean_list(nic);


ganesh.


On 5/16/05, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> Andrew Morton <akpm@osdl.org> wrote:
> >
> > Might be a bug in the e100 driver, might not be.
> >
> > I assume this is the
> >
> >        BUG_ON(skb->list != NULL);
> 
> It certainly is a bug in e100.
> 
> e100_tx_timeout -> e100_down -> e100_rx_clean_list
> 
> is racing against
> 
> e100_poll -> e100_rx_clean -> e100_rx_indicate
> 
> e100_rx_clean/e100_rx_indicate takes an skb off the RX ring and
> while it's being processed e100_rx_clean_list comes along and
> frees it.
> 
> From a quick check similar problems may exist in other drivers that
> have lockless ->poll() functions with RX rings.
> 
> Cheers,
> --
> Visit Openswan at http://www.openswan.org/
> Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
> 
>

^ permalink raw reply

* Re: [patch 02/10] A new 10GB Ethernet Driver by Chelsio Communications
From: David S. Miller @ 2005-05-16 18:23 UTC (permalink / raw)
  To: hch; +Cc: jgarzik, akpm, christoph, tinay, sbardone, christoph, netdev
In-Reply-To: <20050516071218.GA17589@infradead.org>

From: Christoph Hellwig <hch@infradead.org>
Date: Mon, 16 May 2005 08:12:18 +0100

> On Sun, May 15, 2005 at 07:15:50PM -0400, Jeff Garzik wrote:
> > applied
> 
> to what tree?  the driver is still a rather huge mess..

I agree, this thing should not be applied yet.

^ permalink raw reply

* Re: [patch 02/10] A new 10GB Ethernet Driver by Chelsio Communications
From: Scott Bardone @ 2005-05-16 18:30 UTC (permalink / raw)
  To: David S. Miller; +Cc: hch, jgarzik, akpm, christoph, tinay, christoph, netdev
In-Reply-To: <20050516.112344.21928675.davem@davemloft.net>

I will have a cleanup patch available this week. Please don't appy the current 
driver yet.
Thanks,
Scott

David S. Miller wrote:
> From: Christoph Hellwig <hch@infradead.org>
> Date: Mon, 16 May 2005 08:12:18 +0100
> 
> 
>>On Sun, May 15, 2005 at 07:15:50PM -0400, Jeff Garzik wrote:
>>
>>>applied
>>
>>to what tree?  the driver is still a rather huge mess..
> 
> 
> I agree, this thing should not be applied yet.

^ permalink raw reply

* [PATCH] bonding using arp_ip_target may stay down with active path
From: Eric Paris @ 2005-05-16 18:41 UTC (permalink / raw)
  To: netdev; +Cc: jgarzik

The bonding module may get into a state in which an active path to the
network exists through at least one slave device but the bond remains
down forever.  This situation exists using the bonding options  mode=1
arp_interval=500 arp_ip_target=10.10.10.5.  mode=1 is the active/passive
bonding mode.  We determine link status using the reachability of other
network devices determined by if they respond to arp requests.

Reproducer:
The reproducer is not simple.  Easiest with 3 computers and two
crossover cables.  Configure one computer with bonding and each of the
other computers to have an address in the arp_ip_target entries for the
first machine.  In this way if both single nic computers are up bonding
should believe either of the slave interfaces are valid since each can
reach one of the arp_ip_target entries.  Shutdown the interface on the
single nic computer connected to eth0.  The bond should fail over to
eth1.  Shut down the interface connected to eth1.  The bond should
decide both the eth1 slave and the bond as a whole is down (it cannot
contact either of the arp_ip_target entries).  Run tcpdump on both of
the single nic machines and see that only the machine connected to eth0
is receiving arp requests.  Bring back up the interface connected to
eth1.  At this point we have a "valid" connection since eth1 can talk to
one of the arp targets.  But we are only sending arp requests on eth0
(verify with tcpdump)

The Problem:
The problem is in bond_activebackup_arp_mon where we say (in
bond_main.c)

if (!slave) {
        if (!bond->current_arp_slave) {
                bond->current_arp_slave = bond->first_slave;
        }
        if (bond->current_arp_slave) {
                bond_set_slave_inactive_flags(bond->current_arp_slave);

                /* search for next candidate */
                bond_for_each_slave_from(bond, slave, i,
bond->current_arp_slave) {
                        if (IS_UP(slave->dev)) {
                                slave->link = BOND_LINK_BACK;
                                bond_set_slave_active_flags(slave);
                                bond_arp_send_all(bond, slave);
                                slave->jiffies = jiffies;
                                bond->current_arp_slave = slave;
                                break;
                        }

What happens is that we set the current_arp_slave to the first interface
in the bond, bond->current_arp_slave = bond->first_slave; (in our case
eth0) and then if that slave IS_UP we send the arp requests.  IS_UP
checks only physical device information, so the NIC is up if it has
link.

We can make it fail over by pulling the cable, in which case we are !
IS_UP(eth0) and so the bond_for_each_slave_from loop continues to
IS_UP(eth1) and it finds eth1 is physically up.  It then sends the arp
requests on eth1, gets a response from the connected single nic machine
and marks the bond as a whole as up.

The patch below instead just uses bond_for_each_slave_from(bond, slave,
i, bond->current_arp_slave->next) which means that each time we enter
bond_activebackup_arp_mon without a bond->current_active_slave we will
try an interface (actually starting with the second in the list) and if
that interface does not get success the next go round
bond->current_arp_slave will be the next in the list.  This way we will
try all interfaces in turn.  I unconditionally use
current_arp_slave->next since it is a circular list and should always
have a next.

The patch below has been tested by me and appears to fix the problem.
All of the failover tests I performed seem to work including pulling
cables and stopping responses from the arp_ip_target entries.  

--- linux-2.6.11/drivers/net/bonding/bond_main.c.orig   2005-05-12 12:22:52.000000000 -0400
+++ linux-2.6.11/drivers/net/bonding/bond_main.c        2005-05-12 15:13:53.000000000 -0400
@@ -3046,7 +3046,7 @@ static void bond_activebackup_arp_mon(st
                        bond_set_slave_inactive_flags(bond->current_arp_slave);

                        /* search for next candidate */
-                       bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave) {
+                       bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave->next) {
                                if (IS_UP(slave->dev)) {
                                        slave->link = BOND_LINK_BACK;
                                        bond_set_slave_active_flags(slave);

^ permalink raw reply

* Re: [patch 02/10] A new 10GB Ethernet Driver by Chelsio Communications
From: Jeff Garzik @ 2005-05-16 19:03 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: akpm, davem, christoph, tinay, sbardone, christoph, Netdev
In-Reply-To: <20050516071218.GA17589@infradead.org>

Christoph Hellwig wrote:
> On Sun, May 15, 2005 at 07:15:50PM -0400, Jeff Garzik wrote:
> 
>>applied
> 
> 
> to what tree?  the driver is still a rather huge mess..

to the netdev-2.6 tree

^ permalink raw reply

* Re: [patch 02/10] A new 10GB Ethernet Driver by Chelsio Communications
From: Jeff Garzik @ 2005-05-16 19:06 UTC (permalink / raw)
  To: Scott Bardone, David S. Miller, hch; +Cc: akpm, christoph, tinay, netdev
In-Reply-To: <4288E6DD.6070205@chelsio.com>

Scott Bardone wrote:
> I will have a cleanup patch available this week. Please don't appy the 
> current driver yet.

The current driver has been applied to the netdev-2.6 development queue. 
  Send _incremental_ patches to me.

When everybody's happy, the 'chelsio' queue will then be pushed upstream.

	Jeff

^ permalink raw reply

* [2.6 patch] document that 8139TOO supports 8129/8130
From: Adrian Bunk @ 2005-05-16 19:13 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, linux-kernel
In-Reply-To: <4287C637.4030206@pobox.com>

On Sun, May 15, 2005 at 05:59:19PM -0400, Jeff Garzik wrote:
> Adrian Bunk wrote:
> >+	  the RTL 8129/81308139 chips. If you have one of those, say Y and
> 
> typo:  "81308139"

It wasn't easy to make a mistake in such a simple patch.  ;-)

Fixed patch below.

cu
Adrian


<--  snip  -->


The 8129/8130 support is a sub-option that is not visible if the user 
hasn't enabled the 8139 support.

Let's make it a bit easier for users to find the driver for their nic.

Signed-off-by: Adrian Bunk <bunk@stusta.de>

--- linux-2.6.12-rc4-mm1-full/drivers/net/Kconfig.old	2005-05-13 05:54:05.000000000 +0200
+++ linux-2.6.12-rc4-mm1-full/drivers/net/Kconfig	2005-05-13 06:00:21.000000000 +0200
@@ -1484,14 +1484,14 @@
 	  will be called 8139cp.  This is recommended.
 
 config 8139TOO
-	tristate "RealTek RTL-8139 PCI Fast Ethernet Adapter support"
+	tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
 	depends on NET_PCI && PCI
 	select CRC32
 	select MII
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
-	  the RTL8139 chips. If you have one of those, say Y and read
-	  the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
+	  the RTL 8129/8130/8139 chips. If you have one of those, say Y and
+	  read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8139too.  This is recommended.

^ permalink raw reply

* Re: [PATCH] [SCHED] Fix unlock spinlock in error path
From: Catalin(ux aka Dino) BOIE @ 2005-05-16 19:25 UTC (permalink / raw)
  To: Thomas Graf; +Cc: netdev, davem
In-Reply-To: <20050516134900.GC13748@postel.suug.ch>

On Mon, 16 May 2005, Thomas Graf wrote:

> * Catalin(ux aka Dino) BOIE <Pine.LNX.4.62.0505161555080.13294@webhosting.rdsbv.ro> 2005-05-16 16:01
>> In act_api.c::tcf_action_copy_stats, in error path (get_stats
>> returns < 0), the spinlock taken in gnet_stats_start_copy_compat
>> or gnet_stats_start_copy is not unlocked.
>
> This is on purpose, get_stats() is nothing more than a placeholder
> at the moment for something that should really be called dump_stats()
> and have struct gnet_dump as one of its arguments. The unlocking
> must be done in the internal error handling and if we ever have an
> operation that could fail between _start() and _stop() for
> another reason we'll need a gnet_stats_abort() (skb_trim()'ing
> properly) to avoid double unlocking. But since there is no
> user of this API yet it doesn't make sense to bloat the code.


Thanks Thomas for the explication!
Sorry for the noise.

---
Catalin(ux aka Dino) BOIE
catab at deuroconsult.ro
http://kernel.umbrella.ro/

^ permalink raw reply

* Re: Interdomain/interpartition communication without a checksum
From: David S. Miller @ 2005-05-16 20:07 UTC (permalink / raw)
  To: jdmason; +Cc: netdev, niv, habanero
In-Reply-To: <20050511183554.GA28298@us.ibm.com>

From: Jon Mason <jdmason@us.ibm.com>
Date: Wed, 11 May 2005 13:35:54 -0500

> I have been working on a Xen project to remove unnecessary TCP/UDP
> checksums for local (interdomain) communication, while still having the
> checksum for all external network communication.  

I have no objections to this idea.  But let's think about
the implementation.

> +	/* If packet is forwarded to a device that needs a checksum and not 
> +	 * checksummed, correct the pointers and enable checksumming in the 
> +	 * next function.
> +	 */
> +	if (!(dev->features & NETIF_F_FWD_NO_CSUM) && skb->csum) {
> +		skb->ip_summed = CHECKSUM_HW;
> +		skb->h.raw = (void *)skb->nh.iph + (skb->nh.iph->ihl * 4);
> +	}
> +

This means that every packet which the networking tries to checksum
offload will pass this test, superfluously doing these assignments.

It also assumes ipv4.  ipv6 is possible, and for NETIF_F_CHECKSUM_HW
any protocol could be creating the packets as this flag indicates
that the card implements a totally generic 16-bit two's complement
checksum.

^ permalink raw reply

* Re: [PATCH] [SCHED] Fix unlock spinlock in error path
From: Thomas Graf @ 2005-05-16 20:12 UTC (permalink / raw)
  To: Catalin(ux aka Dino) BOIE; +Cc: netdev, davem
In-Reply-To: <Pine.LNX.4.62.0505162224420.20204@webhosting.rdsbv.ro>

* Catalin(ux aka Dino) BOIE <Pine.LNX.4.62.0505162224420.20204@webhosting.rdsbv.ro> 2005-05-16 22:25
> Thanks Thomas for the explication!
> Sorry for the noise.

Don't worry, I should have documented this weird code part. ;->

^ permalink raw reply

* Re: [PATCH] bonding using arp_ip_target may stay down with active path
From: Jay Vosburgh @ 2005-05-16 20:34 UTC (permalink / raw)
  To: Eric Paris; +Cc: netdev, jgarzik, bonding-devel
In-Reply-To: <1116268885.3738.19.camel@dhcp59-180.rdu.redhat.com>

Eric Paris <eparis@parisplace.org> wrote:

>[...]  Bring back up the interface connected to
>eth1.  At this point we have a "valid" connection since eth1 can talk to
>one of the arp targets.  But we are only sending arp requests on eth0
>(verify with tcpdump)

	The trick is to have a situation with a partitioned network and
a failure such that the device still has link, but does not respond to
the ARP queries.  That's not an unreasonable failure if there's a switch
in each path to the arp_ip_target peers (which is how I set it up
locally).

>The patch below has been tested by me and appears to fix the problem.
>All of the failover tests I performed seem to work including pulling
>cables and stopping responses from the arp_ip_target entries.  

	The patch looks good to me, also (although I made the change by
hand instead of via patch).

	-J

---
	-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com


Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>


--- linux-2.6.11/drivers/net/bonding/bond_main.c.orig   2005-05-12 12:22:52.000000000 -0400
+++ linux-2.6.11/drivers/net/bonding/bond_main.c        2005-05-12 15:13:53.000000000 -0400
@@ -3046,7 +3046,7 @@ static void bond_activebackup_arp_mon(st
                        bond_set_slave_inactive_flags(bond->current_arp_slave);

                        /* search for next candidate */
-                       bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave) {
+                       bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave->next) {
                                if (IS_UP(slave->dev)) {
                                        slave->link = BOND_LINK_BACK;
                                        bond_set_slave_active_flags(slave);

^ permalink raw reply

* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Herbert Xu @ 2005-05-16 21:29 UTC (permalink / raw)
  To: Ganesh Venkatesan
  Cc: Andrew Morton, netdev, hejianj, linuxppc64-dev, anton, jgarzik
In-Reply-To: <5fc59ff3050516104367a8d5cd@mail.gmail.com>

On Mon, May 16, 2005 at 10:43:02AM -0700, Ganesh Venkatesan wrote:
>
> @@ -1708,11 +1778,15 @@ err_rx_clean_list:
> 
>  static void e100_down(struct nic *nic)
>  {
> +#ifdef CONFIG_E100_NAPI
> +       /* wait here for poll to complete */
> +       netif_poll_disable(nic->netdev);
> +#endif

Sorry, you can't do that here since you're in softirq context and
netif_poll_disable may sleep.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Jeff Garzik @ 2005-05-16 21:58 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Ganesh Venkatesan, Andrew Morton, netdev, hejianj, linuxppc64-dev,
	anton
In-Reply-To: <20050516212957.GA19211@gondor.apana.org.au>

Herbert Xu wrote:
> On Mon, May 16, 2005 at 10:43:02AM -0700, Ganesh Venkatesan wrote:
> 
>>@@ -1708,11 +1778,15 @@ err_rx_clean_list:
>>
>> static void e100_down(struct nic *nic)
>> {
>>+#ifdef CONFIG_E100_NAPI
>>+       /* wait here for poll to complete */
>>+       netif_poll_disable(nic->netdev);
>>+#endif
> 
> 
> Sorry, you can't do that here since you're in softirq context and
> netif_poll_disable may sleep.

I think the intention is that e100_down() may sleep, from looking at all 
the callsites.

Only e100_tx_timeout() calls it in a context that prevents sleep.

	Jeff

^ permalink raw reply

* Re: patch tulip-natsemi-dp83840a-phy-fix.patch added to -mm tree
From: Grant Grundler @ 2005-05-16 22:26 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Grant Grundler, akpm, T-Bone, varenet, Linux Kernel, Netdev
In-Reply-To: <4288CE51.1050703@pobox.com>

On Mon, May 16, 2005 at 12:46:09PM -0400, Jeff Garzik wrote:
> Simply ensure that tulip_select_media() is always called from a process 
> context. Then can you delay all you want.  Several of the calls are 
> already this way, so that leaves two cases:
> 
> 1) called from timer context, from the media poll timer
> 
> 2) called from spin_lock_irqsave() context, in the ->tx_timeout hook.
> 
> The first case can be fixed by moved all the timer code to a workqueue. 
> Then when the existing timer fires, kick the workqueue.
> 
> The second case can be fixed by kicking the workqueue upon tx_timeout 
> (which is the reason why I did not suggest queue_delayed_work() use).

Thanks - the above guidance has much more detail than you offered before
and is much more useful.
Too bad that schedule_timeout() was the only option at the time. :^(

And I apologize I don't recall what the issues were with schedule_timeout().
I suspect they will rear their ugly head with the workqueue
implementation as well. But if they don't, that will be great.

> See, it's not rocket science :)

Well, then it's a great opportunity for someone interested in hacking
NIC drivers to cut their teeth on. :^)

After three years of using/maintaining the (trivial) tulip patch
in parisc-linux tree (and shipped with RH/SuSe ia64 releases),
I don't recall anyone complaining that udelays in tulip phy reset
caused them problems. Sorry, I'm unmotivated to revisit this.
Convince someone else to make tulip to use workqueues and I'll
resubmit a clean patch on top of that for the phy init sequences.

thanks,
grant

^ permalink raw reply

* [git patches] 2.6.x net driver fixes
From: Jeff Garzik @ 2005-05-16 23:39 UTC (permalink / raw)
  To: Linus Torvalds, Andrew Morton; +Cc: Netdev, Linux Kernel

[-- Attachment #1: Type: text/plain, Size: 450 bytes --]

Here's a first experimental git push from me.  The git URL is
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

but it should be noted that I would like you to pull the 'misc-fixes' 
branch.  I'm told that branches are supposed to live in .git/refs/heads, 
so there you will find netdev-2.6.git/refs/heads/misc-fixes.

Does that work?

Changelog and patch for review attached.

	Jeff, still afraid of trying a 'tough' merge



[-- Attachment #2: changelog.txt --]
[-- Type: text/plain, Size: 2464 bytes --]

commit c8920ba041c8934b29370f5d62ab9ea8f147966b
tree 6e0e12acd812f221906289348bc4e08cd1047df6
parent c4cc26d3310a6614a20e32276228a5d44159fc9b
author Daniel Andersen <daniel@linux-user.net> Fri, 06 May 2005 05:14:09 -0700
committer Jeff Garzik <jgarzik@pobox.com> Mon, 16 May 2005 08:04:29 -0400

[PATCH] wireless: 3CRWE154G72 Kconfig help fix

Version 2 of the 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 is not
supported by the prism54 project.  To stop confusion, the kernel
documentation should state so as 3com made a good job hiding the version.

Signed-off-by: Andrew Morton <akpm@osdl.org>

diff -puN drivers/net/wireless/Kconfig~wireless-3crwe154g72-kconfig-help-fix drivers/net/wireless/Kconfig

--------------------------
commit c4cc26d3310a6614a20e32276228a5d44159fc9b
tree 35246410bf048fb6a0aa455b272f2a2933dbacad
parent 99718699f5746cc365f3a9ab4769568a1da97635
author Jiri Benc <jbenc@suse.cz> Wed, 27 Apr 2005 12:48:56 +0200
committer Jeff Garzik <jgarzik@pobox.com> Mon, 16 May 2005 07:18:48 -0400

[PATCH] Typo in tulip driver

This patch fixes a typo in tulip driver in 2.6.12-rc3.

--------------------------
commit 99718699f5746cc365f3a9ab4769568a1da97635
tree 6f8f9ad590b14514ad88c3478328795148c91e46
parent f7a3aae1723e7ffc9c4fcdb489365da7a3d81255
author Geoff Levand <geoffrey.levand@am.sony.com> Fri, 15 Apr 2005 01:20:32 -0700
committer Jeff Garzik <jgarzik@pobox.com> Mon, 16 May 2005 06:44:26 -0400

[PATCH] {PATCH] Fix IBM EMAC driver ioctl bug

Fix IBM EMAC driver ioctl bug.

I found IBM EMAC driver bug.
So mii-tool command print wrong status.

  # mii-tool
  eth0: 10 Mbit, half duplex, no link
  eth1: 10 Mbit, half duplex, no link

I can get correct status on fixed kernel.

  # mii-tool
  eth0: negotiated 100baseTx-FD, link okZZ
  eth1: negotiated 100baseTx-FD, link ok

Hiroaki Fuse

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> for CELF

--------------------------
commit f7a3aae1723e7ffc9c4fcdb489365da7a3d81255
tree 2c0a93d730060f63670d3e7f130ee12e26b3ed8f
parent 88d7bd8cb9eb8d64bf7997600b0d64f7834047c5
author Al Viro <viro@www.linux.org.uk> Sun, 03 Apr 2005 09:15:52 +0100
committer Jeff Garzik <jgarzik@pobox.com> Mon, 16 May 2005 06:22:32 -0400

[PATCH] drivers/net/wireless enabled by wrong option

	NET_WIRELESS is only a subset of the stuff in drivers/net/wireless;
NET_RADIO is what covers all of them.
Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>

--------------------------

[-- Attachment #3: patch --]
[-- Type: text/plain, Size: 1813 bytes --]

--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -187,7 +187,7 @@ obj-$(CONFIG_TR) += tokenring/
 obj-$(CONFIG_WAN) += wan/
 obj-$(CONFIG_ARCNET) += arcnet/
 obj-$(CONFIG_NET_PCMCIA) += pcmcia/
-obj-$(CONFIG_NET_WIRELESS) += wireless/
+obj-$(CONFIG_NET_RADIO) += wireless/
 obj-$(CONFIG_NET_TULIP) += tulip/
 obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1595,7 +1595,7 @@ static struct ethtool_ops emac_ethtool_o
 static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct ocp_enet_private *fep = dev->priv;
-	uint *data = (uint *) & rq->ifr_ifru;
+	uint16_t *data = (uint16_t *) & rq->ifr_ifru;
 
 	switch (cmd) {
 	case SIOCGMIIPHY:
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1104,7 +1104,7 @@ static void set_rx_mode(struct net_devic
 			if (entry != 0) {
 				/* Avoid a chip errata by prefixing a dummy entry. Don't do
 				   this on the ULI526X as it triggers a different problem */
-				if (!(tp->chip_id == ULI526X && (tp->revision = 0x40 || tp->revision == 0x50))) {
+				if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
 					tp->tx_buffers[entry].skb = NULL;
 					tp->tx_buffers[entry].mapping = 0;
 					tp->tx_ring[entry].length =
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -323,7 +323,7 @@ config PRISM54
 	  For a complete list of supported cards visit <http://prism54.org>.
 	  Here is the latest confirmed list of supported cards:
 
-	  3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+	  3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1)
 	  Allnet ALL0271 PCI Card
 	  Compex WL54G Cardbus Card
 	  Corega CG-WLCB54GT Cardbus Card

^ permalink raw reply

* [PATCH 1/2] LSM-IPSec Networking Hooks
From: Trent Jaeger @ 2005-05-17  2:55 UTC (permalink / raw)
  To: netdev, chrisw; +Cc: jaegert, sergeh, latten, sds, jmorris

Hi,

This is a new patch for extending Linux Security Modules interface to 
leverage IPSec to control socket access to network packets.  The SELinux 
module is extended to use these hooks.

Regards,
Trent.
-------------------------
Trent Jaeger
IBM T.J. Watson Research Center
19 Skyline Dr, Hawthorne, NY 10532
(914) 784-7225, (FAX) (914) 784-6209


This patch series implements per packet access control via the
extension of the Linux Security Modules (LSM) interface by hooks in
the XFRM and pfkey subsystems that leverage IPSec security
associations to label packets.  Extensions to the SELinux LSM are
included that leverage the patch for this purpose.

This patch implements the changes necessary to the XFRM subsystem,
pfkey interface, ipv4/ipv6, and xfrm_user interface to restrict
a socket to use only authorized security associations to access network 
packets (send and receive).

Patch purpose:

The patch is designed to enable access control per packets based on
the strongly authenticated IPSec security association.  Such access
controls augment the existing ones based on network interface and IP
address.  The former are very coarse-grained, and the latter can be
spoofed.  By using IPSec, the system can control access to remote
hosts based on cryptographic keys generated using the IPSec mechanism.
This enables access control on a per-machine basis or per-application
if the remote machine is running the same mechanism and trusted to
enforce the access control policy.

Patch design approach:

The overall approach is that policy (xfrm_policy) entries set by
user-level programs (e.g., setkey for ipsec-tools) are extended with a
security context that is used at policy selection time in the XFRM
subsystem to restrict the sockets that can send/receive packets via
security associations (xfrm_states) that are built from those
policies.

A presentation available at
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
from the SELinux symposium describes the overall approach.

Patch implementation details:

On output, the policy retrieved (via xfrm_policy_lookup or
xfrm_sk_policy_lookup) must be authorized for the security context of
the socket and the same security context is required for resultant
security association (retrieved or negotiated via racoon in
ipsec-tools).  This is enforced in xfrm_state_find.

On input, the policy retrieved must also be authorized for the socket
(at __xfrm_policy_check), and the security context of the policy must
also match the security association being used.

The patch has virtually no impact on packets that do not use IPSec.
The existing Netfilter (outgoing) and LSM rcv_skb hooks are used as
before.

Also, if IPSec is used without security contexts, the impact is
minimal.  The LSM must allow such policies to be selected for the
combination of socket and remote machine, but subsequent IPSec
processing proceeds as in the original case.

Testing:

The pfkey interface is tested using the ipsec-tools.  ipsec-tools have
been modified (a separate ipsec-tools patch is available for version
0.5) that supports assignment of xfrm_policy entries and security
associations with security contexts via setkey and the negotiation
using the security contexts via racoon.

The xfrm_user interface is tested via ad hoc programs that set
security contexts.  These programs are also available from me, and
contain programs for setting, getting, and deleting policy for testing
this interface.  Testing of sa functions was done by tracing kernel
behavior.

---

  include/linux/pfkeyv2.h  |   13 +++
  include/linux/security.h |  119 +++++++++++++++++++++++++++++++++++
  include/linux/xfrm.h     |   36 ++++++++++
  include/net/flow.h       |    5 -
  include/net/xfrm.h       |   21 ++++++
  net/core/flow.c          |    4 -
  net/ipv4/xfrm4_policy.c  |    2
  net/ipv6/xfrm6_policy.c  |    2
  net/key/af_key.c         |  119 +++++++++++++++++++++++++++++++++--
  net/xfrm/xfrm_policy.c   |   64 +++++++++++-------
  net/xfrm/xfrm_state.c    |   14 +++-
  net/xfrm/xfrm_user.c     |  159 +++++++++++++++++++++++++++++++++++++++++++++--
  security/Kconfig         |   13 +++
  security/dummy.c         |   37 ++++++++++
  14 files changed, 568 insertions(+), 40 deletions(-)

diff -puN include/linux/pfkeyv2.h~lsm-xfrm-nethooks include/linux/pfkeyv2.h
--- linux-2.6.12-rc4-nethooks/include/linux/pfkeyv2.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/linux/pfkeyv2.h	2005-05-10 16:19:20.000000000 -0400
@@ -216,6 +216,16 @@ struct sadb_x_nat_t_port {
  } __attribute__((packed));
  /* sizeof(struct sadb_x_nat_t_port) == 8 */

+/* Generic LSM security context */
+struct sadb_x_sec_ctx {
+	uint16_t	sadb_x_sec_len;
+	uint16_t	sadb_x_sec_exttype;
+	uint8_t		sadb_x_ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	uint8_t		sadb_x_ctx_doi;
+	uint16_t	sadb_x_ctx_len;
+} __attribute__((packed));
+/* sizeof(struct sadb_sec_ctx) = 8 */
+
  /* Message types */
  #define SADB_RESERVED		0
  #define SADB_GETSPI		1
@@ -324,7 +334,8 @@ struct sadb_x_nat_t_port {
  #define SADB_X_EXT_NAT_T_SPORT		21
  #define SADB_X_EXT_NAT_T_DPORT		22
  #define SADB_X_EXT_NAT_T_OA		23
-#define SADB_EXT_MAX			23
+#define SADB_X_EXT_SEC_CTX		24
+#define SADB_EXT_MAX			24

  /* Identity Extension values */
  #define SADB_IDENTTYPE_RESERVED	0
diff -puN include/linux/security.h~lsm-xfrm-nethooks include/linux/security.h
--- linux-2.6.12-rc4-nethooks/include/linux/security.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/linux/security.h	2005-05-16 16:12:29.000000000 -0400
@@ -58,6 +58,12 @@ struct sk_buff;
  struct sock;
  struct sockaddr;
  struct socket;
+struct flowi;
+struct dst_entry;
+struct xfrm_selector;
+struct xfrm_policy;
+struct xfrm_state;
+struct sadb_x_sec_ctx;

  extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
  extern int cap_netlink_recv(struct sk_buff *skb);
@@ -802,6 +808,50 @@ struct swap_info_struct;
   * @sk_free_security:
   *	Deallocate security structure.
   *
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+ *	@xp contains the xfrm_policy being added to Security Policy Database
+ *      used by the XFRM system.
+ *      @sec_ctx contains the security context information being provided by
+ *      the user-level policy update program (e.g., setkey).
+ *      Allocate a security structure to the xp->selector.security field.
+ *      The security field is initialized to NULL when the xfrm_policy is
+ *      allocated.
+ *	Return 0 if operation was successful (memory to allocate, legal context)
+ * @xfrm_policy_clone_security:
+ *      @old contains an existing xfrm_policy in the SPD.
+ *      @new contains a new xfrm_policy being cloned from old.
+ *      Allocate a security structure to the new->selector.security field
+ *      that contains the information from the old->selector.security field.
+ *	Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+ *      @xp contains the xfrm_policy
+ *      Deallocate xp->selector.security.
+ * @xfrm_state_alloc_security:
+ *      @x contains the xfrm_state being added to the Security Association
+ *      Database by the XFRM system.
+ *      @sec_ctx contains the security context information being provided by
+ *      the user-level SA generation program (e.g., setkey or racoon).
+ *      Allocate a security structure to the x->sel.security field.  The
+ *      security field is initialized to NULL when the xfrm_state is
+ *      allocated.
+ *	Return 0 if operation was successful (memory to allocate, legal context).
+ * @xfrm_state_free_security:
+ *      @x contains the xfrm_state.
+ *      Deallocate x>sel.security.
+ * @xfrm_policy_lookup:
+ *      @sk contains the sock that is requesting to either send or receive a
+ *      network communication.
+ *      @sel contains the selector that matches the communication end points of
+ *      the network communication (source, destination, and ports).
+ *      @fl contains the flowi that indicates the communication protocol.
+ *      @dir contains the direction of the flow (input or output).
+ *	Check permission when a sock selects a xfrm_policy for processing
+ *      XFRMs on a packet.  The hook is called when selecting either a
+ *      per-socket policy or a generic xfrm policy.
+ *	Return 0 if permission is granted.
+ *
   * Security hooks affecting all System V IPC operations.
   *
   * @ipc_permission:
@@ -1243,6 +1293,15 @@ struct security_operations {
  	int (*sk_alloc_security) (struct sock *sk, int family, int priority);
  	void (*sk_free_security) (struct sock *sk);
  #endif	/* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+	int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx);
+	int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
+	void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+	int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx);
+	void (*xfrm_state_free_security) (struct xfrm_state *x);
+	int (*xfrm_policy_lookup)(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir);
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
  };

  /* global variables */
@@ -2854,5 +2913,65 @@ static inline void security_sk_free(stru
  }
  #endif	/* CONFIG_SECURITY_NETWORK */

+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+        return security_ops->xfrm_policy_clone_security(old, new);
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+        security_ops->xfrm_policy_free_security(xp);
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_state_alloc_security(x, sec_ctx);
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+        security_ops->xfrm_state_free_security(x);
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return security_ops->xfrm_policy_lookup(sk, sel, fl, dir);
+}
+#else	/* CONFIG_SECURITY_NETWORK_XFRM */
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
+
  #endif /* ! __LINUX_SECURITY_H */

diff -puN include/linux/xfrm.h~lsm-xfrm-nethooks include/linux/xfrm.h
--- linux-2.6.12-rc4-nethooks/include/linux/xfrm.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/linux/xfrm.h	2005-05-10 16:22:40.000000000 -0400
@@ -27,6 +27,22 @@ struct xfrm_id
  	__u8		proto;
  };

+struct xfrm_sec_ctx {
+	__u8	ctx_doi;
+	__u8	ctx_alg;
+	__u16	ctx_len;
+	__u32	ctx_sid;
+	char	ctx_str[0];
+};
+
+/* Security Context Domains of Interpretation */
+#define XFRM_SC_DOI_RESERVED 0
+#define XFRM_SC_DOI_LSM 1
+
+/* Security Context Algorithms */
+#define XFRM_SC_ALG_RESERVED 0
+#define XFRM_SC_ALG_SELINUX 1
+
  /* Selector, used as selector both on policy rules (SPD) and SAs. */

  struct xfrm_selector
@@ -43,8 +59,15 @@ struct xfrm_selector
  	__u8	proto;
  	int	ifindex;
  	uid_t	user;
+	struct xfrm_sec_ctx *security;
  };

+/* All but the security field */
+static inline int xfrm_selector_base_size(void)
+{
+	return sizeof(struct xfrm_selector) - sizeof(struct xfrm_sec_ctx *);
+}
+
  #define XFRM_INF (~(__u64)0)

  struct xfrm_lifetime_cfg
@@ -146,6 +169,18 @@ enum {

  #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)

+/*
+ * Generic LSM security context for comunicating to user space
+ * NOTE: Same format as sadb_x_sec_ctx
+ */
+struct xfrm_user_sec_ctx {
+	__u16			len;
+	__u16			exttype;
+	__u8			ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	__u8			ctx_doi;
+	__u16			ctx_len;
+};
+
  struct xfrm_user_tmpl {
  	struct xfrm_id		id;
  	__u16			family;
@@ -173,6 +208,7 @@ enum xfrm_attr_type_t {
  	XFRMA_ALG_CRYPT,	/* struct xfrm_algo */
  	XFRMA_ALG_COMP,		/* struct xfrm_algo */
  	XFRMA_ENCAP,		/* struct xfrm_algo + struct xfrm_encap_tmpl */
+	XFRMA_SEC_CTX,          /* struct xfrm_sec_ctx */
  	XFRMA_TMPL,		/* 1 or more struct xfrm_user_tmpl */
  	__XFRMA_MAX

diff -puN include/net/flow.h~lsm-xfrm-nethooks include/net/flow.h
--- linux-2.6.12-rc4-nethooks/include/net/flow.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/net/flow.h	2005-05-10 15:04:25.000000000 -0400
@@ -84,10 +84,11 @@ struct flowi {
  #define FLOW_DIR_OUT	1
  #define FLOW_DIR_FWD	2

-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+struct sock;
+typedef void (*flow_resolve_t)(struct flowi *key, struct sock *sk, u16 family, u8 dir,
  			       void **objp, atomic_t **obj_refp);

-extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+extern void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16 family, u8 dir,
  			       flow_resolve_t resolver);
  extern void flow_cache_flush(void);
  extern atomic_t flow_cache_genid;
diff -puN include/net/xfrm.h~lsm-xfrm-nethooks include/net/xfrm.h
--- linux-2.6.12-rc4-nethooks/include/net/xfrm.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/net/xfrm.h	2005-05-12 15:38:22.000000000 -0400
@@ -493,6 +493,27 @@ xfrm_selector_match(struct xfrm_selector
  	return 0;
  }

+/* If neither has a context --> match
+   Otherwise, both must have a context and the sids, doi, alg must match */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+	return ((!s1 && !s2) ||
+		(s1 && s2 &&
+		 (s1->ctx_sid == s2->ctx_sid) &&
+		 (s1->ctx_doi == s2->ctx_doi) &&
+		 (s1->ctx_alg == s2->ctx_alg)));
+}
+
+static inline struct xfrm_sec_ctx *xfrm_policy_security(struct xfrm_policy *xp)
+{
+	return (xp ? xp->selector.security : NULL);
+}
+
+static inline struct xfrm_sec_ctx *xfrm_state_security(struct xfrm_state *x)
+{
+	return (x ? x->sel.security : NULL);
+}
+
  /* A struct encoding bundle of transformations to apply to some set of flow.
   *
   * dst->child points to the next element of bundle.
diff -puN net/core/flow.c~lsm-xfrm-nethooks net/core/flow.c
--- linux-2.6.12-rc4-nethooks/net/core/flow.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/core/flow.c	2005-05-10 15:04:25.000000000 -0400
@@ -162,7 +162,7 @@ static int flow_key_compare(struct flowi
  	return 0;
  }

-void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16 family, u8 dir,
  			flow_resolve_t resolver)
  {
  	struct flow_cache_entry *fle, **head;
@@ -221,7 +221,7 @@ nocache:
  		void *obj;
  		atomic_t *obj_ref;

-		resolver(key, family, dir, &obj, &obj_ref);
+		resolver(key, sk, family, dir, &obj, &obj_ref);

  		if (fle) {
  			fle->genid = atomic_read(&flow_cache_genid);
diff -puN net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks net/ipv4/xfrm4_policy.c
--- linux-2.6.12-rc4-nethooks/net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/ipv4/xfrm4_policy.c	2005-05-16 13:33:47.000000000 -0400
@@ -36,6 +36,8 @@ __xfrm4_find_bundle(struct flowi *fl, st
  		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
  		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
  	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+ 		    xfrm_sec_ctx_match(xfrm_policy_security(policy),
+				       xfrm_state_security(dst->xfrm)) &&
  		    xfrm_bundle_ok(xdst, fl, AF_INET)) {
  			dst_clone(dst);
  			break;
diff -puN net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks net/ipv6/xfrm6_policy.c
--- linux-2.6.12-rc4-nethooks/net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/ipv6/xfrm6_policy.c	2005-05-10 15:13:49.000000000 -0400
@@ -54,6 +54,8 @@ __xfrm6_find_bundle(struct flowi *fl, st
  				 xdst->u.rt6.rt6i_src.plen);
  		if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
  		    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
+ 		    xfrm_sec_ctx_match(xfrm_policy_security(policy),
+ 				       xfrm_state_security(dst->xfrm)) &&
  		    xfrm_bundle_ok(xdst, fl, AF_INET6)) {
  			dst_clone(dst);
  			break;
diff -puN net/key/af_key.c~lsm-xfrm-nethooks net/key/af_key.c
--- linux-2.6.12-rc4-nethooks/net/key/af_key.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/key/af_key.c	2005-05-16 16:13:56.000000000 -0400
@@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = {
  	[SADB_X_EXT_NAT_T_SPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
  	[SADB_X_EXT_NAT_T_DPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
  	[SADB_X_EXT_NAT_T_OA]		= (u8) sizeof(struct sadb_address),
+        [SADB_X_EXT_SEC_CTX]            = (u8) sizeof(struct sadb_x_sec_ctx),
  };

  /* Verify sadb_address_{len,prefixlen} against sa_family.  */
@@ -383,6 +384,22 @@ static int verify_address_len(void *p)
  	return 0;
  }

+static inline int verify_sec_ctx_len(void *p)
+{
+	struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
+	int len = 0;
+
+	len += sizeof(struct sadb_x_sec_ctx);
+	len += sec_ctx->sadb_x_ctx_len;
+	len += sizeof(uint64_t) - 1;
+	len /= sizeof(uint64_t);
+
+	if (sec_ctx->sadb_x_sec_len != len)
+		return -EINVAL;
+
+	return 0;
+}
+
  static int present_and_same_family(struct sadb_address *src,
  				   struct sadb_address *dst)
  {
@@ -438,6 +455,10 @@ static int parse_exthdrs(struct sk_buff
  				if (verify_address_len(p))
  					return -EINVAL;
  			} 
+			if (ext_type == SADB_X_EXT_SEC_CTX) {
+				if (verify_sec_ctx_len(p))
+					return -EINVAL;
+			}
  			ext_hdrs[ext_type-1] = p;
  		}
  		p   += ext_len;
@@ -586,6 +607,9 @@ static struct sk_buff * pfkey_xfrm_state
  	struct sadb_key *key;
  	struct sadb_x_sa2 *sa2;
  	struct sockaddr_in *sin;
+	struct sadb_x_sec_ctx *sec_ctx;
+	struct xfrm_sec_ctx *xfrm_ctx;
+	int ctx_size = 0;
  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  	struct sockaddr_in6 *sin6;
  #endif
@@ -609,6 +633,12 @@ static struct sk_buff * pfkey_xfrm_state
  			sizeof(struct sadb_address)*2 +
  				sockaddr_size*2 +
  					sizeof(struct sadb_x_sa2);
+
+	if ((xfrm_ctx = xfrm_state_security(x))) {
+		ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
+		size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
+        }
+
  	/* identity & sensitivity */

  	if ((x->props.family == AF_INET &&
@@ -892,6 +922,20 @@ static struct sk_buff * pfkey_xfrm_state
  		n_port->sadb_x_nat_t_port_reserved = 0;
  	}

+	/* security context */
+        if (xfrm_ctx) {
+		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
+				sizeof(struct sadb_x_sec_ctx) + ctx_size);
+		sec_ctx->sadb_x_sec_len =
+		  (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
+		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+		       xfrm_ctx->ctx_len);
+	}
+
  	return skb;
  }

@@ -902,6 +946,7 @@ static struct xfrm_state * pfkey_msg2xfr
  	struct sadb_lifetime *lifetime;
  	struct sadb_sa *sa;
  	struct sadb_key *key;
+	struct sadb_x_sec_ctx *sec_ctx;
  	uint16_t proto;
  	int err;

@@ -984,6 +1029,13 @@ static struct xfrm_state * pfkey_msg2xfr
  		x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;
  		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
  	}
+
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	if (sec_ctx != NULL) {
+		if (security_xfrm_state_alloc(x, sec_ctx))
+			goto out;
+	}
+
  	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
  	if (sa->sadb_sa_auth) {
  		int keysize = 0;
@@ -1634,6 +1686,18 @@ parse_ipsecrequests(struct xfrm_policy *
  	return 0;
  }

+static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx) {
+		int len = sizeof(struct sadb_x_sec_ctx);
+		len += xfrm_ctx->ctx_len;
+		return PFKEY_ALIGN8(len);
+	}
+	return 0;
+}
+
  static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
  {
  	int sockaddr_size = pfkey_sockaddr_size(xp->family);
@@ -1647,7 +1711,8 @@ static int pfkey_xfrm_policy2msg_size(st
  		(sockaddr_size * 2) +
  		sizeof(struct sadb_x_policy) +
  		(xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) +
-				(socklen * 2)));
+				(socklen * 2))) +
+		pfkey_xfrm_policy2sec_ctx_size(xp);
  }

  static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
@@ -1671,6 +1736,8 @@ static void pfkey_xfrm_policy2msg(struct
  	struct sadb_lifetime *lifetime;
  	struct sadb_x_policy *pol;
  	struct sockaddr_in   *sin;
+	struct sadb_x_sec_ctx *sec_ctx;
+	struct xfrm_sec_ctx *xfrm_ctx;
  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  	struct sockaddr_in6  *sin6;
  #endif
@@ -1855,19 +1922,35 @@ static void pfkey_xfrm_policy2msg(struct
  			}
  		}
  	}
+
+	/* security context */
+        if ((xfrm_ctx = xfrm_policy_security(xp))) {
+		int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);
+
+		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size);
+		sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);
+		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+		       xfrm_ctx->ctx_len);
+	}
+
  	hdr->sadb_msg_len = size / sizeof(uint64_t);
  	hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
  }

  static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
  {
-	int err;
+	int err = 0;
  	struct sadb_lifetime *lifetime;
  	struct sadb_address *sa;
  	struct sadb_x_policy *pol;
  	struct xfrm_policy *xp;
  	struct sk_buff *out_skb;
  	struct sadb_msg *out_hdr;
+	struct sadb_x_sec_ctx *sec_ctx;

  	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
  				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -1914,6 +1997,12 @@ static int pfkey_spdadd(struct sock *sk,
  	if (xp->selector.dport)
  		xp->selector.dport_mask = ~0;

+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	if (sec_ctx != NULL) {
+		if (security_xfrm_policy_alloc(xp, sec_ctx))
+			goto out;
+	}
+
  	xp->lft.soft_byte_limit = XFRM_INF;
  	xp->lft.hard_byte_limit = XFRM_INF;
  	xp->lft.soft_packet_limit = XFRM_INF;
@@ -1963,6 +2052,7 @@ static int pfkey_spdadd(struct sock *sk,
  	return 0;

  out:
+	security_xfrm_policy_free(xp);
  	kfree(xp);
  	return err;
  }
@@ -1972,10 +2062,11 @@ static int pfkey_spddelete(struct sock *
  	int err;
  	struct sadb_address *sa;
  	struct sadb_x_policy *pol;
-	struct xfrm_policy *xp;
+	struct xfrm_policy *xp, tmp;
  	struct sk_buff *out_skb;
  	struct sadb_msg *out_hdr;
  	struct xfrm_selector sel;
+	struct sadb_x_sec_ctx *sec_ctx;

  	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
  				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2004,7 +2095,15 @@ static int pfkey_spddelete(struct sock *
  	if (sel.dport)
  		sel.dport_mask = ~0;

-	xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1);
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	memcpy(&tmp.selector, &sel, sizeof(struct xfrm_selector));
+	if (sec_ctx != NULL) {
+		if (security_xfrm_policy_alloc(&tmp, sec_ctx))
+			goto out;
+	}
+
+	xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &tmp.selector, 1);
+	security_xfrm_policy_free(&tmp);
  	if (xp == NULL)
  		return -ENOENT;

@@ -2482,6 +2581,7 @@ static struct xfrm_policy *pfkey_compile
  {
  	struct xfrm_policy *xp;
  	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
+	struct sadb_x_sec_ctx *sec_ctx;

  	switch (family) {
  	case AF_INET:
@@ -2531,10 +2631,21 @@ static struct xfrm_policy *pfkey_compile
  	    (*dir = parse_ipsecrequests(xp, pol)) < 0)
  		goto out;

+	/* security context too */
+	if (len >= (pol->sadb_x_policy_len*8 +
+		    sizeof(struct sadb_x_sec_ctx))) {
+		char *p = (char *) pol;
+		p += pol->sadb_x_policy_len*8;
+		sec_ctx = (struct sadb_x_sec_ctx *) p;
+		if (security_xfrm_policy_alloc(xp, sec_ctx))
+			goto out;
+	}
+
  	*dir = pol->sadb_x_policy_dir-1;
  	return xp;

  out:
+	security_xfrm_policy_free(xp);
  	kfree(xp);
  	return NULL;
  }
diff -puN net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks net/xfrm/xfrm_policy.c
--- linux-2.6.12-rc4-nethooks/net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/xfrm/xfrm_policy.c	2005-05-16 16:16:54.000000000 -0400
@@ -257,6 +257,7 @@ void __xfrm_policy_destroy(struct xfrm_p
  	if (del_timer(&policy->timer))
  		BUG();

+	security_xfrm_policy_free(policy);
  	kfree(policy);
  }
  EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -396,7 +397,8 @@ struct xfrm_policy *xfrm_policy_bysel(in

  	write_lock_bh(&xfrm_policy_lock);
  	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
-		if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
+		if ((memcmp(sel, &pol->selector, xfrm_selector_base_size()) == 0) &&
+		    (xfrm_sec_ctx_match(sel->security, xfrm_policy_security(pol)))) {
  			xfrm_pol_hold(pol);
  			if (delete)
  				*p = pol->next;
@@ -492,7 +494,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);

  /* Find policy to apply to this flow. */

-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static void xfrm_policy_lookup(struct flowi *fl, struct sock *sk, u16 family, u8 dir,
  			       void **objp, atomic_t **obj_refp)
  {
  	struct xfrm_policy *pol;
@@ -506,9 +508,12 @@ static void xfrm_policy_lookup(struct fl
  			continue;

  		match = xfrm_selector_match(sel, fl, family);
+
  		if (match) {
-			xfrm_pol_hold(pol);
-			break;
+ 			if (!security_xfrm_policy_lookup(sk, sel, fl, dir)) {
+				xfrm_pol_hold(pol);
+				break;
+			}
  		}
  	}
  	read_unlock_bh(&xfrm_policy_lock);
@@ -516,15 +521,38 @@ static void xfrm_policy_lookup(struct fl
  		*obj_refp = &pol->refcnt;
  }

+static inline int policy_to_flow_dir(int dir)
+{
+	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
+ 	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+ 	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
+ 		return dir;
+ 	switch (dir) {
+ 	default:
+ 	case XFRM_POLICY_IN:
+ 		return FLOW_DIR_IN;
+ 	case XFRM_POLICY_OUT:
+ 		return FLOW_DIR_OUT;
+ 	case XFRM_POLICY_FWD:
+ 		return FLOW_DIR_FWD;
+	};
+}
+
  static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
  {
  	struct xfrm_policy *pol;

  	read_lock_bh(&xfrm_policy_lock);
  	if ((pol = sk->sk_policy[dir]) != NULL) {
-		int match = xfrm_selector_match(&pol->selector, fl,
+ 		struct xfrm_selector *sel = &pol->selector;
+ 		int match = xfrm_selector_match(sel, fl,
  						sk->sk_family);
+ 		int err = 0;
+
  		if (match)
+ 			err = security_xfrm_policy_lookup(sk, sel, fl, policy_to_flow_dir(dir));
+
+ 		if (match && !err)
  			xfrm_pol_hold(pol);
  		else
  			pol = NULL;
@@ -595,6 +623,10 @@ static struct xfrm_policy *clone_policy(

  	if (newp) {
  		newp->selector = old->selector;
+		if (security_xfrm_policy_clone(old, newp)) {
+			kfree(newp);
+			return (struct xfrm_policy *)NULL;  /* ENOMEM */
+		}
  		newp->lft = old->lft;
  		newp->curlft = old->curlft;
  		newp->action = old->action;
@@ -706,22 +738,6 @@ xfrm_bundle_create(struct xfrm_policy *p
  	return err;
  }

-static inline int policy_to_flow_dir(int dir)
-{
-	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
-	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
-	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
-		return dir;
-	switch (dir) {
-	default:
-	case XFRM_POLICY_IN:
-		return FLOW_DIR_IN;
-	case XFRM_POLICY_OUT:
-		return FLOW_DIR_OUT;
-	case XFRM_POLICY_FWD:
-		return FLOW_DIR_FWD;
-	};
-}

  static int stale_bundle(struct dst_entry *dst);

@@ -751,7 +767,7 @@ restart:
  		if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
  			return 0;

-		policy = flow_cache_lookup(fl, family,
+		policy = flow_cache_lookup(fl, sk, family,
  					   policy_to_flow_dir(XFRM_POLICY_OUT),
  					   xfrm_policy_lookup);
  	}
@@ -942,7 +958,7 @@ int __xfrm_policy_check(struct sock *sk,
  		int i;

  		for (i=skb->sp->len-1; i>=0; i--) {
-		  struct sec_decap_state *xvec = &(skb->sp->x[i]);
+			struct sec_decap_state *xvec = &(skb->sp->x[i]);
  			if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
  				return 0;

@@ -960,7 +976,7 @@ int __xfrm_policy_check(struct sock *sk,
  		pol = xfrm_sk_policy_lookup(sk, dir, &fl);

  	if (!pol)
-		pol = flow_cache_lookup(&fl, family,
+		pol = flow_cache_lookup(&fl, sk, family,
  					policy_to_flow_dir(dir),
  					xfrm_policy_lookup);

diff -puN net/xfrm/xfrm_state.c~lsm-xfrm-nethooks net/xfrm/xfrm_state.c
--- linux-2.6.12-rc4-nethooks/net/xfrm/xfrm_state.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/xfrm/xfrm_state.c	2005-05-16 15:49:41.000000000 -0400
@@ -74,6 +74,7 @@ static void xfrm_state_gc_destroy(struct
  		x->type->destructor(x);
  		xfrm_put_type(x->type);
  	}
+	security_xfrm_state_free(x);
  	kfree(x);
  }

@@ -338,7 +339,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
  			      selector.
  			 */
  			if (x->km.state == XFRM_STATE_VALID) {
-				if (!xfrm_selector_match(&x->sel, fl, family))
+				if (!xfrm_selector_match(&x->sel, fl, family) ||
+				    !xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
  					continue;
  				if (!best ||
  				    best->km.dying > x->km.dying ||
@@ -349,7 +351,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
  				acquire_in_progress = 1;
  			} else if (x->km.state == XFRM_STATE_ERROR ||
  				   x->km.state == XFRM_STATE_EXPIRED) {
-				if (xfrm_selector_match(&x->sel, fl, family))
+ 				if (xfrm_selector_match(&x->sel, fl, family) &&
+				    xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
  					error = -ESRCH;
  			}
  		}
@@ -374,6 +377,13 @@ xfrm_state_find(xfrm_address_t *daddr, x
  		xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);

  		if (km_query(x, tmpl, pol) == 0) {
+			if (!xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x))) {
+				x->km.state = XFRM_STATE_DEAD;
+				xfrm_state_put(x);
+				x = NULL;
+				error = 1;
+				goto out;
+			}
  			x->km.state = XFRM_STATE_ACQ;
  			list_add_tail(&x->bydst, xfrm_state_bydst+h);
  			xfrm_state_hold(x);
diff -puN net/xfrm/xfrm_user.c~lsm-xfrm-nethooks net/xfrm/xfrm_user.c
--- linux-2.6.12-rc4-nethooks/net/xfrm/xfrm_user.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/xfrm/xfrm_user.c	2005-05-16 16:20:27.000000000 -0400
@@ -200,6 +200,32 @@ static int attach_encap_tmpl(struct xfrm
  	return 0;
  }

+
+static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+	int len;
+
+	if (xfrm_ctx) {
+		len = sizeof(struct xfrm_user_sec_ctx);
+		len += xfrm_ctx->ctx_len;
+		return len;
+	}
+	return 0;
+}
+
+static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg)
+{
+	struct xfrm_user_sec_ctx *uxsc = RTA_DATA(u_arg);
+
+	if (uxsc) {
+		security_xfrm_state_free(x);
+		return security_xfrm_state_alloc(x, uxsc);
+	}
+
+	return 0;
+}
+
  static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
  {
  	memcpy(&x->id, &p->id, sizeof(x->id));
@@ -249,6 +275,9 @@ static struct xfrm_state *xfrm_state_con
  	if (err)
  		goto error;

+	if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1])))
+		goto error;
+
  	x->curlft.add_time = (unsigned long) xtime.tv_sec;
  	x->km.state = XFRM_STATE_VALID;
  	x->km.seq = p->seq;
@@ -335,6 +364,27 @@ struct xfrm_dump_info {
  	int this_idx;
  };

+static int dump_one_sec_ctx(struct xfrm_sec_ctx *ctx, struct xfrm_user_sec_ctx *uctx, struct sk_buff *skb, int ctx_size)
+{
+	if (!ctx)
+		return -1;
+
+	uctx->exttype = XFRMA_SEC_CTX;
+	uctx->len = ctx_size;
+	uctx->ctx_doi = ctx->ctx_doi;
+	uctx->ctx_alg = ctx->ctx_alg;
+	uctx->ctx_len = ctx->ctx_len;
+
+	memcpy(uctx + 1, ctx->ctx_str, ctx->ctx_len);
+
+	RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size, uctx);
+
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
  static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
  {
  	struct xfrm_dump_info *sp = ptr;
@@ -343,6 +393,7 @@ static int dump_one_state(struct xfrm_st
  	struct xfrm_usersa_info *p;
  	struct nlmsghdr *nlh;
  	unsigned char *b = skb->tail;
+	struct xfrm_sec_ctx *xfrm_ctx;

  	if (sp->this_idx < sp->start_idx)
  		goto out;
@@ -367,6 +418,18 @@ static int dump_one_state(struct xfrm_st
  	if (x->encap)
  		RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);

+	if ((xfrm_ctx = xfrm_state_security(x))) {
+		int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+			xfrm_ctx->ctx_len + 1;
+		struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL);
+		int err;
+
+	        err = dump_one_sec_ctx(xfrm_ctx, uctx, skb, ctx_size);
+		kfree(uctx);
+
+		if (err < 0)
+			goto rtattr_failure;
+	}
  	nlh->nlmsg_len = skb->tail - b;
  out:
  	sp->this_idx++;
@@ -580,6 +643,27 @@ static int verify_newpolicy_info(struct
  	return verify_policy_dir(p->dir);
  }

+static int copy_sec_ctx(struct xfrm_policy *pol, struct xfrm_user_sec_ctx *uctx)
+{
+	int err = 0;
+
+	security_xfrm_policy_free(pol);
+	err = security_xfrm_policy_alloc(pol, uctx);
+	return err;
+}
+
+static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct rtattr **xfrma)
+{
+	struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
+	struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+	if (uctx) {
+		copy_sec_ctx(pol, uctx);
+	}
+
+	return 0;
+}
+
  static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
  			   int nr)
  {
@@ -658,7 +742,10 @@ static struct xfrm_policy *xfrm_policy_c
  	}

  	copy_from_user_policy(xp, p);
-	err = copy_from_user_tmpl(xp, xfrma);
+
+	if (!(err = copy_from_user_tmpl(xp, xfrma)))
+		err = copy_from_user_sec_ctx(xp, xfrma);
+
  	if (err) {
  		*errp = err;
  		kfree(xp);
@@ -728,6 +815,27 @@ rtattr_failure:
  	return -1;
  }

+static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb, int src)
+{
+	int err = 0;
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx) {
+		int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+			xfrm_ctx->ctx_len;
+		struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL);
+
+		if (!uctx)
+			return -ENOMEM;
+
+	        err = dump_one_sec_ctx(xfrm_ctx, uctx, skb,
+				       ctx_size);
+		kfree(uctx);
+	}
+
+	return err;
+}
+
  static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
  {
  	struct xfrm_dump_info *sp = ptr;
@@ -749,6 +857,8 @@ static int dump_one_policy(struct xfrm_p
  	copy_to_user_policy(xp, p, dir);
  	if (copy_to_user_tmpl(xp, skb) < 0)
  		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 0) < 0)
+		goto nlmsg_failure;

  	nlh->nlmsg_len = skb->tail - b;
  out:
@@ -804,7 +914,7 @@ static struct sk_buff *xfrm_policy_netli

  static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
  {
-	struct xfrm_policy *xp;
+	struct xfrm_policy *xp, tmp;
  	struct xfrm_userpolicy_id *p;
  	int err;
  	int delete;
@@ -818,8 +928,20 @@ static int xfrm_get_policy(struct sk_buf

  	if (p->index)
  		xp = xfrm_policy_byid(p->dir, p->index, delete);
-	else
-		xp = xfrm_policy_bysel(p->dir, &p->sel, delete);
+	else {
+		struct rtattr **rtattrs = (struct rtattr **) xfrma;
+		struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+
+		memcpy(&tmp.selector, &p->sel, sizeof(struct xfrm_selector));
+		if (rt) {
+			struct xfrm_user_sec_ctx *uxsc = RTA_DATA(rt);
+
+			if ((err = security_xfrm_policy_alloc(&tmp, uxsc)))
+				return err;
+		}
+		xp = xfrm_policy_bysel(p->dir, &tmp.selector, delete);
+		security_xfrm_policy_free(&tmp);
+	}
  	if (xp == NULL)
  		return -ENOENT;

@@ -1101,6 +1223,8 @@ static int build_acquire(struct sk_buff

  	if (copy_to_user_tmpl(xp, skb) < 0)
  		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 1) < 0)
+		goto nlmsg_failure;

  	nlh->nlmsg_len = skb->tail - b;
  	return skb->len;
@@ -1114,10 +1238,12 @@ static int xfrm_send_acquire(struct xfrm
  			     struct xfrm_policy *xp, int dir)
  {
  	struct sk_buff *skb;
+	struct xfrm_sec_ctx *ctx;
  	size_t len;

  	len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
  	len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
+	len += xfrm_user_sec_ctx_size(xp);
  	skb = alloc_skb(len, GFP_ATOMIC);
  	if (skb == NULL)
  		return -ENOMEM;
@@ -1138,8 +1264,9 @@ static struct xfrm_policy *xfrm_compile_
  {
  	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
  	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
+	struct xfrm_user_sec_ctx *uctx;
  	struct xfrm_policy *xp;
-	int nr;
+	int nr = 0;

  	switch (family) {
  	case AF_INET:
@@ -1167,9 +1294,26 @@ static struct xfrm_policy *xfrm_compile_
  	    verify_newpolicy_info(p))
  		return NULL;

+ 	if (len > (sizeof(*p) + (XFRM_MAX_DEPTH *
+				 sizeof(struct xfrm_user_tmpl)))) {
+ 		struct xfrm_user_tmpl *tmpl;
+ 		uctx = (struct xfrm_user_sec_ctx *) (ut + XFRM_MAX_DEPTH);
+
+ 		if (len != sizeof(*p) +
+		    (XFRM_MAX_DEPTH * sizeof(struct xfrm_user_tmpl)) +
+		    uctx->len)
+ 			return NULL;
+
+                 /* spi must be zero'd unless real tmpl */
+ 		for (tmpl = ut; tmpl->id.spi != 0; tmpl = tmpl + 1)
+ 			nr++;
+ 	}
+ 	else {
+ 		uctx = (struct xfrm_user_sec_ctx *) NULL;
  	nr = ((len - sizeof(*p)) / sizeof(*ut));
  	if (nr > XFRM_MAX_DEPTH)
  		return NULL;
+ 	}

  	xp = xfrm_policy_alloc(GFP_KERNEL);
  	if (xp == NULL) {
@@ -1179,6 +1323,8 @@ static struct xfrm_policy *xfrm_compile_

  	copy_from_user_policy(xp, p);
  	copy_templates(xp, ut, nr);
+	if (uctx)
+		copy_sec_ctx(xp, uctx);

  	*dir = p->dir;

@@ -1199,6 +1345,8 @@ static int build_polexpire(struct sk_buf
  	copy_to_user_policy(xp, &upe->pol, dir);
  	if (copy_to_user_tmpl(xp, skb) < 0)
  		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 2) < 0)
+		goto nlmsg_failure;
  	upe->hard = !!hard;

  	nlh->nlmsg_len = skb->tail - b;
@@ -1216,6 +1364,7 @@ static int xfrm_send_policy_notify(struc

  	len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
  	len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
+	len += xfrm_user_sec_ctx_size(xp);
  	skb = alloc_skb(len, GFP_ATOMIC);
  	if (skb == NULL)
  		return -ENOMEM;
diff -puN security/dummy.c~lsm-xfrm-nethooks security/dummy.c
--- linux-2.6.12-rc4-nethooks/security/dummy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/dummy.c	2005-05-10 15:40:22.000000000 -0400
@@ -811,6 +811,35 @@ static inline void dummy_sk_free_securit
  }
  #endif	/* CONFIG_SECURITY_NETWORK */

+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
+{
+}
+
+static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static void dummy_xfrm_state_free_security(struct xfrm_state *x)
+{
+}
+
+static int dummy_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
  static int dummy_register_security (const char *name, struct security_operations *ops)
  {
  	return -EINVAL;
@@ -992,5 +1021,13 @@ void security_fixup_ops (struct security
  	set_to_dummy_if_null(ops, sk_alloc_security);
  	set_to_dummy_if_null(ops, sk_free_security);
  #endif	/* CONFIG_SECURITY_NETWORK */
+#ifdef  CONFIG_SECURITY_NETWORK_XFRM
+	set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
+	set_to_dummy_if_null(ops, xfrm_policy_clone_security);
+	set_to_dummy_if_null(ops, xfrm_policy_free_security);
+	set_to_dummy_if_null(ops, xfrm_state_alloc_security);
+	set_to_dummy_if_null(ops, xfrm_state_free_security);
+	set_to_dummy_if_null(ops, xfrm_policy_lookup);
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
  }

diff -puN security/Kconfig~lsm-xfrm-nethooks security/Kconfig
--- linux-2.6.12-rc4-nethooks/security/Kconfig~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/Kconfig	2005-05-10 15:28:44.000000000 -0400
@@ -53,6 +53,19 @@ config SECURITY_NETWORK
  	  implement socket and networking access controls.
  	  If you are unsure how to answer this question, answer N.

+config SECURITY_NETWORK_XFRM
+	bool "XFRM (IPSec) Networking Security Hooks"
+	depends on XFRM && SECURITY_NETWORK
+	help
+	  This enables the XFRM (IPSec) networking security hooks.
+	  If enabled, a security module can use these hooks to
+	  implement per-packet access controls based on labels
+	  derived from IPSec policy.  Non-IPSec communications are
+	  designated as unlabelled, and only sockets authorized
+	  to communicate unlabelled data can send without using
+	  IPSec.
+	  If you are unsure how to answer this question, answer N.
+
  config SECURITY_CAPABILITIES
  	tristate "Default Linux Capabilities"
  	depends on SECURITY
_

^ permalink raw reply

* [PATCH 2/2] LSM-IPSec Networking Hooks
From: Trent Jaeger @ 2005-05-17  2:58 UTC (permalink / raw)
  To: netdev, chrisw; +Cc: jaegert, sergeh, latten, sds, jmorris


This patch series implements per packet access control via the
extension of the Linux Security Modules (LSM) interface by hooks in
the XFRM and pfkey subsystems that leverage IPSec security
associations to label packets.  Extensions to the SELinux LSM are
included that leverage the patch for this purpose.

This patch implements the changes necessary to the SELinux LSM to
create, deallocate, and use security contexts for policies
(xfrm_policy) and security associations (xfrm_state) that enable
control of a socket's ability to send and receive packets.

Patch purpose:

The patch is designed to enable the SELinux LSM to implement access
control on individual packets based on the strongly authenticated
IPSec security association.  Such access controls augment the existing
ones in SELinux based on network interface and IP address.  The former
are very coarse-grained, and the latter can be spoofed.  By using
IPSec, the SELinux can control access to remote hosts based on
cryptographic keys generated using the IPSec mechanism.  This enables
access control on a per-machine basis or per-application if the remote
machine is running the same mechanism and trusted to enforce the
access control policy.

Patch design approach:

The patch's main function is to authorize a socket's access to a IPSec
policy based on their security contexts.  Since the communication is
implemented by a security association, the patch ensures that the
security association's negotiated and used have the same security
context.  The patch enables allocation and deallocation of such
security contexts for policies and security associations.  It also
enables copying of the security context when policies are cloned.
Lastly, the patch ensures that packets that are sent without using a
IPSec security assocation with a security context are allowed to be
sent in that manner.

A presentation available at
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
from the SELinux symposium describes the overall approach.

Patch implementation details:

The function which authorizes a socket to perform a requested
operation (send/receive) on a IPSec policy (xfrm_policy) is
selinux_xfrm_policy_lookup.  The Netfilter and rcv_skb hooks ensure
that if a IPSec SA with a securit y association has not been used,
then the socket is allowed to send or receive the packet,
respectively.

The patch implements SELinux function for allocating security contexts
when policies (xfrm_policy) are created via the pfkey or xfrm_user
interfaces via selinux_xfrm_policy_alloc.  When a security association
is built, SELinux allocates the security context designated by the
XFRM subsystem which is based on that of the authorized policy via
selinux_xfrm_state_alloc.

When a xfrm_policy is cloned, the security context of that policy, if
any, is copied to the clone via selinux_xfrm_policy_clone.

When a xfrm_policy or xfrm_state is freed, its security context, if
any is also freed at selinux_xfrm_policy_free or
selinux_xfrm_state_free.

Testing:

The SELinux authorization function is tested using ipsec-tools.  We
created policies and security associations with particular security
contexts and added SELinux access control policy entries to verify the
authorization decision.  We also made sure that packets for which no
security context was supplied (which either did or did not use
security associations) were authorized using an unlabelled context.


---

  security/selinux/Makefile           |    2
  security/selinux/hooks.c            |   20 +
  security/selinux/include/nethooks.h |    8
  security/selinux/nethooks.c         |  428 ++++++++++++++++++++++++++++++++++++
  4 files changed, 457 insertions(+), 1 deletion(-)

diff -puN security/selinux/hooks.c~lsm-selinux-nethooks security/selinux/hooks.c
--- linux-2.6.12-rc4-nethooks/security/selinux/hooks.c~lsm-selinux-nethooks	2005-05-13 13:15:47.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/hooks.c	2005-05-13 13:15:47.000000000 -0400
@@ -72,6 +72,7 @@
  #include "avc.h"
  #include "objsec.h"
  #include "netif.h"
+#include "nethooks.h"

  #define XATTR_SELINUX_SUFFIX "selinux"
  #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
@@ -3350,6 +3351,10 @@ static int selinux_socket_sock_rcv_skb(s
  		err = avc_has_perm(sock_sid, port_sid,
  				   sock_class, recv_perm, &ad);
  	}
+
+	if (!err)
+		err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+
  out:
  	return err;
  }
@@ -3537,6 +3542,11 @@ static unsigned int selinux_ip_postroute
  		                   send_perm, &ad) ? NF_DROP : NF_ACCEPT;
  	}

+	if (err != NF_ACCEPT)
+		goto out;
+
+	err = selinux_xfrm_postroute_last(isec->sid, skb);
+
  out:
  	return err;
  }
@@ -4389,6 +4399,15 @@ static struct security_operations selinu
  	.sk_alloc_security =		selinux_sk_alloc_security,
  	.sk_free_security =		selinux_sk_free_security,
  #endif
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+	.xfrm_policy_alloc_security =	selinux_xfrm_policy_alloc,
+	.xfrm_policy_clone_security =	selinux_xfrm_policy_clone,
+	.xfrm_policy_free_security =	selinux_xfrm_policy_free,
+	.xfrm_state_alloc_security =	selinux_xfrm_state_alloc,
+	.xfrm_state_free_security =	selinux_xfrm_state_free,
+	.xfrm_policy_lookup =	        selinux_xfrm_policy_lookup,
+#endif
  };

  static __init int selinux_init(void)
@@ -4499,6 +4518,7 @@ static int __init selinux_nf_ip_init(voi
  		panic("SELinux: nf_register_hook for IPv6: error %d\n", err);

  #endif	/* IPV6 */
+
  out:
  	return err;
  }
diff -puN /dev/null security/selinux/include/nethooks.h
--- /dev/null	2004-02-23 16:02:56.000000000 -0500
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/include/nethooks.h	2005-05-13 13:15:47.000000000 -0400
@@ -0,0 +1,8 @@
+int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx);
+int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx);
+void selinux_xfrm_state_free(struct xfrm_state *x);
+int selinux_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir);
+int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb);
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb);
diff -puN security/selinux/Makefile~lsm-selinux-nethooks security/selinux/Makefile
--- linux-2.6.12-rc4-nethooks/security/selinux/Makefile~lsm-selinux-nethooks	2005-05-13 13:15:47.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/Makefile	2005-05-13 13:15:47.000000000 -0400
@@ -4,7 +4,7 @@

  obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/

-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o nethooks.o

  selinux-$(CONFIG_SECURITY_NETWORK) += netif.o

diff -puN /dev/null security/selinux/nethooks.c
--- /dev/null	2004-02-23 16:02:56.000000000 -0500
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/nethooks.c	2005-05-16 14:28:25.000000000 -0400
@@ -0,0 +1,428 @@
+/*
+ * USAGE:
+ * NOTES:
+ *   1. Make sure to enable the following options in your kernel config:
+ *	CONFIG_SECURITY=y
+ *	CONFIG_SECURITY_NETWORK=y
+ *	CONFIG_SECURITY_NETWORK_XFRM=y
+ *	CONFIG_SECURITY_SELINUX=m/y
+ * ISSUES:
+ *   1. Caching packets, so they are not dropped during negotiation
+ *   2. Emulating a reasonable SO_PEERSEC across machines
+ *   3. Testing sk_policy setting with context
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/xfrm.h>
+#include <net/xfrm.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <asm/semaphore.h>
+
+#include "nethooks.h"
+#include "avc.h"
+#include "objsec.h"
+
+/**************************************************************
+ *
+ * defines
+ *
+ **************************************************************/
+
+#define DEBUG 0
+
+/**************************************************************
+ *
+ * structures
+ *
+ **************************************************************/
+
+/**************************************************************
+ *
+ * globals
+ *
+ **************************************************************/
+
+/**************************************************************
+ *
+ * macros/inlines
+ *
+ **************************************************************/
+
+#define nethooks_debug(fmt, args...) {if (DEBUG) printk(KERN_NOTICE fmt,## args);}
+
+/*
+ * Extract the security blob from the sock (it's actually on the socket)
+ */
+static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
+{
+	if (!sk->sk_socket) {
+		nethooks_debug("%s: no socket on this sock (!?)\n",
+			       __FUNCTION__);
+		return (struct inode_security_struct *) NULL;
+	}
+
+	return SOCK_INODE(sk->sk_socket)->i_security;
+}
+
+/*
+ * Returns true if the xfrm contains a security blob for SELinux
+ */
+static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_state_security(x);
+
+	return (xfrm_ctx &&
+		(xfrm_ctx->ctx_doi == XFRM_SC_DOI_LSM) &&
+		(xfrm_ctx->ctx_alg == XFRM_SC_ALG_SELINUX));
+}
+
+/**************************************************************
+ *
+ * LSM
+ *
+ **************************************************************/
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+/*
+ * LSM hook implementation that authorizes that a socket can be used
+ * with the corresponding xfrm_policy selector and direction.
+ */
+
+int selinux_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+	int rc = 0;
+	struct inode_security_struct *isec = NULL;
+	u32 sock_sid, sel_sid = SECINITSID_UNLABELED;
+
+	nethooks_debug("%s: authorize\n", __FUNCTION__);
+
+	if (!sk) {
+                /* no sock to send -- e.g., icmp reply */
+		/* authorize as kernel packet */
+		if (fl && fl->proto == IPPROTO_ICMP) {
+			nethooks_debug("%s: ICMP case\n",
+				       __FUNCTION__);
+			sock_sid = SECINITSID_KERNEL;
+			goto authorize;
+		}
+		/*
+		 * hooks.c accepts packets with no socket unconditionally
+		 */
+		nethooks_debug("%s: no sock on this skbuff: non-ICMP\n",
+			       __FUNCTION__);
+		goto out;
+	}
+
+	read_lock_bh(&sk->sk_callback_lock);
+	isec = get_sock_isec(sk);
+
+	/* No isec: allow if any sock can read target */
+	if (!isec) {
+		nethooks_debug("%s: no isec from sock\n", __FUNCTION__);
+		sock_sid = SECINITSID_ANY_SOCKET;
+	}
+	else {
+		sock_sid = isec->sid;
+	}
+	read_unlock_bh(&sk->sk_callback_lock);
+
+
+authorize:
+	/* Selector sid is either set to label or ANY_ASSOC */
+	if (sel->security) {
+		sel_sid = sel->security->ctx_sid;
+		nethooks_debug("%s: %s for context %.50s; sid: %d; sock: %d\n",
+			       __FUNCTION__,
+			       ((dir == FLOW_DIR_IN) ? "input" :
+				((dir == FLOW_DIR_OUT) ? "output" : "forward")),
+			       sel->security->ctx_str,
+			       sel_sid,
+			       sock_sid);
+	}
+
+	rc = avc_has_perm(sock_sid, sel_sid, SECCLASS_ASSOCIATION,
+			  ((dir == FLOW_DIR_IN) ? ASSOCIATION__RECVFROM :
+			   ((dir == FLOW_DIR_OUT) ?  ASSOCIATION__SENDTO :
+			    (ASSOCIATION__SENDTO | ASSOCIATION__RECVFROM))),
+			  NULL);
+
+out:
+	return rc;
+}
+
+/*
+ * Security blob allocation for xfrm_policy and xfrm_state
+ *  -- both attached to selectors
+ */
+static inline int selinux_xfrm_selector_alloc(struct xfrm_selector *sel, struct sadb_x_sec_ctx *sec_ctx)
+{
+	int rc = 0;
+
+	if (!sec_ctx)
+		return -EINVAL;
+
+	nethooks_debug(KERN_NOTICE "%s: got a sec_ctx for policy\n",
+		       __FUNCTION__);
+
+	if (sec_ctx->sadb_x_ctx_len >= PAGE_SIZE)
+		return -ENOMEM;
+
+	sel->security = kmalloc(sizeof(*sel->security) +
+				sec_ctx->sadb_x_ctx_len + 1,
+				GFP_KERNEL);
+
+	if (!sel->security)
+		return -ENOMEM;
+
+	sel->security->ctx_doi = sec_ctx->sadb_x_ctx_doi;
+	sel->security->ctx_len = sec_ctx->sadb_x_ctx_len;
+	sel->security->ctx_alg = sec_ctx->sadb_x_ctx_alg;
+
+	nethooks_debug(KERN_NOTICE "%s: doi %u len %u alg %u\n",
+		       __FUNCTION__,
+		       sel->security->ctx_doi,
+		       sel->security->ctx_len,
+		       sel->security->ctx_alg);
+
+	memcpy(sel->security->ctx_str,
+	       sec_ctx+1,
+	       sel->security->ctx_len);
+	rc = security_context_to_sid(sel->security->ctx_str,
+				     sel->security->ctx_len,
+				     &sel->security->ctx_sid);
+	sel->security->ctx_str[sel->security->ctx_len] = 0;
+
+	nethooks_debug(KERN_NOTICE "%s: context was %s with sid %d\n",
+		       __FUNCTION__,
+		       sel->security->ctx_str,
+		       sel->security->ctx_sid);
+
+	if (rc)
+		kfree(sel->security);
+
+	return rc;
+}
+
+/*
+ * LSM hook implementation that allocs and transfers sec_ctx spec to
+ * xfrm_policy.
+ */
+int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+	int rc = 0;
+
+	if (!xp)
+		return -EINVAL;
+
+	nethooks_debug(KERN_NOTICE "%s: start alloc\n", __FUNCTION__);
+
+	rc = selinux_xfrm_selector_alloc(&xp->selector, sec_ctx);
+
+	return rc;
+}
+
+
+/*
+ * LSM hook implementation that copies security data structure from old to
+ * new for policy cloning.
+ */
+int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+	struct xfrm_sec_ctx *old_ctx, *new_ctx;
+
+	old_ctx = xfrm_policy_security(old);
+
+	if (old_ctx) {
+		new_ctx = new->selector.security =
+			kmalloc(sizeof(*new_ctx) +
+				old_ctx->ctx_len + 1,
+				GFP_KERNEL);
+
+		if (!new_ctx)
+			return -ENOMEM;
+
+		memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
+		memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
+	}
+	return 0;
+}
+
+/*
+ * LSM hook implementation that frees xfrm_policy security information.
+ */
+void selinux_xfrm_policy_free(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx)
+		kfree(xfrm_ctx);
+}
+
+/*
+ * LSM hook implementation that allocs and transfers sec_ctx spec to
+ * xfrm_state.
+ */
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+	int rc = 0;
+
+	if (!x)
+		return -EINVAL;
+
+	nethooks_debug(KERN_NOTICE "%s: start alloc\n", __FUNCTION__);
+
+	rc = selinux_xfrm_selector_alloc(&x->sel, sec_ctx);
+
+	return rc;
+}
+
+/*
+ * LSM hook implementation that frees xfrm_state security information.
+ */
+void selinux_xfrm_state_free(struct xfrm_state *x)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_state_security(x);
+
+	if (xfrm_ctx)
+		kfree(xfrm_ctx);
+}
+
+/*
+ * LSM hook that controls access to unlabelled packets.  If
+ * a xfrm_state is authorizable (defined by macro) then it was
+ * already authorized by selector matching process.  If not, then
+ * we need to check for unlabelled access since this may not have
+ * gone thru the selector process.
+ */
+int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+{
+	int i, rc = 0;
+	struct sec_path *sp;
+	struct sock *sk;
+
+	nethooks_debug("%s: starting\n", __FUNCTION__);
+
+	/* regular check for socket with isec */
+	sp = skb->sp;
+	sk = skb->sk;
+
+	if (sp) {
+		nethooks_debug("%s: sp (0x%x) on skb with length %d\n",
+			       __FUNCTION__,
+			       (unsigned) sp, sp->len);
+
+		/*
+		 * __xfrm_policy_check does not approve unless xfrm_policy_ok
+		 * says that spi's match for policy and the socket.
+		 *
+		 *  Only need to verify the existence of an authorizable sp.
+		 */
+		for (i = 0; i < sp->len; i++) {
+			struct xfrm_state *x = sp->x[i].xvec;
+
+			nethooks_debug("%s: sa: 0x%x\n",
+				       __FUNCTION__,
+				       (unsigned) x);
+
+			if (selinux_authorizable_xfrm(x)) {
+				nethooks_debug("%s: sa 0x%x found\n",
+					       __FUNCTION__,
+					       (unsigned) x);
+				goto accept;
+			}
+		}
+	}
+
+	/* check SELinux sock for unlabelled access */
+	nethooks_debug("%s: before unlabelled sa auth: isec_sid = 0x%x\n",
+		       __FUNCTION__,
+		       (unsigned) isec_sid);
+	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
+			  ASSOCIATION__RECVFROM, NULL);
+	nethooks_debug("%s: after unlabelled sa auth rc: %d\n",
+		       __FUNCTION__,
+		       rc);
+
+	if (rc)
+		goto drop;
+
+accept:
+	nethooks_debug("%s: accept\n", __FUNCTION__);
+	return 0;
+
+drop:
+	nethooks_debug("%s: drop\n", __FUNCTION__);
+	return rc;
+}
+
+/*
+ * POSTROUTE_LAST hook's XFRM processing:
+ * If we have no security association, then we need to determine
+ * whether the socket is allowed to send to an unlabelled destination.
+ * If we do have a authorizable security association, then it has already been
+ * checked in xfrm_policy_lookup hook.
+ */
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+{
+	struct dst_entry *dst;
+	int rc = 0;
+
+	dst = skb->dst;
+
+	if (dst) {
+		struct dst_entry *dst_test;
+
+		for (dst_test = dst; dst_test != 0;
+		     dst_test = dst_test->child) {
+			struct xfrm_state *x = dst_test->xfrm;
+
+			if (selinux_authorizable_xfrm(x)) {
+				nethooks_debug("%s: sa 0x%x found\n",
+					       __FUNCTION__,
+					       (unsigned) x);
+				goto accept;
+			}
+		}
+	}
+
+	nethooks_debug("%s: before unlabelled sa auth: isec_sid = 0x%x\n",
+		       __FUNCTION__,
+		       (unsigned) isec_sid);
+	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
+			  ASSOCIATION__SENDTO, NULL);
+	nethooks_debug("%s: after unlabelled sa auth rc: %d\n", __FUNCTION__, rc);
+
+	if (rc)
+		goto drop;
+
+accept:
+	nethooks_debug("%s: accept\n", __FUNCTION__);
+	return NF_ACCEPT;
+
+drop:
+	nethooks_debug("%s: drop\n", __FUNCTION__);
+	return NF_DROP;
+}
+
+#else  /* CONFIG_SECURITY_NETWORK_XFRM */
+
+int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+{
+	return 0;
+}
+
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+{
+	return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
_

^ permalink raw reply

* Re: [git patches] 2.6.x net driver fixes
From: Linus Torvalds @ 2005-05-17  3:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, Netdev, Linux Kernel
In-Reply-To: <42892F2B.8090908@pobox.com>



On Mon, 16 May 2005, Jeff Garzik wrote:
>
> Here's a first experimental git push from me.  The git URL is
> rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
> 
> but it should be noted that I would like you to pull the 'misc-fixes' 
> branch.  I'm told that branches are supposed to live in .git/refs/heads, 
> so there you will find netdev-2.6.git/refs/heads/misc-fixes.
> 
> Does that work?

Yes. Merged and pushed out.

> Changelog and patch for review attached.

It's wonderful if you also do a "diffstat" on the thing, since my merge 
scripts will always show that to me, and I can verify at a glance that it 
matches what you thought you sent me.

Also, if you are really nervous, the "git-diff-tree" thing is actually
quite good at generating changelogs, so you can do something like this:

	git-rev-tree HEAD ^ORIG_HEAD | cut -d' ' -f2 | git-diff-tree -v -p --stdin | less -S

which means: give me a list of all commits that are in HEAD but not in 
ORIG_HEAD (replace with whatever markers you have, in this case you'd use 
"misc-fixes" instead of HEAD and some marker - maybe the SHA1 - for my 
last base), then take just the SHA1 of that list of commits, and show a 
verbose diff of each of the commits with the patch.

For example, the output of the above command (after I merged from you) is 
appended, so you can see exactly what I merged.

		Linus

----
diff-tree 99718699f5746cc365f3a9ab4769568a1da97635 (from f7a3aae1723e7ffc9c4fcdb489365da7a3d81255)
Author: Geoff Levand <geoffrey.levand@am.sony.com>
Date:   Thu Apr 14 11:20:32 2005 -0700
    
    [PATCH] {PATCH] Fix IBM EMAC driver ioctl bug
    
    Fix IBM EMAC driver ioctl bug.
    
    I found IBM EMAC driver bug.
    So mii-tool command print wrong status.
    
      # mii-tool
      eth0: 10 Mbit, half duplex, no link
      eth1: 10 Mbit, half duplex, no link
    
    I can get correct status on fixed kernel.
    
      # mii-tool
      eth0: negotiated 100baseTx-FD, link okZZ
      eth1: negotiated 100baseTx-FD, link ok
    
    Hiroaki Fuse
    
    Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> for CELF

--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1595,7 +1595,7 @@ static struct ethtool_ops emac_ethtool_o
 static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct ocp_enet_private *fep = dev->priv;
-	uint *data = (uint *) & rq->ifr_ifru;
+	uint16_t *data = (uint16_t *) & rq->ifr_ifru;
 
 	switch (cmd) {
 	case SIOCGMIIPHY:

diff-tree c4cc26d3310a6614a20e32276228a5d44159fc9b (from 99718699f5746cc365f3a9ab4769568a1da97635)
Author: Jiri Benc <jbenc@suse.cz>
Date:   Wed Apr 27 08:48:56 2005 +0200
    
    [PATCH] Typo in tulip driver
    
    This patch fixes a typo in tulip driver in 2.6.12-rc3.

--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1104,7 +1104,7 @@ static void set_rx_mode(struct net_devic
 			if (entry != 0) {
 				/* Avoid a chip errata by prefixing a dummy entry. Don't do
 				   this on the ULI526X as it triggers a different problem */
-				if (!(tp->chip_id == ULI526X && (tp->revision = 0x40 || tp->revision == 0x50))) {
+				if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
 					tp->tx_buffers[entry].skb = NULL;
 					tp->tx_buffers[entry].mapping = 0;
 					tp->tx_ring[entry].length =

diff-tree c8920ba041c8934b29370f5d62ab9ea8f147966b (from c4cc26d3310a6614a20e32276228a5d44159fc9b)
Author: Daniel Andersen <daniel@linux-user.net>
Date:   Thu May 5 15:14:09 2005 -0700
    
    [PATCH] wireless: 3CRWE154G72 Kconfig help fix
    
    Version 2 of the 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 is not
    supported by the prism54 project.  To stop confusion, the kernel
    documentation should state so as 3com made a good job hiding the version.
    
    Signed-off-by: Andrew Morton <akpm@osdl.org>
    
    diff -puN drivers/net/wireless/Kconfig~wireless-3crwe154g72-kconfig-help-fix drivers/net/wireless/Kconfig

--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -323,7 +323,7 @@ config PRISM54
 	  For a complete list of supported cards visit <http://prism54.org>.
 	  Here is the latest confirmed list of supported cards:
 
-	  3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+	  3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1)
 	  Allnet ALL0271 PCI Card
 	  Compex WL54G Cardbus Card
 	  Corega CG-WLCB54GT Cardbus Card

diff-tree f7a3aae1723e7ffc9c4fcdb489365da7a3d81255 (from 88d7bd8cb9eb8d64bf7997600b0d64f7834047c5)
Author: Al Viro <viro@www.linux.org.uk>
Date:   Sun Apr 3 07:15:52 2005 +0100
    
    [PATCH] drivers/net/wireless enabled by wrong option
    
    	NET_WIRELESS is only a subset of the stuff in drivers/net/wireless;
    NET_RADIO is what covers all of them.
    Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>

--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -187,7 +187,7 @@ obj-$(CONFIG_TR) += tokenring/
 obj-$(CONFIG_WAN) += wan/
 obj-$(CONFIG_ARCNET) += arcnet/
 obj-$(CONFIG_NET_PCMCIA) += pcmcia/
-obj-$(CONFIG_NET_WIRELESS) += wireless/
+obj-$(CONFIG_NET_RADIO) += wireless/
 obj-$(CONFIG_NET_TULIP) += tulip/
 obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox