免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: sisi8408
打印 上一主题 下一主题

Kernel Bug-Vulnerability-Comment library [复制链接]

论坛徽章:
0
61 [报告]
发表于 2007-12-15 11:19 |只看该作者

  1. part-2,IRT entry programming

  2. static struct IO_APIC_route_entry  ioapic_read_entry(int apic, int pin);
  3. /*
  4. * basic IRTE read/write, indexed by pin,
  5. * but how is mapped to irq, then to vector??
  6. */
  7. static void ioapic_write_entry (int apic, int pin,
  8.                 struct IO_APIC_route_entry e);

  9. /* shutup IRQ mapped by pin */
  10. static void ioapic_mask_entry (int apic, int pin);

  11. /*
  12. * IRQ<-->pin mapping table is irq_2_pin[]
  13. *
  14. * but where irq come from??
  15. */
  16. static void add_pin_to_irq (unsigned int irq, int apic, int pin)
  17. {
  18.         static int first_free_entry = NR_IRQS;
  19.         struct irq_pin_list *entry = irq_2_pin + irq;

  20.         while (entry->next)
  21.                 entry = irq_2_pin + entry->next;

  22.         if (entry->pin != -1) {
  23.                 /*
  24.                  * in case IRQ is shared
  25.                  */
  26.                 entry->next = first_free_entry;
  27.                 entry = irq_2_pin + entry->next;
  28.                
  29.                 if (++first_free_entry >= PIN_MAP_SIZE)
  30.                         panic("io_apic.c: whoops");
  31.         }
  32.         entry->apic = apic;
  33.         entry->pin  = pin;
  34. }

  35. /*
  36. * Reroute an IRQ to a different pin
  37. *
  38. * or, cfg pin to use IRQ
  39. */
  40. static void __init replace_pin_at_irq(unsigned int irq,
  41.                                       int oldapic, int oldpin,
  42.                                       int newapic, int newpin);
  43. /*
  44. * core programing method,
  45. * first read, then write.
  46. */
  47. static void __modify_IO_APIC_irq (unsigned int irq,
  48.                                   unsigned long enable,
  49.                                   unsigned long disable)

  50. static void clear_IO_APIC_pin (unsigned int apic, unsigned int pin)
  51. {
  52. /*
  53. * in chip of ioapic, pin is represented by route entry
  54. */
  55.         struct IO_APIC_route_entry entry;
  56.        
  57.         /* Check delivery_mode to be sure we're not clearing an SMI pin */
  58.         entry = ioapic_read_entry(apic, pin);
  59.         if (entry.delivery_mode == dest_SMI)
  60.                 return;
  61.         /*
  62.          * Disable it in the IO-APIC irq-routing table:
  63.          */
  64.         ioapic_mask_entry(apic, pin);
  65. }
复制代码

论坛徽章:
0
62 [报告]
发表于 2007-12-15 11:20 |只看该作者

  1. part-3 irq affinity/balance

  2. 非常高兴,关于balance在CU已经看见 思一克 漂亮的工作,
  3. 这里八哥就不费心了。

复制代码

[ 本帖最后由 sisi8408 于 2007-12-15 11:29 编辑 ]

论坛徽章:
0
63 [报告]
发表于 2007-12-15 13:48 |只看该作者

  1. part-4 麻烦来了,MADT/MPS

  2. /*
  3. * Find the IRQ entry number of a certain pin
  4. */
  5. static int find_irq_entry (int apic, int pin, int type)
  6. {
  7.         int i;
  8.         /*
  9.          * bonding of irq and pin is pre-defined?!
  10.          */
  11.         for (i = 0; i < mp_irq_entries; i++) {
  12.                 if (mp_irqs[i].mpc_irqtype == type &&
  13.                     (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
  14.                      mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
  15.                     mp_irqs[i].mpc_dstirq == pin)
  16.                         return i;
  17.         }
  18.         return -1;
  19. }
  20. /*
  21. * seems it is impossible to make IRQ unshared, if
  22. * two pci devices cfged shared in mp_irqs[]??
  23. * and it is appreciated in practical usage where
  24. * unshared IRQ preferred.
  25. */
  26. static int __init find_pci_irq_pin (int irq, int type)
  27. {
  28.         int i;

  29.         for (i = 0; i < mp_irq_entries; i++) {
  30.                 int lbus;
  31.                
  32.                 lbus = mp_irqs[i].mpc_srcbus;

  33.                 if (mp_bus_id_to_type[lbus]  == MP_BUS_PCI
  34.                  && mp_irqs[i].mpc_irqtype   == type
  35.                  && mp_irqs[i].mpc_srcbusirq == irq)        /* defined in this way */
  36.                         return mp_irqs[i].mpc_dstirq;        /* and its pin */
  37.         }
  38.         return -1;
  39. }

  40. /*
  41. * Find a specific PCI IRQ entry
  42. *
  43. *********************************************
  44. * Not an __init, possibly needed by modules *  
  45. *********************************************
  46. *
  47. * linux从不决人后路,如果Solaris敢放马开放,
  48. * linux充分吸收后,就没有吸引用户的必要了,请鳖揭开面纱。
  49. */

  50. int IO_APIC_get_PCI_irq_vector (int bus, int slot, int pin)
  51. {
  52.         int apic, i, best_guess = -1;

  53.         apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus%d, "
  54.                 "slot%d, pin%d\n", bus, slot, pin);
  55.        
  56.         if (mp_bus_id_to_pci_bus[bus] == -1) {
  57.                 printk(KERN_WARNING
  58.                         "PCI BIOS passed nonexistent PCI bus%d!\n", bus);
  59.                 return -1;
  60.         }

  61.         for (i = 0; i < mp_irq_entries; i++) {
  62.                 int lbus = mp_irqs[i].mpc_srcbus;

  63.                 for (apic = 0; apic < nr_ioapics; apic++) {
  64.                         /*
  65.                          * determine IRQ controler
  66.                          */
  67.                         if (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid
  68.                          || mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
  69.                                 break;
  70.                 }

  71.                 if (mp_bus_id_to_type[lbus] == MP_BUS_PCI
  72.                  && !mp_irqs[i].mpc_irqtype /* need confirm */
  73.                  && bus == lbus                /* both bus and slot match */
  74.                  && slot == (mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f) {
  75.                         int irq;
  76.                        
  77.                         irq = pin_2_irq(i, apic, mp_irqs[i].mpc_dstirq);
  78.                         if (!(apic || IO_APIC_IRQ(irq)))
  79.                                 continue;
  80.                         /*
  81.                          * and pin match
  82.                          */
  83.                         if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
  84.                                 return irq;

  85.                         /*
  86.                          * Use the first all-but-pin matching entry as a
  87.                          * best-guess fuzzy result for broken mptables.
  88.                          */
  89.                         if (best_guess < 0)
  90.                                 best_guess = irq;
  91.                 }
  92.         }
  93.         return best_guess;
  94. }
  95. /*
  96. * irq of pci_bus:slot.dev is determined in IOAPIC space
  97. * 1, to which controler connected and pin?
  98. * 2, irq = controler_nr * nr_irte + pin
  99. * limited currently by
  100. *        256 vector per cpu
  101. *        128 controler
  102. *         24 irte per controler
  103. *
  104. * irt<-->LAPIC mapping can also be programmed,
  105. * goto see set_ioapic_affinity_irq(irq, TARGET_CPUS) and
  106. * balanced_irq_init()
  107. *
  108. * the major purpose of MADT maybe tell OS controler and pin,
  109. * irq can be re-cfged.
  110. * no problem, ok.
  111. */
  112. static int pin_2_irq (int idx, int apic, int pin)
  113. {
  114.         int irq, i;
  115.         int bus = mp_irqs[idx].mpc_srcbus;
  116.         /*
  117.          * Debugging check, we are in big trouble if this message pops up!
  118.          */
  119.         if (mp_irqs[idx].mpc_dstirq != pin)
  120.                 printk(KERN_ERR "broken BIOS or MPTABLE parser in pin_2_irq, ayiee!!\n");

  121.         switch (mp_bus_id_to_type[bus])
  122.         {
  123.                 case MP_BUS_ISA: /* ISA pin */
  124.                 case MP_BUS_EISA:
  125.                 case MP_BUS_MCA:
  126.                 {
  127.                         irq = mp_irqs[idx].mpc_srcbusirq;
  128.                         break;
  129.                 }
  130.                 case MP_BUS_PCI: /* PCI pin */
  131.                 {
  132.                         /*
  133.                          * PCI IRQs are mapped in order
  134.                          */
  135.                         i = irq = 0;
  136.                         while (i < apic)
  137.                                 irq += nr_ioapic_registers[i++];
  138.                         irq += pin;
  139.                         /*
  140.                          * For MPS mode, so far only needed by ES7000 platform
  141.                          */
  142.                         if (ioapic_renumber_irq)
  143.                                 irq = ioapic_renumber_irq(apic, irq);
  144.                         break;
  145.                 }
  146.                 default:
  147.                 {
  148.                         printk(KERN_ERR "unknown bus type %d in pin_2_irq\n",bus);
  149.                         irq = 0;
  150.                         break;
  151.                 }
  152.         }
  153.         /*
  154.          * PCI IRQ command line redirection.
  155.          * Yes, limits are hardcoded.
  156.          */
  157.         if (pin >= 16 && pin <= 23) {
  158.                 if (pirq_entries[pin -16] != -1) {
  159.                         if (!pirq_entries[pin -16]) {
  160.                                 apic_printk(APIC_VERBOSE, KERN_DEBUG
  161.                                         "disabling PIRQ%d\n", pin -16);
  162.                         } else {
  163.                                 irq = pirq_entries[pin -16];
  164.                                 apic_printk(APIC_VERBOSE, KERN_DEBUG
  165.                                         "using PIRQ%d -> IRQ %d\n", pin -16, irq);
  166.                         }
  167.                 }
  168.         }
  169.         return irq;
  170. }

复制代码

论坛徽章:
0
64 [报告]
发表于 2007-12-15 13:49 |只看该作者

  1. part-5 IRQ attr: trigger/polarity

  2. /*
  3. * 不仅变化快,还很复杂,
  4. *  trigger: edge/level
  5. *  polarity: high/low
  6. */

  7. /*
  8. * check irq is level or edge
  9. */
  10. static inline int IO_APIC_irq_trigger (int irq)
  11. {
  12.         int apic, idx, pin;

  13.         for (apic = 0; apic < nr_ioapics; apic++) {
  14.                 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
  15.                         idx = find_irq_entry(apic, pin, mp_INT);
  16.                         if (idx != -1
  17.                          && irq == pin_2_irq(idx, apic, pin))
  18.                                 return irq_trigger(idx);
  19.                 }
  20.         }
  21.         /*
  22.          * nonexistent IRQs are edge default
  23.          */
  24.         return 0;
  25. }
复制代码

论坛徽章:
0
65 [报告]
发表于 2007-12-15 13:51 |只看该作者

  1. part-6 vector[IRQ]

  2. /*
  3. * irq_vectors is indexed by the sum of all RTEs in all I/O APICs
  4. */
  5. static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };

  6. static int __assign_irq_vector (int irq)
  7. {
  8.         static int current_vector = FIRST_DEVICE_VECTOR;
  9.         static int current_offset = 0;
  10.         int vector, offset, i;

  11.         BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);

  12.         if (irq_vector[irq] > 0)        /* shared irq */
  13.                 return irq_vector[irq];

  14.         vector = current_vector;
  15.         offset = current_offset;
  16. next:
  17.         vector += 8;
  18.         if (vector >= FIRST_SYSTEM_VECTOR) {
  19.                 offset = (offset + 1) % 8;
  20.                 /*
  21.                  * the vector of pci-irq has to
  22.                  * be larger than FIRST_DEVICE_VECTOR,
  23.                  * imposed by Intel
  24.                  */
  25.                 vector = FIRST_DEVICE_VECTOR + offset;
  26.         }
  27.         if (vector == current_vector)
  28.                 return -ENOSPC;

  29.         if (vector == SYSCALL_VECTOR)
  30.                 goto next;

  31.         for (i = 0; i < NR_IRQ_VECTORS; i++)
  32.                 if (irq_vector[i] == vector)
  33.                         goto next;

  34.         current_vector = vector;
  35.         current_offset = offset;

  36.         irq_vector[irq] = vector;
  37.         return vector;
  38. }

  39. static struct irq_chip        ioapic_chip;

  40. #define IOAPIC_AUTO        -1
  41. #define IOAPIC_EDGE         0
  42. #define IOAPIC_LEVEL         1

  43. static void ioapic_register_intr (int irq, int vector, unsigned long trigger)
  44. {
  45.         if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq))
  46.           || trigger == IOAPIC_LEVEL)
  47.                 set_irq_chip_and_handler_name(irq, &ioapic_chip,
  48.                                  handle_fasteoi_irq, "fasteoi");
  49.         else
  50.                 set_irq_chip_and_handler_name(irq, &ioapic_chip,
  51.                                  handle_edge_irq, "edge");

  52.         set_intr_gate(vector, interrupt[irq]);
  53. }
  54. /* and put all together through
  55. * __ioapic_write_entry(apic, pin, entry);
  56. */
  57. static void __init setup_IO_APIC_irqs (void);

  58. /*
  59. * finally setup
  60. * struct irq_chip msi_chip, lapic_chip and ioapic_chip
  61. * for use by struct irq_desc,
  62. * the nut of linux abstract core of IRQ subsystem
  63. */
  64. [homework]
  65. 1, howto make pci-dev irqs unshared??
  66. 2, is IT from independent thought??
  67. [/homework]

复制代码

论坛徽章:
0
66 [报告]
发表于 2007-12-16 10:25 |只看该作者

  1. #ifdef CONFIG_SMP
  2. /*
  3. * linux-2.6.22.5/arch/i386/kernel/io_apic.c
  4. * 2007-12-16 10:18
  5. * ¥1
  6. */
  7. static void set_msi_irq_affinity (unsigned int irq, cpumask_t mask)
  8. {
  9.         struct msi_msg msg;
  10.         unsigned int dest;
  11.         cpumask_t tmp;
  12.         int vector;

  13.         cpus_and(tmp, mask, cpu_online_map);
  14.         if (cpus_empty(tmp))
  15.                 tmp = TARGET_CPUS;
  16.         /*
  17.          * though tmp checked, but not used anymore.
  18.          * the following `mask' should be tmp
  19.          *
  20.          * mask = tmp;
  21.          */
  22.         vector = assign_irq_vector(irq);
  23.         if (vector < 0)
  24.                 return;

  25.         dest = cpu_mask_to_apicid(mask);

  26.         read_msi_msg(irq, &msg);

  27.         msg.data &= ~MSI_DATA_VECTOR_MASK;
  28.         msg.data |= MSI_DATA_VECTOR(vector);

  29.         msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
  30.         msg.address_lo |= MSI_ADDR_DEST_ID(dest);

  31.         write_msi_msg(irq, &msg);
  32.         irq_desc[irq].affinity = mask;
  33. }
  34. #endif
复制代码

论坛徽章:
0
67 [报告]
发表于 2007-12-16 19:27 |只看该作者

  1. /* linux-2.6.22.5/arch/x86_64/kernel/mpparse.c
  2. * 2007-12-16 19:20
  3. * ¥1
  4. */
  5. static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
  6. {
  7.         if (!(m->mpc_flags & MPC_APIC_USABLE))
  8.                 return;

  9.         printk("I/O APIC #%d at 0x%X.\n",
  10.                 m->mpc_apicid, m->mpc_apicaddr);

  11.         if (bad_ioapic(m->mpc_apicaddr))
  12.                 return;
  13. /*
  14.         printk("I/O APIC #%d at 0x%X",
  15.                 m->mpc_apicid, m->mpc_apicaddr);

  16.         if (bad_ioapic(m->mpc_apicaddr)) {
  17.                 printk(" bad\n");
  18.                 return;
  19.         } else
  20.                 printk("\n");
  21. */
  22.         mp_ioapics[nr_ioapics] = *m;
  23.         nr_ioapics++;
  24. }

复制代码

论坛徽章:
0
68 [报告]
发表于 2007-12-19 21:02 |只看该作者

  1. /* linux-2.6.22.5/include/linux/skbuff.h
  2. * 2007-12-19 20:52
  3. * ¥1
  4. */
  5. static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
  6. {
  7.         if (likely(len <= skb_headlen(skb))) {
  8.                 /*
  9.                  * howto sure skb->data += len not overflow ?
  10.                  */
  11.                 return 1;
  12.         }
  13.         if (unlikely(len > skb->len))
  14.                 return 0;
  15.         return __pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL;
  16. }
复制代码

论坛徽章:
0
69 [报告]
发表于 2007-12-22 09:26 |只看该作者

  1. /*
  2.   linux-2.6.22.5/kernel/workqueue.c
  3.   2007-12-22 9:19
  4. */
  5. struct workqueue_struct *__create_workqueue(const char *name,
  6.                                             int singlethread, int freezeable)
  7. {
  8.         struct workqueue_struct *wq;
  9.         struct cpu_workqueue_struct *cwq;
  10.         int err = 0, cpu;

  11.         wq = kzalloc(sizeof(*wq), GFP_KERNEL);
  12.         if (!wq)
  13.                 return NULL;

  14.         wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
  15.         if (!wq->cpu_wq) {
  16.                 kfree(wq);
  17.                 return NULL;
  18.         }

  19.         wq->name = name;
  20.         wq->singlethread = singlethread;
  21.         wq->freezeable = freezeable;
  22.         INIT_LIST_HEAD(&wq->list);

  23.         if (singlethread) {
  24.                 cwq = init_cpu_workqueue(wq, singlethread_cpu);
  25.                 err = create_workqueue_thread(cwq, singlethread_cpu);
  26.                 start_workqueue_thread(cwq, -1);
  27.         } else {
  28.                 mutex_lock(&workqueue_mutex);
  29.                 list_add(&wq->list, &workqueues);

  30.                 for_each_possible_cpu(cpu) {
  31.                         cwq = init_cpu_workqueue(wq, cpu);
  32.                         /*
  33.                         if (!cpu_online(cpu))
  34.                                 continue;
  35.                         if (err)
  36.                                 break;
  37.                         */
  38.                         if (err || !cpu_online(cpu))
  39.                                 continue;
  40.                         err = create_workqueue_thread(cwq, cpu);
  41.                         start_workqueue_thread(cwq, cpu);
  42.                 }
  43.                 mutex_unlock(&workqueue_mutex);
  44.         }

  45.         if (err) {
  46.                 destroy_workqueue(wq);
  47.                 wq = NULL;
  48.         }
  49.         return wq;
  50. }
复制代码

论坛徽章:
0
70 [报告]
发表于 2007-12-22 12:55 |只看该作者

  1. /*
  2.   linux-2.6.22.5/net/netfilter/nf_conntrack_proto_tcp.c
  3.   2007-12-22 10:38
  4.   ¥6
  5.   howto crash netfilter with TCP SYN packet, possible?
  6. */
  7. static int tcp_error(struct sk_buff *skb,
  8.                      unsigned int dataoff,
  9.                      enum ip_conntrack_info *ctinfo,
  10.                      int pf,
  11.                      unsigned int hooknum)
  12. {
  13.         struct tcphdr _tcph, *th;
  14.         unsigned int tcplen = skb->len - dataoff;
  15.         u_int8_t tcpflags;

  16.         /* Smaller that minimal TCP header? */
  17.         th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
  18.         if (th == NULL) {
  19.                 if (LOG_INVALID(IPPROTO_TCP))
  20.                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  21.                                 "nf_ct_tcp: short packet ");
  22.                 return -NF_ACCEPT;
  23.         }

  24.         /* Not whole TCP header or malformed packet */
  25.         if (th->doff*4 < sizeof(struct tcphdr)
  26.             || tcplen < th->doff*4) {
  27. [color=Red]                /*
  28.                  * 其一 隐患;/
  29.                  * TCP头长大于60字节是合法的 8-(:
  30.                  */
  31. [/color]                if (LOG_INVALID(IPPROTO_TCP))
  32.                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  33.                                 "nf_ct_tcp: truncated/malformed packet ");
  34.                 return -NF_ACCEPT;
  35.         }

  36.         /* Checksum invalid? Ignore.
  37.          * We skip checking packets on the outgoing path
  38.          * because the checksum is assumed to be correct.
  39.          */
  40.         /* FIXME: Source route IP option packets --RR */
  41.         if (nf_conntrack_checksum &&
  42.             ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
  43.              (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
  44.             nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
  45.                 if (LOG_INVALID(IPPROTO_TCP))
  46.                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  47.                                   "nf_ct_tcp: bad TCP checksum ");
  48.                 return -NF_ACCEPT;
  49.         }

  50.         /* Check TCP flags. */
  51.         tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR|TH_PUSH));
  52.         if (!tcp_valid_flags[tcpflags]) {
  53.                 if (LOG_INVALID(IPPROTO_TCP))
  54.                         nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
  55.                                   "nf_ct_tcp: invalid TCP flag combination ");
  56.                 return -NF_ACCEPT;
  57.         }
  58.         return NF_ACCEPT;
  59. }

  60. static void tcp_options(const struct sk_buff *skb,
  61.                         unsigned int dataoff,
  62.                         struct tcphdr *tcph,
  63.                         struct ip_ct_tcp_state *state)
  64. {
  65.         unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
  66.         unsigned char *ptr;
  67.         int length = (tcph->doff*4) - sizeof(struct tcphdr);
  68.         /*
  69.          * length可以大于40;/
  70.          * but sizeof(buff) = 40
  71.          */
  72.         if (!length)
  73.                 return;

  74.         ptr = skb_header_pointer(skb, dataoff + sizeof(struct tcphdr),
  75.                                  length, buff);
  76. [color=Red]        /*
  77.          * 其二 buff可能overflow
  78.          */
  79. [/color]        BUG_ON(ptr == NULL);

  80.         state->td_scale = state->flags = 0;

  81.         while (length > 0) {
  82.                 int opcode = *ptr++;
  83.                 int opsize;

  84.                 switch (opcode) {
  85.                 case TCPOPT_EOL:
  86.                         return;
  87.                
  88.                 case TCPOPT_NOP:        /* Ref: RFC 793 section 3.1 */
  89.                         length--;
  90.                         continue;
  91.                
  92.                 default:
  93.                         opsize = *ptr++;
  94.                        
  95.                         if (opsize < 2) /* "silly options" */
  96.                                 return;
  97.                        
  98.                         if (opsize > length)
  99.                                 break;        /* don't parse partial options */

  100.                         if (opcode == TCPOPT_SACK_PERM
  101.                             && opsize == TCPOLEN_SACK_PERM) {
  102.                                 state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
  103.                         }
  104.                         else if (opcode == TCPOPT_WINDOW
  105.                                  && opsize == TCPOLEN_WINDOW) {
  106.                                 state->td_scale = *(u_int8_t *)ptr;

  107.                                 if (state->td_scale > 14) {
  108.                                         /* See RFC1323 */
  109.                                         state->td_scale = 14;
  110.                                 }
  111.                                 state->flags |= IP_CT_TCP_FLAG_WINDOW_SCALE;
  112.                         }
  113.                         ptr += opsize - 2;
  114.                         length -= opsize;
  115.                 }
  116.         }
  117. }

  118. static inline void * skb_header_pointer (const struct sk_buff *skb,
  119.                                          int offset, int len, void *buffer)
  120. { /* in <linux/skbuff.h> */
  121.        
  122.         int hlen = skb_headlen(skb);

  123.         if (hlen - offset >= len)
  124.                 return skb->data + offset;
  125. [color=Red]        /*
  126.          * 其三  如果是大SYN包,使得skb_copy_bits被调用了,
  127.          * if (len > 40 bytes)
  128.          *        buffer overflow;
  129.          *
  130.          * 但是,netfilter看到的包都是整合过的,
  131.          * 这样的机会几乎没有,要看ipfrag reasm的结果
  132.          */
  133. [/color]        if (skb_copy_bits(skb, offset, buffer, len) < 0)
  134.                 return NULL;

  135.         return buffer;
  136. }
  137. int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
  138. {
  139.         int i, copy;
  140.         int start = skb_headlen(skb);

  141.         if (offset > (int)skb->len - len)
  142.                 goto fault;

  143.         /* Copy header. */
  144.         if ((copy = start - offset) > 0) {
  145.                 if (copy > len)
  146.                         copy = len;
  147.                 /*
  148.                   这里没有check len,
  149.                   而是默认len <= sizeof(to)
  150.                 */
  151.                 skb_copy_from_linear_data_offset(skb, offset, to, copy);
  152.                 if ((len -= copy) == 0)
  153.                         return 0;
  154.                 offset += copy;
  155.                 to     += copy;
  156.         }
  157.         ...
  158. }
  159. void * memcpy(void *dest, const void *src, size_t count)
  160. {
  161. /*
  162.    C版的memcpy in lib/string.c

  163.    memcpy没有检测overflow的义务;/
  164. */
  165.         char *tmp = dest;
  166.         const char *s = src;

  167.         while (count--)
  168.                 *tmp++ = *s++;
  169.         return dest;
  170. }

  171. static struct sk_buff * ip_frag_reasm (struct ipq *qp, struct net_device *dev)
  172. { /* net/ipv4/ip_fragment.c */
  173.        
  174.         struct iphdr *iph;
  175.         struct sk_buff *fp, *head = qp->fragments;
  176.         int len;
  177.         int ihlen;

  178.         ipq_kill(qp);

  179.         BUG_TRAP(head != NULL);
  180.         BUG_TRAP(FRAG_CB(head)->offset == 0);

  181.         /* Allocate a new buffer for the datagram. */
  182.         ihlen = ip_hdrlen(head);
  183.         len = ihlen + qp->len;

  184.         if (len > 65535)
  185.                 goto out_oversize;

  186.         /* Head of list must not be cloned. */
  187.         if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC))
  188.                 goto out_nomem;

  189.         /* If the first fragment is fragmented itself, we split
  190.          * it to two chunks: the first with data and paged part
  191.          * and the second, holding only fragments. */
  192.         if (skb_shinfo(head)->frag_list) {
  193.                 struct sk_buff *clone;
  194.                 int i, plen = 0;

  195.                 if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL)
  196.                         goto out_nomem;
  197.                 clone->next = head->next;
  198.                 head->next = clone;
  199.                 skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
  200.                 skb_shinfo(head)->frag_list = NULL;
  201.                 for (i=0; i<skb_shinfo(head)->nr_frags; i++)
  202.                         plen += skb_shinfo(head)->frags[i].size;
  203.                 clone->len = clone->data_len = head->data_len - plen;
  204.                 head->data_len -= clone->len;
  205.                 head->len -= clone->len;
  206.                 clone->csum = 0;
  207.                 clone->ip_summed = head->ip_summed;
  208.                 atomic_add(clone->truesize, &ip_frag_mem);
  209.         }

  210.         skb_shinfo(head)->frag_list = head->next;
  211. [color=Red]        /*
  212.          * 其四  linux skb精巧的设计,可以方便地处理大包 &)
  213.          *
  214.          * 在这里没有实施linearize,性能可佳。
  215.          */
  216. [/color]        skb_push(head, head->data - skb_network_header(head));
  217.         atomic_sub(head->truesize, &ip_frag_mem);

  218.         for (fp = head->next; fp; fp = fp->next) {
  219.                 head->data_len += fp->len;
  220. [color=Red]                /*
  221.                  * 由于没有linearize操作,
  222.                  * 虽然总包长要求len < 65535 byte,
  223.                  * 首包长确可以是
  224.                  * 82byte = 20byte<IP> + 60byte<TCP> + 2byte<trash>
  225.                  *
  226.                  * 所以 tcp->doff*4 = 88byte,
  227.                  * 将迫使skb_header_pointer调用skb_copy_bits,
  228.                  * 结果导致40byte的buff overflow
  229.                  */
  230. [/color]                head->len += fp->len;
  231.                
  232.                 if (head->ip_summed != fp->ip_summed)
  233.                         head->ip_summed = CHECKSUM_NONE;
  234.                 else if (head->ip_summed == CHECKSUM_COMPLETE)
  235.                         head->csum = csum_add(head->csum, fp->csum);
  236.                
  237.                 head->truesize += fp->truesize;
  238.                 atomic_sub(fp->truesize, &ip_frag_mem);
  239.         }

  240.         head->next = NULL;
  241.         head->dev = dev;
  242.         head->tstamp = qp->stamp;

  243.         iph = ip_hdr(head);
  244.         iph->frag_off = 0;
  245.         iph->tot_len = htons(len);
  246.         IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
  247.         qp->fragments = NULL;
  248.         return head;

  249. out_nomem:
  250.         LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
  251.                               "queue %p\n", qp);
  252.         goto out_fail;
  253. out_oversize:
  254.         if (net_ratelimit())
  255.                 printk(KERN_INFO
  256.                         "Oversized IP packet from %d.%d.%d.%d.\n",
  257.                         NIPQUAD(qp->saddr));
  258. out_fail:
  259.         IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
  260.         return NULL;
  261. }
复制代码

[ 本帖最后由 sisi8408 于 2007-12-22 14:42 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP