bpf: Avoid iter->offset making backward progress in bpf_iter_udp
[platform/kernel/linux-starfive.git] / net / ipv4 / udp.c
index a4857c8..9cb22a6 100644 (file)
@@ -3116,16 +3116,18 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
        struct bpf_udp_iter_state *iter = seq->private;
        struct udp_iter_state *state = &iter->state;
        struct net *net = seq_file_net(seq);
+       int resume_bucket, resume_offset;
        struct udp_table *udptable;
        unsigned int batch_sks = 0;
        bool resized = false;
        struct sock *sk;
 
+       resume_bucket = state->bucket;
+       resume_offset = iter->offset;
+
        /* The current batch is done, so advance the bucket. */
-       if (iter->st_bucket_done) {
+       if (iter->st_bucket_done)
                state->bucket++;
-               iter->offset = 0;
-       }
 
        udptable = udp_get_table_seq(seq, net);
 
@@ -3145,19 +3147,19 @@ again:
        for (; state->bucket <= udptable->mask; state->bucket++) {
                struct udp_hslot *hslot2 = &udptable->hash2[state->bucket];
 
-               if (hlist_empty(&hslot2->head)) {
-                       iter->offset = 0;
+               if (hlist_empty(&hslot2->head))
                        continue;
-               }
 
+               iter->offset = 0;
                spin_lock_bh(&hslot2->lock);
                udp_portaddr_for_each_entry(sk, &hslot2->head) {
                        if (seq_sk_match(seq, sk)) {
                                /* Resume from the last iterated socket at the
                                 * offset in the bucket before iterator was stopped.
                                 */
-                               if (iter->offset) {
-                                       --iter->offset;
+                               if (state->bucket == resume_bucket &&
+                                   iter->offset < resume_offset) {
+                                       ++iter->offset;
                                        continue;
                                }
                                if (iter->end_sk < iter->max_sk) {
@@ -3171,9 +3173,6 @@ again:
 
                if (iter->end_sk)
                        break;
-
-               /* Reset the current bucket's offset before moving to the next bucket. */
-               iter->offset = 0;
        }
 
        /* All done: no batch made. */