Skip to content

Expand ciq-cherry-pick with alternate source parameters - #89

Open
PlaidCat wants to merge 13 commits into
mainlinefrom
{rnicolescu}_commit_source
Open

PlaidCat wants to merge 13 commits into
mainlinefrom
{rnicolescu}_commit_source

Conversation

@PlaidCat

@PlaidCat PlaidCat commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Adding in additional features from Roxana, there was a push to make more shared resources between kt libraries and this tool

I used GLM to update the tests and add legacy switches to do the same thing --ticket/--jira do the same thing, --commit/--sha do the same thing.

$ python3.14 ../kernel-src-tree-tools/ciq-cherry-pick.py --commit 48f6a5356a33dd78e7144ae1faef95ffc990aae0 --ciq-tag "cve CVE-2026-43503" --jira VULN-185809 --jira-dry-run --vulns-dir ../vulns/ --ignore-fixes-check --commit-source linux-5.10.y --commit-source-sha fbeab9555564a1b98e8582cd106dfe46c4606991
commit cfc439867d942da6aa0f463f491956c919bbf834 (HEAD -> {maple}_ciqlts8_6, {maple_test}_ciqlts8_6)
Author: Jonathan Maple <jmaple@ciq.com>
Date:   Fri Oct 23 15:46:40 2026 -0400

    net: skbuff: propagate shared-frag marker through frag-transfer helpers

    jira VULN-185809
    cve CVE-2026-43503
    commit-author Hyunwoo Kim <imv4bel@gmail.com>
    commit 48f6a5356a33dd78e7144ae1faef95ffc990aae0
    commit-source linux-5.10.y
    commit-source-sha fbeab9555564a1b98e8582cd106dfe46c4606991

    commit 48f6a5356a33dd78e7144ae1faef95ffc990aae0 upstream.

    Two frag-transfer helpers (__pskb_copy_fclone() and skb_shift()) fail
    to propagate the SKBFL_SHARED_FRAG bit in skb_shinfo()->flags when
    moving frags from source to destination.  __pskb_copy_fclone() defers
    the rest of the shinfo metadata to skb_copy_header() after copying
    frag descriptors, but that helper only carries over gso_{size,segs,
    type} and never touches skb_shinfo()->flags; skb_shift() moves frag
    descriptors directly and leaves flags untouched.  As a result, the
    destination skb keeps a reference to the same externally-owned or
    page-cache-backed pages while reporting skb_has_shared_frag() as
    false.

    The mismatch is harmful in any in-place writer that uses
    skb_has_shared_frag() to decide whether shared pages must be detoured
    through skb_cow_data().  ESP input is one such writer (esp4.c,
    esp6.c), and a single nft 'dup to <local>' rule -- or any other
    nf_dup_ipv4() / xt_TEE caller -- is enough to land a pskb_copy()'d
    skb in esp_input() with the marker stripped, letting an unprivileged
    user write into the page cache of a root-owned read-only file via
    authencesn-ESN stray writes.

    Set SKBFL_SHARED_FRAG on the destination whenever frag descriptors
    were actually moved from the source.  skb_copy() and skb_copy_expand()
    share skb_copy_header() too but linearize all paged data into freshly
    allocated head storage and emerge with nr_frags == 0, so
    skb_has_shared_frag() returns false on its own; they need no change.

    The same omission exists in skb_gro_receive() and skb_gro_receive_list().
    The former moves the incoming skb's frag descriptors into the
    accumulator's last sub-skb via two paths (a direct frag-move loop and
    the head_frag + memcpy path); the latter chains the incoming skb whole
    onto p's frag_list.  Downstream skb_segment() reads only
    skb_shinfo(p)->flags, and skb_segment_list() reuses each sub-skb's
    shinfo as the nskb -- both p and lp must carry the marker.

    The same omission also exists in tcp_clone_payload(), which builds an
    MTU probe skb by moving frag descriptors from skbs on sk_write_queue
    into a freshly allocated nskb.  The helper falls into the same family
    and warrants the same fix for consistency; no TCP TX-side in-place
    writer is currently known to reach a user page through this gap, but
    a future consumer depending on the marker would regress silently.

    The same omission exists in skb_segment(): the per-iteration flag
    merge takes only head_skb's flag, and the inner switch that rebinds
    frag_skb to list_skb on head_skb-frags exhaustion does not fold the
    new frag_skb's flag into nskb.  Fold frag_skb's flag at both sites
    so segments drawing frags from frag_list members carry the marker.

    Fixes: cef401de7be8 ("net: fix possible wrong checksum generation")
    Fixes: f4c50a4034e6 ("xfrm: esp: avoid in-place decrypt on shared skb frags")
            Suggested-by: Sabrina Dubroca <sd@queasysnail.net>
            Suggested-by: Sultan Alsawaf <sultan@kerneltoast.com>
            Suggested-by: Ben Hutchings <ben@decadent.org.uk>
            Suggested-by: Lin Ma <malin89@huawei.com>
            Suggested-by: Jingguo Tan <tanjingguo@huawei.com>
            Suggested-by: Aaron Esau <aaron1esau@gmail.com>
            Cc: stable@vger.kernel.org
            Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
            Tested-by: Rajat Gupta <rajat.gupta@oss.qualcomm.com>
    Link: https://patch.msgid.link/ageeJfJHwgzmKXbh@v4bel
            Signed-off-by: Paolo Abeni <pabeni@redhat.com>
    [bwh: Backported to 5.10:
     - Set the SKBTX_SHARED_FRAG flag in skb_shared_info::tx_flags,
       instead of SKBFL_SHARED_FRAG in skb_shared_info::flags
     - skb_gro_receive() and skb_gro_receive_list() are in skbuff.c here
     - Drop change to tcp_clone_payload(), which does not exist here
     - Adjust context in skb_shift()
    ]
            Signed-off-by: Ben Hutchings <benh@debian.org>
            Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    (cherry picked from commit fbeab9555564a1b98e8582cd106dfe46c4606991)
    Signed-off-by: Jonathan Maple <jmaple@ciq.com>

Coverage Report

Name Stmts Miss Branch BrPart Cover Missing
check_fips_changes.py 42 42 12 0 0% 8-67
check_kernel_commits.py 176 176 74 0 0% 3-365
ciq-cherry-pick.py 224 76 64 5 68% 53, 59, 67-69, 72-101, 139, 178-179, 199-200, 210-227, 258, 263-265, 369-472
ciq-tag.py 146 146 16 0 0% 3-380
jira_pr_check.py 159 159 58 0 0% 3-350
kt/ktlib/ciq_helpers.py 321 195 142 8 35% 33-53, 76-108, 163-165, 237-238, 242, 247, 296, 304->303, 305->304, 325->323, 354, 375-377, 385-390, 399-401, 410-415, 426-439, 450-474, 484-498, 556-622, 631-641, 645-654, 664-679, 691-708
kt/ktlib/ciq_tag.py 235 74 54 12 61% 87, 102, 105, 108-110, 116, 118, 120, 122, 124, 161-168, 194-198, 211-230, 238, 245, 248, 253, 257-259, 271, 286, 293, 302, 331, 340, 347, 350-360, 373-389, 405-429, 442, 455-462
kt/ktlib/command_runner.py 33 20 6 0 33% 16, 20-33, 37-61, 65-66
kt/ktlib/commit_header.py 78 2 26 2 96% 40, 86
kt/ktlib/config.py 59 0 16 0 100%
kt/ktlib/git_remote.py 60 0 14 0 100%
kt/ktlib/jira.py 148 119 32 0 16% 19-27, 39-55, 58-61, 64-68, 71-74, 77-80, 83-88, 91-98, 101-121, 124-131, 134-138, 142-157, 161-164, 171-184, 187-190, 193-209, 212-219, 222-224
kt/ktlib/kernel_workspace.py 147 50 28 2 62% 24, 100, 141-143, 148-150, 153-159, 172-183, 194-204, 221-224, 228-263
kt/ktlib/kernels.py 96 13 20 1 86% 77-85, 139, 155-162
kt/ktlib/local.py 5 1 0 0 80% 12
kt/ktlib/repo.py 29 15 2 0 45% 30-31, 34-35, 43-55
kt/ktlib/ssh.py 12 5 2 0 50% 9-12, 16
kt/ktlib/util.py 17 0 0 0 100%
kt/ktlib/virt.py 80 39 10 0 46% 26, 34-37, 51-78, 82-88, 92-93, 97, 101, 105, 109, 119-127, 133-138, 142-147
kt/ktlib/vm.py 312 148 56 3 51% 126-143, 176-185, 193-204, 233-237, 252->263, 280->286, 291-301, 304-305, 318-322, 325, 328-344, 349-366, 369-376, 385-391, 436-447, 450-451, 454, 458-463, 475-488, 501-508, 517, 526-538, 541-548, 551-560, 563
release_config.py 2 2 0 0 0% 7-27
rolling-release-update.py 264 264 106 0 0% 1-412
run_interdiff.py 165 165 56 0 0% 3-248
update_lt_spec.py 211 211 46 0 0% 9-400
TOTAL 3021 1922 840 33 34%

roxanan1996 and others added 13 commits October 23, 2026 14:04
Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Just an interface that provides more clarity around ciq headers, but needs refining.
Especially around getters and setters.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Had to change --sha and --ticket params to --commit and --jira to match
the CommitHeader dataclass.

Also created CherryPickCommand class that keeps track of the arguments
given to this script, in order to avoid long function with too many parameters.
The logic did not change at all, except for the fact that cherry_pick functions
and their helpers receive a CommitHeader object instead of the multiple params.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Here not a huge change.
upstream commit should be just one, so I removed the useless for.
What's nice that we do not need regex anymore.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
commit_author and commit field represent the commit in mainline.
If the commit is not in mainline yet, commit value can be `-` or left empty.
The fields that show the actual source is something else are:
1. commit_source which could be one of these:

arm64: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
centos-stream-9: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
centos-stream-10: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
linux-stable: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

2. commit_source_sha: the actual sha from the remotes presented above.
3. commit_source_author (optional)

Introduces upstream_sources.yaml file that contains a list of upstream sources
other than mainline. List should be extended to other subsystems soon.

It also modifies the following scripts to take into account different commit sources:
1. ciq-cherry-pick.py
It receives extra arguments with the commit source and it is responsible of
fetching the corresponding upstream remote and cherry picking the commit.
2. check_kernel_commits.py
If there is no mainline commit, it does not do any extra checks, since this means
the commit is probably in review process (taken from lore).
NOTE: This should be revisited later, since we may need checks regardless if
the commit is in mainline or not.
3. run_interdiff.py
If there is another source commit other than mainline, that is the one used
to show the diff.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
…sed bugs

The {rnicolescu}_commit_source refactor replaced the flat ciq-cherry-pick
functions with CherryPickCommand, CommitHeader and UpstreamRemotes, but the
test suite still targeted the deleted API (28 failures) and the new code
itself was untested.

Test changes:
- Rewrite tests/test_ciq_cherry_pick.py against the CherryPickCommand API:
  _manage_commit_message (header tags, ordering, upstream-diff on conflict,
  # Conflicts: stripping, commit-source tags), _cherry_pick (mainline,
  cve-bf, source-sha pick via extract_upstream_name_and_sha, conflict,
  author resolution), _check_fixes, _update_jira_success/failure,
  _cherry_pick_fixes (skip guard for source-only picks, cve -> cve-bf swap)
  and from_argsparse_to_commit_header (tag parsing, sha expansion, remote
  fetch only when both --commit-source and --commit-source-sha are given).
- Expand tests/kt/ktlib/test_commit_header.py: parsing of source-only and
  mainline bodies, to_str() round trip, cve helpers,
  extract_upstream_name_and_sha, and a regression test proving the
  commit-source / commit-source-sha tags can never match the
  '^commit <40hex>' anchor check_kernel_commits.py validates against.
- Add tests/kt/ktlib/test_git_remote.py for UpstreamRemotes/GitRemoteInfo:
  from_dict, auto-add + fetch, idempotency, unknown remote name,
  URL-mismatch warning.
- Adapt tests/kt/ktlib/test_ciq_helpers.py to the commit_header signature.

Fixes the new tests exposed:
- commit_header: to_str() returned a list despite '-> str', leaking a
  Python list repr into every standardized commit message; return the tag
  lines joined with newlines.
- ciq-cherry-pick: map hyphenated tag names (cve-pre, cve-bf) to the
  underscored CommitHeader fields, which from_dict otherwise drops
  silently; tolerate multi-word and comma-separated --ciq-tag values
  (split with maxsplit); skip the Fixes: search when there is no mainline
  sha (source-only pick); let CherryPickCommand construction errors
  propagate instead of crashing later on an uninitialized command.
- git_remote: warn when fetching an existing remote whose url differs from
  the configured one instead of silently fetching from the old url.
The commit_source refactor renamed the target-sha flag --sha to --commit,
which breaks existing callers - notably kernel-tools'
cve_remediation_automation.py, which still invokes
'ciq-cherry-pick.py --sha <sha> --ticket ... --ciq-tag ...' and would
fail with 'unrecognized arguments: --sha'.

Accept both flags naming the same internal parameter:
- --sha is parsed into its own dest and folded into args.commit by
  resolve_sha_alias() right after parse_args()
- passing both with conflicting values is an argparse error
- passing both with the same value is accepted

--help marks --sha as a deprecated alias.
The commit-source tag is a provenance label and can now be either an
upstream_sources.yaml remote name (e.g. centos-stream-9) or a stable
branch name (e.g. linux-6.12.y). Both consumers of that tag treated it
strictly as a remote-name key:

- ciq-cherry-pick.py fetch_remote() would KeyError on a branch name
- run_interdiff.py likewise, flagging every branch-provenance PR
  commit as an ERROR during CI validation

Add UpstreamRemotes.fetch_for_commit_source(commit_source, sha, repo_dir):
1. sha already resolvable locally -> no-op (no network; the CI fast path
   when the workflow pre-fetched the branch)
2. commit_source is a yaml key -> fetch that remote (unchanged behavior)
3. commit_source is a branch -> ls-remote the configured remotes (ref
   query only, no objects) and fetch the first one carrying
   refs/heads/<branch>
4. otherwise raise RuntimeError with actionable guidance

Both call sites switch to the helper. run_interdiff additionally only
fetches when both source name and sha are present.
….org

centos-stream-10 pointed at the arm64 kernel tree (copy-paste bug);
point it at the CentOS Stream 10 kernel gitlab instead.

kernel.org entries used git://, an unauthenticated transport whose port
9418 is commonly blocked by firewalls; switch to https.
The commit_source refactor renamed --ticket to --jira, breaking existing
callers - kernel-tools' cve_remediation_automation.py still passes
--ticket VULN-xxx and died with 'unrecognized arguments' (invisible to
its logs, which discard stderr).

Same pattern as the --sha alias: separate dest folded by
resolve_ticket_alias() right after parse_args(); conflicting values are
an argparse error; same value is fine.
@PlaidCat PlaidCat self-assigned this Oct 26, 2026
Copilot AI balanced review requested due to automatic review settings October 26, 2026 21:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Credential exposure, incorrect follow-up source selection, and metadata-handling regressions remain unresolved.

15 open issues
What changed in this PR

Expands ciq-cherry-pick to support alternate upstream sources and shares commit-header handling across backporting and PR-validation tools.

Changes:

  • Adds source provenance tags, remote discovery, and automatic fetching.
  • Refactors cherry-picking into CherryPickCommand, retaining legacy CLI aliases.
  • Migrates validation tools to shared headers and expands regression coverage.
File Description
upstream_sources.yaml Defines available upstream repositories.
tests/​test_ciq_cherry_pick.py Updates command tests and covers source parameters and aliases.
tests/​kt/​ktlib/​test_git_remote.py Tests remote fetching and source resolution.
tests/​kt/​ktlib/​test_commit_header.py Tests header parsing, serialization, and source selection.
tests/​kt/​ktlib/​test_ciq_helpers.py Updates message-standardization coverage.
run_interdiff.py Selects and fetches alternate comparison sources.
kt/​ktlib/​git_remote.py Adds shared remote discovery and fetching.
kt/​ktlib/​commit_header.py Introduces the shared commit-header model.
kt/​ktlib/​ciq_tag.py Recognizes source provenance tags.
kt/​ktlib/​ciq_helpers.py Uses structured headers for commit messages.
jira_pr_check.py Migrates Jira validation to shared headers.
ciq-tag.py Imports the packaged tag library.
ciq-cherry-pick.py Adds alternate-source handling and legacy aliases.
check_kernel_commits.py Uses shared headers for upstream and CVE checks.

Review effort: Balanced

Comment thread ciq-cherry-pick.py
except (CherryPickException, RuntimeError) as e:
# TODO would add some extra information to jira if the cve-bf deps are not applied
raise e
print(args)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup removing

Comment thread check_kernel_commits.py
Comment on lines +129 to +133
short_uhash = commit_header.commit[:12]
uhash = commit_header.commit
if not uhash or uhash == "-":
print(f"[NOTE]: Mainline commit not present for {pr_commit_desc}, no extra checks for this commit")
continue

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving

Comment thread ciq-cherry-pick.py
Comment on lines +72 to +73
if not commit_header.is_cve():
return commit_header
Comment thread ciq-cherry-pick.py
# Continue with the existing tag
return commit_header

commit_header.set_cve(cve_number=vuln_cve_number)
Comment thread ciq-cherry-pick.py
author and the original commit full sha.
# Cherry pick the fixed-by dependencies
try:
self._cherry_pick_fixes(original_commit_header=updated_commit_header)
Comment thread kt/ktlib/commit_header.py
tag_value = value[0][1]._value
msg_dict[tag_name] = tag_value

return cls(**msg_dict)
Comment thread kt/ktlib/commit_header.py

@classmethod
def from_commit_body(cls, commit_body: str) -> CommitHeader:
ciq_msg = CiqMsg(commit_body)
Comment thread kt/ktlib/commit_header.py

def to_str(self) -> str:
commit_header_dict = asdict(self)
return "\n".join(f"{key.replace('_', '-')} {value}" for key, value in commit_header_dict.items() if value)
Comment thread kt/ktlib/git_remote.py
f"remote '{self.name}' exists with url {remote.url}, "
f"different from configured {self.url}; fetching from the existing url"
)
remote.fetch()
Comment thread kt/ktlib/git_remote.py

# 3. Branch-style provenance: find a configured remote carrying the branch.
for git_remote_info in self.remotes.values():
ls = Repo(repo_dir).git.ls_remote(git_remote_info.url, f"refs/heads/{commit_source}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants