From nobody Sun Apr 12 02:48:12 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 884EEC19F2C for ; Mon, 1 Aug 2022 20:50:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234364AbiHAUut (ORCPT ); Mon, 1 Aug 2022 16:50:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231338AbiHAUuq (ORCPT ); Mon, 1 Aug 2022 16:50:46 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE6849FD4 for ; Mon, 1 Aug 2022 13:50:45 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-31f3959ba41so100674817b3.2 for ; Mon, 01 Aug 2022 13:50:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=E1/rW2r70zyzqbkFgkmqJNWOc56RBiTRd890RD2T0+o=; b=XRNlLnXNNNo/3J7ur9PazcMWQXWXdy0i4aGQbhsUznk0w+tMIO9sDu0/7g4O8KG4rj 1ZrxlurF863pz5Ebm+T4N2HcJD52RhpJaFJPFR9aKR7WBPWlwrfGimgPIESCe9w4X19g /DJzSPvoMe13rkKB5nYSXS3rQqPrju6VAZ8rY5Bz4GkUHFeGAacz6MSAJISiWmY+CAYZ X708Q4v77OzFy5rU4nh05vdJy0wsp/2b49O+5Nwzt1fALXz3+IY16QIf8Y48uNcz6Mgy VGsUQxlIf9Mb7z5Xngd0eivSJTu55Ob0xqWvwq1e//6nRxA32t1PzpuWiPPf4FhxenMo 119w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=E1/rW2r70zyzqbkFgkmqJNWOc56RBiTRd890RD2T0+o=; b=eNVwNQsLhKyTkRcVUxzi6VFZAcFh2ubA6rCUb9PuGyVj530JVtzZaOxH4SG0oxCJj6 67XSgTiOHS0/kU92bU4VEHDxSuRAB3Gi5K9asijybUlY4gyOHk2+KqrsLbF9snMmc2ed hVspTKYQnSD3NAu0iBt5S2TcJ0rhNIcAcCrwbVgz7IePvmqt+vgltICh5JApu9xhpXol xi5GV84pIEcabgZ/HXKq5nAWX3WJsFQZu479nv03OJQwv0UaXhlwFDq25t6hO3b24pjz xuRm/5MmaTbWQmrE2qrwow+ixyvPJ1sO0nVUUVBfPHp+XjR7bQmC28dnUmtXIun+jn4n k0VA== X-Gm-Message-State: ACgBeo1rcdmqT0VR00fBAgmSvH2LkM8FuHk3HwKtB9tcg23H8PnynmcO EHEq/uO6/aFnV8HH5t6T8Lzvu+DBiY7bcXCOjHnJx6g7D8go2FfuDryMMSeDydE8gwp5KYcSduS CUWfh4Im6H8QKslJqK7YQffMyLEytMa/QIXccyUqy1EZqDzzg1ESNmdHFISBY8+Y29bFY5Q== X-Google-Smtp-Source: AA6agR4ATB4rd/E+Yib6g1x/Un/QX10KVOPSLBYrSV7E3jAYeDJgdVlnl3sf2MKEZUQJL1J/GFxE3Eb/Crc= X-Received: from haoluo.svl.corp.google.com ([2620:15c:2d4:203:7c9:7b32:e73f:6716]) (user=haoluo job=sendgmr) by 2002:a25:640d:0:b0:670:9077:2203 with SMTP id y13-20020a25640d000000b0067090772203mr12776495ybb.460.1659387045104; Mon, 01 Aug 2022 13:50:45 -0700 (PDT) Date: Mon, 1 Aug 2022 13:50:39 -0700 Message-Id: <20220801205039.2755281-1-haoluo@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.37.1.455.g008518b4e5-goog Subject: [PATCH bpf-next v1] bpf, iter: clean up bpf_seq_read(). From: Hao Luo To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , KP Singh , John Fastabend , Stanislav Fomichev , Jiri Olsa , Hao Luo Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor bpf_seq_read() by extracting some common logic into helper functions. I hope this makes bpf_seq_read() more readable. This is a refactoring patch, so no behavior change is expected. Signed-off-by: Hao Luo --- kernel/bpf/bpf_iter.c | 156 +++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 63 deletions(-) diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c index 7e8fd49406f6..39b5b647fdb7 100644 --- a/kernel/bpf/bpf_iter.c +++ b/kernel/bpf/bpf_iter.c @@ -77,6 +77,83 @@ static bool bpf_iter_support_resched(struct seq_file *se= q) return iter_priv->tinfo->reg_info->feature & BPF_ITER_RESCHED; } =20 +/* do_copy_to_user, copies seq->buf at offset seq->from to userspace and + * updates corresponding fields in seq. It returns -EFAULT if any error + * happens. The actual number of bytes copied is returned via the argument + * 'copied'. + */ +static int do_copy_to_user(struct seq_file *seq, char __user *buf, size_t = size, + size_t *copied) +{ + size_t n; + + n =3D min(seq->count, size); + if (copy_to_user(buf, seq->buf + seq->from, n)) + return -EFAULT; + + seq->count -=3D n; + seq->from +=3D n; + *copied =3D n; + return 0; +} + +/* do_seq_show, shows the given object 'p'. If 'p' is skipped or + * error happens, resets seq->count to 'offs'. + * + * Returns err > 0, indicating show() skips this object. + * Returns err =3D 0, indicating show() succeeds. + * Returns err < 0, indicating show() fails or overflow happened. + */ +static int do_seq_show(struct seq_file *seq, void *p, size_t offs) +{ + int err; + + WARN_ON(IS_ERR_OR_NULL(p)); + + err =3D seq->op->show(seq, p); + if (err > 0) { + /* object is skipped, decrease seq_num, so next + * valid object can reuse the same seq_num. + */ + bpf_iter_dec_seq_num(seq); + seq->count =3D offs; + return err; + } + + if (err < 0 || seq_has_overflowed(seq)) { + seq->count =3D offs; + return err ? err : -E2BIG; + } + + /* err =3D=3D 0 and no overflow */ + return 0; +} + +/* do_seq_stop, stops at the given object 'p'. 'p' could be an ERR or NULL= . If + * 'p' is an ERR or there was an overflow, reset seq->count to 'offs' and + * returns error. Returns 0 otherwise. + */ +static int do_seq_stop(struct seq_file *seq, void *p, size_t offs) +{ + if (IS_ERR(p)) { + seq->op->stop(seq, NULL); + seq->count =3D offs; + return PTR_ERR(p); + } + + seq->op->stop(seq, p); + if (!p) { + if (!seq_has_overflowed(seq)) { + bpf_iter_done_stop(seq); + } else { + seq->count =3D offs; + if (offs =3D=3D 0) + return -E2BIG; + } + } + return 0; +} + /* maximum visited objects before bailing out */ #define MAX_ITER_OBJECTS 1000000 =20 @@ -91,7 +168,7 @@ static ssize_t bpf_seq_read(struct file *file, char __us= er *buf, size_t size, loff_t *ppos) { struct seq_file *seq =3D file->private_data; - size_t n, offs, copied =3D 0; + size_t offs, copied =3D 0; int err =3D 0, num_objs =3D 0; bool can_resched; void *p; @@ -108,40 +185,18 @@ static ssize_t bpf_seq_read(struct file *file, char _= _user *buf, size_t size, } =20 if (seq->count) { - n =3D min(seq->count, size); - err =3D copy_to_user(buf, seq->buf + seq->from, n); - if (err) { - err =3D -EFAULT; - goto done; - } - seq->count -=3D n; - seq->from +=3D n; - copied =3D n; + err =3D do_copy_to_user(seq, buf, size, &copied); goto done; } =20 seq->from =3D 0; p =3D seq->op->start(seq, &seq->index); - if (!p) + if (IS_ERR_OR_NULL(p)) goto stop; - if (IS_ERR(p)) { - err =3D PTR_ERR(p); - seq->op->stop(seq, p); - seq->count =3D 0; - goto done; - } =20 - err =3D seq->op->show(seq, p); - if (err > 0) { - /* object is skipped, decrease seq_num, so next - * valid object can reuse the same seq_num. - */ - bpf_iter_dec_seq_num(seq); - seq->count =3D 0; - } else if (err < 0 || seq_has_overflowed(seq)) { - if (!err) - err =3D -E2BIG; - seq->op->stop(seq, p); + err =3D do_seq_show(seq, p, 0); + if (err < 0) { + do_seq_stop(seq, p, 0); seq->count =3D 0; goto done; } @@ -153,7 +208,7 @@ static ssize_t bpf_seq_read(struct file *file, char __u= ser *buf, size_t size, num_objs++; offs =3D seq->count; p =3D seq->op->next(seq, p, &seq->index); - if (pos =3D=3D seq->index) { + if (unlikely(pos =3D=3D seq->index)) { pr_info_ratelimited("buggy seq_file .next function %ps " "did not updated position index\n", seq->op->next); @@ -161,7 +216,7 @@ static ssize_t bpf_seq_read(struct file *file, char __u= ser *buf, size_t size, } =20 if (IS_ERR_OR_NULL(p)) - break; + goto stop; =20 /* got a valid next object, increase seq_num */ bpf_iter_inc_seq_num(seq); @@ -172,22 +227,16 @@ static ssize_t bpf_seq_read(struct file *file, char _= _user *buf, size_t size, if (num_objs >=3D MAX_ITER_OBJECTS) { if (offs =3D=3D 0) { err =3D -EAGAIN; - seq->op->stop(seq, p); + do_seq_stop(seq, p, seq->count); goto done; } break; } =20 - err =3D seq->op->show(seq, p); - if (err > 0) { - bpf_iter_dec_seq_num(seq); - seq->count =3D offs; - } else if (err < 0 || seq_has_overflowed(seq)) { - seq->count =3D offs; + err =3D do_seq_show(seq, p, offs); + if (err < 0) { if (offs =3D=3D 0) { - if (!err) - err =3D -E2BIG; - seq->op->stop(seq, p); + do_seq_stop(seq, p, seq->count); goto done; } break; @@ -197,30 +246,11 @@ static ssize_t bpf_seq_read(struct file *file, char _= _user *buf, size_t size, cond_resched(); } stop: - offs =3D seq->count; - /* bpf program called if !p */ - seq->op->stop(seq, p); - if (!p) { - if (!seq_has_overflowed(seq)) { - bpf_iter_done_stop(seq); - } else { - seq->count =3D offs; - if (offs =3D=3D 0) { - err =3D -E2BIG; - goto done; - } - } - } - - n =3D min(seq->count, size); - err =3D copy_to_user(buf, seq->buf, n); - if (err) { - err =3D -EFAULT; + err =3D do_seq_stop(seq, p, seq->count); + if (err) goto done; - } - copied =3D n; - seq->count -=3D n; - seq->from =3D n; + + err =3D do_copy_to_user(seq, buf, size, &copied); done: if (!copied) copied =3D err; --=20 2.37.1.455.g008518b4e5-goog