mirror of
https://git.yoctoproject.org/poky
synced 2026-02-20 08:29:42 +01:00
Compare commits
146 Commits
yocto-4.0.
...
kirkstone-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c05660b21 | ||
|
|
cb1206dd84 | ||
|
|
33d90091be | ||
|
|
9f461395a8 | ||
|
|
0002d5d082 | ||
|
|
db73f23fc2 | ||
|
|
40701465df | ||
|
|
ba9338d810 | ||
|
|
46c836aefa | ||
|
|
5f8155aefa | ||
|
|
dd0a2c2470 | ||
|
|
c5794d82b0 | ||
|
|
169ca8debf | ||
|
|
5d27e8f05d | ||
|
|
d492537188 | ||
|
|
052e4214aa | ||
|
|
c76f44b1da | ||
|
|
088d1497d5 | ||
|
|
22f8da4818 | ||
|
|
4030876db9 | ||
|
|
c6234dce63 | ||
|
|
6639c7b295 | ||
|
|
7c4bd642e4 | ||
|
|
f58483837c | ||
|
|
cdc78fd36f | ||
|
|
36165cce68 | ||
|
|
9734a91472 | ||
|
|
42d2a2e8cd | ||
|
|
940e5e75b9 | ||
|
|
3d559d269a | ||
|
|
36037789d2 | ||
|
|
7dd51aea98 | ||
|
|
851a3f0c55 | ||
|
|
dacb67f70f | ||
|
|
232e8ebe3c | ||
|
|
41c16e82e9 | ||
|
|
cab0ee97d8 | ||
|
|
d54b15eba1 | ||
|
|
2943f88d88 | ||
|
|
9479971ef9 | ||
|
|
2cf2a95adb | ||
|
|
bababfb854 | ||
|
|
6f01aae51d | ||
|
|
33d61e50c1 | ||
|
|
9cc35e0f6d | ||
|
|
a916d3a38a | ||
|
|
b0c11efc8f | ||
|
|
478f5eaa61 | ||
|
|
748f958fd3 | ||
|
|
73e3da5d44 | ||
|
|
6b397fb207 | ||
|
|
6ab506f474 | ||
|
|
809b3e9113 | ||
|
|
e2d947b1cc | ||
|
|
1dd6d90744 | ||
|
|
8641f0fec9 | ||
|
|
484d31c23d | ||
|
|
aaf9219788 | ||
|
|
d152607f64 | ||
|
|
0de012f0f6 | ||
|
|
c4200e606c | ||
|
|
04b39e5b7e | ||
|
|
8d5cd4a310 | ||
|
|
59579acac7 | ||
|
|
56aa9e3241 | ||
|
|
ea90d0a5b1 | ||
|
|
9e1c28514a | ||
|
|
24772dd301 | ||
|
|
5f0dcc1dc6 | ||
|
|
8d8972d1b4 | ||
|
|
9626809dce | ||
|
|
3fe029171f | ||
|
|
9a4c708aa5 | ||
|
|
2442316a1e | ||
|
|
48ab50b55c | ||
|
|
bee2fe9cc5 | ||
|
|
d0f445a1e2 | ||
|
|
0118bd1e10 | ||
|
|
7ca21c761a | ||
|
|
4e75dd0f5f | ||
|
|
75cb79eaf5 | ||
|
|
5abe7f3283 | ||
|
|
9a1d2ff9d0 | ||
|
|
2b691e84d8 | ||
|
|
41ae63737b | ||
|
|
ca6745e603 | ||
|
|
d847c8aac1 | ||
|
|
1bf7d50410 | ||
|
|
b48d3ea982 | ||
|
|
42b3adafcc | ||
|
|
2105de9c82 | ||
|
|
dd624cec3b | ||
|
|
2fdbec72e5 | ||
|
|
7b6bc5b49c | ||
|
|
0c1db5ac27 | ||
|
|
8f20ad5f77 | ||
|
|
74672d72c0 | ||
|
|
f245c680a8 | ||
|
|
2325a1dbc5 | ||
|
|
2952d99f0f | ||
|
|
962d08fb40 | ||
|
|
425363de54 | ||
|
|
e5fb48f371 | ||
|
|
259d81175f | ||
|
|
eca1e13385 | ||
|
|
e46adde7bb | ||
|
|
d34a0bd00b | ||
|
|
11f3763b0f | ||
|
|
89a78911d7 | ||
|
|
673b839a6b | ||
|
|
f63f49bdea | ||
|
|
7a5c6b3e18 | ||
|
|
5d1ccbd52f | ||
|
|
c95f2e55ac | ||
|
|
02148028a0 | ||
|
|
093e91d190 | ||
|
|
0163ca382a | ||
|
|
0adb465b9e | ||
|
|
ca3783f70d | ||
|
|
b5a57a04eb | ||
|
|
ed56389e82 | ||
|
|
4a1254610c | ||
|
|
4ef41425c6 | ||
|
|
db50dd87bc | ||
|
|
2b82706dc5 | ||
|
|
bc7377a239 | ||
|
|
7f12221f49 | ||
|
|
11d8b290dd | ||
|
|
55c58356f1 | ||
|
|
3c3b5d0fe9 | ||
|
|
3ff44348f7 | ||
|
|
1f6c798015 | ||
|
|
fd0df2cb78 | ||
|
|
ffd5cd98d6 | ||
|
|
794b42f01a | ||
|
|
11999973cb | ||
|
|
49a5ab4d5f | ||
|
|
d153a3dc36 | ||
|
|
2399c63ca5 | ||
|
|
866395041f | ||
|
|
6303a9d5b5 | ||
|
|
1811a2d13e | ||
|
|
15dd68bda1 | ||
|
|
9c9c706252 | ||
|
|
d2a96dd89c | ||
|
|
9ae3736eb4 |
@@ -123,110 +123,116 @@ to add the upgraded version.
|
||||
|
||||
$ git commit -s file1 file2 dir1 dir2 ...
|
||||
|
||||
To include **a**\ ll staged files::
|
||||
To include all staged files::
|
||||
|
||||
$ git commit -sa
|
||||
|
||||
- The ``-s`` option of ``git commit`` adds a "Signed-off-by:" line
|
||||
to your commit message. There is the same requirement for contributing
|
||||
to the Linux kernel. Adding such a line signifies that you, the
|
||||
submitter, have agreed to the `Developer's Certificate of Origin 1.1
|
||||
<https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin>`__
|
||||
as follows:
|
||||
#. The ``-s`` option of ``git commit`` adds a "Signed-off-by:" line
|
||||
to your commit message. There is the same requirement for contributing
|
||||
to the Linux kernel. Adding such a line signifies that you, the
|
||||
submitter, have agreed to the `Developer's Certificate of Origin 1.1
|
||||
<https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin>`__
|
||||
as follows:
|
||||
|
||||
.. code-block:: none
|
||||
.. code-block:: none
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
|
||||
- Provide a single-line summary of the change and, if more
|
||||
explanation is needed, provide more detail in the body of the
|
||||
commit. This summary is typically viewable in the "shortlist" of
|
||||
changes. Thus, providing something short and descriptive that
|
||||
gives the reader a summary of the change is useful when viewing a
|
||||
list of many commits. You should prefix this short description
|
||||
with the recipe name (if changing a recipe), or else with the
|
||||
short form path to the file being changed.
|
||||
#. Provide a single-line summary of the change and, if more
|
||||
explanation is needed, provide more detail in the description of the
|
||||
commit. This summary is typically viewable in the "shortlist" of
|
||||
changes. Thus, providing something short and descriptive that
|
||||
gives the reader a summary of the change is useful when viewing a
|
||||
list of many commits. You should prefix this short description
|
||||
with the recipe name (if changing a recipe), or else with the
|
||||
short form path to the file being changed.
|
||||
|
||||
.. note::
|
||||
|
||||
To find a suitable prefix for the commit summary, a good idea
|
||||
is to look for prefixes used in previous commits touching the
|
||||
same files or directories::
|
||||
|
||||
git log --oneline <paths>
|
||||
|
||||
#. For the commit description, provide detailed information
|
||||
that describes what you changed, why you made the change, and the
|
||||
approach you used. It might also be helpful if you mention how you
|
||||
tested the change. Provide as much detail as you can in the commit
|
||||
description.
|
||||
|
||||
.. note::
|
||||
|
||||
If the single line summary is enough to describe a simple
|
||||
change, the commit description can be left empty.
|
||||
|
||||
#. If the change addresses a specific bug or issue that is associated
|
||||
with a bug-tracking ID, include a reference to that ID in the body of the
|
||||
commit message. For example, the Yocto Project uses a
|
||||
specific convention for bug references --- any commit that addresses
|
||||
a specific bug should use the following form for the body of the commit
|
||||
message. Be sure to use the actual bug-tracking ID from
|
||||
Bugzilla for bug-id::
|
||||
|
||||
single-line summary of change
|
||||
|
||||
Fixes [YOCTO #bug-id]
|
||||
|
||||
detailed description of change
|
||||
|
||||
#. If other people participated in this patch, add some tags to the commit
|
||||
description to credit other contributors to the change:
|
||||
|
||||
- ``Reported-by``: name and email of a person reporting a bug
|
||||
that your commit is trying to fix. This is a good practice
|
||||
to encourage people to go on reporting bugs and let them
|
||||
know that their reports are taken into account.
|
||||
|
||||
- ``Suggested-by``: name and email of a person to credit for the
|
||||
idea of making the change.
|
||||
|
||||
- ``Tested-by``, ``Reviewed-by``: name and email for people having
|
||||
tested your changes or reviewed their code. These fields are
|
||||
usually added by the maintainer accepting a patch, or by
|
||||
yourself if you submitted your patches to early reviewers,
|
||||
or are submitting an unmodified patch again as part of a
|
||||
new iteration of your patch series.
|
||||
|
||||
- ``Cc``: name and email of people you want to send a copy
|
||||
of your changes to. This field will be used by ``git send-email``.
|
||||
|
||||
See `more guidance about using such tags
|
||||
<https://www.kernel.org/doc/html/latest/process/submitting-patches.html#using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes>`__
|
||||
in the Linux kernel documentation.
|
||||
|
||||
.. note::
|
||||
|
||||
To find a suitable prefix for the commit summary, a good idea
|
||||
is to look for prefixes used in previous commits touching the
|
||||
same files or directories::
|
||||
|
||||
git log --oneline <paths>
|
||||
|
||||
- For the body of the commit message, provide detailed information
|
||||
that describes what you changed, why you made the change, and the
|
||||
approach you used. It might also be helpful if you mention how you
|
||||
tested the change. Provide as much detail as you can in the body
|
||||
of the commit message.
|
||||
|
||||
.. note::
|
||||
|
||||
If the single line summary is enough to describe a simple
|
||||
change, the body of the commit message can be left empty.
|
||||
|
||||
- If the change addresses a specific bug or issue that is associated
|
||||
with a bug-tracking ID, include a reference to that ID in your
|
||||
detailed description. For example, the Yocto Project uses a
|
||||
specific convention for bug references --- any commit that addresses
|
||||
a specific bug should use the following form for the detailed
|
||||
description. Be sure to use the actual bug-tracking ID from
|
||||
Bugzilla for bug-id::
|
||||
|
||||
Fixes [YOCTO #bug-id]
|
||||
|
||||
detailed description of change
|
||||
|
||||
#. *Crediting contributors:* By using the ``git commit --amend`` command,
|
||||
you can add some tags to the commit description to credit other contributors
|
||||
to the change:
|
||||
|
||||
- ``Reported-by``: name and email of a person reporting a bug
|
||||
that your commit is trying to fix. This is a good practice
|
||||
to encourage people to go on reporting bugs and let them
|
||||
know that their reports are taken into account.
|
||||
|
||||
- ``Suggested-by``: name and email of a person to credit for the
|
||||
idea of making the change.
|
||||
|
||||
- ``Tested-by``, ``Reviewed-by``: name and email for people having
|
||||
tested your changes or reviewed their code. These fields are
|
||||
usually added by the maintainer accepting a patch, or by
|
||||
yourself if you submitted your patches to early reviewers,
|
||||
or are submitting an unmodified patch again as part of a
|
||||
new iteration of your patch series.
|
||||
|
||||
- ``CC:`` Name and email of people you want to send a copy
|
||||
of your changes to. This field will be used by ``git send-email``.
|
||||
|
||||
See `more guidance about using such tags
|
||||
<https://www.kernel.org/doc/html/latest/process/submitting-patches.html#using-reported-by-tested-by-reviewed-by-suggested-by-and-fixes>`__
|
||||
in the Linux kernel documentation.
|
||||
One can amend an existing git commit message to add missing tags for
|
||||
contributors with the ``git commit --amend`` command.
|
||||
|
||||
Test your changes
|
||||
-----------------
|
||||
@@ -650,8 +656,8 @@ backported to a stable branch unless the bug in question does not affect the
|
||||
master branch or the fix on the master branch is unsuitable for backporting.
|
||||
|
||||
The list of stable branches along with the status and maintainer for each
|
||||
branch can be obtained from the
|
||||
:yocto_wiki:`Releases wiki page </Releases>`.
|
||||
branch can be obtained from the :yocto_home:`Releases </development/releases/>`
|
||||
page.
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -909,6 +909,11 @@ to point to that directory::
|
||||
|
||||
EXTERNALSRC_BUILD:pn-myrecipe = "path-to-your-source-tree"
|
||||
|
||||
.. note::
|
||||
|
||||
The values of :term:`EXTERNALSRC` and :term:`EXTERNALSRC_BUILD`
|
||||
must be absolute paths.
|
||||
|
||||
Replicating a Build Offline
|
||||
===========================
|
||||
|
||||
|
||||
@@ -111,17 +111,17 @@ occurred in your project. Perhaps an attempt to :ref:`modify a variable
|
||||
<bitbake-user-manual/bitbake-user-manual-metadata:modifying existing
|
||||
variables>` did not work out as expected.
|
||||
|
||||
BitBake's ``-e`` option is used to display variable values after
|
||||
parsing. The following command displays the variable values after the
|
||||
configuration files (i.e. ``local.conf``, ``bblayers.conf``,
|
||||
BitBake's ``bitbake-getvar`` command is used to display variable values after
|
||||
parsing. The following command displays the variable value for :term:`OVERRIDES`
|
||||
after the configuration files (i.e. ``local.conf``, ``bblayers.conf``,
|
||||
``bitbake.conf`` and so forth) have been parsed::
|
||||
|
||||
$ bitbake -e
|
||||
$ bitbake-getvar OVERRIDES
|
||||
|
||||
The following command displays variable values after a specific recipe has
|
||||
been parsed. The variables include those from the configuration as well::
|
||||
The following command displays the value of :term:`PV` after a specific recipe
|
||||
has been parsed::
|
||||
|
||||
$ bitbake -e recipename
|
||||
$ bitbake-getvar -r recipename PV
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -135,19 +135,25 @@ been parsed. The variables include those from the configuration as well::
|
||||
the recipe datastore, which means that variables set within one task
|
||||
will not be visible to other tasks.
|
||||
|
||||
In the output of ``bitbake -e``, each variable is preceded by a
|
||||
description of how the variable got its value, including temporary
|
||||
values that were later overridden. This description also includes
|
||||
variable flags (varflags) set on the variable. The output can be very
|
||||
In the output of ``bitbake-getvar``, the line containing the value of the
|
||||
variable is preceded by a description of how the variable got its value,
|
||||
including temporary values that were later overridden. This description also
|
||||
includes variable flags (varflags) set on the variable. The output can be very
|
||||
helpful during debugging.
|
||||
|
||||
Variables that are exported to the environment are preceded by
|
||||
``export`` in the output of ``bitbake -e``. See the following example::
|
||||
``export`` in the output of ``bitbake-getvar``. See the following example::
|
||||
|
||||
export CC="i586-poky-linux-gcc -m32 -march=i586 --sysroot=/home/ulf/poky/build/tmp/sysroots/qemux86"
|
||||
|
||||
In addition to variable values, the output of the ``bitbake -e`` and
|
||||
``bitbake -e`` recipe commands includes the following information:
|
||||
Shell functions and tasks can also be inspected with the same mechanism::
|
||||
|
||||
$ bitbake-getvar -r recipename do_install
|
||||
|
||||
For Python functions and tasks, ``bitbake -e recipename`` can be used instead.
|
||||
|
||||
Moreover, the output of the ``bitbake -e`` and ``bitbake -e`` recipe commands
|
||||
includes the following information:
|
||||
|
||||
- The output starts with a tree listing all configuration files and
|
||||
classes included globally, recursively listing the files they include
|
||||
|
||||
@@ -123,10 +123,9 @@ Follow these general steps to create your layer without using tools:
|
||||
Lists all layers on which this layer depends (if any).
|
||||
|
||||
- :term:`LAYERSERIES_COMPAT`:
|
||||
Lists the :yocto_wiki:`Yocto Project </Releases>`
|
||||
releases for which the current version is compatible. This
|
||||
variable is a good way to indicate if your particular layer is
|
||||
current.
|
||||
Lists the :yocto_home:`Yocto Project releases </development/releases/>`
|
||||
for which the current version is compatible. This variable is a good
|
||||
way to indicate if your particular layer is current.
|
||||
|
||||
|
||||
.. note::
|
||||
@@ -822,6 +821,8 @@ The following list describes the available commands:
|
||||
|
||||
- ``create-layer``: Creates a basic layer.
|
||||
|
||||
- ``show-machines``: Lists the machines available in the currently configured layers.
|
||||
|
||||
Creating a General Layer Using the ``bitbake-layers`` Script
|
||||
============================================================
|
||||
|
||||
|
||||
@@ -83,19 +83,20 @@ command::
|
||||
OpenEmbedded recipe tool
|
||||
|
||||
options:
|
||||
-d, --debug Enable debug output
|
||||
-q, --quiet Print only errors
|
||||
--color COLOR Colorize output (where COLOR is auto, always, never)
|
||||
-h, --help show this help message and exit
|
||||
-d, --debug Enable debug output
|
||||
-q, --quiet Print only errors
|
||||
--color COLOR Colorize output (where COLOR is auto, always, never)
|
||||
-h, --help show this help message and exit
|
||||
|
||||
subcommands:
|
||||
create Create a new recipe
|
||||
newappend Create a bbappend for the specified target in the specified
|
||||
layer
|
||||
setvar Set a variable within a recipe
|
||||
appendfile Create/update a bbappend to replace a target file
|
||||
appendsrcfiles Create/update a bbappend to add or replace source files
|
||||
appendsrcfile Create/update a bbappend to add or replace a source file
|
||||
newappend Create a bbappend for the specified target in the specified layer
|
||||
create Create a new recipe
|
||||
setvar Set a variable within a recipe
|
||||
appendfile Create/update a bbappend to replace a target file
|
||||
appendsrcfiles Create/update a bbappend to add or replace source files
|
||||
appendsrcfile Create/update a bbappend to add or replace a source file
|
||||
edit Edit the recipe and appends for the specified target. This obeys $VISUAL if set,
|
||||
otherwise $EDITOR, otherwise vi.
|
||||
Use recipetool <subcommand> --help to get help on a specific command
|
||||
|
||||
Running ``recipetool create -o OUTFILE`` creates the base recipe and
|
||||
@@ -218,9 +219,9 @@ compilation and packaging files, and so forth.
|
||||
|
||||
The path to the per-recipe temporary work directory depends on the
|
||||
context in which it is being built. The quickest way to find this path
|
||||
is to have BitBake return it by running the following::
|
||||
is to use the ``bitbake-getvar`` utility::
|
||||
|
||||
$ bitbake -e basename | grep ^WORKDIR=
|
||||
$ bitbake-getvar -r basename WORKDIR
|
||||
|
||||
As an example, assume a Source Directory
|
||||
top-level folder named ``poky``, a default :term:`Build Directory` at
|
||||
@@ -438,7 +439,7 @@ Licensing
|
||||
=========
|
||||
|
||||
Your recipe needs to define variables related to the license
|
||||
under whith the software is distributed. See the
|
||||
under which the software is distributed. See the
|
||||
:ref:`contributor-guide/recipe-style-guide:recipe license fields`
|
||||
section in the Contributor Guide for details.
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@ See the
|
||||
documentation for details regarding the policies and maintenance of stable
|
||||
branches.
|
||||
|
||||
The :yocto_wiki:`Releases page </Releases>` contains a list
|
||||
of all releases of the Yocto Project. Versions in gray are no longer actively
|
||||
maintained with security patches, but well-tested patches may still be accepted
|
||||
for them for significant issues.
|
||||
The :yocto_home:`Releases </development/releases/>` page contains a list of all
|
||||
releases of the Yocto Project, grouped into current and previous releases.
|
||||
Previous releases are no longer actively maintained with security patches, but
|
||||
well-tested patches may still be accepted for them for significant issues.
|
||||
|
||||
Security-related discussions at the Yocto Project
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -676,7 +676,7 @@ described in the ":ref:`dev-manual/start:accessing index of releases`" section.
|
||||
.. note::
|
||||
|
||||
For a "map" of Yocto Project releases to version numbers, see the
|
||||
:yocto_wiki:`Releases </Releases>` wiki page.
|
||||
:yocto_home:`Releases </development/releases/>` page.
|
||||
|
||||
You can use the "RELEASE ARCHIVE" link to reveal a menu of all Yocto
|
||||
Project releases.
|
||||
|
||||
@@ -12,7 +12,7 @@ known security vulnerabilities, as tracked by the public
|
||||
database.
|
||||
|
||||
The Yocto Project maintains a `list of known vulnerabilities
|
||||
<https://autobuilder.yocto.io/pub/non-release/patchmetrics/>`__
|
||||
<https://valkyrie.yocto.io/pub/non-release/patchmetrics/>`__
|
||||
for packages in Poky and OE-Core, tracking the evolution of the number of
|
||||
unpatched CVEs and the status of patches. Such information is available for
|
||||
the current development version and for each supported release.
|
||||
@@ -235,7 +235,7 @@ products defined in :term:`CVE_PRODUCT`. Then, for each found CVE:
|
||||
The CVE database is stored in :term:`DL_DIR` and can be inspected using
|
||||
``sqlite3`` command as follows::
|
||||
|
||||
sqlite3 downloads/CVE_CHECK/nvdcve_1.1.db .dump | grep CVE-2021-37462
|
||||
sqlite3 downloads/CVE_CHECK/nvd*.db .dump | grep CVE-2021-37462
|
||||
|
||||
When analyzing CVEs, it is recommended to:
|
||||
|
||||
|
||||
@@ -724,13 +724,9 @@ a Raspberry Pi 2, which is based on the Broadcom 2708/2709 chipset::
|
||||
|
||||
KBUILD_DEFCONFIG:raspberrypi2 ?= "bcm2709_defconfig"
|
||||
|
||||
Aside from modifying your kernel recipe and providing your own
|
||||
``defconfig`` file, you need to be sure no files or statements set
|
||||
:term:`SRC_URI` to use a ``defconfig`` other than your "in-tree" file (e.g.
|
||||
a kernel's ``linux-``\ `machine`\ ``.inc`` file). In other words, if the
|
||||
build system detects a statement that identifies an "out-of-tree"
|
||||
``defconfig`` file, that statement will override your
|
||||
:term:`KBUILD_DEFCONFIG` variable.
|
||||
If the build system detects a statement that identifies an "out-of-tree"
|
||||
``defconfig`` file, your :term:`KBUILD_DEFCONFIG` variable will take precedence
|
||||
over it.
|
||||
|
||||
See the
|
||||
:term:`KBUILD_DEFCONFIG`
|
||||
@@ -1276,10 +1272,12 @@ appear in the ``.config`` file, which is in the :term:`Build Directory`.
|
||||
|
||||
It is simple to create a configuration fragment. One method is to use
|
||||
shell commands. For example, issuing the following from the shell
|
||||
creates a configuration fragment file named ``my_smp.cfg`` that enables
|
||||
multi-processor support within the kernel::
|
||||
creates a configuration fragment file named ``my_changes.cfg`` that enables
|
||||
multi-processor support within the kernel and disables the FPGA
|
||||
Configuration Framework::
|
||||
|
||||
$ echo "CONFIG_SMP=y" >> my_smp.cfg
|
||||
$ echo "CONFIG_SMP=y" >> my_changes.cfg
|
||||
$ echo "# CONFIG_FPGA is not set" >> my_changes.cfg
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -1516,15 +1514,13 @@ Expanding Variables
|
||||
===================
|
||||
|
||||
Sometimes it is helpful to determine what a variable expands to during a
|
||||
build. You can examine the values of variables by examining the
|
||||
output of the ``bitbake -e`` command. The output is long and is more
|
||||
easily managed in a text file, which allows for easy searches::
|
||||
build. You can examine the value of a variable by running the ``bitbake-getvar``
|
||||
command::
|
||||
|
||||
$ bitbake -e virtual/kernel > some_text_file
|
||||
$ bitbake-getvar -r virtual/kernel VARIABLE
|
||||
|
||||
Within the text file, you can see
|
||||
exactly how each variable is expanded and used by the OpenEmbedded build
|
||||
system.
|
||||
The output of the command explains exactly how the variable is expanded and used
|
||||
by the :term:`OpenEmbedded Build System`.
|
||||
|
||||
Working with a "Dirty" Kernel Version String
|
||||
============================================
|
||||
|
||||
@@ -36,3 +36,5 @@ Release 4.0 (kirkstone)
|
||||
release-notes-4.0.27
|
||||
release-notes-4.0.28
|
||||
release-notes-4.0.29
|
||||
release-notes-4.0.30
|
||||
release-notes-4.0.31
|
||||
|
||||
170
documentation/migration-guides/release-notes-4.0.30.rst
Normal file
170
documentation/migration-guides/release-notes-4.0.30.rst
Normal file
@@ -0,0 +1,170 @@
|
||||
Release notes for Yocto-4.0.30 (Kirkstone)
|
||||
------------------------------------------
|
||||
|
||||
Security Fixes in Yocto-4.0.30
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- cups: Fix :cve_nist:`2025-58060` and :cve_nist:`2025-58364`
|
||||
- dpkg: Fix :cve_nist:`2025-6297`
|
||||
- ffmpeg: Fix :cve_nist:`2023-6602`, :cve_nist:`2023-6604`, :cve_nist:`2023-6605`,
|
||||
:cve_nist:`2025-1594` and CVE-2025-7700
|
||||
- git: Fix :cve_nist:`2025-27613`, :cve_nist:`2025-27614`, :cve_nist:`2025-46334`,
|
||||
:cve_nist:`2025-46835` and :cve_nist:`2025-48384`
|
||||
- glib-2.0: Fix :cve_nist:`2025-7039`
|
||||
- glib-2.0: Ignore :cve_nist:`2025-4056`
|
||||
- go: Ignore :cve_nist:`2024-24790` and :cve_nist:`2025-0913`
|
||||
- gstreamer1.0-plugins-base: Fix :cve_nist:`2025-47806`, :cve_nist:`2025-47807` and
|
||||
:cve_nist:`2025-47808`
|
||||
- gstreamer1.0-plugins-good: Fix :cve_nist:`2025-47183` and :cve_nist:`2025-47219`
|
||||
- libarchive: Fix :cve_nist:`2025-5918`
|
||||
- libxslt: Fix :cve_nist:`2023-40403`
|
||||
- openssl: Fix :cve_nist:`2023-50781`
|
||||
- python3: Fix :cve_nist:`2025-8194`
|
||||
- qemu: Ignore :cve_nist:`2024-7730`
|
||||
- sqlite3: Revert "sqlite3: patch CVE-2025-7458"
|
||||
- tiff: Fix :cve_nist:`2024-13978`, :cve_nist:`2025-8176`, :cve_nist:`2025-8177`,
|
||||
:cve_nist:`2025-8534` and :cve_nist:`2025-8851`
|
||||
- vim: Fix :cve_nist:`2025-53905` and :cve_nist:`2025-53906`
|
||||
- wpa-supplicant: Fix :cve_nist:`2022-37660`
|
||||
- xserver-xorg: Fix :cve_nist:`2025-49175`, :cve_nist:`2025-49176`, :cve_nist:`2025-49177`,
|
||||
:cve_nist:`2025-49178`, :cve_nist:`2025-49179` and :cve_nist:`2025-49180`
|
||||
|
||||
|
||||
Fixes in Yocto-4.0.30
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- build-appliance-image: Update to kirkstone head revision
|
||||
- default-distrovars.inc: Fix CONNECTIVITY_CHECK_URIS redirect issue
|
||||
- dev-manual/security-subjects.rst: update mailing lists
|
||||
- gnupg: disable tests to avoid running target binaries at build time
|
||||
- go-helloworld: fix license
|
||||
- insane: Ensure that `src-uri-bad` fails correctly
|
||||
- insane: Improve patch warning/error handling
|
||||
- libubootenv: backport patch to fix unknown type name 'size_t'
|
||||
- llvm: fix typo in CVE-2024-0151.patch
|
||||
- migration-guides: add release notes for 4.0.29
|
||||
- overview-manual/yp-intro.rst: fix broken link to article
|
||||
- poky.conf: bump version for 4.0.30
|
||||
- pulseaudio: Add audio group explicitly
|
||||
- ref-manual/classes.rst: document the testexport class
|
||||
- ref-manual/system-requirements.rst: update supported distributions
|
||||
- ref-manual/variables.rst: document :term:`FIT_CONF_PREFIX` :term:`SPL_DTB_BINARY` variable
|
||||
- ref-manual/variables.rst: expand :term:`IMAGE_OVERHEAD_FACTOR` glossary entry
|
||||
- sdk: The main in the C example should return an int
|
||||
- sudo: remove devtool FIXME comment
|
||||
- systemd: Fix manpage build after :cve_nist:`2025-4598`
|
||||
- vim: not adjust script pathnames for native scripts either
|
||||
- vim: upgrade to 9.1.1652
|
||||
|
||||
|
||||
Known Issues in Yocto-4.0.30
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- N/A
|
||||
|
||||
Contributors to Yocto-4.0.30
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Antonin Godard
|
||||
- Archana Polampalli
|
||||
- Dan McGregor
|
||||
- Deepak Rathore
|
||||
- Divya Chellam
|
||||
- Erik Lindsten
|
||||
- Guocai He
|
||||
- Gyorgy Sarvari
|
||||
- Hitendra Prajapati
|
||||
- Jan Vermaete
|
||||
- Jiaying Song
|
||||
- Joao Marcos Costa
|
||||
- Kyungjik Min
|
||||
- Lee Chee Yang
|
||||
- Mingli Yu
|
||||
- Peter Marko
|
||||
- Philip Lorenz
|
||||
- Praveen Kumar
|
||||
- Quentin Schulz
|
||||
- Richard Purdie
|
||||
- Steve Sakoman
|
||||
- Vijay Anusuri
|
||||
- Yogita Urade
|
||||
- Youngseok Jeong
|
||||
|
||||
|
||||
Repositories / Downloads for Yocto-4.0.30
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
poky
|
||||
|
||||
- Repository Location: :yocto_git:`/poky`
|
||||
- Branch: :yocto_git:`kirkstone </poky/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.30 </poky/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :yocto_git:`51dc9c464de0703bfbc6f1ee71ac9bea20933a45 </poky/commit/?id=51dc9c464de0703bfbc6f1ee71ac9bea20933a45>`
|
||||
- Release Artefact: poky-51dc9c464de0703bfbc6f1ee71ac9bea20933a45
|
||||
- sha: 2b5db0a07598df7684975c0839e6f31515a8e78d366503feb9917ef1ca56c0b2
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.30/poky-51dc9c464de0703bfbc6f1ee71ac9bea20933a45.tar.bz2
|
||||
https://mirrors.kernel.org/yocto/yocto/yocto-4.0.30/poky-51dc9c464de0703bfbc6f1ee71ac9bea20933a45.tar.bz2
|
||||
|
||||
openembedded-core
|
||||
|
||||
- Repository Location: :oe_git:`/openembedded-core`
|
||||
- Branch: :oe_git:`kirkstone </openembedded-core/log/?h=kirkstone>`
|
||||
- Tag: :oe_git:`yocto-4.0.30 </openembedded-core/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :oe_git:`d381eeb5e70bd0ce9e78032c909e4a23564f4dd7 </openembedded-core/commit/?id=d381eeb5e70bd0ce9e78032c909e4a23564f4dd7>`
|
||||
- Release Artefact: oecore-d381eeb5e70bd0ce9e78032c909e4a23564f4dd7
|
||||
- sha: 022ab4ef5ac59ac3f01a9dacd8b1d6310cc117c6bed2e86e195ced88e0689c85
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.30/oecore-d381eeb5e70bd0ce9e78032c909e4a23564f4dd7.tar.bz2
|
||||
https://mirrors.kernel.org/yocto/yocto/yocto-4.0.30/oecore-d381eeb5e70bd0ce9e78032c909e4a23564f4dd7.tar.bz2
|
||||
|
||||
meta-mingw
|
||||
|
||||
- Repository Location: :yocto_git:`/meta-mingw`
|
||||
- Branch: :yocto_git:`kirkstone </meta-mingw/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.30 </meta-mingw/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :yocto_git:`87c22abb1f11be430caf4372e6b833dc7d77564e </meta-mingw/commit/?id=87c22abb1f11be430caf4372e6b833dc7d77564e>`
|
||||
- Release Artefact: meta-mingw-87c22abb1f11be430caf4372e6b833dc7d77564e
|
||||
- sha: f0bc4873e2e0319fb9d6d6ab9b98eb3f89664d4339a167d2db6a787dd12bc1a8
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.30/meta-mingw-87c22abb1f11be430caf4372e6b833dc7d77564e.tar.bz2
|
||||
https://mirrors.kernel.org/yocto/yocto/yocto-4.0.30/meta-mingw-87c22abb1f11be430caf4372e6b833dc7d77564e.tar.bz2
|
||||
|
||||
meta-gplv2
|
||||
|
||||
- Repository Location: :yocto_git:`/meta-gplv2`
|
||||
- Branch: :yocto_git:`kirkstone </meta-gplv2/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.30 </meta-gplv2/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :yocto_git:`d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a </meta-gplv2/commit/?id=d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a>`
|
||||
- Release Artefact: meta-gplv2-d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a
|
||||
- sha: c386f59f8a672747dc3d0be1d4234b6039273d0e57933eb87caa20f56b9cca6d
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.30/meta-gplv2-d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a.tar.bz2
|
||||
https://mirrors.kernel.org/yocto/yocto/yocto-4.0.30/meta-gplv2-d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a.tar.bz2
|
||||
|
||||
bitbake
|
||||
|
||||
- Repository Location: :oe_git:`/bitbake`
|
||||
- Branch: :oe_git:`2.0 </bitbake/log/?h=2.0>`
|
||||
- Tag: :oe_git:`yocto-4.0.30 </bitbake/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :oe_git:`8e2d1f8de055549b2101614d85454fcd1d0f94b2 </bitbake/commit/?id=8e2d1f8de055549b2101614d85454fcd1d0f94b2>`
|
||||
- Release Artefact: bitbake-8e2d1f8de055549b2101614d85454fcd1d0f94b2
|
||||
- sha: fad4e7699bae62082118e89785324b031b0af0743064caee87c91ba28549afb0
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.30/bitbake-8e2d1f8de055549b2101614d85454fcd1d0f94b2.tar.bz2
|
||||
https://mirrors.kernel.org/yocto/yocto/yocto-4.0.30/bitbake-8e2d1f8de055549b2101614d85454fcd1d0f94b2.tar.bz2
|
||||
|
||||
meta-yocto
|
||||
|
||||
- Repository Location: :yocto_git:`/meta-yocto`
|
||||
- Branch: :yocto_git:`kirkstone </meta-yocto/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.30 </meta-yocto/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :yocto_git:`edf7950e4d81dd31f29a58acdd8022dabd2be494 </meta-yocto/commit/?id=edf7950e4d81dd31f29a58acdd8022dabd2be494>`
|
||||
|
||||
yocto-docs
|
||||
|
||||
- Repository Location: :yocto_git:`/yocto-docs`
|
||||
- Branch: :yocto_git:`kirkstone </yocto-docs/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.30 </yocto-docs/log/?h=yocto-4.0.30>`
|
||||
- Git Revision: :yocto_git:`71a3933c609ce73ff07e5be48d9e7b03f22ef8d7 </yocto-docs/commit/?id=71a3933c609ce73ff07e5be48d9e7b03f22ef8d7>`
|
||||
|
||||
210
documentation/migration-guides/release-notes-4.0.31.rst
Normal file
210
documentation/migration-guides/release-notes-4.0.31.rst
Normal file
@@ -0,0 +1,210 @@
|
||||
Release notes for Yocto-4.0.31 (Kirkstone)
|
||||
------------------------------------------
|
||||
|
||||
Security Fixes in Yocto-4.0.31
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- binutils: Fix :cve_nist:`2025-8225`, :cve_nist:`2025-11081`, :cve_nist:`2025-11082` and
|
||||
:cve_nist:`2025-11083`
|
||||
- busybox: Fix :cve_nist:`2025-46394`
|
||||
- cmake: Fix :cve_nist:`2025-9301`
|
||||
- curl: Fix :cve_nist:`2025-9086`
|
||||
- ffmpeg: Ignore :cve_nist:`2023-6603`
|
||||
- ffmpeg: mark :cve_nist:`2023-6601` as Fixed
|
||||
- ghostscript: Fix :cve_nist:`2025-59798`, :cve_nist:`2025-59799` and :cve_nist:`2025-59800`
|
||||
- git: Fix :cve_nist:`2025-48386`
|
||||
- glib-networking: Fix :cve_nist:`2025-60018` and :cve_nist:`2025-60019`
|
||||
- go: Fix :cve_nist:`2025-47906` and :cve_nist:`2025-47907`
|
||||
- grub2: Fix :cve_nist:`2024-56738`
|
||||
- grub: Ignore :cve_nist:`2024-2312`
|
||||
- gstreamer1.0-plugins-bad: Fix :cve_nist:`2025-3887`
|
||||
- gstreamer1.0: Ignore :cve_nist:`2025-2759`, :cve_nist:`2025-3887`, :cve_nist:`2025-47183`,
|
||||
:cve_nist:`2025-47219`, :cve_nist:`2025-47806`, :cve_nist:`2025-47807` and :cve_nist:`2025-47808`
|
||||
- python3-jinja2: Fix :cve_nist:`2024-56201`, :cve_nist:`2024-56326` and :cve_nist:`2025-27516`
|
||||
- libxml2: Fix :cve_nist:`2025-9714`
|
||||
- libxslt: Fix :cve_nist:`2025-7424`
|
||||
- lz4: Fix :cve_nist:`2025-62813`
|
||||
- openssl: Fix :cve_nist:`2025-9230` and :cve_nist:`2025-9232`
|
||||
- pulseaudio: Ignore :cve_nist:`2024-11586`
|
||||
- python3: Fix :cve_nist:`2024-6345`, :cve_nist:`2025-47273` and :cve_nist:`2025-59375`
|
||||
- qemu: Fix :cve_nist:`2024-8354`
|
||||
- tiff: Fix :cve_nist:`2025-8961`, :cve_nist:`2025-9165` and :cve_nist:`2025-9900`
|
||||
- vim: Fix :cve_nist:`2025-9389`
|
||||
|
||||
|
||||
Fixes in Yocto-4.0.31
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- build-appliance-image: Update to kirkstone head revision
|
||||
- poky.conf: bump version for 4.0.31
|
||||
- ref-manual/classes.rst: document the relative_symlinks class
|
||||
- ref-manual/classes.rst: gettext: extend the documentation of the class
|
||||
- ref-manual/variables.rst: document the CCACHE_DISABLE, UNINATIVE_CHECKSUM, UNINATIVE_URL, USE_NLS,
|
||||
REQUIRED_COMBINED_FEATURES, REQUIRED_IMAGE_FEATURES, :term:`REQUIRED_MACHINE_FEATURES` variable
|
||||
- ref-manual/variables.rst: fix :term:`LAYERDEPENDS` description
|
||||
- dev-manual, test-manual: Update autobuilder output links
|
||||
- ref-manual/classes.rst: extend the uninative class documentation
|
||||
- python3: upgrade to 3.10.19
|
||||
- linux-yocto/5.15: update to v5.15.194
|
||||
- glibc: : PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions (bug 32786)
|
||||
- glibc: nptl Use all of g1_start and g_signals
|
||||
- glibc: nptl rename __condvar_quiesce_and_switch_g1
|
||||
- glibc: nptl Fix indentation
|
||||
- glibc: nptl Use a single loop in pthread_cond_wait instaed of a nested loop
|
||||
- glibc: Remove g_refs from condition variables
|
||||
- glibc: nptl Remove unnecessary quadruple check in pthread_cond_wait
|
||||
- glibc: nptl Remove unnecessary catch-all-wake in condvar group switch
|
||||
- glibc: nptl Update comments and indentation for new condvar implementation
|
||||
- glibc: pthreads NPTL lost wakeup fix 2
|
||||
- glibc: Remove partial BZ#25847 backport patches
|
||||
- vulnerabilities: update nvdcve file name
|
||||
- migration-guides: add release notes for 4.0.30
|
||||
- oeqa/sdk/cases/buildcpio.py: use gnu mirror instead of main server
|
||||
- selftest/cases/meta_ide.py: use use gnu mirror instead of main server
|
||||
- conf/bitbake.conf: use gnu mirror instead of main server
|
||||
- p11-kit: backport fix for handle :term:`USE_NLS` from master
|
||||
- systemd: backport fix for handle :term:`USE_NLS` from master
|
||||
- glibc: stable 2.35 branch updates
|
||||
- openssl: upgrade to 3.0.18
|
||||
- scripts/install-buildtools: Update to 4.0.30
|
||||
- ref-manual/variables.rst: fix the description of :term:`STAGING_DIR`
|
||||
- ref-manual/structure: document the auto.conf file
|
||||
- dev-manual/building.rst: add note about externalsrc variables absolute paths
|
||||
- ref-manual/variables.rst: fix the description of :term:`KBUILD_DEFCONFIG`
|
||||
- kernel-dev/common.rst: fix the in-tree defconfig description
|
||||
- test-manual/yocto-project-compatible.rst: fix a typo
|
||||
- contributor-guide: submit-changes: make "Crediting contributors" part of "Commit your changes"
|
||||
- contributor-guide: submit-changes: number instruction list in commit your changes
|
||||
- contributor-guide: submit-changes: reword commit message instructions
|
||||
- contributor-guide: submit-changes: make the Cc tag follow kernel guidelines
|
||||
- contributor-guide: submit-changes: align :term:`CC` tag description
|
||||
- contributor-guide: submit-changes: clarify example with Yocto bug ID
|
||||
- contributor-guide: submit-changes: fix improper bold string
|
||||
- libhandy: update git branch name
|
||||
- python3-jinja2: upgrade to 3.1.6
|
||||
- vim: upgrade to 9.1.1683
|
||||
|
||||
|
||||
Known Issues in Yocto-4.0.31
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- N/A
|
||||
|
||||
|
||||
Contributors to Yocto-4.0.31
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Adam Blank
|
||||
- Aleksandar Nikolic
|
||||
- Antonin Godard
|
||||
- Archana Polampalli
|
||||
- AshishKumar Mishra
|
||||
- Bruce Ashfield
|
||||
- Deepesh Varatharajan
|
||||
- Divya Chellam
|
||||
- Gyorgy Sarvari
|
||||
- Hitendra Prajapati
|
||||
- João Marcos Costa
|
||||
- Lee Chee Yang
|
||||
- Paul Barker
|
||||
- Peter Marko
|
||||
- Praveen Kumar
|
||||
- Quentin Schulz
|
||||
- Rajeshkumar Ramasamy
|
||||
- Saravanan
|
||||
- Soumya Sambu
|
||||
- Steve Sakoman
|
||||
- Sunil Dora
|
||||
- Talel BELHAJ SALEM
|
||||
- Theo GAIGE
|
||||
- Vijay Anusuri
|
||||
- Yash Shinde
|
||||
- Yogita Urade
|
||||
|
||||
Repositories / Downloads for Yocto-4.0.31
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
yocto-docs
|
||||
|
||||
- Repository Location: :yocto_git:`/yocto-docs`
|
||||
- Branch: :yocto_git:`kirkstone </yocto-docs/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.31 </yocto-docs/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :yocto_git:`073f3bca4c374b03398317e7f445d2440a287741 </yocto-docs/commit/?id=073f3bca4c374b03398317e7f445d2440a287741>`
|
||||
- Release Artefact: yocto-docs-073f3bca4c374b03398317e7f445d2440a287741
|
||||
- sha: 3bfde9b6ad310dd42817509b67f61cd69552f74b2bc5011bd20788fe96d6823b
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/yocto-docs-073f3bca4c374b03398317e7f445d2440a287741.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/yocto-docs-073f3bca4c374b03398317e7f445d2440a287741.tar.bz2
|
||||
|
||||
poky
|
||||
|
||||
- Repository Location: :yocto_git:`/poky`
|
||||
- Branch: :yocto_git:`kirkstone </poky/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.31 </poky/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :yocto_git:`04b39e5b7eb19498215d85c88a5fffb460fea1eb </poky/commit/?id=04b39e5b7eb19498215d85c88a5fffb460fea1eb>`
|
||||
- Release Artefact: poky-04b39e5b7eb19498215d85c88a5fffb460fea1eb
|
||||
- sha: 0ca18ab1ed25c0d77412ba30dbb03d74811756c7c2fe2401940f848a5e734930
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/poky-04b39e5b7eb19498215d85c88a5fffb460fea1eb.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/poky-04b39e5b7eb19498215d85c88a5fffb460fea1eb.tar.bz2
|
||||
|
||||
openembedded-core
|
||||
|
||||
- Repository Location: :oe_git:`/openembedded-core`
|
||||
- Branch: :oe_git:`kirkstone </openembedded-core/log/?h=kirkstone>`
|
||||
- Tag: :oe_git:`yocto-4.0.31 </openembedded-core/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :oe_git:`99204008786f659ab03538cd2ae2fd23ed4164c5 </openembedded-core/commit/?id=99204008786f659ab03538cd2ae2fd23ed4164c5>`
|
||||
- Release Artefact: oecore-99204008786f659ab03538cd2ae2fd23ed4164c5
|
||||
- sha: aa97bf826ad217b3a5278b4ad60bef4d194f0f1ff617677cf2323d3cc4897687
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/oecore-99204008786f659ab03538cd2ae2fd23ed4164c5.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/oecore-99204008786f659ab03538cd2ae2fd23ed4164c5.tar.bz2
|
||||
|
||||
meta-yocto
|
||||
|
||||
- Repository Location: :yocto_git:`/meta-yocto`
|
||||
- Branch: :yocto_git:`kirkstone </meta-yocto/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.31 </meta-yocto/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :yocto_git:`3b2df00345b46479237fe0218675a818249f891c </meta-yocto/commit/?id=3b2df00345b46479237fe0218675a818249f891c>`
|
||||
- Release Artefact: meta-yocto-3b2df00345b46479237fe0218675a818249f891c
|
||||
- sha: 630e99e0f515bab8a316b2e32aff1352b4404f15aa087e8821b84093596a08ce
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/meta-yocto-3b2df00345b46479237fe0218675a818249f891c.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/meta-yocto-3b2df00345b46479237fe0218675a818249f891c.tar.bz2
|
||||
|
||||
meta-mingw
|
||||
|
||||
- Repository Location: :yocto_git:`/meta-mingw`
|
||||
- Branch: :yocto_git:`kirkstone </meta-mingw/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.31 </meta-mingw/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :yocto_git:`87c22abb1f11be430caf4372e6b833dc7d77564e </meta-mingw/commit/?id=87c22abb1f11be430caf4372e6b833dc7d77564e>`
|
||||
- Release Artefact: meta-mingw-87c22abb1f11be430caf4372e6b833dc7d77564e
|
||||
- sha: f0bc4873e2e0319fb9d6d6ab9b98eb3f89664d4339a167d2db6a787dd12bc1a8
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/meta-mingw-87c22abb1f11be430caf4372e6b833dc7d77564e.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/meta-mingw-87c22abb1f11be430caf4372e6b833dc7d77564e.tar.bz2
|
||||
|
||||
meta-gplv2
|
||||
|
||||
- Repository Location: :yocto_git:`/meta-gplv2`
|
||||
- Branch: :yocto_git:`kirkstone </meta-gplv2/log/?h=kirkstone>`
|
||||
- Tag: :yocto_git:`yocto-4.0.31 </meta-gplv2/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :yocto_git:`d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a </meta-gplv2/commit/?id=d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a>`
|
||||
- Release Artefact: meta-gplv2-d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a
|
||||
- sha: c386f59f8a672747dc3d0be1d4234b6039273d0e57933eb87caa20f56b9cca6d
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/meta-gplv2-d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/meta-gplv2-d2f8b5cdb285b72a4ed93450f6703ca27aa42e8a.tar.bz2
|
||||
|
||||
bitbake
|
||||
|
||||
- Repository Location: :oe_git:`/bitbake`
|
||||
- Branch: :oe_git:`2.0 </bitbake/log/?h=2.0>`
|
||||
- Tag: :oe_git:`yocto-4.0.31 </bitbake/log/?h=yocto-4.0.31>`
|
||||
- Git Revision: :oe_git:`8e2d1f8de055549b2101614d85454fcd1d0f94b2 </bitbake/commit/?id=8e2d1f8de055549b2101614d85454fcd1d0f94b2>`
|
||||
- Release Artefact: bitbake-8e2d1f8de055549b2101614d85454fcd1d0f94b2
|
||||
- sha: fad4e7699bae62082118e89785324b031b0af0743064caee87c91ba28549afb0
|
||||
- Download Locations:
|
||||
https://downloads.yoctoproject.org/releases/yocto/yocto-4.0.31/bitbake-8e2d1f8de055549b2101614d85454fcd1d0f94b2.tar.bz2
|
||||
https://mirrors.edge.kernel.org/yocto/yocto/yocto-4.0.31/bitbake-8e2d1f8de055549b2101614d85454fcd1d0f94b2.tar.bz2
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
172
documentation/overview-manual/svg/key-dev-elements.svg
Normal file
172
documentation/overview-manual/svg/key-dev-elements.svg
Normal file
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="164.765mm"
|
||||
height="72.988113mm"
|
||||
viewBox="0 0 164.765 72.988114"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="key-dev-elements.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="341.5"
|
||||
inkscape:cy="-31.5"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1440"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer2"
|
||||
showborder="false"
|
||||
borderlayer="false"
|
||||
inkscape:antialias-rendering="true"
|
||||
showguides="true" /><defs
|
||||
id="defs1" /><g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer "
|
||||
style="display:inline"
|
||||
transform="translate(-20.664242,-129.6793)"><rect
|
||||
style="display:inline;fill:#f1e9cc;fill-opacity:1;stroke:#6d8eb4;stroke-width:0.653;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
id="rect1"
|
||||
width="164.112"
|
||||
height="54.273098"
|
||||
x="20.990742"
|
||||
y="130.0058"
|
||||
ry="0"
|
||||
inkscape:label="yp-rect" /><rect
|
||||
style="display:inline;fill:#f3d770;fill-opacity:1;stroke:#6d8eb4;stroke-width:0.653;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
id="rect2"
|
||||
width="101.45864"
|
||||
height="41.151588"
|
||||
x="28.1292"
|
||||
y="137.10953"
|
||||
inkscape:label="poky-rect" /><rect
|
||||
style="display:inline;fill:#c0ebf5;fill-opacity:1;stroke:#6d8eb4;stroke-width:0.653;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
id="rect3"
|
||||
width="50.652737"
|
||||
height="53.04562"
|
||||
x="35.516178"
|
||||
y="149.29529"
|
||||
inkscape:label="oe-rect" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;white-space:pre;inline-size:46.7487;display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
x="136.38763"
|
||||
y="137.69727"
|
||||
id="text3"
|
||||
inkscape:label="poky-title"
|
||||
transform="matrix(0.90889596,0,0,0.81399719,-26.072941,39.399474)"><tspan
|
||||
x="136.38763"
|
||||
y="137.69727"
|
||||
id="tspan2">Poky</tspan></text><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;white-space:pre;inline-size:46.7487;display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
x="136.38763"
|
||||
y="137.69727"
|
||||
id="text3-8"
|
||||
inkscape:label="oe-title"
|
||||
transform="matrix(0.90889596,0,0,0.81399719,-78.327995,83.175189)"><tspan
|
||||
x="136.38763"
|
||||
y="137.69727"
|
||||
id="tspan4">OpenEmbedded</tspan></text><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;white-space:pre;inline-size:46.7487;display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
x="136.38763"
|
||||
y="137.69727"
|
||||
id="text3-0"
|
||||
inkscape:label="yp-title"
|
||||
transform="matrix(0.8469291,0,0,0.81399719,21.497595,28.033837)"><tspan
|
||||
x="136.38763"
|
||||
y="137.69727"
|
||||
id="tspan5">YOCTO PROJECT (YP)</tspan></text><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.98347px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
x="137.19444"
|
||||
y="150.50006"
|
||||
id="text4"
|
||||
transform="scale(1.0050579,0.9949676)"
|
||||
inkscape:label="yp-text"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.98347px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="137.19444"
|
||||
y="150.50006">Umbrella Open Source Project</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.98347px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="137.19444"
|
||||
y="154.2294"
|
||||
id="tspan6">that Builds and Maintains</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.98347px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="137.19444"
|
||||
y="157.95874"
|
||||
id="tspan7">Validated Open Source Tools and</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.98347px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="137.19444"
|
||||
y="161.68808"
|
||||
id="tspan8">Components Associated with</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.98347px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="137.19444"
|
||||
y="165.4174"
|
||||
id="tspan9">Embedded Linux</tspan></text><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.97078px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
x="90.582634"
|
||||
y="159.10139"
|
||||
id="text10"
|
||||
transform="scale(1.0018079,0.9981954)"
|
||||
inkscape:label="poky-text"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan10"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.97078px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="90.582634"
|
||||
y="159.10139">Yocto Project Open</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.97078px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="90.582634"
|
||||
y="162.81487"
|
||||
id="tspan11">Source Reference</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.97078px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="90.582634"
|
||||
y="166.52835"
|
||||
id="tspan12">Embedded Distribution</tspan></text><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.01677px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:7.4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
x="40.36692"
|
||||
y="160.98824"
|
||||
id="text13"
|
||||
transform="scale(0.99784993,1.0021547)"
|
||||
inkscape:label="oe-text"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan13"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.01677px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="40.36692"
|
||||
y="160.98824">Open Source Build Engine</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.01677px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="40.36692"
|
||||
y="164.7592"
|
||||
id="tspan14">and YP-Compatible Metadata</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.01677px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0"
|
||||
x="40.36692"
|
||||
y="168.53017"
|
||||
id="tspan15">for Embedded Linux</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -23,8 +23,8 @@ comes to delivering embedded software stacks. The project allows
|
||||
software customizations and build interchange for multiple hardware
|
||||
platforms as well as software stacks that can be maintained and scaled.
|
||||
|
||||
.. image:: figures/key-dev-elements.png
|
||||
:align: center
|
||||
.. image:: svg/key-dev-elements.*
|
||||
:width: 100%
|
||||
|
||||
For further introductory information on the Yocto Project, you might be
|
||||
interested in this
|
||||
|
||||
@@ -309,8 +309,12 @@ file for details about how to enable this mechanism in your configuration
|
||||
file, how to disable it for specific recipes, and how to share ``ccache``
|
||||
files between builds.
|
||||
|
||||
However, using the class can lead to unexpected side-effects. Thus, using
|
||||
this class is not recommended.
|
||||
Recipes can also explicitly disable `Ccache` support even when the
|
||||
:ref:`ref-classes-ccache` class is enabled, by setting the
|
||||
:term:`CCACHE_DISABLE` variable to "1".
|
||||
|
||||
Using the :ref:`ref-classes-ccache` class can lead to unexpected side-effects.
|
||||
Using this class is not recommended.
|
||||
|
||||
.. _ref-classes-chrpath:
|
||||
|
||||
@@ -825,6 +829,14 @@ software that uses the GNU ``gettext`` internationalization and localization
|
||||
system. All recipes building software that use ``gettext`` should inherit this
|
||||
class.
|
||||
|
||||
This class will configure recipes to build translations *unless*:
|
||||
|
||||
- the :term:`USE_NLS` variable is set to ``no``, or
|
||||
|
||||
- the :term:`INHIBIT_DEFAULT_DEPS` variable is set and the recipe inheriting
|
||||
the :ref:`ref-classes-gettext` class does not also inherit the
|
||||
:ref:`ref-classes-cross-canadian` class.
|
||||
|
||||
.. _ref-classes-gnomebase:
|
||||
|
||||
``gnomebase``
|
||||
@@ -2544,6 +2556,25 @@ The :ref:`ref-classes-recipe_sanity` class checks for the presence of any host s
|
||||
recipe prerequisites that might affect the build (e.g. variables that
|
||||
are set or software that is present).
|
||||
|
||||
.. _ref-classes-relative_symlinks:
|
||||
|
||||
``relative_symlinks``
|
||||
=====================
|
||||
|
||||
The :ref:`ref-classes-relative_symlinks` class walks the symbolic links in the
|
||||
:term:`D` directory and replaces links pointing to absolute paths to relative
|
||||
paths. This is occasionally used in some recipes that create wrong symbolic
|
||||
links when their :ref:`ref-classes-native` version is built, and/or would cause
|
||||
breakage in the :ref:`overview-manual/concepts:shared state cache`.
|
||||
|
||||
For example, if the following symbolic link is found in :term:`D`::
|
||||
|
||||
/usr/bin/foo -> /sbin/bar
|
||||
|
||||
It is replaced by::
|
||||
|
||||
/usr/bin/foo -> ../../sbin/bar
|
||||
|
||||
.. _ref-classes-relocatable:
|
||||
|
||||
``relocatable``
|
||||
@@ -3214,22 +3245,51 @@ imitates.
|
||||
``uninative``
|
||||
=============
|
||||
|
||||
Attempts to isolate the build system from the host distribution's C
|
||||
library in order to make re-use of native shared state artifacts across
|
||||
different host distributions practical. With this class enabled, a
|
||||
tarball containing a pre-built C library is downloaded at the start of
|
||||
the build. In the Poky reference distribution this is enabled by default
|
||||
through ``meta/conf/distro/include/yocto-uninative.inc``. Other
|
||||
distributions that do not derive from poky can also
|
||||
"``require conf/distro/include/yocto-uninative.inc``" to use this.
|
||||
Alternatively if you prefer, you can build the uninative-tarball recipe
|
||||
yourself, publish the resulting tarball (e.g. via HTTP) and set
|
||||
``UNINATIVE_URL`` and ``UNINATIVE_CHECKSUM`` appropriately. For an
|
||||
example, see the ``meta/conf/distro/include/yocto-uninative.inc``.
|
||||
The :ref:`ref-classes-uninative` class allows binaries to run on systems with
|
||||
older or newer :wikipedia:`Glibc <Glibc>` versions. This means
|
||||
:ref:`ref-classes-native` recipe :ref:`overview-manual/concepts:shared state
|
||||
cache` can be shared among different host distributions of different versions,
|
||||
i.e. the :ref:`overview-manual/concepts:shared state cache` is "universal".
|
||||
|
||||
The :ref:`ref-classes-uninative` class is also used unconditionally by the extensible
|
||||
SDK. When building the extensible SDK, ``uninative-tarball`` is built
|
||||
and the resulting tarball is included within the SDK.
|
||||
To allow this to work, the dynamic loader is changed to our own :manpage:`ld.so
|
||||
<ld.so.8>` when binaries are compiled using the
|
||||
``--dynamic-linker`` option. This means when the binary is executed, it finds
|
||||
our own :manpage:`ld.so <ld.so.8>` and that loader has a modified search path
|
||||
which finds a newer Glibc version.
|
||||
|
||||
The linking of the binaries is not changed at link time since the
|
||||
headers on the system wouldn't match the newer Glibc and this causes
|
||||
obtuse failures. Changing the loader is effectively the same as if the
|
||||
system had a Glibc upgrade after the binary was compiled, so it is a
|
||||
mechanism supported by upstream.
|
||||
|
||||
One caveat to this approach is that the uninative Glibc binary must be
|
||||
equal to or newer in version to the versions on all the systems using
|
||||
the common :ref:`overview-manual/concepts:shared state cache`. This is why
|
||||
:ref:`ref-classes-uninative` is regularly changed on the development and stable
|
||||
branches.
|
||||
|
||||
Another potential issue is static linking: static libraries created on
|
||||
a system with a new Glibc version may have symbols not present in older
|
||||
versions, which would then fail during linking on older systems. This
|
||||
is one reason we don't use static linking for our :ref:`ref-classes-native`
|
||||
binaries.
|
||||
|
||||
With this class enabled, a tarball containing a pre-built C library is
|
||||
downloaded at the start of the build. In the Poky reference distribution this is
|
||||
enabled by default through :oe_git:`meta/conf/distro/include/yocto-uninative.inc
|
||||
</openembedded-core/tree/meta/conf/distro/include/yocto-uninative.inc>`. Other distributions that do
|
||||
not derive from Poky can also "``require conf/distro/include/yocto-uninative.inc``"
|
||||
to use this. Alternatively if you prefer, you can build the uninative-tarball
|
||||
recipe yourself, publish the resulting tarball (e.g. via HTTP) and set
|
||||
:term:`UNINATIVE_URL` and :term:`UNINATIVE_CHECKSUM` appropriately. For an
|
||||
example, see :oe_git:`meta/conf/distro/include/yocto-uninative.inc
|
||||
</openembedded-core/tree/meta/conf/distro/include/yocto-uninative.inc>`.
|
||||
|
||||
The :ref:`ref-classes-uninative` class is also used unconditionally by the
|
||||
:doc:`extensible SDK </sdk-manual/extensible>`. When building the extensible
|
||||
SDK, ``uninative-tarball`` is built and the resulting tarball is included within
|
||||
the SDK.
|
||||
|
||||
.. _ref-classes-update-alternatives:
|
||||
|
||||
|
||||
@@ -62,7 +62,8 @@ codename are likely to be compatible and thus work together.
|
||||
|
||||
Releases are given a nominal release version as well but the codename is
|
||||
used in repositories for this reason. You can find information on Yocto
|
||||
Project releases and codenames at :yocto_wiki:`/Releases`.
|
||||
Project releases and codenames in the :yocto_home:`Releases page
|
||||
</development/releases/>`.
|
||||
|
||||
Our :doc:`/migration-guides/index` detail how to migrate from one release of
|
||||
the Yocto Project to the next.
|
||||
|
||||
@@ -328,6 +328,15 @@ Once the build process gets the sample file, it uses ``sed`` to substitute final
|
||||
This file indicates the state of the sanity checks and is created during
|
||||
the build.
|
||||
|
||||
.. _structure-build-conf-auto.conf:
|
||||
|
||||
``build/conf/auto.conf``
|
||||
------------------------
|
||||
|
||||
This file contains configuration variables that are automatically modified by
|
||||
tools such as :oe_git:`bitbake-config-build </bitbake/tree/bin/bitbake-config-build>`.
|
||||
This file should not be modified manually.
|
||||
|
||||
.. _structure-build-downloads:
|
||||
|
||||
``build/downloads/``
|
||||
|
||||
@@ -1097,6 +1097,11 @@ system and gives an overview of their function and contents.
|
||||
:term:`CC`
|
||||
The minimal command and arguments used to run the C compiler.
|
||||
|
||||
:term:`CCACHE_DISABLE`
|
||||
When inheriting the :ref:`ref-classes-ccache` class, the
|
||||
:term:`CCACHE_DISABLE` variable can be set to "1" in a recipe to disable
|
||||
`Ccache` support. This is useful when the recipe is known to not support it.
|
||||
|
||||
:term:`CFLAGS`
|
||||
Specifies the flags to pass to the C compiler. This variable is
|
||||
exported to an environment variable and thus made visible to the
|
||||
@@ -4251,8 +4256,7 @@ system and gives an overview of their function and contents.
|
||||
would place patch files and configuration fragment files (i.e.
|
||||
"out-of-tree"). However, if you want to use a ``defconfig`` file that
|
||||
is part of the kernel tree (i.e. "in-tree"), you can use the
|
||||
:term:`KBUILD_DEFCONFIG` variable and append the
|
||||
:term:`KMACHINE` variable to point to the
|
||||
:term:`KBUILD_DEFCONFIG` variable to point to the
|
||||
``defconfig`` file.
|
||||
|
||||
To use the variable, set it in the append file for your kernel recipe
|
||||
@@ -4688,7 +4692,7 @@ system and gives an overview of their function and contents.
|
||||
information on how this variable is used.
|
||||
|
||||
:term:`LAYERDEPENDS`
|
||||
Lists the layers, separated by spaces, on which this recipe depends.
|
||||
Lists the layers, separated by spaces, on which this layer depends.
|
||||
Optionally, you can specify a specific layer version for a dependency
|
||||
by adding it to the end of the layer name. Here is an example::
|
||||
|
||||
@@ -5545,8 +5549,8 @@ system and gives an overview of their function and contents.
|
||||
|
||||
.. note::
|
||||
|
||||
An easy way to see what overrides apply is to search for :term:`OVERRIDES`
|
||||
in the output of the ``bitbake -e`` command. See the
|
||||
An easy way to see what overrides apply is to run the command
|
||||
``bitbake-getvar -r myrecipe OVERRIDES``. See the
|
||||
":ref:`dev-manual/debugging:viewing variable values`" section in the Yocto
|
||||
Project Development Tasks Manual for more information.
|
||||
|
||||
@@ -6822,6 +6826,16 @@ system and gives an overview of their function and contents.
|
||||
:term:`REPODIR`
|
||||
See :term:`bitbake:REPODIR` in the BitBake manual.
|
||||
|
||||
:term:`REQUIRED_COMBINED_FEATURES`
|
||||
When inheriting the :ref:`ref-classes-features_check` class, this variable
|
||||
identifies combined features (the intersection of :term:`MACHINE_FEATURES`
|
||||
and :term:`DISTRO_FEATURES`) that must exist in the current configuration
|
||||
in order for the :term:`OpenEmbedded Build System` to build the recipe. In
|
||||
other words, if the :term:`REQUIRED_COMBINED_FEATURES` variable lists a
|
||||
feature that does not appear in :term:`COMBINED_FEATURES` within the
|
||||
current configuration, then the recipe will be skipped, and if the build
|
||||
system attempts to build the recipe then an error will be triggered.
|
||||
|
||||
:term:`REQUIRED_DISTRO_FEATURES`
|
||||
When inheriting the
|
||||
:ref:`features_check <ref-classes-features_check>`
|
||||
@@ -6833,6 +6847,32 @@ system and gives an overview of their function and contents.
|
||||
the recipe will be skipped, and if the build system attempts to build
|
||||
the recipe then an error will be triggered.
|
||||
|
||||
:term:`REQUIRED_IMAGE_FEATURES`
|
||||
When inheriting the :ref:`ref-classes-features_check` class, this variable
|
||||
identifies image features that must exist in the current
|
||||
configuration in order for the :term:`OpenEmbedded Build System` to build
|
||||
the recipe. In other words, if the :term:`REQUIRED_IMAGE_FEATURES` variable
|
||||
lists a feature that does not appear in :term:`IMAGE_FEATURES` within the
|
||||
current configuration, then the recipe will be skipped, and if the build
|
||||
system attempts to build the recipe then an error will be triggered.
|
||||
|
||||
Compared to other ``REQUIRED_*_FEATURES`` variables, the
|
||||
:term:`REQUIRED_IMAGE_FEATURES` varible only targets image recipes, as the
|
||||
:term:`IMAGE_FEATURES` variable is handled by the :ref:`ref-classes-core-image`
|
||||
class). However, the :term:`REQUIRED_IMAGE_FEATURES` varible can also be
|
||||
set from a :term:`Configuration File`, such as a distro
|
||||
configuration file, if the list of required image features should apply to
|
||||
all images using this :term:`DISTRO`.
|
||||
|
||||
:term:`REQUIRED_MACHINE_FEATURES`
|
||||
When inheriting the :ref:`ref-classes-features_check` class, this variable
|
||||
identifies :term:`MACHINE_FEATURES` that must exist in the current
|
||||
configuration in order for the :term:`OpenEmbedded Build System` to build
|
||||
the recipe. In other words, if the :term:`REQUIRED_MACHINE_FEATURES` variable
|
||||
lists a feature that does not appear in :term:`MACHINE_FEATURES` within the
|
||||
current configuration, then the recipe will be skipped, and if the build
|
||||
system attempts to build the recipe then an error will be triggered.
|
||||
|
||||
:term:`REQUIRED_VERSION`
|
||||
If there are multiple versions of a recipe available, this variable
|
||||
determines which version should be given preference.
|
||||
@@ -8174,7 +8214,7 @@ system and gives an overview of their function and contents.
|
||||
directory for the build host.
|
||||
|
||||
:term:`STAGING_DIR`
|
||||
Helps construct the ``recipe-sysroots`` directory, which is used
|
||||
Helps construct the ``recipe-sysroot*`` directories, which are used
|
||||
during packaging.
|
||||
|
||||
For information on how staging for recipe-specific sysroots occurs,
|
||||
@@ -9422,6 +9462,22 @@ system and gives an overview of their function and contents.
|
||||
passes and uses "all" for the target during the U-Boot building
|
||||
process.
|
||||
|
||||
:term:`UNINATIVE_CHECKSUM`
|
||||
When inheriting the :ref:`ref-classes-uninative` class, the
|
||||
:term:`UNINATIVE_CHECKSUM` variable flags contain the checksums of the
|
||||
uninative tarball as specified by the :term:`UNINATIVE_URL` variable.
|
||||
There should be one checksum per tarballs published at
|
||||
:term:`UNINATIVE_URL`, which match architectures. For example::
|
||||
|
||||
UNINATIVE_CHECKSUM[aarch64] ?= "812045d826b7fda88944055e8526b95a5a9440bfef608d5b53fd52faab49bf85"
|
||||
UNINATIVE_CHECKSUM[i686] ?= "5cc28efd0c15a75de4bcb147c6cce65f1c1c9d442173a220f08427f40a3ffa09"
|
||||
UNINATIVE_CHECKSUM[x86_64] ?= "4c03d1ed2b7b4e823aca4a1a23d8f2e322f1770fc10e859adcede5777aff4f3a"
|
||||
|
||||
:term:`UNINATIVE_URL`
|
||||
When inheriting the :ref:`ref-classes-uninative` class, the
|
||||
:term:`UNINATIVE_URL` variable contains the URL where the uninative
|
||||
tarballs are published.
|
||||
|
||||
:term:`UNKNOWN_CONFIGURE_OPT_IGNORE`
|
||||
Specifies a list of options that, if reported by the configure script
|
||||
as being invalid, should not generate a warning during the
|
||||
@@ -9517,6 +9573,18 @@ system and gives an overview of their function and contents.
|
||||
the Yocto Project Development Tasks Manual for information on how to
|
||||
use this variable.
|
||||
|
||||
:term:`USE_NLS`
|
||||
Determine if language translations should be built for recipes that can
|
||||
build them. This variable can be equal to:
|
||||
|
||||
- ``yes``: translations are enabled.
|
||||
- ``no``: translation are disabled.
|
||||
|
||||
Recipes can use the value of this variable to enable language
|
||||
translations in their build. Classes such as :ref:`ref-classes-gettext`
|
||||
use the value of this variable to enable :wikipedia:`Gettext <Gettext>`
|
||||
support.
|
||||
|
||||
:term:`USE_VT`
|
||||
When using
|
||||
:ref:`SysVinit <dev-manual/new-recipe:enabling system services>`,
|
||||
|
||||
@@ -113,7 +113,7 @@ If ``OEQA_DEBUGGING_SAVED_OUTPUT`` is set, any differing packages will be saved
|
||||
here. The test is also able to run the ``diffoscope`` command on the output to
|
||||
generate HTML files showing the differences between the packages, to aid
|
||||
debugging. On the Autobuilder, these appear under
|
||||
https://autobuilder.yocto.io/pub/repro-fail/ in the form ``oe-reproducible +
|
||||
https://valkyrie.yocto.io/pub/repro-fail/ in the form ``oe-reproducible +
|
||||
<date> + <random ID>``, e.g. ``oe-reproducible-20200202-1lm8o1th``.
|
||||
|
||||
The project's current reproducibility status can be seen at
|
||||
|
||||
@@ -69,7 +69,7 @@ box to "generate an email to QA" is also checked.
|
||||
When the build completes, an email is sent out using the ``send-qa-email``
|
||||
script in the :yocto_git:`yocto-autobuilder-helper </yocto-autobuilder-helper>`
|
||||
repository to the list of people configured for that release. Release builds
|
||||
are placed into a directory in https://autobuilder.yocto.io/pub/releases on the
|
||||
are placed into a directory in https://valkyrie.yocto.io/pub/releases on the
|
||||
Autobuilder which is included in the email. The process from here is
|
||||
more manual and control is effectively passed to release engineering.
|
||||
The next steps include:
|
||||
|
||||
@@ -38,7 +38,7 @@ Benefits
|
||||
and flexible: it gives users the ultimate power to change pretty much any
|
||||
aspect of the system but as with most things, power comes with responsibility.
|
||||
The Yocto Project would like to see people able to mix and match BSPs with
|
||||
distro configs or software stacks and be able to merge succesfully.
|
||||
distro configs or software stacks and be able to merge successfully.
|
||||
Over time, the project identified characteristics in layers that allow them
|
||||
to operate well together. "anti-patterns" were also found, preventing layers
|
||||
from working well together.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
DISTRO = "poky"
|
||||
DISTRO_NAME = "Poky (Yocto Project Reference Distro)"
|
||||
#DISTRO_VERSION = "3.4+snapshot-${METADATA_REVISION}"
|
||||
DISTRO_VERSION = "4.0.30"
|
||||
DISTRO_VERSION = "4.0.32"
|
||||
DISTRO_CODENAME = "kirkstone"
|
||||
SDK_VENDOR = "-pokysdk"
|
||||
SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${METADATA_REVISION}', 'snapshot')}"
|
||||
|
||||
@@ -18,6 +18,9 @@ TARGET_GOMIPS = "${@go_map_mips(d.getVar('TARGET_ARCH'), d.getVar('TUNE_FEATURES
|
||||
TARGET_GOARM:class-native = "7"
|
||||
TARGET_GO386:class-native = "sse2"
|
||||
TARGET_GOMIPS:class-native = "hardfloat"
|
||||
TARGET_GOARM:class-crosssdk = "7"
|
||||
TARGET_GO386:class-crosssdk = "sse2"
|
||||
TARGET_GOMIPS:class-crosssdk = "hardfloat"
|
||||
TARGET_GOTUPLE = "${TARGET_GOOS}_${TARGET_GOARCH}"
|
||||
GO_BUILD_BINDIR = "${@['bin/${HOST_GOTUPLE}','bin'][d.getVar('BUILD_GOTUPLE') == d.getVar('HOST_GOTUPLE')]}"
|
||||
|
||||
|
||||
@@ -690,7 +690,7 @@ DEBIAN_MIRROR = "http://ftp.debian.org/debian/pool"
|
||||
GENTOO_MIRROR = "http://distfiles.gentoo.org/distfiles"
|
||||
GNOME_GIT = "git://gitlab.gnome.org/GNOME"
|
||||
GNOME_MIRROR = "https://download.gnome.org/sources/"
|
||||
GNU_MIRROR = "https://ftp.gnu.org/gnu"
|
||||
GNU_MIRROR = "https://ftpmirror.gnu.org/gnu"
|
||||
GNUPG_MIRROR = "https://www.gnupg.org/ftp/gcrypt"
|
||||
GPE_MIRROR = "http://gpe.linuxtogo.org/download/source"
|
||||
KERNELORG_MIRROR = "https://cdn.kernel.org/pub"
|
||||
|
||||
@@ -17,7 +17,7 @@ class BuildCpioTest(OESDKTestCase):
|
||||
"""
|
||||
def test_cpio(self):
|
||||
with tempfile.TemporaryDirectory(prefix="cpio-", dir=self.tc.sdk_dir) as testdir:
|
||||
tarball = self.fetch(testdir, self.td["DL_DIR"], "https://ftp.gnu.org/gnu/cpio/cpio-2.13.tar.gz")
|
||||
tarball = self.fetch(testdir, self.td["DL_DIR"], "https://ftpmirror.gnu.org/gnu/cpio/cpio-2.13.tar.gz")
|
||||
|
||||
dirs = {}
|
||||
dirs["source"] = os.path.join(testdir, "cpio-2.13")
|
||||
|
||||
@@ -40,7 +40,7 @@ class MetaIDE(OESelftestTestCase):
|
||||
def test_meta_ide_can_build_cpio_project(self):
|
||||
dl_dir = self.td.get('DL_DIR', None)
|
||||
self.project = SDKBuildProject(self.tmpdir_metaideQA + "/cpio/", self.environment_script_path,
|
||||
"https://ftp.gnu.org/gnu/cpio/cpio-2.13.tar.gz",
|
||||
"https://ftpmirror.gnu.org/gnu/cpio/cpio-2.13.tar.gz",
|
||||
self.tmpdir_metaideQA, self.td['DATETIME'], dl_dir=dl_dir)
|
||||
self.project.download_archive()
|
||||
self.assertEqual(self.project.run_configure('$CONFIGURE_FLAGS --disable-maintainer-mode','sed -i -e "/char \*program_name/d" src/global.c;'), 0,
|
||||
|
||||
@@ -10,7 +10,7 @@ DEPENDS = "efivar popt"
|
||||
|
||||
COMPATIBLE_HOST = "(i.86|x86_64|arm|aarch64).*-linux"
|
||||
|
||||
SRC_URI = "git://github.com/rhinstaller/efibootmgr.git;protocol=https;branch=master \
|
||||
SRC_URI = "git://github.com/rhinstaller/efibootmgr.git;protocol=https;branch=main \
|
||||
file://0001-remove-extra-decl.patch \
|
||||
file://97668ae0bce776a36ea2001dea63d376be8274ac.patch \
|
||||
file://0001-src-make-compatible-with-efivar-38.patch \
|
||||
|
||||
75
meta/recipes-bsp/grub/files/CVE-2024-56738.patch
Normal file
75
meta/recipes-bsp/grub/files/CVE-2024-56738.patch
Normal file
@@ -0,0 +1,75 @@
|
||||
From 4cef2fc7308b2132317ad166939994f098b41561 Mon Sep 17 00:00:00 2001
|
||||
From: Ross Burton <ross.burton@arm.com>
|
||||
Date: Tue, 9 Sep 2025 14:23:14 +0100
|
||||
Subject: [PATCH] CVE-2024-56738
|
||||
|
||||
Backport an algorithmic change to grub_crypto_memcmp() so that it completes in
|
||||
constant time and thus isn't susceptible to side-channel attacks.
|
||||
|
||||
This is a partial backport of grub 0739d24cd
|
||||
("libgcrypt: Adjust import script, definitions and API users for libgcrypt 1.11")
|
||||
|
||||
CVE: CVE-2024-56738
|
||||
Upstream-Status: Backport [0739d24cd]
|
||||
Signed-off-by: Ross Burton <ross.burton@arm.com>
|
||||
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
|
||||
---
|
||||
grub-core/lib/crypto.c | 23 ++++++++++++++++-------
|
||||
include/grub/crypto.h | 2 +-
|
||||
2 files changed, 17 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
|
||||
index ca334d5..1bfa922 100644
|
||||
--- a/grub-core/lib/crypto.c
|
||||
+++ b/grub-core/lib/crypto.c
|
||||
@@ -433,19 +433,28 @@ grub_crypto_gcry_error (gcry_err_code_t in)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Compare byte arrays of length LEN, return 1 if it's not same,
|
||||
+ * 0, otherwise.
|
||||
+ */
|
||||
int
|
||||
-grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
|
||||
+grub_crypto_memcmp (const void *b1, const void *b2, grub_size_t len)
|
||||
{
|
||||
- register grub_size_t counter = 0;
|
||||
- const grub_uint8_t *pa, *pb;
|
||||
+ const grub_uint8_t *a = b1;
|
||||
+ const grub_uint8_t *b = b2;
|
||||
+ int ab, ba;
|
||||
+ grub_size_t i;
|
||||
|
||||
- for (pa = a, pb = b; n; pa++, pb++, n--)
|
||||
+ /* Constant-time compare. */
|
||||
+ for (i = 0, ab = 0, ba = 0; i < len; i++)
|
||||
{
|
||||
- if (*pa != *pb)
|
||||
- counter++;
|
||||
+ /* If a[i] != b[i], either ab or ba will be negative. */
|
||||
+ ab |= a[i] - b[i];
|
||||
+ ba |= b[i] - a[i];
|
||||
}
|
||||
|
||||
- return !!counter;
|
||||
+ /* 'ab | ba' is negative when buffers are not equal, extract sign bit. */
|
||||
+ return ((unsigned int)(ab | ba) >> (sizeof(unsigned int) * 8 - 1)) & 1;
|
||||
}
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
diff --git a/include/grub/crypto.h b/include/grub/crypto.h
|
||||
index 21cd1f7..432912b 100644
|
||||
--- a/include/grub/crypto.h
|
||||
+++ b/include/grub/crypto.h
|
||||
@@ -393,7 +393,7 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
|
||||
grub_uint8_t *DK, grub_size_t dkLen);
|
||||
|
||||
int
|
||||
-grub_crypto_memcmp (const void *a, const void *b, grub_size_t n);
|
||||
+grub_crypto_memcmp (const void *b1, const void *b2, grub_size_t len);
|
||||
|
||||
int
|
||||
grub_password_get (char buf[], unsigned buf_size);
|
||||
--
|
||||
2.40.0
|
||||
@@ -59,6 +59,7 @@ SRC_URI = "${GNU_MIRROR}/grub/grub-${PV}.tar.gz \
|
||||
file://CVE-2025-0678_CVE-2025-1125.patch \
|
||||
file://CVE-2025-0690.patch \
|
||||
file://CVE-2025-1118.patch \
|
||||
file://CVE-2024-56738.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "23b64b4c741569f9426ed2e3d0e6780796fca081bee4c99f62aa3f53ae803f5f"
|
||||
@@ -69,6 +70,8 @@ CVE_CHECK_IGNORE += "CVE-2019-14865"
|
||||
CVE_CHECK_IGNORE += "CVE-2021-46705"
|
||||
# not-applicable-platform: Applies only to RHEL/Fedora
|
||||
CVE_CHECK_IGNORE += "CVE-2024-1048 CVE-2023-4001"
|
||||
# not-applicable-platform: Applies only to Ubuntu
|
||||
CVE_CHECK_IGNORE += "CVE-2024-2312"
|
||||
|
||||
DEPENDS = "flex-native bison-native gettext-native"
|
||||
|
||||
|
||||
56
meta/recipes-bsp/u-boot/files/CVE-2024-42040.patch
Normal file
56
meta/recipes-bsp/u-boot/files/CVE-2024-42040.patch
Normal file
@@ -0,0 +1,56 @@
|
||||
From 1406fc918977bba4dac0af5e22e63a5553aa6aff Mon Sep 17 00:00:00 2001
|
||||
From: Paul HENRYS <paul.henrys_ext@softathome.com>
|
||||
Date: Thu, 9 Oct 2025 17:43:28 +0200
|
||||
Subject: [PATCH] net: bootp: Prevent buffer overflow to avoid leaking the RAM
|
||||
content
|
||||
|
||||
CVE-2024-42040 describes a possible buffer overflow when calling
|
||||
bootp_process_vendor() in bootp_handler() since the total length
|
||||
of the packet is passed to bootp_process_vendor() without being
|
||||
reduced to len-(offsetof(struct bootp_hdr,bp_vend)+4).
|
||||
|
||||
The packet length is also checked against its minimum size to avoid
|
||||
reading data from struct bootp_hdr outside of the packet length.
|
||||
|
||||
Signed-off-by: Paul HENRYS <paul.henrys_ext@softathome.com>
|
||||
Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
|
||||
|
||||
CVE: CVE-2024-42040
|
||||
Upstream-Status: Backport [https://source.denx.de/u-boot/u-boot/-/commit/81e5708cc2c865df606e49aed5415adb2a662171]
|
||||
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
||||
---
|
||||
net/bootp.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/bootp.c b/net/bootp.c
|
||||
index 68002909634..843180d296c 100644
|
||||
--- a/net/bootp.c
|
||||
+++ b/net/bootp.c
|
||||
@@ -362,6 +362,14 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
|
||||
debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n",
|
||||
src, dest, len, sizeof(struct bootp_hdr));
|
||||
|
||||
+ /* Check the minimum size of a BOOTP packet is respected.
|
||||
+ * A BOOTP packet is between 300 bytes and 576 bytes big
|
||||
+ */
|
||||
+ if (len < offsetof(struct bootp_hdr, bp_vend) + 64) {
|
||||
+ printf("Error: got an invalid BOOTP packet (len=%u)\n", len);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
bp = (struct bootp_hdr *)pkt;
|
||||
|
||||
/* Filter out pkts we don't want */
|
||||
@@ -379,7 +387,8 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
|
||||
|
||||
/* Retrieve extended information (we must parse the vendor area) */
|
||||
if (net_read_u32((u32 *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
|
||||
- bootp_process_vendor((uchar *)&bp->bp_vend[4], len);
|
||||
+ bootp_process_vendor((uchar *)&bp->bp_vend[4], len -
|
||||
+ (offsetof(struct bootp_hdr, bp_vend) + 4));
|
||||
|
||||
net_set_timeout_handler(0, (thand_f *)0);
|
||||
bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop");
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -14,7 +14,9 @@ PE = "1"
|
||||
# repo during parse
|
||||
SRCREV = "d637294e264adfeb29f390dfc393106fd4d41b17"
|
||||
|
||||
SRC_URI = "git://source.denx.de/u-boot/u-boot.git;protocol=https;branch=master"
|
||||
SRC_URI = "git://source.denx.de/u-boot/u-boot.git;protocol=https;branch=master \
|
||||
file://CVE-2024-42040.patch \
|
||||
"
|
||||
|
||||
S = "${WORKDIR}/git"
|
||||
B = "${WORKDIR}/build"
|
||||
|
||||
@@ -20,7 +20,7 @@ SRC_URI = "https://ftp.isc.org/isc/bind9/${PV}/${BPN}-${PV}.tar.xz \
|
||||
file://0001-avoid-start-failure-with-bind-user.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "fb373fac5ebbc41c645160afd5a9fb451918f6c0e69ab1d9474154e2b515de40"
|
||||
SRC_URI[sha256sum] = "6ddc1d981511c4da0b203b0513af131e5d15e5f1c261145736fe1f35dd1fe79d"
|
||||
|
||||
UPSTREAM_CHECK_URI = "https://ftp.isc.org/isc/bind9/"
|
||||
# follow the ESV versions divisible by 2
|
||||
@@ -0,0 +1,98 @@
|
||||
From 35d5917652106aede47621bb3f64044604164043 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Thu, 4 Sep 2025 00:29:09 +0000
|
||||
Subject: [PATCH] upstream: Improve rules for %-expansion of username.
|
||||
|
||||
Usernames passed on the commandline will no longer be subject to
|
||||
% expansion. Some tools invoke ssh with connection information
|
||||
(i.e. usernames and host names) supplied from untrusted sources.
|
||||
These may contain % expansion sequences which could yield
|
||||
unexpected results.
|
||||
|
||||
Since openssh-9.6, all usernames have been subject to validity
|
||||
checking. This change tightens the validity checks by refusing
|
||||
usernames that include control characters (again, these can cause
|
||||
surprises when supplied adversarially).
|
||||
|
||||
This change also relaxes the validity checks in one small way:
|
||||
usernames supplied via the configuration file as literals (i.e.
|
||||
include no % expansion characters) are not subject to these
|
||||
validity checks. This allows usernames that contain arbitrary
|
||||
characters to be used, but only via configuration files. This
|
||||
is done on the basis that ssh's configuration is trusted.
|
||||
|
||||
Pointed out by David Leadbeater, ok deraadt@
|
||||
|
||||
OpenBSD-Commit-ID: e2f0c871fbe664aba30607321575e7c7fc798362
|
||||
|
||||
CVE: CVE-2025-61984
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/35d5917652106aede47621bb3f64044604164043]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
ssh.c | 11 +++++++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ssh.c b/ssh.c
|
||||
index 82ed15f..d4e2040 100644
|
||||
--- a/ssh.c
|
||||
+++ b/ssh.c
|
||||
@@ -634,6 +634,8 @@ valid_ruser(const char *s)
|
||||
if (*s == '-')
|
||||
return 0;
|
||||
for (i = 0; s[i] != 0; i++) {
|
||||
+ if (iscntrl((u_char)s[i]))
|
||||
+ return 0;
|
||||
if (strchr("'`\";&<>|(){}", s[i]) != NULL)
|
||||
return 0;
|
||||
/* Disallow '-' after whitespace */
|
||||
@@ -655,6 +657,7 @@ main(int ac, char **av)
|
||||
struct ssh *ssh = NULL;
|
||||
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
|
||||
int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
|
||||
+ int user_on_commandline = 0, user_was_default = 0, user_expanded = 0;
|
||||
char *p, *cp, *line, *argv0, *logfile, *host_arg;
|
||||
char cname[NI_MAXHOST], thishost[NI_MAXHOST];
|
||||
struct stat st;
|
||||
@@ -995,8 +998,10 @@ main(int ac, char **av)
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
- if (options.user == NULL)
|
||||
+ if (options.user == NULL) {
|
||||
options.user = optarg;
|
||||
+ user_on_commandline = 1;
|
||||
+ }
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
@@ -1099,6 +1104,7 @@ main(int ac, char **av)
|
||||
if (options.user == NULL) {
|
||||
options.user = tuser;
|
||||
tuser = NULL;
|
||||
+ user_on_commandline = 1;
|
||||
}
|
||||
free(tuser);
|
||||
if (options.port == -1 && tport != -1)
|
||||
@@ -1113,6 +1119,7 @@ main(int ac, char **av)
|
||||
if (options.user == NULL) {
|
||||
options.user = p;
|
||||
p = NULL;
|
||||
+ user_on_commandline = 1;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
host = xstrdup(cp);
|
||||
@@ -1265,8 +1272,10 @@ main(int ac, char **av)
|
||||
if (fill_default_options(&options) != 0)
|
||||
cleanup_exit(255);
|
||||
|
||||
- if (options.user == NULL)
|
||||
+ if (options.user == NULL) {
|
||||
+ user_was_default = 1;
|
||||
options.user = xstrdup(pw->pw_name);
|
||||
+ }
|
||||
|
||||
/*
|
||||
* If ProxyJump option specified, then construct a ProxyCommand now.
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 54928cb9eaa7143ff17f463efa7ed3109afdbf30 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Thu, 4 Sep 2025 00:30:06 +0000
|
||||
Subject: [PATCH] upstream: don't allow \0 characters in url-encoded strings.
|
||||
Suggested by David Leadbeater, ok deraadt@
|
||||
|
||||
OpenBSD-Commit-ID: c92196cef0f970ceabc1e8007a80b01e9b7cd49c
|
||||
|
||||
CVE: CVE-2025-61985
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/43b3bff47bb029f2299bacb6a36057981b39fdb0]
|
||||
|
||||
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
||||
---
|
||||
misc.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/misc.c b/misc.c
|
||||
index 6135b15..3d133b5 100644
|
||||
--- a/misc.c
|
||||
+++ b/misc.c
|
||||
@@ -934,9 +934,10 @@ urldecode(const char *src)
|
||||
*dst++ = ' ';
|
||||
break;
|
||||
case '%':
|
||||
+ /* note: don't allow \0 characters */
|
||||
if (!isxdigit((unsigned char)src[1]) ||
|
||||
!isxdigit((unsigned char)src[2]) ||
|
||||
- (ch = hexchar(src + 1)) == -1) {
|
||||
+ (ch = hexchar(src + 1)) == -1 || ch == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
2.40.0
|
||||
@@ -39,6 +39,8 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar
|
||||
file://CVE-2024-6387.patch \
|
||||
file://CVE-2025-26465.patch \
|
||||
file://CVE-2025-32728.patch \
|
||||
file://CVE-2025-61985.patch \
|
||||
file://CVE-2025-61984.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "fd497654b7ab1686dac672fb83dfb4ba4096e8b5ffcdaccd262380ae58bec5e7"
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ SRC_URI:append:class-nativesdk = " \
|
||||
file://environment.d-openssl.sh \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "dfdd77e4ea1b57ff3a6dbde6b0bdc3f31db5ac99e7fdd4eaf9e1fbb6ec2db8ce"
|
||||
SRC_URI[sha256sum] = "d80c34f5cf902dccf1f1b5df5ebb86d0392e37049e5d73df1b3abae72e4ffe8b"
|
||||
|
||||
inherit lib_package multilib_header multilib_script ptest perlnative
|
||||
MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash"
|
||||
@@ -0,0 +1,79 @@
|
||||
From 726432d7622cc0088ac353d073b59628b590ea44 Mon Sep 17 00:00:00 2001
|
||||
From: Jouni Malinen <j@w1.fi>
|
||||
Date: Sat, 25 Jan 2025 11:21:16 +0200
|
||||
Subject: [PATCH] RADIUS: Drop pending request only when accepting the response
|
||||
|
||||
The case of an invalid authenticator in a RADIUS response could imply
|
||||
that the response is not from the correct RADIUS server and as such,
|
||||
such a response should be discarded without changing internal state for
|
||||
the pending request. The case of an unknown response (RADIUS_RX_UNKNOWN)
|
||||
is somewhat more complex since it could have been indicated before
|
||||
validating the authenticator. In any case, it seems better to change the
|
||||
state for the pending request only when we have fully accepted the
|
||||
response.
|
||||
|
||||
Allowing the internal state of pending RADIUS request to change based on
|
||||
responses that are not fully validation could have allow at least a
|
||||
theoretical DoS attack if an attacker were to have means for injecting
|
||||
RADIUS messages to the network using the IP address of the real RADIUS
|
||||
server and being able to do so more quickly than the real server and
|
||||
with the matching identifier from the request header (i.e., either by
|
||||
flooding 256 responses quickly or by having means to capture the RADIUS
|
||||
request). These should not really be realistic options in a properly
|
||||
protected deployment, but nevertheless it is good to be more careful in
|
||||
processing RADIUS responses.
|
||||
|
||||
Remove a pending RADIUS request from the internal list only when having
|
||||
fully accepted a matching RADIUS response, i.e., after one of the
|
||||
registered handlers has confirmed that the authenticator is valid and
|
||||
processing of the response has succeeded.
|
||||
|
||||
Signed-off-by: Jouni Malinen <j@w1.fi>
|
||||
|
||||
CVE: CVE-2025-24912
|
||||
Upstream-Status: Backport [https://w1.fi/cgit/hostap/commit/?id=726432d7622cc0088ac353d073b59628b590ea44]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
src/radius/radius_client.c | 15 +++++++--------
|
||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
|
||||
index 2a7f36170..7909b29a7 100644
|
||||
--- a/src/radius/radius_client.c
|
||||
+++ b/src/radius/radius_client.c
|
||||
@@ -922,13 +922,6 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
roundtrip / 100, roundtrip % 100);
|
||||
rconf->round_trip_time = roundtrip;
|
||||
|
||||
- /* Remove ACKed RADIUS packet from retransmit list */
|
||||
- if (prev_req)
|
||||
- prev_req->next = req->next;
|
||||
- else
|
||||
- radius->msgs = req->next;
|
||||
- radius->num_msgs--;
|
||||
-
|
||||
for (i = 0; i < num_handlers; i++) {
|
||||
RadiusRxResult res;
|
||||
res = handlers[i].handler(msg, req->msg, req->shared_secret,
|
||||
@@ -939,6 +932,13 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
radius_msg_free(msg);
|
||||
/* fall through */
|
||||
case RADIUS_RX_QUEUED:
|
||||
+ /* Remove ACKed RADIUS packet from retransmit list */
|
||||
+ if (prev_req)
|
||||
+ prev_req->next = req->next;
|
||||
+ else
|
||||
+ radius->msgs = req->next;
|
||||
+ radius->num_msgs--;
|
||||
+
|
||||
radius_client_msg_free(req);
|
||||
return;
|
||||
case RADIUS_RX_INVALID_AUTHENTICATOR:
|
||||
@@ -960,7 +960,6 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
msg_type, hdr->code, hdr->identifier,
|
||||
invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
|
||||
"");
|
||||
- radius_client_msg_free(req);
|
||||
|
||||
fail:
|
||||
radius_msg_free(msg);
|
||||
@@ -0,0 +1,70 @@
|
||||
From 339a334551ca911187cc870f4f97ef08e11db109 Mon Sep 17 00:00:00 2001
|
||||
From: Jouni Malinen <quic_jouni@quicinc.com>
|
||||
Date: Wed, 5 Feb 2025 19:23:39 +0200
|
||||
Subject: [PATCH] RADIUS: Fix pending request dropping
|
||||
|
||||
A recent change to this moved the place where the processed RADIUS
|
||||
request was removed from the pending list to happen after the message
|
||||
handler had been called. This did not take into account possibility of
|
||||
the handler adding a new pending request in the list and the prev_req
|
||||
pointer not necessarily pointing to the correct entry anymore. As such,
|
||||
some of the pending requests could have been lost and that would result
|
||||
in not being able to process responses to those requests and also, to a
|
||||
memory leak.
|
||||
|
||||
Fix this by determining prev_req at the point when the pending request
|
||||
is being removed, i.e., after the handler function has already added a
|
||||
new entry.
|
||||
|
||||
Fixes: 726432d7622c ("RADIUS: Drop pending request only when accepting the response")
|
||||
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
|
||||
|
||||
CVE: CVE-2025-24912
|
||||
Upstream-Status: Backport [https://w1.fi/cgit/hostap/commit/?id=339a334551ca911187cc870f4f97ef08e11db109]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
src/radius/radius_client.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
|
||||
index 7909b29a7..d4faa7936 100644
|
||||
--- a/src/radius/radius_client.c
|
||||
+++ b/src/radius/radius_client.c
|
||||
@@ -824,7 +824,7 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
struct radius_hdr *hdr;
|
||||
struct radius_rx_handler *handlers;
|
||||
size_t num_handlers, i;
|
||||
- struct radius_msg_list *req, *prev_req;
|
||||
+ struct radius_msg_list *req, *prev_req, *r;
|
||||
struct os_reltime now;
|
||||
struct hostapd_radius_server *rconf;
|
||||
int invalid_authenticator = 0;
|
||||
@@ -887,7 +887,6 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
break;
|
||||
}
|
||||
|
||||
- prev_req = NULL;
|
||||
req = radius->msgs;
|
||||
while (req) {
|
||||
/* TODO: also match by src addr:port of the packet when using
|
||||
@@ -899,7 +898,6 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
hdr->identifier)
|
||||
break;
|
||||
|
||||
- prev_req = req;
|
||||
req = req->next;
|
||||
}
|
||||
|
||||
@@ -933,6 +931,12 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
||||
/* fall through */
|
||||
case RADIUS_RX_QUEUED:
|
||||
/* Remove ACKed RADIUS packet from retransmit list */
|
||||
+ prev_req = NULL;
|
||||
+ for (r = radius->msgs; r; r = r->next) {
|
||||
+ if (r == req)
|
||||
+ break;
|
||||
+ prev_req = r;
|
||||
+ }
|
||||
if (prev_req)
|
||||
prev_req->next = req->next;
|
||||
else
|
||||
@@ -43,6 +43,8 @@ SRC_URI = "http://w1.fi/releases/wpa_supplicant-${PV}.tar.gz \
|
||||
file://CVE-2022-37660-0003.patch \
|
||||
file://CVE-2022-37660-0004.patch \
|
||||
file://CVE-2022-37660-0005.patch \
|
||||
file://CVE-2025-24912-01.patch \
|
||||
file://CVE-2025-24912-02.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "20df7ae5154b3830355f8ab4269123a87affdea59fe74fe9292a91d0d7e17b2f"
|
||||
|
||||
|
||||
57
meta/recipes-core/busybox/busybox/CVE-2025-46394-01.patch
Normal file
57
meta/recipes-core/busybox/busybox/CVE-2025-46394-01.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From f5e1bf966b19ea1821f00a8c9ecd7774598689b4 Mon Sep 17 00:00:00 2001
|
||||
From: Denys Vlasenko <vda.linux@googlemail.com>
|
||||
Date: Wed, 24 Sep 2025 03:28:47 +0200
|
||||
Subject: [PATCH] archival/libarchive: sanitize filenames on output (prevent
|
||||
control sequence attacks
|
||||
|
||||
This fixes CVE-2025-46394 (terminal escape sequence injection)
|
||||
|
||||
Original credit: Ian.Norton at entrust.com
|
||||
|
||||
function old new delta
|
||||
header_list 9 15 +6
|
||||
header_verbose_list 239 244 +5
|
||||
------------------------------------------------------------------------------
|
||||
(add/remove: 0/0 grow/shrink: 2/0 up/down: 11/0) Total: 11 bytes
|
||||
|
||||
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
|
||||
|
||||
CVE: CVE-2025-46394
|
||||
Upstream-Status: Backport [https://git.busybox.net/busybox/commit/?id=f5e1bf966b19ea1821f00a8c9ecd7774598689b4]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
archival/libarchive/header_list.c | 2 +-
|
||||
archival/libarchive/header_verbose_list.c | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/archival/libarchive/header_list.c b/archival/libarchive/header_list.c
|
||||
index 0621aa406..9490b3635 100644
|
||||
--- a/archival/libarchive/header_list.c
|
||||
+++ b/archival/libarchive/header_list.c
|
||||
@@ -8,5 +8,5 @@
|
||||
void FAST_FUNC header_list(const file_header_t *file_header)
|
||||
{
|
||||
//TODO: cpio -vp DIR should output "DIR/NAME", not just "NAME" */
|
||||
- puts(file_header->name);
|
||||
+ puts(printable_string(file_header->name));
|
||||
}
|
||||
diff --git a/archival/libarchive/header_verbose_list.c b/archival/libarchive/header_verbose_list.c
|
||||
index a575a08a0..e7a09430d 100644
|
||||
--- a/archival/libarchive/header_verbose_list.c
|
||||
+++ b/archival/libarchive/header_verbose_list.c
|
||||
@@ -57,13 +57,13 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
|
||||
ptm->tm_hour,
|
||||
ptm->tm_min,
|
||||
ptm->tm_sec,
|
||||
- file_header->name);
|
||||
+ printable_string(file_header->name));
|
||||
|
||||
#endif /* FEATURE_TAR_UNAME_GNAME */
|
||||
|
||||
/* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */
|
||||
if (file_header->link_target) {
|
||||
- printf(" -> %s", file_header->link_target);
|
||||
+ printf(" -> %s", printable_string(file_header->link_target));
|
||||
}
|
||||
bb_putchar('\n');
|
||||
}
|
||||
32
meta/recipes-core/busybox/busybox/CVE-2025-46394-02.patch
Normal file
32
meta/recipes-core/busybox/busybox/CVE-2025-46394-02.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
From 7378db981d87b4a2264e14d60340a7fb5c67ae59 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Marko <peter.marko@siemens.com>
|
||||
Date: Fri, 3 Oct 2025 16:12:56 +0200
|
||||
Subject: [PATCH] testsuite/tar.tests: fix test after CVE-2025-46394
|
||||
|
||||
tar now sanitizes output and this test needs to expect that.
|
||||
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
|
||||
CVE: CVE-2025-46394
|
||||
Upstream-Status: Submitted [https://lists.busybox.net/pipermail/busybox/2025-October/091743.html]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
testsuite/tar.tests | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
|
||||
index 0f2e89112..48fc38114 100755
|
||||
--- a/testsuite/tar.tests
|
||||
+++ b/testsuite/tar.tests
|
||||
@@ -325,9 +325,9 @@ unset LANG
|
||||
rm -rf etc usr
|
||||
' "\
|
||||
etc/ssl/certs/3b2716e5.0
|
||||
-etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
|
||||
+etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sa??lay??c??s??.pem
|
||||
etc/ssl/certs/f80cc7f6.0
|
||||
-usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
|
||||
+usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sa??lay??c??s??.crt
|
||||
0
|
||||
etc/ssl/certs/3b2716e5.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
|
||||
etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem -> /usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
|
||||
@@ -59,6 +59,8 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
|
||||
file://CVE-2023-42366.patch \
|
||||
file://0001-cut-Fix-s-flag-to-omit-blank-lines.patch \
|
||||
file://CVE-2023-39810.patch \
|
||||
file://CVE-2025-46394-01.patch \
|
||||
file://CVE-2025-46394-02.patch \
|
||||
"
|
||||
SRC_URI:append:libc-musl = " file://musl.cfg "
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
From 4dd540505d40babe488404f3174ec39f49a84485 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
||||
Date: Mon, 4 Aug 2025 15:10:21 -0500
|
||||
Subject: [PATCH] openssl: properly check return value when writing to BIO
|
||||
objects
|
||||
|
||||
In particular, we will read out of bounds, and then write the invalid
|
||||
memory, if BIO_write() fails when getting the PROP_CERTIFICATE_PEM
|
||||
property. Here we attempt to check the return value, but the check is
|
||||
not correct.
|
||||
|
||||
This also fixes a leak of the BIO in the same place.
|
||||
|
||||
Also add error checking to PROP_SUBJECT_NAME and PROP_ISSUER_NAME, for
|
||||
good measure.
|
||||
|
||||
Fixes #226
|
||||
|
||||
CVE: CVE-2025-60018
|
||||
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib-networking/-/commit/4dd540505d40babe488404f3174ec39f49a84485]
|
||||
|
||||
Signed-off-by: Rajeshkumar Ramasamy <rajeshkumar.ramasamy@windriver.com>
|
||||
---
|
||||
tls/openssl/gtlscertificate-openssl.c | 25 +++++++++++++++----------
|
||||
1 file changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c
|
||||
index 648f3e8..b536559 100644
|
||||
--- a/tls/openssl/gtlscertificate-openssl.c
|
||||
+++ b/tls/openssl/gtlscertificate-openssl.c
|
||||
@@ -362,15 +362,12 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
case PROP_CERTIFICATE_PEM:
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
|
||||
- if (!PEM_write_bio_X509 (bio, openssl->cert) || !BIO_write (bio, "\0", 1))
|
||||
- certificate_pem = NULL;
|
||||
- else
|
||||
+ if (PEM_write_bio_X509 (bio, openssl->cert) == 1 && BIO_write (bio, "\0", 1) == 1)
|
||||
{
|
||||
BIO_get_mem_data (bio, &certificate_pem);
|
||||
g_value_set_string (value, certificate_pem);
|
||||
-
|
||||
- BIO_free_all (bio);
|
||||
}
|
||||
+ BIO_free_all (bio);
|
||||
break;
|
||||
|
||||
case PROP_PRIVATE_KEY:
|
||||
@@ -411,8 +408,12 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
case PROP_SUBJECT_NAME:
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
name = X509_get_subject_name (openssl->cert);
|
||||
- X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS);
|
||||
- BIO_write (bio, "\0", 1);
|
||||
+ if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 ||
|
||||
+ BIO_write (bio, "\0", 1) != 1)
|
||||
+ {
|
||||
+ BIO_free_all (bio);
|
||||
+ break;
|
||||
+ }
|
||||
BIO_get_mem_data (bio, (char **)&name_string);
|
||||
g_value_set_string (value, name_string);
|
||||
BIO_free_all (bio);
|
||||
@@ -421,9 +422,13 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
case PROP_ISSUER_NAME:
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
name = X509_get_issuer_name (openssl->cert);
|
||||
- X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS);
|
||||
- BIO_write (bio, "\0", 1);
|
||||
- BIO_get_mem_data (bio, &name_string);
|
||||
+ if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 ||
|
||||
+ BIO_write (bio, "\0", 1) != 1)
|
||||
+ {
|
||||
+ BIO_free_all (bio);
|
||||
+ break;
|
||||
+ }
|
||||
+ BIO_get_mem_data (bio, (char **)&name_string);
|
||||
g_value_set_string (value, name_string);
|
||||
BIO_free_all (bio);
|
||||
break;
|
||||
--
|
||||
2.48.1
|
||||
@@ -0,0 +1,137 @@
|
||||
From 70df675dd4f5e4a593b2f95406c1aac031aa8bc7 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
||||
Date: Thu, 21 Aug 2025 17:21:01 -0500
|
||||
Subject: [PATCH] openssl: check return values of BIO_new()
|
||||
|
||||
We probably need to check even more return values of even more OpenSSL
|
||||
functions, but these ones allocate memory and that's particularly
|
||||
important to get right.
|
||||
|
||||
CVE: CVE-2025-60019
|
||||
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib-networking/-/commit/70df675dd4f5e4a593b2f95406c1aac031aa8bc7]
|
||||
|
||||
Signed-off-by: Rajeshkumar Ramasamy <rajeshkumar.ramasamy@windriver.com>
|
||||
---
|
||||
tls/openssl/gtlscertificate-openssl.c | 39 ++++++++++++++++++++-------
|
||||
1 file changed, 29 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c
|
||||
index 8f828a7..f7fde51 100644
|
||||
--- a/tls/openssl/gtlscertificate-openssl.c
|
||||
+++ b/tls/openssl/gtlscertificate-openssl.c
|
||||
@@ -156,6 +156,9 @@ export_privkey_to_der (GTlsCertificateOpenssl *openssl,
|
||||
goto err;
|
||||
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
+ if (!bio)
|
||||
+ goto err;
|
||||
+
|
||||
if (i2d_PKCS8_PRIV_KEY_INFO_bio (bio, pkcs8) == 0)
|
||||
goto err;
|
||||
|
||||
@@ -189,6 +192,9 @@ export_privkey_to_pem (GTlsCertificateOpenssl *openssl)
|
||||
return NULL;
|
||||
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
+ if (!bio)
|
||||
+ goto out;
|
||||
+
|
||||
ret = PEM_write_bio_PKCS8PrivateKey (bio, openssl->key, NULL, NULL, 0, NULL, NULL);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
@@ -201,7 +207,7 @@ export_privkey_to_pem (GTlsCertificateOpenssl *openssl)
|
||||
result = g_strdup (data);
|
||||
|
||||
out:
|
||||
- BIO_free_all (bio);
|
||||
+ g_clear_pointer (&bio, BIO_free_all);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -216,7 +222,7 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
guint8 *data;
|
||||
BIO *bio;
|
||||
GByteArray *byte_array;
|
||||
- char *certificate_pem;
|
||||
+ const char *certificate_pem;
|
||||
long size;
|
||||
|
||||
const ASN1_TIME *time_asn1;
|
||||
@@ -251,12 +257,12 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
case PROP_CERTIFICATE_PEM:
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
|
||||
- if (PEM_write_bio_X509 (bio, openssl->cert) == 1 && BIO_write (bio, "\0", 1) == 1)
|
||||
+ if (bio && PEM_write_bio_X509 (bio, openssl->cert) == 1 && BIO_write (bio, "\0", 1) == 1)
|
||||
{
|
||||
BIO_get_mem_data (bio, &certificate_pem);
|
||||
g_value_set_string (value, certificate_pem);
|
||||
}
|
||||
- BIO_free_all (bio);
|
||||
+ g_clear_pointer (&bio, BIO_free_all);
|
||||
break;
|
||||
|
||||
case PROP_PRIVATE_KEY:
|
||||
@@ -296,6 +302,8 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
|
||||
case PROP_SUBJECT_NAME:
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
+ if (!bio)
|
||||
+ break;
|
||||
name = X509_get_subject_name (openssl->cert);
|
||||
if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 ||
|
||||
BIO_write (bio, "\0", 1) != 1)
|
||||
@@ -310,6 +318,8 @@ g_tls_certificate_openssl_get_property (GObject *object,
|
||||
|
||||
case PROP_ISSUER_NAME:
|
||||
bio = BIO_new (BIO_s_mem ());
|
||||
+ if (!bio)
|
||||
+ break;
|
||||
name = X509_get_issuer_name (openssl->cert);
|
||||
if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 ||
|
||||
BIO_write (bio, "\0", 1) != 1)
|
||||
@@ -377,8 +387,11 @@ g_tls_certificate_openssl_set_property (GObject *object,
|
||||
break;
|
||||
g_return_if_fail (openssl->have_cert == FALSE);
|
||||
bio = BIO_new_mem_buf ((gpointer)string, -1);
|
||||
- openssl->cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
|
||||
- BIO_free (bio);
|
||||
+ if (bio)
|
||||
+ {
|
||||
+ openssl->cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
|
||||
+ BIO_free (bio);
|
||||
+ }
|
||||
if (openssl->cert)
|
||||
openssl->have_cert = TRUE;
|
||||
else if (!openssl->construct_error)
|
||||
@@ -397,8 +410,11 @@ g_tls_certificate_openssl_set_property (GObject *object,
|
||||
break;
|
||||
g_return_if_fail (openssl->have_key == FALSE);
|
||||
bio = BIO_new_mem_buf (bytes->data, bytes->len);
|
||||
- openssl->key = d2i_PrivateKey_bio (bio, NULL);
|
||||
- BIO_free (bio);
|
||||
+ if (bio)
|
||||
+ {
|
||||
+ openssl->key = d2i_PrivateKey_bio (bio, NULL);
|
||||
+ BIO_free (bio);
|
||||
+ }
|
||||
if (openssl->key)
|
||||
openssl->have_key = TRUE;
|
||||
else if (!openssl->construct_error)
|
||||
@@ -417,8 +433,11 @@ g_tls_certificate_openssl_set_property (GObject *object,
|
||||
break;
|
||||
g_return_if_fail (openssl->have_key == FALSE);
|
||||
bio = BIO_new_mem_buf ((gpointer)string, -1);
|
||||
- openssl->key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL);
|
||||
- BIO_free (bio);
|
||||
+ if (bio)
|
||||
+ {
|
||||
+ openssl->key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL);
|
||||
+ BIO_free (bio);
|
||||
+ }
|
||||
if (openssl->key)
|
||||
openssl->have_key = TRUE;
|
||||
else if (!openssl->construct_error)
|
||||
--
|
||||
2.48.1
|
||||
@@ -24,6 +24,8 @@ GNOMEBASEBUILDCLASS = "meson"
|
||||
inherit gnomebase gettext upstream-version-is-even gio-module-cache ptest-gnome
|
||||
|
||||
SRC_URI += "file://run-ptest"
|
||||
SRC_URI += "file://CVE-2025-60018.patch"
|
||||
SRC_URI += "file://CVE-2025-60019.patch"
|
||||
|
||||
FILES:${PN} += "\
|
||||
${libdir}/gio/modules/libgio*.so \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SRCBRANCH ?= "release/2.35/master"
|
||||
PV = "2.35"
|
||||
SRCREV_glibc ?= "a66bc3941ff298e474d5f02d0c3303401951141f"
|
||||
SRCREV_glibc ?= "4e50046821f05ada5f14c76803845125ddb3ed7d"
|
||||
SRCREV_localedef ?= "794da69788cbf9bf57b59a852f9f11307663fa87"
|
||||
|
||||
GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
From 31d9848830e496f57d4182b518467c4c63bfd4bd Mon Sep 17 00:00:00 2001
|
||||
From 0402999b82f697011de388f61bad68da26060bef Mon Sep 17 00:00:00 2001
|
||||
From: Frank Barrus <frankbarrus_sw@shaggy.cc>
|
||||
Date: Mon, 16 Jun 2025 22:37:54 -0700
|
||||
Date: Tue, 14 Oct 2025 03:55:17 -0700
|
||||
Subject: [PATCH] pthreads NPTL: lost wakeup fix 2
|
||||
|
||||
This fixes the lost wakeup (from a bug in signal stealing) with a change
|
||||
@@ -65,18 +65,19 @@ full wakeup from a G1/G2 switch.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
Commit : 1db84775f831a1494993ce9c118deaf9537cc50a
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=1db84775f831a1494993ce9c118deaf9537cc50a]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002277.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_common.c | 106 +++++++++------------------
|
||||
nptl/pthread_cond_common.c | 105 +++++++++------------------
|
||||
nptl/pthread_cond_wait.c | 144 ++++++++++++-------------------------
|
||||
2 files changed, 81 insertions(+), 169 deletions(-)
|
||||
2 files changed, 81 insertions(+), 168 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index fb035f72c3..8dd7037923 100644
|
||||
index fb035f72..a55eee3e 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -201,7 +201,6 @@ static bool __attribute__ ((unused))
|
||||
@@ -87,7 +88,7 @@ index fb035f72c3..8dd7037923 100644
|
||||
unsigned int g1 = *g1index;
|
||||
|
||||
/* If there is no waiter in G2, we don't do anything. The expression may
|
||||
@@ -222,85 +221,46 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
@@ -222,84 +221,46 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
* New waiters arriving concurrently with the group switching will all go
|
||||
into G2 until we atomically make the switch. Waiters existing in G2
|
||||
are not affected.
|
||||
@@ -176,7 +177,6 @@ index fb035f72c3..8dd7037923 100644
|
||||
- that this is now a new group (see __pthread_cond_wait_common for the
|
||||
- matching acquire MO loads). */
|
||||
- atomic_store_release (cond->__data.__g_signals + g1, 0);
|
||||
-
|
||||
+ unsigned int lowseq = ((old_g1_start + old_orig_size) << 1) & ~1U;
|
||||
+
|
||||
+ /* If any waiters still hold group references (and thus could be blocked),
|
||||
@@ -201,10 +201,10 @@ index fb035f72c3..8dd7037923 100644
|
||||
+
|
||||
+ futex_wake (cond->__data.__g_signals + g1, INT_MAX, private);
|
||||
+ }
|
||||
|
||||
/* At this point, the old G1 is now a valid new G2 (but not in use yet).
|
||||
No old waiter can neither grab a signal nor acquire a reference without
|
||||
noticing that __g1_start is larger.
|
||||
@@ -311,6 +271,10 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
@@ -311,6 +272,10 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
g1 ^= 1;
|
||||
*g1index ^= 1;
|
||||
|
||||
@@ -216,7 +216,7 @@ index fb035f72c3..8dd7037923 100644
|
||||
lock. */
|
||||
unsigned int orig_size = wseq - (old_g1_start + old_orig_size);
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 20c348a503..1cb3dbf7b0 100644
|
||||
index 20c348a5..1cb3dbf7 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -238,9 +238,7 @@ __condvar_cleanup_waiting (void *arg)
|
||||
|
||||
54
meta/recipes-core/glibc/glibc/0026-PR25847-10.patch
Normal file
54
meta/recipes-core/glibc/glibc/0026-PR25847-10.patch
Normal file
@@ -0,0 +1,54 @@
|
||||
From 4f78382dd671f381db6d1f452e6f1593d17b177e Mon Sep 17 00:00:00 2001
|
||||
From: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue, 14 Oct 2025 06:53:40 -0700
|
||||
Subject: [PATCH] nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41
|
||||
versions (bug 32786)
|
||||
|
||||
The new initializer and struct layout does not initialize the
|
||||
__g_signals field in the old struct layout before the change in
|
||||
commit c36fc50781995e6758cae2b6927839d0157f213c ("nptl: Remove
|
||||
g_refs from condition variables"). Bring back fields at the end
|
||||
of struct __pthread_cond_s, so that they are again zero-initialized.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: dbc5a50d12eff4cb3f782129029d04b8a76f58e7
|
||||
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002282.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
sysdeps/nptl/bits/thread-shared-types.h | 2 ++
|
||||
sysdeps/nptl/pthread.h | 2 +-
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h
|
||||
index 6f17afa4..2354ea21 100644
|
||||
--- a/sysdeps/nptl/bits/thread-shared-types.h
|
||||
+++ b/sysdeps/nptl/bits/thread-shared-types.h
|
||||
@@ -99,6 +99,8 @@ struct __pthread_cond_s
|
||||
unsigned int __g1_orig_size;
|
||||
unsigned int __wrefs;
|
||||
unsigned int __g_signals[2];
|
||||
+ unsigned int __unused_initialized_1;
|
||||
+ unsigned int __unused_initialized_2;
|
||||
};
|
||||
|
||||
typedef unsigned int __tss_t;
|
||||
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
|
||||
index bbb36540..8d6d24ff 100644
|
||||
--- a/sysdeps/nptl/pthread.h
|
||||
+++ b/sysdeps/nptl/pthread.h
|
||||
@@ -152,7 +152,7 @@ enum
|
||||
|
||||
|
||||
/* Conditional variable handling. */
|
||||
-#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0} } }
|
||||
+#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0, 0 } }
|
||||
|
||||
|
||||
/* Cleanup buffers */
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
From 6aab1191e35a3da66e8c49d95178a9d77c119a1f Mon Sep 17 00:00:00 2001
|
||||
From 306ea7810f5f6709ef3942a7be75077203b5d201 Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Mon, 16 Jun 2025 23:17:53 -0700
|
||||
Date: Tue, 14 Oct 2025 04:27:19 -0700
|
||||
Subject: [PATCH] nptl: Update comments and indentation for new condvar
|
||||
implementation
|
||||
|
||||
@@ -9,9 +9,10 @@ Also fixing indentation where it was using spaces instead of tabs.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: 0cc973160c23bb67f895bc887dd6942d29f8fee3
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=0cc973160c23bb67f895bc887dd6942d29f8fee3]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002275.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
@@ -20,7 +21,7 @@ Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
2 files changed, 22 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index 8dd7037923..306a207dd6 100644
|
||||
index a55eee3e..350a16fa 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -221,8 +221,9 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
@@ -36,7 +37,7 @@ index 8dd7037923..306a207dd6 100644
|
||||
__g_signals since it provides enough signals for all possible
|
||||
remaining waiters. As a result, they can each consume a signal
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 1cb3dbf7b0..cee1968756 100644
|
||||
index 1cb3dbf7..cee19687 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -249,7 +249,7 @@ __condvar_cleanup_waiting (void *arg)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
From 28a5082045429fdc5a4744d45fdc5b5202528eaa Mon Sep 17 00:00:00 2001
|
||||
From 5f22e8cf95cf6b3b2e16ddb03820ae3e77fd420d Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Mon, 16 Jun 2025 23:29:49 -0700
|
||||
Date: Tue, 14 Oct 2025 04:47:48 -0700
|
||||
Subject: [PATCH] nptl: Remove unnecessary catch-all-wake in condvar group
|
||||
switch
|
||||
|
||||
@@ -15,17 +15,18 @@ switch g1 when it should, so we wouldn't even have entered this code path.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: b42cc6af11062c260c7dfa91f1c89891366fed3e
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=b42cc6af11062c260c7dfa91f1c89891366fed3e]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002274.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_common.c | 30 +-----------------------------
|
||||
1 file changed, 1 insertion(+), 29 deletions(-)
|
||||
nptl/pthread_cond_common.c | 31 +------------------------------
|
||||
1 file changed, 1 insertion(+), 30 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index 306a207dd6..f976a533a1 100644
|
||||
index 350a16fa..f976a533 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -221,13 +221,7 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
@@ -43,7 +44,7 @@ index 306a207dd6..f976a533a1 100644
|
||||
|
||||
/* Update __g1_start, which finishes closing this group. The value we add
|
||||
will never be negative because old_orig_size can only be zero when we
|
||||
@@ -240,28 +234,6 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
@@ -240,29 +234,6 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
|
||||
unsigned int lowseq = ((old_g1_start + old_orig_size) << 1) & ~1U;
|
||||
|
||||
@@ -69,6 +70,7 @@ index 306a207dd6..f976a533a1 100644
|
||||
-
|
||||
- futex_wake (cond->__data.__g_signals + g1, INT_MAX, private);
|
||||
- }
|
||||
-
|
||||
/* At this point, the old G1 is now a valid new G2 (but not in use yet).
|
||||
No old waiter can neither grab a signal nor acquire a reference without
|
||||
noticing that __g1_start is larger.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
From 16b9af737c77b153fca4f36cbdbe94f7416c0b42 Mon Sep 17 00:00:00 2001
|
||||
From d714165c8bb3cac420077cfa61e3df87ea7f8b2c Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Mon, 16 Jun 2025 23:38:40 -0700
|
||||
Date: Tue, 14 Oct 2025 05:34:06 -0700
|
||||
Subject: [PATCH] nptl: Remove unnecessary quadruple check in pthread_cond_wait
|
||||
|
||||
pthread_cond_wait was checking whether it was in a closed group no less than
|
||||
@@ -22,9 +22,10 @@ Removing the duplicate checks clarifies the code.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: 4f7b051f8ee3feff1b53b27a906f245afaa9cee1
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=4f7b051f8ee3feff1b53b27a906f245afaa9cee1]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002276.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
@@ -32,7 +33,7 @@ Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
1 file changed, 49 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index cee1968756..47e834cade 100644
|
||||
index cee19687..47e834ca 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -366,7 +366,6 @@ static __always_inline int
|
||||
|
||||
@@ -1,105 +1,188 @@
|
||||
From d9ffb50dc55f77e584a5d0275eea758c7a6b04e3 Mon Sep 17 00:00:00 2001
|
||||
From f904a81ff8d0469ceaf3220329e716c03fcbd2d3 Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Mon, 16 Jun 2025 23:53:35 -0700
|
||||
Subject: [PATCH] nptl: Use a single loop in pthread_cond_wait instaed of a
|
||||
nested loop
|
||||
Date: Tue, 14 Oct 2025 05:59:02 -0700
|
||||
Subject: [PATCH] nptl: Remove g_refs from condition variables
|
||||
|
||||
The loop was a little more complicated than necessary. There was only one
|
||||
break statement out of the inner loop, and the outer loop was nearly empty.
|
||||
So just remove the outer loop, moving its code to the one break statement in
|
||||
the inner loop. This allows us to replace all gotos with break statements.
|
||||
This variable used to be needed to wait in group switching until all sleepers
|
||||
have confirmed that they have woken. This is no longer needed. Nothing waits
|
||||
on this variable so there is no need to track how many threads are currently
|
||||
asleep in each group.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
cmmit: c36fc50781995e6758cae2b6927839d0157f213c
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=929a4764ac90382616b6a21f099192b2475da674]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002278.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_wait.c | 41 +++++++++++++++++++---------------------
|
||||
1 file changed, 19 insertions(+), 22 deletions(-)
|
||||
nptl/pthread_cond_wait.c | 52 +------------------------
|
||||
nptl/tst-cond22.c | 12 +++---
|
||||
sysdeps/nptl/bits/thread-shared-types.h | 3 +-
|
||||
sysdeps/nptl/pthread.h | 2 +-
|
||||
4 files changed, 9 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 47e834cade..5c86880105 100644
|
||||
index 47e834ca..8a9219e0 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -410,17 +410,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
return err;
|
||||
@@ -143,23 +143,6 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
|
||||
}
|
||||
}
|
||||
|
||||
- /* Now wait until a signal is available in our group or it is closed.
|
||||
- Acquire MO so that if we observe (signals == lowseq) after group
|
||||
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
- store and will see the prior update of __g1_start done while switching
|
||||
- groups too. */
|
||||
- unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
-
|
||||
- do
|
||||
-/* Wake up any signalers that might be waiting. */
|
||||
-static void
|
||||
-__condvar_dec_grefs (pthread_cond_t *cond, unsigned int g, int private)
|
||||
-{
|
||||
- /* Release MO to synchronize-with the acquire load in
|
||||
- __condvar_quiesce_and_switch_g1. */
|
||||
- if (atomic_fetch_add_release (cond->__data.__g_refs + g, -2) == 3)
|
||||
- {
|
||||
+
|
||||
while (1)
|
||||
{
|
||||
+ /* Now wait until a signal is available in our group or it is closed.
|
||||
+ Acquire MO so that if we observe (signals == lowseq) after group
|
||||
+ switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
+ store and will see the prior update of __g1_start done while switching
|
||||
+ groups too. */
|
||||
+ unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
|
||||
@@ -429,7 +427,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
/* If the group is closed already,
|
||||
then this waiter originally had enough extra signals to
|
||||
consume, up until the time its group was closed. */
|
||||
- goto done;
|
||||
+ break;
|
||||
}
|
||||
|
||||
/* If there is an available signal, don't block.
|
||||
@@ -438,8 +436,16 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
G2, but in either case we're allowed to consume the available
|
||||
signal and should not block anymore. */
|
||||
if ((int)(signals - lowseq) >= 2)
|
||||
- break;
|
||||
- /* Clear the wake-up request flag before waking up. We do not need more
|
||||
- than relaxed MO and it doesn't matter if we apply this for an aliased
|
||||
- group because we wake all futex waiters right after clearing the
|
||||
- flag. */
|
||||
- atomic_fetch_and_relaxed (cond->__data.__g_refs + g, ~(unsigned int) 1);
|
||||
- futex_wake (cond->__data.__g_refs + g, INT_MAX, private);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
+ {
|
||||
+ /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
+ iteration we need to see the correct value of g1_start) */
|
||||
+ if (atomic_compare_exchange_weak_acquire (
|
||||
+ cond->__data.__g_signals + g,
|
||||
+ &signals, signals - 2))
|
||||
+ break;
|
||||
+ else
|
||||
+ continue;
|
||||
+ }
|
||||
/* No signals available after spinning, so prepare to block.
|
||||
We first acquire a group reference and use acquire MO for that so
|
||||
that we synchronize with the dummy read-modify-write in
|
||||
@@ -479,21 +485,12 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
the lock during cancellation is not possible. */
|
||||
/* Clean-up for cancellation of waiters waiting for normal signals. We cancel
|
||||
our registration as a waiter, confirm we have woken up, and re-acquire the
|
||||
mutex. */
|
||||
@@ -171,8 +154,6 @@ __condvar_cleanup_waiting (void *arg)
|
||||
pthread_cond_t *cond = cbuffer->cond;
|
||||
unsigned g = cbuffer->wseq & 1;
|
||||
|
||||
- __condvar_dec_grefs (cond, g, cbuffer->private);
|
||||
-
|
||||
__condvar_cancel_waiting (cond, cbuffer->wseq >> 1, g, cbuffer->private);
|
||||
/* FIXME With the current cancellation implementation, it is possible that
|
||||
a thread is cancelled after it has returned from a syscall. This could
|
||||
@@ -327,15 +308,6 @@ __condvar_cleanup_waiting (void *arg)
|
||||
sufficient because if a waiter can see a sufficiently large value, it could
|
||||
have also consume a signal in the waiters group.
|
||||
|
||||
- It is essential that the last field in pthread_cond_t is __g_signals[1]:
|
||||
- The previous condvar used a pointer-sized field in pthread_cond_t, so a
|
||||
- PTHREAD_COND_INITIALIZER from that condvar implementation might only
|
||||
- initialize 4 bytes to zero instead of the 8 bytes we need (i.e., 44 bytes
|
||||
- in total instead of the 48 we need). __g_signals[1] is not accessed before
|
||||
- the first group switch (G2 starts at index 0), which will set its value to
|
||||
- zero after a harmless fetch-or whose return value is ignored. This
|
||||
- effectively completes initialization.
|
||||
-
|
||||
|
||||
Limitations:
|
||||
* This condvar isn't designed to allow for more than
|
||||
@@ -440,21 +412,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
if ((int)(signals - lowseq) >= 2)
|
||||
break;
|
||||
|
||||
- /* No signals available after spinning, so prepare to block.
|
||||
- We first acquire a group reference and use acquire MO for that so
|
||||
- that we synchronize with the dummy read-modify-write in
|
||||
- __condvar_quiesce_and_switch_g1 if we read from that. In turn,
|
||||
- in this case this will make us see the advancement of __g_signals
|
||||
- to the upcoming new g1_start that occurs with a concurrent
|
||||
- attempt to reuse the group's slot.
|
||||
- We use acquire MO for the __g_signals check to make the
|
||||
- __g1_start check work (see spinning above).
|
||||
- Note that the group reference acquisition will not mask the
|
||||
- release MO when decrementing the reference count because we use
|
||||
- an atomic read-modify-write operation and thus extend the release
|
||||
- sequence. */
|
||||
- atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
|
||||
-
|
||||
// Now block.
|
||||
struct _pthread_cleanup_buffer buffer;
|
||||
struct _condvar_cleanup_buffer cbuffer;
|
||||
@@ -471,18 +428,11 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
|
||||
if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
|
||||
{
|
||||
- __condvar_dec_grefs (cond, g, private);
|
||||
- /* If we timed out, we effectively cancel waiting. Note that
|
||||
- we have decremented __g_refs before cancellation, so that a
|
||||
- deadlock between waiting for quiescence of our group in
|
||||
- __condvar_quiesce_and_switch_g1 and us trying to acquire
|
||||
- the lock during cancellation is not possible. */
|
||||
+ /* If we timed out, we effectively cancel waiting. */
|
||||
__condvar_cancel_waiting (cond, seq, g, private);
|
||||
result = err;
|
||||
- goto done;
|
||||
+ break;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
__condvar_dec_grefs (cond, g, private);
|
||||
- else
|
||||
- __condvar_dec_grefs (cond, g, private);
|
||||
|
||||
- /* Reload signals. See above for MO. */
|
||||
- signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
}
|
||||
- }
|
||||
- /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
- iteration we need to see the correct value of g1_start) */
|
||||
- while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
|
||||
- &signals, signals - 2));
|
||||
-
|
||||
- done:
|
||||
/* Reload signals. See above for MO. */
|
||||
signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
diff --git a/nptl/tst-cond22.c b/nptl/tst-cond22.c
|
||||
index 1336e9c7..bdcb45c5 100644
|
||||
--- a/nptl/tst-cond22.c
|
||||
+++ b/nptl/tst-cond22.c
|
||||
@@ -106,13 +106,13 @@ do_test (void)
|
||||
status = 1;
|
||||
}
|
||||
|
||||
/* Confirm that we have been woken. We do that before acquiring the mutex
|
||||
to allow for execution of pthread_cond_destroy while having acquired the
|
||||
- printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n",
|
||||
+ printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u, %u/%u, %u, %u }\n",
|
||||
c.__data.__wseq.__value32.__high,
|
||||
c.__data.__wseq.__value32.__low,
|
||||
c.__data.__g1_start.__value32.__high,
|
||||
c.__data.__g1_start.__value32.__low,
|
||||
- c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
|
||||
- c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
|
||||
+ c.__data.__g_signals[0], c.__data.__g_size[0],
|
||||
+ c.__data.__g_signals[1], c.__data.__g_size[1],
|
||||
c.__data.__g1_orig_size, c.__data.__wrefs);
|
||||
|
||||
if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
|
||||
@@ -152,13 +152,13 @@ do_test (void)
|
||||
status = 1;
|
||||
}
|
||||
|
||||
- printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n",
|
||||
+ printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u, %u/%u, %u, %u }\n",
|
||||
c.__data.__wseq.__value32.__high,
|
||||
c.__data.__wseq.__value32.__low,
|
||||
c.__data.__g1_start.__value32.__high,
|
||||
c.__data.__g1_start.__value32.__low,
|
||||
- c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
|
||||
- c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
|
||||
+ c.__data.__g_signals[0], c.__data.__g_size[0],
|
||||
+ c.__data.__g_signals[1], c.__data.__g_size[1],
|
||||
c.__data.__g1_orig_size, c.__data.__wrefs);
|
||||
|
||||
return status;
|
||||
diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h
|
||||
index 5653507e..6f17afa4 100644
|
||||
--- a/sysdeps/nptl/bits/thread-shared-types.h
|
||||
+++ b/sysdeps/nptl/bits/thread-shared-types.h
|
||||
@@ -95,8 +95,7 @@ struct __pthread_cond_s
|
||||
{
|
||||
__atomic_wide_counter __wseq;
|
||||
__atomic_wide_counter __g1_start;
|
||||
- unsigned int __g_refs[2] __LOCK_ALIGNMENT;
|
||||
- unsigned int __g_size[2];
|
||||
+ unsigned int __g_size[2] __LOCK_ALIGNMENT;
|
||||
unsigned int __g1_orig_size;
|
||||
unsigned int __wrefs;
|
||||
unsigned int __g_signals[2];
|
||||
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
|
||||
index dedad4ec..bbb36540 100644
|
||||
--- a/sysdeps/nptl/pthread.h
|
||||
+++ b/sysdeps/nptl/pthread.h
|
||||
@@ -152,7 +152,7 @@ enum
|
||||
|
||||
|
||||
/* Conditional variable handling. */
|
||||
-#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
|
||||
+#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0} } }
|
||||
|
||||
|
||||
/* Cleanup buffers */
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
||||
@@ -1,166 +1,100 @@
|
||||
From a2faee6d0dac6e5232255da9afda4d9ed6cfb6e5 Mon Sep 17 00:00:00 2001
|
||||
From bbd7c84a1a14bf93bf1e5976d8a1540aabbf901b Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Tue, 17 Jun 2025 01:37:12 -0700
|
||||
Subject: [PATCH] nptl: Fix indentation
|
||||
Date: Tue, 14 Oct 2025 06:19:02 -0700
|
||||
Subject: [PATCH] nptl: Use a single loop in pthread_cond_wait instaed of a
|
||||
nested loop
|
||||
|
||||
In my previous change I turned a nested loop into a simple loop. I'm doing
|
||||
the resulting indentation changes in a separate commit to make the diff on
|
||||
the previous commit easier to review.
|
||||
The loop was a little more complicated than necessary. There was only one
|
||||
break statement out of the inner loop, and the outer loop was nearly empty.
|
||||
So just remove the outer loop, moving its code to the one break statement in
|
||||
the inner loop. This allows us to replace all gotos with break statements.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: 929a4764ac90382616b6a21f099192b2475da674
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=ee6c14ed59d480720721aaacc5fb03213dc153da]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002279.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_wait.c | 132 ++++++++++++++++-----------------------
|
||||
1 file changed, 54 insertions(+), 78 deletions(-)
|
||||
nptl/pthread_cond_wait.c | 41 +++++++++++++++++++---------------------
|
||||
1 file changed, 19 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 5c86880105..104ebd48ca 100644
|
||||
index 8a9219e0..c8c99bbf 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -410,87 +410,63 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
@@ -382,17 +382,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
return err;
|
||||
}
|
||||
|
||||
- /* Now wait until a signal is available in our group or it is closed.
|
||||
- Acquire MO so that if we observe (signals == lowseq) after group
|
||||
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
- store and will see the prior update of __g1_start done while switching
|
||||
- groups too. */
|
||||
- unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
-
|
||||
- while (1)
|
||||
- {
|
||||
- /* Now wait until a signal is available in our group or it is closed.
|
||||
- Acquire MO so that if we observe (signals == lowseq) after group
|
||||
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
- store and will see the prior update of __g1_start done while switching
|
||||
- groups too. */
|
||||
- unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
- uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
- unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
-
|
||||
- if (seq < (g1_start >> 1))
|
||||
- {
|
||||
- /* If the group is closed already,
|
||||
- then this waiter originally had enough extra signals to
|
||||
- consume, up until the time its group was closed. */
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* If there is an available signal, don't block.
|
||||
- If __g1_start has advanced at all, then we must be in G1
|
||||
- by now, perhaps in the process of switching back to an older
|
||||
- G2, but in either case we're allowed to consume the available
|
||||
- signal and should not block anymore. */
|
||||
- if ((int)(signals - lowseq) >= 2)
|
||||
- {
|
||||
- /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
- iteration we need to see the correct value of g1_start) */
|
||||
- if (atomic_compare_exchange_weak_acquire (
|
||||
- cond->__data.__g_signals + g,
|
||||
+ while (1)
|
||||
+ {
|
||||
+ /* Now wait until a signal is available in our group or it is closed.
|
||||
+ Acquire MO so that if we observe (signals == lowseq) after group
|
||||
+ switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
+ store and will see the prior update of __g1_start done while switching
|
||||
+ groups too. */
|
||||
+ unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
+ uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
+ unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
- do
|
||||
- {
|
||||
+
|
||||
+ if (seq < (g1_start >> 1))
|
||||
+ {
|
||||
+ /* If the group is closed already,
|
||||
+ then this waiter originally had enough extra signals to
|
||||
+ consume, up until the time its group was closed. */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* If there is an available signal, don't block.
|
||||
+ If __g1_start has advanced at all, then we must be in G1
|
||||
+ by now, perhaps in the process of switching back to an older
|
||||
+ G2, but in either case we're allowed to consume the available
|
||||
+ signal and should not block anymore. */
|
||||
+ if ((int)(signals - lowseq) >= 2)
|
||||
+ {
|
||||
+ /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
+ iteration we need to see the correct value of g1_start) */
|
||||
+ if (atomic_compare_exchange_weak_acquire (
|
||||
+ cond->__data.__g_signals + g,
|
||||
&signals, signals - 2))
|
||||
- break;
|
||||
- else
|
||||
- continue;
|
||||
- }
|
||||
- /* No signals available after spinning, so prepare to block.
|
||||
- We first acquire a group reference and use acquire MO for that so
|
||||
- that we synchronize with the dummy read-modify-write in
|
||||
- __condvar_quiesce_and_switch_g1 if we read from that. In turn,
|
||||
- in this case this will make us see the advancement of __g_signals
|
||||
- to the upcoming new g1_start that occurs with a concurrent
|
||||
- attempt to reuse the group's slot.
|
||||
- We use acquire MO for the __g_signals check to make the
|
||||
- __g1_start check work (see spinning above).
|
||||
- Note that the group reference acquisition will not mask the
|
||||
- release MO when decrementing the reference count because we use
|
||||
- an atomic read-modify-write operation and thus extend the release
|
||||
- sequence. */
|
||||
- atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
|
||||
while (1)
|
||||
{
|
||||
+ /* Now wait until a signal is available in our group or it is closed.
|
||||
+ Acquire MO so that if we observe (signals == lowseq) after group
|
||||
+ switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
+ store and will see the prior update of __g1_start done while switching
|
||||
+ groups too. */
|
||||
+ unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
|
||||
@@ -401,7 +399,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
/* If the group is closed already,
|
||||
then this waiter originally had enough extra signals to
|
||||
consume, up until the time its group was closed. */
|
||||
- goto done;
|
||||
+ break;
|
||||
}
|
||||
|
||||
/* If there is an available signal, don't block.
|
||||
@@ -410,7 +408,16 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
G2, but in either case we're allowed to consume the available
|
||||
signal and should not block anymore. */
|
||||
if ((int)(signals - lowseq) >= 2)
|
||||
- break;
|
||||
+ {
|
||||
+ /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
+ iteration we need to see the correct value of g1_start) */
|
||||
+ if (atomic_compare_exchange_weak_acquire (
|
||||
+ cond->__data.__g_signals + g,
|
||||
+ &signals, signals - 2))
|
||||
+ break;
|
||||
+ else
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
// Now block.
|
||||
struct _pthread_cleanup_buffer buffer;
|
||||
@@ -431,19 +438,9 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
/* If we timed out, we effectively cancel waiting. */
|
||||
__condvar_cancel_waiting (cond, seq, g, private);
|
||||
result = err;
|
||||
- goto done;
|
||||
+ break;
|
||||
}
|
||||
-
|
||||
- // Now block.
|
||||
- struct _pthread_cleanup_buffer buffer;
|
||||
- struct _condvar_cleanup_buffer cbuffer;
|
||||
- cbuffer.wseq = wseq;
|
||||
- cbuffer.cond = cond;
|
||||
- cbuffer.mutex = mutex;
|
||||
- cbuffer.private = private;
|
||||
- __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
|
||||
-
|
||||
- err = __futex_abstimed_wait_cancelable64 (
|
||||
- cond->__data.__g_signals + g, signals, clockid, abstime, private);
|
||||
-
|
||||
- __pthread_cleanup_pop (&buffer, 0);
|
||||
-
|
||||
- if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
|
||||
- {
|
||||
- __condvar_dec_grefs (cond, g, private);
|
||||
- /* If we timed out, we effectively cancel waiting. Note that
|
||||
- we have decremented __g_refs before cancellation, so that a
|
||||
- deadlock between waiting for quiescence of our group in
|
||||
- __condvar_quiesce_and_switch_g1 and us trying to acquire
|
||||
- the lock during cancellation is not possible. */
|
||||
- __condvar_cancel_waiting (cond, seq, g, private);
|
||||
- result = err;
|
||||
break;
|
||||
- }
|
||||
- else
|
||||
- __condvar_dec_grefs (cond, g, private);
|
||||
-
|
||||
+ else
|
||||
+ continue;
|
||||
- /* Reload signals. See above for MO. */
|
||||
- signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
}
|
||||
+ // Now block.
|
||||
+ struct _pthread_cleanup_buffer buffer;
|
||||
+ struct _condvar_cleanup_buffer cbuffer;
|
||||
+ cbuffer.wseq = wseq;
|
||||
+ cbuffer.cond = cond;
|
||||
+ cbuffer.mutex = mutex;
|
||||
+ cbuffer.private = private;
|
||||
+ __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
|
||||
+
|
||||
+ err = __futex_abstimed_wait_cancelable64 (
|
||||
+ cond->__data.__g_signals + g, signals, clockid, abstime, private);
|
||||
+
|
||||
+ __pthread_cleanup_pop (&buffer, 0);
|
||||
+
|
||||
+ if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
|
||||
+ {
|
||||
+ /* If we timed out, we effectively cancel waiting. */
|
||||
+ __condvar_cancel_waiting (cond, seq, g, private);
|
||||
+ result = err;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
- }
|
||||
- /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
- iteration we need to see the correct value of g1_start) */
|
||||
- while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
|
||||
- &signals, signals - 2));
|
||||
-
|
||||
- done:
|
||||
|
||||
/* Confirm that we have been woken. We do that before acquiring the mutex
|
||||
to allow for execution of pthread_cond_destroy while having acquired the
|
||||
|
||||
@@ -1,160 +1,149 @@
|
||||
From 2a601ac9041e2ca645acad2c174b1c545cfceafe Mon Sep 17 00:00:00 2001
|
||||
From 1077953950d1e8864c63222967141c67f51297f8 Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Tue, 17 Jun 2025 01:53:25 -0700
|
||||
Subject: [PATCH] nptl: rename __condvar_quiesce_and_switch_g1
|
||||
Date: Tue, 14 Oct 2025 06:27:04 -0700
|
||||
Subject: [PATCH] nptl: Fix indentation
|
||||
|
||||
This function no longer waits for threads to leave g1, so rename it to
|
||||
__condvar_switch_g1
|
||||
In my previous change I turned a nested loop into a simple loop. I'm doing
|
||||
the resulting indentation changes in a separate commit to make the diff on
|
||||
the previous commit easier to review.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: ee6c14ed59d480720721aaacc5fb03213dc153da
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=4b79e27a5073c02f6bff9aa8f4791230a0ab1867]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002280.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_broadcast.c | 4 ++--
|
||||
nptl/pthread_cond_common.c | 26 ++++++++++++--------------
|
||||
nptl/pthread_cond_signal.c | 17 ++++++++---------
|
||||
nptl/pthread_cond_wait.c | 9 ++++-----
|
||||
4 files changed, 26 insertions(+), 30 deletions(-)
|
||||
nptl/pthread_cond_wait.c | 110 +++++++++++++++++++--------------------
|
||||
1 file changed, 55 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
|
||||
index 5ae141ac81..a07435589a 100644
|
||||
--- a/nptl/pthread_cond_broadcast.c
|
||||
+++ b/nptl/pthread_cond_broadcast.c
|
||||
@@ -60,7 +60,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
cond->__data.__g_size[g1] << 1);
|
||||
cond->__data.__g_size[g1] = 0;
|
||||
|
||||
- /* We need to wake G1 waiters before we quiesce G1 below. */
|
||||
+ /* We need to wake G1 waiters before we switch G1 below. */
|
||||
/* TODO Only set it if there are indeed futex waiters. We could
|
||||
also try to move this out of the critical section in cases when
|
||||
G2 is empty (and we don't need to quiesce). */
|
||||
@@ -69,7 +69,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
|
||||
/* G1 is complete. Step (2) is next unless there are no waiters in G2, in
|
||||
which case we can stop. */
|
||||
- if (__condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
|
||||
+ if (__condvar_switch_g1 (cond, wseq, &g1, private))
|
||||
{
|
||||
/* Step (3): Send signals to all waiters in the old G2 / new G1. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index f976a533a1..3baac4dabc 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -189,16 +189,15 @@ __condvar_get_private (int flags)
|
||||
return FUTEX_SHARED;
|
||||
}
|
||||
|
||||
-/* This closes G1 (whose index is in G1INDEX), waits for all futex waiters to
|
||||
- leave G1, converts G1 into a fresh G2, and then switches group roles so that
|
||||
- the former G2 becomes the new G1 ending at the current __wseq value when we
|
||||
- eventually make the switch (WSEQ is just an observation of __wseq by the
|
||||
- signaler).
|
||||
+/* This closes G1 (whose index is in G1INDEX), converts G1 into a fresh G2,
|
||||
+ and then switches group roles so that the former G2 becomes the new G1
|
||||
+ ending at the current __wseq value when we eventually make the switch
|
||||
+ (WSEQ is just an observation of __wseq by the signaler).
|
||||
If G2 is empty, it will not switch groups because then it would create an
|
||||
empty G1 which would require switching groups again on the next signal.
|
||||
Returns false iff groups were not switched because G2 was empty. */
|
||||
static bool __attribute__ ((unused))
|
||||
-__condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
+__condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
unsigned int *g1index, int private)
|
||||
{
|
||||
unsigned int g1 = *g1index;
|
||||
@@ -214,8 +213,7 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
+ cond->__data.__g_size[g1 ^ 1]) == 0)
|
||||
return false;
|
||||
|
||||
- /* Now try to close and quiesce G1. We have to consider the following kinds
|
||||
- of waiters:
|
||||
+ /* We have to consider the following kinds of waiters:
|
||||
* Waiters from less recent groups than G1 are not affected because
|
||||
nothing will change for them apart from __g1_start getting larger.
|
||||
* New waiters arriving concurrently with the group switching will all go
|
||||
@@ -223,12 +221,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
are not affected.
|
||||
* Waiters in G1 have already received a signal and been woken. */
|
||||
|
||||
- /* Update __g1_start, which finishes closing this group. The value we add
|
||||
- will never be negative because old_orig_size can only be zero when we
|
||||
- switch groups the first time after a condvar was initialized, in which
|
||||
- case G1 will be at index 1 and we will add a value of 1.
|
||||
- Relaxed MO is fine because the change comes with no additional
|
||||
- constraints that others would have to observe. */
|
||||
+ /* Update __g1_start, which closes this group. The value we add will never
|
||||
+ be negative because old_orig_size can only be zero when we switch groups
|
||||
+ the first time after a condvar was initialized, in which case G1 will be
|
||||
+ at index 1 and we will add a value of 1. Relaxed MO is fine because the
|
||||
+ change comes with no additional constraints that others would have to
|
||||
+ observe. */
|
||||
__condvar_add_g1_start_relaxed (cond,
|
||||
(old_orig_size << 1) + (g1 == 1 ? 1 : - 1));
|
||||
|
||||
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
|
||||
index 14800ba00b..a9bc10dcca 100644
|
||||
--- a/nptl/pthread_cond_signal.c
|
||||
+++ b/nptl/pthread_cond_signal.c
|
||||
@@ -69,18 +69,17 @@ ___pthread_cond_signal (pthread_cond_t *cond)
|
||||
bool do_futex_wake = false;
|
||||
|
||||
/* If G1 is still receiving signals, we put the signal there. If not, we
|
||||
- check if G2 has waiters, and if so, quiesce and switch G1 to the former
|
||||
- G2; if this results in a new G1 with waiters (G2 might have cancellations
|
||||
- already, see __condvar_quiesce_and_switch_g1), we put the signal in the
|
||||
- new G1. */
|
||||
+ check if G2 has waiters, and if so, switch G1 to the former G2; if this
|
||||
+ results in a new G1 with waiters (G2 might have cancellations already,
|
||||
+ see __condvar_switch_g1), we put the signal in the new G1. */
|
||||
if ((cond->__data.__g_size[g1] != 0)
|
||||
- || __condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
|
||||
+ || __condvar_switch_g1 (cond, wseq, &g1, private))
|
||||
{
|
||||
/* Add a signal. Relaxed MO is fine because signaling does not need to
|
||||
- establish a happens-before relation (see above). We do not mask the
|
||||
- release-MO store when initializing a group in
|
||||
- __condvar_quiesce_and_switch_g1 because we use an atomic
|
||||
- read-modify-write and thus extend that store's release sequence. */
|
||||
+ establish a happens-before relation (see above). We do not mask the
|
||||
+ release-MO store when initializing a group in __condvar_switch_g1
|
||||
+ because we use an atomic read-modify-write and thus extend that
|
||||
+ store's release sequence. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
|
||||
cond->__data.__g_size[g1]--;
|
||||
/* TODO Only set it if there are indeed futex waiters. */
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 104ebd48ca..bb46f3605d 100644
|
||||
index c8c99bbf..adf26a80 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -382,8 +382,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
because we do not need to establish any happens-before relation with
|
||||
signalers (see __pthread_cond_signal); modification order alone
|
||||
establishes a total order of waiters/signals. We do need acquire MO
|
||||
- to synchronize with group reinitialization in
|
||||
- __condvar_quiesce_and_switch_g1. */
|
||||
+ to synchronize with group reinitialization in __condvar_switch_g1. */
|
||||
uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);
|
||||
/* Find our group's index. We always go into what was G2 when we acquired
|
||||
our position. */
|
||||
@@ -414,9 +413,9 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
{
|
||||
/* Now wait until a signal is available in our group or it is closed.
|
||||
Acquire MO so that if we observe (signals == lowseq) after group
|
||||
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
- store and will see the prior update of __g1_start done while switching
|
||||
- groups too. */
|
||||
+ switching in __condvar_switch_g1, we synchronize with that store and
|
||||
+ will see the prior update of __g1_start done while switching groups
|
||||
+ too. */
|
||||
unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
@@ -383,65 +383,65 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
}
|
||||
|
||||
|
||||
- while (1)
|
||||
- {
|
||||
- /* Now wait until a signal is available in our group or it is closed.
|
||||
- Acquire MO so that if we observe (signals == lowseq) after group
|
||||
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
- store and will see the prior update of __g1_start done while switching
|
||||
- groups too. */
|
||||
- unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
- uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
- unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
-
|
||||
- if (seq < (g1_start >> 1))
|
||||
- {
|
||||
- /* If the group is closed already,
|
||||
- then this waiter originally had enough extra signals to
|
||||
- consume, up until the time its group was closed. */
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* If there is an available signal, don't block.
|
||||
- If __g1_start has advanced at all, then we must be in G1
|
||||
- by now, perhaps in the process of switching back to an older
|
||||
- G2, but in either case we're allowed to consume the available
|
||||
- signal and should not block anymore. */
|
||||
- if ((int)(signals - lowseq) >= 2)
|
||||
- {
|
||||
- /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
- iteration we need to see the correct value of g1_start) */
|
||||
- if (atomic_compare_exchange_weak_acquire (
|
||||
- cond->__data.__g_signals + g,
|
||||
+ while (1)
|
||||
+ {
|
||||
+ /* Now wait until a signal is available in our group or it is closed.
|
||||
+ Acquire MO so that if we observe (signals == lowseq) after group
|
||||
+ switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
+ store and will see the prior update of __g1_start done while switching
|
||||
+ groups too. */
|
||||
+ unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
+ uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
+ unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
+
|
||||
+ if (seq < (g1_start >> 1))
|
||||
+ {
|
||||
+ /* If the group is closed already,
|
||||
+ then this waiter originally had enough extra signals to
|
||||
+ consume, up until the time its group was closed. */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* If there is an available signal, don't block.
|
||||
+ If __g1_start has advanced at all, then we must be in G1
|
||||
+ by now, perhaps in the process of switching back to an older
|
||||
+ G2, but in either case we're allowed to consume the available
|
||||
+ signal and should not block anymore. */
|
||||
+ if ((int)(signals - lowseq) >= 2)
|
||||
+ {
|
||||
+ /* Try to grab a signal. See above for MO. (if we do another loop
|
||||
+ iteration we need to see the correct value of g1_start) */
|
||||
+ if (atomic_compare_exchange_weak_acquire (
|
||||
+ cond->__data.__g_signals + g,
|
||||
&signals, signals - 2))
|
||||
- break;
|
||||
- else
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- // Now block.
|
||||
- struct _pthread_cleanup_buffer buffer;
|
||||
- struct _condvar_cleanup_buffer cbuffer;
|
||||
- cbuffer.wseq = wseq;
|
||||
- cbuffer.cond = cond;
|
||||
- cbuffer.mutex = mutex;
|
||||
- cbuffer.private = private;
|
||||
- __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
|
||||
-
|
||||
- err = __futex_abstimed_wait_cancelable64 (
|
||||
- cond->__data.__g_signals + g, signals, clockid, abstime, private);
|
||||
-
|
||||
- __pthread_cleanup_pop (&buffer, 0);
|
||||
-
|
||||
- if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
|
||||
- {
|
||||
- /* If we timed out, we effectively cancel waiting. */
|
||||
- __condvar_cancel_waiting (cond, seq, g, private);
|
||||
- result = err;
|
||||
break;
|
||||
- }
|
||||
+ else
|
||||
+ continue;
|
||||
}
|
||||
|
||||
+ // Now block.
|
||||
+ struct _pthread_cleanup_buffer buffer;
|
||||
+ struct _condvar_cleanup_buffer cbuffer;
|
||||
+ cbuffer.wseq = wseq;
|
||||
+ cbuffer.cond = cond;
|
||||
+ cbuffer.mutex = mutex;
|
||||
+ cbuffer.private = private;
|
||||
+ __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
|
||||
+
|
||||
+ err = __futex_abstimed_wait_cancelable64 (
|
||||
+ cond->__data.__g_signals + g, signals, clockid, abstime, private);
|
||||
+
|
||||
+ __pthread_cleanup_pop (&buffer, 0);
|
||||
+
|
||||
+ if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
|
||||
+ {
|
||||
+ /* If we timed out, we effectively cancel waiting. */
|
||||
+ __condvar_cancel_waiting (cond, seq, g, private);
|
||||
+ result = err;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Confirm that we have been woken. We do that before acquiring the mutex
|
||||
to allow for execution of pthread_cond_destroy while having acquired the
|
||||
mutex. */
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
||||
@@ -1,192 +1,161 @@
|
||||
From fc074de88796eb2036fbe9bade638e00adfd5cb2 Mon Sep 17 00:00:00 2001
|
||||
From 20d84dfa0b9a32f88259269bbeaae588744ae4ae Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Tue, 17 Jun 2025 02:08:36 -0700
|
||||
Subject: [PATCH] nptl: Use all of g1_start and g_signals
|
||||
Date: Tue, 14 Oct 2025 06:33:50 -0700
|
||||
Subject: [PATCH] nptl: rename __condvar_quiesce_and_switch_g1
|
||||
|
||||
The LSB of g_signals was unused. The LSB of g1_start was used to indicate
|
||||
which group is G2. This was used to always go to sleep in pthread_cond_wait
|
||||
if a waiter is in G2. A comment earlier in the file says that this is not
|
||||
correct to do:
|
||||
|
||||
"Waiters cannot determine whether they are currently in G2 or G1 -- but they
|
||||
do not have to because all they are interested in is whether there are
|
||||
available signals"
|
||||
|
||||
I either would have had to update the comment, or get rid of the check. I
|
||||
chose to get rid of the check. In fact I don't quite know why it was there.
|
||||
There will never be available signals for group G2, so we didn't need the
|
||||
special case. Even if there were, this would just be a spurious wake. This
|
||||
might have caught some cases where the count has wrapped around, but it
|
||||
wouldn't reliably do that, (and even if it did, why would you want to force a
|
||||
sleep in that case?) and we don't support that many concurrent waiters
|
||||
anyway. Getting rid of it allows us to use one more bit, making us more
|
||||
robust to wraparound.
|
||||
This function no longer waits for threads to leave g1, so rename it to
|
||||
__condvar_switch_g1
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: 4b79e27a5073c02f6bff9aa8f4791230a0ab1867
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://sourceware.org/git/?p=glibc.git;a=commit;h=91bb902f58264a2fd50fbce8f39a9a290dd23706]
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002281.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_broadcast.c | 4 ++--
|
||||
nptl/pthread_cond_common.c | 26 ++++++++++----------------
|
||||
nptl/pthread_cond_signal.c | 2 +-
|
||||
nptl/pthread_cond_wait.c | 14 +++++---------
|
||||
4 files changed, 18 insertions(+), 28 deletions(-)
|
||||
nptl/pthread_cond_common.c | 26 ++++++++++++--------------
|
||||
nptl/pthread_cond_signal.c | 17 ++++++++---------
|
||||
nptl/pthread_cond_wait.c | 9 ++++-----
|
||||
4 files changed, 26 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
|
||||
index a07435589a..ef0943cdc5 100644
|
||||
index 5ae141ac..a0743558 100644
|
||||
--- a/nptl/pthread_cond_broadcast.c
|
||||
+++ b/nptl/pthread_cond_broadcast.c
|
||||
@@ -57,7 +57,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
{
|
||||
/* Add as many signals as the remaining size of the group. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
|
||||
- cond->__data.__g_size[g1] << 1);
|
||||
+ cond->__data.__g_size[g1]);
|
||||
@@ -60,7 +60,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
cond->__data.__g_size[g1] << 1);
|
||||
cond->__data.__g_size[g1] = 0;
|
||||
|
||||
/* We need to wake G1 waiters before we switch G1 below. */
|
||||
@@ -73,7 +73,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
- /* We need to wake G1 waiters before we quiesce G1 below. */
|
||||
+ /* We need to wake G1 waiters before we switch G1 below. */
|
||||
/* TODO Only set it if there are indeed futex waiters. We could
|
||||
also try to move this out of the critical section in cases when
|
||||
G2 is empty (and we don't need to quiesce). */
|
||||
@@ -69,7 +69,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
|
||||
/* G1 is complete. Step (2) is next unless there are no waiters in G2, in
|
||||
which case we can stop. */
|
||||
- if (__condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
|
||||
+ if (__condvar_switch_g1 (cond, wseq, &g1, private))
|
||||
{
|
||||
/* Step (3): Send signals to all waiters in the old G2 / new G1. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
|
||||
- cond->__data.__g_size[g1] << 1);
|
||||
+ cond->__data.__g_size[g1]);
|
||||
cond->__data.__g_size[g1] = 0;
|
||||
/* TODO Only set it if there are indeed futex waiters. */
|
||||
do_futex_wake = true;
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index 3baac4dabc..e48f914321 100644
|
||||
index f976a533..3baac4da 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -208,9 +208,9 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
behavior.
|
||||
Note that this works correctly for a zero-initialized condvar too. */
|
||||
unsigned int old_orig_size = __condvar_get_orig_size (cond);
|
||||
- uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
|
||||
- if (((unsigned) (wseq - old_g1_start - old_orig_size)
|
||||
- + cond->__data.__g_size[g1 ^ 1]) == 0)
|
||||
+ uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
+ uint64_t new_g1_start = old_g1_start + old_orig_size;
|
||||
+ if (((unsigned) (wseq - new_g1_start) + cond->__data.__g_size[g1 ^ 1]) == 0)
|
||||
@@ -189,16 +189,15 @@ __condvar_get_private (int flags)
|
||||
return FUTEX_SHARED;
|
||||
}
|
||||
|
||||
-/* This closes G1 (whose index is in G1INDEX), waits for all futex waiters to
|
||||
- leave G1, converts G1 into a fresh G2, and then switches group roles so that
|
||||
- the former G2 becomes the new G1 ending at the current __wseq value when we
|
||||
- eventually make the switch (WSEQ is just an observation of __wseq by the
|
||||
- signaler).
|
||||
+/* This closes G1 (whose index is in G1INDEX), converts G1 into a fresh G2,
|
||||
+ and then switches group roles so that the former G2 becomes the new G1
|
||||
+ ending at the current __wseq value when we eventually make the switch
|
||||
+ (WSEQ is just an observation of __wseq by the signaler).
|
||||
If G2 is empty, it will not switch groups because then it would create an
|
||||
empty G1 which would require switching groups again on the next signal.
|
||||
Returns false iff groups were not switched because G2 was empty. */
|
||||
static bool __attribute__ ((unused))
|
||||
-__condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
+__condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
unsigned int *g1index, int private)
|
||||
{
|
||||
unsigned int g1 = *g1index;
|
||||
@@ -214,8 +213,7 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
+ cond->__data.__g_size[g1 ^ 1]) == 0)
|
||||
return false;
|
||||
|
||||
/* We have to consider the following kinds of waiters:
|
||||
@@ -221,16 +221,10 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
- /* Now try to close and quiesce G1. We have to consider the following kinds
|
||||
- of waiters:
|
||||
+ /* We have to consider the following kinds of waiters:
|
||||
* Waiters from less recent groups than G1 are not affected because
|
||||
nothing will change for them apart from __g1_start getting larger.
|
||||
* New waiters arriving concurrently with the group switching will all go
|
||||
@@ -223,12 +221,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
are not affected.
|
||||
* Waiters in G1 have already received a signal and been woken. */
|
||||
|
||||
- /* Update __g1_start, which closes this group. The value we add will never
|
||||
- be negative because old_orig_size can only be zero when we switch groups
|
||||
- the first time after a condvar was initialized, in which case G1 will be
|
||||
- at index 1 and we will add a value of 1. Relaxed MO is fine because the
|
||||
- change comes with no additional constraints that others would have to
|
||||
- observe. */
|
||||
- __condvar_add_g1_start_relaxed (cond,
|
||||
- (old_orig_size << 1) + (g1 == 1 ? 1 : - 1));
|
||||
-
|
||||
- unsigned int lowseq = ((old_g1_start + old_orig_size) << 1) & ~1U;
|
||||
+ /* Update __g1_start, which closes this group. Relaxed MO is fine because
|
||||
+ the change comes with no additional constraints that others would have
|
||||
+ to observe. */
|
||||
+ __condvar_add_g1_start_relaxed (cond, old_orig_size);
|
||||
- /* Update __g1_start, which finishes closing this group. The value we add
|
||||
- will never be negative because old_orig_size can only be zero when we
|
||||
- switch groups the first time after a condvar was initialized, in which
|
||||
- case G1 will be at index 1 and we will add a value of 1.
|
||||
- Relaxed MO is fine because the change comes with no additional
|
||||
- constraints that others would have to observe. */
|
||||
+ /* Update __g1_start, which closes this group. The value we add will never
|
||||
+ be negative because old_orig_size can only be zero when we switch groups
|
||||
+ the first time after a condvar was initialized, in which case G1 will be
|
||||
+ at index 1 and we will add a value of 1. Relaxed MO is fine because the
|
||||
+ change comes with no additional constraints that others would have to
|
||||
+ observe. */
|
||||
__condvar_add_g1_start_relaxed (cond,
|
||||
(old_orig_size << 1) + (g1 == 1 ? 1 : - 1));
|
||||
|
||||
/* At this point, the old G1 is now a valid new G2 (but not in use yet).
|
||||
No old waiter can neither grab a signal nor acquire a reference without
|
||||
@@ -242,13 +236,13 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
g1 ^= 1;
|
||||
*g1index ^= 1;
|
||||
|
||||
- /* Now advance the new G1 g_signals to the new lowseq, giving it
|
||||
+ /* Now advance the new G1 g_signals to the new g1_start, giving it
|
||||
an effective signal count of 0 to start. */
|
||||
- atomic_store_release (cond->__data.__g_signals + g1, lowseq);
|
||||
+ atomic_store_release (cond->__data.__g_signals + g1, (unsigned)new_g1_start);
|
||||
|
||||
/* These values are just observed by signalers, and thus protected by the
|
||||
lock. */
|
||||
- unsigned int orig_size = wseq - (old_g1_start + old_orig_size);
|
||||
+ unsigned int orig_size = wseq - new_g1_start;
|
||||
__condvar_set_orig_size (cond, orig_size);
|
||||
/* Use and addition to not loose track of cancellations in what was
|
||||
previously G2. */
|
||||
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
|
||||
index a9bc10dcca..07427369aa 100644
|
||||
index 14800ba0..a9bc10dc 100644
|
||||
--- a/nptl/pthread_cond_signal.c
|
||||
+++ b/nptl/pthread_cond_signal.c
|
||||
@@ -80,7 +80,7 @@ ___pthread_cond_signal (pthread_cond_t *cond)
|
||||
release-MO store when initializing a group in __condvar_switch_g1
|
||||
because we use an atomic read-modify-write and thus extend that
|
||||
store's release sequence. */
|
||||
- atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
|
||||
+ atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 1);
|
||||
@@ -69,18 +69,17 @@ ___pthread_cond_signal (pthread_cond_t *cond)
|
||||
bool do_futex_wake = false;
|
||||
|
||||
/* If G1 is still receiving signals, we put the signal there. If not, we
|
||||
- check if G2 has waiters, and if so, quiesce and switch G1 to the former
|
||||
- G2; if this results in a new G1 with waiters (G2 might have cancellations
|
||||
- already, see __condvar_quiesce_and_switch_g1), we put the signal in the
|
||||
- new G1. */
|
||||
+ check if G2 has waiters, and if so, switch G1 to the former G2; if this
|
||||
+ results in a new G1 with waiters (G2 might have cancellations already,
|
||||
+ see __condvar_switch_g1), we put the signal in the new G1. */
|
||||
if ((cond->__data.__g_size[g1] != 0)
|
||||
- || __condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
|
||||
+ || __condvar_switch_g1 (cond, wseq, &g1, private))
|
||||
{
|
||||
/* Add a signal. Relaxed MO is fine because signaling does not need to
|
||||
- establish a happens-before relation (see above). We do not mask the
|
||||
- release-MO store when initializing a group in
|
||||
- __condvar_quiesce_and_switch_g1 because we use an atomic
|
||||
- read-modify-write and thus extend that store's release sequence. */
|
||||
+ establish a happens-before relation (see above). We do not mask the
|
||||
+ release-MO store when initializing a group in __condvar_switch_g1
|
||||
+ because we use an atomic read-modify-write and thus extend that
|
||||
+ store's release sequence. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
|
||||
cond->__data.__g_size[g1]--;
|
||||
/* TODO Only set it if there are indeed futex waiters. */
|
||||
do_futex_wake = true;
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index bb46f3605d..430cbe8a35 100644
|
||||
index adf26a80..40a74342 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -84,7 +84,7 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
|
||||
not hold a reference on the group. */
|
||||
__condvar_acquire_lock (cond, private);
|
||||
|
||||
- uint64_t g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
|
||||
+ uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
if (g1_start > seq)
|
||||
@@ -354,8 +354,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
because we do not need to establish any happens-before relation with
|
||||
signalers (see __pthread_cond_signal); modification order alone
|
||||
establishes a total order of waiters/signals. We do need acquire MO
|
||||
- to synchronize with group reinitialization in
|
||||
- __condvar_quiesce_and_switch_g1. */
|
||||
+ to synchronize with group reinitialization in __condvar_switch_g1. */
|
||||
uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);
|
||||
/* Find our group's index. We always go into what was G2 when we acquired
|
||||
our position. */
|
||||
@@ -387,9 +386,9 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
{
|
||||
/* Our group is closed, so someone provided enough signals for it.
|
||||
@@ -278,7 +278,6 @@ __condvar_cleanup_waiting (void *arg)
|
||||
* Waiters fetch-add while having acquire the mutex associated with the
|
||||
condvar. Signalers load it and fetch-xor it concurrently.
|
||||
__g1_start: Starting position of G1 (inclusive)
|
||||
- * LSB is index of current G2.
|
||||
* Modified by signalers while having acquired the condvar-internal lock
|
||||
and observed concurrently by waiters.
|
||||
__g1_orig_size: Initial size of G1
|
||||
@@ -299,11 +298,9 @@ __condvar_cleanup_waiting (void *arg)
|
||||
* Reference count used by waiters concurrently with signalers that have
|
||||
acquired the condvar-internal lock.
|
||||
__g_signals: The number of signals that can still be consumed, relative to
|
||||
- the current g1_start. (i.e. bits 31 to 1 of __g_signals are bits
|
||||
- 31 to 1 of g1_start with the signal count added)
|
||||
+ the current g1_start. (i.e. g1_start with the signal count added)
|
||||
* Used as a futex word by waiters. Used concurrently by waiters and
|
||||
signalers.
|
||||
- * LSB is currently reserved and 0.
|
||||
__g_size: Waiters remaining in this group (i.e., which have not been
|
||||
signaled yet.
|
||||
* Accessed by signalers and waiters that cancel waiting (both do so only
|
||||
@@ -418,9 +415,8 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
too. */
|
||||
/* Now wait until a signal is available in our group or it is closed.
|
||||
Acquire MO so that if we observe (signals == lowseq) after group
|
||||
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
|
||||
- store and will see the prior update of __g1_start done while switching
|
||||
- groups too. */
|
||||
+ switching in __condvar_switch_g1, we synchronize with that store and
|
||||
+ will see the prior update of __g1_start done while switching groups
|
||||
+ too. */
|
||||
unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
- unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
|
||||
- if (seq < (g1_start >> 1))
|
||||
+ if (seq < g1_start)
|
||||
{
|
||||
/* If the group is closed already,
|
||||
then this waiter originally had enough extra signals to
|
||||
@@ -433,13 +429,13 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
by now, perhaps in the process of switching back to an older
|
||||
G2, but in either case we're allowed to consume the available
|
||||
signal and should not block anymore. */
|
||||
- if ((int)(signals - lowseq) >= 2)
|
||||
+ if ((int)(signals - (unsigned int)g1_start) > 0)
|
||||
{
|
||||
/* Try to grab a signal. See above for MO. (if we do another loop
|
||||
iteration we need to see the correct value of g1_start) */
|
||||
if (atomic_compare_exchange_weak_acquire (
|
||||
cond->__data.__g_signals + g,
|
||||
- &signals, signals - 2))
|
||||
+ &signals, signals - 1))
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
||||
193
meta/recipes-core/glibc/glibc/0026-PR25847-9.patch
Normal file
193
meta/recipes-core/glibc/glibc/0026-PR25847-9.patch
Normal file
@@ -0,0 +1,193 @@
|
||||
From c2677e68956bb9677d8de4ee6c5341b1a744d490 Mon Sep 17 00:00:00 2001
|
||||
From: Malte Skarupke <malteskarupke@fastmail.fm>
|
||||
Date: Tue, 14 Oct 2025 06:40:57 -0700
|
||||
Subject: [PATCH] nptl: Use all of g1_start and g_signals
|
||||
|
||||
The LSB of g_signals was unused. The LSB of g1_start was used to indicate
|
||||
which group is G2. This was used to always go to sleep in pthread_cond_wait
|
||||
if a waiter is in G2. A comment earlier in the file says that this is not
|
||||
correct to do:
|
||||
|
||||
"Waiters cannot determine whether they are currently in G2 or G1 -- but they
|
||||
do not have to because all they are interested in is whether there are
|
||||
available signals"
|
||||
|
||||
I either would have had to update the comment, or get rid of the check. I
|
||||
chose to get rid of the check. In fact I don't quite know why it was there.
|
||||
There will never be available signals for group G2, so we didn't need the
|
||||
special case. Even if there were, this would just be a spurious wake. This
|
||||
might have caught some cases where the count has wrapped around, but it
|
||||
wouldn't reliably do that, (and even if it did, why would you want to force a
|
||||
sleep in that case?) and we don't support that many concurrent waiters
|
||||
anyway. Getting rid of it allows us to use one more bit, making us more
|
||||
robust to wraparound.
|
||||
|
||||
The following commits have been cherry-picked from Glibc master branch:
|
||||
Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847
|
||||
commit: 91bb902f58264a2fd50fbce8f39a9a290dd23706
|
||||
|
||||
Upstream-Status: Submitted
|
||||
[https://sourceware.org/pipermail/libc-stable/2025-July/002283.html]
|
||||
|
||||
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
|
||||
---
|
||||
nptl/pthread_cond_broadcast.c | 4 ++--
|
||||
nptl/pthread_cond_common.c | 26 ++++++++++----------------
|
||||
nptl/pthread_cond_signal.c | 2 +-
|
||||
nptl/pthread_cond_wait.c | 14 +++++---------
|
||||
4 files changed, 18 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
|
||||
index a0743558..ef0943cd 100644
|
||||
--- a/nptl/pthread_cond_broadcast.c
|
||||
+++ b/nptl/pthread_cond_broadcast.c
|
||||
@@ -57,7 +57,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
{
|
||||
/* Add as many signals as the remaining size of the group. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
|
||||
- cond->__data.__g_size[g1] << 1);
|
||||
+ cond->__data.__g_size[g1]);
|
||||
cond->__data.__g_size[g1] = 0;
|
||||
|
||||
/* We need to wake G1 waiters before we switch G1 below. */
|
||||
@@ -73,7 +73,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
{
|
||||
/* Step (3): Send signals to all waiters in the old G2 / new G1. */
|
||||
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
|
||||
- cond->__data.__g_size[g1] << 1);
|
||||
+ cond->__data.__g_size[g1]);
|
||||
cond->__data.__g_size[g1] = 0;
|
||||
/* TODO Only set it if there are indeed futex waiters. */
|
||||
do_futex_wake = true;
|
||||
diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c
|
||||
index 3baac4da..e48f9143 100644
|
||||
--- a/nptl/pthread_cond_common.c
|
||||
+++ b/nptl/pthread_cond_common.c
|
||||
@@ -208,9 +208,9 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
behavior.
|
||||
Note that this works correctly for a zero-initialized condvar too. */
|
||||
unsigned int old_orig_size = __condvar_get_orig_size (cond);
|
||||
- uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
|
||||
- if (((unsigned) (wseq - old_g1_start - old_orig_size)
|
||||
- + cond->__data.__g_size[g1 ^ 1]) == 0)
|
||||
+ uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
+ uint64_t new_g1_start = old_g1_start + old_orig_size;
|
||||
+ if (((unsigned) (wseq - new_g1_start) + cond->__data.__g_size[g1 ^ 1]) == 0)
|
||||
return false;
|
||||
|
||||
/* We have to consider the following kinds of waiters:
|
||||
@@ -221,16 +221,10 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
are not affected.
|
||||
* Waiters in G1 have already received a signal and been woken. */
|
||||
|
||||
- /* Update __g1_start, which closes this group. The value we add will never
|
||||
- be negative because old_orig_size can only be zero when we switch groups
|
||||
- the first time after a condvar was initialized, in which case G1 will be
|
||||
- at index 1 and we will add a value of 1. Relaxed MO is fine because the
|
||||
- change comes with no additional constraints that others would have to
|
||||
- observe. */
|
||||
- __condvar_add_g1_start_relaxed (cond,
|
||||
- (old_orig_size << 1) + (g1 == 1 ? 1 : - 1));
|
||||
-
|
||||
- unsigned int lowseq = ((old_g1_start + old_orig_size) << 1) & ~1U;
|
||||
+ /* Update __g1_start, which closes this group. Relaxed MO is fine because
|
||||
+ the change comes with no additional constraints that others would have
|
||||
+ to observe. */
|
||||
+ __condvar_add_g1_start_relaxed (cond, old_orig_size);
|
||||
|
||||
/* At this point, the old G1 is now a valid new G2 (but not in use yet).
|
||||
No old waiter can neither grab a signal nor acquire a reference without
|
||||
@@ -242,13 +236,13 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
|
||||
g1 ^= 1;
|
||||
*g1index ^= 1;
|
||||
|
||||
- /* Now advance the new G1 g_signals to the new lowseq, giving it
|
||||
+ /* Now advance the new G1 g_signals to the new g1_start, giving it
|
||||
an effective signal count of 0 to start. */
|
||||
- atomic_store_release (cond->__data.__g_signals + g1, lowseq);
|
||||
+ atomic_store_release (cond->__data.__g_signals + g1, (unsigned)new_g1_start);
|
||||
|
||||
/* These values are just observed by signalers, and thus protected by the
|
||||
lock. */
|
||||
- unsigned int orig_size = wseq - (old_g1_start + old_orig_size);
|
||||
+ unsigned int orig_size = wseq - new_g1_start;
|
||||
__condvar_set_orig_size (cond, orig_size);
|
||||
/* Use and addition to not loose track of cancellations in what was
|
||||
previously G2. */
|
||||
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
|
||||
index a9bc10dc..07427369 100644
|
||||
--- a/nptl/pthread_cond_signal.c
|
||||
+++ b/nptl/pthread_cond_signal.c
|
||||
@@ -80,7 +80,7 @@ ___pthread_cond_signal (pthread_cond_t *cond)
|
||||
release-MO store when initializing a group in __condvar_switch_g1
|
||||
because we use an atomic read-modify-write and thus extend that
|
||||
store's release sequence. */
|
||||
- atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
|
||||
+ atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 1);
|
||||
cond->__data.__g_size[g1]--;
|
||||
/* TODO Only set it if there are indeed futex waiters. */
|
||||
do_futex_wake = true;
|
||||
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
|
||||
index 40a74342..d7e073ab 100644
|
||||
--- a/nptl/pthread_cond_wait.c
|
||||
+++ b/nptl/pthread_cond_wait.c
|
||||
@@ -84,7 +84,7 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
|
||||
not hold a reference on the group. */
|
||||
__condvar_acquire_lock (cond, private);
|
||||
|
||||
- uint64_t g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
|
||||
+ uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
if (g1_start > seq)
|
||||
{
|
||||
/* Our group is closed, so someone provided enough signals for it.
|
||||
@@ -259,7 +259,6 @@ __condvar_cleanup_waiting (void *arg)
|
||||
* Waiters fetch-add while having acquire the mutex associated with the
|
||||
condvar. Signalers load it and fetch-xor it concurrently.
|
||||
__g1_start: Starting position of G1 (inclusive)
|
||||
- * LSB is index of current G2.
|
||||
* Modified by signalers while having acquired the condvar-internal lock
|
||||
and observed concurrently by waiters.
|
||||
__g1_orig_size: Initial size of G1
|
||||
@@ -280,11 +279,9 @@ __condvar_cleanup_waiting (void *arg)
|
||||
* Reference count used by waiters concurrently with signalers that have
|
||||
acquired the condvar-internal lock.
|
||||
__g_signals: The number of signals that can still be consumed, relative to
|
||||
- the current g1_start. (i.e. bits 31 to 1 of __g_signals are bits
|
||||
- 31 to 1 of g1_start with the signal count added)
|
||||
+ the current g1_start. (i.e. g1_start with the signal count added)
|
||||
* Used as a futex word by waiters. Used concurrently by waiters and
|
||||
signalers.
|
||||
- * LSB is currently reserved and 0.
|
||||
__g_size: Waiters remaining in this group (i.e., which have not been
|
||||
signaled yet.
|
||||
* Accessed by signalers and waiters that cancel waiting (both do so only
|
||||
@@ -391,9 +388,8 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
too. */
|
||||
unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
|
||||
uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
|
||||
- unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U;
|
||||
|
||||
- if (seq < (g1_start >> 1))
|
||||
+ if (seq < g1_start)
|
||||
{
|
||||
/* If the group is closed already,
|
||||
then this waiter originally had enough extra signals to
|
||||
@@ -406,13 +402,13 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
by now, perhaps in the process of switching back to an older
|
||||
G2, but in either case we're allowed to consume the available
|
||||
signal and should not block anymore. */
|
||||
- if ((int)(signals - lowseq) >= 2)
|
||||
+ if ((int)(signals - (unsigned int)g1_start) > 0)
|
||||
{
|
||||
/* Try to grab a signal. See above for MO. (if we do another loop
|
||||
iteration we need to see the correct value of g1_start) */
|
||||
if (atomic_compare_exchange_weak_acquire (
|
||||
cond->__data.__g_signals + g,
|
||||
- &signals, signals - 2))
|
||||
+ &signals, signals - 1))
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -70,6 +70,8 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
|
||||
file://0026-PR25847-6.patch \
|
||||
file://0026-PR25847-7.patch \
|
||||
file://0026-PR25847-8.patch \
|
||||
file://0026-PR25847-9.patch \
|
||||
file://0026-PR25847-10.patch \
|
||||
\
|
||||
file://0001-Revert-Linux-Implement-a-useful-version-of-_startup_.patch \
|
||||
file://0002-get_nscd_addresses-Fix-subscript-typos-BZ-29605.patch \
|
||||
|
||||
@@ -24,7 +24,7 @@ IMAGE_FSTYPES = "wic.vmdk wic.vhd wic.vhdx"
|
||||
|
||||
inherit core-image setuptools3
|
||||
|
||||
SRCREV ?= "49e837cefaa0d1844b32ff788c6e9de246a3a739"
|
||||
SRCREV ?= "cb1206dd8460f2701df03b1e9224825bad23a90e"
|
||||
SRC_URI = "git://git.yoctoproject.org/poky;branch=kirkstone \
|
||||
file://Yocto_Build_Appliance.vmx \
|
||||
file://Yocto_Build_Appliance.vmxf \
|
||||
|
||||
802
meta/recipes-core/libxml/libxml2/CVE-2025-7425.patch
Normal file
802
meta/recipes-core/libxml/libxml2/CVE-2025-7425.patch
Normal file
@@ -0,0 +1,802 @@
|
||||
From 87786d6200ae1f5ac98d21f04d451e17ff25a216 Mon Sep 17 00:00:00 2001
|
||||
From: David Kilzer <ddkilzer@apple.com>
|
||||
Reviewed-By: Aron Xu <aron@debian.org>
|
||||
Date: Mon, 23 Jun 2025 14:41:56 -0700
|
||||
Subject: [PATCH] libxslt: heap-use-after-free in xmlFreeID caused by `atype`
|
||||
corruption
|
||||
|
||||
* include/libxml/tree.h:
|
||||
(XML_ATTR_CLEAR_ATYPE): Add.
|
||||
(XML_ATTR_GET_ATYPE): Add.
|
||||
(XML_ATTR_SET_ATYPE): Add.
|
||||
(XML_NODE_ADD_EXTRA): Add.
|
||||
(XML_NODE_CLEAR_EXTRA): Add.
|
||||
(XML_NODE_GET_EXTRA): Add.
|
||||
(XML_NODE_SET_EXTRA): Add.
|
||||
(XML_DOC_ADD_PROPERTIES): Add.
|
||||
(XML_DOC_CLEAR_PROPERTIES): Add.
|
||||
(XML_DOC_GET_PROPERTIES): Add.
|
||||
(XML_DOC_SET_PROPERTIES): Add.
|
||||
- Add macros for accessing fields with upper bits that may be set by
|
||||
libxslt.
|
||||
|
||||
* HTMLparser.c:
|
||||
(htmlNewDocNoDtD):
|
||||
* SAX2.c:
|
||||
(xmlSAX2StartDocument):
|
||||
(xmlSAX2EndDocument):
|
||||
* parser.c:
|
||||
(xmlParseEntityDecl):
|
||||
(xmlParseExternalSubset):
|
||||
(xmlParseReference):
|
||||
(xmlCtxtParseDtd):
|
||||
* runxmlconf.c:
|
||||
(xmlconfTestInvalid):
|
||||
(xmlconfTestValid):
|
||||
* tree.c:
|
||||
(xmlNewDoc):
|
||||
(xmlFreeProp):
|
||||
(xmlNodeSetDoc):
|
||||
(xmlSetNsProp):
|
||||
(xmlDOMWrapAdoptBranch):
|
||||
* valid.c:
|
||||
(xmlFreeID):
|
||||
(xmlAddIDInternal):
|
||||
(xmlValidateAttributeValueInternal):
|
||||
(xmlValidateOneAttribute):
|
||||
(xmlValidateRef):
|
||||
* xmlreader.c:
|
||||
(xmlTextReaderStartElement):
|
||||
(xmlTextReaderStartElementNs):
|
||||
(xmlTextReaderValidateEntity):
|
||||
(xmlTextReaderRead):
|
||||
(xmlTextReaderNext):
|
||||
(xmlTextReaderIsEmptyElement):
|
||||
(xmlTextReaderPreserve):
|
||||
* xmlschemas.c:
|
||||
(xmlSchemaPValAttrNodeID):
|
||||
* xmlschemastypes.c:
|
||||
(xmlSchemaValAtomicType):
|
||||
- Adopt macros by renaming the struct fields, recompiling and fixing
|
||||
compiler failures, then changing the struct field names back.
|
||||
Origin: https://launchpad.net/ubuntu/+source/libxml2/2.9.14+dfsg-1.3ubuntu3.6
|
||||
Ref : https://security-tracker.debian.org/tracker/CVE-2025-7425
|
||||
|
||||
CVE: CVE-2025-7425
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/issues/140]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
HTMLparser.c | 1 +
|
||||
SAX2.c | 6 ++--
|
||||
include/libxml/tree.h | 14 ++++++++-
|
||||
parser.c | 8 ++---
|
||||
runxmlconf.c | 4 +--
|
||||
tree.c | 20 ++++++-------
|
||||
valid.c | 68 +++++++++++++++++++++----------------------
|
||||
xmlreader.c | 30 +++++++++----------
|
||||
xmlschemas.c | 4 +--
|
||||
xmlschemastypes.c | 12 ++++----
|
||||
10 files changed, 90 insertions(+), 77 deletions(-)
|
||||
|
||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
||||
index e720bb2..1307f71 100644
|
||||
--- a/HTMLparser.c
|
||||
+++ b/HTMLparser.c
|
||||
@@ -2514,6 +2514,7 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) {
|
||||
cur->refs = NULL;
|
||||
cur->_private = NULL;
|
||||
cur->charset = XML_CHAR_ENCODING_UTF8;
|
||||
+ XML_DOC_SET_PROPERTIES(cur, XML_DOC_HTML | XML_DOC_USERBUILT);
|
||||
cur->properties = XML_DOC_HTML | XML_DOC_USERBUILT;
|
||||
if ((ExternalID != NULL) ||
|
||||
(URI != NULL))
|
||||
diff --git a/SAX2.c b/SAX2.c
|
||||
index f7c77c2..0d8e84a 100644
|
||||
--- a/SAX2.c
|
||||
+++ b/SAX2.c
|
||||
@@ -970,7 +970,7 @@ xmlSAX2StartDocument(void *ctx)
|
||||
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
|
||||
return;
|
||||
}
|
||||
- ctxt->myDoc->properties = XML_DOC_HTML;
|
||||
+ XML_DOC_SET_PROPERTIES(ctxt->myDoc, XML_DOC_HTML);
|
||||
ctxt->myDoc->parseFlags = ctxt->options;
|
||||
#else
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
@@ -983,9 +983,9 @@ xmlSAX2StartDocument(void *ctx)
|
||||
} else {
|
||||
doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
|
||||
if (doc != NULL) {
|
||||
- doc->properties = 0;
|
||||
+ XML_DOC_CLEAR_PROPERTIES(doc);
|
||||
if (ctxt->options & XML_PARSE_OLD10)
|
||||
- doc->properties |= XML_DOC_OLD10;
|
||||
+ XML_DOC_ADD_PROPERTIES(doc, XML_DOC_OLD10);
|
||||
doc->parseFlags = ctxt->options;
|
||||
if (ctxt->encoding != NULL)
|
||||
doc->encoding = xmlStrdup(ctxt->encoding);
|
||||
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
|
||||
index 1e79be9..61178b2 100644
|
||||
--- a/include/libxml/tree.h
|
||||
+++ b/include/libxml/tree.h
|
||||
@@ -365,7 +365,6 @@ struct _xmlElement {
|
||||
#endif
|
||||
};
|
||||
|
||||
-
|
||||
/**
|
||||
* XML_LOCAL_NAMESPACE:
|
||||
*
|
||||
@@ -446,6 +445,10 @@ struct _xmlAttr {
|
||||
void *psvi; /* for type/PSVI information */
|
||||
};
|
||||
|
||||
+#define XML_ATTR_CLEAR_ATYPE(attr) (((attr)->atype) = 0)
|
||||
+#define XML_ATTR_GET_ATYPE(attr) (((attr)->atype) & ~(15U << 27))
|
||||
+#define XML_ATTR_SET_ATYPE(attr, type) ((attr)->atype = ((((attr)->atype) & (15U << 27)) | ((type) & ~(15U << 27))))
|
||||
+
|
||||
/**
|
||||
* xmlID:
|
||||
*
|
||||
@@ -507,6 +510,11 @@ struct _xmlNode {
|
||||
unsigned short extra; /* extra data for XPath/XSLT */
|
||||
};
|
||||
|
||||
+#define XML_NODE_ADD_EXTRA(node, type) ((node)->extra |= ((type) & ~(15U << 12)))
|
||||
+#define XML_NODE_CLEAR_EXTRA(node) (((node)->extra) = 0)
|
||||
+#define XML_NODE_GET_EXTRA(node) (((node)->extra) & ~(15U << 12))
|
||||
+#define XML_NODE_SET_EXTRA(node, type) ((node)->extra = ((((node)->extra) & (15U << 12)) | ((type) & ~(15U << 12))))
|
||||
+
|
||||
/**
|
||||
* XML_GET_CONTENT:
|
||||
*
|
||||
@@ -585,6 +593,10 @@ struct _xmlDoc {
|
||||
set at the end of parsing */
|
||||
};
|
||||
|
||||
+#define XML_DOC_ADD_PROPERTIES(doc, type) ((doc)->properties |= ((type) & ~(15U << 27)))
|
||||
+#define XML_DOC_CLEAR_PROPERTIES(doc) (((doc)->properties) = 0)
|
||||
+#define XML_DOC_GET_PROPERTIES(doc) (((doc)->properties) & ~(15U << 27))
|
||||
+#define XML_DOC_SET_PROPERTIES(doc, type) ((doc)->properties = ((((doc)->properties) & (15U << 27)) | ((type) & ~(15U << 27))))
|
||||
|
||||
typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt;
|
||||
typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr;
|
||||
diff --git a/parser.c b/parser.c
|
||||
index 738dbee..772d883 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -5523,7 +5523,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
|
||||
xmlErrMemory(ctxt, "New Doc failed");
|
||||
return;
|
||||
}
|
||||
- ctxt->myDoc->properties = XML_DOC_INTERNAL;
|
||||
+ XML_DOC_SET_PROPERTIES(ctxt->myDoc, XML_DOC_INTERNAL);
|
||||
}
|
||||
if (ctxt->myDoc->intSubset == NULL)
|
||||
ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
|
||||
@@ -5594,7 +5594,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
|
||||
xmlErrMemory(ctxt, "New Doc failed");
|
||||
return;
|
||||
}
|
||||
- ctxt->myDoc->properties = XML_DOC_INTERNAL;
|
||||
+ XML_DOC_SET_PROPERTIES(ctxt->myDoc, XML_DOC_INTERNAL);
|
||||
}
|
||||
|
||||
if (ctxt->myDoc->intSubset == NULL)
|
||||
@@ -7035,7 +7035,7 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
|
||||
xmlErrMemory(ctxt, "New Doc failed");
|
||||
return;
|
||||
}
|
||||
- ctxt->myDoc->properties = XML_DOC_INTERNAL;
|
||||
+ XML_DOC_SET_PROPERTIES(ctxt->myDoc, XML_DOC_INTERNAL);
|
||||
}
|
||||
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
|
||||
xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
|
||||
@@ -7419,7 +7419,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
||||
(nw != NULL) &&
|
||||
(nw->type == XML_ELEMENT_NODE) &&
|
||||
(nw->children == NULL))
|
||||
- nw->extra = 1;
|
||||
+ XML_NODE_SET_EXTRA(nw, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
diff --git a/runxmlconf.c b/runxmlconf.c
|
||||
index f43fdd3..82b7241 100644
|
||||
--- a/runxmlconf.c
|
||||
+++ b/runxmlconf.c
|
||||
@@ -197,7 +197,7 @@ xmlconfTestInvalid(const char *id, const char *filename, int options) {
|
||||
id, filename);
|
||||
} else {
|
||||
/* invalidity should be reported both in the context and in the document */
|
||||
- if ((ctxt->valid != 0) || (doc->properties & XML_DOC_DTDVALID)) {
|
||||
+ if ((ctxt->valid != 0) || (XML_DOC_GET_PROPERTIES(doc) & XML_DOC_DTDVALID)) {
|
||||
test_log("test %s : %s failed to detect invalid document\n",
|
||||
id, filename);
|
||||
nb_errors++;
|
||||
@@ -229,7 +229,7 @@ xmlconfTestValid(const char *id, const char *filename, int options) {
|
||||
ret = 0;
|
||||
} else {
|
||||
/* validity should be reported both in the context and in the document */
|
||||
- if ((ctxt->valid == 0) || ((doc->properties & XML_DOC_DTDVALID) == 0)) {
|
||||
+ if ((ctxt->valid == 0) || ((XML_DOC_GET_PROPERTIES(doc) & XML_DOC_DTDVALID) == 0)) {
|
||||
test_log("test %s : %s failed to validate a valid document\n",
|
||||
id, filename);
|
||||
nb_errors++;
|
||||
diff --git a/tree.c b/tree.c
|
||||
index cdf863c..3bac0b8 100644
|
||||
--- a/tree.c
|
||||
+++ b/tree.c
|
||||
@@ -1192,7 +1192,7 @@ xmlNewDoc(const xmlChar *version) {
|
||||
cur->compression = -1; /* not initialized */
|
||||
cur->doc = cur;
|
||||
cur->parseFlags = 0;
|
||||
- cur->properties = XML_DOC_USERBUILT;
|
||||
+ XML_DOC_SET_PROPERTIES(cur, XML_DOC_USERBUILT);
|
||||
/*
|
||||
* The in memory encoding is always UTF8
|
||||
* This field will never change and would
|
||||
@@ -2119,7 +2119,7 @@ xmlFreeProp(xmlAttrPtr cur) {
|
||||
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
|
||||
|
||||
/* Check for ID removal -> leading to invalid references ! */
|
||||
- if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
|
||||
+ if ((cur->doc != NULL) && (XML_ATTR_GET_ATYPE(cur) == XML_ATTRIBUTE_ID)) {
|
||||
xmlRemoveID(cur->doc, cur);
|
||||
}
|
||||
if (cur->children != NULL) xmlFreeNodeList(cur->children);
|
||||
@@ -2838,7 +2838,7 @@ xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
|
||||
if(tree->type == XML_ELEMENT_NODE) {
|
||||
prop = tree->properties;
|
||||
while (prop != NULL) {
|
||||
- if (prop->atype == XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(prop) == XML_ATTRIBUTE_ID) {
|
||||
xmlRemoveID(tree->doc, prop);
|
||||
}
|
||||
|
||||
@@ -6953,9 +6953,9 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
||||
/*
|
||||
* Modify the attribute's value.
|
||||
*/
|
||||
- if (prop->atype == XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(prop) == XML_ATTRIBUTE_ID) {
|
||||
xmlRemoveID(node->doc, prop);
|
||||
- prop->atype = XML_ATTRIBUTE_ID;
|
||||
+ XML_ATTR_SET_ATYPE(prop, XML_ATTRIBUTE_ID);
|
||||
}
|
||||
if (prop->children != NULL)
|
||||
xmlFreeNodeList(prop->children);
|
||||
@@ -6975,7 +6975,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
- if (prop->atype == XML_ATTRIBUTE_ID)
|
||||
+ if (XML_ATTR_GET_ATYPE(prop) == XML_ATTRIBUTE_ID)
|
||||
xmlAddID(NULL, node->doc, value, prop);
|
||||
return(prop);
|
||||
}
|
||||
@@ -9252,7 +9252,7 @@ ns_end:
|
||||
if (cur->type == XML_ELEMENT_NODE) {
|
||||
cur->psvi = NULL;
|
||||
cur->line = 0;
|
||||
- cur->extra = 0;
|
||||
+ XML_NODE_CLEAR_EXTRA(cur);
|
||||
/*
|
||||
* Walk attributes.
|
||||
*/
|
||||
@@ -9268,11 +9268,11 @@ ns_end:
|
||||
* Attributes.
|
||||
*/
|
||||
if ((sourceDoc != NULL) &&
|
||||
- (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
|
||||
+ (XML_ATTR_GET_ATYPE((xmlAttrPtr) cur) == XML_ATTRIBUTE_ID))
|
||||
{
|
||||
xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
|
||||
}
|
||||
- ((xmlAttrPtr) cur)->atype = 0;
|
||||
+ XML_ATTR_CLEAR_ATYPE((xmlAttrPtr) cur);
|
||||
((xmlAttrPtr) cur)->psvi = NULL;
|
||||
}
|
||||
break;
|
||||
@@ -9992,7 +9992,7 @@ xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
|
||||
}
|
||||
|
||||
XML_TREE_ADOPT_STR(attr->name);
|
||||
- attr->atype = 0;
|
||||
+ XML_ATTR_CLEAR_ATYPE(attr);
|
||||
attr->psvi = NULL;
|
||||
/*
|
||||
* Walk content.
|
||||
diff --git a/valid.c b/valid.c
|
||||
index 36a0435..8e76cfa 100644
|
||||
--- a/valid.c
|
||||
+++ b/valid.c
|
||||
@@ -1906,7 +1906,7 @@ xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem, int err) {
|
||||
if (elem == NULL) return(0);
|
||||
cur = elem->attributes;
|
||||
while (cur != NULL) {
|
||||
- if (cur->atype == XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(cur) == XML_ATTRIBUTE_ID) {
|
||||
ret ++;
|
||||
if ((ret > 1) && (err))
|
||||
xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
|
||||
@@ -2279,7 +2279,7 @@ xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
|
||||
xmlBufferWriteChar(buf, ":");
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, attr->name);
|
||||
- switch (attr->atype) {
|
||||
+ switch (XML_ATTR_GET_ATYPE(attr)) {
|
||||
case XML_ATTRIBUTE_CDATA:
|
||||
xmlBufferWriteChar(buf, " CDATA");
|
||||
break;
|
||||
@@ -2758,7 +2758,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
|
||||
return(NULL);
|
||||
}
|
||||
if (attr != NULL)
|
||||
- attr->atype = XML_ATTRIBUTE_ID;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_ID);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@@ -2837,7 +2837,7 @@ xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
|
||||
if ((fullelemname != felem) && (fullelemname != elem->name))
|
||||
xmlFree(fullelemname);
|
||||
|
||||
- if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
|
||||
+ if ((attrDecl != NULL) && (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ID))
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
@@ -2878,7 +2878,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
|
||||
|
||||
xmlHashRemoveEntry(table, ID, xmlFreeIDTableEntry);
|
||||
xmlFree(ID);
|
||||
- attr->atype = 0;
|
||||
+ XML_ATTR_CLEAR_ATYPE(attr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -3157,8 +3157,8 @@ xmlIsRef(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
|
||||
elem->name, attr->name);
|
||||
|
||||
if ((attrDecl != NULL) &&
|
||||
- (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
|
||||
- attrDecl->atype == XML_ATTRIBUTE_IDREFS))
|
||||
+ (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREF ||
|
||||
+ XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREFS))
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
@@ -3532,7 +3532,7 @@ xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
|
||||
|
||||
static int
|
||||
xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
|
||||
- if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
|
||||
+ if ((doc == NULL) || (XML_DOC_GET_PROPERTIES(doc) & XML_DOC_OLD10) == 0) {
|
||||
/*
|
||||
* Use the new checks of production [4] [4a] amd [5] of the
|
||||
* Update 5 of XML-1.0
|
||||
@@ -3562,7 +3562,7 @@ xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
|
||||
|
||||
static int
|
||||
xmlIsDocNameChar(xmlDocPtr doc, int c) {
|
||||
- if ((doc == NULL) || (doc->properties & XML_DOC_OLD10) == 0) {
|
||||
+ if ((doc == NULL) || (XML_DOC_GET_PROPERTIES(doc) & XML_DOC_OLD10) == 0) {
|
||||
/*
|
||||
* Use the new checks of production [4] [4a] amd [5] of the
|
||||
* Update 5 of XML-1.0
|
||||
@@ -4112,7 +4112,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
|
||||
if (attrDecl == NULL)
|
||||
return(NULL);
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_CDATA)
|
||||
return(NULL);
|
||||
|
||||
ret = xmlStrdup(value);
|
||||
@@ -4174,7 +4174,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
|
||||
|
||||
if (attrDecl == NULL)
|
||||
return(NULL);
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_CDATA)
|
||||
return(NULL);
|
||||
|
||||
ret = xmlStrdup(value);
|
||||
@@ -4189,7 +4189,7 @@ xmlValidateAttributeIdCallback(void *payload, void *data,
|
||||
const xmlChar *name ATTRIBUTE_UNUSED) {
|
||||
xmlAttributePtr attr = (xmlAttributePtr) payload;
|
||||
int *count = (int *) data;
|
||||
- if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
|
||||
+ if (XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_ID) (*count)++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4221,7 +4221,7 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
/* Attribute Default Legal */
|
||||
/* Enumeration */
|
||||
if (attr->defaultValue != NULL) {
|
||||
- val = xmlValidateAttributeValueInternal(doc, attr->atype,
|
||||
+ val = xmlValidateAttributeValueInternal(doc, XML_ATTR_GET_ATYPE(attr),
|
||||
attr->defaultValue);
|
||||
if (val == 0) {
|
||||
xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
|
||||
@@ -4232,7 +4232,7 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
}
|
||||
|
||||
/* ID Attribute Default */
|
||||
- if ((attr->atype == XML_ATTRIBUTE_ID)&&
|
||||
+ if ((XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_ID)&&
|
||||
(attr->def != XML_ATTRIBUTE_IMPLIED) &&
|
||||
(attr->def != XML_ATTRIBUTE_REQUIRED)) {
|
||||
xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
|
||||
@@ -4242,7 +4242,7 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
}
|
||||
|
||||
/* One ID per Element Type */
|
||||
- if (attr->atype == XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_ID) {
|
||||
int nbId;
|
||||
|
||||
/* the trick is that we parse DtD as their own internal subset */
|
||||
@@ -4501,9 +4501,9 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
attr->name, elem->name, NULL);
|
||||
return(0);
|
||||
}
|
||||
- attr->atype = attrDecl->atype;
|
||||
+ XML_ATTR_SET_ATYPE(attr, attrDecl->atype);
|
||||
|
||||
- val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
|
||||
+ val = xmlValidateAttributeValueInternal(doc, XML_ATTR_GET_ATYPE(attrDecl), value);
|
||||
if (val == 0) {
|
||||
xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
|
||||
"Syntax of value for attribute %s of %s is not valid\n",
|
||||
@@ -4522,19 +4522,19 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
}
|
||||
|
||||
/* Validity Constraint: ID uniqueness */
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ID) {
|
||||
if (xmlAddID(ctxt, doc, value, attr) == NULL)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
- if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
|
||||
- (attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
|
||||
+ if ((XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREF) ||
|
||||
+ (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREFS)) {
|
||||
if (xmlAddRef(ctxt, doc, value, attr) == NULL)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* Validity Constraint: Notation Attributes */
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_NOTATION) {
|
||||
xmlEnumerationPtr tree = attrDecl->tree;
|
||||
xmlNotationPtr nota;
|
||||
|
||||
@@ -4564,7 +4564,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
}
|
||||
|
||||
/* Validity Constraint: Enumeration */
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ENUMERATION) {
|
||||
xmlEnumerationPtr tree = attrDecl->tree;
|
||||
while (tree != NULL) {
|
||||
if (xmlStrEqual(tree->name, value)) break;
|
||||
@@ -4589,7 +4589,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
|
||||
/* Extra check for the attribute value */
|
||||
ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
|
||||
- attrDecl->atype, value);
|
||||
+ XML_ATTR_GET_ATYPE(attrDecl), value);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
@@ -4688,7 +4688,7 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
- val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
|
||||
+ val = xmlValidateAttributeValueInternal(doc, XML_ATTR_GET_ATYPE(attrDecl), value);
|
||||
if (val == 0) {
|
||||
if (ns->prefix != NULL) {
|
||||
xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
|
||||
@@ -4738,7 +4738,7 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
|
||||
#endif
|
||||
|
||||
/* Validity Constraint: Notation Attributes */
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_NOTATION) {
|
||||
xmlEnumerationPtr tree = attrDecl->tree;
|
||||
xmlNotationPtr nota;
|
||||
|
||||
@@ -4780,7 +4780,7 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
|
||||
}
|
||||
|
||||
/* Validity Constraint: Enumeration */
|
||||
- if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ENUMERATION) {
|
||||
xmlEnumerationPtr tree = attrDecl->tree;
|
||||
while (tree != NULL) {
|
||||
if (xmlStrEqual(tree->name, value)) break;
|
||||
@@ -4818,10 +4818,10 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
|
||||
/* Extra check for the attribute value */
|
||||
if (ns->prefix != NULL) {
|
||||
ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
|
||||
- attrDecl->atype, value);
|
||||
+ XML_ATTR_GET_ATYPE(attrDecl), value);
|
||||
} else {
|
||||
ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
|
||||
- attrDecl->atype, value);
|
||||
+ XML_ATTR_GET_ATYPE(attrDecl), value);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
@@ -6574,7 +6574,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
|
||||
while (IS_BLANK_CH(*cur)) cur++;
|
||||
}
|
||||
xmlFree(dup);
|
||||
- } else if (attr->atype == XML_ATTRIBUTE_IDREF) {
|
||||
+ } else if (XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_IDREF) {
|
||||
id = xmlGetID(ctxt->doc, name);
|
||||
if (id == NULL) {
|
||||
xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
|
||||
@@ -6582,7 +6582,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
|
||||
attr->name, name, NULL);
|
||||
ctxt->valid = 0;
|
||||
}
|
||||
- } else if (attr->atype == XML_ATTRIBUTE_IDREFS) {
|
||||
+ } else if (XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_IDREFS) {
|
||||
xmlChar *dup, *str = NULL, *cur, save;
|
||||
|
||||
dup = xmlStrdup(name);
|
||||
@@ -6782,7 +6782,7 @@ xmlValidateAttributeCallback(void *payload, void *data,
|
||||
|
||||
if (cur == NULL)
|
||||
return;
|
||||
- switch (cur->atype) {
|
||||
+ switch (XML_ATTR_GET_ATYPE(cur)) {
|
||||
case XML_ATTRIBUTE_CDATA:
|
||||
case XML_ATTRIBUTE_ID:
|
||||
case XML_ATTRIBUTE_IDREF :
|
||||
@@ -6797,7 +6797,7 @@ xmlValidateAttributeCallback(void *payload, void *data,
|
||||
if (cur->defaultValue != NULL) {
|
||||
|
||||
ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
|
||||
- cur->atype, cur->defaultValue);
|
||||
+ XML_ATTR_GET_ATYPE(cur), cur->defaultValue);
|
||||
if ((ret == 0) && (ctxt->valid == 1))
|
||||
ctxt->valid = 0;
|
||||
}
|
||||
@@ -6805,14 +6805,14 @@ xmlValidateAttributeCallback(void *payload, void *data,
|
||||
xmlEnumerationPtr tree = cur->tree;
|
||||
while (tree != NULL) {
|
||||
ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
|
||||
- cur->name, cur->atype, tree->name);
|
||||
+ cur->name, XML_ATTR_GET_ATYPE(cur), tree->name);
|
||||
if ((ret == 0) && (ctxt->valid == 1))
|
||||
ctxt->valid = 0;
|
||||
tree = tree->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
- if (cur->atype == XML_ATTRIBUTE_NOTATION) {
|
||||
+ if (XML_ATTR_GET_ATYPE(cur) == XML_ATTRIBUTE_NOTATION) {
|
||||
doc = cur->doc;
|
||||
if (cur->elem == NULL) {
|
||||
xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||
diff --git a/xmlreader.c b/xmlreader.c
|
||||
index 67ff2cd..2a1a66a 100644
|
||||
--- a/xmlreader.c
|
||||
+++ b/xmlreader.c
|
||||
@@ -753,7 +753,7 @@ xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
|
||||
if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
|
||||
(ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
|
||||
(ctxt->input->cur[1] == '>'))
|
||||
- ctxt->node->extra = NODE_IS_EMPTY;
|
||||
+ XML_NODE_SET_EXTRA(ctxt->node, NODE_IS_EMPTY);
|
||||
}
|
||||
if (reader != NULL)
|
||||
reader->state = XML_TEXTREADER_ELEMENT;
|
||||
@@ -818,7 +818,7 @@ xmlTextReaderStartElementNs(void *ctx,
|
||||
if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
|
||||
(ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
|
||||
(ctxt->input->cur[1] == '>'))
|
||||
- ctxt->node->extra = NODE_IS_EMPTY;
|
||||
+ XML_NODE_SET_EXTRA(ctxt->node, NODE_IS_EMPTY);
|
||||
}
|
||||
if (reader != NULL)
|
||||
reader->state = XML_TEXTREADER_ELEMENT;
|
||||
@@ -1216,7 +1216,7 @@ skip_children:
|
||||
xmlNodePtr tmp;
|
||||
if (reader->entNr == 0) {
|
||||
while ((tmp = node->last) != NULL) {
|
||||
- if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
|
||||
+ if ((XML_NODE_GET_EXTRA(tmp) & NODE_IS_PRESERVED) == 0) {
|
||||
xmlUnlinkNode(tmp);
|
||||
xmlTextReaderFreeNode(reader, tmp);
|
||||
} else
|
||||
@@ -1467,7 +1467,7 @@ get_next_node:
|
||||
if ((oldstate == XML_TEXTREADER_ELEMENT) &&
|
||||
(reader->node->type == XML_ELEMENT_NODE) &&
|
||||
(reader->node->children == NULL) &&
|
||||
- ((reader->node->extra & NODE_IS_EMPTY) == 0)
|
||||
+ ((XML_NODE_GET_EXTRA(reader->node) & NODE_IS_EMPTY) == 0)
|
||||
#ifdef LIBXML_XINCLUDE_ENABLED
|
||||
&& (reader->in_xinclude <= 0)
|
||||
#endif
|
||||
@@ -1481,7 +1481,7 @@ get_next_node:
|
||||
xmlTextReaderValidatePop(reader);
|
||||
#endif /* LIBXML_REGEXP_ENABLED */
|
||||
if ((reader->preserves > 0) &&
|
||||
- (reader->node->extra & NODE_IS_SPRESERVED))
|
||||
+ (XML_NODE_GET_EXTRA(reader->node) & NODE_IS_SPRESERVED))
|
||||
reader->preserves--;
|
||||
reader->node = reader->node->next;
|
||||
reader->state = XML_TEXTREADER_ELEMENT;
|
||||
@@ -1497,7 +1497,7 @@ get_next_node:
|
||||
(reader->node->prev != NULL) &&
|
||||
(reader->node->prev->type != XML_DTD_NODE)) {
|
||||
xmlNodePtr tmp = reader->node->prev;
|
||||
- if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
|
||||
+ if ((XML_NODE_GET_EXTRA(tmp) & NODE_IS_PRESERVED) == 0) {
|
||||
if (oldnode == tmp)
|
||||
oldnode = NULL;
|
||||
xmlUnlinkNode(tmp);
|
||||
@@ -1510,7 +1510,7 @@ get_next_node:
|
||||
if ((oldstate == XML_TEXTREADER_ELEMENT) &&
|
||||
(reader->node->type == XML_ELEMENT_NODE) &&
|
||||
(reader->node->children == NULL) &&
|
||||
- ((reader->node->extra & NODE_IS_EMPTY) == 0)) {;
|
||||
+ ((XML_NODE_GET_EXTRA(reader->node) & NODE_IS_EMPTY) == 0)) {;
|
||||
reader->state = XML_TEXTREADER_END;
|
||||
goto node_found;
|
||||
}
|
||||
@@ -1519,7 +1519,7 @@ get_next_node:
|
||||
xmlTextReaderValidatePop(reader);
|
||||
#endif /* LIBXML_REGEXP_ENABLED */
|
||||
if ((reader->preserves > 0) &&
|
||||
- (reader->node->extra & NODE_IS_SPRESERVED))
|
||||
+ (XML_NODE_GET_EXTRA(reader->node) & NODE_IS_SPRESERVED))
|
||||
reader->preserves--;
|
||||
reader->node = reader->node->parent;
|
||||
if ((reader->node == NULL) ||
|
||||
@@ -1546,7 +1546,7 @@ get_next_node:
|
||||
#endif
|
||||
(reader->entNr == 0) &&
|
||||
(oldnode->type != XML_DTD_NODE) &&
|
||||
- ((oldnode->extra & NODE_IS_PRESERVED) == 0)) {
|
||||
+ ((XML_NODE_GET_EXTRA(oldnode) & NODE_IS_PRESERVED) == 0)) {
|
||||
xmlUnlinkNode(oldnode);
|
||||
xmlTextReaderFreeNode(reader, oldnode);
|
||||
}
|
||||
@@ -1559,7 +1559,7 @@ get_next_node:
|
||||
#endif
|
||||
(reader->entNr == 0) &&
|
||||
(reader->node->last != NULL) &&
|
||||
- ((reader->node->last->extra & NODE_IS_PRESERVED) == 0)) {
|
||||
+ ((XML_NODE_GET_EXTRA(reader->node->last) & NODE_IS_PRESERVED) == 0)) {
|
||||
xmlNodePtr tmp = reader->node->last;
|
||||
xmlUnlinkNode(tmp);
|
||||
xmlTextReaderFreeNode(reader, tmp);
|
||||
@@ -1741,7 +1741,7 @@ xmlTextReaderNext(xmlTextReaderPtr reader) {
|
||||
return(xmlTextReaderRead(reader));
|
||||
if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
|
||||
return(xmlTextReaderRead(reader));
|
||||
- if (cur->extra & NODE_IS_EMPTY)
|
||||
+ if (XML_NODE_GET_EXTRA(cur) & NODE_IS_EMPTY)
|
||||
return(xmlTextReaderRead(reader));
|
||||
do {
|
||||
ret = xmlTextReaderRead(reader);
|
||||
@@ -3167,7 +3167,7 @@ xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
|
||||
if (reader->in_xinclude > 0)
|
||||
return(1);
|
||||
#endif
|
||||
- return((reader->node->extra & NODE_IS_EMPTY) != 0);
|
||||
+ return((XML_NODE_GET_EXTRA(reader->node) & NODE_IS_EMPTY) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4035,15 +4035,15 @@ xmlTextReaderPreserve(xmlTextReaderPtr reader) {
|
||||
return(NULL);
|
||||
|
||||
if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
|
||||
- cur->extra |= NODE_IS_PRESERVED;
|
||||
- cur->extra |= NODE_IS_SPRESERVED;
|
||||
+ XML_NODE_ADD_EXTRA(cur, NODE_IS_PRESERVED);
|
||||
+ XML_NODE_ADD_EXTRA(cur, NODE_IS_SPRESERVED);
|
||||
}
|
||||
reader->preserves++;
|
||||
|
||||
parent = cur->parent;;
|
||||
while (parent != NULL) {
|
||||
if (parent->type == XML_ELEMENT_NODE)
|
||||
- parent->extra |= NODE_IS_PRESERVED;
|
||||
+ XML_NODE_ADD_EXTRA(parent, NODE_IS_PRESERVED);
|
||||
parent = parent->parent;
|
||||
}
|
||||
return(cur);
|
||||
diff --git a/xmlschemas.c b/xmlschemas.c
|
||||
index a2dd6cf..2e6c349 100644
|
||||
--- a/xmlschemas.c
|
||||
+++ b/xmlschemas.c
|
||||
@@ -6024,7 +6024,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
|
||||
/*
|
||||
* NOTE: the IDness might have already be declared in the DTD
|
||||
*/
|
||||
- if (attr->atype != XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attr) != XML_ATTRIBUTE_ID) {
|
||||
xmlIDPtr res;
|
||||
xmlChar *strip;
|
||||
|
||||
@@ -6047,7 +6047,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
|
||||
NULL, NULL, "Duplicate value '%s' of simple "
|
||||
"type 'xs:ID'", value, NULL);
|
||||
} else
|
||||
- attr->atype = XML_ATTRIBUTE_ID;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_ID);
|
||||
}
|
||||
} else if (ret > 0) {
|
||||
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
|
||||
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
|
||||
index af31be5..d40da49 100644
|
||||
--- a/xmlschemastypes.c
|
||||
+++ b/xmlschemastypes.c
|
||||
@@ -2867,7 +2867,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
/*
|
||||
* NOTE: the IDness might have already be declared in the DTD
|
||||
*/
|
||||
- if (attr->atype != XML_ATTRIBUTE_ID) {
|
||||
+ if (XML_ATTR_GET_ATYPE(attr) != XML_ATTRIBUTE_ID) {
|
||||
xmlIDPtr res;
|
||||
xmlChar *strip;
|
||||
|
||||
@@ -2880,7 +2880,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
if (res == NULL) {
|
||||
ret = 2;
|
||||
} else {
|
||||
- attr->atype = XML_ATTRIBUTE_ID;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2905,7 +2905,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
xmlFree(strip);
|
||||
} else
|
||||
xmlAddRef(NULL, node->doc, value, attr);
|
||||
- attr->atype = XML_ATTRIBUTE_IDREF;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_IDREF);
|
||||
}
|
||||
goto done;
|
||||
case XML_SCHEMAS_IDREFS:
|
||||
@@ -2919,7 +2919,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
(node->type == XML_ATTRIBUTE_NODE)) {
|
||||
xmlAttrPtr attr = (xmlAttrPtr) node;
|
||||
|
||||
- attr->atype = XML_ATTRIBUTE_IDREFS;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_IDREFS);
|
||||
}
|
||||
goto done;
|
||||
case XML_SCHEMAS_ENTITY:{
|
||||
@@ -2950,7 +2950,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
(node->type == XML_ATTRIBUTE_NODE)) {
|
||||
xmlAttrPtr attr = (xmlAttrPtr) node;
|
||||
|
||||
- attr->atype = XML_ATTRIBUTE_ENTITY;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_ENTITY);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
@@ -2967,7 +2967,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
||||
(node->type == XML_ATTRIBUTE_NODE)) {
|
||||
xmlAttrPtr attr = (xmlAttrPtr) node;
|
||||
|
||||
- attr->atype = XML_ATTRIBUTE_ENTITIES;
|
||||
+ XML_ATTR_SET_ATYPE(attr, XML_ATTRIBUTE_ENTITIES);
|
||||
}
|
||||
goto done;
|
||||
case XML_SCHEMAS_NOTATION:{
|
||||
--
|
||||
2.50.1
|
||||
|
||||
117
meta/recipes-core/libxml/libxml2/CVE-2025-9714.patch
Normal file
117
meta/recipes-core/libxml/libxml2/CVE-2025-9714.patch
Normal file
@@ -0,0 +1,117 @@
|
||||
From 6ef8b9f05cc21d3fc28156fe5d1251834c29c7d7 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Thu, 28 Jul 2022 20:21:24 +0200
|
||||
Subject: [PATCH] Make XPath depth check work with recursive invocations
|
||||
|
||||
EXSLT functions like dyn:map or dyn:evaluate invoke xmlXPathRunEval
|
||||
recursively. Don't set depth to zero but keep and restore the original
|
||||
value to avoid stack overflows when abusing these functions.
|
||||
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/677a42645ef22b5a50741bad5facf9d8a8bc6d21]
|
||||
CVE: CVE-2025-9714
|
||||
|
||||
Signed-off-by: Theo GAIGE <tgaige.opensource@witekio.com>
|
||||
---
|
||||
xpath.c | 23 +++++++++++++++++------
|
||||
1 file changed, 17 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/xpath.c b/xpath.c
|
||||
index c2d845888..028471d53 100644
|
||||
--- a/xpath.c
|
||||
+++ b/xpath.c
|
||||
@@ -13883,12 +13883,11 @@ static int
|
||||
xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
|
||||
{
|
||||
xmlXPathCompExprPtr comp;
|
||||
+ int oldDepth;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->comp == NULL))
|
||||
return(-1);
|
||||
|
||||
- ctxt->context->depth = 0;
|
||||
-
|
||||
if (ctxt->valueTab == NULL) {
|
||||
/* Allocate the value stack */
|
||||
ctxt->valueTab = (xmlXPathObjectPtr *)
|
||||
@@ -13942,11 +13941,13 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
|
||||
"xmlXPathRunEval: last is less than zero\n");
|
||||
return(-1);
|
||||
}
|
||||
+ oldDepth = ctxt->context->depth;
|
||||
if (toBool)
|
||||
return(xmlXPathCompOpEvalToBoolean(ctxt,
|
||||
&comp->steps[comp->last], 0));
|
||||
else
|
||||
xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
|
||||
+ ctxt->context->depth = oldDepth;
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -14217,6 +14218,7 @@ xmlXPathCompExprPtr
|
||||
xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
|
||||
xmlXPathParserContextPtr pctxt;
|
||||
xmlXPathCompExprPtr comp;
|
||||
+ int oldDepth = 0;
|
||||
|
||||
#ifdef XPATH_STREAMING
|
||||
comp = xmlXPathTryStreamCompile(ctxt, str);
|
||||
@@ -14230,8 +14232,10 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
|
||||
if (pctxt == NULL)
|
||||
return NULL;
|
||||
if (ctxt != NULL)
|
||||
- ctxt->depth = 0;
|
||||
+ oldDepth = ctxt->depth;
|
||||
xmlXPathCompileExpr(pctxt, 1);
|
||||
+ if (ctxt != NULL)
|
||||
+ ctxt->depth = oldDepth;
|
||||
|
||||
if( pctxt->error != XPATH_EXPRESSION_OK )
|
||||
{
|
||||
@@ -14252,8 +14256,10 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
|
||||
comp = pctxt->comp;
|
||||
if ((comp->nbStep > 1) && (comp->last >= 0)) {
|
||||
if (ctxt != NULL)
|
||||
- ctxt->depth = 0;
|
||||
+ oldDepth = ctxt->depth;
|
||||
xmlXPathOptimizeExpression(pctxt, &comp->steps[comp->last]);
|
||||
+ if (ctxt != NULL)
|
||||
+ ctxt->depth = oldDepth;
|
||||
}
|
||||
pctxt->comp = NULL;
|
||||
}
|
||||
@@ -14409,6 +14415,7 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
|
||||
#ifdef XPATH_STREAMING
|
||||
xmlXPathCompExprPtr comp;
|
||||
#endif
|
||||
+ int oldDepth = 0;
|
||||
|
||||
if (ctxt == NULL) return;
|
||||
|
||||
@@ -14422,8 +14429,10 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
|
||||
#endif
|
||||
{
|
||||
if (ctxt->context != NULL)
|
||||
- ctxt->context->depth = 0;
|
||||
+ oldDepth = ctxt->context->depth;
|
||||
xmlXPathCompileExpr(ctxt, 1);
|
||||
+ if (ctxt->context != NULL)
|
||||
+ ctxt->context->depth = oldDepth;
|
||||
CHECK_ERROR;
|
||||
|
||||
/* Check for trailing characters. */
|
||||
@@ -14432,9 +14441,11 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
|
||||
|
||||
if ((ctxt->comp->nbStep > 1) && (ctxt->comp->last >= 0)) {
|
||||
if (ctxt->context != NULL)
|
||||
- ctxt->context->depth = 0;
|
||||
+ oldDepth = ctxt->context->depth;
|
||||
xmlXPathOptimizeExpression(ctxt,
|
||||
&ctxt->comp->steps[ctxt->comp->last]);
|
||||
+ if (ctxt->context != NULL)
|
||||
+ ctxt->context->depth = oldDepth;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -42,6 +42,8 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20080827.tar;subdir=${BP};name=testt
|
||||
file://CVE-2025-6021.patch \
|
||||
file://CVE-2025-49794-CVE-2025-49796.patch \
|
||||
file://CVE-2025-6170.patch \
|
||||
file://CVE-2025-9714.patch \
|
||||
file://CVE-2025-7425.patch \
|
||||
"
|
||||
|
||||
SRC_URI[archive.sha256sum] = "60d74a257d1ccec0475e749cba2f21559e48139efba6ff28224357c7c798dfee"
|
||||
|
||||
39
meta/recipes-core/musl/musl/CVE-2025-26519-1.patch
Normal file
39
meta/recipes-core/musl/musl/CVE-2025-26519-1.patch
Normal file
@@ -0,0 +1,39 @@
|
||||
From 345d2a053c32f3443dbfdd313f49346ce30b92f8 Mon Sep 17 00:00:00 2001
|
||||
From: Rich Felker <dalias@aerifal.cx>
|
||||
Date: Wed, 19 Nov 2025 13:23:38 +0100
|
||||
Subject: [PATCH] iconv: fix erroneous input validation in EUC-KR decoder
|
||||
|
||||
as a result of incorrect bounds checking on the lead byte being
|
||||
decoded, certain invalid inputs which should produce an encoding
|
||||
error, such as "\xc8\x41", instead produced out-of-bounds loads from
|
||||
the ksc table.
|
||||
|
||||
in a worst case, the loaded value may not be a valid unicode scalar
|
||||
value, in which case, if the output encoding was UTF-8, wctomb would
|
||||
return (size_t)-1, causing an overflow in the output pointer and
|
||||
remaining buffer size which could clobber memory outside of the output
|
||||
buffer.
|
||||
|
||||
bug report was submitted in private by Nick Wellnhofer on account of
|
||||
potential security implications.
|
||||
|
||||
CVE: CVE-2025-26519
|
||||
Upstream-Status: Backport [https://git.musl-libc.org/cgit/musl/commit/?id=e5adcd97b5196e29991b524237381a0202a60659]
|
||||
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
|
||||
---
|
||||
src/locale/iconv.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
|
||||
index 3047c27b..1fb66bc8 100644
|
||||
--- a/src/locale/iconv.c
|
||||
+++ b/src/locale/iconv.c
|
||||
@@ -495,7 +495,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
|
||||
if (c >= 93 || d >= 94) {
|
||||
c += (0xa1-0x81);
|
||||
d += 0xa1;
|
||||
- if (c >= 93 || c>=0xc6-0x81 && d>0x52)
|
||||
+ if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52)
|
||||
goto ilseq;
|
||||
if (d-'A'<26) d = d-'A';
|
||||
else if (d-'a'<26) d = d-'a'+26;
|
||||
38
meta/recipes-core/musl/musl/CVE-2025-26519-2.patch
Normal file
38
meta/recipes-core/musl/musl/CVE-2025-26519-2.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From b81230050f6c3348038fe470d260028824b9a9e5 Mon Sep 17 00:00:00 2001
|
||||
From: Rich Felker <dalias@aerifal.cx>
|
||||
Date: Wed, 19 Nov 2025 13:27:15 +0100
|
||||
Subject: [PATCH] iconv: harden UTF-8 output code path against input decoder
|
||||
bugs
|
||||
|
||||
the UTF-8 output code was written assuming an invariant that iconv's
|
||||
decoders only emit valid Unicode Scalar Values which wctomb can encode
|
||||
successfully, thereby always returning a value between 1 and 4.
|
||||
|
||||
if this invariant is not satisfied, wctomb returns (size_t)-1, and the
|
||||
subsequent adjustments to the output buffer pointer and remaining
|
||||
output byte count overflow, moving the output position backwards,
|
||||
potentially past the beginning of the buffer, without storing any
|
||||
bytes.
|
||||
|
||||
CVE: CVE-2025-26519
|
||||
Upstream-Status: Backport [https://git.musl-libc.org/cgit/musl/commit/?id=c47ad25ea3b484e10326f933e927c0bc8cded3da]
|
||||
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
|
||||
---
|
||||
src/locale/iconv.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
|
||||
index 1fb66bc8..fb1d3217 100644
|
||||
--- a/src/locale/iconv.c
|
||||
+++ b/src/locale/iconv.c
|
||||
@@ -538,6 +538,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
|
||||
if (*outb < k) goto toobig;
|
||||
memcpy(*out, tmp, k);
|
||||
} else k = wctomb_utf8(*out, c);
|
||||
+ /* This failure condition should be unreachable, but
|
||||
+ * is included to prevent decoder bugs from translating
|
||||
+ * into advancement outside the output buffer range. */
|
||||
+ if (k>4) goto ilseq;
|
||||
*out += k;
|
||||
*outb -= k;
|
||||
break;
|
||||
@@ -15,7 +15,9 @@ PV = "${BASEVER}+git${SRCPV}"
|
||||
SRC_URI = "git://git.musl-libc.org/musl;branch=master \
|
||||
file://0001-Make-dynamic-linker-a-relative-symlink-to-libc.patch \
|
||||
file://0002-ldso-Use-syslibdir-and-libdir-as-default-pathes-to-l.patch \
|
||||
"
|
||||
file://CVE-2025-26519-1.patch \
|
||||
file://CVE-2025-26519-2.patch \
|
||||
"
|
||||
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
|
||||
@@ -235,6 +235,7 @@ EXTRA_OEMESON += "-Dnobody-user=nobody \
|
||||
-Dmode=release \
|
||||
-Dsystem-alloc-uid-min=101 \
|
||||
-Dsystem-uid-max=999 \
|
||||
-Dtranslations=${@'false' if d.getVar('USE_NLS') == 'no' else 'true'} \
|
||||
-Dsystem-alloc-gid-min=101 \
|
||||
-Dsystem-gid-max=999 \
|
||||
"
|
||||
|
||||
@@ -80,5 +80,11 @@ SRC_URI = "\
|
||||
file://0042-CVE-2025-5245.patch \
|
||||
file://0043-CVE-2025-7546.patch \
|
||||
file://0043-CVE-2025-7545.patch \
|
||||
file://0044-CVE-2025-11082.patch \
|
||||
file://0045-CVE-2025-11083.patch \
|
||||
file://0046-CVE-2025-11081.patch \
|
||||
file://0047-CVE-2025-8225.patch \
|
||||
file://CVE-2025-11412.patch \
|
||||
file://CVE-2025-11413.patch \
|
||||
"
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
From ea1a0737c7692737a644af0486b71e4a392cbca8 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Mon, 22 Sep 2025 15:20:34 +0800
|
||||
Subject: [PATCH] elf: Don't read beyond .eh_frame section size
|
||||
|
||||
PR ld/33464
|
||||
* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Don't read beyond
|
||||
.eh_frame section size.
|
||||
|
||||
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
CVE: CVE-2025-11082
|
||||
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ea1a0737c7692737a644af0486b71e4a392cbca8]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
bfd/elf-eh-frame.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
|
||||
index dc0d2e097f5..30bb313489c 100644
|
||||
--- a/bfd/elf-eh-frame.c
|
||||
+++ b/bfd/elf-eh-frame.c
|
||||
@@ -733,6 +733,7 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||
if (hdr_id == 0)
|
||||
{
|
||||
unsigned int initial_insn_length;
|
||||
+ char *null_byte;
|
||||
|
||||
/* CIE */
|
||||
this_inf->cie = 1;
|
||||
@@ -749,10 +750,13 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||
REQUIRE (cie->version == 1
|
||||
|| cie->version == 3
|
||||
|| cie->version == 4);
|
||||
- REQUIRE (strlen ((char *) buf) < sizeof (cie->augmentation));
|
||||
+ null_byte = memchr ((char *) buf, 0, end - buf);
|
||||
+ REQUIRE (null_byte != NULL);
|
||||
+ REQUIRE ((size_t) (null_byte - (char *) buf)
|
||||
+ < sizeof (cie->augmentation));
|
||||
|
||||
strcpy (cie->augmentation, (char *) buf);
|
||||
- buf = (bfd_byte *) strchr ((char *) buf, '\0') + 1;
|
||||
+ buf = (bfd_byte *) null_byte + 1;
|
||||
this_inf->u.cie.aug_str_len = buf - start - 1;
|
||||
ENSURE_NO_RELOCS (buf);
|
||||
if (buf[0] == 'e' && buf[1] == 'h')
|
||||
@@ -0,0 +1,77 @@
|
||||
From 9ca499644a21ceb3f946d1c179c38a83be084490 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Thu, 18 Sep 2025 16:59:25 -0700
|
||||
Subject: [PATCH] elf: Don't match corrupt section header in linker input
|
||||
|
||||
Don't swap in nor match corrupt section header in linker input to avoid
|
||||
linker crash later.
|
||||
|
||||
PR ld/33457
|
||||
* elfcode.h (elf_swap_shdr_in): Changed to return bool. Return
|
||||
false for corrupt section header in linker input.
|
||||
(elf_object_p): Reject if elf_swap_shdr_in returns false.
|
||||
|
||||
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
CVE: CVE-2025-11083
|
||||
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9ca499644a21ceb3f946d1c179c38a83be084490]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
bfd/elfcode.h | 14 +++++++++-----
|
||||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
|
||||
index 9c65852e103..5224a1abee6 100644
|
||||
--- a/bfd/elfcode.h
|
||||
+++ b/bfd/elfcode.h
|
||||
@@ -298,7 +298,7 @@ elf_swap_ehdr_out (bfd *abfd,
|
||||
/* Translate an ELF section header table entry in external format into an
|
||||
ELF section header table entry in internal format. */
|
||||
|
||||
-static void
|
||||
+static bool
|
||||
elf_swap_shdr_in (bfd *abfd,
|
||||
const Elf_External_Shdr *src,
|
||||
Elf_Internal_Shdr *dst)
|
||||
@@ -328,6 +328,9 @@ elf_swap_shdr_in (bfd *abfd,
|
||||
if (!abfd->read_only)
|
||||
_bfd_error_handler (_("warning: %pB has a section "
|
||||
"extending past end of file"), abfd);
|
||||
+ /* PR ld/33457: Don't match corrupt section header. */
|
||||
+ if (abfd->is_linker_input)
|
||||
+ return false;
|
||||
abfd->read_only = 1;
|
||||
}
|
||||
}
|
||||
@@ -337,6 +340,7 @@ elf_swap_shdr_in (bfd *abfd,
|
||||
dst->sh_entsize = H_GET_WORD (abfd, src->sh_entsize);
|
||||
dst->bfd_section = NULL;
|
||||
dst->contents = NULL;
|
||||
+ return true;
|
||||
}
|
||||
|
||||
/* Translate an ELF section header table entry in internal format into an
|
||||
@@ -629,9 +633,9 @@ elf_object_p (bfd *abfd)
|
||||
|
||||
/* Read the first section header at index 0, and convert to internal
|
||||
form. */
|
||||
- if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
|
||||
+ if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)
|
||||
+ || !elf_swap_shdr_in (abfd, &x_shdr, &i_shdr))
|
||||
goto got_no_match;
|
||||
- elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
|
||||
|
||||
/* If the section count is zero, the actual count is in the first
|
||||
section header. */
|
||||
@@ -717,9 +721,9 @@ elf_object_p (bfd *abfd)
|
||||
to internal form. */
|
||||
for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
|
||||
{
|
||||
- if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr))
|
||||
+ if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)
|
||||
+ || !elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex))
|
||||
goto got_no_match;
|
||||
- elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
|
||||
|
||||
/* Sanity check sh_link and sh_info. */
|
||||
if (i_shdrp[shindex].sh_link >= num_sec)
|
||||
@@ -0,0 +1,84 @@
|
||||
From f87a66db645caf8cc0e6fc87b0c28c78a38af59b Mon Sep 17 00:00:00 2001
|
||||
From: Alan Modra <amodra@gmail.com>
|
||||
Date: Tue, 9 Sep 2025 18:32:09 +0930
|
||||
Subject: [PATCH] PR 33406 SEGV in dump_dwarf_section
|
||||
|
||||
Trying to dump .sframe in a PE file results in a segfault accessing
|
||||
elf_section_data.
|
||||
|
||||
* objdump (dump_sframe_section, dump_dwarf_section): Don't access
|
||||
elf_section_type without first checking the file is ELF.
|
||||
---
|
||||
binutils/objdump.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f87a66db645caf8cc0e6fc87b0c28c78a38af59b]
|
||||
CVE: CVE-2025-11081
|
||||
|
||||
Signed-off-by: Alan Modra <amodra@gmail.com>
|
||||
Signed-off-by: Yash Shinde <Yash.Shinde@windriver.com>
|
||||
|
||||
diff --git a/binutils/objdump.c b/binutils/objdump.c
|
||||
index 290f7e51f66..ee8823da05a 100644
|
||||
--- a/binutils/objdump.c
|
||||
+++ b/binutils/objdump.c
|
||||
@@ -4418,6 +4418,10 @@
|
||||
else
|
||||
match = name;
|
||||
|
||||
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
|
||||
+ && elf_section_type (section) == SHT_GNU_SFRAME)
|
||||
+ match = ".sframe";
|
||||
+
|
||||
for (i = 0; i < max; i++)
|
||||
if ((strcmp (debug_displays [i].section.uncompressed_name, match) == 0
|
||||
|| strcmp (debug_displays [i].section.compressed_name, match) == 0
|
||||
@@ -4923,6 +4927,36 @@
|
||||
}
|
||||
|
||||
+static void
|
||||
+dump_sframe_section (bfd *abfd, const char *sect_name, bool is_mainfile)
|
||||
+
|
||||
+{
|
||||
+ /* Error checking for user provided SFrame section name, if any. */
|
||||
+ if (sect_name)
|
||||
+ {
|
||||
+ asection *sec = bfd_get_section_by_name (abfd, sect_name);
|
||||
+ if (sec == NULL)
|
||||
+ {
|
||||
+ printf (_("No %s section present\n\n"), sanitize_string (sect_name));
|
||||
+ return;
|
||||
+ }
|
||||
+ /* Starting with Binutils 2.45, SFrame sections have section type
|
||||
+ SHT_GNU_SFRAME. For SFrame sections from Binutils 2.44 or earlier,
|
||||
+ check explcitly for SFrame sections of type SHT_PROGBITS and name
|
||||
+ ".sframe" to allow them. */
|
||||
+ else if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
|
||||
+ || (elf_section_type (sec) != SHT_GNU_SFRAME
|
||||
+ && !(elf_section_type (sec) == SHT_PROGBITS
|
||||
+ && strcmp (sect_name, ".sframe") == 0)))
|
||||
+ {
|
||||
+ printf (_("Section %s does not contain SFrame data\n\n"),
|
||||
+ sanitize_string (sect_name));
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ dump_dwarf (abfd, is_mainfile);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
dump_target_specific (bfd *abfd)
|
||||
{
|
||||
const struct objdump_private_desc * const *desc;
|
||||
diff --git a/include/elf/common.h b/include/elf/common.h
|
||||
--- a/include/elf/common.h
|
||||
+++ b/include/elf/common.h
|
||||
@@ -528,6 +528,8 @@
|
||||
#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
|
||||
#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
|
||||
|
||||
+#define SHT_GNU_SFRAME 0x6ffffff4 /* SFrame stack trace information. */
|
||||
+
|
||||
#define SHT_GNU_INCREMENTAL_INPUTS 0x6fff4700 /* incremental build data */
|
||||
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes */
|
||||
#define SHT_GNU_HASH 0x6ffffff6 /* GNU style symbol hash table */
|
||||
@@ -0,0 +1,47 @@
|
||||
From e51fdff7d2e538c0e5accdd65649ac68e6e0ddd4 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Modra <amodra@gmail.com>
|
||||
Date: Wed, 19 Feb 2025 22:45:29 +1030
|
||||
Subject: [PATCH] binutils/dwarf.c debug_information leak
|
||||
|
||||
It is possible with fuzzed files to have num_debug_info_entries zero
|
||||
after allocating space for debug_information, leading to multiple
|
||||
allocations.
|
||||
|
||||
* dwarf.c (process_debug_info): Don't test num_debug_info_entries
|
||||
to determine whether debug_information has been allocated,
|
||||
test alloc_num_debug_info_entries.
|
||||
---
|
||||
|
||||
Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=e51fdff7d2e538c0e5accdd65649ac68e6e0ddd4]
|
||||
CVE: CVE-2025-8225
|
||||
|
||||
binutils/dwarf.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
Signed-off-by: Alan Modra <amodra@gmail.com>
|
||||
Signed-off-by: Yash Shinde <Yash.Shinde@windriver.com>
|
||||
|
||||
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
|
||||
index 8e004cea839..bfbf83ec9f4 100644
|
||||
--- a/binutils/dwarf.c
|
||||
+++ b/binutils/dwarf.c
|
||||
@@ -3807,13 +3807,11 @@ process_debug_info (struct dwarf_section * section,
|
||||
}
|
||||
|
||||
if ((do_loc || do_debug_loc || do_debug_ranges || do_debug_info)
|
||||
- && num_debug_info_entries == 0
|
||||
- && ! do_types)
|
||||
+ && alloc_num_debug_info_entries == 0
|
||||
+ && !do_types)
|
||||
{
|
||||
-
|
||||
/* Then allocate an array to hold the information. */
|
||||
- debug_information = (debug_info *) cmalloc (num_units,
|
||||
- sizeof (* debug_information));
|
||||
+ debug_information = cmalloc (num_units, sizeof (*debug_information));
|
||||
if (debug_information == NULL)
|
||||
{
|
||||
error (_("Not enough memory for a debug info array of %u entries\n"),
|
||||
--
|
||||
2.43.7
|
||||
|
||||
35
meta/recipes-devtools/binutils/binutils/CVE-2025-11412.patch
Normal file
35
meta/recipes-devtools/binutils/binutils/CVE-2025-11412.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
From 047435dd988a3975d40c6626a8f739a0b2e154bc Mon Sep 17 00:00:00 2001
|
||||
From: Alan Modra <amodra@gmail.com>
|
||||
Date: Thu, 25 Sep 2025 08:22:24 +0930
|
||||
Subject: [PATCH] PR 33452 SEGV in bfd_elf_gc_record_vtentry
|
||||
|
||||
Limit addends on vtentry relocs, otherwise ld might attempt to
|
||||
allocate a stupidly large array. This also fixes the expression
|
||||
overflow leading to pr33452. A vtable of 33M entries on a 64-bit
|
||||
host is surely large enough, especially considering that VTINHERIT
|
||||
and VTENTRY relocations are to support -fvtable-gc that disappeared
|
||||
from gcc over 20 years ago.
|
||||
|
||||
PR ld/33452
|
||||
* elflink.c (bfd_elf_gc_record_vtentry): Sanity check addend.
|
||||
|
||||
CVE: CVE-2025-11412
|
||||
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=047435dd988a3975d40c6626a8f739a0b2e154bc]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
bfd/elflink.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/bfd/elflink.c b/bfd/elflink.c
|
||||
index 54f0d6e957e..0a0456177c2 100644
|
||||
--- a/bfd/elflink.c
|
||||
+++ b/bfd/elflink.c
|
||||
@@ -14407,7 +14407,7 @@ bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
unsigned int log_file_align = bed->s->log_file_align;
|
||||
|
||||
- if (!h)
|
||||
+ if (!h || addend > 1u << 28)
|
||||
{
|
||||
/* xgettext:c-format */
|
||||
_bfd_error_handler (_("%pB: section '%pA': corrupt VTENTRY entry"),
|
||||
38
meta/recipes-devtools/binutils/binutils/CVE-2025-11413.patch
Normal file
38
meta/recipes-devtools/binutils/binutils/CVE-2025-11413.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 72efdf166aa0ed72ecc69fc2349af6591a7a19c0 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Modra <amodra@gmail.com>
|
||||
Date: Thu, 25 Sep 2025 10:41:32 +0930
|
||||
Subject: [PATCH] Re: elf: Disallow the empty global symbol name
|
||||
|
||||
sparc64-linux-gnu +FAIL: selective2
|
||||
sparc64-linux-gnu +FAIL: selective3
|
||||
|
||||
PR ld/33456
|
||||
* elflink.c (elf_link_add_object_symbols): Move new check later
|
||||
to give the backend add_symbol_hook a chance to remove symbols
|
||||
with empty names.
|
||||
|
||||
CVE: CVE-2025-11413
|
||||
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=72efdf166aa0ed72ecc69fc2349af6591a7a19c0]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
bfd/elflink.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/bfd/elflink.c b/bfd/elflink.c
|
||||
index 0a0456177c2..5c8b822e36a 100644
|
||||
--- a/bfd/elflink.c
|
||||
+++ b/bfd/elflink.c
|
||||
@@ -4931,6 +4931,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (name[0] == '\0')
|
||||
+ {
|
||||
+ _bfd_error_handler (_("%pB: corrupt symbol table"), abfd);
|
||||
+ bfd_set_error (bfd_error_bad_value);
|
||||
+ goto error_free_vers;
|
||||
+ }
|
||||
+
|
||||
/* Sanity check that all possibilities were handled. */
|
||||
if (sec == NULL)
|
||||
abort ();
|
||||
71
meta/recipes-devtools/cmake/cmake/CVE-2025-9301.patch
Normal file
71
meta/recipes-devtools/cmake/cmake/CVE-2025-9301.patch
Normal file
@@ -0,0 +1,71 @@
|
||||
From 37e27f71bc356d880c908040cd0cb68fa2c371b8 Mon Sep 17 00:00:00 2001
|
||||
From: Tyler Yankee <tyler.yankee@kitware.com>
|
||||
Date: Wed, 13 Aug 2025 15:22:28 -0400
|
||||
Subject: [PATCH] foreach: Explicitly skip replay without iterations
|
||||
|
||||
As written, foreach loops with a trailing `IN` (i.e., no loop
|
||||
variable(s) given) lead to an assertion error. Handle this case by
|
||||
exiting early when we know the loop won't execute anything.
|
||||
|
||||
Fixes: #27135
|
||||
|
||||
CVE: CVE-2025-9301
|
||||
|
||||
Upstream-Status: Backport
|
||||
https://gitlab.kitware.com/cmake/cmake/-/commit/37e27f71bc356d880c908040cd0cb68fa2c371b8
|
||||
|
||||
Signed-off-by: Tyler Yankee <tyler.yankee@kitware.com>
|
||||
Signed-off-by: Saravanan <saravanan.kadambathursubramaniyam@windriver.com>
|
||||
---
|
||||
Source/cmForEachCommand.cxx | 3 +++
|
||||
Tests/RunCMake/foreach/RunCMakeTest.cmake | 1 +
|
||||
Tests/RunCMake/foreach/TrailingIn-result.txt | 1 +
|
||||
Tests/RunCMake/foreach/TrailingIn.cmake | 5 +++++
|
||||
4 files changed, 10 insertions(+)
|
||||
create mode 100644 Tests/RunCMake/foreach/TrailingIn-result.txt
|
||||
create mode 100644 Tests/RunCMake/foreach/TrailingIn.cmake
|
||||
|
||||
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
|
||||
index dcb36265..35b59960 100644
|
||||
--- a/Source/cmForEachCommand.cxx
|
||||
+++ b/Source/cmForEachCommand.cxx
|
||||
@@ -100,6 +100,9 @@ bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
|
||||
bool cmForEachFunctionBlocker::Replay(
|
||||
std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus)
|
||||
{
|
||||
+ if (this->Args.size() == this->IterationVarsCount) {
|
||||
+ return true;
|
||||
+ }
|
||||
return this->ZipLists ? this->ReplayZipLists(functions, inStatus)
|
||||
: this->ReplayItems(functions, inStatus);
|
||||
}
|
||||
diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake
|
||||
index 15ca4770..acfc742e 100644
|
||||
--- a/Tests/RunCMake/foreach/RunCMakeTest.cmake
|
||||
+++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake
|
||||
@@ -22,3 +22,4 @@ run_cmake(foreach-RANGE-invalid-test)
|
||||
run_cmake(foreach-RANGE-out-of-range-test)
|
||||
run_cmake(foreach-var-scope-CMP0124-OLD)
|
||||
run_cmake(foreach-var-scope-CMP0124-NEW)
|
||||
+run_cmake(TrailingIn)
|
||||
diff --git a/Tests/RunCMake/foreach/TrailingIn-result.txt b/Tests/RunCMake/foreach/TrailingIn-result.txt
|
||||
new file mode 100644
|
||||
index 00000000..573541ac
|
||||
--- /dev/null
|
||||
+++ b/Tests/RunCMake/foreach/TrailingIn-result.txt
|
||||
@@ -0,0 +1 @@
|
||||
+0
|
||||
diff --git a/Tests/RunCMake/foreach/TrailingIn.cmake b/Tests/RunCMake/foreach/TrailingIn.cmake
|
||||
new file mode 100644
|
||||
index 00000000..e2b5b2f2
|
||||
--- /dev/null
|
||||
+++ b/Tests/RunCMake/foreach/TrailingIn.cmake
|
||||
@@ -0,0 +1,5 @@
|
||||
+foreach(v IN)
|
||||
+endforeach()
|
||||
+
|
||||
+foreach(v1 v2 IN)
|
||||
+endforeach()
|
||||
--
|
||||
2.35.5
|
||||
|
||||
@@ -12,6 +12,7 @@ SRC_URI:append:class-nativesdk = " \
|
||||
file://0001-CMakeDetermineSystem-use-oe-environment-vars-to-load.patch \
|
||||
file://0001-ctest-Allow-arbitrary-characters-in-test-names-of-CT.patch \
|
||||
"
|
||||
SRC_URI += "file://CVE-2025-9301.patch"
|
||||
|
||||
LICENSE:append = " & BSD-1-Clause & MIT"
|
||||
LIC_FILES_CHKSUM:append = " \
|
||||
|
||||
@@ -25,6 +25,8 @@ SRC_URI = "https://sourceware.org/elfutils/ftp/${PV}/${BP}.tar.bz2 \
|
||||
file://0001-debuginfod-debuginfod-client.c-use-long-for-cache-ti.patch \
|
||||
file://CVE-2025-1352.patch \
|
||||
file://CVE-2025-1372.patch \
|
||||
file://CVE-2025-1376.patch \
|
||||
file://CVE-2025-1377.patch \
|
||||
"
|
||||
SRC_URI:append:libc-musl = " \
|
||||
file://0003-musl-utils.patch \
|
||||
|
||||
58
meta/recipes-devtools/elfutils/files/CVE-2025-1376.patch
Normal file
58
meta/recipes-devtools/elfutils/files/CVE-2025-1376.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From b16f441cca0a4841050e3215a9f120a6d8aea918 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Wielaard <mark@klomp.org>
|
||||
Date: Thu, 13 Feb 2025 00:02:32 +0100
|
||||
Subject: [PATCH] libelf: Handle elf_strptr on section without any data
|
||||
|
||||
In the unlikely situation that elf_strptr was called on a section with
|
||||
sh_size already set, but that doesn't have any data yet we could crash
|
||||
trying to verify the string to return.
|
||||
|
||||
This could happen for example when a new section was created with
|
||||
elf_newscn, but no data having been added yet.
|
||||
|
||||
* libelf/elf_strptr.c (elf_strptr): Check strscn->rawdata_base
|
||||
is not NULL.
|
||||
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=32672
|
||||
|
||||
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
||||
|
||||
CVE: CVE-2025-1376
|
||||
|
||||
Upstream-Status: Backport [https://sourceware.org/git/?p=elfutils.git;a=commit;h=b16f441cca0a4841050e3215a9f120a6d8aea918]
|
||||
|
||||
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
|
||||
---
|
||||
libelf/elf_strptr.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libelf/elf_strptr.c b/libelf/elf_strptr.c
|
||||
index c5a94f8..7be7f5e 100644
|
||||
--- a/libelf/elf_strptr.c
|
||||
+++ b/libelf/elf_strptr.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Return string pointer from string section.
|
||||
Copyright (C) 1998-2002, 2004, 2008, 2009, 2015 Red Hat, Inc.
|
||||
+ Copyright (C) 2025 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@@ -183,9 +184,12 @@ elf_strptr (Elf *elf, size_t idx, size_t offset)
|
||||
// initialized yet (when data_read is zero). So we cannot just
|
||||
// look at the rawdata.d.d_size.
|
||||
|
||||
- /* Make sure the string is NUL terminated. Start from the end,
|
||||
- which very likely is a NUL char. */
|
||||
- if (likely (validate_str (strscn->rawdata_base, offset, sh_size)))
|
||||
+ /* First check there actually is any data. This could be a new
|
||||
+ section which hasn't had any data set yet. Then make sure
|
||||
+ the string is at a valid offset and NUL terminated. */
|
||||
+ if (unlikely (strscn->rawdata_base == NULL))
|
||||
+ __libelf_seterrno (ELF_E_INVALID_SECTION);
|
||||
+ else if (likely (validate_str (strscn->rawdata_base, offset, sh_size)))
|
||||
result = &strscn->rawdata_base[offset];
|
||||
else
|
||||
__libelf_seterrno (ELF_E_INVALID_INDEX);
|
||||
--
|
||||
2.40.0
|
||||
|
||||
68
meta/recipes-devtools/elfutils/files/CVE-2025-1377.patch
Normal file
68
meta/recipes-devtools/elfutils/files/CVE-2025-1377.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
From fbf1df9ca286de3323ae541973b08449f8d03aba Mon Sep 17 00:00:00 2001
|
||||
From: Mark Wielaard <mark@klomp.org>
|
||||
Date: Thu, 13 Feb 2025 14:59:34 +0100
|
||||
Subject: [PATCH] strip: Verify symbol table is a real symbol table
|
||||
|
||||
We didn't check the symbol table referenced from the relocation table
|
||||
was a real symbol table. This could cause a crash if that section
|
||||
happened to be an SHT_NOBITS section without any data. Fix this by
|
||||
adding an explicit check.
|
||||
|
||||
* src/strip.c (INTERNAL_ERROR_MSG): New macro that takes a
|
||||
message string to display.
|
||||
(INTERNAL_ERROR): Use INTERNAL_ERROR_MSG with elf_errmsg (-1).
|
||||
(remove_debug_relocations): Check the sh_link referenced
|
||||
section is real and isn't a SHT_NOBITS section.
|
||||
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=32673
|
||||
|
||||
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
||||
|
||||
CVE: CVE-2025-1377
|
||||
|
||||
Upstream-Status: Backport [https://sourceware.org/git/?p=elfutils.git;a=commit;h=fbf1df9ca286de3323ae541973b08449f8d03aba]
|
||||
|
||||
Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
|
||||
---
|
||||
src/strip.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/strip.c b/src/strip.c
|
||||
index d5b753d..0cfd8c8 100644
|
||||
--- a/src/strip.c
|
||||
+++ b/src/strip.c
|
||||
@@ -127,13 +127,14 @@ static char *tmp_debug_fname = NULL;
|
||||
/* Close debug file descriptor, if opened. And remove temporary debug file. */
|
||||
static void cleanup_debug (void);
|
||||
|
||||
-#define INTERNAL_ERROR(fname) \
|
||||
+#define INTERNAL_ERROR_MSG(fname, msg) \
|
||||
do { \
|
||||
cleanup_debug (); \
|
||||
error (EXIT_FAILURE, 0, _("%s: INTERNAL ERROR %d (%s): %s"), \
|
||||
- fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1)); \
|
||||
+ fname, __LINE__, PACKAGE_VERSION, msg); \
|
||||
} while (0)
|
||||
|
||||
+#define INTERNAL_ERROR(fname) INTERNAL_ERROR_MSG(fname, elf_errmsg (-1))
|
||||
|
||||
/* Name of the output file. */
|
||||
static const char *output_fname;
|
||||
@@ -632,7 +633,13 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
|
||||
resolve relocation symbol indexes. */
|
||||
Elf64_Word symt = shdr->sh_link;
|
||||
Elf_Data *symdata, *xndxdata;
|
||||
- Elf_Scn * symscn = elf_getscn (elf, symt);
|
||||
+ Elf_Scn *symscn = elf_getscn (elf, symt);GElf_Shdr symshdr_mem;
|
||||
+ GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
|
||||
+ if (symshdr == NULL)
|
||||
+ INTERNAL_ERROR (fname);
|
||||
+ if (symshdr->sh_type == SHT_NOBITS)
|
||||
+ INTERNAL_ERROR_MSG (fname, "NOBITS section");
|
||||
+
|
||||
symdata = elf_getdata (symscn, NULL);
|
||||
xndxdata = get_xndxdata (elf, symscn);
|
||||
if (symdata == NULL)
|
||||
--
|
||||
2.40.0
|
||||
|
||||
97
meta/recipes-devtools/git/git/CVE-2025-48386.patch
Normal file
97
meta/recipes-devtools/git/git/CVE-2025-48386.patch
Normal file
@@ -0,0 +1,97 @@
|
||||
From 9de345cb273cc7faaeda279c7e07149d8a15a319 Mon Sep 17 00:00:00 2001
|
||||
From: Taylor Blau <me@ttaylorr.com>
|
||||
Date: Mon, 19 May 2025 18:30:29 -0400
|
||||
Subject: [PATCH] wincred: avoid buffer overflow in wcsncat()
|
||||
|
||||
The wincred credential helper uses a static buffer ("target") as a
|
||||
unique key for storing and comparing against internal storage. It does
|
||||
this by building up a string is supposed to look like:
|
||||
|
||||
git:$PROTOCOL://$USERNAME@$HOST/@path
|
||||
|
||||
However, the static "target" buffer is declared as a wide string with no
|
||||
more than 1,024 wide characters. The first call to wcsncat() is almost
|
||||
correct (it copies no more than ARRAY_SIZE(target) wchar_t's), but does
|
||||
not account for the trailing NUL, introducing an off-by-one error.
|
||||
|
||||
But subsequent calls to wcsncat() have an additional problem on top of
|
||||
the off-by-one. They do not account for the length of the existing
|
||||
wide string being built up in 'target'. So the following:
|
||||
|
||||
$ perl -e '
|
||||
my $x = "x" x 1_000;
|
||||
print "protocol=$x\nhost=$x\nusername=$x\npath=$x\n"
|
||||
' |
|
||||
C\:/Program\ Files/Git/mingw64/libexec/git-core/git-credential-wincred.exe get
|
||||
|
||||
will result in a segmentation fault from over-filling buffer.
|
||||
|
||||
This bug is as old as the wincred helper itself, dating back to
|
||||
a6253da (contrib: add win32 credential-helper, 2012-07-27). Commit
|
||||
8b2d219 (wincred: improve compatibility with windows versions,
|
||||
2013-01-10) replaced the use of strncat() with wcsncat(), but retained
|
||||
the buggy behavior.
|
||||
|
||||
Fix this by using a "target_append()" helper which accounts for both the
|
||||
length of the existing string within the buffer, as well as the trailing
|
||||
NUL character.
|
||||
|
||||
Reported-by: David Leadbeater <dgl@dgl.cx>
|
||||
Helped-by: David Leadbeater <dgl@dgl.cx>
|
||||
Helped-by: Jeff King <peff@peff.net>
|
||||
Signed-off-by: Taylor Blau <me@ttaylorr.com>
|
||||
|
||||
CVE: CVE-2025-48386
|
||||
Upstream-Status: Backport [https://github.com/git/git/commit/9de345cb273cc7faaeda279c7e07149d8a15a319]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
.../wincred/git-credential-wincred.c | 22 +++++++++++++------
|
||||
1 file changed, 15 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
|
||||
index 5091048..00ecd87 100644
|
||||
--- a/contrib/credential/wincred/git-credential-wincred.c
|
||||
+++ b/contrib/credential/wincred/git-credential-wincred.c
|
||||
@@ -93,6 +93,14 @@ static void load_cred_funcs(void)
|
||||
|
||||
static WCHAR *wusername, *password, *protocol, *host, *path, target[1024];
|
||||
|
||||
+static void target_append(const WCHAR *src)
|
||||
+{
|
||||
+ size_t avail = ARRAY_SIZE(target) - wcslen(target) - 1; /* -1 for NUL */
|
||||
+ if (avail < wcslen(src))
|
||||
+ die("target buffer overflow");
|
||||
+ wcsncat(target, src, avail);
|
||||
+}
|
||||
+
|
||||
static void write_item(const char *what, LPCWSTR wbuf, int wlen)
|
||||
{
|
||||
char *buf;
|
||||
@@ -304,17 +312,17 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* prepare 'target', the unique key for the credential */
|
||||
wcscpy(target, L"git:");
|
||||
- wcsncat(target, protocol, ARRAY_SIZE(target));
|
||||
- wcsncat(target, L"://", ARRAY_SIZE(target));
|
||||
+ target_append(protocol);
|
||||
+ target_append(L"://");
|
||||
if (wusername) {
|
||||
- wcsncat(target, wusername, ARRAY_SIZE(target));
|
||||
- wcsncat(target, L"@", ARRAY_SIZE(target));
|
||||
+ target_append(wusername);
|
||||
+ target_append(L"@");
|
||||
}
|
||||
if (host)
|
||||
- wcsncat(target, host, ARRAY_SIZE(target));
|
||||
+ target_append(host);
|
||||
if (path) {
|
||||
- wcsncat(target, L"/", ARRAY_SIZE(target));
|
||||
- wcsncat(target, path, ARRAY_SIZE(target));
|
||||
+ target_append(L"/");
|
||||
+ target_append(path);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "get"))
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@@ -28,6 +28,7 @@ SRC_URI = "${KERNELORG_MIRROR}/software/scm/git/git-${PV}.tar.gz;name=tarball \
|
||||
file://CVE-2024-52006.patch \
|
||||
file://CVE-2025-27614-CVE-2025-27613-CVE-2025-46334-CVE-2025-46835.patch \
|
||||
file://CVE-2025-48384.patch \
|
||||
file://CVE-2025-48386.patch \
|
||||
"
|
||||
|
||||
S = "${WORKDIR}/git-${PV}"
|
||||
|
||||
@@ -4,67 +4,76 @@ FILESEXTRAPATHS:prepend := "${FILE_DIRNAME}/go-1.21:${FILE_DIRNAME}/go-1.20:${FI
|
||||
|
||||
LIC_FILES_CHKSUM = "file://LICENSE;md5=5d4950ecb7b26d2c5e4e7b4e0dd74707"
|
||||
|
||||
SRC_URI += "\
|
||||
file://0001-allow-CC-and-CXX-to-have-multiple-words.patch \
|
||||
file://0002-cmd-go-make-content-based-hash-generation-less-pedan.patch \
|
||||
file://0003-allow-GOTOOLDIR-to-be-overridden-in-the-environment.patch \
|
||||
file://0004-ld-add-soname-to-shareable-objects.patch \
|
||||
file://0005-make.bash-override-CC-when-building-dist-and-go_boot.patch \
|
||||
file://0006-cmd-dist-separate-host-and-target-builds.patch \
|
||||
file://0007-cmd-go-make-GOROOT-precious-by-default.patch \
|
||||
file://0008-use-GOBUILDMODE-to-set-buildmode.patch \
|
||||
file://0009-Revert-cmd-go-make-sure-CC-and-CXX-are-absolute.patch \
|
||||
file://0001-exec.go-do-not-write-linker-flags-into-buildids.patch \
|
||||
file://0001-src-cmd-dist-buildgo.go-do-not-hardcode-host-compile.patch \
|
||||
file://0010-net-Fix-issue-with-DNS-not-being-updated.patch \
|
||||
file://CVE-2022-27664.patch \
|
||||
file://0001-net-http-httputil-avoid-query-parameter-smuggling.patch \
|
||||
file://CVE-2022-41715.patch \
|
||||
file://CVE-2022-41717.patch \
|
||||
file://CVE-2022-2879.patch \
|
||||
file://CVE-2022-41720.patch \
|
||||
file://CVE-2022-41723.patch \
|
||||
file://cve-2022-41724.patch \
|
||||
file://add_godebug.patch \
|
||||
file://cve-2022-41725.patch \
|
||||
file://CVE-2022-41722.patch \
|
||||
file://CVE-2023-24537.patch \
|
||||
file://CVE-2023-24534.patch \
|
||||
file://CVE-2023-24538_1.patch \
|
||||
file://CVE-2023-24538_2.patch \
|
||||
file://CVE-2023-24540.patch \
|
||||
file://CVE-2023-24539.patch \
|
||||
file://CVE-2023-29404.patch \
|
||||
file://CVE-2023-29405.patch \
|
||||
file://CVE-2023-29402.patch \
|
||||
file://CVE-2023-29400.patch \
|
||||
file://CVE-2023-29406-1.patch \
|
||||
file://CVE-2023-29406-2.patch \
|
||||
file://CVE-2023-24536_1.patch \
|
||||
file://CVE-2023-24536_2.patch \
|
||||
file://CVE-2023-24536_3.patch \
|
||||
file://CVE-2023-24531_1.patch \
|
||||
file://CVE-2023-24531_2.patch \
|
||||
file://CVE-2023-29409.patch \
|
||||
file://CVE-2023-39319.patch \
|
||||
file://CVE-2023-39318.patch \
|
||||
file://CVE-2023-39326.patch \
|
||||
file://CVE-2023-45285.patch \
|
||||
file://CVE-2023-45287.patch \
|
||||
file://CVE-2023-45289.patch \
|
||||
file://CVE-2023-45290.patch \
|
||||
file://CVE-2024-24784.patch \
|
||||
file://CVE-2024-24785.patch \
|
||||
file://CVE-2023-45288.patch \
|
||||
file://CVE-2024-24789.patch \
|
||||
file://CVE-2024-24791.patch \
|
||||
file://CVE-2024-34155.patch \
|
||||
file://CVE-2024-34156.patch \
|
||||
file://CVE-2024-34158.patch \
|
||||
file://CVE-2024-45336.patch \
|
||||
file://CVE-2025-22871.patch \
|
||||
file://CVE-2025-4673.patch \
|
||||
"
|
||||
SRC_URI = "https://golang.org/dl/go${PV}.src.tar.gz;name=main \
|
||||
file://0001-allow-CC-and-CXX-to-have-multiple-words.patch \
|
||||
file://0002-cmd-go-make-content-based-hash-generation-less-pedan.patch \
|
||||
file://0003-allow-GOTOOLDIR-to-be-overridden-in-the-environment.patch \
|
||||
file://0004-ld-add-soname-to-shareable-objects.patch \
|
||||
file://0005-make.bash-override-CC-when-building-dist-and-go_boot.patch \
|
||||
file://0006-cmd-dist-separate-host-and-target-builds.patch \
|
||||
file://0007-cmd-go-make-GOROOT-precious-by-default.patch \
|
||||
file://0008-use-GOBUILDMODE-to-set-buildmode.patch \
|
||||
file://0009-Revert-cmd-go-make-sure-CC-and-CXX-are-absolute.patch \
|
||||
file://0001-exec.go-do-not-write-linker-flags-into-buildids.patch \
|
||||
file://0001-src-cmd-dist-buildgo.go-do-not-hardcode-host-compile.patch \
|
||||
file://0010-net-Fix-issue-with-DNS-not-being-updated.patch \
|
||||
file://CVE-2022-27664.patch \
|
||||
file://0001-net-http-httputil-avoid-query-parameter-smuggling.patch \
|
||||
file://CVE-2022-41715.patch \
|
||||
file://CVE-2022-41717.patch \
|
||||
file://CVE-2022-2879.patch \
|
||||
file://CVE-2022-41720.patch \
|
||||
file://CVE-2022-41723.patch \
|
||||
file://cve-2022-41724.patch \
|
||||
file://add_godebug.patch \
|
||||
file://cve-2022-41725.patch \
|
||||
file://CVE-2022-41722.patch \
|
||||
file://CVE-2023-24537.patch \
|
||||
file://CVE-2023-24534.patch \
|
||||
file://CVE-2023-24538_1.patch \
|
||||
file://CVE-2023-24538_2.patch \
|
||||
file://CVE-2023-24540.patch \
|
||||
file://CVE-2023-24539.patch \
|
||||
file://CVE-2023-29404.patch \
|
||||
file://CVE-2023-29405.patch \
|
||||
file://CVE-2023-29402.patch \
|
||||
file://CVE-2023-29400.patch \
|
||||
file://CVE-2023-29406-1.patch \
|
||||
file://CVE-2023-29406-2.patch \
|
||||
file://CVE-2023-24536_1.patch \
|
||||
file://CVE-2023-24536_2.patch \
|
||||
file://CVE-2023-24536_3.patch \
|
||||
file://CVE-2023-24531_1.patch \
|
||||
file://CVE-2023-24531_2.patch \
|
||||
file://CVE-2023-29409.patch \
|
||||
file://CVE-2023-39319.patch \
|
||||
file://CVE-2023-39318.patch \
|
||||
file://CVE-2023-39326.patch \
|
||||
file://CVE-2023-45285.patch \
|
||||
file://CVE-2023-45287.patch \
|
||||
file://CVE-2023-45289.patch \
|
||||
file://CVE-2023-45290.patch \
|
||||
file://CVE-2024-24784.patch \
|
||||
file://CVE-2024-24785.patch \
|
||||
file://CVE-2023-45288.patch \
|
||||
file://CVE-2024-24789.patch \
|
||||
file://CVE-2024-24791.patch \
|
||||
file://CVE-2024-34155.patch \
|
||||
file://CVE-2024-34156.patch \
|
||||
file://CVE-2024-34158.patch \
|
||||
file://CVE-2024-45336.patch \
|
||||
file://CVE-2025-22871.patch \
|
||||
file://CVE-2025-4673.patch \
|
||||
file://CVE-2025-47907-pre-0001.patch \
|
||||
file://CVE-2025-47907-pre-0002.patch \
|
||||
file://CVE-2025-47907.patch \
|
||||
file://CVE-2025-47906.patch \
|
||||
file://CVE-2024-24783.patch \
|
||||
file://CVE-2025-58187.patch \
|
||||
file://CVE-2025-58189.patch \
|
||||
file://CVE-2025-61723.patch \
|
||||
file://CVE-2025-61724.patch \
|
||||
"
|
||||
SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd"
|
||||
|
||||
# Upstream don't believe it is a signifiant real world issue and will only
|
||||
|
||||
349
meta/recipes-devtools/go/go-1.18/CVE-2025-58187.patch
Normal file
349
meta/recipes-devtools/go/go-1.18/CVE-2025-58187.patch
Normal file
@@ -0,0 +1,349 @@
|
||||
From f334417e71f8b078ad64035bddb6df7f8910da6c Mon Sep 17 00:00:00 2001
|
||||
From: Neal Patel <nealpatel@google.com>
|
||||
Date: Mon, 15 Sep 2025 16:31:22 -0400
|
||||
Subject: [PATCH] crypto/x509: improve domain name verification
|
||||
|
||||
Don't use domainToReverseLabels to check if domain names are valid,
|
||||
since it is not particularly performant, and can contribute to DoS
|
||||
vectors. Instead just iterate over the name and enforce the properties
|
||||
we care about.
|
||||
|
||||
This also enforces that DNS names, both in SANs and name constraints,
|
||||
are valid. We previously allowed invalid SANs, because some
|
||||
intermediates had these weird names (see #23995), but there are
|
||||
currently no trusted intermediates that have this property, and since we
|
||||
target the web PKI, supporting this particular case is not a high
|
||||
priority.
|
||||
|
||||
Thank you to Jakub Ciolek for reporting this issue.
|
||||
|
||||
Fixes CVE-2025-58187
|
||||
For #75681
|
||||
Fixes #75714
|
||||
|
||||
Change-Id: I6ebce847dcbe5fc63ef2f9a74f53f11c4c56d3d1
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2820
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2982
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/709839
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
|
||||
CVE: CVE-2025-58187
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/f334417e71f8b078ad64035bddb6df7f8910da6c]
|
||||
|
||||
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
||||
---
|
||||
src/crypto/x509/name_constraints_test.go | 66 ++------------------
|
||||
src/crypto/x509/parser.go | 77 ++++++++++++++----------
|
||||
src/crypto/x509/parser_test.go | 43 +++++++++++++
|
||||
src/crypto/x509/verify.go | 1 +
|
||||
4 files changed, 95 insertions(+), 92 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go
|
||||
index c59a7dc..d4f7d41 100644
|
||||
--- a/src/crypto/x509/name_constraints_test.go
|
||||
+++ b/src/crypto/x509/name_constraints_test.go
|
||||
@@ -1452,63 +1452,7 @@ var nameConstraintsTests = []nameConstraintsTest{
|
||||
requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
|
||||
},
|
||||
|
||||
- // An invalid DNS SAN should be detected only at validation time so
|
||||
- // that we can process CA certificates in the wild that have invalid SANs.
|
||||
- // See https://github.com/golang/go/issues/23995
|
||||
-
|
||||
- // #77: an invalid DNS or mail SAN will not be detected if name constraint
|
||||
- // checking is not triggered.
|
||||
- {
|
||||
- roots: make([]constraintsSpec, 1),
|
||||
- intermediates: [][]constraintsSpec{
|
||||
- {
|
||||
- {},
|
||||
- },
|
||||
- },
|
||||
- leaf: leafSpec{
|
||||
- sans: []string{"dns:this is invalid", "email:this @ is invalid"},
|
||||
- },
|
||||
- },
|
||||
-
|
||||
- // #78: an invalid DNS SAN will be detected if any name constraint checking
|
||||
- // is triggered.
|
||||
- {
|
||||
- roots: []constraintsSpec{
|
||||
- {
|
||||
- bad: []string{"uri:"},
|
||||
- },
|
||||
- },
|
||||
- intermediates: [][]constraintsSpec{
|
||||
- {
|
||||
- {},
|
||||
- },
|
||||
- },
|
||||
- leaf: leafSpec{
|
||||
- sans: []string{"dns:this is invalid"},
|
||||
- },
|
||||
- expectedError: "cannot parse dnsName",
|
||||
- },
|
||||
-
|
||||
- // #79: an invalid email SAN will be detected if any name constraint
|
||||
- // checking is triggered.
|
||||
- {
|
||||
- roots: []constraintsSpec{
|
||||
- {
|
||||
- bad: []string{"uri:"},
|
||||
- },
|
||||
- },
|
||||
- intermediates: [][]constraintsSpec{
|
||||
- {
|
||||
- {},
|
||||
- },
|
||||
- },
|
||||
- leaf: leafSpec{
|
||||
- sans: []string{"email:this @ is invalid"},
|
||||
- },
|
||||
- expectedError: "cannot parse rfc822Name",
|
||||
- },
|
||||
-
|
||||
- // #80: if several EKUs are requested, satisfying any of them is sufficient.
|
||||
+ // #77: if several EKUs are requested, satisfying any of them is sufficient.
|
||||
{
|
||||
roots: make([]constraintsSpec, 1),
|
||||
intermediates: [][]constraintsSpec{
|
||||
@@ -1523,7 +1467,7 @@ var nameConstraintsTests = []nameConstraintsTest{
|
||||
requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection},
|
||||
},
|
||||
|
||||
- // #81: EKUs that are not asserted in VerifyOpts are not required to be
|
||||
+ // #78: EKUs that are not asserted in VerifyOpts are not required to be
|
||||
// nested.
|
||||
{
|
||||
roots: make([]constraintsSpec, 1),
|
||||
@@ -1542,7 +1486,7 @@ var nameConstraintsTests = []nameConstraintsTest{
|
||||
},
|
||||
},
|
||||
|
||||
- // #82: a certificate without SANs and CN is accepted in a constrained chain.
|
||||
+ // #79: a certificate without SANs and CN is accepted in a constrained chain.
|
||||
{
|
||||
roots: []constraintsSpec{
|
||||
{
|
||||
@@ -1559,7 +1503,7 @@ var nameConstraintsTests = []nameConstraintsTest{
|
||||
},
|
||||
},
|
||||
|
||||
- // #83: a certificate without SANs and with a CN that does not parse as a
|
||||
+ // #80: a certificate without SANs and with a CN that does not parse as a
|
||||
// hostname is accepted in a constrained chain.
|
||||
{
|
||||
roots: []constraintsSpec{
|
||||
@@ -1578,7 +1522,7 @@ var nameConstraintsTests = []nameConstraintsTest{
|
||||
},
|
||||
},
|
||||
|
||||
- // #84: a certificate with SANs and CN is accepted in a constrained chain.
|
||||
+ // #81: a certificate with SANs and CN is accepted in a constrained chain.
|
||||
{
|
||||
roots: []constraintsSpec{
|
||||
{
|
||||
diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go
|
||||
index 635e74b..0788210 100644
|
||||
--- a/src/crypto/x509/parser.go
|
||||
+++ b/src/crypto/x509/parser.go
|
||||
@@ -391,10 +391,14 @@ func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string
|
||||
if err := isIA5String(email); err != nil {
|
||||
return errors.New("x509: SAN rfc822Name is malformed")
|
||||
}
|
||||
+ parsed, ok := parseRFC2821Mailbox(email)
|
||||
+ if !ok || (ok && !domainNameValid(parsed.domain, false)) {
|
||||
+ return errors.New("x509: SAN rfc822Name is malformed")
|
||||
+ }
|
||||
emailAddresses = append(emailAddresses, email)
|
||||
case nameTypeDNS:
|
||||
name := string(data)
|
||||
- if err := isIA5String(name); err != nil {
|
||||
+ if err := isIA5String(name); err != nil || (err == nil && !domainNameValid(name, false)) {
|
||||
return errors.New("x509: SAN dNSName is malformed")
|
||||
}
|
||||
dnsNames = append(dnsNames, string(name))
|
||||
@@ -404,14 +408,9 @@ func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string
|
||||
return errors.New("x509: SAN uniformResourceIdentifier is malformed")
|
||||
}
|
||||
uri, err := url.Parse(uriStr)
|
||||
- if err != nil {
|
||||
+ if err != nil || (err == nil && uri.Host != "" && !domainNameValid(uri.Host, false)) {
|
||||
return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err)
|
||||
}
|
||||
- if len(uri.Host) > 0 {
|
||||
- if _, ok := domainToReverseLabels(uri.Host); !ok {
|
||||
- return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr)
|
||||
- }
|
||||
- }
|
||||
uris = append(uris, uri)
|
||||
case nameTypeIP:
|
||||
switch len(data) {
|
||||
@@ -551,15 +550,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle
|
||||
return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error())
|
||||
}
|
||||
|
||||
- trimmedDomain := domain
|
||||
- if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {
|
||||
- // constraints can have a leading
|
||||
- // period to exclude the domain
|
||||
- // itself, but that's not valid in a
|
||||
- // normal domain name.
|
||||
- trimmedDomain = trimmedDomain[1:]
|
||||
- }
|
||||
- if _, ok := domainToReverseLabels(trimmedDomain); !ok {
|
||||
+ if !domainNameValid(domain, true) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain)
|
||||
}
|
||||
dnsNames = append(dnsNames, domain)
|
||||
@@ -600,12 +591,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle
|
||||
return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)
|
||||
}
|
||||
} else {
|
||||
- // Otherwise it's a domain name.
|
||||
- domain := constraint
|
||||
- if len(domain) > 0 && domain[0] == '.' {
|
||||
- domain = domain[1:]
|
||||
- }
|
||||
- if _, ok := domainToReverseLabels(domain); !ok {
|
||||
+ if !domainNameValid(constraint, true) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint)
|
||||
}
|
||||
}
|
||||
@@ -621,15 +607,7 @@ func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandle
|
||||
return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain)
|
||||
}
|
||||
|
||||
- trimmedDomain := domain
|
||||
- if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' {
|
||||
- // constraints can have a leading
|
||||
- // period to exclude the domain itself,
|
||||
- // but that's not valid in a normal
|
||||
- // domain name.
|
||||
- trimmedDomain = trimmedDomain[1:]
|
||||
- }
|
||||
- if _, ok := domainToReverseLabels(trimmedDomain); !ok {
|
||||
+ if !domainNameValid(domain, true) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain)
|
||||
}
|
||||
uriDomains = append(uriDomains, domain)
|
||||
@@ -1011,3 +989,40 @@ func ParseCertificates(der []byte) ([]*Certificate, error) {
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
+
|
||||
+// domainNameValid does minimal domain name validity checking. In particular it
|
||||
+// enforces the following properties:
|
||||
+// - names cannot have the trailing period
|
||||
+// - names can only have a leading period if constraint is true
|
||||
+// - names must be <= 253 characters
|
||||
+// - names cannot have empty labels
|
||||
+// - names cannot labels that are longer than 63 characters
|
||||
+//
|
||||
+// Note that this does not enforce the LDH requirements for domain names.
|
||||
+func domainNameValid(s string, constraint bool) bool {
|
||||
+ if len(s) == 0 && constraint {
|
||||
+ return true
|
||||
+ }
|
||||
+ if len(s) == 0 || (!constraint && s[0] == '.') || s[len(s)-1] == '.' || len(s) > 253 {
|
||||
+ return false
|
||||
+ }
|
||||
+ lastDot := -1
|
||||
+ if constraint && s[0] == '.' {
|
||||
+ s = s[1:]
|
||||
+ }
|
||||
+
|
||||
+ for i := 0; i <= len(s); i++ {
|
||||
+ if i == len(s) || s[i] == '.' {
|
||||
+ labelLen := i
|
||||
+ if lastDot >= 0 {
|
||||
+ labelLen -= lastDot + 1
|
||||
+ }
|
||||
+ if labelLen == 0 || labelLen > 63 {
|
||||
+ return false
|
||||
+ }
|
||||
+ lastDot = i
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true
|
||||
+}
|
||||
diff --git a/src/crypto/x509/parser_test.go b/src/crypto/x509/parser_test.go
|
||||
index d7cf7ea..95ed116 100644
|
||||
--- a/src/crypto/x509/parser_test.go
|
||||
+++ b/src/crypto/x509/parser_test.go
|
||||
@@ -5,6 +5,7 @@ package x509
|
||||
|
||||
import (
|
||||
"encoding/asn1"
|
||||
+ "strings"
|
||||
"testing"
|
||||
|
||||
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
|
||||
@@ -100,3 +101,45 @@ func TestParseASN1String(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestDomainNameValid(t *testing.T) {
|
||||
+ for _, tc := range []struct {
|
||||
+ name string
|
||||
+ dnsName string
|
||||
+ constraint bool
|
||||
+ valid bool
|
||||
+ }{
|
||||
+ {"empty name, name", "", false, false},
|
||||
+ {"empty name, constraint", "", true, true},
|
||||
+ {"empty label, name", "a..a", false, false},
|
||||
+ {"empty label, constraint", "a..a", true, false},
|
||||
+ {"period, name", ".", false, false},
|
||||
+ {"period, constraint", ".", true, false}, // TODO(roland): not entirely clear if this is a valid constraint (require at least one label?)
|
||||
+ {"valid, name", "a.b.c", false, true},
|
||||
+ {"valid, constraint", "a.b.c", true, true},
|
||||
+ {"leading period, name", ".a.b.c", false, false},
|
||||
+ {"leading period, constraint", ".a.b.c", true, true},
|
||||
+ {"trailing period, name", "a.", false, false},
|
||||
+ {"trailing period, constraint", "a.", true, false},
|
||||
+ {"bare label, name", "a", false, true},
|
||||
+ {"bare label, constraint", "a", true, true},
|
||||
+ {"254 char label, name", strings.Repeat("a.a", 84) + "aaa", false, false},
|
||||
+ {"254 char label, constraint", strings.Repeat("a.a", 84) + "aaa", true, false},
|
||||
+ {"253 char label, name", strings.Repeat("a.a", 84) + "aa", false, false},
|
||||
+ {"253 char label, constraint", strings.Repeat("a.a", 84) + "aa", true, false},
|
||||
+ {"64 char single label, name", strings.Repeat("a", 64), false, false},
|
||||
+ {"64 char single label, constraint", strings.Repeat("a", 64), true, false},
|
||||
+ {"63 char single label, name", strings.Repeat("a", 63), false, true},
|
||||
+ {"63 char single label, constraint", strings.Repeat("a", 63), true, true},
|
||||
+ {"64 char label, name", "a." + strings.Repeat("a", 64), false, false},
|
||||
+ {"64 char label, constraint", "a." + strings.Repeat("a", 64), true, false},
|
||||
+ {"63 char label, name", "a." + strings.Repeat("a", 63), false, true},
|
||||
+ {"63 char label, constraint", "a." + strings.Repeat("a", 63), true, true},
|
||||
+ } {
|
||||
+ t.Run(tc.name, func(t *testing.T) {
|
||||
+ if tc.valid != domainNameValid(tc.dnsName, tc.constraint) {
|
||||
+ t.Errorf("domainNameValid(%q, %t) = %v; want %v", tc.dnsName, tc.constraint, !tc.valid, tc.valid)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
|
||||
index 3e95808..fb2f4b2 100644
|
||||
--- a/src/crypto/x509/verify.go
|
||||
+++ b/src/crypto/x509/verify.go
|
||||
@@ -357,6 +357,7 @@ func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {
|
||||
// domainToReverseLabels converts a textual domain name like foo.example.com to
|
||||
// the list of labels in reverse order, e.g. ["com", "example", "foo"].
|
||||
func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
|
||||
+ reverseLabels = make([]string, 0, strings.Count(domain, ".")+1)
|
||||
for len(domain) > 0 {
|
||||
if i := strings.LastIndexByte(domain, '.'); i == -1 {
|
||||
reverseLabels = append(reverseLabels, domain)
|
||||
--
|
||||
2.40.0
|
||||
|
||||
51
meta/recipes-devtools/go/go-1.18/CVE-2025-58189.patch
Normal file
51
meta/recipes-devtools/go/go-1.18/CVE-2025-58189.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
From 2e1e356e33b9c792a9643749a7626a1789197bb9 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Mon, 29 Sep 2025 10:11:56 -0700
|
||||
Subject: [PATCH] crypto/tls: quote protocols in ALPN error message
|
||||
|
||||
Quote the protocols sent by the client when returning the ALPN
|
||||
negotiation error message.
|
||||
|
||||
Fixes CVE-2025-58189
|
||||
Updates #75652
|
||||
Fixes #75660
|
||||
|
||||
Change-Id: Ie7b3a1ed0b6efcc1705b71f0f1e8417126661330
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/707776
|
||||
Auto-Submit: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||
Reviewed-by: Nicholas Husin <nsh@golang.org>
|
||||
Auto-Submit: Nicholas Husin <nsh@golang.org>
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
TryBot-Bypass: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
|
||||
(cherry picked from commit 4e9006a716533fe1c7ee08df02dfc73078f7dc19)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/708096
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
|
||||
CVE: CVE-2025-58189
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/2e1e356e33b9c792a9643749a7626a1789197bb9]
|
||||
|
||||
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
||||
---
|
||||
src/crypto/tls/handshake_server.go | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
|
||||
index 4e84aa9..17b6891 100644
|
||||
--- a/src/crypto/tls/handshake_server.go
|
||||
+++ b/src/crypto/tls/handshake_server.go
|
||||
@@ -312,7 +312,7 @@ func negotiateALPN(serverProtos, clientProtos []string, quic bool) (string, erro
|
||||
if http11fallback {
|
||||
return "", nil
|
||||
}
|
||||
- return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos)
|
||||
+ return "", fmt.Errorf("tls: client requested unsupported application protocols (%q)", clientProtos)
|
||||
}
|
||||
|
||||
// supportsECDHE returns whether ECDHE key exchanges can be used with this
|
||||
--
|
||||
2.40.0
|
||||
|
||||
221
meta/recipes-devtools/go/go-1.18/CVE-2025-61723.patch
Normal file
221
meta/recipes-devtools/go/go-1.18/CVE-2025-61723.patch
Normal file
@@ -0,0 +1,221 @@
|
||||
From 74d4d836b91318a8764b94bc2b4b66ff599eb5f2 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Tue, 30 Sep 2025 11:16:56 -0700
|
||||
Subject: [PATCH] encoding/pem: make Decode complexity linear Because Decode
|
||||
scanned the input first for the first BEGIN line, and then the first END
|
||||
line, the complexity of Decode is quadratic. If the input contained a large
|
||||
number of BEGINs and then a single END right at the end of the input, we
|
||||
would find the first BEGIN, and then scan the entire input for the END, and
|
||||
fail to parse the block, so move onto the next BEGIN, scan the entire input
|
||||
for the END, etc.
|
||||
|
||||
Instead, look for the first END in the input, and then the first BEGIN
|
||||
that precedes the found END. We then process the bytes between the BEGIN
|
||||
and END, and move onto the bytes after the END for further processing.
|
||||
This gives us linear complexity.
|
||||
|
||||
Fixes CVE-2025-61723
|
||||
For #75676
|
||||
Fixes #75708
|
||||
|
||||
Change-Id: I813c4f63e78bca4054226c53e13865c781564ccf
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2921
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2986
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/709842
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
|
||||
CVE: CVE-2025-61723
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/74d4d836b91318a8764b94bc2b4b66ff599eb5f2]
|
||||
|
||||
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
||||
---
|
||||
src/encoding/pem/pem.go | 67 +++++++++++++++++++-----------------
|
||||
src/encoding/pem/pem_test.go | 13 +++----
|
||||
2 files changed, 43 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go
|
||||
index 1bee1c1..01bed75 100644
|
||||
--- a/src/encoding/pem/pem.go
|
||||
+++ b/src/encoding/pem/pem.go
|
||||
@@ -35,7 +35,7 @@ type Block struct {
|
||||
// line bytes. The remainder of the byte array (also not including the new line
|
||||
// bytes) is also returned and this will always be smaller than the original
|
||||
// argument.
|
||||
-func getLine(data []byte) (line, rest []byte) {
|
||||
+func getLine(data []byte) (line, rest []byte, consumed int) {
|
||||
i := bytes.IndexByte(data, '\n')
|
||||
var j int
|
||||
if i < 0 {
|
||||
@@ -47,7 +47,7 @@ func getLine(data []byte) (line, rest []byte) {
|
||||
i--
|
||||
}
|
||||
}
|
||||
- return bytes.TrimRight(data[0:i], " \t"), data[j:]
|
||||
+ return bytes.TrimRight(data[0:i], " \t"), data[j:], j
|
||||
}
|
||||
|
||||
// removeSpacesAndTabs returns a copy of its input with all spaces and tabs
|
||||
@@ -88,19 +88,29 @@ func Decode(data []byte) (p *Block, rest []byte) {
|
||||
// the byte array, we'll accept the start string without it.
|
||||
rest = data
|
||||
for {
|
||||
- if bytes.HasPrefix(rest, pemStart[1:]) {
|
||||
- rest = rest[len(pemStart)-1:]
|
||||
- } else if i := bytes.Index(rest, pemStart); i >= 0 {
|
||||
- rest = rest[i+len(pemStart) : len(rest)]
|
||||
- } else {
|
||||
+ // Find the first END line, and then find the last BEGIN line before
|
||||
+ // the end line. This lets us skip any repeated BEGIN lines that don't
|
||||
+ // have a matching END.
|
||||
+ endIndex := bytes.Index(rest, pemEnd)
|
||||
+ if endIndex < 0 {
|
||||
return nil, data
|
||||
}
|
||||
-
|
||||
+ endTrailerIndex := endIndex + len(pemEnd)
|
||||
+ beginIndex := bytes.LastIndex(rest[:endIndex], pemStart[1:])
|
||||
+ if beginIndex < 0 || beginIndex > 0 && rest[beginIndex-1] != '\n' {
|
||||
+ return nil, data
|
||||
+ }
|
||||
+ rest = rest[beginIndex+len(pemStart)-1:]
|
||||
+ endIndex -= beginIndex + len(pemStart) - 1
|
||||
+ endTrailerIndex -= beginIndex + len(pemStart) - 1
|
||||
var typeLine []byte
|
||||
- typeLine, rest = getLine(rest)
|
||||
+ var consumed int
|
||||
+ typeLine, rest, consumed = getLine(rest)
|
||||
if !bytes.HasSuffix(typeLine, pemEndOfLine) {
|
||||
continue
|
||||
}
|
||||
+ endIndex -= consumed
|
||||
+ endTrailerIndex -= consumed
|
||||
typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
|
||||
|
||||
p = &Block{
|
||||
@@ -114,7 +124,7 @@ func Decode(data []byte) (p *Block, rest []byte) {
|
||||
if len(rest) == 0 {
|
||||
return nil, data
|
||||
}
|
||||
- line, next := getLine(rest)
|
||||
+ line, next, consumed := getLine(rest)
|
||||
|
||||
i := bytes.IndexByte(line, ':')
|
||||
if i == -1 {
|
||||
@@ -127,21 +137,13 @@ func Decode(data []byte) (p *Block, rest []byte) {
|
||||
val = bytes.TrimSpace(val)
|
||||
p.Headers[string(key)] = string(val)
|
||||
rest = next
|
||||
+ endIndex -= consumed
|
||||
+ endTrailerIndex -= consumed
|
||||
}
|
||||
|
||||
- var endIndex, endTrailerIndex int
|
||||
-
|
||||
- // If there were no headers, the END line might occur
|
||||
- // immediately, without a leading newline.
|
||||
- if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
|
||||
- endIndex = 0
|
||||
- endTrailerIndex = len(pemEnd) - 1
|
||||
- } else {
|
||||
- endIndex = bytes.Index(rest, pemEnd)
|
||||
- endTrailerIndex = endIndex + len(pemEnd)
|
||||
- }
|
||||
-
|
||||
- if endIndex < 0 {
|
||||
+ // If there were headers, there must be a newline between the headers
|
||||
+ // and the END line, so endIndex should be >= 0.
|
||||
+ if len(p.Headers) > 0 && endIndex < 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -161,21 +163,24 @@ func Decode(data []byte) (p *Block, rest []byte) {
|
||||
}
|
||||
|
||||
// The line must end with only whitespace.
|
||||
- if s, _ := getLine(restOfEndLine); len(s) != 0 {
|
||||
+ if s, _, _ := getLine(restOfEndLine); len(s) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
- base64Data := removeSpacesAndTabs(rest[:endIndex])
|
||||
- p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
|
||||
- n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
|
||||
- if err != nil {
|
||||
- continue
|
||||
+ p.Bytes = []byte{}
|
||||
+ if endIndex > 0 {
|
||||
+ base64Data := removeSpacesAndTabs(rest[:endIndex])
|
||||
+ p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
|
||||
+ n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
|
||||
+ if err != nil {
|
||||
+ continue
|
||||
+ }
|
||||
+ p.Bytes = p.Bytes[:n]
|
||||
}
|
||||
- p.Bytes = p.Bytes[:n]
|
||||
|
||||
// the -1 is because we might have only matched pemEnd without the
|
||||
// leading newline if the PEM block was empty.
|
||||
- _, rest = getLine(rest[endIndex+len(pemEnd)-1:])
|
||||
+ _, rest, _ = getLine(rest[endIndex+len(pemEnd)-1:])
|
||||
return p, rest
|
||||
}
|
||||
}
|
||||
diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
|
||||
index c94b5ca..a326f9b 100644
|
||||
--- a/src/encoding/pem/pem_test.go
|
||||
+++ b/src/encoding/pem/pem_test.go
|
||||
@@ -34,7 +34,7 @@ var getLineTests = []GetLineTest{
|
||||
|
||||
func TestGetLine(t *testing.T) {
|
||||
for i, test := range getLineTests {
|
||||
- x, y := getLine([]byte(test.in))
|
||||
+ x, y, _ := getLine([]byte(test.in))
|
||||
if string(x) != test.out1 || string(y) != test.out2 {
|
||||
t.Errorf("#%d got:%+v,%+v want:%s,%s", i, x, y, test.out1, test.out2)
|
||||
}
|
||||
@@ -46,6 +46,7 @@ func TestDecode(t *testing.T) {
|
||||
if !reflect.DeepEqual(result, certificate) {
|
||||
t.Errorf("#0 got:%#v want:%#v", result, certificate)
|
||||
}
|
||||
+
|
||||
result, remainder = Decode(remainder)
|
||||
if !reflect.DeepEqual(result, privateKey) {
|
||||
t.Errorf("#1 got:%#v want:%#v", result, privateKey)
|
||||
@@ -68,7 +69,7 @@ func TestDecode(t *testing.T) {
|
||||
}
|
||||
|
||||
result, remainder = Decode(remainder)
|
||||
- if result == nil || result.Type != "HEADERS" || len(result.Headers) != 1 {
|
||||
+ if result == nil || result.Type != "VALID HEADERS" || len(result.Headers) != 1 {
|
||||
t.Errorf("#5 expected single header block but got :%v", result)
|
||||
}
|
||||
|
||||
@@ -381,15 +382,15 @@ ZWAaUoVtWIQ52aKS0p19G99hhb+IVANC4akkdHV4SP8i7MVNZhfUmg==
|
||||
|
||||
# This shouldn't be recognised because of the missing newline after the
|
||||
headers.
|
||||
------BEGIN HEADERS-----
|
||||
+-----BEGIN INVALID HEADERS-----
|
||||
Header: 1
|
||||
------END HEADERS-----
|
||||
+-----END INVALID HEADERS-----
|
||||
|
||||
# This should be valid, however.
|
||||
------BEGIN HEADERS-----
|
||||
+-----BEGIN VALID HEADERS-----
|
||||
Header: 1
|
||||
|
||||
------END HEADERS-----`)
|
||||
+-----END VALID HEADERS-----`)
|
||||
|
||||
var certificate = &Block{Type: "CERTIFICATE",
|
||||
Headers: map[string]string{},
|
||||
--
|
||||
2.40.0
|
||||
|
||||
74
meta/recipes-devtools/go/go-1.18/CVE-2025-61724.patch
Normal file
74
meta/recipes-devtools/go/go-1.18/CVE-2025-61724.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From a402f4ad285514f5f3db90516d72047d591b307a Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Tue, 30 Sep 2025 15:11:16 -0700
|
||||
Subject: [PATCH] net/textproto: avoid quadratic complexity in
|
||||
Reader.ReadResponse Reader.ReadResponse constructed a response string from
|
||||
repeated string concatenation, permitting a malicious sender to cause
|
||||
excessive memory allocation and CPU consumption by sending a response
|
||||
consisting of many short lines.
|
||||
|
||||
Use a strings.Builder to construct the string instead.
|
||||
|
||||
Thanks to Jakub Ciolek for reporting this issue.
|
||||
|
||||
Fixes CVE-2025-61724
|
||||
For #75716
|
||||
Fixes #75717
|
||||
|
||||
Change-Id: I1a98ce85a21b830cb25799f9ac9333a67400d736
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2940
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2980
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/709837
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
|
||||
CVE: CVE-2025-61724
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/a402f4ad285514f5f3db90516d72047d591b307a]
|
||||
|
||||
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
||||
---
|
||||
src/net/textproto/reader.go | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
|
||||
index 3ac4d4d..a996257 100644
|
||||
--- a/src/net/textproto/reader.go
|
||||
+++ b/src/net/textproto/reader.go
|
||||
@@ -288,8 +288,10 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
|
||||
// An expectCode <= 0 disables the check of the status code.
|
||||
//
|
||||
func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
|
||||
- code, continued, message, err := r.readCodeLine(expectCode)
|
||||
+ code, continued, first, err := r.readCodeLine(expectCode)
|
||||
multi := continued
|
||||
+ var messageBuilder strings.Builder
|
||||
+ messageBuilder.WriteString(first)
|
||||
for continued {
|
||||
line, err := r.ReadLine()
|
||||
if err != nil {
|
||||
@@ -300,12 +302,15 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
|
||||
var moreMessage string
|
||||
code2, continued, moreMessage, err = parseCodeLine(line, 0)
|
||||
if err != nil || code2 != code {
|
||||
- message += "\n" + strings.TrimRight(line, "\r\n")
|
||||
+ messageBuilder.WriteByte('\n')
|
||||
+ messageBuilder.WriteString(strings.TrimRight(line, "\r\n"))
|
||||
continued = true
|
||||
continue
|
||||
}
|
||||
- message += "\n" + moreMessage
|
||||
+ messageBuilder.WriteByte('\n')
|
||||
+ messageBuilder.WriteString(moreMessage)
|
||||
}
|
||||
+ message = messageBuilder.String()
|
||||
if err != nil && multi && message != "" {
|
||||
// replace one line error message with all lines (full message)
|
||||
err = &Error{code, message}
|
||||
--
|
||||
2.40.0
|
||||
|
||||
83
meta/recipes-devtools/go/go-1.21/CVE-2024-24783.patch
Normal file
83
meta/recipes-devtools/go/go-1.21/CVE-2024-24783.patch
Normal file
@@ -0,0 +1,83 @@
|
||||
From be5b52bea674190ef7de272664be6c7ae93ec5a0 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Thu, 18 Jan 2024 12:51:13 -0800
|
||||
Subject: [PATCH] [release-branch.go1.21] crypto/x509: make sure pub key is
|
||||
non-nil before interface conversion
|
||||
|
||||
alreadyInChain assumes all keys fit a interface which contains the
|
||||
Equal method (which they do), but this ignores that certificates may
|
||||
have a nil key when PublicKeyAlgorithm is UnknownPublicKeyAlgorithm. In
|
||||
this case alreadyInChain panics.
|
||||
|
||||
Check that the key is non-nil as part of considerCandidate (we are never
|
||||
going to build a chain containing UnknownPublicKeyAlgorithm anyway).
|
||||
|
||||
For #65390
|
||||
Fixes #65392
|
||||
Fixes CVE-2024-24783
|
||||
|
||||
Change-Id: Ibdccc0a487e3368b6812be35daad2512220243f3
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2137282
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173774
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Carlos Amedee <amedee@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/569238
|
||||
Auto-Submit: Michael Knyszek <mknyszek@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
|
||||
CVE: CVE-2024-24783
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/be5b52bea674190ef7de272664be6c7ae93ec5a0]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
src/crypto/x509/verify.go | 3 +++
|
||||
src/crypto/x509/verify_test.go | 19 +++++++++++++++++++
|
||||
2 files changed, 22 insertions(+)
|
||||
|
||||
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
|
||||
index 9ef1146..3e95808 100644
|
||||
--- a/src/crypto/x509/verify.go
|
||||
+++ b/src/crypto/x509/verify.go
|
||||
@@ -819,6 +819,9 @@ func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, curre
|
||||
)
|
||||
|
||||
considerCandidate := func(certType int, candidate *Certificate) {
|
||||
+ if candidate.PublicKey == nil {
|
||||
+ return
|
||||
+ }
|
||||
for _, cert := range currentChain {
|
||||
if cert.Equal(candidate) {
|
||||
return
|
||||
diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
|
||||
index 9954a67..9da39ca 100644
|
||||
--- a/src/crypto/x509/verify_test.go
|
||||
+++ b/src/crypto/x509/verify_test.go
|
||||
@@ -1968,3 +1968,22 @@ func TestSystemRootsErrorUnwrap(t *testing.T) {
|
||||
t.Error("errors.Is failed, wanted success")
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestVerifyNilPubKey(t *testing.T) {
|
||||
+ c := &Certificate{
|
||||
+ RawIssuer: []byte{1, 2, 3},
|
||||
+ AuthorityKeyId: []byte{1, 2, 3},
|
||||
+ }
|
||||
+ opts := &VerifyOptions{}
|
||||
+ opts.Roots = NewCertPool()
|
||||
+ r := &Certificate{
|
||||
+ RawSubject: []byte{1, 2, 3},
|
||||
+ SubjectKeyId: []byte{1, 2, 3},
|
||||
+ }
|
||||
+ opts.Roots.AddCert(r)
|
||||
+
|
||||
+ _, err := c.buildChains(nil, []*Certificate{r}, nil, opts)
|
||||
+ if _, ok := err.(UnknownAuthorityError); !ok {
|
||||
+ t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{})
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.50.1
|
||||
|
||||
171
meta/recipes-devtools/go/go-1.21/CVE-2025-47906.patch
Normal file
171
meta/recipes-devtools/go/go-1.21/CVE-2025-47906.patch
Normal file
@@ -0,0 +1,171 @@
|
||||
From 8fa31a2d7d9e60c50a3a94080c097b6e65773f4b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Olivier=20Mengu=C3=A9?= <olivier.mengue@gmail.com>
|
||||
Date: Mon, 30 Jun 2025 16:58:59 +0200
|
||||
Subject: [PATCH] [release-branch.go1.23] os/exec: fix incorrect expansion of
|
||||
"", "." and ".." in LookPath Fix incorrect expansion of "" and "." when $PATH
|
||||
contains an executable file or, on Windows, a parent directory of a %PATH%
|
||||
element contains an file with the same name as the %PATH% element but with
|
||||
one of the %PATHEXT% extension (ex: C:\utils\bin is in PATH, and
|
||||
C:\utils\bin.exe exists).
|
||||
|
||||
Fix incorrect expansion of ".." when $PATH contains an element which is
|
||||
an the concatenation of the path to an executable file (or on Windows
|
||||
a path that can be expanded to an executable by appending a %PATHEXT%
|
||||
extension), a path separator and a name.
|
||||
|
||||
"", "." and ".." are now rejected early with ErrNotFound.
|
||||
|
||||
Fixes CVE-2025-47906
|
||||
Fixes #74803
|
||||
|
||||
Change-Id: Ie50cc0a660fce8fbdc952a7f2e05c36062dcb50e
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/685755
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Auto-Submit: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
(cherry picked from commit e0b07dc)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/691855
|
||||
Reviewed-by: Michael Knyszek <mknyszek@google.com>
|
||||
|
||||
CVE: CVE-2025-47906
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/8fa31a2d7d9e60c50a3a94080c097b6e65773f4b]
|
||||
|
||||
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
|
||||
---
|
||||
src/internal/execabs/execabs_test.go | 55 ++++++++++++++++++++++++++++
|
||||
src/os/exec/exec.go | 9 +++++
|
||||
src/os/exec/lp_plan9.go | 4 ++
|
||||
src/os/exec/lp_unix.go | 4 ++
|
||||
src/os/exec/lp_windows.go | 4 ++
|
||||
5 files changed, 76 insertions(+)
|
||||
|
||||
diff --git a/src/internal/execabs/execabs_test.go b/src/internal/execabs/execabs_test.go
|
||||
index 97a3f39..99fd64b 100644
|
||||
--- a/src/internal/execabs/execabs_test.go
|
||||
+++ b/src/internal/execabs/execabs_test.go
|
||||
@@ -100,4 +100,59 @@ func TestLookPath(t *testing.T) {
|
||||
} else if err.Error() != expectedErr {
|
||||
t.Errorf("LookPath returned unexpected error: want %q, got %q", expectedErr, err.Error())
|
||||
}
|
||||
+ checker := func(test string) func(t *testing.T) {
|
||||
+ return func(t *testing.T) {
|
||||
+ t.Helper()
|
||||
+ t.Logf("PATH=%s", os.Getenv("PATH"))
|
||||
+ p, err := LookPath(test)
|
||||
+ if err == nil {
|
||||
+ t.Errorf("%q: error expected, got nil", test)
|
||||
+ }
|
||||
+ if p != "" {
|
||||
+ t.Errorf("%q: path returned should be \"\". Got %q", test, p)
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Reference behavior for the next test
|
||||
+ t.Run(pathVar+"=$OTHER2", func(t *testing.T) {
|
||||
+ t.Run("empty", checker(""))
|
||||
+ t.Run("dot", checker("."))
|
||||
+ t.Run("dotdot1", checker("abc/.."))
|
||||
+ t.Run("dotdot2", checker(".."))
|
||||
+ })
|
||||
+
|
||||
+ // Test the behavior when PATH contains an executable file which is not a directory
|
||||
+ t.Run(pathVar+"=exe", func(t *testing.T) {
|
||||
+ // Inject an executable file (not a directory) in PATH.
|
||||
+ // Use our own binary os.Args[0].
|
||||
+ testenv.MustHaveExec(t)
|
||||
+ exe, err := os.Executable()
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+
|
||||
+ t.Setenv(pathVar, exe)
|
||||
+ t.Run("empty", checker(""))
|
||||
+ t.Run("dot", checker("."))
|
||||
+ t.Run("dotdot1", checker("abc/.."))
|
||||
+ t.Run("dotdot2", checker(".."))
|
||||
+ })
|
||||
+
|
||||
+ // Test the behavior when PATH contains an executable file which is not a directory
|
||||
+ t.Run(pathVar+"=exe/xx", func(t *testing.T) {
|
||||
+ // Inject an executable file (not a directory) in PATH.
|
||||
+ // Use our own binary os.Args[0].
|
||||
+ testenv.MustHaveExec(t)
|
||||
+ exe, err := os.Executable()
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+
|
||||
+ t.Setenv(pathVar, filepath.Join(exe, "xx"))
|
||||
+ t.Run("empty", checker(""))
|
||||
+ t.Run("dot", checker("."))
|
||||
+ t.Run("dotdot1", checker("abc/.."))
|
||||
+ t.Run("dotdot2", checker(".."))
|
||||
+ })
|
||||
}
|
||||
diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go
|
||||
index 505de58..84fd82f 100644
|
||||
--- a/src/os/exec/exec.go
|
||||
+++ b/src/os/exec/exec.go
|
||||
@@ -790,3 +790,12 @@ func addCriticalEnv(env []string) []string {
|
||||
}
|
||||
return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT"))
|
||||
}
|
||||
+// validateLookPath excludes paths that can't be valid
|
||||
+// executable names. See issue #74466 and CVE-2025-47906.
|
||||
+func validateLookPath(s string) error {
|
||||
+ switch s {
|
||||
+ case "", ".", "..":
|
||||
+ return ErrNotFound
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go
|
||||
index e8826a5..ed9f6e3 100644
|
||||
--- a/src/os/exec/lp_plan9.go
|
||||
+++ b/src/os/exec/lp_plan9.go
|
||||
@@ -33,6 +33,10 @@ func findExecutable(file string) error {
|
||||
// The result may be an absolute path or a path relative to the current directory.
|
||||
func LookPath(file string) (string, error) {
|
||||
// skip the path lookup for these prefixes
|
||||
+ if err := validateLookPath(file); err != nil {
|
||||
+ return "", &Error{file, err}
|
||||
+ }
|
||||
+
|
||||
skip := []string{"/", "#", "./", "../"}
|
||||
|
||||
for _, p := range skip {
|
||||
diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go
|
||||
index d1d246a..1b27f2b 100644
|
||||
--- a/src/os/exec/lp_unix.go
|
||||
+++ b/src/os/exec/lp_unix.go
|
||||
@@ -38,6 +38,10 @@ func LookPath(file string) (string, error) {
|
||||
// (only bypass the path if file begins with / or ./ or ../)
|
||||
// but that would not match all the Unix shells.
|
||||
|
||||
+ if err := validateLookPath(file); err != nil {
|
||||
+ return "", &Error{file, err}
|
||||
+ }
|
||||
+
|
||||
if strings.Contains(file, "/") {
|
||||
err := findExecutable(file)
|
||||
if err == nil {
|
||||
diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go
|
||||
index e7a2cdf..7a1d6fb 100644
|
||||
--- a/src/os/exec/lp_windows.go
|
||||
+++ b/src/os/exec/lp_windows.go
|
||||
@@ -58,6 +58,10 @@ func findExecutable(file string, exts []string) (string, error) {
|
||||
// a suitable candidate.
|
||||
// The result may be an absolute path or a path relative to the current directory.
|
||||
func LookPath(file string) (string, error) {
|
||||
+ if err := validateLookPath(file); err != nil {
|
||||
+ return "", &Error{file, err}
|
||||
+ }
|
||||
+
|
||||
var exts []string
|
||||
x := os.Getenv(`PATHEXT`)
|
||||
if x != "" {
|
||||
--
|
||||
2.40.0
|
||||
354
meta/recipes-devtools/go/go-1.21/CVE-2025-47907-pre-0001.patch
Normal file
354
meta/recipes-devtools/go/go-1.21/CVE-2025-47907-pre-0001.patch
Normal file
@@ -0,0 +1,354 @@
|
||||
From 298fe517a9333c05143a8a8e1f9d5499f0c6e59b Mon Sep 17 00:00:00 2001
|
||||
From: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Date: Tue, 23 May 2023 15:12:47 -0700
|
||||
Subject: [PATCH] database/sql: make RawBytes safely usable with contexts
|
||||
|
||||
sql.RawBytes was added the very first Go release, Go 1. Its docs
|
||||
say:
|
||||
|
||||
> RawBytes is a byte slice that holds a reference to memory owned by
|
||||
> the database itself. After a Scan into a RawBytes, the slice is only
|
||||
> valid until the next call to Next, Scan, or Close.
|
||||
|
||||
That "only valid until the next call" bit was true at the time,
|
||||
until contexts were added to database/sql in Go 1.8.
|
||||
|
||||
In the past ~dozen releases it's been unsafe to use QueryContext with
|
||||
a context that might become Done to get an *sql.Rows that's scanning
|
||||
into a RawBytes. The Scan can succeed, but then while the caller's
|
||||
reading the memory, a database/sql-managed goroutine can see the
|
||||
context becoming done and call Close on the database/sql/driver and
|
||||
make the caller's view of the RawBytes memory no longer valid,
|
||||
introducing races, crashes, or database corruption. See #60304
|
||||
and #53970 for details.
|
||||
|
||||
This change does the minimal surgery on database/sql to make it safe
|
||||
again: Rows.Scan was already acquiring a mutex to check whether the
|
||||
rows had been closed, so this change make Rows.Scan notice whether
|
||||
*RawBytes was used and, if so, doesn't release the mutex on exit
|
||||
before returning. That mean it's still locked while the user code
|
||||
operates on the RawBytes memory and the concurrent context-watching
|
||||
goroutine to close the database still runs, but if it fires, it then
|
||||
gets blocked on the mutex until the next call to a Rows method (Next,
|
||||
NextResultSet, Err, Close).
|
||||
|
||||
Updates #60304
|
||||
Updates #53970 (earlier one I'd missed)
|
||||
|
||||
Change-Id: Ie41c0c6f32c24887b2f53ec3686c2aab73a1bfff
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/497675
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Reviewed-by: Ian Lance Taylor <iant@google.com>
|
||||
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Auto-Submit: Ian Lance Taylor <iant@google.com>
|
||||
Reviewed-by: Russ Cox <rsc@golang.org>
|
||||
|
||||
CVE: CVE-2025-47907
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/298fe517a9333c05143a8a8e1f9d5499f0c6e59b]
|
||||
|
||||
Signed-off-by: Praveen Kumar <praveen.kumar@windriver.com>
|
||||
---
|
||||
src/database/sql/fakedb_test.go | 13 +++++-
|
||||
src/database/sql/sql.go | 72 ++++++++++++++++++++++++++++++++-
|
||||
src/database/sql/sql_test.go | 58 ++++++++++++++++++++++++++
|
||||
3 files changed, 141 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
|
||||
index 4b68f1c..33c57b9 100644
|
||||
--- a/src/database/sql/fakedb_test.go
|
||||
+++ b/src/database/sql/fakedb_test.go
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
+ "sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -90,6 +91,8 @@ func (cc *fakeDriverCtx) OpenConnector(name string) (driver.Connector, error) {
|
||||
type fakeDB struct {
|
||||
name string
|
||||
|
||||
+ useRawBytes atomic.Bool
|
||||
+
|
||||
mu sync.Mutex
|
||||
tables map[string]*table
|
||||
badConn bool
|
||||
@@ -680,6 +683,8 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm
|
||||
switch cmd {
|
||||
case "WIPE":
|
||||
// Nothing
|
||||
+ case "USE_RAWBYTES":
|
||||
+ c.db.useRawBytes.Store(true)
|
||||
case "SELECT":
|
||||
stmt, err = c.prepareSelect(stmt, parts)
|
||||
case "CREATE":
|
||||
@@ -783,6 +788,9 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d
|
||||
case "WIPE":
|
||||
db.wipe()
|
||||
return driver.ResultNoRows, nil
|
||||
+ case "USE_RAWBYTES":
|
||||
+ s.c.db.useRawBytes.Store(true)
|
||||
+ return driver.ResultNoRows, nil
|
||||
case "CREATE":
|
||||
if err := db.createTable(s.table, s.colName, s.colType); err != nil {
|
||||
return nil, err
|
||||
@@ -912,6 +920,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
|
||||
txStatus = "transaction"
|
||||
}
|
||||
cursor := &rowsCursor{
|
||||
+ db: s.c.db,
|
||||
parentMem: s.c,
|
||||
posRow: -1,
|
||||
rows: [][]*row{
|
||||
@@ -1008,6 +1017,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
|
||||
}
|
||||
|
||||
cursor := &rowsCursor{
|
||||
+ db: s.c.db,
|
||||
parentMem: s.c,
|
||||
posRow: -1,
|
||||
rows: setMRows,
|
||||
@@ -1050,6 +1060,7 @@ func (tx *fakeTx) Rollback() error {
|
||||
}
|
||||
|
||||
type rowsCursor struct {
|
||||
+ db *fakeDB
|
||||
parentMem memToucher
|
||||
cols [][]string
|
||||
colType [][]string
|
||||
@@ -1121,7 +1132,7 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
|
||||
// messing up conversions or doing them differently.
|
||||
dest[i] = v
|
||||
|
||||
- if bs, ok := v.([]byte); ok {
|
||||
+ if bs, ok := v.([]byte); ok && !rc.db.useRawBytes.Load() {
|
||||
if rc.bytesClone == nil {
|
||||
rc.bytesClone = make(map[*byte][]byte)
|
||||
}
|
||||
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
|
||||
index 68fb392..ef49e70 100644
|
||||
--- a/src/database/sql/sql.go
|
||||
+++ b/src/database/sql/sql.go
|
||||
@@ -2879,6 +2879,8 @@ type Rows struct {
|
||||
cancel func() // called when Rows is closed, may be nil.
|
||||
closeStmt *driverStmt // if non-nil, statement to Close on close
|
||||
|
||||
+ contextDone atomic.Value // error that awaitDone saw; set before close attempt
|
||||
+
|
||||
// closemu prevents Rows from closing while there
|
||||
// is an active streaming result. It is held for read during non-close operations
|
||||
// and exclusively during close.
|
||||
@@ -2891,6 +2893,15 @@ type Rows struct {
|
||||
// lastcols is only used in Scan, Next, and NextResultSet which are expected
|
||||
// not to be called concurrently.
|
||||
lastcols []driver.Value
|
||||
+
|
||||
+ // closemuScanHold is whether the previous call to Scan kept closemu RLock'ed
|
||||
+ // without unlocking it. It does that when the user passes a *RawBytes scan
|
||||
+ // target. In that case, we need to prevent awaitDone from closing the Rows
|
||||
+ // while the user's still using the memory. See go.dev/issue/60304.
|
||||
+ //
|
||||
+ // It is only used by Scan, Next, and NextResultSet which are expected
|
||||
+ // not to be called concurrently.
|
||||
+ closemuScanHold bool
|
||||
}
|
||||
|
||||
// lasterrOrErrLocked returns either lasterr or the provided err.
|
||||
@@ -2928,7 +2939,11 @@ func (rs *Rows) awaitDone(ctx, txctx context.Context) {
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
+ err := ctx.Err()
|
||||
+ rs.contextDone.Store(&err)
|
||||
case <-txctxDone:
|
||||
+ err := txctx.Err()
|
||||
+ rs.contextDone.Store(&err)
|
||||
}
|
||||
rs.close(ctx.Err())
|
||||
}
|
||||
@@ -2940,6 +2955,15 @@ func (rs *Rows) awaitDone(ctx, txctx context.Context) {
|
||||
//
|
||||
// Every call to Scan, even the first one, must be preceded by a call to Next.
|
||||
func (rs *Rows) Next() bool {
|
||||
+ // If the user's calling Next, they're done with their previous row's Scan
|
||||
+ // results (any RawBytes memory), so we can release the read lock that would
|
||||
+ // be preventing awaitDone from calling close.
|
||||
+ rs.closemuRUnlockIfHeldByScan()
|
||||
+
|
||||
+ if rs.contextDone.Load() != nil {
|
||||
+ return false
|
||||
+ }
|
||||
+
|
||||
var doClose, ok bool
|
||||
withLock(rs.closemu.RLocker(), func() {
|
||||
doClose, ok = rs.nextLocked()
|
||||
@@ -2994,6 +3018,11 @@ func (rs *Rows) nextLocked() (doClose, ok bool) {
|
||||
// scanning. If there are further result sets they may not have rows in the result
|
||||
// set.
|
||||
func (rs *Rows) NextResultSet() bool {
|
||||
+ // If the user's calling NextResultSet, they're done with their previous
|
||||
+ // row's Scan results (any RawBytes memory), so we can release the read lock
|
||||
+ // that would be preventing awaitDone from calling close.
|
||||
+ rs.closemuRUnlockIfHeldByScan()
|
||||
+
|
||||
var doClose bool
|
||||
defer func() {
|
||||
if doClose {
|
||||
@@ -3030,6 +3059,10 @@ func (rs *Rows) NextResultSet() bool {
|
||||
// Err returns the error, if any, that was encountered during iteration.
|
||||
// Err may be called after an explicit or implicit Close.
|
||||
func (rs *Rows) Err() error {
|
||||
+ if errp := rs.contextDone.Load(); errp != nil {
|
||||
+ return *(errp.(*error))
|
||||
+ }
|
||||
+
|
||||
rs.closemu.RLock()
|
||||
defer rs.closemu.RUnlock()
|
||||
return rs.lasterrOrErrLocked(nil)
|
||||
@@ -3223,6 +3256,11 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType {
|
||||
// If any of the first arguments implementing Scanner returns an error,
|
||||
// that error will be wrapped in the returned error
|
||||
func (rs *Rows) Scan(dest ...interface{}) error {
|
||||
+ if rs.closemuScanHold {
|
||||
+ // This should only be possible if the user calls Scan twice in a row
|
||||
+ // without calling Next.
|
||||
+ return fmt.Errorf("sql: Scan called without calling Next (closemuScanHold)")
|
||||
+ }
|
||||
rs.closemu.RLock()
|
||||
|
||||
if rs.lasterr != nil && rs.lasterr != io.EOF {
|
||||
@@ -3234,23 +3272,50 @@ func (rs *Rows) Scan(dest ...interface{}) error {
|
||||
rs.closemu.RUnlock()
|
||||
return err
|
||||
}
|
||||
- rs.closemu.RUnlock()
|
||||
+
|
||||
+ if scanArgsContainRawBytes(dest) {
|
||||
+ rs.closemuScanHold = true
|
||||
+ } else {
|
||||
+ rs.closemu.RUnlock()
|
||||
+ }
|
||||
|
||||
if rs.lastcols == nil {
|
||||
+ rs.closemuRUnlockIfHeldByScan()
|
||||
return errors.New("sql: Scan called without calling Next")
|
||||
}
|
||||
if len(dest) != len(rs.lastcols) {
|
||||
+ rs.closemuRUnlockIfHeldByScan()
|
||||
return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
|
||||
}
|
||||
+
|
||||
for i, sv := range rs.lastcols {
|
||||
err := convertAssignRows(dest[i], sv, rs)
|
||||
if err != nil {
|
||||
+ rs.closemuRUnlockIfHeldByScan()
|
||||
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+// closemuRUnlockIfHeldByScan releases any closemu.RLock held open by a previous
|
||||
+// call to Scan with *RawBytes.
|
||||
+func (rs *Rows) closemuRUnlockIfHeldByScan() {
|
||||
+ if rs.closemuScanHold {
|
||||
+ rs.closemuScanHold = false
|
||||
+ rs.closemu.RUnlock()
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func scanArgsContainRawBytes(args []interface{}) bool {
|
||||
+ for _, a := range args {
|
||||
+ if _, ok := a.(*RawBytes); ok {
|
||||
+ return true
|
||||
+ }
|
||||
+ }
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
// rowsCloseHook returns a function so tests may install the
|
||||
// hook through a test only mutex.
|
||||
var rowsCloseHook = func() func(*Rows, *error) { return nil }
|
||||
@@ -3260,6 +3325,11 @@ var rowsCloseHook = func() func(*Rows, *error) { return nil }
|
||||
// the Rows are closed automatically and it will suffice to check the
|
||||
// result of Err. Close is idempotent and does not affect the result of Err.
|
||||
func (rs *Rows) Close() error {
|
||||
+ // If the user's calling Close, they're done with their previous row's Scan
|
||||
+ // results (any RawBytes memory), so we can release the read lock that would
|
||||
+ // be preventing awaitDone from calling the unexported close before we do so.
|
||||
+ rs.closemuRUnlockIfHeldByScan()
|
||||
+
|
||||
return rs.close(nil)
|
||||
}
|
||||
|
||||
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
|
||||
index f771dee..53b38d1 100644
|
||||
--- a/src/database/sql/sql_test.go
|
||||
+++ b/src/database/sql/sql_test.go
|
||||
@@ -4255,6 +4255,64 @@ func TestRowsScanProperlyWrapsErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+// From go.dev/issue/60304
|
||||
+func TestContextCancelDuringRawBytesScan(t *testing.T) {
|
||||
+ db := newTestDB(t, "people")
|
||||
+ defer closeDB(t, db)
|
||||
+
|
||||
+ if _, err := db.Exec("USE_RAWBYTES"); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+
|
||||
+ ctx, cancel := context.WithCancel(context.Background())
|
||||
+ defer cancel()
|
||||
+
|
||||
+ r, err := db.QueryContext(ctx, "SELECT|people|name|")
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ numRows := 0
|
||||
+ var sink byte
|
||||
+ for r.Next() {
|
||||
+ numRows++
|
||||
+ var s RawBytes
|
||||
+ err = r.Scan(&s)
|
||||
+ if !r.closemuScanHold {
|
||||
+ t.Errorf("expected closemu to be held")
|
||||
+ }
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ t.Logf("read %q", s)
|
||||
+ if numRows == 2 {
|
||||
+ cancel() // invalidate the context, which used to call close asynchronously
|
||||
+ }
|
||||
+ for _, b := range s { // some operation reading from the raw memory
|
||||
+ sink += b
|
||||
+ }
|
||||
+ }
|
||||
+ if r.closemuScanHold {
|
||||
+ t.Errorf("closemu held; should not be")
|
||||
+ }
|
||||
+
|
||||
+ // There are 3 rows. We canceled after reading 2 so we expect either
|
||||
+ // 2 or 3 depending on how the awaitDone goroutine schedules.
|
||||
+ switch numRows {
|
||||
+ case 0, 1:
|
||||
+ t.Errorf("got %d rows; want 2+", numRows)
|
||||
+ case 2:
|
||||
+ if err := r.Err(); err != context.Canceled {
|
||||
+ t.Errorf("unexpected error: %v (%T)", err, err)
|
||||
+ }
|
||||
+ default:
|
||||
+ // Made it to the end. This is rare, but fine. Permit it.
|
||||
+ }
|
||||
+
|
||||
+ if err := r.Close(); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// badConn implements a bad driver.Conn, for TestBadDriver.
|
||||
// The Exec method panics.
|
||||
type badConn struct{}
|
||||
232
meta/recipes-devtools/go/go-1.21/CVE-2025-47907-pre-0002.patch
Normal file
232
meta/recipes-devtools/go/go-1.21/CVE-2025-47907-pre-0002.patch
Normal file
@@ -0,0 +1,232 @@
|
||||
From c23579f031ecd09bf37c644723b33736dffa8b92 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Tue, 23 Jan 2024 15:59:47 -0800
|
||||
Subject: [PATCH] database/sql: avoid clobbering driver-owned memory in
|
||||
RawBytes
|
||||
|
||||
Depending on the query, a RawBytes can contain memory owned by the
|
||||
driver or by database/sql:
|
||||
|
||||
If the driver provides the column as a []byte,
|
||||
RawBytes aliases that []byte.
|
||||
|
||||
If the driver provides the column as any other type,
|
||||
RawBytes contains memory allocated by database/sql.
|
||||
Prior to this CL, Rows.Scan will reuse existing capacity in a
|
||||
RawBytes to permit a single allocation to be reused across rows.
|
||||
|
||||
When a RawBytes is reused across queries, this can result
|
||||
in database/sql writing to driver-owned memory.
|
||||
|
||||
Add a buffer to Rows to store RawBytes data, and reuse this
|
||||
buffer across calls to Rows.Scan.
|
||||
|
||||
Fixes #65201
|
||||
|
||||
Change-Id: Iac640174c7afa97eeb39496f47dec202501b2483
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/557917
|
||||
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
|
||||
CVE: CVE-2025-47907
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/c23579f031ecd09bf37c644723b33736dffa8b92]
|
||||
|
||||
Signed-off-by: Praveen Kumar <praveen.kumar@windriver.com>
|
||||
---
|
||||
src/database/sql/convert.go | 8 +++---
|
||||
src/database/sql/convert_test.go | 14 +++++++---
|
||||
src/database/sql/sql.go | 34 +++++++++++++++++++++++
|
||||
src/database/sql/sql_test.go | 47 ++++++++++++++++++++++++++++++++
|
||||
4 files changed, 95 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go
|
||||
index b966ef9..3a581f6 100644
|
||||
--- a/src/database/sql/convert.go
|
||||
+++ b/src/database/sql/convert.go
|
||||
@@ -237,7 +237,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error {
|
||||
if d == nil {
|
||||
return errNilPtr
|
||||
}
|
||||
- *d = append((*d)[:0], s...)
|
||||
+ *d = rows.setrawbuf(append(rows.rawbuf(), s...))
|
||||
return nil
|
||||
}
|
||||
case []byte:
|
||||
@@ -285,7 +285,7 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error {
|
||||
if d == nil {
|
||||
return errNilPtr
|
||||
}
|
||||
- *d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
|
||||
+ *d = rows.setrawbuf(s.AppendFormat(rows.rawbuf(), time.RFC3339Nano))
|
||||
return nil
|
||||
}
|
||||
case decimalDecompose:
|
||||
@@ -366,8 +366,8 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error {
|
||||
}
|
||||
case *RawBytes:
|
||||
sv = reflect.ValueOf(src)
|
||||
- if b, ok := asBytes([]byte(*d)[:0], sv); ok {
|
||||
- *d = RawBytes(b)
|
||||
+ if b, ok := asBytes(rows.rawbuf(), sv); ok {
|
||||
+ *d = rows.setrawbuf(b)
|
||||
return nil
|
||||
}
|
||||
case *bool:
|
||||
diff --git a/src/database/sql/convert_test.go b/src/database/sql/convert_test.go
|
||||
index 2668a5e..23a70bf 100644
|
||||
--- a/src/database/sql/convert_test.go
|
||||
+++ b/src/database/sql/convert_test.go
|
||||
@@ -357,9 +357,10 @@ func TestRawBytesAllocs(t *testing.T) {
|
||||
{"time", time.Unix(2, 5).UTC(), "1970-01-01T00:00:02.000000005Z"},
|
||||
}
|
||||
|
||||
- buf := make(RawBytes, 10)
|
||||
- test := func(name string, in interface{}, want string) {
|
||||
- if err := convertAssign(&buf, in); err != nil {
|
||||
+ var buf RawBytes
|
||||
+ rows := &Rows{}
|
||||
+ test := func(name string, in interface{}, want string) {
|
||||
+ if err := convertAssignRows(&buf, in, rows); err != nil {
|
||||
t.Fatalf("%s: convertAssign = %v", name, err)
|
||||
}
|
||||
match := len(buf) == len(want)
|
||||
@@ -378,6 +379,7 @@ func TestRawBytesAllocs(t *testing.T) {
|
||||
|
||||
n := testing.AllocsPerRun(100, func() {
|
||||
for _, tt := range tests {
|
||||
+ rows.raw = rows.raw[:0]
|
||||
test(tt.name, tt.in, tt.want)
|
||||
}
|
||||
})
|
||||
@@ -386,7 +388,11 @@ func TestRawBytesAllocs(t *testing.T) {
|
||||
// and gc. With 32-bit words there are more convT2E allocs, and
|
||||
// with gccgo, only pointers currently go in interface data.
|
||||
// So only care on amd64 gc for now.
|
||||
- measureAllocs := runtime.GOARCH == "amd64" && runtime.Compiler == "gc"
|
||||
+ measureAllocs := false
|
||||
+ switch runtime.GOARCH {
|
||||
+ case "amd64", "arm64":
|
||||
+ measureAllocs = runtime.Compiler == "gc"
|
||||
+ }
|
||||
|
||||
if n > 0.5 && measureAllocs {
|
||||
t.Fatalf("allocs = %v; want 0", n)
|
||||
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
|
||||
index ef49e70..e25447c 100644
|
||||
--- a/src/database/sql/sql.go
|
||||
+++ b/src/database/sql/sql.go
|
||||
@@ -2894,6 +2894,13 @@ type Rows struct {
|
||||
// not to be called concurrently.
|
||||
lastcols []driver.Value
|
||||
|
||||
+ // raw is a buffer for RawBytes that persists between Scan calls.
|
||||
+ // This is used when the driver returns a mismatched type that requires
|
||||
+ // a cloning allocation. For example, if the driver returns a *string and
|
||||
+ // the user is scanning into a *RawBytes, we need to copy the string.
|
||||
+ // The raw buffer here lets us reuse the memory for that copy across Scan calls.
|
||||
+ raw []byte
|
||||
+
|
||||
// closemuScanHold is whether the previous call to Scan kept closemu RLock'ed
|
||||
// without unlocking it. It does that when the user passes a *RawBytes scan
|
||||
// target. In that case, we need to prevent awaitDone from closing the Rows
|
||||
@@ -3068,6 +3075,32 @@ func (rs *Rows) Err() error {
|
||||
return rs.lasterrOrErrLocked(nil)
|
||||
}
|
||||
|
||||
+// rawbuf returns the buffer to append RawBytes values to.
|
||||
+// This buffer is reused across calls to Rows.Scan.
|
||||
+//
|
||||
+// Usage:
|
||||
+//
|
||||
+// rawBytes = rows.setrawbuf(append(rows.rawbuf(), value...))
|
||||
+func (rs *Rows) rawbuf() []byte {
|
||||
+ if rs == nil {
|
||||
+ // convertAssignRows can take a nil *Rows; for simplicity handle it here
|
||||
+ return nil
|
||||
+ }
|
||||
+ return rs.raw
|
||||
+}
|
||||
+
|
||||
+// setrawbuf updates the RawBytes buffer with the result of appending a new value to it.
|
||||
+// It returns the new value.
|
||||
+func (rs *Rows) setrawbuf(b []byte) RawBytes {
|
||||
+ if rs == nil {
|
||||
+ // convertAssignRows can take a nil *Rows; for simplicity handle it here
|
||||
+ return RawBytes(b)
|
||||
+ }
|
||||
+ off := len(rs.raw)
|
||||
+ rs.raw = b
|
||||
+ return RawBytes(rs.raw[off:])
|
||||
+}
|
||||
+
|
||||
var errRowsClosed = errors.New("sql: Rows are closed")
|
||||
var errNoRows = errors.New("sql: no Rows available")
|
||||
|
||||
@@ -3275,6 +3308,7 @@ func (rs *Rows) Scan(dest ...interface{}) error {
|
||||
|
||||
if scanArgsContainRawBytes(dest) {
|
||||
rs.closemuScanHold = true
|
||||
+ rs.raw = rs.raw[:0]
|
||||
} else {
|
||||
rs.closemu.RUnlock()
|
||||
}
|
||||
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
|
||||
index 53b38d1..6aa9bf0 100644
|
||||
--- a/src/database/sql/sql_test.go
|
||||
+++ b/src/database/sql/sql_test.go
|
||||
@@ -4313,6 +4313,53 @@ func TestContextCancelDuringRawBytesScan(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+// Issue #65201.
|
||||
+//
|
||||
+// If a RawBytes is reused across multiple queries,
|
||||
+// subsequent queries shouldn't overwrite driver-owned memory from previous queries.
|
||||
+func TestRawBytesReuse(t *testing.T) {
|
||||
+ db := newTestDB(t, "people")
|
||||
+ defer closeDB(t, db)
|
||||
+
|
||||
+ if _, err := db.Exec("USE_RAWBYTES"); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+
|
||||
+ var raw RawBytes
|
||||
+
|
||||
+ // The RawBytes in this query aliases driver-owned memory.
|
||||
+ rows, err := db.Query("SELECT|people|name|")
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ rows.Next()
|
||||
+ rows.Scan(&raw) // now raw is pointing to driver-owned memory
|
||||
+ name1 := string(raw)
|
||||
+ rows.Close()
|
||||
+
|
||||
+ // The RawBytes in this query does not alias driver-owned memory.
|
||||
+ rows, err = db.Query("SELECT|people|age|")
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ rows.Next()
|
||||
+ rows.Scan(&raw) // this must not write to the driver-owned memory in raw
|
||||
+ rows.Close()
|
||||
+
|
||||
+ // Repeat the first query. Nothing should have changed.
|
||||
+ rows, err = db.Query("SELECT|people|name|")
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ rows.Next()
|
||||
+ rows.Scan(&raw) // raw points to driver-owned memory again
|
||||
+ name2 := string(raw)
|
||||
+ rows.Close()
|
||||
+ if name1 != name2 {
|
||||
+ t.Fatalf("Scan read name %q, want %q", name2, name1)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// badConn implements a bad driver.Conn, for TestBadDriver.
|
||||
// The Exec method panics.
|
||||
type badConn struct{}
|
||||
327
meta/recipes-devtools/go/go-1.21/CVE-2025-47907.patch
Normal file
327
meta/recipes-devtools/go/go-1.21/CVE-2025-47907.patch
Normal file
@@ -0,0 +1,327 @@
|
||||
From 8a924caaf348fdc366bab906424616b2974ad4e9 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Wed, 23 Jul 2025 14:26:54 -0700
|
||||
Subject: [PATCH] database/sql: avoid closing Rows while scan is in progress
|
||||
|
||||
A database/sql/driver.Rows can return database-owned data
|
||||
from Rows.Next. The driver.Rows documentation doesn't explicitly
|
||||
document the lifetime guarantees for this data, but a reasonable
|
||||
expectation is that the caller of Next should only access it
|
||||
until the next call to Rows.Close or Rows.Next.
|
||||
|
||||
Avoid violating that constraint when a query is cancelled while
|
||||
a call to database/sql.Rows.Scan (note the difference between
|
||||
the two different Rows types!) is in progress. We previously
|
||||
took care to avoid closing a driver.Rows while the user has
|
||||
access to driver-owned memory via a RawData, but we could still
|
||||
close a driver.Rows while a Scan call was in the process of
|
||||
reading previously-returned driver-owned data.
|
||||
|
||||
Update the fake DB used in database/sql tests to invalidate
|
||||
returned data to help catch other places we might be
|
||||
incorrectly retaining it.
|
||||
|
||||
Updates #74831
|
||||
Fixes #74832
|
||||
|
||||
Change-Id: Ice45b5fad51b679c38e3e1d21ef39156b56d6037
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2540
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2601
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/693558
|
||||
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
|
||||
Reviewed-by: Mark Freeman <markfreeman@google.com>
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||
|
||||
CVE: CVE-2025-47907
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/8a924caaf348fdc366bab906424616b2974ad4e9]
|
||||
|
||||
Signed-off-by: Praveen Kumar <praveen.kumar@windriver.com>
|
||||
---
|
||||
src/database/sql/convert.go | 2 --
|
||||
src/database/sql/fakedb_test.go | 47 ++++++++++++--------------
|
||||
src/database/sql/sql.go | 26 +++++++-------
|
||||
src/database/sql/sql_test.go | 60 ++++++++++++++++++++++++++++++---
|
||||
4 files changed, 90 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go
|
||||
index 3a581f6..5b0c6f0 100644
|
||||
--- a/src/database/sql/convert.go
|
||||
+++ b/src/database/sql/convert.go
|
||||
@@ -324,7 +324,6 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error {
|
||||
if rows == nil {
|
||||
return errors.New("invalid context to convert cursor rows, missing parent *Rows")
|
||||
}
|
||||
- rows.closemu.Lock()
|
||||
*d = Rows{
|
||||
dc: rows.dc,
|
||||
releaseConn: func(error) {},
|
||||
@@ -340,7 +339,6 @@ func convertAssignRows(dest, src interface{}, rows *Rows) error {
|
||||
parentCancel()
|
||||
}
|
||||
}
|
||||
- rows.closemu.Unlock()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
|
||||
index 33c57b9..9f3d517 100644
|
||||
--- a/src/database/sql/fakedb_test.go
|
||||
+++ b/src/database/sql/fakedb_test.go
|
||||
@@ -5,6 +5,7 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
+ "bytes"
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
- "sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -91,8 +91,6 @@ func (cc *fakeDriverCtx) OpenConnector(name string) (driver.Connector, error) {
|
||||
type fakeDB struct {
|
||||
name string
|
||||
|
||||
- useRawBytes atomic.Bool
|
||||
-
|
||||
mu sync.Mutex
|
||||
tables map[string]*table
|
||||
badConn bool
|
||||
@@ -683,8 +681,6 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm
|
||||
switch cmd {
|
||||
case "WIPE":
|
||||
// Nothing
|
||||
- case "USE_RAWBYTES":
|
||||
- c.db.useRawBytes.Store(true)
|
||||
case "SELECT":
|
||||
stmt, err = c.prepareSelect(stmt, parts)
|
||||
case "CREATE":
|
||||
@@ -788,9 +784,6 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d
|
||||
case "WIPE":
|
||||
db.wipe()
|
||||
return driver.ResultNoRows, nil
|
||||
- case "USE_RAWBYTES":
|
||||
- s.c.db.useRawBytes.Store(true)
|
||||
- return driver.ResultNoRows, nil
|
||||
case "CREATE":
|
||||
if err := db.createTable(s.table, s.colName, s.colType); err != nil {
|
||||
return nil, err
|
||||
@@ -1073,10 +1066,9 @@ type rowsCursor struct {
|
||||
errPos int
|
||||
err error
|
||||
|
||||
- // a clone of slices to give out to clients, indexed by the
|
||||
- // original slice's first byte address. we clone them
|
||||
- // just so we're able to corrupt them on close.
|
||||
- bytesClone map[*byte][]byte
|
||||
+ // Data returned to clients.
|
||||
+ // We clone and stash it here so it can be invalidated by Close and Next.
|
||||
+ driverOwnedMemory [][]byte
|
||||
|
||||
// Every operation writes to line to enable the race detector
|
||||
// check for data races.
|
||||
@@ -1090,9 +1082,19 @@ func (rc *rowsCursor) touchMem() {
|
||||
rc.line++
|
||||
}
|
||||
|
||||
+func (rc *rowsCursor) invalidateDriverOwnedMemory() {
|
||||
+ for _, buf := range rc.driverOwnedMemory {
|
||||
+ for i := range buf {
|
||||
+ buf[i] = 'x'
|
||||
+ }
|
||||
+ }
|
||||
+ rc.driverOwnedMemory = nil
|
||||
+}
|
||||
+
|
||||
func (rc *rowsCursor) Close() error {
|
||||
rc.touchMem()
|
||||
rc.parentMem.touchMem()
|
||||
+ rc.invalidateDriverOwnedMemory()
|
||||
rc.closed = true
|
||||
return nil
|
||||
}
|
||||
@@ -1123,6 +1125,8 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
|
||||
if rc.posRow >= len(rc.rows[rc.posSet]) {
|
||||
return io.EOF // per interface spec
|
||||
}
|
||||
+ // Corrupt any previously returned bytes.
|
||||
+ rc.invalidateDriverOwnedMemory()
|
||||
for i, v := range rc.rows[rc.posSet][rc.posRow].cols {
|
||||
// TODO(bradfitz): convert to subset types? naah, I
|
||||
// think the subset types should only be input to
|
||||
@@ -1130,20 +1134,13 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
|
||||
// a wider range of types coming out of drivers. all
|
||||
// for ease of drivers, and to prevent drivers from
|
||||
// messing up conversions or doing them differently.
|
||||
- dest[i] = v
|
||||
-
|
||||
- if bs, ok := v.([]byte); ok && !rc.db.useRawBytes.Load() {
|
||||
- if rc.bytesClone == nil {
|
||||
- rc.bytesClone = make(map[*byte][]byte)
|
||||
- }
|
||||
- clone, ok := rc.bytesClone[&bs[0]]
|
||||
- if !ok {
|
||||
- clone = make([]byte, len(bs))
|
||||
- copy(clone, bs)
|
||||
- rc.bytesClone[&bs[0]] = clone
|
||||
- }
|
||||
- dest[i] = clone
|
||||
+ if bs, ok := v.([]byte); ok {
|
||||
+ // Clone []bytes and stash for later invalidation.
|
||||
+ bs = bytes.Clone(bs)
|
||||
+ rc.driverOwnedMemory = append(rc.driverOwnedMemory, bs)
|
||||
+ v = bs
|
||||
}
|
||||
+ dest[i] = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
|
||||
index e25447c..a428e29 100644
|
||||
--- a/src/database/sql/sql.go
|
||||
+++ b/src/database/sql/sql.go
|
||||
@@ -3294,38 +3294,36 @@ func (rs *Rows) Scan(dest ...interface{}) error {
|
||||
// without calling Next.
|
||||
return fmt.Errorf("sql: Scan called without calling Next (closemuScanHold)")
|
||||
}
|
||||
+
|
||||
rs.closemu.RLock()
|
||||
+ rs.raw = rs.raw[:0]
|
||||
+ err := rs.scanLocked(dest...)
|
||||
+ if err == nil && scanArgsContainRawBytes(dest) {
|
||||
+ rs.closemuScanHold = true
|
||||
+ } else {
|
||||
+ rs.closemu.RUnlock()
|
||||
+ }
|
||||
+ return err
|
||||
+}
|
||||
|
||||
+func (rs *Rows) scanLocked(dest ...interface{}) error {
|
||||
if rs.lasterr != nil && rs.lasterr != io.EOF {
|
||||
- rs.closemu.RUnlock()
|
||||
return rs.lasterr
|
||||
}
|
||||
if rs.closed {
|
||||
- err := rs.lasterrOrErrLocked(errRowsClosed)
|
||||
- rs.closemu.RUnlock()
|
||||
- return err
|
||||
- }
|
||||
-
|
||||
- if scanArgsContainRawBytes(dest) {
|
||||
- rs.closemuScanHold = true
|
||||
- rs.raw = rs.raw[:0]
|
||||
- } else {
|
||||
- rs.closemu.RUnlock()
|
||||
+ return rs.lasterrOrErrLocked(errRowsClosed)
|
||||
}
|
||||
|
||||
if rs.lastcols == nil {
|
||||
- rs.closemuRUnlockIfHeldByScan()
|
||||
return errors.New("sql: Scan called without calling Next")
|
||||
}
|
||||
if len(dest) != len(rs.lastcols) {
|
||||
- rs.closemuRUnlockIfHeldByScan()
|
||||
return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
|
||||
}
|
||||
|
||||
for i, sv := range rs.lastcols {
|
||||
err := convertAssignRows(dest[i], sv, rs)
|
||||
if err != nil {
|
||||
- rs.closemuRUnlockIfHeldByScan()
|
||||
return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
|
||||
}
|
||||
}
|
||||
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
|
||||
index 6aa9bf0..6aec7ec 100644
|
||||
--- a/src/database/sql/sql_test.go
|
||||
+++ b/src/database/sql/sql_test.go
|
||||
@@ -5,6 +5,7 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
+ "bytes"
|
||||
"context"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
@@ -4321,10 +4322,6 @@ func TestRawBytesReuse(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
- if _, err := db.Exec("USE_RAWBYTES"); err != nil {
|
||||
- t.Fatal(err)
|
||||
- }
|
||||
-
|
||||
var raw RawBytes
|
||||
|
||||
// The RawBytes in this query aliases driver-owned memory.
|
||||
@@ -4469,6 +4466,61 @@ func TestTypedString(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+type testScanner struct {
|
||||
+ scanf func(src any) error
|
||||
+}
|
||||
+
|
||||
+func (ts testScanner) Scan(src any) error { return ts.scanf(src) }
|
||||
+
|
||||
+func TestContextCancelDuringScan(t *testing.T) {
|
||||
+ db := newTestDB(t, "people")
|
||||
+ defer closeDB(t, db)
|
||||
+
|
||||
+ ctx, cancel := context.WithCancel(context.Background())
|
||||
+ defer cancel()
|
||||
+
|
||||
+ scanStart := make(chan any)
|
||||
+ scanEnd := make(chan error)
|
||||
+ scanner := &testScanner{
|
||||
+ scanf: func(src any) error {
|
||||
+ scanStart <- src
|
||||
+ return <-scanEnd
|
||||
+ },
|
||||
+ }
|
||||
+
|
||||
+ // Start a query, and pause it mid-scan.
|
||||
+ want := []byte("Alice")
|
||||
+ r, err := db.QueryContext(ctx, "SELECT|people|name|name=?", string(want))
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if !r.Next() {
|
||||
+ t.Fatalf("r.Next() = false, want true")
|
||||
+ }
|
||||
+ go func() {
|
||||
+ r.Scan(scanner)
|
||||
+ }()
|
||||
+ got := <-scanStart
|
||||
+ defer close(scanEnd)
|
||||
+ gotBytes, ok := got.([]byte)
|
||||
+ if !ok {
|
||||
+ t.Fatalf("r.Scan returned %T, want []byte", got)
|
||||
+ }
|
||||
+ if !bytes.Equal(gotBytes, want) {
|
||||
+ t.Fatalf("before cancel: r.Scan returned %q, want %q", gotBytes, want)
|
||||
+ }
|
||||
+
|
||||
+ // Cancel the query.
|
||||
+ // Sleep to give it a chance to finish canceling.
|
||||
+ cancel()
|
||||
+ time.Sleep(10 * time.Millisecond)
|
||||
+
|
||||
+ // Cancelling the query should not have changed the result.
|
||||
+ if !bytes.Equal(gotBytes, want) {
|
||||
+ t.Fatalf("after cancel: r.Scan result is now %q, want %q", gotBytes, want)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func BenchmarkConcurrentDBExec(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
ct := new(concurrentDBExecTest)
|
||||
2484
meta/recipes-devtools/python/python3-idna/CVE-2024-3651.patch
Normal file
2484
meta/recipes-devtools/python/python3-idna/CVE-2024-3651.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,8 @@ LIC_FILES_CHKSUM = "file://LICENSE.md;md5=239668a7c6066d9e0c5382e9c8c6c0e1"
|
||||
|
||||
SRC_URI[sha256sum] = "9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
|
||||
|
||||
SRC_URI += " file://CVE-2024-3651.patch"
|
||||
|
||||
inherit pypi setuptools3
|
||||
|
||||
# Remove bundled egg-info
|
||||
|
||||
@@ -4,7 +4,7 @@ HOMEPAGE = "https://pypi.org/project/Jinja2/"
|
||||
LICENSE = "BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=5dc88300786f1c214c1e9827a5229462"
|
||||
|
||||
SRC_URI[sha256sum] = "4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"
|
||||
SRC_URI[sha256sum] = "0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"
|
||||
|
||||
PYPI_PACKAGE = "jinja2"
|
||||
|
||||
@@ -22,6 +22,9 @@ SRC_URI += " \
|
||||
do_install_ptest() {
|
||||
install -d ${D}${PTEST_PATH}/tests
|
||||
cp -rf ${S}/tests/* ${D}${PTEST_PATH}/tests/
|
||||
|
||||
# test_async items require trio module
|
||||
rm -f ${D}${PTEST_PATH}/tests/test_async.py ${D}${PTEST_PATH}/tests/test_async_filters.py
|
||||
}
|
||||
|
||||
RDEPENDS:${PN}-ptest += " \
|
||||
@@ -15,7 +15,7 @@ DEPENDS += "python3 glib-2.0"
|
||||
SRCNAME="pygobject"
|
||||
|
||||
SRC_URI = " \
|
||||
http://ftp.gnome.org/pub/GNOME/sources/${SRCNAME}/${@gnome_verdir("${PV}")}/${SRCNAME}-${PV}.tar.xz \
|
||||
${GNOME_MIRROR}/${SRCNAME}/${@gnome_verdir("${PV}")}/${SRCNAME}-${PV}.tar.xz \
|
||||
file://0001-Do-not-build-tests.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "9b12616e32cfc792f9dc841d9c472a41a35b85ba67d3a6eb427e307a6fe4367b"
|
||||
|
||||
@@ -3,7 +3,7 @@ HOMEPAGE = "https://github.com/shazow/urllib3"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=c2823cb995439c984fd62a973d79815c"
|
||||
|
||||
SRC_URI[sha256sum] = "f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"
|
||||
SRC_URI[sha256sum] = "40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"
|
||||
|
||||
inherit pypi setuptools3
|
||||
|
||||
@@ -16,7 +16,7 @@ diff --git a/Lib/tarfile.py b/Lib/tarfile.py
|
||||
index 3bbbcaa..473167d 100755
|
||||
--- a/Lib/tarfile.py
|
||||
+++ b/Lib/tarfile.py
|
||||
@@ -2675,7 +2675,8 @@ class TarFile(object):
|
||||
@@ -2678,7 +2678,8 @@ class TarFile(object):
|
||||
os.lchown(targetpath, u, g)
|
||||
else:
|
||||
os.chown(targetpath, u, g)
|
||||
|
||||
364
meta/recipes-devtools/python/python3/CVE-2025-6075.patch
Normal file
364
meta/recipes-devtools/python/python3/CVE-2025-6075.patch
Normal file
@@ -0,0 +1,364 @@
|
||||
From 892747b4cf0f95ba8beb51c0d0658bfaa381ebca Mon Sep 17 00:00:00 2001
|
||||
From: Łukasz Langa <lukasz@langa.pl>
|
||||
Date: Fri, 31 Oct 2025 17:51:32 +0100
|
||||
Subject: [PATCH] gh-136065: Fix quadratic complexity in os.path.expandvars()
|
||||
(GH-134952) (GH-140851)
|
||||
|
||||
(cherry picked from commit f029e8db626ddc6e3a3beea4eff511a71aaceb5c)
|
||||
|
||||
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
|
||||
|
||||
CVE: CVE-2025-6075
|
||||
|
||||
Upstream-Status: Backport [https://github.com/python/cpython/commit/892747b4cf0f95ba8beb51c0d0658bfaa381ebca]
|
||||
|
||||
Signed-off-by: Praveen Kumar <praveen.kumar@windriver.com>
|
||||
---
|
||||
Lib/ntpath.py | 126 ++++++------------
|
||||
Lib/posixpath.py | 43 +++---
|
||||
Lib/test/test_genericpath.py | 14 ++
|
||||
Lib/test/test_ntpath.py | 20 ++-
|
||||
...-05-30-22-33-27.gh-issue-136065.bu337o.rst | 1 +
|
||||
5 files changed, 93 insertions(+), 111 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst
|
||||
|
||||
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
|
||||
index 9b0cca4..bd2b4e2 100644
|
||||
--- a/Lib/ntpath.py
|
||||
+++ b/Lib/ntpath.py
|
||||
@@ -374,17 +374,23 @@ def expanduser(path):
|
||||
# XXX With COMMAND.COM you can use any characters in a variable name,
|
||||
# XXX except '^|<>='.
|
||||
|
||||
+_varpattern = r"'[^']*'?|%(%|[^%]*%?)|\$(\$|[-\w]+|\{[^}]*\}?)"
|
||||
+_varsub = None
|
||||
+_varsubb = None
|
||||
+
|
||||
def expandvars(path):
|
||||
"""Expand shell variables of the forms $var, ${var} and %var%.
|
||||
|
||||
Unknown variables are left unchanged."""
|
||||
path = os.fspath(path)
|
||||
+ global _varsub, _varsubb
|
||||
if isinstance(path, bytes):
|
||||
if b'$' not in path and b'%' not in path:
|
||||
return path
|
||||
- import string
|
||||
- varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii')
|
||||
- quote = b'\''
|
||||
+ if not _varsubb:
|
||||
+ import re
|
||||
+ _varsubb = re.compile(_varpattern.encode(), re.ASCII).sub
|
||||
+ sub = _varsubb
|
||||
percent = b'%'
|
||||
brace = b'{'
|
||||
rbrace = b'}'
|
||||
@@ -393,94 +399,44 @@ def expandvars(path):
|
||||
else:
|
||||
if '$' not in path and '%' not in path:
|
||||
return path
|
||||
- import string
|
||||
- varchars = string.ascii_letters + string.digits + '_-'
|
||||
- quote = '\''
|
||||
+ if not _varsub:
|
||||
+ import re
|
||||
+ _varsub = re.compile(_varpattern, re.ASCII).sub
|
||||
+ sub = _varsub
|
||||
percent = '%'
|
||||
brace = '{'
|
||||
rbrace = '}'
|
||||
dollar = '$'
|
||||
environ = os.environ
|
||||
- res = path[:0]
|
||||
- index = 0
|
||||
- pathlen = len(path)
|
||||
- while index < pathlen:
|
||||
- c = path[index:index+1]
|
||||
- if c == quote: # no expansion within single quotes
|
||||
- path = path[index + 1:]
|
||||
- pathlen = len(path)
|
||||
- try:
|
||||
- index = path.index(c)
|
||||
- res += c + path[:index + 1]
|
||||
- except ValueError:
|
||||
- res += c + path
|
||||
- index = pathlen - 1
|
||||
- elif c == percent: # variable or '%'
|
||||
- if path[index + 1:index + 2] == percent:
|
||||
- res += c
|
||||
- index += 1
|
||||
- else:
|
||||
- path = path[index+1:]
|
||||
- pathlen = len(path)
|
||||
- try:
|
||||
- index = path.index(percent)
|
||||
- except ValueError:
|
||||
- res += percent + path
|
||||
- index = pathlen - 1
|
||||
- else:
|
||||
- var = path[:index]
|
||||
- try:
|
||||
- if environ is None:
|
||||
- value = os.fsencode(os.environ[os.fsdecode(var)])
|
||||
- else:
|
||||
- value = environ[var]
|
||||
- except KeyError:
|
||||
- value = percent + var + percent
|
||||
- res += value
|
||||
- elif c == dollar: # variable or '$$'
|
||||
- if path[index + 1:index + 2] == dollar:
|
||||
- res += c
|
||||
- index += 1
|
||||
- elif path[index + 1:index + 2] == brace:
|
||||
- path = path[index+2:]
|
||||
- pathlen = len(path)
|
||||
- try:
|
||||
- index = path.index(rbrace)
|
||||
- except ValueError:
|
||||
- res += dollar + brace + path
|
||||
- index = pathlen - 1
|
||||
- else:
|
||||
- var = path[:index]
|
||||
- try:
|
||||
- if environ is None:
|
||||
- value = os.fsencode(os.environ[os.fsdecode(var)])
|
||||
- else:
|
||||
- value = environ[var]
|
||||
- except KeyError:
|
||||
- value = dollar + brace + var + rbrace
|
||||
- res += value
|
||||
- else:
|
||||
- var = path[:0]
|
||||
- index += 1
|
||||
- c = path[index:index + 1]
|
||||
- while c and c in varchars:
|
||||
- var += c
|
||||
- index += 1
|
||||
- c = path[index:index + 1]
|
||||
- try:
|
||||
- if environ is None:
|
||||
- value = os.fsencode(os.environ[os.fsdecode(var)])
|
||||
- else:
|
||||
- value = environ[var]
|
||||
- except KeyError:
|
||||
- value = dollar + var
|
||||
- res += value
|
||||
- if c:
|
||||
- index -= 1
|
||||
+
|
||||
+ def repl(m):
|
||||
+ lastindex = m.lastindex
|
||||
+ if lastindex is None:
|
||||
+ return m[0]
|
||||
+ name = m[lastindex]
|
||||
+ if lastindex == 1:
|
||||
+ if name == percent:
|
||||
+ return name
|
||||
+ if not name.endswith(percent):
|
||||
+ return m[0]
|
||||
+ name = name[:-1]
|
||||
else:
|
||||
- res += c
|
||||
- index += 1
|
||||
- return res
|
||||
+ if name == dollar:
|
||||
+ return name
|
||||
+ if name.startswith(brace):
|
||||
+ if not name.endswith(rbrace):
|
||||
+ return m[0]
|
||||
+ name = name[1:-1]
|
||||
+
|
||||
+ try:
|
||||
+ if environ is None:
|
||||
+ return os.fsencode(os.environ[os.fsdecode(name)])
|
||||
+ else:
|
||||
+ return environ[name]
|
||||
+ except KeyError:
|
||||
+ return m[0]
|
||||
+
|
||||
+ return sub(repl, path)
|
||||
|
||||
|
||||
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
|
||||
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
|
||||
index b8dd563..75020ee 100644
|
||||
--- a/Lib/posixpath.py
|
||||
+++ b/Lib/posixpath.py
|
||||
@@ -279,42 +279,41 @@ def expanduser(path):
|
||||
# This expands the forms $variable and ${variable} only.
|
||||
# Non-existent variables are left unchanged.
|
||||
|
||||
-_varprog = None
|
||||
-_varprogb = None
|
||||
+_varpattern = r'\$(\w+|\{[^}]*\}?)'
|
||||
+_varsub = None
|
||||
+_varsubb = None
|
||||
|
||||
def expandvars(path):
|
||||
"""Expand shell variables of form $var and ${var}. Unknown variables
|
||||
are left unchanged."""
|
||||
path = os.fspath(path)
|
||||
- global _varprog, _varprogb
|
||||
+ global _varsub, _varsubb
|
||||
if isinstance(path, bytes):
|
||||
if b'$' not in path:
|
||||
return path
|
||||
- if not _varprogb:
|
||||
+ if not _varsubb:
|
||||
import re
|
||||
- _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII)
|
||||
- search = _varprogb.search
|
||||
+ _varsubb = re.compile(_varpattern.encode(), re.ASCII).sub
|
||||
+ sub = _varsubb
|
||||
start = b'{'
|
||||
end = b'}'
|
||||
environ = getattr(os, 'environb', None)
|
||||
else:
|
||||
if '$' not in path:
|
||||
return path
|
||||
- if not _varprog:
|
||||
+ if not _varsub:
|
||||
import re
|
||||
- _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII)
|
||||
- search = _varprog.search
|
||||
+ _varsub = re.compile(_varpattern, re.ASCII).sub
|
||||
+ sub = _varsub
|
||||
start = '{'
|
||||
end = '}'
|
||||
environ = os.environ
|
||||
- i = 0
|
||||
- while True:
|
||||
- m = search(path, i)
|
||||
- if not m:
|
||||
- break
|
||||
- i, j = m.span(0)
|
||||
- name = m.group(1)
|
||||
- if name.startswith(start) and name.endswith(end):
|
||||
+
|
||||
+ def repl(m):
|
||||
+ name = m[1]
|
||||
+ if name.startswith(start):
|
||||
+ if not name.endswith(end):
|
||||
+ return m[0]
|
||||
name = name[1:-1]
|
||||
try:
|
||||
if environ is None:
|
||||
@@ -322,13 +321,11 @@ def expandvars(path):
|
||||
else:
|
||||
value = environ[name]
|
||||
except KeyError:
|
||||
- i = j
|
||||
+ return m[0]
|
||||
else:
|
||||
- tail = path[j:]
|
||||
- path = path[:i] + value
|
||||
- i = len(path)
|
||||
- path += tail
|
||||
- return path
|
||||
+ return value
|
||||
+
|
||||
+ return sub(repl, path)
|
||||
|
||||
|
||||
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
|
||||
diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py
|
||||
index 1ff7f75..b0a1326 100644
|
||||
--- a/Lib/test/test_genericpath.py
|
||||
+++ b/Lib/test/test_genericpath.py
|
||||
@@ -7,6 +7,7 @@ import os
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
+from test import support
|
||||
from test.support import os_helper
|
||||
from test.support import warnings_helper
|
||||
from test.support.script_helper import assert_python_ok
|
||||
@@ -430,6 +431,19 @@ class CommonTest(GenericTest):
|
||||
os.fsencode('$bar%s bar' % nonascii))
|
||||
check(b'$spam}bar', os.fsencode('%s}bar' % nonascii))
|
||||
|
||||
+ @support.requires_resource('cpu')
|
||||
+ def test_expandvars_large(self):
|
||||
+ expandvars = self.pathmodule.expandvars
|
||||
+ with os_helper.EnvironmentVarGuard() as env:
|
||||
+ env.clear()
|
||||
+ env["A"] = "B"
|
||||
+ n = 100_000
|
||||
+ self.assertEqual(expandvars('$A'*n), 'B'*n)
|
||||
+ self.assertEqual(expandvars('${A}'*n), 'B'*n)
|
||||
+ self.assertEqual(expandvars('$A!'*n), 'B!'*n)
|
||||
+ self.assertEqual(expandvars('${A}A'*n), 'BA'*n)
|
||||
+ self.assertEqual(expandvars('${'*10*n), '${'*10*n)
|
||||
+
|
||||
def test_abspath(self):
|
||||
self.assertIn("foo", self.pathmodule.abspath("foo"))
|
||||
with warnings.catch_warnings():
|
||||
diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py
|
||||
index f790f77..161e57d 100644
|
||||
--- a/Lib/test/test_ntpath.py
|
||||
+++ b/Lib/test/test_ntpath.py
|
||||
@@ -5,8 +5,8 @@ import sys
|
||||
import unittest
|
||||
import warnings
|
||||
from ntpath import ALLOW_MISSING
|
||||
+from test import support
|
||||
from test.support import os_helper
|
||||
-from test.support import TestFailed
|
||||
from test.support.os_helper import FakePath
|
||||
from test import test_genericpath
|
||||
from tempfile import TemporaryFile
|
||||
@@ -56,7 +56,7 @@ def tester(fn, wantResult):
|
||||
fn = fn.replace("\\", "\\\\")
|
||||
gotResult = eval(fn)
|
||||
if wantResult != gotResult and _norm(wantResult) != _norm(gotResult):
|
||||
- raise TestFailed("%s should return: %s but returned: %s" \
|
||||
+ raise support.TestFailed("%s should return: %s but returned: %s" \
|
||||
%(str(fn), str(wantResult), str(gotResult)))
|
||||
|
||||
# then with bytes
|
||||
@@ -72,7 +72,7 @@ def tester(fn, wantResult):
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
gotResult = eval(fn)
|
||||
if _norm(wantResult) != _norm(gotResult):
|
||||
- raise TestFailed("%s should return: %s but returned: %s" \
|
||||
+ raise support.TestFailed("%s should return: %s but returned: %s" \
|
||||
%(str(fn), str(wantResult), repr(gotResult)))
|
||||
|
||||
|
||||
@@ -689,6 +689,19 @@ class TestNtpath(NtpathTestCase):
|
||||
check('%spam%bar', '%sbar' % nonascii)
|
||||
check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii)
|
||||
|
||||
+ @support.requires_resource('cpu')
|
||||
+ def test_expandvars_large(self):
|
||||
+ expandvars = ntpath.expandvars
|
||||
+ with os_helper.EnvironmentVarGuard() as env:
|
||||
+ env.clear()
|
||||
+ env["A"] = "B"
|
||||
+ n = 100_000
|
||||
+ self.assertEqual(expandvars('%A%'*n), 'B'*n)
|
||||
+ self.assertEqual(expandvars('%A%A'*n), 'BA'*n)
|
||||
+ self.assertEqual(expandvars("''"*n + '%%'), "''"*n + '%')
|
||||
+ self.assertEqual(expandvars("%%"*n), "%"*n)
|
||||
+ self.assertEqual(expandvars("$$"*n), "$"*n)
|
||||
+
|
||||
def test_expanduser(self):
|
||||
tester('ntpath.expanduser("test")', 'test')
|
||||
|
||||
@@ -923,6 +936,7 @@ class TestNtpath(NtpathTestCase):
|
||||
self.assertIsInstance(b_final_path, bytes)
|
||||
self.assertGreater(len(b_final_path), 0)
|
||||
|
||||
+
|
||||
class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase):
|
||||
pathmodule = ntpath
|
||||
attributes = ['relpath']
|
||||
diff --git a/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst b/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst
|
||||
new file mode 100644
|
||||
index 0000000..1d152bb
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2025-05-30-22-33-27.gh-issue-136065.bu337o.rst
|
||||
@@ -0,0 +1 @@
|
||||
+Fix quadratic complexity in :func:`os.path.expandvars`.
|
||||
--
|
||||
2.40.0
|
||||
@@ -1,219 +0,0 @@
|
||||
From c9d9f78feb1467e73fd29356c040bde1c104f29f Mon Sep 17 00:00:00 2001
|
||||
From: "Miss Islington (bot)"
|
||||
<31488909+miss-islington@users.noreply.github.com>
|
||||
Date: Mon, 4 Aug 2025 13:45:06 +0200
|
||||
Subject: [PATCH] [3.12] gh-130577: tarfile now validates archives to ensure
|
||||
member offsets are non-negative (GH-137027) (#137171)
|
||||
|
||||
(cherry picked from commit 7040aa54f14676938970e10c5f74ea93cd56aa38)
|
||||
|
||||
Co-authored-by: Alexander Urieles <aeurielesn@users.noreply.github.com>
|
||||
Co-authored-by: Gregory P. Smith <greg@krypto.org>
|
||||
|
||||
CVE: CVE-2025-8194
|
||||
Upstream-Status: Backport [https://github.com/python/cpython/commit/c9d9f78feb1467e73fd29356c040bde1c104f29f]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
Lib/tarfile.py | 3 +
|
||||
Lib/test/test_tarfile.py | 156 ++++++++++++++++++
|
||||
...-07-23-00-35-29.gh-issue-130577.c7EITy.rst | 3 +
|
||||
3 files changed, 162 insertions(+)
|
||||
create mode 100644 Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst
|
||||
|
||||
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
|
||||
index 9999a99d54..59d3f6e5cc 100755
|
||||
--- a/Lib/tarfile.py
|
||||
+++ b/Lib/tarfile.py
|
||||
@@ -1613,6 +1613,9 @@ class TarInfo(object):
|
||||
"""Round up a byte count by BLOCKSIZE and return it,
|
||||
e.g. _block(834) => 1024.
|
||||
"""
|
||||
+ # Only non-negative offsets are allowed
|
||||
+ if count < 0:
|
||||
+ raise InvalidHeaderError("invalid offset")
|
||||
blocks, remainder = divmod(count, BLOCKSIZE)
|
||||
if remainder:
|
||||
blocks += 1
|
||||
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
|
||||
index a184ba75a8..759fa03ead 100644
|
||||
--- a/Lib/test/test_tarfile.py
|
||||
+++ b/Lib/test/test_tarfile.py
|
||||
@@ -49,6 +49,7 @@ bz2name = os.path.join(TEMPDIR, "testtar.tar.bz2")
|
||||
xzname = os.path.join(TEMPDIR, "testtar.tar.xz")
|
||||
tmpname = os.path.join(TEMPDIR, "tmp.tar")
|
||||
dotlessname = os.path.join(TEMPDIR, "testtar")
|
||||
+SPACE = b" "
|
||||
|
||||
sha256_regtype = (
|
||||
"e09e4bc8b3c9d9177e77256353b36c159f5f040531bbd4b024a8f9b9196c71ce"
|
||||
@@ -4273,6 +4274,161 @@ class TestExtractionFilters(unittest.TestCase):
|
||||
self.expect_exception(TypeError) # errorlevel is not int
|
||||
|
||||
|
||||
+class OffsetValidationTests(unittest.TestCase):
|
||||
+ tarname = tmpname
|
||||
+ invalid_posix_header = (
|
||||
+ # name: 100 bytes
|
||||
+ tarfile.NUL * tarfile.LENGTH_NAME
|
||||
+ # mode, space, null terminator: 8 bytes
|
||||
+ + b"000755" + SPACE + tarfile.NUL
|
||||
+ # uid, space, null terminator: 8 bytes
|
||||
+ + b"000001" + SPACE + tarfile.NUL
|
||||
+ # gid, space, null terminator: 8 bytes
|
||||
+ + b"000001" + SPACE + tarfile.NUL
|
||||
+ # size, space: 12 bytes
|
||||
+ + b"\xff" * 11 + SPACE
|
||||
+ # mtime, space: 12 bytes
|
||||
+ + tarfile.NUL * 11 + SPACE
|
||||
+ # chksum: 8 bytes
|
||||
+ + b"0011407" + tarfile.NUL
|
||||
+ # type: 1 byte
|
||||
+ + tarfile.REGTYPE
|
||||
+ # linkname: 100 bytes
|
||||
+ + tarfile.NUL * tarfile.LENGTH_LINK
|
||||
+ # magic: 6 bytes, version: 2 bytes
|
||||
+ + tarfile.POSIX_MAGIC
|
||||
+ # uname: 32 bytes
|
||||
+ + tarfile.NUL * 32
|
||||
+ # gname: 32 bytes
|
||||
+ + tarfile.NUL * 32
|
||||
+ # devmajor, space, null terminator: 8 bytes
|
||||
+ + tarfile.NUL * 6 + SPACE + tarfile.NUL
|
||||
+ # devminor, space, null terminator: 8 bytes
|
||||
+ + tarfile.NUL * 6 + SPACE + tarfile.NUL
|
||||
+ # prefix: 155 bytes
|
||||
+ + tarfile.NUL * tarfile.LENGTH_PREFIX
|
||||
+ # padding: 12 bytes
|
||||
+ + tarfile.NUL * 12
|
||||
+ )
|
||||
+ invalid_gnu_header = (
|
||||
+ # name: 100 bytes
|
||||
+ tarfile.NUL * tarfile.LENGTH_NAME
|
||||
+ # mode, null terminator: 8 bytes
|
||||
+ + b"0000755" + tarfile.NUL
|
||||
+ # uid, null terminator: 8 bytes
|
||||
+ + b"0000001" + tarfile.NUL
|
||||
+ # gid, space, null terminator: 8 bytes
|
||||
+ + b"0000001" + tarfile.NUL
|
||||
+ # size, space: 12 bytes
|
||||
+ + b"\xff" * 11 + SPACE
|
||||
+ # mtime, space: 12 bytes
|
||||
+ + tarfile.NUL * 11 + SPACE
|
||||
+ # chksum: 8 bytes
|
||||
+ + b"0011327" + tarfile.NUL
|
||||
+ # type: 1 byte
|
||||
+ + tarfile.REGTYPE
|
||||
+ # linkname: 100 bytes
|
||||
+ + tarfile.NUL * tarfile.LENGTH_LINK
|
||||
+ # magic: 8 bytes
|
||||
+ + tarfile.GNU_MAGIC
|
||||
+ # uname: 32 bytes
|
||||
+ + tarfile.NUL * 32
|
||||
+ # gname: 32 bytes
|
||||
+ + tarfile.NUL * 32
|
||||
+ # devmajor, null terminator: 8 bytes
|
||||
+ + tarfile.NUL * 8
|
||||
+ # devminor, null terminator: 8 bytes
|
||||
+ + tarfile.NUL * 8
|
||||
+ # padding: 167 bytes
|
||||
+ + tarfile.NUL * 167
|
||||
+ )
|
||||
+ invalid_v7_header = (
|
||||
+ # name: 100 bytes
|
||||
+ tarfile.NUL * tarfile.LENGTH_NAME
|
||||
+ # mode, space, null terminator: 8 bytes
|
||||
+ + b"000755" + SPACE + tarfile.NUL
|
||||
+ # uid, space, null terminator: 8 bytes
|
||||
+ + b"000001" + SPACE + tarfile.NUL
|
||||
+ # gid, space, null terminator: 8 bytes
|
||||
+ + b"000001" + SPACE + tarfile.NUL
|
||||
+ # size, space: 12 bytes
|
||||
+ + b"\xff" * 11 + SPACE
|
||||
+ # mtime, space: 12 bytes
|
||||
+ + tarfile.NUL * 11 + SPACE
|
||||
+ # chksum: 8 bytes
|
||||
+ + b"0010070" + tarfile.NUL
|
||||
+ # type: 1 byte
|
||||
+ + tarfile.REGTYPE
|
||||
+ # linkname: 100 bytes
|
||||
+ + tarfile.NUL * tarfile.LENGTH_LINK
|
||||
+ # padding: 255 bytes
|
||||
+ + tarfile.NUL * 255
|
||||
+ )
|
||||
+ valid_gnu_header = tarfile.TarInfo("filename").tobuf(tarfile.GNU_FORMAT)
|
||||
+ data_block = b"\xff" * tarfile.BLOCKSIZE
|
||||
+
|
||||
+ def _write_buffer(self, buffer):
|
||||
+ with open(self.tarname, "wb") as f:
|
||||
+ f.write(buffer)
|
||||
+
|
||||
+ def _get_members(self, ignore_zeros=None):
|
||||
+ with open(self.tarname, "rb") as f:
|
||||
+ with tarfile.open(
|
||||
+ mode="r", fileobj=f, ignore_zeros=ignore_zeros
|
||||
+ ) as tar:
|
||||
+ return tar.getmembers()
|
||||
+
|
||||
+ def _assert_raises_read_error_exception(self):
|
||||
+ with self.assertRaisesRegex(
|
||||
+ tarfile.ReadError, "file could not be opened successfully"
|
||||
+ ):
|
||||
+ self._get_members()
|
||||
+
|
||||
+ def test_invalid_offset_header_validations(self):
|
||||
+ for tar_format, invalid_header in (
|
||||
+ ("posix", self.invalid_posix_header),
|
||||
+ ("gnu", self.invalid_gnu_header),
|
||||
+ ("v7", self.invalid_v7_header),
|
||||
+ ):
|
||||
+ with self.subTest(format=tar_format):
|
||||
+ self._write_buffer(invalid_header)
|
||||
+ self._assert_raises_read_error_exception()
|
||||
+
|
||||
+ def test_early_stop_at_invalid_offset_header(self):
|
||||
+ buffer = self.valid_gnu_header + self.invalid_gnu_header + self.valid_gnu_header
|
||||
+ self._write_buffer(buffer)
|
||||
+ members = self._get_members()
|
||||
+ self.assertEqual(len(members), 1)
|
||||
+ self.assertEqual(members[0].name, "filename")
|
||||
+ self.assertEqual(members[0].offset, 0)
|
||||
+
|
||||
+ def test_ignore_invalid_archive(self):
|
||||
+ # 3 invalid headers with their respective data
|
||||
+ buffer = (self.invalid_gnu_header + self.data_block) * 3
|
||||
+ self._write_buffer(buffer)
|
||||
+ members = self._get_members(ignore_zeros=True)
|
||||
+ self.assertEqual(len(members), 0)
|
||||
+
|
||||
+ def test_ignore_invalid_offset_headers(self):
|
||||
+ for first_block, second_block, expected_offset in (
|
||||
+ (
|
||||
+ (self.valid_gnu_header),
|
||||
+ (self.invalid_gnu_header + self.data_block),
|
||||
+ 0,
|
||||
+ ),
|
||||
+ (
|
||||
+ (self.invalid_gnu_header + self.data_block),
|
||||
+ (self.valid_gnu_header),
|
||||
+ 1024,
|
||||
+ ),
|
||||
+ ):
|
||||
+ self._write_buffer(first_block + second_block)
|
||||
+ members = self._get_members(ignore_zeros=True)
|
||||
+ self.assertEqual(len(members), 1)
|
||||
+ self.assertEqual(members[0].name, "filename")
|
||||
+ self.assertEqual(members[0].offset, expected_offset)
|
||||
+
|
||||
+
|
||||
def setUpModule():
|
||||
os_helper.unlink(TEMPDIR)
|
||||
os.makedirs(TEMPDIR)
|
||||
diff --git a/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst b/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst
|
||||
new file mode 100644
|
||||
index 0000000000..342cabbc86
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst
|
||||
@@ -0,0 +1,3 @@
|
||||
+:mod:`tarfile` now validates archives to ensure member offsets are
|
||||
+non-negative. (Contributed by Alexander Enrique Urieles Nieto in
|
||||
+:gh:`130577`.)
|
||||
@@ -37,7 +37,7 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
|
||||
file://0001-Avoid-shebang-overflow-on-python-config.py.patch \
|
||||
file://0001-test_storlines-skip-due-to-load-variability.patch \
|
||||
file://0001-gh-107811-tarfile-treat-overflow-in-UID-GID-as-failu.patch \
|
||||
file://CVE-2025-8194.patch \
|
||||
file://CVE-2025-6075.patch \
|
||||
"
|
||||
|
||||
SRC_URI:append:class-native = " \
|
||||
@@ -46,7 +46,7 @@ SRC_URI:append:class-native = " \
|
||||
file://12-distutils-prefix-is-inside-staging-area.patch \
|
||||
file://0001-Don-t-search-system-for-headers-libraries.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "ae665bc678abd9ab6a6e1573d2481625a53719bc517e9a634ed2b9fefae3817f"
|
||||
SRC_URI[sha256sum] = "c8f4a596572201d81dd7df91f70e177e19a70f1d489968b54b5fbbf29a97c076"
|
||||
|
||||
# exclude pre-releases for both python 2.x and 3.x
|
||||
UPSTREAM_CHECK_REGEX = "[Pp]ython-(?P<pver>\d+(\.\d+)+).tar"
|
||||
@@ -128,6 +128,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
|
||||
file://CVE-2024-3446-0005.patch \
|
||||
file://CVE-2024-3446-0006.patch \
|
||||
file://CVE-2024-3447.patch \
|
||||
file://CVE-2024-8354.patch \
|
||||
"
|
||||
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user