aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nfnetlink_log.h1
-rw-r--r--net/netfilter/nfnetlink_log.c18
2 files changed, 13 insertions, 6 deletions
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index d3bab7a2c9b..1d0b84aa1d4 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 8ec23ec568e..fb86a51bb65 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
186static void __nfulnl_flush(struct nfulnl_instance *inst); 186static void __nfulnl_flush(struct nfulnl_instance *inst);
187 187
188/* called with BH disabled */
188static void 189static 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 }