Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@woody.osdl.org>
Thu, 7 Dec 2006 17:05:15 +0000 (09:05 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Thu, 7 Dec 2006 17:05:15 +0000 (09:05 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (48 commits)
  [NETFILTER]: Fix non-ANSI func. decl.
  [TG3]: Identify Serdes devices more clearly.
  [TG3]: Use msleep.
  [TG3]: Use netif_msg_*.
  [TG3]: Allow partial speed advertisement.
  [TG3]: Add TG3_FLG2_IS_NIC flag.
  [TG3]: Add 5787F device ID.
  [TG3]: Fix Phy loopback.
  [WANROUTER]: Kill kmalloc debugging code.
  [TCP] inet_twdr_hangman: Delete unnecessary memory barrier().
  [NET]: Memory barrier cleanups
  [IPSEC]: Fix inetpeer leak in ipv4 xfrm dst entries.
  audit: disable ipsec auditing when CONFIG_AUDITSYSCALL=n
  audit: Add auditing to ipsec
  [IRDA] irlan: Fix compile warning when CONFIG_PROC_FS=n
  [IrDA]: Incorrect TTP header reservation
  [IrDA]: PXA FIR code device model conversion
  [GENETLINK]: Fix misplaced command flags.
  [NETLIK]: Add a pointer to the Generic Netlink wiki page.
  [IPV6] RAW: Don't release unlocked sock.
  ...

1  2 
drivers/block/Kconfig
drivers/md/dm-crypt.c
include/linux/pci_ids.h
net/ipv4/inet_timewait_sock.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/xfrm/xfrm_policy.c

diff --combined drivers/block/Kconfig
@@@ -168,8 -168,7 +168,8 @@@ config BLK_CPQ_CISS_D
  
  config CISS_SCSI_TAPE
        bool "SCSI tape drive support for Smart Array 5xxx"
 -      depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS
 +      depends on BLK_CPQ_CISS_DA && PROC_FS
 +      depends on SCSI=y || SCSI=BLK_CPQ_CISS_DA
        help
          When enabled (Y), this option allows SCSI tape drives and SCSI medium
          changers (tape robots) to be accessed via a Compaq 5xxx array 
@@@ -306,6 -305,7 +306,7 @@@ config BLK_DEV_LOO
  config BLK_DEV_CRYPTOLOOP
        tristate "Cryptoloop Support"
        select CRYPTO
+       select CRYPTO_CBC
        depends on BLK_DEV_LOOP
        ---help---
          Say Y here if you want to be able to use the ciphers that are 
diff --combined drivers/md/dm-crypt.c
@@@ -20,6 -20,7 +20,7 @@@
  #include <asm/atomic.h>
  #include <linux/scatterlist.h>
  #include <asm/page.h>
+ #include <asm/unaligned.h>
  
  #include "dm.h"
  
@@@ -85,7 -86,10 +86,10 @@@ struct crypt_config 
         */
        struct crypt_iv_operations *iv_gen_ops;
        char *iv_mode;
-       struct crypto_cipher *iv_gen_private;
+       union {
+               struct crypto_cipher *essiv_tfm;
+               int benbi_shift;
+       } iv_gen_private;
        sector_t iv_offset;
        unsigned int iv_size;
  
  #define MIN_POOL_PAGES 32
  #define MIN_BIO_PAGES  8
  
 -static kmem_cache_t *_crypt_io_pool;
 +static struct kmem_cache *_crypt_io_pool;
  
  /*
   * Different IV generation algorithms:
   *        encrypted with the bulk cipher using a salt as key. The salt
   *        should be derived from the bulk cipher's key via hashing.
   *
+  * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1
+  *        (needed for LRW-32-AES and possible other narrow block modes)
+  *
   * plumb: unimplemented, see:
   * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
   */
@@@ -191,21 -198,61 +198,61 @@@ static int crypt_iv_essiv_ctr(struct cr
        }
        kfree(salt);
  
-       cc->iv_gen_private = essiv_tfm;
+       cc->iv_gen_private.essiv_tfm = essiv_tfm;
        return 0;
  }
  
  static void crypt_iv_essiv_dtr(struct crypt_config *cc)
  {
-       crypto_free_cipher(cc->iv_gen_private);
-       cc->iv_gen_private = NULL;
+       crypto_free_cipher(cc->iv_gen_private.essiv_tfm);
+       cc->iv_gen_private.essiv_tfm = NULL;
  }
  
  static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
  {
        memset(iv, 0, cc->iv_size);
        *(u64 *)iv = cpu_to_le64(sector);
-       crypto_cipher_encrypt_one(cc->iv_gen_private, iv, iv);
+       crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv);
+       return 0;
+ }
+ static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
+                             const char *opts)
+ {
+       unsigned int bs = crypto_blkcipher_blocksize(cc->tfm);
+       int log = long_log2(bs);
+       /* we need to calculate how far we must shift the sector count
+        * to get the cipher block count, we use this shift in _gen */
+       if (1 << log != bs) {
+               ti->error = "cypher blocksize is not a power of 2";
+               return -EINVAL;
+       }
+       if (log > 9) {
+               ti->error = "cypher blocksize is > 512";
+               return -EINVAL;
+       }
+       cc->iv_gen_private.benbi_shift = 9 - log;
+       return 0;
+ }
+ static void crypt_iv_benbi_dtr(struct crypt_config *cc)
+ {
+ }
+ static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+ {
+       __be64 val;
+       memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
+       val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1);
+       put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64)));
        return 0;
  }
  
@@@ -219,13 -266,18 +266,18 @@@ static struct crypt_iv_operations crypt
        .generator = crypt_iv_essiv_gen
  };
  
+ static struct crypt_iv_operations crypt_iv_benbi_ops = {
+       .ctr       = crypt_iv_benbi_ctr,
+       .dtr       = crypt_iv_benbi_dtr,
+       .generator = crypt_iv_benbi_gen
+ };
  
  static int
  crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
                            struct scatterlist *in, unsigned int length,
                            int write, sector_t sector)
  {
-       u8 iv[cc->iv_size];
+       u8 iv[cc->iv_size] __attribute__ ((aligned(__alignof__(u64))));
        struct blkcipher_desc desc = {
                .tfm = cc->tfm,
                .info = iv,
@@@ -768,7 -820,7 +820,7 @@@ static int crypt_ctr(struct dm_target *
        cc->tfm = tfm;
  
        /*
-        * Choose ivmode. Valid modes: "plain", "essiv:<esshash>".
+        * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi".
         * See comments at iv code
         */
  
                cc->iv_gen_ops = &crypt_iv_plain_ops;
        else if (strcmp(ivmode, "essiv") == 0)
                cc->iv_gen_ops = &crypt_iv_essiv_ops;
+       else if (strcmp(ivmode, "benbi") == 0)
+               cc->iv_gen_ops = &crypt_iv_benbi_ops;
        else {
                ti->error = "Invalid IV mode";
                goto bad2;
diff --combined include/linux/pci_ids.h
  #define PCI_DEVICE_ID_NS_CS5535_IDE   0x002d
  #define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e
  #define PCI_DEVICE_ID_NS_CS5535_USB   0x002f
 -#define PCI_DEVICE_ID_NS_CS5535_VIDEO 0x0030
 +#define PCI_DEVICE_ID_NS_GX_VIDEO     0x0030
  #define PCI_DEVICE_ID_NS_SATURN               0x0035
  #define PCI_DEVICE_ID_NS_SCx200_BRIDGE        0x0500
  #define PCI_DEVICE_ID_NS_SCx200_SMI   0x0501
  #define PCI_DEVICE_ID_NS_SC1100_XBUS  0x0515
  #define PCI_DEVICE_ID_NS_87410                0xd001
  
 -#define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE  0x0028
 -#define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE   0x002b
 +#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE  0x0028
  
  #define PCI_VENDOR_ID_TSENG           0x100c
  #define PCI_DEVICE_ID_TSENG_W32P_2    0x3202
  #define PCI_DEVICE_ID_OXSEMI_16PCI95N 0x9511
  #define PCI_DEVICE_ID_OXSEMI_16PCI954PP       0x9513
  #define PCI_DEVICE_ID_OXSEMI_16PCI952 0x9521
 +#define PCI_DEVICE_ID_OXSEMI_16PCI952PP       0x9523
  
  #define PCI_VENDOR_ID_SAMSUNG         0x144d
  
  #define PCI_DEVICE_ID_TIGON3_5750M    0x167c
  #define PCI_DEVICE_ID_TIGON3_5751M    0x167d
  #define PCI_DEVICE_ID_TIGON3_5751F    0x167e
+ #define PCI_DEVICE_ID_TIGON3_5787F    0x167f
  #define PCI_DEVICE_ID_TIGON3_5787M    0x1693
  #define PCI_DEVICE_ID_TIGON3_5782     0x1696
  #define PCI_DEVICE_ID_TIGON3_5786     0x169a
  #define PCI_DEVICE_ID_FARSITE_TE1       0x1610
  #define PCI_DEVICE_ID_FARSITE_TE1C      0x1612
  
+ #define PCI_VENDOR_ID_ARIMA           0x161f
  #define PCI_VENDOR_ID_SIBYTE          0x166d
  #define PCI_DEVICE_ID_BCM1250_PCI     0x0001
  #define PCI_DEVICE_ID_BCM1250_HT      0x0002
@@@ -91,7 -91,7 +91,7 @@@ struct inet_timewait_sock *inet_twsk_al
  {
        struct inet_timewait_sock *tw =
                kmem_cache_alloc(sk->sk_prot_creator->twsk_prot->twsk_slab,
 -                               SLAB_ATOMIC);
 +                               GFP_ATOMIC);
        if (tw != NULL) {
                const struct inet_sock *inet = inet_sk(sk);
  
@@@ -178,7 -178,6 +178,6 @@@ void inet_twdr_hangman(unsigned long da
        need_timer = 0;
        if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {
                twdr->thread_slots |= (1 << twdr->slot);
-               mb();
                schedule_work(&twdr->twkill_work);
                need_timer = 1;
        } else {
@@@ -108,7 -108,7 +108,7 @@@ static struct 
        size_t size;
  
        /* slab cache pointer */
 -      kmem_cache_t *cachep;
 +      struct kmem_cache *cachep;
  
        /* allocated slab cache + modules which uses this slab cache */
        int use;
@@@ -147,7 -147,7 +147,7 @@@ int nf_conntrack_register_cache(u_int32
  {
        int ret = 0;
        char *cache_name;
 -      kmem_cache_t *cachep;
 +      struct kmem_cache *cachep;
  
        DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n",
               features, name, size);
@@@ -226,7 -226,7 +226,7 @@@ EXPORT_SYMBOL_GPL(nf_conntrack_register
  /* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */
  void nf_conntrack_unregister_cache(u_int32_t features)
  {
 -      kmem_cache_t *cachep;
 +      struct kmem_cache *cachep;
        char *name;
  
        /*
@@@ -1093,7 -1093,7 +1093,7 @@@ static void free_conntrack_hash(struct 
                           get_order(sizeof(struct list_head) * size));
  }
  
- void nf_conntrack_flush()
+ void nf_conntrack_flush(void)
  {
        nf_ct_iterate_cleanup(kill_all, NULL);
  }
@@@ -29,7 -29,7 +29,7 @@@
  LIST_HEAD(nf_conntrack_expect_list);
  EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);
  
 -kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
 +struct kmem_cache *nf_conntrack_expect_cachep __read_mostly;
  static unsigned int nf_conntrack_expect_next_id;
  
  /* nf_conntrack_expect helper functions */
@@@ -91,25 -91,28 +91,28 @@@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_f
  struct nf_conntrack_expect *
  find_expectation(const struct nf_conntrack_tuple *tuple)
  {
-       struct nf_conntrack_expect *i;
+       struct nf_conntrack_expect *exp;
+       exp = __nf_conntrack_expect_find(tuple);
+       if (!exp)
+               return NULL;
  
-       list_for_each_entry(i, &nf_conntrack_expect_list, list) {
        /* If master is not in hash table yet (ie. packet hasn't left
           this machine yet), how can other end know about expected?
           Hence these are not the droids you are looking for (if
           master ct never got confirmed, we'd hold a reference to it
           and weird things would happen to future packets). */
-               if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
-                   && nf_ct_is_confirmed(i->master)) {
-                       if (i->flags & NF_CT_EXPECT_PERMANENT) {
-                               atomic_inc(&i->use);
-                               return i;
-                       } else if (del_timer(&i->timeout)) {
-                               nf_ct_unlink_expect(i);
-                               return i;
-                       }
-               }
+       if (!nf_ct_is_confirmed(exp->master))
+               return NULL;
+       if (exp->flags & NF_CT_EXPECT_PERMANENT) {
+               atomic_inc(&exp->use);
+               return exp;
+       } else if (del_timer(&exp->timeout)) {
+               nf_ct_unlink_expect(exp);
+               return exp;
        }
        return NULL;
  }
  
diff --combined net/xfrm/xfrm_policy.c
@@@ -25,6 -25,7 +25,7 @@@
  #include <linux/cache.h>
  #include <net/xfrm.h>
  #include <net/ip.h>
+ #include <linux/audit.h>
  
  #include "xfrm_hash.h"
  
@@@ -39,7 -40,7 +40,7 @@@ EXPORT_SYMBOL(xfrm_policy_count)
  static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
  static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
  
 -static kmem_cache_t *xfrm_dst_cache __read_mostly;
 +static struct kmem_cache *xfrm_dst_cache __read_mostly;
  
  static struct work_struct xfrm_policy_gc_work;
  static HLIST_HEAD(xfrm_policy_gc_list);
@@@ -804,7 -805,7 +805,7 @@@ struct xfrm_policy *xfrm_policy_byid(u
  }
  EXPORT_SYMBOL(xfrm_policy_byid);
  
- void xfrm_policy_flush(u8 type)
+ void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
  {
        int dir;
  
                        hlist_del(&pol->byidx);
                        write_unlock_bh(&xfrm_policy_lock);
  
+                       xfrm_audit_log(audit_info->loginuid, audit_info->secid,
+                                      AUDIT_MAC_IPSEC_DELSPD, 1, pol, NULL);
                        xfrm_policy_kill(pol);
                        killed++;
  
                                hlist_del(&pol->byidx);
                                write_unlock_bh(&xfrm_policy_lock);
  
+                               xfrm_audit_log(audit_info->loginuid,
+                                              audit_info->secid,
+                                              AUDIT_MAC_IPSEC_DELSPD, 1,
+                                              pol, NULL);
                                xfrm_policy_kill(pol);
                                killed++;
  
@@@ -860,33 -869,12 +869,12 @@@ EXPORT_SYMBOL(xfrm_policy_flush)
  int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
                     void *data)
  {
-       struct xfrm_policy *pol;
+       struct xfrm_policy *pol, *last = NULL;
        struct hlist_node *entry;
-       int dir, count, error;
+       int dir, last_dir = 0, count, error;
  
        read_lock_bh(&xfrm_policy_lock);
        count = 0;
-       for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
-               struct hlist_head *table = xfrm_policy_bydst[dir].table;
-               int i;
-               hlist_for_each_entry(pol, entry,
-                                    &xfrm_policy_inexact[dir], bydst) {
-                       if (pol->type == type)
-                               count++;
-               }
-               for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
-                       hlist_for_each_entry(pol, entry, table + i, bydst) {
-                               if (pol->type == type)
-                                       count++;
-                       }
-               }
-       }
-       if (count == 0) {
-               error = -ENOENT;
-               goto out;
-       }
  
        for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
                struct hlist_head *table = xfrm_policy_bydst[dir].table;
                                     &xfrm_policy_inexact[dir], bydst) {
                        if (pol->type != type)
                                continue;
-                       error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
-                       if (error)
-                               goto out;
+                       if (last) {
+                               error = func(last, last_dir % XFRM_POLICY_MAX,
+                                            count, data);
+                               if (error)
+                                       goto out;
+                       }
+                       last = pol;
+                       last_dir = dir;
+                       count++;
                }
                for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
                        hlist_for_each_entry(pol, entry, table + i, bydst) {
                                if (pol->type != type)
                                        continue;
-                               error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
-                               if (error)
-                                       goto out;
+                               if (last) {
+                                       error = func(last, last_dir % XFRM_POLICY_MAX,
+                                                    count, data);
+                                       if (error)
+                                               goto out;
+                               }
+                               last = pol;
+                               last_dir = dir;
+                               count++;
                        }
                }
        }
-       error = 0;
+       if (count == 0) {
+               error = -ENOENT;
+               goto out;
+       }
+       error = func(last, last_dir % XFRM_POLICY_MAX, 0, data);
  out:
        read_unlock_bh(&xfrm_policy_lock);
        return error;
@@@ -1982,6 -1986,117 +1986,117 @@@ int xfrm_bundle_ok(struct xfrm_policy *
  
  EXPORT_SYMBOL(xfrm_bundle_ok);
  
+ #ifdef CONFIG_AUDITSYSCALL
+ /* Audit addition and deletion of SAs and ipsec policy */
+ void xfrm_audit_log(uid_t auid, u32 sid, int type, int result,
+                   struct xfrm_policy *xp, struct xfrm_state *x)
+ {
+       char *secctx;
+       u32 secctx_len;
+       struct xfrm_sec_ctx *sctx = NULL;
+       struct audit_buffer *audit_buf;
+       int family;
+       extern int audit_enabled;
+       if (audit_enabled == 0)
+               return;
+       audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
+       if (audit_buf == NULL)
+       return;
+       switch(type) {
+       case AUDIT_MAC_IPSEC_ADDSA:
+               audit_log_format(audit_buf, "SAD add: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_DELSA:
+               audit_log_format(audit_buf, "SAD delete: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_ADDSPD:
+               audit_log_format(audit_buf, "SPD add: auid=%u", auid);
+               break;
+       case AUDIT_MAC_IPSEC_DELSPD:
+               audit_log_format(audit_buf, "SPD delete: auid=%u", auid);
+               break;
+       default:
+               return;
+       }
+       if (sid != 0 &&
+               security_secid_to_secctx(sid, &secctx, &secctx_len) == 0)
+               audit_log_format(audit_buf, " subj=%s", secctx);
+       else
+               audit_log_task_context(audit_buf);
+       if (xp) {
+               family = xp->selector.family;
+               if (xp->security)
+                       sctx = xp->security;
+       } else {
+               family = x->props.family;
+               if (x->security)
+                       sctx = x->security;
+       }
+       if (sctx)
+               audit_log_format(audit_buf,
+                               " sec_alg=%u sec_doi=%u sec_obj=%s",
+                               sctx->ctx_alg, sctx->ctx_doi, sctx->ctx_str);
+       switch(family) {
+       case AF_INET:
+               {
+                       struct in_addr saddr, daddr;
+                       if (xp) {
+                               saddr.s_addr = xp->selector.saddr.a4;
+                               daddr.s_addr = xp->selector.daddr.a4;
+                       } else {
+                               saddr.s_addr = x->props.saddr.a4;
+                               daddr.s_addr = x->id.daddr.a4;
+                       }
+                       audit_log_format(audit_buf,
+                                        " src=%u.%u.%u.%u dst=%u.%u.%u.%u",
+                                        NIPQUAD(saddr), NIPQUAD(daddr));
+               }
+                       break;
+       case AF_INET6:
+               {
+                       struct in6_addr saddr6, daddr6;
+                       if (xp) {
+                               memcpy(&saddr6, xp->selector.saddr.a6,
+                                       sizeof(struct in6_addr));
+                               memcpy(&daddr6, xp->selector.daddr.a6,
+                                       sizeof(struct in6_addr));
+                       } else {
+                               memcpy(&saddr6, x->props.saddr.a6,
+                                       sizeof(struct in6_addr));
+                               memcpy(&daddr6, x->id.daddr.a6,
+                                       sizeof(struct in6_addr));
+                       }
+                       audit_log_format(audit_buf,
+                                        " src=" NIP6_FMT "dst=" NIP6_FMT,
+                                        NIP6(saddr6), NIP6(daddr6));
+               }
+               break;
+       }
+       if (x)
+               audit_log_format(audit_buf, " spi=%lu(0x%lx) protocol=%s",
+                               (unsigned long)ntohl(x->id.spi),
+                               (unsigned long)ntohl(x->id.spi),
+                               x->id.proto == IPPROTO_AH ? "AH" :
+                               (x->id.proto == IPPROTO_ESP ?
+                               "ESP" : "IPCOMP"));
+       audit_log_format(audit_buf, " res=%u", result);
+       audit_log_end(audit_buf);
+ }
+ EXPORT_SYMBOL(xfrm_audit_log);
+ #endif /* CONFIG_AUDITSYSCALL */
  int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
  {
        int err = 0;