diff options
-rw-r--r-- | include/linux/netfilter/nfnetlink_log.h | 1 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 18 |
2 files changed, 13 insertions, 6 deletions
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index d3bab7a2c9b7..1d0b84aa1d42 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h | |||
@@ -89,6 +89,7 @@ enum nfulnl_attr_config { | |||
89 | #define NFULNL_COPY_NONE 0x00 | 89 | #define NFULNL_COPY_NONE 0x00 |
90 | #define NFULNL_COPY_META 0x01 | 90 | #define NFULNL_COPY_META 0x01 |
91 | #define NFULNL_COPY_PACKET 0x02 | 91 | #define NFULNL_COPY_PACKET 0x02 |
92 | #define NFULNL_COPY_DISABLED 0x03 | ||
92 | 93 | ||
93 | #define NFULNL_CFG_F_SEQ 0x0001 | 94 | #define NFULNL_CFG_F_SEQ 0x0001 |
94 | #define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 | 95 | #define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 8ec23ec568e7..fb86a51bb65a 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -109,8 +109,8 @@ instance_lookup_get(u_int16_t group_num) | |||
109 | 109 | ||
110 | rcu_read_lock_bh(); | 110 | rcu_read_lock_bh(); |
111 | inst = __instance_lookup(group_num); | 111 | inst = __instance_lookup(group_num); |
112 | if (inst) | 112 | if (inst && !atomic_inc_not_zero(&inst->use)) |
113 | instance_get(inst); | 113 | inst = NULL; |
114 | rcu_read_unlock_bh(); | 114 | rcu_read_unlock_bh(); |
115 | 115 | ||
116 | return inst; | 116 | return inst; |
@@ -171,7 +171,7 @@ instance_create(u_int16_t group_num, int pid) | |||
171 | inst->copy_mode = NFULNL_COPY_PACKET; | 171 | inst->copy_mode = NFULNL_COPY_PACKET; |
172 | inst->copy_range = NFULNL_COPY_RANGE_MAX; | 172 | inst->copy_range = NFULNL_COPY_RANGE_MAX; |
173 | 173 | ||
174 | hlist_add_head(&inst->hlist, | 174 | hlist_add_head_rcu(&inst->hlist, |
175 | &instance_table[instance_hashfn(group_num)]); | 175 | &instance_table[instance_hashfn(group_num)]); |
176 | 176 | ||
177 | spin_unlock_bh(&instances_lock); | 177 | spin_unlock_bh(&instances_lock); |
@@ -185,18 +185,23 @@ out_unlock: | |||
185 | 185 | ||
186 | static void __nfulnl_flush(struct nfulnl_instance *inst); | 186 | static void __nfulnl_flush(struct nfulnl_instance *inst); |
187 | 187 | ||
188 | /* called with BH disabled */ | ||
188 | static void | 189 | static void |
189 | __instance_destroy(struct nfulnl_instance *inst) | 190 | __instance_destroy(struct nfulnl_instance *inst) |
190 | { | 191 | { |
191 | /* first pull it out of the global list */ | 192 | /* first pull it out of the global list */ |
192 | hlist_del(&inst->hlist); | 193 | hlist_del_rcu(&inst->hlist); |
193 | 194 | ||
194 | /* then flush all pending packets from skb */ | 195 | /* then flush all pending packets from skb */ |
195 | 196 | ||
196 | spin_lock_bh(&inst->lock); | 197 | spin_lock(&inst->lock); |
198 | |||
199 | /* lockless readers wont be able to use us */ | ||
200 | inst->copy_mode = NFULNL_COPY_DISABLED; | ||
201 | |||
197 | if (inst->skb) | 202 | if (inst->skb) |
198 | __nfulnl_flush(inst); | 203 | __nfulnl_flush(inst); |
199 | spin_unlock_bh(&inst->lock); | 204 | spin_unlock(&inst->lock); |
200 | 205 | ||
201 | /* and finally put the refcount */ | 206 | /* and finally put the refcount */ |
202 | instance_put(inst); | 207 | instance_put(inst); |
@@ -624,6 +629,7 @@ nfulnl_log_packet(u_int8_t pf, | |||
624 | size += nla_total_size(data_len); | 629 | size += nla_total_size(data_len); |
625 | break; | 630 | break; |
626 | 631 | ||
632 | case NFULNL_COPY_DISABLED: | ||
627 | default: | 633 | default: |
628 | goto unlock_and_release; | 634 | goto unlock_and_release; |
629 | } | 635 | } |