- 论坛徽章:
- 0
|
it is hot&hard to deal with SBL,
but another version of, maybe slower, fragment treatment can be made with rcu,
of cough, possibly followed with bug&vulnerability,
to rx frag either legal or illegal.
- --- linux-2.6.22.1/net/ipv4/ip_fragment.c 2007-07-11 02:56:30.000000000 +0800
- +++ /usr/src/chg/ip_fragment3.c 2007-08-21 11:27:03.000000000 +0800
- @@ -25,6 +25,7 @@
- #include <linux/compiler.h>
- #include <linux/module.h>
- #include <linux/types.h>
- +#include <linux/rcupdate.h>
- #include <linux/mm.h>
- #include <linux/jiffies.h>
- #include <linux/skbuff.h>
- @@ -111,8 +112,8 @@ int ip_frag_nqueues = 0;
-
- static __inline__ void __ipq_unlink(struct ipq *qp)
- {
- - hlist_del(&qp->list);
- - list_del(&qp->lru_list);
- + hlist_del_rcu(&qp->list);
- + list_del_rcu(&qp->lru_list);
- ip_frag_nqueues--;
- }
-
- @@ -149,10 +150,10 @@ static void ipfrag_secret_rebuild(unsign
- q->daddr, q->protocol);
-
- if (hval != i) {
- - hlist_del(&q->list);
- + hlist_del_rcu(&q->list);
-
- /* Relink to new hash chain. */
- - hlist_add_head(&q->list, &ipq_hash[hval]);
- + hlist_add_head_rcu(&q->list, &ipq_hash[hval]);
- }
- }
- }
- @@ -252,16 +253,16 @@ static void ip_evictor(void)
- return;
-
- while (work > 0) {
- - read_lock(&ipfrag_lock);
- + rcu_read_lock();
- if (list_empty(&ipq_lru_list)) {
- - read_unlock(&ipfrag_lock);
- + rcu_read_unlock();
- return;
- }
- - tmp = ipq_lru_list.next;
- - qp = list_entry(tmp, struct ipq, lru_list);
- + tmp = rcu_dereference(ipq_lru_list.next);
- + qp = list_entry(tmp, struct ipq, lru_list);
- atomic_inc(&qp->refcnt);
- - read_unlock(&ipfrag_lock);
- -
- + rcu_read_unlock();
- +
- spin_lock(&qp->lock);
- if (!(qp->last_in&COMPLETE))
- ipq_kill(qp);
- @@ -320,7 +321,7 @@ static struct ipq *ip_frag_intern(struct
- * such entry could be created on other cpu, while we
- * promoted read lock to write lock.
- */
- - hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
- + hlist_for_each_entry_rcu(qp, n, &ipq_hash[hash], list) {
- if (qp->id == qp_in->id &&
- qp->saddr == qp_in->saddr &&
- qp->daddr == qp_in->daddr &&
- @@ -340,9 +341,9 @@ static struct ipq *ip_frag_intern(struct
- atomic_inc(&qp->refcnt);
-
- atomic_inc(&qp->refcnt);
- - hlist_add_head(&qp->list, &ipq_hash[hash]);
- + hlist_add_head_rcu(&qp->list, &ipq_hash[hash]);
- INIT_LIST_HEAD(&qp->lru_list);
- - list_add_tail(&qp->lru_list, &ipq_lru_list);
- + list_add_tail_rcu(&qp->lru_list, &ipq_lru_list);
- ip_frag_nqueues++;
- write_unlock(&ipfrag_lock);
- return qp;
- @@ -395,20 +396,20 @@ static inline struct ipq *ip_find(struct
- struct ipq *qp;
- struct hlist_node *n;
-
- - read_lock(&ipfrag_lock);
- + rcu_read_lock();
- hash = ipqhashfn(id, saddr, daddr, protocol);
- - hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
- + hlist_for_each_entry_rcu(qp, n, &ipq_hash[hash], list) {
- if (qp->id == id &&
- qp->saddr == saddr &&
- qp->daddr == daddr &&
- qp->protocol == protocol &&
- qp->user == user) {
- atomic_inc(&qp->refcnt);
- - read_unlock(&ipfrag_lock);
- + rcu_read_unlock();
- return qp;
- }
- }
- - read_unlock(&ipfrag_lock);
- + rcu_read_lock();
-
- return ip_frag_create(iph, user);
- }
- @@ -599,7 +600,8 @@ static void ip_frag_queue(struct ipq *qp
- qp->last_in |= FIRST_IN;
-
- write_lock(&ipfrag_lock);
- - list_move_tail(&qp->lru_list, &ipq_lru_list);
- + list_del_rcu(&qp->lru_list);
- + list_add_tail_rcu(&qp->lru_list, &ipq_lru_list);
- write_unlock(&ipfrag_lock);
-
- return;
复制代码
[ 本帖最后由 sisi8408 于 2007-8-22 10:48 编辑 ] |
|