diff options
Diffstat (limited to 'main')
149 files changed, 14403 insertions, 596 deletions
diff --git a/main/alpine-base/APKBUILD b/main/alpine-base/APKBUILD index c3eee98e1de..e226c059e7d 100644 --- a/main/alpine-base/APKBUILD +++ b/main/alpine-base/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Natanael Copa <ncopa@alpinelinux.org> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=alpine-base -pkgver=3.12.8 +pkgver=3.12.12 pkgrel=0 pkgdesc="Meta package for minimal alpine base" url="https://alpinelinux.org" diff --git a/main/alpine-keys/APKBUILD b/main/alpine-keys/APKBUILD index 1ca5e93b6fe..9c95f33c466 100644 --- a/main/alpine-keys/APKBUILD +++ b/main/alpine-keys/APKBUILD @@ -1,6 +1,6 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=alpine-keys -pkgver=2.2 +pkgver=2.4 pkgrel=0 pkgdesc="Public keys for Alpine Linux packages" url="https://alpinelinux.org" @@ -12,17 +12,27 @@ options="!check" # No testsuite _arch_keys=" aarch64:alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub - armhf:alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub + aarch64:alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub + armhf,armv7:alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub + armv7:alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub + armhf:alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub x86:alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub + x86:alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub x86,x86_64:alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub x86_64:alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub + x86_64:alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub ppc64le:alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub + ppc64le:alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub s390x:alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub + s390x:alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub mips64:alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub + + riscv64:alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub + riscv64:alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub " for _i in $_arch_keys; do @@ -64,6 +74,12 @@ _install_mips() { esac } +_install_riscv() { + case "$1" in + riscv*) _ins_key $1 $2 ;; + esac +} + package() { # copy keys for repos mkdir -p "$pkgdir"/etc/apk/keys @@ -83,16 +99,28 @@ package() { ppc*) _install_ppc $_arch $_key ;; s390x) _install_s390x $_arch $_key ;; mips*) _install_mips $_arch $_key ;; + riscv*) _install_riscv $_arch $_key ;; esac done done } -sha512sums="e4f9e314f8e506fba2cb3e599c6412a036ec37ce3a54990fc7d80a821d8728f40ee3b4aa8a15218d50341fa785d9ddf7c7471f45018c6a2065ab13664a1aa9e9 alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub +sha512sums=" +e4f9e314f8e506fba2cb3e599c6412a036ec37ce3a54990fc7d80a821d8728f40ee3b4aa8a15218d50341fa785d9ddf7c7471f45018c6a2065ab13664a1aa9e9 alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub +51a5ec21283fe218809b2325202e1f8c9b2551705db48254b9d48a04f4ed0075de51e9886c4704647ffb309fd32d9850d14013848a53038039e85011251fe1cc alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub 698fda502f70365a852de3c10636eadfc4f70a7a00f096581119aef665e248b787004ceef63f4c8cb18c6f88d18b8b1bd6b3c5d260e79e6d73a3cc09537b196e alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub +a98095a626f2dcbda73ffd8873ba2d609ee1d881f5da13b0eb3469ddd58b06440b4b0b2f791b037c88073e9a17c6dfc62dc1a4c8491bed871524d772ef04ad24 alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub +7aa5526a88519ae91f997bf914a9bd3d230b21c011587f155ce22c4bb94b70181b28590027eb555d96d1122dffb8242c1fb044228e99b4e9b7650fcf6f5121c7 alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub e18e65ee911eb1f8ea869f758e8f2c94cf2ac254ee7ab90a3de1d47b94a547c2066214abf710da21910ebedc0153d05fd4fe579cc5ce24f46e0cfd29a02b1a68 alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub +b89d825e6af73687339848817791b294e2404162e2e069d9212d76d4ee53d6216eb75421a07b02f9778ef57dbb27962b2436247264eea1a1d882967ca0c18724 alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub 2d4064cbe09ff958493ec86bcb925af9b7517825d1d9d8d00f2986201ad5952f986fea83d1e2c177e92130700bafa8c0bff61411b3cdb59a41e460ed719580a6 alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub 721134f289ab1e7dde9158359906017daee40983199fe55f28206c8cdc46b8fcf177a36f270ce374b0eba5dbe01f68cbb3e385ae78a54bb0a2ed1e83a4d820a5 alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub +8b9c2208c904c9f34d9d01d3d68b224208530e684265df214deb8c9e6b4b19633aa48a405e673249c9e93a8ee194a336e951cd82a4e27e5e66e85fdc5e0d495e alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub bb5a3df8fac14a62d5936fb3722873fa6a121219b703cba955eb77de38c4384aeaf378fb9321a655e255f0be761e894e309b3789867279c1524dab6300cd8ef1 alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub +bad4da65221150a5d4cc6f63981e4dd203d40844d32e82c17f346eee5350e460e32d28f0e231a2b78d326ec32b898eec597d3787dae47dcacc9a9776d19fb4a1 alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub 0666389ca53121453578cd4bef5fd06e159e291164b3e3233e7d6521604f8bebd30caeef1663adcd5309e07278833402c8a92c33294ec0c5cada24dc47c8cc98 alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub -66ce9677e9c2a7961d5d7bc5b162ed3114a7aef6d01181073c1f42a9934966eecded2ec09deb210f5a389d434d1641ba35fe3abdd5246b2e97d5a5b26a945c5c alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub" +83fc29066f6073418ecf01176ce24c1c0e788508f3083a97691706e2c78323e53448060fb0d2abb8118a759570f1f0db9d39953c63fe26fe06da2be05dff393c alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub +66ce9677e9c2a7961d5d7bc5b162ed3114a7aef6d01181073c1f42a9934966eecded2ec09deb210f5a389d434d1641ba35fe3abdd5246b2e97d5a5b26a945c5c alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub +34514100e502f449dcabe0aa550232c3330ed2f0b789b977eb228d4ac86afc93479474ac005914992a3b47c18ee3eb32ca27ccd0d392700a8f11f47d64a78969 alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub +7cea57204a50d72bddff201c509ccbf06773d87062a3ead0a206cc6e4a00e0960f52d21f7cee7aaec6a4abba7a697e2e2e7f630fa1ccef7ee2c33908fca18998 alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub +" diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub new file mode 100644 index 00000000000..2b8a4a93e06 --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwR4uJVtJOnOFGchnMW5Y +j5/waBdG1u5BTMlH+iQMcV5+VgWhmpZHJCBz3ocD+0IGk2I68S5TDOHec/GSC0lv +6R9o6F7h429GmgPgVKQsc8mPTPtbjJMuLLs4xKc+viCplXc0Nc0ZoHmCH4da6fCV +tdpHQjVe6F9zjdquZ4RjV6R6JTiN9v924dGMAkbW/xXmamtz51FzondKC52Gh8Mo +/oA0/T0KsCMCi7tb4QNQUYrf+Xcha9uus4ww1kWNZyfXJB87a2kORLiWMfs2IBBJ +TmZ2Fnk0JnHDb8Oknxd9PvJPT0mvyT8DA+KIAPqNvOjUXP4bnjEHJcoCP9S5HkGC +IQIDAQAB +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub new file mode 100644 index 00000000000..f2165aebada --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAutQkua2CAig4VFSJ7v54 +ALyu/J1WB3oni7qwCZD3veURw7HxpNAj9hR+S5N/pNeZgubQvJWyaPuQDm7PTs1+ +tFGiYNfAsiibX6Rv0wci3M+z2XEVAeR9Vzg6v4qoofDyoTbovn2LztaNEjTkB+oK +tlvpNhg1zhou0jDVYFniEXvzjckxswHVb8cT0OMTKHALyLPrPOJzVtM9C1ew2Nnc +3848xLiApMu3NBk0JqfcS3Bo5Y2b1FRVBvdt+2gFoKZix1MnZdAEZ8xQzL/a0YS5 +Hd0wj5+EEKHfOd3A75uPa/WQmA+o0cBFfrzm69QDcSJSwGpzWrD1ScH3AK8nWvoj +v7e9gukK/9yl1b4fQQ00vttwJPSgm9EnfPHLAtgXkRloI27H6/PuLoNvSAMQwuCD +hQRlyGLPBETKkHeodfLoULjhDi1K2gKJTMhtbnUcAA7nEphkMhPWkBpgFdrH+5z4 +Lxy+3ek0cqcI7K68EtrffU8jtUj9LFTUC8dERaIBs7NgQ/LfDbDfGh9g6qVj1hZl +k9aaIPTm/xsi8v3u+0qaq7KzIBc9s59JOoA8TlpOaYdVgSQhHHLBaahOuAigH+VI +isbC9vmqsThF2QdDtQt37keuqoda2E6sL7PUvIyVXDRfwX7uMDjlzTxHTymvq2Ck +htBqojBnThmjJQFgZXocHG8CAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub new file mode 100644 index 00000000000..aa63d81d662 --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlEyxkHggKCXC2Wf5Mzx4 +nZLFZvU2bgcA3exfNPO/g1YunKfQY+Jg4fr6tJUUTZ3XZUrhmLNWvpvSwDS19ZmC +IXOu0+V94aNgnhMsk9rr59I8qcbsQGIBoHzuAl8NzZCgdbEXkiY90w1skUw8J57z +qCsMBydAueMXuWqF5nGtYbi5vHwK42PffpiZ7G5Kjwn8nYMW5IZdL6ZnMEVJUWC9 +I4waeKg0yskczYDmZUEAtrn3laX9677ToCpiKrvmZYjlGl0BaGp3cxggP2xaDbUq +qfFxWNgvUAb3pXD09JM6Mt6HSIJaFc9vQbrKB9KT515y763j5CC2KUsilszKi3mB +HYe5PoebdjS7D1Oh+tRqfegU2IImzSwW3iwA7PJvefFuc/kNIijfS/gH/cAqAK6z +bhdOtE/zc7TtqW2Wn5Y03jIZdtm12CxSxwgtCF1NPyEWyIxAQUX9ACb3M0FAZ61n +fpPrvwTaIIxxZ01L3IzPLpbc44x/DhJIEU+iDt6IMTrHOphD9MCG4631eIdB0H1b +6zbNX1CXTsafqHRFV9XmYYIeOMggmd90s3xIbEujA6HKNP/gwzO6CDJ+nHFDEqoF +SkxRdTkEqjTjVKieURW7Swv7zpfu5PrsrrkyGnsRrBJJzXlm2FOOxnbI2iSL1B5F +rO5kbUxFeZUIDq+7Yv4kLWcCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub new file mode 100644 index 00000000000..59c330e9f73 --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnC+bR4bHf/L6QdU4puhQ +gl1MHePszRC38bzvVFDUJsmCaMCL2suCs2A2yxAgGb9pu9AJYLAmxQC4mM3jNqhg +/E7yuaBbek3O02zN/ctvflJ250wZCy+z0ZGIp1ak6pu1j14IwHokl9j36zNfGtfv +ADVOcdpWITFFlPqwq1qt/H3UsKVmtiF3BNWWTeUEQwKvlU8ymxgS99yn0+4OPyNT +L3EUeS+NQJtDS01unau0t7LnjUXn+XIneWny8bIYOQCuVR6s/gpIGuhBaUqwaJOw +7jkJZYF2Ij7uPb4b5/R3vX2FfxxqEHqssFSg8FFUNTZz3qNZs0CRVyfA972g9WkJ +hPfn31pQYil4QGRibCMIeU27YAEjXoqfJKEPh4UWMQsQLrEfdGfb8VgwrPbniGfU +L3jKJR3VAafL9330iawzVQDlIlwGl6u77gEXMl9K0pfazunYhAp+BMP+9ot5ckK+ +osmrqj11qMESsAj083GeFdfV3pXEIwUytaB0AKEht9DbqUfiE/oeZ/LAXgySMtVC +sbC4ESmgVeY2xSBIJdDyUap7FR49GGrw0W49NUv9gRgQtGGaNVQQO9oGL2PBC41P +iWF9GLoX30HIz1P8PF/cZvicSSPkQf2Z6TV+t0ebdGNS5DjapdnCrq8m9Z0pyKsQ +uxAL2a7zX8l5i1CZh1ycUGsCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub new file mode 100644 index 00000000000..915bc566b74 --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0MfCDrhODRCIxR9Dep1s +eXafh5CE5BrF4WbCgCsevyPIdvTeyIaW4vmO3bbG4VzhogDZju+R3IQYFuhoXP5v +Y+zYJGnwrgz3r5wYAvPnLEs1+dtDKYOgJXQj+wLJBW1mzRDL8FoRXOe5iRmn1EFS +wZ1DoUvyu7/J5r0itKicZp3QKED6YoilXed+1vnS4Sk0mzN4smuMR9eO1mMCqNp9 +9KTfRDHTbakIHwasECCXCp50uXdoW6ig/xUAFanpm9LtK6jctNDbXDhQmgvAaLXZ +LvFqoaYJ/CvWkyYCgL6qxvMvVmPoRv7OPcyni4xR/WgWa0MSaEWjgPx3+yj9fiMA +1S02pFWFDOr5OUF/O4YhFJvUCOtVsUPPfA/Lj6faL0h5QI9mQhy5Zb9TTaS9jB6p +Lw7u0dJlrjFedk8KTJdFCcaGYHP6kNPnOxMylcB/5WcztXZVQD5WpCicGNBxCGMm +W64SgrV7M07gQfL/32QLsdqPUf0i8hoVD8wfQ3EpbQzv6Fk1Cn90bZqZafg8XWGY +wddhkXk7egrr23Djv37V2okjzdqoyLBYBxMz63qQzFoAVv5VoY2NDTbXYUYytOvG +GJ1afYDRVWrExCech1mX5ZVUB1br6WM+psFLJFoBFl6mDmiYt0vMYBddKISsvwLl +IJQkzDwtXzT2cSjoj3T5QekCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub new file mode 100644 index 00000000000..1e49d246902 --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvaaoSLab+IluixwKV5Od +0gib2YurjPatGIbn5Ov2DLUFYiebj2oJINXJSwUOO+4WcuHFEqiL/1rya+k5hLZt +hnPL1tn6QD4rESznvGSasRCQNT2vS/oyZbTYJRyAtFkEYLlq0t3S3xBxxHWuvIf0 +qVxVNYpQWyM3N9RIeYBR/euXKJXileSHk/uq1I5wTC0XBIHWcthczGN0m9wBEiWS +0m3cnPk4q0Ea8mUJ91Rqob19qETz6VbSPYYpZk3qOycjKosuwcuzoMpwU8KRiMFd +5LHtX0Hx85ghGsWDVtS0c0+aJa4lOMGvJCAOvDfqvODv7gKlCXUpgumGpLdTmaZ8 +1RwqspAe3IqBcdKTqRD4m2mSg23nVx2FAY3cjFvZQtfooT7q1ItRV5RgH6FhQSl7 ++6YIMJ1Bf8AAlLdRLpg+doOUGcEn+pkDiHFgI8ylH1LKyFKw+eXaAml/7DaWZk1d +dqggwhXOhc/UUZFQuQQ8A8zpA13PcbC05XxN2hyP93tCEtyynMLVPtrRwDnHxFKa +qKzs3rMDXPSXRn3ZZTdKH3069ApkEjQdpcwUh+EmJ1Ve/5cdtzT6kKWCjKBFZP/s +91MlRrX2BTRdHaU5QJkUheUtakwxuHrdah2F94lRmsnQlpPr2YseJu6sIE+Dnx4M +CfhdVbQL2w54R645nlnohu8CAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub new file mode 100644 index 00000000000..bb15efe96d7 --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq0BFD1D4lIxQcsqEpQzU +pNCYM3aP1V/fxxVdT4DWvSI53JHTwHQamKdMWtEXetWVbP5zSROniYKFXd/xrD9X +0jiGHey3lEtylXRIPxe5s+wXoCmNLcJVnvTcDtwx/ne2NLHxp76lyc25At+6RgE6 +ADjLVuoD7M4IFDkAsd8UQ8zM0Dww9SylIk/wgV3ZkifecvgUQRagrNUdUjR56EBZ +raQrev4hhzOgwelT0kXCu3snbUuNY/lU53CoTzfBJ5UfEJ5pMw1ij6X0r5S9IVsy +KLWH1hiO0NzU2c8ViUYCly4Fe9xMTFc6u2dy/dxf6FwERfGzETQxqZvSfrRX+GLj +/QZAXiPg5178hT/m0Y3z5IGenIC/80Z9NCi+byF1WuJlzKjDcF/TU72zk0+PNM/H +Kuppf3JT4DyjiVzNC5YoWJT2QRMS9KLP5iKCSThwVceEEg5HfhQBRT9M6KIcFLSs +mFjx9kNEEmc1E8hl5IR3+3Ry8G5/bTIIruz14jgeY9u5jhL8Vyyvo41jgt9sLHR1 +/J1TxKfkgksYev7PoX6/ZzJ1ksWKZY5NFoDXTNYUgzFUTOoEaOg3BAQKadb3Qbbq +XIrxmPBdgrn9QI7NCgfnAY3Tb4EEjs3ON/BNyEhUENcXOH6I1NbcuBQ7g9P73kE4 +VORdoc8MdJ5eoKBpO8Ww8HECAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub new file mode 100644 index 00000000000..0ecbccc2e4a --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyduVzi1mWm+lYo2Tqt/0 +XkCIWrDNP1QBMVPrE0/ZlU2bCGSoo2Z9FHQKz/mTyMRlhNqTfhJ5qU3U9XlyGOPJ +piM+b91g26pnpXJ2Q2kOypSgOMOPA4cQ42PkHBEqhuzssfj9t7x47ppS94bboh46 +xLSDRff/NAbtwTpvhStV3URYkxFG++cKGGa5MPXBrxIp+iZf9GnuxVdST5PGiVGP +ODL/b69sPJQNbJHVquqUTOh5Ry8uuD2WZuXfKf7/C0jC/ie9m2+0CttNu9tMciGM +EyKG1/Xhk5iIWO43m4SrrT2WkFlcZ1z2JSf9Pjm4C2+HovYpihwwdM/OdP8Xmsnr +DzVB4YvQiW+IHBjStHVuyiZWc+JsgEPJzisNY0Wyc/kNyNtqVKpX6dRhMLanLmy+ +f53cCSI05KPQAcGj6tdL+D60uKDkt+FsDa0BTAobZ31OsFVid0vCXtsbplNhW1IF +HwsGXBTVcfXg44RLyL8Lk/2dQxDHNHzAUslJXzPxaHBLmt++2COa2EI1iWlvtznk +Ok9WP8SOAIj+xdqoiHcC4j72BOVVgiITIJNHrbppZCq6qPR+fgXmXa+sDcGh30m6 +9Wpbr28kLMSHiENCWTdsFij+NQTd5S47H7XTROHnalYDuF1RpS+DpQidT5tUimaT +JZDr++FjKrnnijbyNF8b98UCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub new file mode 100644 index 00000000000..ceffa3ace9c --- /dev/null +++ b/main/alpine-keys/alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpUpyWDWjlUk3smlWeA0 +lIMW+oJ38t92CRLHH3IqRhyECBRW0d0aRGtq7TY8PmxjjvBZrxTNDpJT6KUk4LRm +a6A6IuAI7QnNK8SJqM0DLzlpygd7GJf8ZL9SoHSH+gFsYF67Cpooz/YDqWrlN7Vw +tO00s0B+eXy+PCXYU7VSfuWFGK8TGEv6HfGMALLjhqMManyvfp8hz3ubN1rK3c8C +US/ilRh1qckdbtPvoDPhSbTDmfU1g/EfRSIEXBrIMLg9ka/XB9PvWRrekrppnQzP +hP9YE3x/wbFc5QqQWiRCYyQl/rgIMOXvIxhkfe8H5n1Et4VAorkpEAXdsfN8KSVv +LSMazVlLp9GYq5SUpqYX3KnxdWBgN7BJoZ4sltsTpHQ/34SXWfu3UmyUveWj7wp0 +x9hwsPirVI00EEea9AbP7NM2rAyu6ukcm4m6ATd2DZJIViq2es6m60AE6SMCmrQF +wmk4H/kdQgeAELVfGOm2VyJ3z69fQuywz7xu27S6zTKi05Qlnohxol4wVb6OB7qG +LPRtK9ObgzRo/OPumyXqlzAi/Yvyd1ZQk8labZps3e16bQp8+pVPiumWioMFJDWV +GZjCmyMSU8V6MB6njbgLHoyg2LCukCAeSjbPGGGYhnKLm1AKSoJh3IpZuqcKCk5C +8CM1S15HxV78s9dFntEqIokCAwEAAQ== +-----END PUBLIC KEY----- diff --git a/main/apache2/APKBUILD b/main/apache2/APKBUILD index e8ad6cfa807..6ac81b4063c 100644 --- a/main/apache2/APKBUILD +++ b/main/apache2/APKBUILD @@ -2,7 +2,7 @@ # Contributor: Valery Kartel <valery.kartel@gmail.com> pkgname=apache2 _pkgreal=httpd -pkgver=2.4.51 +pkgver=2.4.53 pkgrel=0 pkgdesc="A high performance Unix-based HTTP server" url="https://httpd.apache.org/" @@ -50,6 +50,14 @@ options="suid" builddir="$srcdir"/$_pkgreal-$pkgver # secfixes: +# 2.4.53-r0: +# - CVE-2022-22719 +# - CVE-2022-22720 +# - CVE-2022-22721 +# - CVE-2022-23943 +# 2.4.52-r0: +# - CVE-2021-44224 +# - CVE-2021-44790 # 2.4.51-r0: # - CVE-2021-42013 # 2.4.50-r0: @@ -368,7 +376,7 @@ _lua() { } sha512sums=" -9fb07c4b176f5c0485a143e2b1bb1085345ca9120b959974f68c37a8911a57894d2cb488b1b42fdf3102860b99e890204f5e9fa7ae3828b481119c563812cc66 httpd-2.4.51.tar.bz2 +07ef59594251a30a864cc9cc9a58ab788c2d006cef85b728f29533243927c63cb063e0867f2a306f37324c3adb9cf7dcb2402f3516b05c2c6f32469d475dd756 httpd-2.4.53.tar.bz2 8e62b101f90c67babe864bcb74f711656180b011df3fd4b541dc766b980b72aa409e86debf3559a55be359471c1cad81b8779ef3a55add8d368229fc7e9544fc apache2.confd 18e8859c7d99c4483792a5fd20127873aad8fa396cafbdb6f2c4253451ffe7a1093a3859ce719375e0769739c93704c88897bd087c63e1ef585e26dcc1f5dd9b apache2.logrotate 81a2d2a297d8049ba1b021b879ec863767149e056d9bdb2ac8acf63572b254935ec96c2e1580eba86639ea56433eec5c41341e4f1501f9072745dccdb3602701 apache2.initd diff --git a/main/apk-tools/0001-io-Handle-really-long-lines.patch b/main/apk-tools/0001-io-Handle-really-long-lines.patch new file mode 100644 index 00000000000..0ae4c7c26ce --- /dev/null +++ b/main/apk-tools/0001-io-Handle-really-long-lines.patch @@ -0,0 +1,38 @@ +From 9d71b61c5ca8222fba170fd5f7c5be18e0cde322 Mon Sep 17 00:00:00 2001 +From: Olliver Schinagl <oliver@schinagl.nl> +Date: Tue, 19 Jan 2021 20:32:07 +0100 +Subject: [PATCH] io: Handle really long lines + +While commit 18b0b45 (io: Handle long lines, Thu Jan 7 17:25:23 2021 ++0100) did attempt to address this issue, the buffer really is still to +small when dealing with big-big dependency lists. + +Lets make it sufficiently large for now, until the new APKINDEX format +can support multi-line dependencies, making this not needed any more. + +[TT: Originally the buffer size was conservative to run on resource +constrained embedded platforms. But since the available memory on those +has also increased much, the adjustment to 128kB makes sense also to +increase performance a little bit. Backported to 2.10-stable.] + +Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> +--- + src/io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/io.c b/src/io.c +index 47f34bf..414e4e2 100644 +--- a/src/io.c ++++ b/src/io.c +@@ -213,7 +213,7 @@ struct apk_istream_bstream { + struct apk_bstream bs; + struct apk_istream *is; + apk_blob_t left; +- char buffer[8*1024]; ++ char buffer[128*1024]; + }; + + static void is_bs_get_meta(struct apk_bstream *bs, struct apk_file_meta *meta) +-- +2.35.1 + diff --git a/main/apk-tools/APKBUILD b/main/apk-tools/APKBUILD index 38a43ff33fd..f94a07c215f 100644 --- a/main/apk-tools/APKBUILD +++ b/main/apk-tools/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=apk-tools pkgver=2.10.8 -pkgrel=0 +pkgrel=1 pkgdesc="Alpine Package Keeper - package manager for alpine" arch="all" url="https://gitlab.alpinelinux.org/alpine/apk-tools" @@ -14,7 +14,9 @@ if [ "$CBUILD" = "$CHOST" ]; then subpackages="$subpackages lua5.3-apk:luaapk" makedepends="$makedepends lua5.3-dev" fi -source="https://gitlab.alpinelinux.org/alpine/$pkgname/-/archive/v$pkgver/$pkgname-v$pkgver.tar.gz" +source="https://gitlab.alpinelinux.org/alpine/$pkgname/-/archive/v$pkgver/$pkgname-v$pkgver.tar.gz + 0001-io-Handle-really-long-lines.patch + " builddir="$srcdir/$pkgname-v$pkgver" # secfixes: @@ -85,4 +87,5 @@ luaapk() { sha512sums=" 865772688b93343361d82847e3fc0846a52062304c2370e8da5c5a86a23ce37edf44b213174c85b27f1c392b0ac4851e0b8b44e90fc371412458e0b9321a82e1 apk-tools-v2.10.8.tar.gz +03165e0efe3da78d67f1539a0e97e566d4c4366a4bbae38c2b6caa6a98c081e109e10aae1be57e4bce47a7147501ceccf43990a3fc6aa6be58a95b407ef2b13b 0001-io-Handle-really-long-lines.patch " diff --git a/main/bind/APKBUILD b/main/bind/APKBUILD index b78bd522d1e..de9a1305e8c 100644 --- a/main/bind/APKBUILD +++ b/main/bind/APKBUILD @@ -5,7 +5,7 @@ # Contributor: ungleich <alpinelinux@ungleich.ch> # Maintainer: pkgname=bind -pkgver=9.16.20 +pkgver=9.16.27 _ver=${pkgver%_p*} _p=${pkgver#*_p} _major=${pkgver%%.*} @@ -57,10 +57,13 @@ source=" named.conf.recursive 127.zone localhost.zone - bind-9.16.20-map-format-fix.patch " # secfixes: +# 9.16.27-r0: +# - CVE-2022-0396 +# - CVE-2021-25219 +# - CVE-2021-25220 # 9.16.20-r0: # - CVE-2021-25218 # 9.16.15-r0: @@ -273,7 +276,7 @@ _gpgfingerprints=" " sha512sums=" -bd4ffcc2589ca8f1ac228576ec11e86f317d5a78d7964a0a7ae70b2fa38831d5bd65c2e8c35d8190502de7139f85d8b080b3b8ee968811a8df78e5761781525d bind-9.16.20.tar.xz +5c71f228db83aa8cc9e65466d6e5afca4a9f80c693358111a003fe09e1a14522175eb2b6a0f11e2a2cd4fdba01f2ae315de52e394a441b3861ca2a011e02af62 bind-9.16.27.tar.xz 2b32d1e7f62cd1e01bb4fdd92d15460bc14761b933d5acc463a91f5ecd4773d7477c757c5dd2738e8e433693592cf3f623ffc142241861c91848f01aa84640d6 bind.plugindir.patch 7167dccdb2833643dfdb92994373d2cc087e52ba23b51bd68bd322ff9aca6744f01fa9d8a4b9cd8c4ce471755a85c03ec956ec0d8a1d4fae02124ddbed6841f6 bind.so_bsdcompat.patch 53db80f7ee4902f42fb1d0bc959242bcb6f20d95256bda99ce2c206af8b4703c7f72bb26d026c633f70451b84a37c3946b210951e34dd5d6620b181cd0183de4 named.initd @@ -282,5 +285,4 @@ d2f61d02d7829af51faf14fbe2bafe8bc90087e6b6697c6275a269ebbddcaa14a234fff5c41da793 3aba9763cfaf0880a89fd01202f41406b465547296ce91373eb999ea7719040bc1ac4e47b0de025a8060f693d3d88774a20d09a43fa7ac6aa43989b58b5ee8fe named.conf.recursive eed9886717539399518e011ae5eae6335aed4fae019e1def088c5be26bdc896c99c07adf84ee61babafa31d31ff3b028263d1c88d2eee17ecf4c95a9d77d524c 127.zone 340e86472a2c2746fe585c0aa5f079d3a9b46e828c1f53d48026533a169b7f77ded7d0a13d291d6962607bb9481456e6fa69df1834603e7555332615fb998f0b localhost.zone -d9224712ee2c6f6d0ff483ed253497548935fe35f45e5bdf26c9bd25c6234adde00727df7eb49fbfbfb34aad9d9fa0f112e900804794ad90a5cd8a64e9db61c6 bind-9.16.20-map-format-fix.patch " diff --git a/main/bind/bind-9.16.20-map-format-fix.patch b/main/bind/bind-9.16.20-map-format-fix.patch deleted file mode 100644 index f6e3c9b3782..00000000000 --- a/main/bind/bind-9.16.20-map-format-fix.patch +++ /dev/null @@ -1,8 +0,0 @@ ---- a/lib/dns/mapapi -+++ b/lib/dns/mapapi -@@ -13,4 +13,4 @@ - # Whenever releasing a new major release of BIND9, set this value - # back to 1.0 when releasing the first alpha. Map files are *never* - # compatible across major releases. --MAPAPI=2.0 -+MAPAPI=3.0 diff --git a/main/binutils/APKBUILD b/main/binutils/APKBUILD index 76817f0e6ac..79d8f73d8ac 100644 --- a/main/binutils/APKBUILD +++ b/main/binutils/APKBUILD @@ -16,6 +16,7 @@ source="https://ftp.gnu.org/gnu/binutils/binutils-$pkgver.tar.xz ld-bfd-mips.patch CVE-2021-3487.patch " +builddir="$srcdir/$pkgname-$pkgver" if [ "$CHOST" != "$CTARGET" ]; then pkgname="$pkgname-$CTARGET_ARCH" diff --git a/main/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch b/main/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch new file mode 100644 index 00000000000..1d1716e3b0c --- /dev/null +++ b/main/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch @@ -0,0 +1,40 @@ +From 0c8da1bead8ffaf270b4b723ead2c517371405d7 Mon Sep 17 00:00:00 2001 +From: Ariadne Conill <ariadne@dereferenced.org> +Date: Sun, 3 Apr 2022 12:14:33 +0000 +Subject: [PATCH 1/2] libbb: sockaddr2str: ensure only printable characters are + returned for the hostname part + +CVE: Pending +Upstream-Status: Pending +Signed-off-by: Ariadne Conill <ariadne@dereferenced.org> +--- + libbb/xconnect.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/libbb/xconnect.c b/libbb/xconnect.c +index 0e0b247b8..02c061e67 100644 +--- a/libbb/xconnect.c ++++ b/libbb/xconnect.c +@@ -497,8 +497,9 @@ static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags) + ); + if (rc) + return NULL; ++ /* ensure host contains only printable characters */ + if (flags & IGNORE_PORT) +- return xstrdup(host); ++ return xstrdup(printable_string(host)); + #if ENABLE_FEATURE_IPV6 + if (sa->sa_family == AF_INET6) { + if (strchr(host, ':')) /* heh, it's not a resolved hostname */ +@@ -509,7 +510,7 @@ static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags) + #endif + /* For now we don't support anything else, so it has to be INET */ + /*if (sa->sa_family == AF_INET)*/ +- return xasprintf("%s:%s", host, serv); ++ return xasprintf("%s:%s", printable_string(host), serv); + /*return xstrdup(host);*/ + } + +-- +2.35.1 + diff --git a/main/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch b/main/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch new file mode 100644 index 00000000000..4be540d0262 --- /dev/null +++ b/main/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch @@ -0,0 +1,59 @@ +From 812b407e545b70b16cf32aade135b5c32eaf674f Mon Sep 17 00:00:00 2001 +From: Ariadne Conill <ariadne@dereferenced.org> +Date: Sun, 3 Apr 2022 12:16:45 +0000 +Subject: [PATCH 2/2] nslookup: sanitize all printed strings with + printable_string + +Otherwise, terminal sequences can be injected, which enables various terminal injection +attacks from DNS results. + +CVE: Pending +Upstream-Status: Pending +Signed-off-by: Ariadne Conill <ariadne@dereferenced.org> +--- + networking/nslookup.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/networking/nslookup.c b/networking/nslookup.c +index 6da97baf4..4bdcde1b8 100644 +--- a/networking/nslookup.c ++++ b/networking/nslookup.c +@@ -407,7 +407,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) + //printf("Unable to uncompress domain: %s\n", strerror(errno)); + return -1; + } +- printf(format, ns_rr_name(rr), dname); ++ printf(format, ns_rr_name(rr), printable_string(dname)); + break; + + case ns_t_mx: +@@ -422,7 +422,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) + //printf("Cannot uncompress MX domain: %s\n", strerror(errno)); + return -1; + } +- printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, dname); ++ printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, printable_string(dname)); + break; + + case ns_t_txt: +@@ -434,7 +434,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) + if (n > 0) { + memset(dname, 0, sizeof(dname)); + memcpy(dname, ns_rr_rdata(rr) + 1, n); +- printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), dname); ++ printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), printable_string(dname)); + } + break; + +@@ -483,7 +483,7 @@ static NOINLINE int parse_reply(const unsigned char *msg, size_t len) + return -1; + } + +- printf("\tmail addr = %s\n", dname); ++ printf("\tmail addr = %s\n", printable_string(dname)); + cp += n; + + printf("\tserial = %lu\n", ns_get32(cp)); +-- +2.35.1 + diff --git a/main/busybox/APKBUILD b/main/busybox/APKBUILD index b053fb148de..d3d2844c272 100644 --- a/main/busybox/APKBUILD +++ b/main/busybox/APKBUILD @@ -3,12 +3,13 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=busybox pkgver=1.31.1 -pkgrel=20 +pkgrel=22 pkgdesc="Size optimized toolbox of many common UNIX utilities" url="https://busybox.net/" arch="all" license="GPL-2.0-only" -makedepends_host="linux-headers openssl-dev libtls-standalone-dev perl" +makedepends_build="perl" +makedepends_host="linux-headers openssl-dev libtls-standalone-dev" makedepends="$makedepends_build $makedepends_host" checkdepends="zip" provides="/bin/sh" @@ -37,7 +38,13 @@ source="https://busybox.net/downloads/busybox-$pkgver.tar.bz2 busybox-bc.patch nslookup.patch - traceroute-opt-x.patch::https://git.busybox.net/busybox/patch/?id=89358a7131d3e75c74af834bb117b4fad7914983 + traceroute-opt-x.patch + + CVE-2021-42374.patch + awk-fixes.patch + + 0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch + 0002-nslookup-sanitize-all-printed-strings-with-printable.patch acpid.logrotate busyboxconfig @@ -49,6 +56,20 @@ source="https://busybox.net/downloads/busybox-$pkgver.tar.bz2 " # secfixes: +# 1.31.1-r22: +# - ALPINE-13661 +# - CVE-2022-28391 +# 1.31.1-r21: +# - CVE-2021-42374 +# - CVE-2021-42378 +# - CVE-2021-42379 +# - CVE-2021-42380 +# - CVE-2021-42381 +# - CVE-2021-42382 +# - CVE-2021-42383 +# - CVE-2021-42384 +# - CVE-2021-42385 +# - CVE-2021-42386 # 1.31.1-r20: # - CVE-2021-28831 # 1.30.1-r2: @@ -61,6 +82,11 @@ source="https://busybox.net/downloads/busybox-$pkgver.tar.bz2 # - CVE-2017-16544 # - CVE-2017-15873 # - CVE-2017-15874 +# 0: +# - CVE-2021-42373 +# - CVE-2021-42375 +# - CVE-2021-42376 +# - CVE-2021-42377 _staticdir="$srcdir"/build-static @@ -216,9 +242,8 @@ ssl_client() { install -m755 "$_dyndir"/ssl_client \ "$subpkgdir"/usr/bin/ssl_client } - - -sha512sums="0d1197c25d963d7f95ef21e08c06c0d6124ac7b59c99989e891f744ffee4878a3b1fe44a247241a9da39fa5de0ba87f1b6d862401b591f277e66e89c02764bbf busybox-1.31.1.tar.bz2 +sha512sums=" +0d1197c25d963d7f95ef21e08c06c0d6124ac7b59c99989e891f744ffee4878a3b1fe44a247241a9da39fa5de0ba87f1b6d862401b591f277e66e89c02764bbf busybox-1.31.1.tar.bz2 07e79138c80a12fd3c8770c4a1beaba986465b099816511d2de744b34f7457f22351d991f510cce8665effd651cca34a85f685ed52747313b3980ebf25988958 0001-ln-no-target-directory-implies-no-dereference.patch ead3403578c071c2216de17ab0543984c1f1509c12c062f03af49141547c3ea21356f3e8f0f0695550f05a41a1379dd73fc3cc18dcd78addbb411f247351e353 0001-nologin-Install-applet-to-sbin-instead-of-usr-sbin.patch a2787a3ecaf6746dadef62166e8ee6ecaa166147e5ad8b917c5838536057c875bab5f9cf40c3e05eba74d575484ac662929ac3799d58432d3a99ac46f364f302 0001-adduser-default-to-sbin-nologin-as-shell-for-system-.patch @@ -236,11 +261,16 @@ b0f956e98ed1b670dc27f835441407d32395d371599780cf87a5fb2eee43ad2f77c8c484d20f08b1 d8926f0e4ed7d2fe5af89ff2a944d781b45b109c9edf1ef2591e7bce2a8bbadd7c8ca814cb3c928ae09027d9603434fe70496f308d701f3d42260ebd1e9e9b29 0013-testsuite-fix-cpio-tests.patch 9bb4d16ca418b6fd3c0b6dc867c92920e66ddb0c98040373d1166608284d2755b8d6eed0022bfddfcc07f5df93974fb7ed79402511a9728eb6c95ce05c37cfeb busybox-bc.patch 00d7f186bac8f228ebda3c486282df34c0021b58948946f4b2c7efe0cccf5f34a0e0430318359f1008ed51455747ffb525010f2feef450faf05fbc511d99d1d6 nslookup.patch -c6dc917e67ab4c9aa0294f22707fd3cfc8cb37d703d8a0bce7f257ac9fb931dc4b815ab1d5e4f3ed3520b6ba046bdc1fbd0d1f8ed73b8d2d51f9238f03e03688 traceroute-opt-x.patch +90598077e3000efa92167d446211965737bd3ee8c9dc29b6a33ebbd7c2e2a52eaadd225a1695bc4375ae0ec90a533915926de5fa4364d880b6c99934d7b0f916 traceroute-opt-x.patch +0e241dc63d49103569852089c07149a2ff2599331f988ca20e8f6f606e560795b919ceffb6b3f4f1aba56b688b969c52bfdc2d1deb7c6ec08deaf707771b996a CVE-2021-42374.patch +e4fae8467f2f3c6c3274a5f7e4b9d9c3e9742fe478379ae0096b5b0dc93a52e5a295acd2d4d12f0cc4679b3df5b5490076de5196a70cc4e17d8dbc829c57d903 awk-fixes.patch +b52050678e79e4da856956906d07fcb620cbf35f2ef6b5a8ee3b8d244ea63b4b98eef505451184d5b4937740d91eef154ed748c30d329ac485be51b37626f251 0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch +017ed99fbf95debf6ab975ccf259590a79d86b999f4ae8ac39244e84881eff72abb99ac82209a02377b6b30bc552f3b673fe118752cbf349a42d3fb5a34e9cb1 0002-nslookup-sanitize-all-printed-strings-with-printable.patch aa93095e20de88730f526c6f463cef711b290b9582cdbd8c1ba2bd290019150cbeaa7007c2e15f0362d5b9315dd63f60511878f0ea05e893f4fdfb4a54af3fb1 acpid.logrotate 33ee716a324a622e03ae3303afb50c856d0706a5e78923e313040e98513aaa311ecfbc1e4acf784eba9e35cc6f91fa72862bbbfe3b1f7c2a76f94b6f55cb13c0 busyboxconfig 5f9739b9d0c1ba5d77e3153c373593a1bcb813cf466f951b00a2a040262e5077fb13c1a7aa17d67d1533a473bfcacc1a22833b7f491b4dde9dcb5638ad585f9a busyboxconfig-extras 0becc2186d6c32fb0c401cf7bc0e46268b38ce8892db33be1daf40273024c1c02d518283f44086a313a2ccef34230a1d945ec148cc173f26e6aa9d88a7426e54 bbsuid.c b993ce589685d5d1f806153d0b7f71657f2d37556654ec60884130a40f09acc4944a13e0a4d02914000bedd779e5a35da08c760fed5f7ca5b601243aff7ba2c9 dad.if-up 646ad9aefe3596d0170d92c8506ca1846e43b5b83cbef97ae565f15ffa7b14665a8c7061bc69c608c043f834c134c5d63f042509f8999031e89163508a868e46 ssl_client.c -c047594a1a3c685f679b98bb80015020ed51e7502c0b2f535f8483a8852b8d43b894b36f34ba680ef96a52c67f3d1af706edbfe43c4a2117c469bb2967215252 default.script" +c047594a1a3c685f679b98bb80015020ed51e7502c0b2f535f8483a8852b8d43b894b36f34ba680ef96a52c67f3d1af706edbfe43c4a2117c469bb2967215252 default.script +" diff --git a/main/busybox/CVE-2021-42374.patch b/main/busybox/CVE-2021-42374.patch new file mode 100644 index 00000000000..000ea4eb4f0 --- /dev/null +++ b/main/busybox/CVE-2021-42374.patch @@ -0,0 +1,45 @@ +From 0a79496ff649bd4b426b14a2a8810e84c3dccb34 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko <vda.linux@googlemail.com> +Date: Tue, 15 Jun 2021 15:07:57 +0200 +Subject: [PATCH] unlzma: fix a case where we could read before beginning of + buffer + +CVE-2021-42374 + +Testcase: + + 21 01 01 00 00 00 00 00 e7 01 01 01 ef 00 df b6 + 00 17 02 10 11 0f ff 00 16 00 00 + +Unfortunately, the bug is not reliably causing a segfault, +the behavior depends on what's in memory before the buffer. + +function old new delta +unpack_lzma_stream 2762 2768 +6 + +Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> +(cherry picked from commit 04f052c56ded5ab6a904e3a264a73dc0412b2e78) +--- + archival/libarchive/decompress_unlzma.c | 5 ++++- + testsuite/unlzma.tests | 17 +++++++++++++---- + testsuite/unlzma_issue_3.lzma | Bin 0 -> 27 bytes + 3 files changed, 17 insertions(+), 5 deletions(-) + create mode 100644 testsuite/unlzma_issue_3.lzma + +diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c +index 0744f231a..fb5aac8fe 100644 +--- a/archival/libarchive/decompress_unlzma.c ++++ b/archival/libarchive/decompress_unlzma.c +@@ -290,8 +290,11 @@ unpack_lzma_stream(transformer_state_t *xstate) + uint32_t pos; + + pos = buffer_pos - rep0; +- if ((int32_t)pos < 0) ++ if ((int32_t)pos < 0) { + pos += header.dict_size; ++ if ((int32_t)pos < 0) ++ goto bad; ++ } + match_byte = buffer[pos]; + do { + int bit; diff --git a/main/busybox/awk-fixes.patch b/main/busybox/awk-fixes.patch new file mode 100644 index 00000000000..f5127c0ebee --- /dev/null +++ b/main/busybox/awk-fixes.patch @@ -0,0 +1,3208 @@ +Diff from all patches 1.31_0..1_34_0. + +diff --git a/editors/awk.c b/editors/awk.c +index d25508e5d..bbdd64e09 100644 +--- a/editors/awk.c ++++ b/editors/awk.c +@@ -66,6 +66,8 @@ + #endif + #ifndef debug_printf_parse + # define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__)) ++#else ++# define debug_parse_print_tc(...) ((void)0) + #endif + + +@@ -91,7 +93,6 @@ enum { + }; + + #define MAXVARFMT 240 +-#define MINNVBLOCK 64 + + /* variable flags */ + #define VF_NUMBER 0x0001 /* 1 = primary type is number */ +@@ -101,7 +102,7 @@ enum { + #define VF_USER 0x0200 /* 1 = user input (may be numeric string) */ + #define VF_SPECIAL 0x0400 /* 1 = requires extra handling when changed */ + #define VF_WALK 0x0800 /* 1 = variable has alloc'd x.walker list */ +-#define VF_FSTR 0x1000 /* 1 = var::string points to fstring buffer */ ++#define VF_FSTR 0x1000 /* 1 = don't free() var::string (not malloced, or is owned by something else) */ + #define VF_CHILD 0x2000 /* 1 = function arg; x.parent points to source */ + #define VF_DIRTY 0x4000 /* 1 = variable was set explicitly */ + +@@ -118,8 +119,8 @@ typedef struct walker_list { + /* Variable */ + typedef struct var_s { + unsigned type; /* flags */ +- double number; + char *string; ++ double number; + union { + int aidx; /* func arg idx (for compilation stage) */ + struct xhash_s *array; /* array ptr */ +@@ -138,6 +139,7 @@ typedef struct chain_s { + /* Function */ + typedef struct func_s { + unsigned nargs; ++ smallint defined; + struct chain_s body; + } func; + +@@ -177,7 +179,7 @@ typedef struct node_s { + struct node_s *n; + var *v; + int aidx; +- char *new_progname; ++ const char *new_progname; + regex_t *re; + } l; + union { +@@ -190,90 +192,120 @@ typedef struct node_s { + } a; + } node; + +-/* Block of temporary variables */ +-typedef struct nvblock_s { +- int size; +- var *pos; +- struct nvblock_s *prev; +- struct nvblock_s *next; +- var nv[]; +-} nvblock; +- + typedef struct tsplitter_s { + node n; + regex_t re[2]; + } tsplitter; + + /* simple token classes */ +-/* Order and hex values are very important!!! See next_token() */ +-#define TC_SEQSTART (1 << 0) /* ( */ +-#define TC_SEQTERM (1 << 1) /* ) */ +-#define TC_REGEXP (1 << 2) /* /.../ */ +-#define TC_OUTRDR (1 << 3) /* | > >> */ +-#define TC_UOPPOST (1 << 4) /* unary postfix operator */ +-#define TC_UOPPRE1 (1 << 5) /* unary prefix operator */ +-#define TC_BINOPX (1 << 6) /* two-opnd operator */ +-#define TC_IN (1 << 7) +-#define TC_COMMA (1 << 8) +-#define TC_PIPE (1 << 9) /* input redirection pipe */ +-#define TC_UOPPRE2 (1 << 10) /* unary prefix operator */ +-#define TC_ARRTERM (1 << 11) /* ] */ +-#define TC_GRPSTART (1 << 12) /* { */ +-#define TC_GRPTERM (1 << 13) /* } */ +-#define TC_SEMICOL (1 << 14) +-#define TC_NEWLINE (1 << 15) +-#define TC_STATX (1 << 16) /* ctl statement (for, next...) */ +-#define TC_WHILE (1 << 17) +-#define TC_ELSE (1 << 18) +-#define TC_BUILTIN (1 << 19) ++/* order and hex values are very important!!! See next_token() */ ++#define TC_LPAREN (1 << 0) /* ( */ ++#define TC_RPAREN (1 << 1) /* ) */ ++#define TC_REGEXP (1 << 2) /* /.../ */ ++#define TC_OUTRDR (1 << 3) /* | > >> */ ++#define TC_UOPPOST (1 << 4) /* unary postfix operator ++ -- */ ++#define TC_UOPPRE1 (1 << 5) /* unary prefix operator ++ -- $ */ ++#define TC_BINOPX (1 << 6) /* two-opnd operator */ ++#define TC_IN (1 << 7) /* 'in' */ ++#define TC_COMMA (1 << 8) /* , */ ++#define TC_PIPE (1 << 9) /* input redirection pipe | */ ++#define TC_UOPPRE2 (1 << 10) /* unary prefix operator + - ! */ ++#define TC_ARRTERM (1 << 11) /* ] */ ++#define TC_LBRACE (1 << 12) /* { */ ++#define TC_RBRACE (1 << 13) /* } */ ++#define TC_SEMICOL (1 << 14) /* ; */ ++#define TC_NEWLINE (1 << 15) ++#define TC_STATX (1 << 16) /* ctl statement (for, next...) */ ++#define TC_WHILE (1 << 17) /* 'while' */ ++#define TC_ELSE (1 << 18) /* 'else' */ ++#define TC_BUILTIN (1 << 19) + /* This costs ~50 bytes of code. + * A separate class to support deprecated "length" form. If we don't need that + * (i.e. if we demand that only "length()" with () is valid), then TC_LENGTH + * can be merged with TC_BUILTIN: + */ +-#define TC_LENGTH (1 << 20) +-#define TC_GETLINE (1 << 21) +-#define TC_FUNCDECL (1 << 22) /* 'function' 'func' */ +-#define TC_BEGIN (1 << 23) +-#define TC_END (1 << 24) +-#define TC_EOF (1 << 25) +-#define TC_VARIABLE (1 << 26) +-#define TC_ARRAY (1 << 27) +-#define TC_FUNCTION (1 << 28) +-#define TC_STRING (1 << 29) +-#define TC_NUMBER (1 << 30) +- +-#define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2) +- +-/* combined token classes */ +-#define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) +-//#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) +-#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ +- | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ +- | TC_SEQSTART | TC_STRING | TC_NUMBER) +- +-#define TC_STATEMNT (TC_STATX | TC_WHILE) +-#define TC_OPTERM (TC_SEMICOL | TC_NEWLINE) ++#define TC_LENGTH (1 << 20) /* 'length' */ ++#define TC_GETLINE (1 << 21) /* 'getline' */ ++#define TC_FUNCDECL (1 << 22) /* 'function' 'func' */ ++#define TC_BEGIN (1 << 23) /* 'BEGIN' */ ++#define TC_END (1 << 24) /* 'END' */ ++#define TC_EOF (1 << 25) ++#define TC_VARIABLE (1 << 26) /* name */ ++#define TC_ARRAY (1 << 27) /* name[ */ ++#define TC_FUNCTION (1 << 28) /* name( */ ++#define TC_STRING (1 << 29) /* "..." */ ++#define TC_NUMBER (1 << 30) ++ ++#ifndef debug_parse_print_tc ++static void debug_parse_print_tc(uint32_t n) ++{ ++ if (n & TC_LPAREN ) debug_printf_parse(" LPAREN" ); ++ if (n & TC_RPAREN ) debug_printf_parse(" RPAREN" ); ++ if (n & TC_REGEXP ) debug_printf_parse(" REGEXP" ); ++ if (n & TC_OUTRDR ) debug_printf_parse(" OUTRDR" ); ++ if (n & TC_UOPPOST ) debug_printf_parse(" UOPPOST" ); ++ if (n & TC_UOPPRE1 ) debug_printf_parse(" UOPPRE1" ); ++ if (n & TC_BINOPX ) debug_printf_parse(" BINOPX" ); ++ if (n & TC_IN ) debug_printf_parse(" IN" ); ++ if (n & TC_COMMA ) debug_printf_parse(" COMMA" ); ++ if (n & TC_PIPE ) debug_printf_parse(" PIPE" ); ++ if (n & TC_UOPPRE2 ) debug_printf_parse(" UOPPRE2" ); ++ if (n & TC_ARRTERM ) debug_printf_parse(" ARRTERM" ); ++ if (n & TC_LBRACE ) debug_printf_parse(" LBRACE" ); ++ if (n & TC_RBRACE ) debug_printf_parse(" RBRACE" ); ++ if (n & TC_SEMICOL ) debug_printf_parse(" SEMICOL" ); ++ if (n & TC_NEWLINE ) debug_printf_parse(" NEWLINE" ); ++ if (n & TC_STATX ) debug_printf_parse(" STATX" ); ++ if (n & TC_WHILE ) debug_printf_parse(" WHILE" ); ++ if (n & TC_ELSE ) debug_printf_parse(" ELSE" ); ++ if (n & TC_BUILTIN ) debug_printf_parse(" BUILTIN" ); ++ if (n & TC_LENGTH ) debug_printf_parse(" LENGTH" ); ++ if (n & TC_GETLINE ) debug_printf_parse(" GETLINE" ); ++ if (n & TC_FUNCDECL) debug_printf_parse(" FUNCDECL"); ++ if (n & TC_BEGIN ) debug_printf_parse(" BEGIN" ); ++ if (n & TC_END ) debug_printf_parse(" END" ); ++ if (n & TC_EOF ) debug_printf_parse(" EOF" ); ++ if (n & TC_VARIABLE) debug_printf_parse(" VARIABLE"); ++ if (n & TC_ARRAY ) debug_printf_parse(" ARRAY" ); ++ if (n & TC_FUNCTION) debug_printf_parse(" FUNCTION"); ++ if (n & TC_STRING ) debug_printf_parse(" STRING" ); ++ if (n & TC_NUMBER ) debug_printf_parse(" NUMBER" ); ++} ++#endif ++ ++/* combined token classes ("token [class] sets") */ ++#define TS_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2) ++ ++#define TS_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) ++//#define TS_UNARYOP (TS_UOPPRE | TC_UOPPOST) ++#define TS_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ ++ | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ ++ | TC_LPAREN | TC_STRING | TC_NUMBER) ++ ++#define TS_LVALUE (TC_VARIABLE | TC_ARRAY) ++#define TS_STATEMNT (TC_STATX | TC_WHILE) + + /* word tokens, cannot mean something else if not expected */ +-#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE \ +- | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ +- | TC_FUNCDECL | TC_BEGIN | TC_END) ++#define TS_WORD (TC_IN | TS_STATEMNT | TC_ELSE \ ++ | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ ++ | TC_FUNCDECL | TC_BEGIN | TC_END) + + /* discard newlines after these */ +-#define TC_NOTERM (TC_COMMA | TC_GRPSTART | TC_GRPTERM \ +- | TC_BINOP | TC_OPTERM) ++#define TS_NOTERM (TS_BINOP | TC_COMMA | TC_LBRACE | TC_RBRACE \ ++ | TC_SEMICOL | TC_NEWLINE) + + /* what can expression begin with */ +-#define TC_OPSEQ (TC_OPERAND | TC_UOPPRE | TC_REGEXP) ++#define TS_OPSEQ (TS_OPERAND | TS_UOPPRE | TC_REGEXP) + /* what can group begin with */ +-#define TC_GRPSEQ (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART) ++#define TS_GRPSEQ (TS_OPSEQ | TS_STATEMNT \ ++ | TC_SEMICOL | TC_NEWLINE | TC_LBRACE) + +-/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */ ++/* if previous token class is CONCAT_L and next is CONCAT_R, concatenation */ + /* operator is inserted between them */ +-#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \ +- | TC_STRING | TC_NUMBER | TC_UOPPOST) +-#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) ++#define TS_CONCAT_L (TC_VARIABLE | TC_ARRTERM | TC_RPAREN \ ++ | TC_STRING | TC_NUMBER | TC_UOPPOST \ ++ | TC_LENGTH) ++#define TS_CONCAT_R (TS_OPERAND | TS_UOPPRE) + + #define OF_RES1 0x010000 + #define OF_RES2 0x020000 +@@ -283,13 +315,12 @@ typedef struct tsplitter_s { + #define OF_CHECKED 0x200000 + #define OF_REQUIRED 0x400000 + +- + /* combined operator flags */ + #define xx 0 + #define xV OF_RES2 + #define xS (OF_RES2 | OF_STR2) + #define Vx OF_RES1 +-#define Rx (OF_RES1 | OF_NUM1 | OF_REQUIRED) ++#define Rx OF_REQUIRED + #define VV (OF_RES1 | OF_RES2) + #define Nx (OF_RES1 | OF_NUM1) + #define NV (OF_RES1 | OF_NUM1 | OF_RES2) +@@ -301,8 +332,7 @@ typedef struct tsplitter_s { + #define OPNMASK 0x007F + + /* operator priority is a highest byte (even: r->l, odd: l->r grouping) +- * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1, +- * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string ++ * (for builtins it has different meaning) + */ + #undef P + #undef PRIMASK +@@ -312,10 +342,8 @@ typedef struct tsplitter_s { + #define PRIMASK2 0x7E000000 + + /* Operation classes */ +- + #define SHIFT_TIL_THIS 0x0600 + #define RECUR_FROM_THIS 0x1000 +- + enum { + OC_DELETE = 0x0100, OC_EXEC = 0x0200, OC_NEWSOURCE = 0x0300, + OC_PRINT = 0x0400, OC_PRINTF = 0x0500, OC_WALKINIT = 0x0600, +@@ -357,8 +385,8 @@ enum { + #define NTCC '\377' + + static const char tokenlist[] ALIGN1 = +- "\1(" NTC /* TC_SEQSTART */ +- "\1)" NTC /* TC_SEQTERM */ ++ "\1(" NTC /* TC_LPAREN */ ++ "\1)" NTC /* TC_RPAREN */ + "\1/" NTC /* TC_REGEXP */ + "\2>>" "\1>" "\1|" NTC /* TC_OUTRDR */ + "\2++" "\2--" NTC /* TC_UOPPOST */ +@@ -375,8 +403,8 @@ static const char tokenlist[] ALIGN1 = + "\1|" NTC /* TC_PIPE */ + "\1+" "\1-" "\1!" NTC /* TC_UOPPRE2 */ + "\1]" NTC /* TC_ARRTERM */ +- "\1{" NTC /* TC_GRPSTART */ +- "\1}" NTC /* TC_GRPTERM */ ++ "\1{" NTC /* TC_LBRACE */ ++ "\1}" NTC /* TC_RBRACE */ + "\1;" NTC /* TC_SEMICOL */ + "\1\n" NTC /* TC_NEWLINE */ + "\2if" "\2do" "\3for" "\5break" /* TC_STATX */ +@@ -390,7 +418,7 @@ static const char tokenlist[] ALIGN1 = + "\5close" "\6system" "\6fflush" "\5atan2" + "\3cos" "\3exp" "\3int" "\3log" + "\4rand" "\3sin" "\4sqrt" "\5srand" +- "\6gensub" "\4gsub" "\5index" /* "\6length" was here */ ++ "\6gensub" "\4gsub" "\5index" /* "\6length" was here */ + "\5match" "\5split" "\7sprintf" "\3sub" + "\6substr" "\7systime" "\10strftime" "\6mktime" + "\7tolower" "\7toupper" NTC +@@ -402,25 +430,32 @@ static const char tokenlist[] ALIGN1 = + /* compiler adds trailing "\0" */ + ; + +-#define OC_B OC_BUILTIN +- +-static const uint32_t tokeninfo[] = { ++static const uint32_t tokeninfo[] ALIGN4 = { + 0, + 0, +- OC_REGEXP, ++#define TI_REGEXP OC_REGEXP ++ TI_REGEXP, + xS|'a', xS|'w', xS|'|', + OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m', +- OC_UNARY|xV|P(9)|'P', OC_UNARY|xV|P(9)|'M', OC_FIELD|xV|P(5), ++#define TI_PREINC (OC_UNARY|xV|P(9)|'P') ++#define TI_PREDEC (OC_UNARY|xV|P(9)|'M') ++ TI_PREINC, TI_PREDEC, OC_FIELD|xV|P(5), + OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74), OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-', + OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&', + OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-', OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&', + OC_BINARY|NV|P(25)|'/', OC_BINARY|NV|P(25)|'%', OC_BINARY|NV|P(15)|'&', OC_BINARY|NV|P(25)|'*', + OC_COMPARE|VV|P(39)|4, OC_COMPARE|VV|P(39)|3, OC_COMPARE|VV|P(39)|0, OC_COMPARE|VV|P(39)|1, +- OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!', OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55), +- OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?', OC_COLON|xx|P(67)|':', +- OC_IN|SV|P(49), /* TC_IN */ +- OC_COMMA|SS|P(80), +- OC_PGETLINE|SV|P(37), ++#define TI_LESS (OC_COMPARE|VV|P(39)|2) ++ TI_LESS, OC_MATCH|Sx|P(45)|'!', OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55), ++#define TI_TERNARY (OC_TERNARY|Vx|P(64)|'?') ++#define TI_COLON (OC_COLON|xx|P(67)|':') ++ OC_LOR|Vx|P(59), TI_TERNARY, TI_COLON, ++#define TI_IN (OC_IN|SV|P(49)) ++ TI_IN, ++#define TI_COMMA (OC_COMMA|SS|P(80)) ++ TI_COMMA, ++#define TI_PGETLINE (OC_PGETLINE|SV|P(37)) ++ TI_PGETLINE, + OC_UNARY|xV|P(19)|'+', OC_UNARY|xV|P(19)|'-', OC_UNARY|xV|P(19)|'!', + 0, /* ] */ + 0, +@@ -433,20 +468,45 @@ static const uint32_t tokeninfo[] = { + OC_RETURN|Vx, OC_EXIT|Nx, + ST_WHILE, + 0, /* else */ +- OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83), +- OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83), +- OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83), +- OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg, +- OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr, +- OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), /* OC_FBLTIN|Sx|F_le, was here */ +- OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6), +- OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), +- OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), +- OC_FBLTIN|Sx|F_le, /* TC_LENGTH */ +- OC_GETLINE|SV|P(0), +- 0, 0, +- 0, +- 0 /* TC_END */ ++// OC_B's are builtins with enforced minimum number of arguments (two upper bits). ++// Highest byte bit pattern: nn s3s2s1 v3v2v1 ++// nn - min. number of args, sN - resolve Nth arg to string, vN - resolve to var ++// OC_F's are builtins with zero or one argument. ++// |Rx| enforces that arg is present for: system, close, cos, sin, exp, int, log, sqrt ++// Check for no args is present in builtins' code (not in this table): rand, systime ++// Have one _optional_ arg: fflush, srand, length ++#define OC_B OC_BUILTIN ++#define OC_F OC_FBLTIN ++#define A1 P(0x40) /*one arg*/ ++#define A2 P(0x80) /*two args*/ ++#define A3 P(0xc0) /*three args*/ ++#define __v P(1) ++#define _vv P(3) ++#define __s__v P(9) ++#define __s_vv P(0x0b) ++#define __svvv P(0x0f) ++#define _ss_vv P(0x1b) ++#define _s_vv_ P(0x16) ++#define ss_vv_ P(0x36) ++ OC_B|B_an|_vv|A2, OC_B|B_co|__v|A1, OC_B|B_ls|_vv|A2, OC_B|B_or|_vv|A2, // and compl lshift or ++ OC_B|B_rs|_vv|A2, OC_B|B_xo|_vv|A2, // rshift xor ++ OC_F|F_cl|Sx|Rx, OC_F|F_sy|Sx|Rx, OC_F|F_ff|Sx, OC_B|B_a2|_vv|A2, // close system fflush atan2 ++ OC_F|F_co|Nx|Rx, OC_F|F_ex|Nx|Rx, OC_F|F_in|Nx|Rx, OC_F|F_lg|Nx|Rx, // cos exp int log ++ OC_F|F_rn, OC_F|F_si|Nx|Rx, OC_F|F_sq|Nx|Rx, OC_F|F_sr|Nx, // rand sin sqrt srand ++ OC_B|B_ge|_s_vv_|A3,OC_B|B_gs|ss_vv_|A2,OC_B|B_ix|_ss_vv|A2, // gensub gsub index /*length was here*/ ++ OC_B|B_ma|__s__v|A2,OC_B|B_sp|__s_vv|A2,OC_SPRINTF, OC_B|B_su|ss_vv_|A2,// match split sprintf sub ++ OC_B|B_ss|__svvv|A2,OC_F|F_ti, OC_B|B_ti|__s_vv, OC_B|B_mt|__s_vv, // substr systime strftime mktime ++ OC_B|B_lo|__s__v|A1,OC_B|B_up|__s__v|A1, // tolower toupper ++ OC_F|F_le|Sx, // length ++ OC_GETLINE|SV, // getline ++ 0, 0, // func function ++ 0, // BEGIN ++ 0 // END ++#undef A1 ++#undef A2 ++#undef A3 ++#undef OC_B ++#undef OC_F + }; + + /* internal variable names and their initial values */ +@@ -487,21 +547,29 @@ struct globals { + chain *seq; + node *break_ptr, *continue_ptr; + rstream *iF; +- xhash *vhash, *ahash, *fdhash, *fnhash; ++ xhash *ahash; /* argument names, used only while parsing function bodies */ ++ xhash *fnhash; /* function names, used only in parsing stage */ ++ xhash *vhash; /* variables and arrays */ ++ //xhash *fdhash; /* file objects, used only in execution stage */ ++ //we are reusing ahash as fdhash, via define (see later) + const char *g_progname; + int g_lineno; + int nfields; + int maxfields; /* used in fsrealloc() only */ + var *Fields; +- nvblock *g_cb; + char *g_pos; +- char *g_buf; ++ char g_saved_ch; + smallint icase; + smallint exiting; + smallint nextrec; + smallint nextfile; + smallint is_f0_split; + smallint t_rollback; ++ ++ /* former statics from various functions */ ++ smallint next_token__concat_inserted; ++ uint32_t next_token__save_tclass; ++ uint32_t next_token__save_info; + }; + struct globals2 { + uint32_t t_info; /* often used */ +@@ -514,32 +582,35 @@ struct globals2 { + /* former statics from various functions */ + char *split_f0__fstrings; + +- uint32_t next_token__save_tclass; +- uint32_t next_token__save_info; +- uint32_t next_token__ltclass; +- smallint next_token__concat_inserted; +- +- smallint next_input_file__files_happen; + rstream next_input_file__rsm; ++ smallint next_input_file__files_happen; ++ ++ smalluint exitcode; + +- var *evaluate__fnargs; + unsigned evaluate__seed; ++ var *evaluate__fnargs; + regex_t evaluate__sreg; + +- var ptest__v; ++ var ptest__tmpvar; ++ var awk_printf__tmpvar; ++ var as_regex__tmpvar; ++ var exit__tmpvar; ++ var main__tmpvar; + + tsplitter exec_builtin__tspl; + + /* biggest and least used members go last */ + tsplitter fsplitter, rsplitter; ++ ++ char g_buf[MAXVARFMT + 1]; + }; + #define G1 (ptr_to_globals[-1]) + #define G (*(struct globals2 *)ptr_to_globals) + /* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */ +-/*char G1size[sizeof(G1)]; - 0x74 */ +-/*char Gsize[sizeof(G)]; - 0x1c4 */ ++//char G1size[sizeof(G1)]; // 0x70 ++//char Gsize[sizeof(G)]; // 0x2f8 + /* Trying to keep most of members accessible with short offsets: */ +-/*char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */ ++//char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; // 0x7c + #define t_double (G1.t_double ) + #define beginseq (G1.beginseq ) + #define mainseq (G1.mainseq ) +@@ -548,18 +619,20 @@ struct globals2 { + #define break_ptr (G1.break_ptr ) + #define continue_ptr (G1.continue_ptr) + #define iF (G1.iF ) +-#define vhash (G1.vhash ) + #define ahash (G1.ahash ) +-#define fdhash (G1.fdhash ) + #define fnhash (G1.fnhash ) ++#define vhash (G1.vhash ) ++#define fdhash ahash ++//^^^^^^^^^^^^^^^^^^ ahash is cleared after every function parsing, ++// and ends up empty after parsing phase. Thus, we can simply reuse it ++// for fdhash in execution stage. + #define g_progname (G1.g_progname ) + #define g_lineno (G1.g_lineno ) + #define nfields (G1.nfields ) + #define maxfields (G1.maxfields ) + #define Fields (G1.Fields ) +-#define g_cb (G1.g_cb ) + #define g_pos (G1.g_pos ) +-#define g_buf (G1.g_buf ) ++#define g_saved_ch (G1.g_saved_ch ) + #define icase (G1.icase ) + #define exiting (G1.exiting ) + #define nextrec (G1.nextrec ) +@@ -573,25 +646,13 @@ struct globals2 { + #define intvar (G.intvar ) + #define fsplitter (G.fsplitter ) + #define rsplitter (G.rsplitter ) ++#define g_buf (G.g_buf ) + #define INIT_G() do { \ + SET_PTR_TO_GLOBALS((char*)xzalloc(sizeof(G1)+sizeof(G)) + sizeof(G1)); \ +- G.next_token__ltclass = TC_OPTERM; \ ++ t_tclass = TC_NEWLINE; \ + G.evaluate__seed = 1; \ + } while (0) + +- +-/* function prototypes */ +-static void handle_special(var *); +-static node *parse_expr(uint32_t); +-static void chain_group(void); +-static var *evaluate(node *, var *); +-static rstream *next_input_file(void); +-static int fmt_num(char *, int, const char *, double, int); +-static int awk_exit(int) NORETURN; +- +-/* ---- error handling ---- */ +- +-static const char EMSG_INTERNAL_ERROR[] ALIGN1 = "Internal error"; + static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string"; + static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; + static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; +@@ -603,10 +664,7 @@ static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; + static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in"; + static const char EMSG_NEGATIVE_FIELD[] ALIGN1 = "Access to negative field"; + +-static void zero_out_var(var *vp) +-{ +- memset(vp, 0, sizeof(*vp)); +-} ++static int awk_exit(void) NORETURN; + + static void syntax_error(const char *message) NORETURN; + static void syntax_error(const char *message) +@@ -637,12 +695,40 @@ static xhash *hash_init(void) + return newhash; + } + ++static void hash_clear(xhash *hash) ++{ ++ unsigned i; ++ hash_item *hi, *thi; ++ ++ for (i = 0; i < hash->csize; i++) { ++ hi = hash->items[i]; ++ while (hi) { ++ thi = hi; ++ hi = hi->next; ++//FIXME: this assumes that it's a hash of *variables*: ++ free(thi->data.v.string); ++ free(thi); ++ } ++ hash->items[i] = NULL; ++ } ++ hash->glen = hash->nel = 0; ++} ++ ++#if 0 //UNUSED ++static void hash_free(xhash *hash) ++{ ++ hash_clear(hash); ++ free(hash->items); ++ free(hash); ++} ++#endif ++ + /* find item in hash, return ptr to data, NULL if not found */ +-static void *hash_search(xhash *hash, const char *name) ++static NOINLINE void *hash_search3(xhash *hash, const char *name, unsigned idx) + { + hash_item *hi; + +- hi = hash->items[hashidx(name) % hash->csize]; ++ hi = hash->items[idx % hash->csize]; + while (hi) { + if (strcmp(hi->name, name) == 0) + return &hi->data; +@@ -651,6 +737,11 @@ static void *hash_search(xhash *hash, const char *name) + return NULL; + } + ++static void *hash_search(xhash *hash, const char *name) ++{ ++ return hash_search3(hash, name, hashidx(name)); ++} ++ + /* grow hash if it becomes too big */ + static void hash_rebuild(xhash *hash) + { +@@ -686,16 +777,17 @@ static void *hash_find(xhash *hash, const char *name) + unsigned idx; + int l; + +- hi = hash_search(hash, name); ++ idx = hashidx(name); ++ hi = hash_search3(hash, name, idx); + if (!hi) { +- if (++hash->nel / hash->csize > 10) ++ if (++hash->nel > hash->csize * 8) + hash_rebuild(hash); + + l = strlen(name) + 1; + hi = xzalloc(sizeof(*hi) + l); + strcpy(hi->name, name); + +- idx = hashidx(name) % hash->csize; ++ idx = idx % hash->csize; + hi->next = hash->items[idx]; + hash->items[idx] = hi; + hash->glen += l; +@@ -730,7 +822,7 @@ static void hash_remove(xhash *hash, const char *name) + + static char *skip_spaces(char *p) + { +- while (1) { ++ for (;;) { + if (*p == '\\' && p[1] == '\n') { + p++; + t_lineno++; +@@ -746,8 +838,10 @@ static char *skip_spaces(char *p) + static char *nextword(char **s) + { + char *p = *s; +- while (*(*s)++ != '\0') ++ char *q = p; ++ while (*q++ != '\0') + continue; ++ *s = q; + return p; + } + +@@ -810,10 +904,27 @@ static double my_strtod(char **pp) + + /* -------- working with variables (set/get/copy/etc) -------- */ + +-static xhash *iamarray(var *v) ++static void fmt_num(const char *format, double n) + { +- var *a = v; ++ if (n == (long long)n) { ++ snprintf(g_buf, MAXVARFMT, "%lld", (long long)n); ++ } else { ++ const char *s = format; ++ char c; ++ ++ do { c = *s; } while (c && *++s); ++ if (strchr("diouxX", c)) { ++ snprintf(g_buf, MAXVARFMT, format, (int)n); ++ } else if (strchr("eEfFgGaA", c)) { ++ snprintf(g_buf, MAXVARFMT, format, n); ++ } else { ++ syntax_error(EMSG_INV_FMT); ++ } ++ } ++} + ++static xhash *iamarray(var *a) ++{ + while (a->type & VF_CHILD) + a = a->x.parent; + +@@ -824,23 +935,7 @@ static xhash *iamarray(var *v) + return a->x.array; + } + +-static void clear_array(xhash *array) +-{ +- unsigned i; +- hash_item *hi, *thi; +- +- for (i = 0; i < array->csize; i++) { +- hi = array->items[i]; +- while (hi) { +- thi = hi; +- hi = hi->next; +- free(thi->data.v.string); +- free(thi); +- } +- array->items[i] = NULL; +- } +- array->glen = array->nel = 0; +-} ++#define clear_array(array) hash_clear(array) + + /* clear a variable */ + static var *clrvar(var *v) +@@ -854,6 +949,8 @@ static var *clrvar(var *v) + return v; + } + ++static void handle_special(var *); ++ + /* assign string value to variable */ + static var *setvar_p(var *v, char *value) + { +@@ -900,7 +997,7 @@ static const char *getvar_s(var *v) + { + /* if v is numeric and has no cached string, convert it to string */ + if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) { +- fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[CONVFMT]), v->number, TRUE); ++ fmt_num(getvar_s(intvar[CONVFMT]), v->number); + v->string = xstrdup(g_buf); + v->type |= VF_CACHED; + } +@@ -919,6 +1016,7 @@ static double getvar_i(var *v) + v->number = my_strtod(&s); + debug_printf_eval("%f (s:'%s')\n", v->number, s); + if (v->type & VF_USER) { ++//TODO: skip_spaces() also skips backslash+newline, is it intended here? + s = skip_spaces(s); + if (*s != '\0') + v->type &= ~VF_USER; +@@ -980,103 +1078,43 @@ static int istrue(var *v) + return (v->string && v->string[0]); + } + +-/* temporary variables allocator. Last allocated should be first freed */ +-static var *nvalloc(int n) +-{ +- nvblock *pb = NULL; +- var *v, *r; +- int size; +- +- while (g_cb) { +- pb = g_cb; +- if ((g_cb->pos - g_cb->nv) + n <= g_cb->size) +- break; +- g_cb = g_cb->next; +- } +- +- if (!g_cb) { +- size = (n <= MINNVBLOCK) ? MINNVBLOCK : n; +- g_cb = xzalloc(sizeof(nvblock) + size * sizeof(var)); +- g_cb->size = size; +- g_cb->pos = g_cb->nv; +- g_cb->prev = pb; +- /*g_cb->next = NULL; - xzalloc did it */ +- if (pb) +- pb->next = g_cb; +- } +- +- v = r = g_cb->pos; +- g_cb->pos += n; +- +- while (v < g_cb->pos) { +- v->type = 0; +- v->string = NULL; +- v++; +- } +- +- return r; +-} +- +-static void nvfree(var *v) +-{ +- var *p; +- +- if (v < g_cb->nv || v >= g_cb->pos) +- syntax_error(EMSG_INTERNAL_ERROR); +- +- for (p = v; p < g_cb->pos; p++) { +- if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) { +- clear_array(iamarray(p)); +- free(p->x.array->items); +- free(p->x.array); +- } +- if (p->type & VF_WALK) { +- walker_list *n; +- walker_list *w = p->x.walker; +- debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker); +- p->x.walker = NULL; +- while (w) { +- n = w->prev; +- debug_printf_walker(" free(%p)\n", w); +- free(w); +- w = n; +- } +- } +- clrvar(p); +- } +- +- g_cb->pos = v; +- while (g_cb->prev && g_cb->pos == g_cb->nv) { +- g_cb = g_cb->prev; +- } +-} +- + /* ------- awk program text parsing ------- */ + +-/* Parse next token pointed by global pos, place results into global ttt. +- * If token isn't expected, give away. Return token class ++/* Parse next token pointed by global pos, place results into global t_XYZ variables. ++ * If token isn't expected, print error message and die. ++ * Return token class (also store it in t_tclass). + */ + static uint32_t next_token(uint32_t expected) + { +-#define concat_inserted (G.next_token__concat_inserted) +-#define save_tclass (G.next_token__save_tclass) +-#define save_info (G.next_token__save_info) +-/* Initialized to TC_OPTERM: */ +-#define ltclass (G.next_token__ltclass) ++#define concat_inserted (G1.next_token__concat_inserted) ++#define save_tclass (G1.next_token__save_tclass) ++#define save_info (G1.next_token__save_info) + +- char *p, *s; ++ char *p; + const char *tl; +- uint32_t tc; + const uint32_t *ti; ++ uint32_t tc, last_token_class; ++ ++ last_token_class = t_tclass; /* t_tclass is initialized to TC_NEWLINE */ ++ ++ debug_printf_parse("%s() expected(%x):", __func__, expected); ++ debug_parse_print_tc(expected); ++ debug_printf_parse("\n"); + + if (t_rollback) { ++ debug_printf_parse("%s: using rolled-back token\n", __func__); + t_rollback = FALSE; + } else if (concat_inserted) { ++ debug_printf_parse("%s: using concat-inserted token\n", __func__); + concat_inserted = FALSE; + t_tclass = save_tclass; + t_info = save_info; + } else { + p = g_pos; ++ if (g_saved_ch != '\0') { ++ *p = g_saved_ch; ++ g_saved_ch = '\0'; ++ } + readnext: + p = skip_spaces(p); + g_lineno = t_lineno; +@@ -1084,15 +1122,12 @@ static uint32_t next_token(uint32_t expected) + while (*p != '\n' && *p != '\0') + p++; + +- if (*p == '\n') +- t_lineno++; +- + if (*p == '\0') { + tc = TC_EOF; + debug_printf_parse("%s: token found: TC_EOF\n", __func__); + } else if (*p == '\"') { + /* it's a string */ +- t_string = s = ++p; ++ char *s = t_string = ++p; + while (*p != '\"') { + char *pp; + if (*p == '\0' || *p == '\n') +@@ -1107,7 +1142,7 @@ static uint32_t next_token(uint32_t expected) + debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string); + } else if ((expected & TC_REGEXP) && *p == '/') { + /* it's regexp */ +- t_string = s = ++p; ++ char *s = t_string = ++p; + while (*p != '/') { + if (*p == '\0' || *p == '\n') + syntax_error(EMSG_UNEXP_EOS); +@@ -1138,6 +1173,11 @@ static uint32_t next_token(uint32_t expected) + tc = TC_NUMBER; + debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double); + } else { ++ char *end_of_name; ++ ++ if (*p == '\n') ++ t_lineno++; ++ + /* search for something known */ + tl = tokenlist; + tc = 0x00000001; +@@ -1152,9 +1192,9 @@ static uint32_t next_token(uint32_t expected) + * token matches, + * and it's not a longer word, + */ +- if ((tc & (expected | TC_WORD | TC_NEWLINE)) ++ if ((tc & (expected | TS_WORD | TC_NEWLINE)) + && strncmp(p, tl, l) == 0 +- && !((tc & TC_WORD) && isalnum_(p[l])) ++ && !((tc & TS_WORD) && isalnum_(p[l])) + ) { + /* then this is what we are looking for */ + t_info = *ti; +@@ -1171,61 +1211,94 @@ static uint32_t next_token(uint32_t expected) + if (!isalnum_(*p)) + syntax_error(EMSG_UNEXP_TOKEN); /* no */ + /* yes */ +- t_string = --p; +- while (isalnum_(*++p)) { +- p[-1] = *p; +- } +- p[-1] = '\0'; +- tc = TC_VARIABLE; +- /* also consume whitespace between functionname and bracket */ +- if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY)) ++ t_string = p; ++ while (isalnum_(*p)) ++ p++; ++ end_of_name = p; ++ ++ if (last_token_class == TC_FUNCDECL) ++ /* eat space in "function FUNC (...) {...}" declaration */ + p = skip_spaces(p); ++ else if (expected & TC_ARRAY) { ++ /* eat space between array name and [ */ ++ char *s = skip_spaces(p); ++ if (*s == '[') /* array ref, not just a name? */ ++ p = s; ++ } ++ /* else: do NOT consume whitespace after variable name! ++ * gawk allows definition "function FUNC (p) {...}" - note space, ++ * but disallows the call "FUNC (p)" because it isn't one - ++ * expression "v (a)" should NOT be parsed as TC_FUNCTION: ++ * it is a valid concatenation if "v" is a variable, ++ * not a function name (and type of name is not known at parse time). ++ */ ++ + if (*p == '(') { ++ p++; + tc = TC_FUNCTION; + debug_printf_parse("%s: token found:'%s' TC_FUNCTION\n", __func__, t_string); ++ } else if (*p == '[') { ++ p++; ++ tc = TC_ARRAY; ++ debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string); + } else { +- if (*p == '[') { +- p++; +- tc = TC_ARRAY; +- debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string); +- } else +- debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string); ++ tc = TC_VARIABLE; ++ debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string); ++ if (end_of_name == p) { ++ /* there is no space for trailing NUL in t_string! ++ * We need to save the char we are going to NUL. ++ * (we'll use it in future call to next_token()) ++ */ ++ g_saved_ch = *end_of_name; ++// especially pathological example is V="abc"; V.2 - it's V concatenated to .2 ++// (it evaluates to "abc0.2"). Because of this case, we can't simply cache ++// '.' and analyze it later: we also have to *store it back* in next ++// next_token(), in order to give my_strtod() the undamaged ".2" string. ++ } + } ++ *end_of_name = '\0'; /* terminate t_string */ + } + token_found: + g_pos = p; + + /* skipping newlines in some cases */ +- if ((ltclass & TC_NOTERM) && (tc & TC_NEWLINE)) ++ if ((last_token_class & TS_NOTERM) && (tc & TC_NEWLINE)) + goto readnext; + + /* insert concatenation operator when needed */ +- if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) { ++ debug_printf_parse("%s: concat_inserted if all nonzero: %x %x %x %x\n", __func__, ++ (last_token_class & TS_CONCAT_L), (tc & TS_CONCAT_R), (expected & TS_BINOP), ++ !(last_token_class == TC_LENGTH && tc == TC_LPAREN)); ++ if ((last_token_class & TS_CONCAT_L) && (tc & TS_CONCAT_R) && (expected & TS_BINOP) ++ && !(last_token_class == TC_LENGTH && tc == TC_LPAREN) /* but not for "length(..." */ ++ ) { + concat_inserted = TRUE; + save_tclass = tc; + save_info = t_info; +- tc = TC_BINOP; ++ tc = TC_BINOPX; + t_info = OC_CONCAT | SS | P(35); + } + + t_tclass = tc; ++ debug_printf_parse("%s: t_tclass=tc=%x\n", __func__, tc); + } +- ltclass = t_tclass; +- + /* Are we ready for this? */ +- if (!(ltclass & expected)) { +- syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ? ++ if (!(t_tclass & expected)) { ++ syntax_error((last_token_class & (TC_NEWLINE | TC_EOF)) ? + EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN); + } + +- return ltclass; ++ debug_printf_parse("%s: returning, t_double:%f t_tclass:", __func__, t_double); ++ debug_parse_print_tc(t_tclass); ++ debug_printf_parse("\n"); ++ ++ return t_tclass; + #undef concat_inserted + #undef save_tclass + #undef save_info +-#undef ltclass + } + +-static void rollback_token(void) ++static ALWAYS_INLINE void rollback_token(void) + { + t_rollback = TRUE; + } +@@ -1242,162 +1315,188 @@ static node *new_node(uint32_t info) + + static void mk_re_node(const char *s, node *n, regex_t *re) + { +- n->info = OC_REGEXP; ++ n->info = TI_REGEXP; + n->l.re = re; + n->r.ire = re + 1; + xregcomp(re, s, REG_EXTENDED); + xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE); + } + +-static node *condition(void) ++static node *parse_expr(uint32_t); ++ ++static node *parse_lrparen_list(void) + { +- next_token(TC_SEQSTART); +- return parse_expr(TC_SEQTERM); ++ next_token(TC_LPAREN); ++ return parse_expr(TC_RPAREN); + } + + /* parse expression terminated by given argument, return ptr + * to built subtree. Terminator is eaten by parse_expr */ +-static node *parse_expr(uint32_t iexp) ++static node *parse_expr(uint32_t term_tc) + { + node sn; + node *cn = &sn; + node *vn, *glptr; +- uint32_t tc, xtc; ++ uint32_t tc, expected_tc; + var *v; + +- debug_printf_parse("%s(%x)\n", __func__, iexp); ++ debug_printf_parse("%s() term_tc(%x):", __func__, term_tc); ++ debug_parse_print_tc(term_tc); ++ debug_printf_parse("\n"); + + sn.info = PRIMASK; + sn.r.n = sn.a.n = glptr = NULL; +- xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; ++ expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP | term_tc; + +- while (!((tc = next_token(xtc)) & iexp)) { ++ while (!((tc = next_token(expected_tc)) & term_tc)) { + +- if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { ++ if (glptr && (t_info == TI_LESS)) { + /* input redirection (<) attached to glptr node */ + debug_printf_parse("%s: input redir\n", __func__); + cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); + cn->a.n = glptr; +- xtc = TC_OPERAND | TC_UOPPRE; ++ expected_tc = TS_OPERAND | TS_UOPPRE; + glptr = NULL; +- +- } else if (tc & (TC_BINOP | TC_UOPPOST)) { +- debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__); ++ continue; ++ } ++ if (tc & (TS_BINOP | TC_UOPPOST)) { ++ debug_printf_parse("%s: TS_BINOP | TC_UOPPOST tc:%x\n", __func__, tc); + /* for binary and postfix-unary operators, jump back over + * previous operators with higher priority */ + vn = cn; + while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2)) +- || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON)) ++ || ((t_info == vn->info) && t_info == TI_COLON) + ) { + vn = vn->a.n; + if (!vn->a.n) syntax_error(EMSG_UNEXP_TOKEN); + } +- if ((t_info & OPCLSMASK) == OC_TERNARY) ++ if (t_info == TI_TERNARY) ++//TODO: why? + t_info += P(6); + cn = vn->a.n->r.n = new_node(t_info); + cn->a.n = vn->a.n; +- if (tc & TC_BINOP) { ++ if (tc & TS_BINOP) { + cn->l.n = vn; +- xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; +- if ((t_info & OPCLSMASK) == OC_PGETLINE) { ++//FIXME: this is the place to detect and reject assignments to non-lvalues. ++//Currently we allow "assignments" to consts and temporaries, nonsense like this: ++// awk 'BEGIN { "qwe" = 1 }' ++// awk 'BEGIN { 7 *= 7 }' ++// awk 'BEGIN { length("qwe") = 1 }' ++// awk 'BEGIN { (1+1) += 3 }' ++ expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP; ++ if (t_info == TI_PGETLINE) { + /* it's a pipe */ + next_token(TC_GETLINE); + /* give maximum priority to this pipe */ + cn->info &= ~PRIMASK; +- xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; ++ expected_tc = TS_OPERAND | TS_UOPPRE | TS_BINOP | term_tc; + } + } else { + cn->r.n = vn; +- xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; ++ expected_tc = TS_OPERAND | TS_UOPPRE | TS_BINOP | term_tc; + } + vn->a.n = cn; ++ continue; ++ } + +- } else { +- debug_printf_parse("%s: other\n", __func__); +- /* for operands and prefix-unary operators, attach them +- * to last node */ +- vn = cn; +- cn = vn->r.n = new_node(t_info); +- cn->a.n = vn; +- xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP; +- if (tc & (TC_OPERAND | TC_REGEXP)) { +- debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__); +- xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp; +- /* one should be very careful with switch on tclass - +- * only simple tclasses should be used! */ +- switch (tc) { +- case TC_VARIABLE: +- case TC_ARRAY: +- debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__); +- cn->info = OC_VAR; +- v = hash_search(ahash, t_string); +- if (v != NULL) { +- cn->info = OC_FNARG; +- cn->l.aidx = v->x.aidx; +- } else { +- cn->l.v = newvar(t_string); +- } +- if (tc & TC_ARRAY) { +- cn->info |= xS; +- cn->r.n = parse_expr(TC_ARRTERM); +- } +- break; ++ debug_printf_parse("%s: other, t_info:%x\n", __func__, t_info); ++ /* for operands and prefix-unary operators, attach them ++ * to last node */ ++ vn = cn; ++ cn = vn->r.n = new_node(t_info); ++ cn->a.n = vn; + +- case TC_NUMBER: +- case TC_STRING: +- debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__); +- cn->info = OC_VAR; +- v = cn->l.v = xzalloc(sizeof(var)); +- if (tc & TC_NUMBER) +- setvar_i(v, t_double); +- else +- setvar_s(v, t_string); +- break; ++ expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP; ++ if (t_info == TI_PREINC || t_info == TI_PREDEC) ++ expected_tc = TS_LVALUE | TC_UOPPRE1; + +- case TC_REGEXP: +- debug_printf_parse("%s: TC_REGEXP\n", __func__); +- mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2)); +- break; ++ if (!(tc & (TS_OPERAND | TC_REGEXP))) ++ continue; + +- case TC_FUNCTION: +- debug_printf_parse("%s: TC_FUNCTION\n", __func__); +- cn->info = OC_FUNC; +- cn->r.f = newfunc(t_string); +- cn->l.n = condition(); +- break; ++ debug_printf_parse("%s: TS_OPERAND | TC_REGEXP\n", __func__); ++ expected_tc = TS_UOPPRE | TC_UOPPOST | TS_BINOP | TS_OPERAND | term_tc; ++ /* one should be very careful with switch on tclass - ++ * only simple tclasses should be used (TC_xyz, not TS_xyz) */ ++ switch (tc) { ++ case TC_VARIABLE: ++ case TC_ARRAY: ++ debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__); ++ cn->info = OC_VAR; ++ v = hash_search(ahash, t_string); ++ if (v != NULL) { ++ cn->info = OC_FNARG; ++ cn->l.aidx = v->x.aidx; ++ } else { ++ cn->l.v = newvar(t_string); ++ } ++ if (tc & TC_ARRAY) { ++ cn->info |= xS; ++ cn->r.n = parse_expr(TC_ARRTERM); ++ } ++ break; + +- case TC_SEQSTART: +- debug_printf_parse("%s: TC_SEQSTART\n", __func__); +- cn = vn->r.n = parse_expr(TC_SEQTERM); +- if (!cn) +- syntax_error("Empty sequence"); +- cn->a.n = vn; +- break; ++ case TC_NUMBER: ++ case TC_STRING: ++ debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__); ++ cn->info = OC_VAR; ++ v = cn->l.v = xzalloc(sizeof(var)); ++ if (tc & TC_NUMBER) ++ setvar_i(v, t_double); ++ else { ++ setvar_s(v, t_string); ++ expected_tc &= ~TC_UOPPOST; /* "str"++ is not allowed */ ++ } ++ break; + +- case TC_GETLINE: +- debug_printf_parse("%s: TC_GETLINE\n", __func__); +- glptr = cn; +- xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp; +- break; ++ case TC_REGEXP: ++ debug_printf_parse("%s: TC_REGEXP\n", __func__); ++ mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2)); ++ break; + +- case TC_BUILTIN: +- debug_printf_parse("%s: TC_BUILTIN\n", __func__); +- cn->l.n = condition(); +- break; ++ case TC_FUNCTION: ++ debug_printf_parse("%s: TC_FUNCTION\n", __func__); ++ cn->info = OC_FUNC; ++ cn->r.f = newfunc(t_string); ++ cn->l.n = parse_expr(TC_RPAREN); ++ break; + +- case TC_LENGTH: +- debug_printf_parse("%s: TC_LENGTH\n", __func__); +- next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM); +- rollback_token(); +- if (t_tclass & TC_SEQSTART) { +- /* It was a "(" token. Handle just like TC_BUILTIN */ +- cn->l.n = condition(); +- } +- break; +- } ++ case TC_LPAREN: ++ debug_printf_parse("%s: TC_LPAREN\n", __func__); ++ cn = vn->r.n = parse_expr(TC_RPAREN); ++ if (!cn) ++ syntax_error("Empty sequence"); ++ cn->a.n = vn; ++ break; ++ ++ case TC_GETLINE: ++ debug_printf_parse("%s: TC_GETLINE\n", __func__); ++ glptr = cn; ++ expected_tc = TS_OPERAND | TS_UOPPRE | TS_BINOP | term_tc; ++ break; ++ ++ case TC_BUILTIN: ++ debug_printf_parse("%s: TC_BUILTIN\n", __func__); ++ cn->l.n = parse_lrparen_list(); ++ break; ++ ++ case TC_LENGTH: ++ debug_printf_parse("%s: TC_LENGTH\n", __func__); ++ tc = next_token(TC_LPAREN /* length(...) */ ++ | TC_SEMICOL /* length; */ ++ | TC_NEWLINE /* length<newline> */ ++ | TC_RBRACE /* length } */ ++ | TC_BINOPX /* length <op> NUM */ ++ | TC_COMMA /* print length, 1 */ ++ ); ++ if (tc != TC_LPAREN) ++ rollback_token(); ++ else { ++ /* It was a "(" token. Handle just like TC_BUILTIN */ ++ cn->l.n = parse_expr(TC_RPAREN); + } ++ break; + } +- } ++ } /* while() */ + + debug_printf_parse("%s() returns %p\n", __func__, sn.r.n); + return sn.r.n; +@@ -1414,7 +1513,7 @@ static node *chain_node(uint32_t info) + if (seq->programname != g_progname) { + seq->programname = g_progname; + n = chain_node(OC_NEWSOURCE); +- n->l.new_progname = xstrdup(g_progname); ++ n->l.new_progname = g_progname; + } + + n = seq->last; +@@ -1430,14 +1529,16 @@ static void chain_expr(uint32_t info) + + n = chain_node(info); + +- n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM); ++ n->l.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_RBRACE); + if ((info & OF_REQUIRED) && !n->l.n) + syntax_error(EMSG_TOO_FEW_ARGS); + +- if (t_tclass & TC_GRPTERM) ++ if (t_tclass & TC_RBRACE) + rollback_token(); + } + ++static void chain_group(void); ++ + static node *chain_loop(node *nn) + { + node *n, *n2, *save_brk, *save_cont; +@@ -1461,207 +1562,284 @@ static node *chain_loop(node *nn) + return n; + } + ++static void chain_until_rbrace(void) ++{ ++ uint32_t tc; ++ while ((tc = next_token(TS_GRPSEQ | TC_RBRACE)) != TC_RBRACE) { ++ debug_printf_parse("%s: !TC_RBRACE\n", __func__); ++ if (tc == TC_NEWLINE) ++ continue; ++ rollback_token(); ++ chain_group(); ++ } ++ debug_printf_parse("%s: TC_RBRACE\n", __func__); ++} ++ + /* parse group and attach it to chain */ + static void chain_group(void) + { +- uint32_t c; ++ uint32_t tc; + node *n, *n2, *n3; + + do { +- c = next_token(TC_GRPSEQ); +- } while (c & TC_NEWLINE); +- +- if (c & TC_GRPSTART) { +- debug_printf_parse("%s: TC_GRPSTART\n", __func__); +- while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) { +- debug_printf_parse("%s: !TC_GRPTERM\n", __func__); +- if (t_tclass & TC_NEWLINE) +- continue; +- rollback_token(); +- chain_group(); +- } +- debug_printf_parse("%s: TC_GRPTERM\n", __func__); +- } else if (c & (TC_OPSEQ | TC_OPTERM)) { +- debug_printf_parse("%s: TC_OPSEQ | TC_OPTERM\n", __func__); ++ tc = next_token(TS_GRPSEQ); ++ } while (tc == TC_NEWLINE); ++ ++ if (tc == TC_LBRACE) { ++ debug_printf_parse("%s: TC_LBRACE\n", __func__); ++ chain_until_rbrace(); ++ return; ++ } ++ if (tc & (TS_OPSEQ | TC_SEMICOL)) { ++ debug_printf_parse("%s: TS_OPSEQ | TC_SEMICOL\n", __func__); + rollback_token(); + chain_expr(OC_EXEC | Vx); +- } else { +- /* TC_STATEMNT */ +- debug_printf_parse("%s: TC_STATEMNT(?)\n", __func__); +- switch (t_info & OPCLSMASK) { +- case ST_IF: +- debug_printf_parse("%s: ST_IF\n", __func__); +- n = chain_node(OC_BR | Vx); +- n->l.n = condition(); ++ return; ++ } ++ ++ /* TS_STATEMNT */ ++ debug_printf_parse("%s: TS_STATEMNT(?)\n", __func__); ++ switch (t_info & OPCLSMASK) { ++ case ST_IF: ++ debug_printf_parse("%s: ST_IF\n", __func__); ++ n = chain_node(OC_BR | Vx); ++ n->l.n = parse_lrparen_list(); ++ chain_group(); ++ n2 = chain_node(OC_EXEC); ++ n->r.n = seq->last; ++ if (next_token(TS_GRPSEQ | TC_RBRACE | TC_ELSE) == TC_ELSE) { + chain_group(); +- n2 = chain_node(OC_EXEC); +- n->r.n = seq->last; +- if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE) == TC_ELSE) { +- chain_group(); +- n2->a.n = seq->last; +- } else { +- rollback_token(); +- } +- break; ++ n2->a.n = seq->last; ++ } else { ++ rollback_token(); ++ } ++ break; + +- case ST_WHILE: +- debug_printf_parse("%s: ST_WHILE\n", __func__); +- n2 = condition(); +- n = chain_loop(NULL); +- n->l.n = n2; +- break; ++ case ST_WHILE: ++ debug_printf_parse("%s: ST_WHILE\n", __func__); ++ n2 = parse_lrparen_list(); ++ n = chain_loop(NULL); ++ n->l.n = n2; ++ break; + +- case ST_DO: +- debug_printf_parse("%s: ST_DO\n", __func__); +- n2 = chain_node(OC_EXEC); +- n = chain_loop(NULL); +- n2->a.n = n->a.n; +- next_token(TC_WHILE); +- n->l.n = condition(); +- break; ++ case ST_DO: ++ debug_printf_parse("%s: ST_DO\n", __func__); ++ n2 = chain_node(OC_EXEC); ++ n = chain_loop(NULL); ++ n2->a.n = n->a.n; ++ next_token(TC_WHILE); ++ n->l.n = parse_lrparen_list(); ++ break; + +- case ST_FOR: +- debug_printf_parse("%s: ST_FOR\n", __func__); +- next_token(TC_SEQSTART); +- n2 = parse_expr(TC_SEMICOL | TC_SEQTERM); +- if (t_tclass & TC_SEQTERM) { /* for-in */ +- if (!n2 || (n2->info & OPCLSMASK) != OC_IN) +- syntax_error(EMSG_UNEXP_TOKEN); +- n = chain_node(OC_WALKINIT | VV); +- n->l.n = n2->l.n; +- n->r.n = n2->r.n; +- n = chain_loop(NULL); +- n->info = OC_WALKNEXT | Vx; +- n->l.n = n2->l.n; +- } else { /* for (;;) */ +- n = chain_node(OC_EXEC | Vx); +- n->l.n = n2; +- n2 = parse_expr(TC_SEMICOL); +- n3 = parse_expr(TC_SEQTERM); +- n = chain_loop(n3); +- n->l.n = n2; +- if (!n2) +- n->info = OC_EXEC; +- } +- break; ++ case ST_FOR: ++ debug_printf_parse("%s: ST_FOR\n", __func__); ++ next_token(TC_LPAREN); ++ n2 = parse_expr(TC_SEMICOL | TC_RPAREN); ++ if (t_tclass & TC_RPAREN) { /* for (I in ARRAY) */ ++ if (!n2 || n2->info != TI_IN) ++ syntax_error(EMSG_UNEXP_TOKEN); ++ n = chain_node(OC_WALKINIT | VV); ++ n->l.n = n2->l.n; ++ n->r.n = n2->r.n; ++ n = chain_loop(NULL); ++ n->info = OC_WALKNEXT | Vx; ++ n->l.n = n2->l.n; ++ } else { /* for (;;) */ ++ n = chain_node(OC_EXEC | Vx); ++ n->l.n = n2; ++ n2 = parse_expr(TC_SEMICOL); ++ n3 = parse_expr(TC_RPAREN); ++ n = chain_loop(n3); ++ n->l.n = n2; ++ if (!n2) ++ n->info = OC_EXEC; ++ } ++ break; + +- case OC_PRINT: +- case OC_PRINTF: +- debug_printf_parse("%s: OC_PRINT[F]\n", __func__); +- n = chain_node(t_info); +- n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM); +- if (t_tclass & TC_OUTRDR) { +- n->info |= t_info; +- n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM); +- } +- if (t_tclass & TC_GRPTERM) +- rollback_token(); +- break; ++ case OC_PRINT: ++ case OC_PRINTF: ++ debug_printf_parse("%s: OC_PRINT[F]\n", __func__); ++ n = chain_node(t_info); ++ n->l.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_OUTRDR | TC_RBRACE); ++ if (t_tclass & TC_OUTRDR) { ++ n->info |= t_info; ++ n->r.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_RBRACE); ++ } ++ if (t_tclass & TC_RBRACE) ++ rollback_token(); ++ break; + +- case OC_BREAK: +- debug_printf_parse("%s: OC_BREAK\n", __func__); +- n = chain_node(OC_EXEC); +- n->a.n = break_ptr; +- chain_expr(t_info); +- break; ++ case OC_BREAK: ++ debug_printf_parse("%s: OC_BREAK\n", __func__); ++ n = chain_node(OC_EXEC); ++ if (!break_ptr) ++ syntax_error("'break' not in a loop"); ++ n->a.n = break_ptr; ++ chain_expr(t_info); ++ break; + +- case OC_CONTINUE: +- debug_printf_parse("%s: OC_CONTINUE\n", __func__); +- n = chain_node(OC_EXEC); +- n->a.n = continue_ptr; +- chain_expr(t_info); +- break; ++ case OC_CONTINUE: ++ debug_printf_parse("%s: OC_CONTINUE\n", __func__); ++ n = chain_node(OC_EXEC); ++ if (!continue_ptr) ++ syntax_error("'continue' not in a loop"); ++ n->a.n = continue_ptr; ++ chain_expr(t_info); ++ break; + +- /* delete, next, nextfile, return, exit */ +- default: +- debug_printf_parse("%s: default\n", __func__); +- chain_expr(t_info); +- } ++ /* delete, next, nextfile, return, exit */ ++ default: ++ debug_printf_parse("%s: default\n", __func__); ++ chain_expr(t_info); + } + } + + static void parse_program(char *p) + { +- uint32_t tclass; +- node *cn; +- func *f; +- var *v; ++ debug_printf_parse("%s()\n", __func__); + + g_pos = p; + t_lineno = 1; +- while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART | +- TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) { ++ for (;;) { ++ uint32_t tclass; + +- if (tclass & TC_OPTERM) { +- debug_printf_parse("%s: TC_OPTERM\n", __func__); ++ tclass = next_token(TS_OPSEQ | TC_LBRACE | TC_BEGIN | TC_END | TC_FUNCDECL ++ | TC_EOF | TC_NEWLINE /* but not TC_SEMICOL */); ++ got_tok: ++ if (tclass == TC_EOF) { ++ debug_printf_parse("%s: TC_EOF\n", __func__); ++ break; ++ } ++ if (tclass == TC_NEWLINE) { ++ debug_printf_parse("%s: TC_NEWLINE\n", __func__); + continue; + } +- +- seq = &mainseq; +- if (tclass & TC_BEGIN) { ++ if (tclass == TC_BEGIN) { + debug_printf_parse("%s: TC_BEGIN\n", __func__); + seq = &beginseq; +- chain_group(); +- } else if (tclass & TC_END) { ++ /* ensure there is no newline between BEGIN and { */ ++ next_token(TC_LBRACE); ++ chain_until_rbrace(); ++ goto next_tok; ++ } ++ if (tclass == TC_END) { + debug_printf_parse("%s: TC_END\n", __func__); + seq = &endseq; +- chain_group(); +- } else if (tclass & TC_FUNCDECL) { ++ /* ensure there is no newline between END and { */ ++ next_token(TC_LBRACE); ++ chain_until_rbrace(); ++ goto next_tok; ++ } ++ if (tclass == TC_FUNCDECL) { ++ func *f; ++ + debug_printf_parse("%s: TC_FUNCDECL\n", __func__); + next_token(TC_FUNCTION); +- g_pos++; + f = newfunc(t_string); +- f->body.first = NULL; +- f->nargs = 0; +- /* Match func arg list: a comma sep list of >= 0 args, and a close paren */ +- while (next_token(TC_VARIABLE | TC_SEQTERM | TC_COMMA)) { +- /* Either an empty arg list, or trailing comma from prev iter +- * must be followed by an arg */ +- if (f->nargs == 0 && t_tclass == TC_SEQTERM) +- break; +- +- /* TC_SEQSTART/TC_COMMA must be followed by TC_VARIABLE */ +- if (t_tclass != TC_VARIABLE) ++ if (f->defined) ++ syntax_error("Duplicate function"); ++ f->defined = 1; ++ //f->body.first = NULL; - already is ++ //f->nargs = 0; - already is ++ /* func arg list: comma sep list of args, and a close paren */ ++ for (;;) { ++ var *v; ++ if (next_token(TC_VARIABLE | TC_RPAREN) == TC_RPAREN) { ++ if (f->nargs == 0) ++ break; /* func() is ok */ ++ /* func(a,) is not ok */ + syntax_error(EMSG_UNEXP_TOKEN); +- ++ } + v = findvar(ahash, t_string); + v->x.aidx = f->nargs++; +- + /* Arg followed either by end of arg list or 1 comma */ +- if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) ++ if (next_token(TC_COMMA | TC_RPAREN) == TC_RPAREN) + break; +- if (t_tclass != TC_COMMA) +- syntax_error(EMSG_UNEXP_TOKEN); ++ /* it was a comma, we ate it */ + } + seq = &f->body; +- chain_group(); +- clear_array(ahash); +- } else if (tclass & TC_OPSEQ) { +- debug_printf_parse("%s: TC_OPSEQ\n", __func__); ++ /* ensure there is { after "func F(...)" - but newlines are allowed */ ++ while (next_token(TC_LBRACE | TC_NEWLINE) == TC_NEWLINE) ++ continue; ++ chain_until_rbrace(); ++ hash_clear(ahash); ++ goto next_tok; ++ } ++ seq = &mainseq; ++ if (tclass & TS_OPSEQ) { ++ node *cn; ++ ++ debug_printf_parse("%s: TS_OPSEQ\n", __func__); + rollback_token(); + cn = chain_node(OC_TEST); +- cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART); +- if (t_tclass & TC_GRPSTART) { +- debug_printf_parse("%s: TC_GRPSTART\n", __func__); +- rollback_token(); +- chain_group(); ++ cn->l.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_EOF | TC_LBRACE); ++ if (t_tclass == TC_LBRACE) { ++ debug_printf_parse("%s: TC_LBRACE\n", __func__); ++ chain_until_rbrace(); + } else { +- debug_printf_parse("%s: !TC_GRPSTART\n", __func__); ++ /* no action, assume default "{ print }" */ ++ debug_printf_parse("%s: !TC_LBRACE\n", __func__); + chain_node(OC_PRINT); + } + cn->r.n = mainseq.last; +- } else /* if (tclass & TC_GRPSTART) */ { +- debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__); +- rollback_token(); +- chain_group(); ++ goto next_tok; + } +- } +- debug_printf_parse("%s: TC_EOF\n", __func__); ++ /* tclass == TC_LBRACE */ ++ debug_printf_parse("%s: TC_LBRACE(?)\n", __func__); ++ chain_until_rbrace(); ++ next_tok: ++ /* Same as next_token() at the top of the loop, + TC_SEMICOL */ ++ tclass = next_token(TS_OPSEQ | TC_LBRACE | TC_BEGIN | TC_END | TC_FUNCDECL ++ | TC_EOF | TC_NEWLINE | TC_SEMICOL); ++ /* gawk allows many newlines, but does not allow more than one semicolon: ++ * BEGIN {...}<newline>;<newline>; ++ * would complain "each rule must have a pattern or an action part". ++ * Same message for ++ * ; BEGIN {...} ++ */ ++ if (tclass != TC_SEMICOL) ++ goto got_tok; /* use this token */ ++ /* else: loop back - ate the semicolon, get and use _next_ token */ ++ } /* for (;;) */ + } + +- + /* -------- program execution part -------- */ + ++/* temporary variables allocator */ ++static var *nvalloc(int sz) ++{ ++ return xzalloc(sz * sizeof(var)); ++} ++ ++static void nvfree(var *v, int sz) ++{ ++ var *p = v; ++ ++ while (--sz >= 0) { ++ if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) { ++ clear_array(iamarray(p)); ++ free(p->x.array->items); ++ free(p->x.array); ++ } ++ if (p->type & VF_WALK) { ++ walker_list *n; ++ walker_list *w = p->x.walker; ++ debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker); ++ p->x.walker = NULL; ++ while (w) { ++ n = w->prev; ++ debug_printf_walker(" free(%p)\n", w); ++ free(w); ++ w = n; ++ } ++ } ++ clrvar(p); ++ p++; ++ } ++ ++ free(v); ++} ++ + static node *mk_splitter(const char *s, tsplitter *spl) + { + regex_t *re, *ire; +@@ -1670,7 +1848,7 @@ static node *mk_splitter(const char *s, tsplitter *spl) + re = &spl->re[0]; + ire = &spl->re[1]; + n = &spl->n; +- if ((n->info & OPCLSMASK) == OC_REGEXP) { ++ if (n->info == TI_REGEXP) { + regfree(re); + regfree(ire); // TODO: nuke ire, use re+1? + } +@@ -1683,21 +1861,28 @@ static node *mk_splitter(const char *s, tsplitter *spl) + return n; + } + +-/* use node as a regular expression. Supplied with node ptr and regex_t ++static var *evaluate(node *, var *); ++ ++/* Use node as a regular expression. Supplied with node ptr and regex_t + * storage space. Return ptr to regex (if result points to preg, it should +- * be later regfree'd manually ++ * be later regfree'd manually). + */ + static regex_t *as_regex(node *op, regex_t *preg) + { + int cflags; +- var *v; + const char *s; + +- if ((op->info & OPCLSMASK) == OC_REGEXP) { ++ if (op->info == TI_REGEXP) { + return icase ? op->r.ire : op->l.re; + } +- v = nvalloc(1); +- s = getvar_s(evaluate(op, v)); ++ ++ //tmpvar = nvalloc(1); ++#define TMPVAR (&G.as_regex__tmpvar) ++ // We use a single "static" tmpvar (instead of on-stack or malloced one) ++ // to decrease memory consumption in deeply-recursive awk programs. ++ // The rule to work safely is to never call evaluate() while our static ++ // TMPVAR's value is still needed. ++ s = getvar_s(evaluate(op, TMPVAR)); + + cflags = icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED; + /* Testcase where REG_EXTENDED fails (unpaired '{'): +@@ -1709,7 +1894,8 @@ static regex_t *as_regex(node *op, regex_t *preg) + cflags &= ~REG_EXTENDED; + xregcomp(preg, s, cflags); + } +- nvfree(v); ++ //nvfree(tmpvar, 1); ++#undef TMPVAR + return preg; + } + +@@ -1729,12 +1915,22 @@ static char* qrealloc(char *b, int n, int *size) + /* resize field storage space */ + static void fsrealloc(int size) + { +- int i; ++ int i, newsize; + + if (size >= maxfields) { ++ /* Sanity cap, easier than catering for overflows */ ++ if (size > 0xffffff) ++ bb_die_memory_exhausted(); ++ + i = maxfields; + maxfields = size + 16; +- Fields = xrealloc(Fields, maxfields * sizeof(Fields[0])); ++ ++ newsize = maxfields * sizeof(Fields[0]); ++ debug_printf_eval("fsrealloc: xrealloc(%p, %u)\n", Fields, newsize); ++ Fields = xrealloc(Fields, newsize); ++ debug_printf_eval("fsrealloc: Fields=%p..%p\n", Fields, (char*)Fields + newsize - 1); ++ /* ^^^ did Fields[] move? debug aid for L.v getting "upstaged" by R.v in evaluate() */ ++ + for (; i < maxfields; i++) { + Fields[i].type = VF_SPECIAL; + Fields[i].string = NULL; +@@ -1747,12 +1943,34 @@ static void fsrealloc(int size) + nfields = size; + } + ++static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[]) ++{ ++ int r = regexec(preg, s, 1, pmatch, 0); ++ if (r == 0 && pmatch[0].rm_eo == 0) { ++ /* For example, happens when FS can match ++ * an empty string (awk -F ' *'). Logically, ++ * this should split into one-char fields. ++ * However, gawk 5.0.1 searches for first ++ * _non-empty_ separator string match: ++ */ ++ size_t ofs = 0; ++ do { ++ ofs++; ++ if (!s[ofs]) ++ return REG_NOMATCH; ++ regexec(preg, s + ofs, 1, pmatch, 0); ++ } while (pmatch[0].rm_eo == 0); ++ pmatch[0].rm_so += ofs; ++ pmatch[0].rm_eo += ofs; ++ } ++ return r; ++} ++ + static int awk_split(const char *s, node *spl, char **slist) + { +- int l, n; ++ int n; + char c[4]; + char *s1; +- regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... + + /* in worst case, each char would be a separate field */ + *slist = s1 = xzalloc(strlen(s) * 2 + 3); +@@ -1764,34 +1982,36 @@ static int awk_split(const char *s, node *spl, char **slist) + c[2] = '\n'; + + n = 0; +- if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */ ++ if (spl->info == TI_REGEXP) { /* regex split */ + if (!*s) + return n; /* "": zero fields */ + n++; /* at least one field will be there */ + do { ++ int l; ++ regmatch_t pmatch[1]; ++ + l = strcspn(s, c+2); /* len till next NUL or \n */ +- if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0 ++ if (regexec1_nonempty(icase ? spl->r.ire : spl->l.re, s, pmatch) == 0 + && pmatch[0].rm_so <= l + ) { ++ /* if (pmatch[0].rm_eo == 0) ... - impossible */ + l = pmatch[0].rm_so; +- if (pmatch[0].rm_eo == 0) { +- l++; +- pmatch[0].rm_eo++; +- } + n++; /* we saw yet another delimiter */ + } else { + pmatch[0].rm_eo = l; + if (s[l]) + pmatch[0].rm_eo++; + } +- memcpy(s1, s, l); +- /* make sure we remove *all* of the separator chars */ +- do { +- s1[l] = '\0'; +- } while (++l < pmatch[0].rm_eo); +- nextword(&s1); ++ s1 = mempcpy(s1, s, l); ++ *s1++ = '\0'; + s += pmatch[0].rm_eo; + } while (*s); ++ ++ /* echo a-- | awk -F-- '{ print NF, length($NF), $NF }' ++ * should print "2 0 ": ++ */ ++ *s1 = '\0'; ++ + return n; + } + if (c[0] == '\0') { /* null split */ +@@ -1929,7 +2149,7 @@ static node *nextarg(node **pn) + node *n; + + n = *pn; +- if (n && (n->info & OPCLSMASK) == OC_COMMA) { ++ if (n && n->info == TI_COMMA) { + *pn = n->r.n; + n = n->l.n; + } else { +@@ -1960,8 +2180,7 @@ static void hashwalk_init(var *v, xhash *array) + for (i = 0; i < array->csize; i++) { + hi = array->items[i]; + while (hi) { +- strcpy(w->end, hi->name); +- nextword(&w->end); ++ w->end = stpcpy(w->end, hi->name) + 1; + hi = hi->next; + } + } +@@ -1987,15 +2206,18 @@ static int hashwalk_next(var *v) + /* evaluate node, return 1 when result is true, 0 otherwise */ + static int ptest(node *pattern) + { +- /* ptest__v is "static": to save stack space? */ +- return istrue(evaluate(pattern, &G.ptest__v)); ++ // We use a single "static" tmpvar (instead of on-stack or malloced one) ++ // to decrease memory consumption in deeply-recursive awk programs. ++ // The rule to work safely is to never call evaluate() while our static ++ // TMPVAR's value is still needed. ++ return istrue(evaluate(pattern, &G.ptest__tmpvar)); + } + + /* read next record from stream rsm into a variable v */ + static int awk_getline(rstream *rsm, var *v) + { + char *b; +- regmatch_t pmatch[2]; ++ regmatch_t pmatch[1]; + int size, a, p, pp = 0; + int fd, so, eo, r, rp; + char c, *m, *s; +@@ -2021,7 +2243,7 @@ static int awk_getline(rstream *rsm, var *v) + so = eo = p; + r = 1; + if (p > 0) { +- if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) { ++ if (rsplitter.n.info == TI_REGEXP) { + if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re, + b, 1, pmatch, 0) == 0) { + so = pmatch[0].rm_so; +@@ -2093,42 +2315,36 @@ static int awk_getline(rstream *rsm, var *v) + return r; + } + +-static int fmt_num(char *b, int size, const char *format, double n, int int_as_int) +-{ +- int r = 0; +- char c; +- const char *s = format; +- +- if (int_as_int && n == (long long)n) { +- r = snprintf(b, size, "%lld", (long long)n); +- } else { +- do { c = *s; } while (c && *++s); +- if (strchr("diouxX", c)) { +- r = snprintf(b, size, format, (int)n); +- } else if (strchr("eEfgG", c)) { +- r = snprintf(b, size, format, n); +- } else { +- syntax_error(EMSG_INV_FMT); +- } +- } +- return r; +-} +- + /* formatted output into an allocated buffer, return ptr to buffer */ +-static char *awk_printf(node *n) ++#if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS ++# define awk_printf(a, b) awk_printf(a) ++#endif ++static char *awk_printf(node *n, size_t *len) + { +- char *b = NULL; +- char *fmt, *s, *f; +- const char *s1; +- int i, j, incr, bsize; +- char c, c1; +- var *v, *arg; +- +- v = nvalloc(1); +- fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), v))); +- ++ char *b; ++ char *fmt, *f; ++ size_t i; ++ ++ //tmpvar = nvalloc(1); ++#define TMPVAR (&G.awk_printf__tmpvar) ++ // We use a single "static" tmpvar (instead of on-stack or malloced one) ++ // to decrease memory consumption in deeply-recursive awk programs. ++ // The rule to work safely is to never call evaluate() while our static ++ // TMPVAR's value is still needed. ++ fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), TMPVAR))); ++ // ^^^^^^^^^ here we immediately strdup() the value, so the later call ++ // to evaluate() potentially recursing into another awk_printf() can't ++ // mangle the value. ++ ++ b = NULL; + i = 0; +- while (*f) { ++ while (*f) { /* "print one format spec" loop */ ++ char *s; ++ char c; ++ char sv; ++ var *arg; ++ size_t slen; ++ + s = f; + while (*f && (*f != '%' || *++f == '%')) + f++; +@@ -2137,38 +2353,68 @@ static char *awk_printf(node *n) + syntax_error("%*x formats are not supported"); + f++; + } +- +- incr = (f - s) + MAXVARFMT; +- b = qrealloc(b, incr + i, &bsize); + c = *f; +- if (c != '\0') +- f++; +- c1 = *f; ++ if (!c) { ++ /* Tail of fmt with no percent chars, ++ * or "....%" (percent seen, but no format specifier char found) ++ */ ++ slen = strlen(s); ++ goto tail; ++ } ++ sv = *++f; + *f = '\0'; +- arg = evaluate(nextarg(&n), v); +- +- j = i; +- if (c == 'c' || !c) { +- i += sprintf(b+i, s, is_numeric(arg) ? +- (char)getvar_i(arg) : *getvar_s(arg)); +- } else if (c == 's') { +- s1 = getvar_s(arg); +- b = qrealloc(b, incr+i+strlen(s1), &bsize); +- i += sprintf(b+i, s, s1); ++ arg = evaluate(nextarg(&n), TMPVAR); ++ ++ /* Result can be arbitrarily long. Example: ++ * printf "%99999s", "BOOM" ++ */ ++ if (c == 'c') { ++ char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg); ++ char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */); ++ slen = strlen(r); ++ if (cc == '\0') /* if cc is NUL, re-format the string with it */ ++ sprintf(r, s, cc); ++ s = r; + } else { +- i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE); ++ if (c == 's') { ++ s = xasprintf(s, getvar_s(arg)); ++ } else { ++ double d = getvar_i(arg); ++ if (strchr("diouxX", c)) { ++//TODO: make it wider here (%x -> %llx etc)? ++ s = xasprintf(s, (int)d); ++ } else if (strchr("eEfFgGaA", c)) { ++ s = xasprintf(s, d); ++ } else { ++ syntax_error(EMSG_INV_FMT); ++ } ++ } ++ slen = strlen(s); + } +- *f = c1; ++ *f = sv; + +- /* if there was an error while sprintf, return value is negative */ +- if (i < j) +- i = j; ++ if (i == 0) { ++ b = s; ++ i = slen; ++ continue; ++ } ++ tail: ++ b = xrealloc(b, i + slen + 1); ++ strcpy(b + i, s); ++ i += slen; ++ if (!c) /* tail? */ ++ break; ++ free(s); + } + + free(fmt); +- nvfree(v); +- b = xrealloc(b, i + 1); +- b[i] = '\0'; ++ //nvfree(tmpvar, 1); ++#undef TMPVAR ++ ++#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS ++ if (len) ++ *len = i; ++#endif + return b; + } + +@@ -2298,33 +2544,59 @@ static NOINLINE int do_mktime(const char *ds) + return mktime(&then); + } + ++/* Reduce stack usage in exec_builtin() by keeping match() code separate */ ++static NOINLINE var *do_match(node *an1, const char *as0) ++{ ++ regmatch_t pmatch[1]; ++ regex_t sreg, *re; ++ int n, start, len; ++ ++ re = as_regex(an1, &sreg); ++ n = regexec(re, as0, 1, pmatch, 0); ++ if (re == &sreg) ++ regfree(re); ++ start = 0; ++ len = -1; ++ if (n == 0) { ++ start = pmatch[0].rm_so + 1; ++ len = pmatch[0].rm_eo - pmatch[0].rm_so; ++ } ++ setvar_i(newvar("RLENGTH"), len); ++ return setvar_i(newvar("RSTART"), start); ++} ++ ++/* Reduce stack usage in evaluate() by keeping builtins' code separate */ + static NOINLINE var *exec_builtin(node *op, var *res) + { + #define tspl (G.exec_builtin__tspl) + +- var *tv; ++ var *tmpvars; + node *an[4]; + var *av[4]; + const char *as[4]; +- regmatch_t pmatch[2]; +- regex_t sreg, *re; + node *spl; + uint32_t isr, info; + int nargs; + time_t tt; + int i, l, ll, n; + +- tv = nvalloc(4); ++ tmpvars = nvalloc(4); ++#define TMPVAR0 (tmpvars) ++#define TMPVAR1 (tmpvars + 1) ++#define TMPVAR2 (tmpvars + 2) ++#define TMPVAR3 (tmpvars + 3) ++#define TMPVAR(i) (tmpvars + (i)) + isr = info = op->info; + op = op->l.n; + + av[2] = av[3] = NULL; + for (i = 0; i < 4 && op; i++) { + an[i] = nextarg(&op); +- if (isr & 0x09000000) +- av[i] = evaluate(an[i], &tv[i]); +- if (isr & 0x08000000) +- as[i] = getvar_s(av[i]); ++ if (isr & 0x09000000) { ++ av[i] = evaluate(an[i], TMPVAR(i)); ++ if (isr & 0x08000000) ++ as[i] = getvar_s(av[i]); ++ } + isr >>= 1; + } + +@@ -2346,8 +2618,8 @@ static NOINLINE var *exec_builtin(node *op, var *res) + char *s, *s1; + + if (nargs > 2) { +- spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ? +- an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl); ++ spl = (an[2]->info == TI_REGEXP) ? an[2] ++ : mk_splitter(getvar_s(evaluate(an[2], TMPVAR2)), &tspl); + } else { + spl = &fsplitter.n; + } +@@ -2461,20 +2733,7 @@ static NOINLINE var *exec_builtin(node *op, var *res) + break; + + case B_ma: +- re = as_regex(an[1], &sreg); +- n = regexec(re, as[0], 1, pmatch, 0); +- if (n == 0) { +- pmatch[0].rm_so++; +- pmatch[0].rm_eo++; +- } else { +- pmatch[0].rm_so = 0; +- pmatch[0].rm_eo = -1; +- } +- setvar_i(newvar("RSTART"), pmatch[0].rm_so); +- setvar_i(newvar("RLENGTH"), pmatch[0].rm_eo - pmatch[0].rm_so); +- setvar_i(res, pmatch[0].rm_so); +- if (re == &sreg) +- regfree(re); ++ res = do_match(an[1], as[0]); + break; + + case B_ge: +@@ -2490,14 +2749,79 @@ static NOINLINE var *exec_builtin(node *op, var *res) + break; + } + +- nvfree(tv); ++ nvfree(tmpvars, 4); ++#undef TMPVAR0 ++#undef TMPVAR1 ++#undef TMPVAR2 ++#undef TMPVAR3 ++#undef TMPVAR ++ + return res; + #undef tspl + } + ++/* if expr looks like "var=value", perform assignment and return 1, ++ * otherwise return 0 */ ++static int is_assignment(const char *expr) ++{ ++ char *exprc, *val; ++ ++ val = (char*)endofname(expr); ++ if (val == (char*)expr || *val != '=') { ++ return FALSE; ++ } ++ ++ exprc = xstrdup(expr); ++ val = exprc + (val - expr); ++ *val++ = '\0'; ++ ++ unescape_string_in_place(val); ++ setvar_u(newvar(exprc), val); ++ free(exprc); ++ return TRUE; ++} ++ ++/* switch to next input file */ ++static rstream *next_input_file(void) ++{ ++#define rsm (G.next_input_file__rsm) ++#define files_happen (G.next_input_file__files_happen) ++ ++ const char *fname, *ind; ++ ++ if (rsm.F) ++ fclose(rsm.F); ++ rsm.F = NULL; ++ rsm.pos = rsm.adv = 0; ++ ++ for (;;) { ++ if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) { ++ if (files_happen) ++ return NULL; ++ fname = "-"; ++ rsm.F = stdin; ++ break; ++ } ++ ind = getvar_s(incvar(intvar[ARGIND])); ++ fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind)); ++ if (fname && *fname && !is_assignment(fname)) { ++ rsm.F = xfopen_stdin(fname); ++ break; ++ } ++ } ++ ++ files_happen = TRUE; ++ setvar_s(intvar[FILENAME], fname); ++ return &rsm; ++#undef rsm ++#undef files_happen ++} ++ + /* + * Evaluate node - the heart of the program. Supplied with subtree +- * and place where to store result. returns ptr to result. ++ * and "res" variable to assign the result to if we evaluate an expression. ++ * If node refers to e.g. a variable or a field, no assignment happens. ++ * Return ptr to the result (which may or may not be the "res" variable!) + */ + #define XC(n) ((n) >> 8) + +@@ -2509,14 +2833,16 @@ static var *evaluate(node *op, var *res) + #define seed (G.evaluate__seed) + #define sreg (G.evaluate__sreg) + +- var *v1; ++ var *tmpvars; + + if (!op) + return setvar_s(res, NULL); + + debug_printf_eval("entered %s()\n", __func__); + +- v1 = nvalloc(2); ++ tmpvars = nvalloc(2); ++#define TMPVAR0 (tmpvars) ++#define TMPVAR1 (tmpvars + 1) + + while (op) { + struct { +@@ -2538,48 +2864,35 @@ static var *evaluate(node *op, var *res) + op1 = op->l.n; + debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn); + +- /* "delete" is special: +- * "delete array[var--]" must evaluate index expr only once, +- * must not evaluate it in "execute inevitable things" part. +- */ +- if (XC(opinfo & OPCLSMASK) == XC(OC_DELETE)) { +- uint32_t info = op1->info & OPCLSMASK; +- var *v; +- +- debug_printf_eval("DELETE\n"); +- if (info == OC_VAR) { +- v = op1->l.v; +- } else if (info == OC_FNARG) { +- v = &fnargs[op1->l.aidx]; +- } else { +- syntax_error(EMSG_NOT_ARRAY); ++ /* execute inevitable things */ ++ if (opinfo & OF_RES1) { ++ if ((opinfo & OF_REQUIRED) && !op1) ++ syntax_error(EMSG_TOO_FEW_ARGS); ++ L.v = evaluate(op1, TMPVAR0); ++ if (opinfo & OF_STR1) { ++ L.s = getvar_s(L.v); ++ debug_printf_eval("L.s:'%s'\n", L.s); + } +- if (op1->r.n) { /* array ref? */ +- const char *s; +- s = getvar_s(evaluate(op1->r.n, v1)); +- hash_remove(iamarray(v), s); +- } else { +- clear_array(iamarray(v)); ++ if (opinfo & OF_NUM1) { ++ L_d = getvar_i(L.v); ++ debug_printf_eval("L_d:%f\n", L_d); + } +- goto next; +- } +- +- /* execute inevitable things */ +- if (opinfo & OF_RES1) +- L.v = evaluate(op1, v1); +- if (opinfo & OF_RES2) +- R.v = evaluate(op->r.n, v1+1); +- if (opinfo & OF_STR1) { +- L.s = getvar_s(L.v); +- debug_printf_eval("L.s:'%s'\n", L.s); + } +- if (opinfo & OF_STR2) { +- R.s = getvar_s(R.v); +- debug_printf_eval("R.s:'%s'\n", R.s); +- } +- if (opinfo & OF_NUM1) { +- L_d = getvar_i(L.v); +- debug_printf_eval("L_d:%f\n", L_d); ++ /* NB: Must get string/numeric values of L (done above) ++ * _before_ evaluate()'ing R.v: if both L and R are $NNNs, ++ * and right one is large, then L.v points to Fields[NNN1], ++ * second evaluate() reallocates and moves (!) Fields[], ++ * R.v points to Fields[NNN2] but L.v now points to freed mem! ++ * (Seen trying to evaluate "$444 $44444") ++ */ ++ if (opinfo & OF_RES2) { ++ R.v = evaluate(op->r.n, TMPVAR1); ++ //TODO: L.v may be invalid now, set L.v to NULL to catch bugs? ++ //L.v = NULL; ++ if (opinfo & OF_STR2) { ++ R.s = getvar_s(R.v); ++ debug_printf_eval("R.s:'%s'\n", R.s); ++ } + } + + debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK)); +@@ -2589,7 +2902,8 @@ static var *evaluate(node *op, var *res) + + /* test pattern */ + case XC( OC_TEST ): +- if ((op1->info & OPCLSMASK) == OC_COMMA) { ++ debug_printf_eval("TEST\n"); ++ if (op1->info == TI_COMMA) { + /* it's range pattern */ + if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) { + op->info |= OF_CHECKED; +@@ -2606,25 +2920,32 @@ static var *evaluate(node *op, var *res) + + /* just evaluate an expression, also used as unconditional jump */ + case XC( OC_EXEC ): ++ debug_printf_eval("EXEC\n"); + break; + + /* branch, used in if-else and various loops */ + case XC( OC_BR ): ++ debug_printf_eval("BR\n"); + op = istrue(L.v) ? op->a.n : op->r.n; + break; + + /* initialize for-in loop */ + case XC( OC_WALKINIT ): ++ debug_printf_eval("WALKINIT\n"); + hashwalk_init(L.v, iamarray(R.v)); + break; + + /* get next array item */ + case XC( OC_WALKNEXT ): ++ debug_printf_eval("WALKNEXT\n"); + op = hashwalk_next(L.v) ? op->a.n : op->r.n; + break; + + case XC( OC_PRINT ): +- case XC( OC_PRINTF ): { ++ debug_printf_eval("PRINT /\n"); ++ case XC( OC_PRINTF ): ++ debug_printf_eval("PRINTF\n"); ++ { + FILE *F = stdout; + + if (op->r.n) { +@@ -2642,55 +2963,94 @@ static var *evaluate(node *op, var *res) + F = rsm->F; + } + ++ /* Can't just check 'opinfo == OC_PRINT' here, parser ORs ++ * additional bits to opinfos of print/printf with redirects ++ */ + if ((opinfo & OPCLSMASK) == OC_PRINT) { + if (!op1) { + fputs(getvar_s(intvar[F0]), F); + } else { +- while (op1) { +- var *v = evaluate(nextarg(&op1), v1); ++ for (;;) { ++ var *v = evaluate(nextarg(&op1), TMPVAR0); + if (v->type & VF_NUMBER) { +- fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[OFMT]), +- getvar_i(v), TRUE); ++ fmt_num(getvar_s(intvar[OFMT]), ++ getvar_i(v)); + fputs(g_buf, F); + } else { + fputs(getvar_s(v), F); + } +- +- if (op1) +- fputs(getvar_s(intvar[OFS]), F); ++ if (!op1) ++ break; ++ fputs(getvar_s(intvar[OFS]), F); + } + } + fputs(getvar_s(intvar[ORS]), F); +- +- } else { /* OC_PRINTF */ +- char *s = awk_printf(op1); ++ } else { /* PRINTF */ ++ IF_FEATURE_AWK_GNU_EXTENSIONS(size_t len;) ++ char *s = awk_printf(op1, &len); ++#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS ++ fwrite(s, len, 1, F); ++#else + fputs(s, F); ++#endif + free(s); + } + fflush(F); + break; + } + +- /* case XC( OC_DELETE ): - moved to happen before arg evaluation */ ++ case XC( OC_DELETE ): ++ debug_printf_eval("DELETE\n"); ++ { ++ /* "delete" is special: ++ * "delete array[var--]" must evaluate index expr only once. ++ */ ++ uint32_t info = op1->info & OPCLSMASK; ++ var *v; ++ ++ if (info == OC_VAR) { ++ v = op1->l.v; ++ } else if (info == OC_FNARG) { ++ v = &fnargs[op1->l.aidx]; ++ } else { ++ syntax_error(EMSG_NOT_ARRAY); ++ } ++ if (op1->r.n) { /* array ref? */ ++ const char *s; ++ s = getvar_s(evaluate(op1->r.n, TMPVAR0)); ++ hash_remove(iamarray(v), s); ++ } else { ++ clear_array(iamarray(v)); ++ } ++ break; ++ } + + case XC( OC_NEWSOURCE ): ++ debug_printf_eval("NEWSOURCE\n"); + g_progname = op->l.new_progname; + break; + + case XC( OC_RETURN ): ++ debug_printf_eval("RETURN\n"); + copyvar(res, L.v); + break; + + case XC( OC_NEXTFILE ): ++ debug_printf_eval("NEXTFILE\n"); + nextfile = TRUE; + case XC( OC_NEXT ): ++ debug_printf_eval("NEXT\n"); + nextrec = TRUE; + case XC( OC_DONE ): ++ debug_printf_eval("DONE\n"); + clrvar(res); + break; + + case XC( OC_EXIT ): +- awk_exit(L_d); ++ debug_printf_eval("EXIT\n"); ++ if (op1) ++ G.exitcode = (int)L_d; ++ awk_exit(); + + /* -- recursive node type -- */ + +@@ -2709,15 +3069,18 @@ static var *evaluate(node *op, var *res) + break; + + case XC( OC_IN ): ++ debug_printf_eval("IN\n"); + setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0); + break; + + case XC( OC_REGEXP ): ++ debug_printf_eval("REGEXP\n"); + op1 = op; + L.s = getvar_s(intvar[F0]); + goto re_cont; + + case XC( OC_MATCH ): ++ debug_printf_eval("MATCH\n"); + op1 = op->r.n; + re_cont: + { +@@ -2732,61 +3095,80 @@ static var *evaluate(node *op, var *res) + case XC( OC_MOVE ): + debug_printf_eval("MOVE\n"); + /* if source is a temporary string, jusk relink it to dest */ +-//Disabled: if R.v is numeric but happens to have cached R.v->string, +-//then L.v ends up being a string, which is wrong +-// if (R.v == v1+1 && R.v->string) { +-// res = setvar_p(L.v, R.v->string); +-// R.v->string = NULL; +-// } else { ++ if (R.v == TMPVAR1 ++ && !(R.v->type & VF_NUMBER) ++ /* Why check !NUMBER? if R.v is a number but has cached R.v->string, ++ * L.v ends up a string, which is wrong */ ++ /*&& R.v->string - always not NULL (right?) */ ++ ) { ++ res = setvar_p(L.v, R.v->string); /* avoids strdup */ ++ R.v->string = NULL; ++ } else { + res = copyvar(L.v, R.v); +-// } ++ } + break; + + case XC( OC_TERNARY ): +- if ((op->r.n->info & OPCLSMASK) != OC_COLON) ++ debug_printf_eval("TERNARY\n"); ++ if (op->r.n->info != TI_COLON) + syntax_error(EMSG_POSSIBLE_ERROR); + res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res); + break; + + case XC( OC_FUNC ): { +- var *vbeg, *v; ++ var *argvars, *sv_fnargs; + const char *sv_progname; ++ int nargs, i; + +- /* The body might be empty, still has to eval the args */ +- if (!op->r.n->info && !op->r.f->body.first) ++ debug_printf_eval("FUNC\n"); ++ ++ if (!op->r.f->defined) + syntax_error(EMSG_UNDEF_FUNC); + +- vbeg = v = nvalloc(op->r.f->nargs + 1); ++ /* The body might be empty, still has to eval the args */ ++ nargs = op->r.f->nargs; ++ argvars = nvalloc(nargs); ++ i = 0; + while (op1) { +- var *arg = evaluate(nextarg(&op1), v1); +- copyvar(v, arg); +- v->type |= VF_CHILD; +- v->x.parent = arg; +- if (++v - vbeg >= op->r.f->nargs) +- break; ++ var *arg = evaluate(nextarg(&op1), TMPVAR0); ++ if (i == nargs) { ++ /* call with more arguments than function takes. ++ * (gawk warns: "warning: function 'f' called with more arguments than declared"). ++ * They are still evaluated, but discarded: */ ++ clrvar(arg); ++ continue; ++ } ++ copyvar(&argvars[i], arg); ++ argvars[i].type |= VF_CHILD; ++ argvars[i].x.parent = arg; ++ i++; + } + +- v = fnargs; +- fnargs = vbeg; ++ sv_fnargs = fnargs; + sv_progname = g_progname; + ++ fnargs = argvars; + res = evaluate(op->r.f->body.first, res); ++ nvfree(argvars, nargs); + + g_progname = sv_progname; +- nvfree(fnargs); +- fnargs = v; ++ fnargs = sv_fnargs; + + break; + } + + case XC( OC_GETLINE ): +- case XC( OC_PGETLINE ): { ++ debug_printf_eval("GETLINE /\n"); ++ case XC( OC_PGETLINE ): ++ debug_printf_eval("PGETLINE\n"); ++ { + rstream *rsm; + int i; + + if (op1) { + rsm = newfile(L.s); + if (!rsm->F) { ++ /* NB: can't use "opinfo == TI_PGETLINE", would break "cmd" | getline */ + if ((opinfo & OPCLSMASK) == OC_PGETLINE) { + rsm->F = popen(L.s, "r"); + rsm->is_pipe = TRUE; +@@ -2821,16 +3203,34 @@ static var *evaluate(node *op, var *res) + /* simple builtins */ + case XC( OC_FBLTIN ): { + double R_d = R_d; /* for compiler */ ++ debug_printf_eval("FBLTIN\n"); ++ ++ if (op1 && op1->info == TI_COMMA) ++ /* Simple builtins take one arg maximum */ ++ syntax_error("Too many arguments"); + + switch (opn) { + case F_in: + R_d = (long long)L_d; + break; + +- case F_rn: +- R_d = (double)rand() / (double)RAND_MAX; ++ case F_rn: /*rand*/ ++ if (op1) ++ syntax_error("Too many arguments"); ++ { ++#if RAND_MAX >= 0x7fffffff ++ uint32_t u = ((uint32_t)rand() << 16) ^ rand(); ++ uint64_t v = ((uint64_t)rand() << 32) | u; ++ /* the above shift+or is optimized out on 32-bit arches */ ++# if RAND_MAX > 0x7fffffff ++ v &= 0x7fffffffffffffffULL; ++# endif ++ R_d = (double)v / 0x8000000000000000ULL; ++#else ++# error Not implemented for this value of RAND_MAX ++#endif + break; +- ++ } + case F_co: + if (ENABLE_FEATURE_AWK_LIBM) { + R_d = cos(L_d); +@@ -2870,7 +3270,9 @@ static var *evaluate(node *op, var *res) + srand(seed); + break; + +- case F_ti: ++ case F_ti: /*systime*/ ++ if (op1) ++ syntax_error("Too many arguments"); + R_d = time(NULL); + break; + +@@ -2909,7 +3311,7 @@ static var *evaluate(node *op, var *res) + rstream *rsm; + int err = 0; + rsm = (rstream *)hash_search(fdhash, L.s); +- debug_printf_eval("OC_FBLTIN F_cl rsm:%p\n", rsm); ++ debug_printf_eval("OC_FBLTIN close: op1:%p s:'%s' rsm:%p\n", op1, L.s, rsm); + if (rsm) { + debug_printf_eval("OC_FBLTIN F_cl " + "rsm->is_pipe:%d, ->F:%p\n", +@@ -2920,6 +3322,11 @@ static var *evaluate(node *op, var *res) + */ + if (rsm->F) + err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F); ++//TODO: fix this case: ++// $ awk 'BEGIN { print close(""); print ERRNO }' ++// -1 ++// close of redirection that was never opened ++// (we print 0, 0) + free(rsm->buffer); + hash_remove(fdhash, L.s); + } +@@ -2934,14 +3341,18 @@ static var *evaluate(node *op, var *res) + } + + case XC( OC_BUILTIN ): ++ debug_printf_eval("BUILTIN\n"); + res = exec_builtin(op, res); + break; + + case XC( OC_SPRINTF ): +- setvar_p(res, awk_printf(op1)); ++ debug_printf_eval("SPRINTF\n"); ++ setvar_p(res, awk_printf(op1, NULL)); + break; + +- case XC( OC_UNARY ): { ++ case XC( OC_UNARY ): ++ debug_printf_eval("UNARY\n"); ++ { + double Ld, R_d; + + Ld = R_d = getvar_i(R.v); +@@ -2971,7 +3382,9 @@ static var *evaluate(node *op, var *res) + break; + } + +- case XC( OC_FIELD ): { ++ case XC( OC_FIELD ): ++ debug_printf_eval("FIELD\n"); ++ { + int i = (int)getvar_i(R.v); + if (i < 0) + syntax_error(EMSG_NEGATIVE_FIELD); +@@ -2988,26 +3401,33 @@ static var *evaluate(node *op, var *res) + + /* concatenation (" ") and index joining (",") */ + case XC( OC_CONCAT ): ++ debug_printf_eval("CONCAT /\n"); + case XC( OC_COMMA ): { + const char *sep = ""; +- if ((opinfo & OPCLSMASK) == OC_COMMA) ++ debug_printf_eval("COMMA\n"); ++ if (opinfo == TI_COMMA) + sep = getvar_s(intvar[SUBSEP]); + setvar_p(res, xasprintf("%s%s%s", L.s, sep, R.s)); + break; + } + + case XC( OC_LAND ): ++ debug_printf_eval("LAND\n"); + setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0); + break; + + case XC( OC_LOR ): ++ debug_printf_eval("LOR\n"); + setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n)); + break; + + case XC( OC_BINARY ): +- case XC( OC_REPLACE ): { ++ debug_printf_eval("BINARY /\n"); ++ case XC( OC_REPLACE ): ++ debug_printf_eval("REPLACE\n"); ++ { + double R_d = getvar_i(R.v); +- debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn); ++ debug_printf_eval("R_d:%f opn:%c\n", R_d, opn); + switch (opn) { + case '+': + L_d += R_d; +@@ -3043,6 +3463,7 @@ static var *evaluate(node *op, var *res) + case XC( OC_COMPARE ): { + int i = i; /* for compiler */ + double Ld; ++ debug_printf_eval("COMPARE\n"); + + if (is_numeric(L.v) && is_numeric(R.v)) { + Ld = getvar_i(L.v) - getvar_i(R.v); +@@ -3069,7 +3490,7 @@ static var *evaluate(node *op, var *res) + default: + syntax_error(EMSG_POSSIBLE_ERROR); + } /* switch */ +- next: ++ + if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) + op = op->a.n; + if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS) +@@ -3078,7 +3499,10 @@ static var *evaluate(node *op, var *res) + break; + } /* while (op) */ + +- nvfree(v1); ++ nvfree(tmpvars, 2); ++#undef TMPVAR0 ++#undef TMPVAR1 ++ + debug_printf_eval("returning from %s(): %p\n", __func__, res); + return res; + #undef fnargs +@@ -3086,25 +3510,21 @@ static var *evaluate(node *op, var *res) + #undef sreg + } + +- + /* -------- main & co. -------- */ + +-static int awk_exit(int r) ++static int awk_exit(void) + { +- var tv; + unsigned i; +- hash_item *hi; +- +- zero_out_var(&tv); + + if (!exiting) { + exiting = TRUE; + nextrec = FALSE; +- evaluate(endseq.first, &tv); ++ evaluate(endseq.first, &G.exit__tmpvar); + } + + /* waiting for children */ + for (i = 0; i < fdhash->csize; i++) { ++ hash_item *hi; + hi = fdhash->items[i]; + while (hi) { + if (hi->data.rs.F && hi->data.rs.is_pipe) +@@ -3113,65 +3533,7 @@ static int awk_exit(int r) + } + } + +- exit(r); +-} +- +-/* if expr looks like "var=value", perform assignment and return 1, +- * otherwise return 0 */ +-static int is_assignment(const char *expr) +-{ +- char *exprc, *val; +- +- if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { +- return FALSE; +- } +- +- exprc = xstrdup(expr); +- val = exprc + (val - expr); +- *val++ = '\0'; +- +- unescape_string_in_place(val); +- setvar_u(newvar(exprc), val); +- free(exprc); +- return TRUE; +-} +- +-/* switch to next input file */ +-static rstream *next_input_file(void) +-{ +-#define rsm (G.next_input_file__rsm) +-#define files_happen (G.next_input_file__files_happen) +- +- FILE *F; +- const char *fname, *ind; +- +- if (rsm.F) +- fclose(rsm.F); +- rsm.F = NULL; +- rsm.pos = rsm.adv = 0; +- +- for (;;) { +- if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) { +- if (files_happen) +- return NULL; +- fname = "-"; +- F = stdin; +- break; +- } +- ind = getvar_s(incvar(intvar[ARGIND])); +- fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind)); +- if (fname && *fname && !is_assignment(fname)) { +- F = xfopen_stdin(fname); +- break; +- } +- } +- +- files_happen = TRUE; +- setvar_s(intvar[FILENAME], fname); +- rsm.F = F; +- return &rsm; +-#undef rsm +-#undef files_happen ++ exit(G.exitcode); + } + + int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +@@ -3184,12 +3546,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS + llist_t *list_e = NULL; + #endif +- int i, j; +- var *v; +- var tv; +- char **envp; +- char *vnames = (char *)vNames; /* cheat */ +- char *vvalues = (char *)vValues; ++ int i; + + INIT_G(); + +@@ -3198,48 +3555,43 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + if (ENABLE_LOCALE_SUPPORT) + setlocale(LC_NUMERIC, "C"); + +- zero_out_var(&tv); +- +- /* allocate global buffer */ +- g_buf = xmalloc(MAXVARFMT + 1); +- +- vhash = hash_init(); +- ahash = hash_init(); +- fdhash = hash_init(); +- fnhash = hash_init(); +- + /* initialize variables */ +- for (i = 0; *vnames; i++) { +- intvar[i] = v = newvar(nextword(&vnames)); +- if (*vvalues != '\377') +- setvar_s(v, nextword(&vvalues)); +- else +- setvar_i(v, 0); +- +- if (*vnames == '*') { +- v->type |= VF_SPECIAL; +- vnames++; ++ vhash = hash_init(); ++ { ++ char *vnames = (char *)vNames; /* cheat */ ++ char *vvalues = (char *)vValues; ++ for (i = 0; *vnames; i++) { ++ var *v; ++ intvar[i] = v = newvar(nextword(&vnames)); ++ if (*vvalues != '\377') ++ setvar_s(v, nextword(&vvalues)); ++ else ++ setvar_i(v, 0); ++ ++ if (*vnames == '*') { ++ v->type |= VF_SPECIAL; ++ vnames++; ++ } + } + } + + handle_special(intvar[FS]); + handle_special(intvar[RS]); + +- newfile("/dev/stdin")->F = stdin; +- newfile("/dev/stdout")->F = stdout; +- newfile("/dev/stderr")->F = stderr; +- + /* Huh, people report that sometimes environ is NULL. Oh well. */ +- if (environ) for (envp = environ; *envp; envp++) { +- /* environ is writable, thus we don't strdup it needlessly */ +- char *s = *envp; +- char *s1 = strchr(s, '='); +- if (s1) { +- *s1 = '\0'; +- /* Both findvar and setvar_u take const char* +- * as 2nd arg -> environment is not trashed */ +- setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1); +- *s1 = '='; ++ if (environ) { ++ char **envp; ++ for (envp = environ; *envp; envp++) { ++ /* environ is writable, thus we don't strdup it needlessly */ ++ char *s = *envp; ++ char *s1 = strchr(s, '='); ++ if (s1) { ++ *s1 = '\0'; ++ /* Both findvar and setvar_u take const char* ++ * as 2nd arg -> environment is not trashed */ ++ setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1); ++ *s1 = '='; ++ } + } + } + opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL); +@@ -3255,20 +3607,19 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + if (!is_assignment(llist_pop(&list_v))) + bb_show_usage(); + } ++ ++ /* Parse all supplied programs */ ++ fnhash = hash_init(); ++ ahash = hash_init(); + while (list_f) { +- char *s = NULL; +- FILE *from_file; ++ int fd; ++ char *s; + + g_progname = llist_pop(&list_f); +- from_file = xfopen_stdin(g_progname); +- /* one byte is reserved for some trick in next_token */ +- for (i = j = 1; j > 0; i += j) { +- s = xrealloc(s, i + 4096); +- j = fread(s + i, 1, 4094, from_file); +- } +- s[i] = '\0'; +- fclose(from_file); +- parse_program(s + 1); ++ fd = xopen_stdin(g_progname); ++ s = xmalloc_read(fd, NULL); /* it's NUL-terminated */ ++ close(fd); ++ parse_program(s); + free(s); + } + g_progname = "cmd. line"; +@@ -3277,11 +3628,23 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + parse_program(llist_pop(&list_e)); + } + #endif ++//FIXME: preserve order of -e and -f ++//TODO: implement -i LIBRARY and -E FILE too, they are easy-ish + if (!(opt & (OPT_f | OPT_e))) { + if (!*argv) + bb_show_usage(); + parse_program(*argv++); + } ++ /* Free unused parse structures */ ++ //hash_free(fnhash); // ~250 bytes when empty, used only for function names ++ //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs ++ // (IOW: hash_clear() assumes it's a hash of variables. fnhash is not). ++ free(fnhash->items); ++ free(fnhash); ++ fnhash = NULL; // debug ++ //hash_free(ahash); // empty after parsing, will reuse as fdhash instead of freeing ++ ++ /* Parsing done, on to executing */ + + /* fill in ARGV array */ + setari_u(intvar[ARGV], 0, "awk"); +@@ -3290,9 +3653,14 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + setari_u(intvar[ARGV], ++i, *argv++); + setvar_i(intvar[ARGC], i + 1); + +- evaluate(beginseq.first, &tv); ++ //fdhash = ahash; // done via define ++ newfile("/dev/stdin")->F = stdin; ++ newfile("/dev/stdout")->F = stdout; ++ newfile("/dev/stderr")->F = stderr; ++ ++ evaluate(beginseq.first, &G.main__tmpvar); + if (!mainseq.first && !endseq.first) +- awk_exit(EXIT_SUCCESS); ++ awk_exit(); + + /* input file could already be opened in BEGIN block */ + if (!iF) +@@ -3307,7 +3675,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + nextrec = FALSE; + incvar(intvar[NR]); + incvar(intvar[FNR]); +- evaluate(mainseq.first, &tv); ++ evaluate(mainseq.first, &G.main__tmpvar); + + if (nextfile) + break; +@@ -3319,6 +3687,6 @@ int awk_main(int argc UNUSED_PARAM, char **argv) + iF = next_input_file(); + } + +- awk_exit(EXIT_SUCCESS); ++ awk_exit(); + /*return 0;*/ + } +diff --git a/testsuite/awk.tests b/testsuite/awk.tests +index a7a533ba0..87f6b5007 100755 +--- a/testsuite/awk.tests ++++ b/testsuite/awk.tests +@@ -85,7 +85,8 @@ testing "awk floating const with leading zeroes" \ + "" "\n" + + # long field seps requiring regex +-testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ ++testing "awk long field sep" \ ++ "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ + "2 0 \n3 0 \n4 0 \n5 0 \n" \ + "" \ + "a--\na--b--\na--b--c--\na--b--c--d--" +@@ -317,6 +318,26 @@ testing "awk length()" \ + "3\n3\n3\n3\n" \ + "" "qwe" + ++testing "awk print length, 1" \ ++ "awk '{ print length, 1 }'" \ ++ "0 1\n" \ ++ "" "\n" ++ ++testing "awk print length 1" \ ++ "awk '{ print length 1 }'" \ ++ "01\n" \ ++ "" "\n" ++ ++testing "awk length == 0" \ ++ "awk 'length == 0 { print \"foo\" }'" \ ++ "foo\n" \ ++ "" "\n" ++ ++testing "awk if (length == 0)" \ ++ "awk '{ if (length == 0) { print \"bar\" } }'" \ ++ "bar\n" \ ++ "" "\n" ++ + testing "awk -f and ARGC" \ + "awk -f - input" \ + "re\n2\n" \ +@@ -369,5 +390,13 @@ testing 'awk negative field access' \ + '' \ + 'anything' + ++# was misinterpreted as (("str"++) i) instead of ("str" (++i)) ++# (and was executed: "str"++ is "0", thus concatenating "0" and "1"): ++testing 'awk do not allow "str"++' \ ++ 'awk -v i=1 "BEGIN {print \"str\" ++i}"' \ ++ "str2\n" \ ++ '' \ ++ 'anything' ++ + + exit $FAILCOUNT diff --git a/main/busybox/traceroute-opt-x.patch b/main/busybox/traceroute-opt-x.patch new file mode 100644 index 00000000000..eea17891006 --- /dev/null +++ b/main/busybox/traceroute-opt-x.patch @@ -0,0 +1,26 @@ +From 89358a7131d3e75c74af834bb117b4fad7914983 Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko <vda.linux@googlemail.com> +Date: Tue, 2 Feb 2021 13:48:21 +0100 +Subject: traceroute: fix option parsing + +Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> +--- + networking/traceroute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/networking/traceroute.c b/networking/traceroute.c +index 3f1a9ab46..29f5e480b 100644 +--- a/networking/traceroute.c ++++ b/networking/traceroute.c +@@ -896,7 +896,7 @@ traceroute_init(int op, char **argv) + + op |= getopt32(argv, "^" + OPT_STRING +- "\0" "-1:x-x" /* minimum 1 arg */ ++ "\0" "-1" /* minimum 1 arg */ + , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str + , &source, &waittime_str, &pausemsecs_str, &first_ttl_str + ); +-- +cgit v1.2.3 + diff --git a/main/ca-certificates/APKBUILD b/main/ca-certificates/APKBUILD index 4b9e93adaae..38e0b40206e 100644 --- a/main/ca-certificates/APKBUILD +++ b/main/ca-certificates/APKBUILD @@ -1,8 +1,8 @@ # Contributor: Sören Tempel <soeren+alpine@soeren-tempel.net> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=ca-certificates -pkgver=20191127 -pkgrel=4 +pkgver=20220614 +pkgrel=0 pkgdesc="Common CA certificates PEM files from Mozilla" url="https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/" arch="all" @@ -15,16 +15,10 @@ replaces="libcrypto1.0 openssl openssl1.0" options="!fhs !check" triggers="ca-certificates.trigger=/usr/share/ca-certificates:/usr/local/share/ca-certificates:/etc/ssl/certs:/etc/ca-certificates/update.d" install="$pkgname.post-deinstall" -source="https://gitlab.alpinelinux.org/alpine/ca-certificates/-/archive/$pkgver/ca-certificates-$pkgver.tar.bz2 - 0001-update-ca-fix-compiler-warning.patch - 0002-replace-python-script-with-perl-script.patch - 0003-update-ca-insert-newline-between-certs.patch - " +source="https://gitlab.alpinelinux.org/alpine/ca-certificates/-/archive/$pkgver/ca-certificates-$pkgver.tar.bz2" build() { make - # remove expired cert (https://gitlab.alpinelinux.org/alpine/aports/issues/11607) - rm AddTrust_External_Root.crt } package() { @@ -69,7 +63,6 @@ bundle() { "$subpkgdir"/etc/ssl/cert.pem } -sha512sums="05e3a11efd80ea88eb81774e084febe4b8d1fa48f01f49e5ed3d469e10a2769260a264faed42ea3a0b725659cda1cc4a67ce5575fe04cdff9dc1c08207911c9b ca-certificates-20191127.tar.bz2 -aafe6d9047380fc403792fbf27146dc9c0532ef401e6eb9bd8b533c110f902cad0a66701cf3563ad625d07ae54619e9f2f3091ec14772b92e178dbed142ecd97 0001-update-ca-fix-compiler-warning.patch -4d9c71b9ea0596f5efaa188f244b7ab587f96c218bb6fed01f11e34c553909f65bbe660156f8300be9511ae50614661c5dcd3b493ac146a8e888f62fc52bd9d4 0002-replace-python-script-with-perl-script.patch -051b5d78916ee7389dfbd4e8871aab720415bd6e9ee0313dba770fc40ee7c68ac67d7918f2503458a3218e3bfc10691b5e379b65269106fde02c7e7a36eb7595 0003-update-ca-insert-newline-between-certs.patch" +sha512sums=" +8e20d3021222bb3b470a935d34ffe23e7857bf0b7fedda5284049155aab01bc88ab54ae939376968fb7fbff41e6b06bd32e34405210a8e74faadb68ffa6d9dd4 ca-certificates-20220614.tar.bz2 +" diff --git a/main/cairo/APKBUILD b/main/cairo/APKBUILD index b4a63a44a5b..67b31fa38ec 100644 --- a/main/cairo/APKBUILD +++ b/main/cairo/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=cairo pkgver=1.16.0 -pkgrel=3 +pkgrel=5 pkgdesc="A vector graphics library" url="https://cairographics.org/" arch="all" @@ -17,10 +17,13 @@ source="https://cairographics.org/releases/cairo-$pkgver.tar.xz CVE-2018-19876.patch pdf-flush.patch 85.patch + fix-inf-loop.patch " builddir="$srcdir/$pkgname-$pkgver" # secfixes: +# 1.16.0-r5: +# - CVE-2019-6462 # 1.16.0-r3: # - CVE-2020-35492 # 1.16.0-r1: @@ -70,8 +73,11 @@ tools() { "$subpkgdir"/usr/lib/cairo/ } -sha512sums="9eb27c4cf01c0b8b56f2e15e651f6d4e52c99d0005875546405b64f1132aed12fbf84727273f493d84056a13105e065009d89e94a8bfaf2be2649e232b82377f cairo-1.16.0.tar.xz +sha512sums=" +9eb27c4cf01c0b8b56f2e15e651f6d4e52c99d0005875546405b64f1132aed12fbf84727273f493d84056a13105e065009d89e94a8bfaf2be2649e232b82377f cairo-1.16.0.tar.xz 86f26fe41deb5e14f553c999090d1ec1d92a534fa7984112c9a7f1d6c6a8f1b7bb735947e8ec3f26e817f56410efe8cc46c5e682f6a278d49b40a683513740e0 musl-stacksize.patch 8f13cdcae0f134e04778cf5915f858fb8d5357a7e0a454791c93d1566935b985ec66dfe1683cd0b74a1cb44a130923d7a27cf006f3fc70b9bee93abd58a55aa3 CVE-2018-19876.patch 533ea878dc7f917af92e2694bd3f535a09cde77f0ecd0cc00881fbc9ec1ea86f60026eacc76129705f525f6672929ad8d15d8cfe1bfa61e9962e805a7fbded81 pdf-flush.patch -20699d2dd10531f99587cdcd187a23e23bca5a9f031255c95aade4dadb79bbb62118c7ddff677c2fd20e4ba7694eee4debcd79a4d0736d62951a4fcee56ccae0 85.patch" +20699d2dd10531f99587cdcd187a23e23bca5a9f031255c95aade4dadb79bbb62118c7ddff677c2fd20e4ba7694eee4debcd79a4d0736d62951a4fcee56ccae0 85.patch +ebe5d71b18aa9eefe1e0a6c150761bb7abef41f144f37eb0bfa8a01947aacb1292ac131cf815dcaaaa6478c0aac07ca5428fba28ad346a00c5aaa5fa64f6ff5b fix-inf-loop.patch +" diff --git a/main/cairo/fix-inf-loop.patch b/main/cairo/fix-inf-loop.patch new file mode 100644 index 00000000000..2a26876c36d --- /dev/null +++ b/main/cairo/fix-inf-loop.patch @@ -0,0 +1,36 @@ +From bbeaf08190d3006a80b80a77724801cd477a37b8 Mon Sep 17 00:00:00 2001 +From: Heiko Lewin <hlewin@worldiety.de> +Date: Sat, 17 Apr 2021 19:15:03 +0200 +Subject: [PATCH] _arc_max_angle_for_tolerance_normalized: fix infinite loop + +--- + src/cairo-arc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/cairo-arc.c b/src/cairo-arc.c +index 390397bae..1c891d1a0 100644 +--- a/src/cairo-arc.c ++++ b/src/cairo-arc.c +@@ -90,16 +90,18 @@ _arc_max_angle_for_tolerance_normalized (double tolerance) + { M_PI / 11.0, 9.81410988043554039085e-09 }, + }; + int table_size = ARRAY_LENGTH (table); ++ const int max_segments = 1000; /* this value is chosen arbitrarily. this gives an error of about 1.74909e-20 */ + + for (i = 0; i < table_size; i++) + if (table[i].error < tolerance) + return table[i].angle; + + ++i; ++ + do { + angle = M_PI / i++; + error = _arc_error_normalized (angle); +- } while (error > tolerance); ++ } while (error > tolerance && i < max_segments); + + return angle; + } +-- +GitLab + diff --git a/main/cifs-utils/APKBUILD b/main/cifs-utils/APKBUILD index 3efe5551f89..481dca25373 100644 --- a/main/cifs-utils/APKBUILD +++ b/main/cifs-utils/APKBUILD @@ -18,7 +18,8 @@ options="suid" # secfixes: # 6.13-r0: # - CVE-2021-20208 -# - CVE-2020-14342 (not actually applicable) +# 0: +# - CVE-2020-14342 # (not actually applicable) prepare() { default_prepare diff --git a/main/clamav/APKBUILD b/main/clamav/APKBUILD index 81aef9f55f8..4206cef11ef 100644 --- a/main/clamav/APKBUILD +++ b/main/clamav/APKBUILD @@ -3,7 +3,7 @@ # Contributor: Carlo Landmeter <clandmeter@gmail.com> # Maintainer: Carlo Landmeter <clandmeter@gmail.com> pkgname=clamav -pkgver=0.103.2 +pkgver=0.103.6 pkgrel=0 pkgusers="clamav" pkggroups="clamav" @@ -32,6 +32,13 @@ source="https://www.clamav.net/downloads/production/clamav-$pkgver.tar.gz # secfixes: +# 0.103.6-r0: +# - CVE-2022-20698 +# - CVE-2022-20770 +# - CVE-2022-20771 +# - CVE-2022-20785 +# - CVE-2022-20792 +# - CVE-2022-20796 # 0.103.2-r0: # - CVE-2021-1405 # - CVE-2021-1404 @@ -250,10 +257,12 @@ milter() { "$subpkgdir"/etc/clamav/clamav-milter.conf } -sha512sums="87d47c4529a57da0b47b3744a279996ca24fa74ce10d7e27a53c19c1e13098af680e0e48ed767122bb2bbd3f927302451da84ccf51a933e7e3556ef43cbe9f45 clamav-0.103.2.tar.gz +sha512sums=" +d39e1964678b8251bde3a9f3db30fe3d3d76cc566a86834297f4dd8489086dc9cc4c6541ca128089159f4c071d2d85b530455bd942987d3929ea0082b8ab272b clamav-0.103.6.tar.gz d886d810de66e8da800384c1e8192f7da4352402ffc3b33cfbca93d81a2235d8c902ca9d436b9be70f00740b4555e1efbf09bf9f84059095a1a297b27581cd20 clamd.initd 59c561b3dcb0b616b647cd8e4ebc46a2cc5e7144c8c7ea0054cc1c3021d1da8f67e4dad5c083c3fe712ed887aaabfca91b538f4759537e7c4c9ab71ba4fd5794 clamd.confd 6f0c615b89f0f0d2f0e9f965f025b9ac8c81b2168fa6727dc8a47222abd780f9b656732f289d6061a20126b16126a975d50e8b3b8ff131f55dd8803da8be5dec freshclam.initd ba181fe1abaac7b898ccb40b0713455aa3c9d5e25ad21d687b6cac09b0105b9e376526e7c776a44636234d8db819709d8d6a6cc76119bc3e98b637b1a3f26c08 freshclam.confd 3ae493dd1610a819402c015f6b8c0f080f926b72dc43d2bded60030bf6a55040e4b88e0f64d3aae299dc1133d7e1b89855e7346b4665a64e8b82592f7b75cf6a clamd.logrotate -30cff378bc28c76b795e00c92ae5ee623f3abe4a19bed61dd8403c96e72658bb02b7f040d26a6258104af754464d25ea7d9646918c4b47d2ba9a8cbf4687056c freshclam.logrotate" +30cff378bc28c76b795e00c92ae5ee623f3abe4a19bed61dd8403c96e72658bb02b7f040d26a6258104af754464d25ea7d9646918c4b47d2ba9a8cbf4687056c freshclam.logrotate +" diff --git a/main/cryptsetup/APKBUILD b/main/cryptsetup/APKBUILD index 8bba60cee69..9073b6e49f7 100644 --- a/main/cryptsetup/APKBUILD +++ b/main/cryptsetup/APKBUILD @@ -1,8 +1,8 @@ # Contributor: Sören Tempel <soeren+alpine@soeren-tempel.net> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=cryptsetup -pkgver=2.3.2 -pkgrel=1 +pkgver=2.3.7 +pkgrel=0 pkgdesc="Userspace setup tool for transparent encryption of block devices using the Linux 2.6 cryptoapi" url="https://gitlab.com/cryptsetup/cryptsetup" arch="all" @@ -16,10 +16,11 @@ source="https://www.kernel.org/pub/linux/utils/cryptsetup/v${pkgver%.*}/cryptset flush-stdout.patch dmcrypt.confd dmcrypt.initd - CVE-2020-14382.patch::https://gitlab.com/cryptsetup/cryptsetup/-/commit/52f5cb8cedf22fb3e14c744814ec8af7614146c7.patch " # secfixes: +# 2.3.7-r0: +# - CVE-2021-4122 # 2.3.2-r1: # - CVE-2020-14382 @@ -60,8 +61,7 @@ libs() { mv "$pkgdir"/lib "$subpkgdir"/ } -sha512sums="a3e8694e52b2d92269f74d5c796a18ef3bf8fe8b082192b1a31090542ca95392f4909218581eb9df5c79a465a03ef08e25df3358c382a7ab1394e9df276357df cryptsetup-2.3.2.tar.gz +sha512sums="754f1b5c3dd234f256549118789af4187d75466743e5ec43d929d402c01e9c6997a9166fd8e4dc30c177f58d43284f7e28cc02fc015f02d605f3d6e5784a6b4c cryptsetup-2.3.7.tar.gz dc896fdb7697d01443a168819f01af02db00a9de75589f062a1ebbfc0bc185b6d2109b18352309c41b818e3ad89609dcea3660d6f3cda890de825f053f94de97 flush-stdout.patch 74422d5e1614b43af894ea01da1ea80d805ec7f77981cbb80a6b1a4becad737a8825d7269812499095a7f50d39fa7da5bf4e4edae63529b1fe87b9176943a733 dmcrypt.confd -81dad61cdecf1dc529b26eb3cdc15979a582c876b01268f88e7a71c8fae6911137c03bfa63fee64e064e5fb31f673610be27ecab9fc432229f13e7040698bd5c dmcrypt.initd -5a8e68f4efc68a34a917c298ccf7d45a67adb67de06bf3560d58a01b4d6c77c52b868af9f322c3b82789c2e890f120e5c6e56b96f8cff083413301f24a6befc1 CVE-2020-14382.patch" +81dad61cdecf1dc529b26eb3cdc15979a582c876b01268f88e7a71c8fae6911137c03bfa63fee64e064e5fb31f673610be27ecab9fc432229f13e7040698bd5c dmcrypt.initd" diff --git a/main/curl/APKBUILD b/main/curl/APKBUILD index fb207bd6816..8a0ab3bc74a 100644 --- a/main/curl/APKBUILD +++ b/main/curl/APKBUILD @@ -4,7 +4,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=curl pkgver=7.79.1 -pkgrel=0 +pkgrel=1 pkgdesc="URL retrival utility and library" url="https://curl.se/" arch="all" @@ -14,10 +14,21 @@ depends_dev="openssl-dev nghttp2-dev zlib-dev" checkdepends="python3" makedepends="$depends_dev autoconf automake groff libtool perl" subpackages="$pkgname-dbg $pkgname-static $pkgname-doc $pkgname-dev libcurl" -source="https://curl.se/download/curl-$pkgver.tar.xz" +source="https://curl.se/download/curl-$pkgver.tar.xz + CVE-2022-22576.patch + CVE-2022-27774-pre.patch + CVE-2022-27774.patch + CVE-2022-27775.patch + CVE-2022-27776.patch + " options="net" # Required for running tests # secfixes: +# 7.79.1-r1: +# - CVE-2022-22576 +# - CVE-2022-27774 +# - CVE-2022-27775 +# - CVE-2022-27776 # 7.79.0-r0: # - CVE-2021-22945 # - CVE-2021-22946 @@ -159,4 +170,9 @@ static() { sha512sums=" 1edb71647a7f4dbb070baf1a019b4751aefeda793ff523c504410bb5cc74e5bffc52f20dd889697d1585f9ca3c4e81b1a9caadd182c30c8358ffd25f33e4db4d curl-7.79.1.tar.xz +9456de77de52e7980fb8e42bdc524b56dc7029c8205209de2de39d6354c8f5457e3fc8068d36d55cbf96ae82aabd390afc94721995dfc4b8e4a69bed9d0b00c8 CVE-2022-22576.patch +63af4876fa94ff11ec3c1d4a36cfd2919083cf57cedc5086703966e627b27d8fac520155214b6f81e80a38a392cbd542f135f218944ae5117cf8b1ba388c7046 CVE-2022-27774-pre.patch +4161539ebf5b9d4b1c5f4f83a8af313a96f5d9a4871a3da5f1ea564903b9079ac02003816f613e05aec9f3819bd2e152bb7885d0df138997abcaeb4adab897d6 CVE-2022-27774.patch +c68b3eff3ef6120277c8acbd1d3ce4e16a26219a6b543af03a7bb9c5c3bc5d3480c237f11470995d088c9cbd06531352b86b151038cfcd551477038da0a96b33 CVE-2022-27775.patch +116d30037af107cd028bd6404b6488106ebe1f3482b65159fe6764c355edf57b5fc460ce034a4eb07053f97128d68e89ef50ae080b33ee82b0fc5460f09866c4 CVE-2022-27776.patch " diff --git a/main/curl/CVE-2022-22576.patch b/main/curl/CVE-2022-22576.patch new file mode 100644 index 00000000000..5238d9998b4 --- /dev/null +++ b/main/curl/CVE-2022-22576.patch @@ -0,0 +1,143 @@ +Patch-Source: https://github.com/curl/curl/commit/852aa5ad351ea53e5f01d2f44b5b4370c2bf5425 +From 852aa5ad351ea53e5f01d2f44b5b4370c2bf5425 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat <patrick@monnerat.net> +Date: Mon, 25 Apr 2022 11:44:05 +0200 +Subject: [PATCH] url: check sasl additional parameters for connection reuse. + +Also move static function safecmp() as non-static Curl_safecmp() since +its purpose is needed at several places. + +Bug: https://curl.se/docs/CVE-2022-22576.html + +CVE-2022-22576 + +Closes #8746 +--- + lib/strcase.c | 10 ++++++++++ + lib/strcase.h | 2 ++ + lib/url.c | 13 ++++++++++++- + lib/urldata.h | 1 + + lib/vtls/vtls.c | 21 ++++++--------------- + 5 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/lib/strcase.c b/lib/strcase.c +index dd46ca1ba0e5..692a3f14aee7 100644 +--- a/lib/strcase.c ++++ b/lib/strcase.c +@@ -131,6 +131,16 @@ void Curl_strntolower(char *dest, const char *src, size_t n) + } while(*src++ && --n); + } + ++/* Compare case-sensitive NUL-terminated strings, taking care of possible ++ * null pointers. Return true if arguments match. ++ */ ++bool Curl_safecmp(char *a, char *b) ++{ ++ if(a && b) ++ return !strcmp(a, b); ++ return !a && !b; ++} ++ + /* --- public functions --- */ + + int curl_strequal(const char *first, const char *second) +diff --git a/lib/strcase.h b/lib/strcase.h +index b234d3815220..2635f5117e99 100644 +--- a/lib/strcase.h ++++ b/lib/strcase.h +@@ -49,4 +49,6 @@ char Curl_raw_toupper(char in); + void Curl_strntoupper(char *dest, const char *src, size_t n); + void Curl_strntolower(char *dest, const char *src, size_t n); + ++bool Curl_safecmp(char *a, char *b); ++ + #endif /* HEADER_CURL_STRCASE_H */ +diff --git a/lib/url.c b/lib/url.c +index 9a988b4d58d8..e1647b133854 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -781,6 +781,7 @@ static void conn_free(struct connectdata *conn) + Curl_safefree(conn->passwd); + Curl_safefree(conn->sasl_authzid); + Curl_safefree(conn->options); ++ Curl_safefree(conn->oauth_bearer); + Curl_dyn_free(&conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ +@@ -1342,7 +1343,9 @@ ConnectionExists(struct Curl_easy *data, + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(strcmp(needle->user, check->user) || +- strcmp(needle->passwd, check->passwd)) { ++ strcmp(needle->passwd, check->passwd) || ++ !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) || ++ !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ + continue; + } +@@ -3637,6 +3640,14 @@ static CURLcode create_conn(struct Curl_easy *data, + } + } + ++ if(data->set.str[STRING_BEARER]) { ++ conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); ++ if(!conn->oauth_bearer) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } ++ } ++ + #ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); +diff --git a/lib/urldata.h b/lib/urldata.h +index 07eb19b87034..1d89b8d7fa68 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -984,6 +984,7 @@ struct connectdata { + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + char *sasl_authzid; /* authorisation identity string, allocated */ ++ char *oauth_bearer; /* OAUTH2 bearer, allocated */ + unsigned char httpversion; /* the HTTP version*10 reported by the server */ + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 03b85ba065e5..a40ac06f684f 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -125,15 +125,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second) + return !memcmp(first->data, second->data, first->len); /* same data */ + } + +-static bool safecmp(char *a, char *b) +-{ +- if(a && b) +- return !strcmp(a, b); +- else if(!a && !b) +- return TRUE; /* match */ +- return FALSE; /* no match */ +-} +- + + bool + Curl_ssl_config_matches(struct ssl_primary_config *data, +@@ -147,12 +138,12 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + blobcmp(data->cert_blob, needle->cert_blob) && + blobcmp(data->ca_info_blob, needle->ca_info_blob) && + blobcmp(data->issuercert_blob, needle->issuercert_blob) && +- safecmp(data->CApath, needle->CApath) && +- safecmp(data->CAfile, needle->CAfile) && +- safecmp(data->issuercert, needle->issuercert) && +- safecmp(data->clientcert, needle->clientcert) && +- safecmp(data->random_file, needle->random_file) && +- safecmp(data->egdsocket, needle->egdsocket) && ++ Curl_safecmp(data->CApath, needle->CApath) && ++ Curl_safecmp(data->CAfile, needle->CAfile) && ++ Curl_safecmp(data->issuercert, needle->issuercert) && ++ Curl_safecmp(data->clientcert, needle->clientcert) && ++ Curl_safecmp(data->random_file, needle->random_file) && ++ Curl_safecmp(data->egdsocket, needle->egdsocket) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && + Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) && + Curl_safe_strcasecompare(data->curves, needle->curves) && diff --git a/main/curl/CVE-2022-27774-pre.patch b/main/curl/CVE-2022-27774-pre.patch new file mode 100644 index 00000000000..b5cf4fccc30 --- /dev/null +++ b/main/curl/CVE-2022-27774-pre.patch @@ -0,0 +1,41 @@ +Patch-Source: https://github.com/curl/curl/commit/08b8ef4e726ba10f45081ecda5b3cea788d3c839 +From 08b8ef4e726ba10f45081ecda5b3cea788d3c839 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH] connect: store "conn_remote_port" in the info struct + +To make it available after the connection ended. +--- + lib/connect.c | 1 + + lib/urldata.h | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lib/connect.c b/lib/connect.c +index e0b740147157..9bcf525ebb39 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -623,6 +623,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, + data->info.conn_scheme = conn->handler->scheme; + data->info.conn_protocol = conn->handler->protocol; + data->info.conn_primary_port = conn->port; ++ data->info.conn_remote_port = conn->remote_port; + data->info.conn_local_port = local_port; + } + +diff --git a/lib/urldata.h b/lib/urldata.h +index ef2174d9e727..9c34ec444c08 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1160,7 +1160,11 @@ struct PureInfo { + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; +- int conn_primary_port; ++ int conn_primary_port; /* this is the destination port to the connection, ++ which might have been a proxy */ ++ int conn_remote_port; /* this is the "remote port", which is the port ++ number of the used URL, independent of proxy or ++ not */ + char conn_local_ip[MAX_IPADR_LEN]; + int conn_local_port; + const char *conn_scheme; diff --git a/main/curl/CVE-2022-27774.patch b/main/curl/CVE-2022-27774.patch new file mode 100644 index 00000000000..db358af55e6 --- /dev/null +++ b/main/curl/CVE-2022-27774.patch @@ -0,0 +1,78 @@ +Patch-Source: https://github.com/curl/curl/commit/620ea21410030a9977396b4661806bc187231b79 +From 620ea21410030a9977396b4661806bc187231b79 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH] transfer: redirects to other protocols or ports clear auth + +... unless explicitly permitted. + +Bug: https://curl.se/docs/CVE-2022-27774.html +Reported-by: Harry Sintonen +Closes #8748 +--- + lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/lib/transfer.c b/lib/transfer.c +index 53ef0b03b8e0..315da876c4a8 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1611,10 +1611,57 @@ CURLcode Curl_follow(struct Curl_easy *data, + return CURLE_OUT_OF_MEMORY; + } + else { +- + uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); + if(uc) + return Curl_uc_to_curlcode(uc); ++ ++ /* Clear auth if this redirects to a different port number or protocol, ++ unless permitted */ ++ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { ++ char *portnum; ++ int port; ++ bool clear = FALSE; ++ ++ if(data->set.use_port && data->state.allow_port) ++ /* a custom port is used */ ++ port = (int)data->set.use_port; ++ else { ++ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, ++ CURLU_DEFAULT_PORT); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ port = atoi(portnum); ++ free(portnum); ++ } ++ if(port != data->info.conn_remote_port) { ++ infof(data, "Clear auth, redirects to port from %u to %u", ++ data->info.conn_remote_port, port); ++ clear = TRUE; ++ } ++ else { ++ char *scheme; ++ const struct Curl_handler *p; ++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ ++ p = Curl_builtin_scheme(scheme); ++ if(p && (p->protocol != data->info.conn_protocol)) { ++ infof(data, "Clear auth, redirects scheme from %s to %s", ++ data->info.conn_scheme, scheme); ++ clear = TRUE; ++ } ++ free(scheme); ++ } ++ if(clear) { ++ Curl_safefree(data->state.aptr.user); ++ Curl_safefree(data->state.aptr.passwd); ++ } ++ } + } + + if(type == FOLLOW_FAKE) { diff --git a/main/curl/CVE-2022-27775.patch b/main/curl/CVE-2022-27775.patch new file mode 100644 index 00000000000..e1c02b8969d --- /dev/null +++ b/main/curl/CVE-2022-27775.patch @@ -0,0 +1,35 @@ +Patch-Source: https://github.com/curl/curl/commit/058f98dc3fe595f21dc26a5b9b1699e519ba5705 +From 058f98dc3fe595f21dc26a5b9b1699e519ba5705 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 25 Apr 2022 11:48:00 +0200 +Subject: [PATCH] conncache: include the zone id in the "bundle" hashkey + +Make connections to two separate IPv6 zone ids create separate +connections. + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27775.html +Closes #8747 +--- + lib/conncache.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/conncache.c b/lib/conncache.c +index ec669b971dc3..8948b53fa500 100644 +--- a/lib/conncache.c ++++ b/lib/conncache.c +@@ -155,8 +155,12 @@ static void hashkey(struct connectdata *conn, char *buf, + /* report back which name we used */ + *hostp = hostname; + +- /* put the number first so that the hostname gets cut off if too long */ +- msnprintf(buf, len, "%ld%s", port, hostname); ++ /* put the numbers first so that the hostname gets cut off if too long */ ++#ifdef ENABLE_IPV6 ++ msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname); ++#else ++ msnprintf(buf, len, "%ld/%s", port, hostname); ++#endif + Curl_strntolower(buf, buf, len); + } + diff --git a/main/curl/CVE-2022-27776.patch b/main/curl/CVE-2022-27776.patch new file mode 100644 index 00000000000..59ffa79a36a --- /dev/null +++ b/main/curl/CVE-2022-27776.patch @@ -0,0 +1,113 @@ +Patch-Source: https://github.com/curl/curl/commit/6e659993952aa5f90f48864be84a1bbb047fc258 +From 6e659993952aa5f90f48864be84a1bbb047fc258 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 25 Apr 2022 13:05:40 +0200 +Subject: [PATCH] http: avoid auth/cookie on redirects same host diff port + +CVE-2022-27776 + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27776.html +Closes #8749 +--- + lib/http.c | 34 ++++++++++++++++++++++------------ + lib/urldata.h | 16 +++++++++------- + 2 files changed, 31 insertions(+), 19 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index ce79fc4e31c8..f0476f3b9272 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -775,6 +775,21 @@ output_auth_headers(struct Curl_easy *data, + return CURLE_OK; + } + ++/* ++ * allow_auth_to_host() tells if autentication, cookies or other "sensitive ++ * data" can (still) be sent to this host. ++ */ ++static bool allow_auth_to_host(struct Curl_easy *data) ++{ ++ struct connectdata *conn = data->conn; ++ return (!data->state.this_is_a_follow || ++ data->set.allow_auth_to_other_hosts || ++ (data->state.first_host && ++ strcasecompare(data->state.first_host, conn->host.name) && ++ (data->state.first_remote_port == conn->remote_port) && ++ (data->state.first_remote_protocol == conn->handler->protocol))); ++} ++ + /** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication +@@ -847,17 +862,14 @@ Curl_http_output_auth(struct Curl_easy *data, + with it */ + authproxy->done = TRUE; + +- /* To prevent the user+password to get sent to other than the original +- host due to a location-follow, we do some weirdo checks here */ +- if(!data->state.this_is_a_follow || ++ /* To prevent the user+password to get sent to other than the original host ++ due to a location-follow */ ++ if(allow_auth_to_host(data) + #ifndef CURL_DISABLE_NETRC +- conn->bits.netrc || ++ || conn->bits.netrc + #endif +- !data->state.first_host || +- data->set.allow_auth_to_other_hosts || +- strcasecompare(data->state.first_host, conn->host.name)) { ++ ) + result = output_auth_headers(data, conn, authhost, request, path, FALSE); +- } + else + authhost->done = TRUE; + +@@ -1905,10 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ +- (data->state.this_is_a_follow && +- data->state.first_host && +- !data->set.allow_auth_to_other_hosts && +- !strcasecompare(data->state.first_host, conn->host.name))) ++ !allow_auth_to_host(data)) + ; + else { + #ifdef USE_HYPER +@@ -2084,6 +2093,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) + return CURLE_OUT_OF_MEMORY; + + data->state.first_remote_port = conn->remote_port; ++ data->state.first_remote_protocol = conn->handler->protocol; + } + Curl_safefree(data->state.aptr.host); + +diff --git a/lib/urldata.h b/lib/urldata.h +index 1d89b8d7fa68..ef2174d9e727 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1329,14 +1329,16 @@ struct UrlState { + char *ulbuf; /* allocated upload buffer or NULL */ + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ +- char *first_host; /* host name of the first (not followed) request. +- if set, this should be the host name that we will +- sent authorization to, no else. Used to make Location: +- following not keep sending user+password... This is +- strdup() data. +- */ ++ ++ /* host name, port number and protocol of the first (not followed) request. ++ if set, this should be the host name that we will sent authorization to, ++ no else. Used to make Location: following not keep sending user+password. ++ This is strdup()ed data. */ ++ char *first_host; ++ int first_remote_port; ++ unsigned int first_remote_protocol; ++ + int retrycount; /* number of retries on a new connection */ +- int first_remote_port; /* remote port of the first (not followed) request */ + struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ diff --git a/main/cyrus-sasl/APKBUILD b/main/cyrus-sasl/APKBUILD index 7ef5b6286e8..5d3a6e454d5 100644 --- a/main/cyrus-sasl/APKBUILD +++ b/main/cyrus-sasl/APKBUILD @@ -1,8 +1,8 @@ # Contributor: Leonardo Arena <rnalrd@alpinelinux.org> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=cyrus-sasl -pkgver=2.1.27 -pkgrel=6 +pkgver=2.1.28 +pkgrel=0 pkgdesc="Cyrus Simple Authentication Service Layer (SASL)" url="https://www.cyrusimap.org/sasl/" arch="all" @@ -34,16 +34,12 @@ makedepends=" libtool " source="https://github.com/cyrusimap/cyrus-sasl/releases/download/cyrus-sasl-$pkgver/cyrus-sasl-$pkgver.tar.gz - cyrus-sasl-2.1.27-as_needed.patch - cyrus-sasl-2.1.27-autotools_fixes.patch - cyrus-sasl-2.1.27-avoid_pic_overwrite.patch - cyrus-sasl-2.1.27-doc_build_fix.patch - cyrus-sasl-2.1.27-gss_c_nt_hostbased_service.patch - CVE-2019-19906.patch saslauthd.initd " # secfixes: +# 2.1.28-r0: +# - CVE-2022-24407 # 2.1.27-r5: # - CVE-2019-19906 # 2.1.26-r7: @@ -120,11 +116,7 @@ libsasl() { mv "$pkgdir"/usr/lib/libsasl*.so.* "$subpkgdir"/usr/lib/ } -sha512sums="d11549a99b3b06af79fc62d5478dba3305d7e7cc0824f4b91f0d2638daafbe940623eab235f85af9be38dcf5d42fc131db531c177040a85187aee5096b8df63b cyrus-sasl-2.1.27.tar.gz -9eefa6d45e3dd9157a5672909acdd88f0ae35e76d64c3723890a474bbb05b22499cfadb0c077924d27f34da3710b2b700094dd7d5704050138c08dabcefdde94 cyrus-sasl-2.1.27-as_needed.patch -0d99ca049e76c11500769079d94f3bdb634bddb4c8d45a83b383e9bb9777edda66b17566800acbd450e1f4842d070ec3fbc236e7f0ef8759c36e6dd5ea8e3c64 cyrus-sasl-2.1.27-autotools_fixes.patch -4ca601839b023ef790e48dae567ffbbd57c632384c980946639ec7437ad23874961451718569455e6e25afaeff1728ecbc71a8686f6b43246f83465f95a2c904 cyrus-sasl-2.1.27-avoid_pic_overwrite.patch -6d723e7ec2c431b45c011b887187b6a670dbe646aa4c39d38171047ab23db529c30c433f8d4dd624181917c5ce4e5271f86e35e2644ede1c40dfb09cb67dccde cyrus-sasl-2.1.27-doc_build_fix.patch -fca4f2b7e427c7613f71daa4a31772c33c8c0fe9d7f85b57b85da71bc5a88a18fc52f7caea463188b4addd31cd041d5349af689d5face2cc45fb50c700a8afd7 cyrus-sasl-2.1.27-gss_c_nt_hostbased_service.patch -c39efd87dc9c883d3b07474197f6835fbd32f23baa1f5cd04b25a0473639f847321c40f232e390d4dc9d9ee189dbd177c05d3d1461af4d28a48a4827abc5d9b8 CVE-2019-19906.patch -f76bfb61567172428cdbc1ed900d5e0b6e66afc38118db6ba0e2fd8ba01956ad896e56463b2249bdc46d8725384f1b975a2af3601c0735327d3f8bc26ce1ed75 saslauthd.initd" +sha512sums=" +db15af9079758a9f385457a79390c8a7cd7ea666573dace8bf4fb01bb4b49037538d67285727d6a70ad799d2e2318f265c9372e2427de9371d626a1959dd6f78 cyrus-sasl-2.1.28.tar.gz +f76bfb61567172428cdbc1ed900d5e0b6e66afc38118db6ba0e2fd8ba01956ad896e56463b2249bdc46d8725384f1b975a2af3601c0735327d3f8bc26ce1ed75 saslauthd.initd +" diff --git a/main/cyrus-sasl/CVE-2019-19906.patch b/main/cyrus-sasl/CVE-2019-19906.patch deleted file mode 100644 index f7edb521e89..00000000000 --- a/main/cyrus-sasl/CVE-2019-19906.patch +++ /dev/null @@ -1,15 +0,0 @@ -https://github.com/cyrusimap/cyrus-sasl/issues/587 - -diff --git a/lib/common.c b/lib/common.c -index bc3bf1df..9969d6aa 100644 ---- a/lib/common.c -+++ b/lib/common.c -@@ -190,7 +190,7 @@ int _sasl_add_string(char **out, size_t *alloclen, - - if (add==NULL) add = "(null)"; - -- addlen=strlen(add); /* only compute once */ -+ addlen=strlen(add)+1; /* only compute once */ - if (_buf_alloc(out, alloclen, (*outlen)+addlen)!=SASL_OK) - return SASL_NOMEM; - diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.27-as_needed.patch b/main/cyrus-sasl/cyrus-sasl-2.1.27-as_needed.patch deleted file mode 100644 index 7cd9e151fbb..00000000000 --- a/main/cyrus-sasl/cyrus-sasl-2.1.27-as_needed.patch +++ /dev/null @@ -1,25 +0,0 @@ -Author: Matthias Klose <doko@ubuntu.com> -Desription: Fix FTBFS, add $(SASL_DB_LIB) as dependency to libsasldb, and use -it. ---- cyrus-sasl-2.1.27/saslauthd/Makefile.am -+++ cyrus-sasl-2.1.27/saslauthd/Makefile.am -@@ -25,7 +25,7 @@ - saslauthd_DEPENDENCIES = saslauthd-main.o $(LTLIBOBJS_FULL) - saslauthd_LDADD = @SASL_KRB_LIB@ \ - @GSSAPIBASE_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \ -- @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ $(LTLIBOBJS_FULL) $(CRYPTO_COMPAT_OBJS) $(LIBSASLDB_OBJS) -+ @LIB_SOCKET@ ../sasldb/libsasldb.la @LIB_PAM@ @LDAP_LIBS@ $(LTLIBOBJS_FULL) $(CRYPTO_COMPAT_OBJS) $(LIBSASLDB_OBJS) - - testsaslauthd_SOURCES = testsaslauthd.c utils.c - testsaslauthd_LDADD = @LIB_SOCKET@ ---- cyrus-sasl-2.1.27/sasldb/Makefile.am -+++ cyrus-sasl-2.1.27/sasldb/Makefile.am -@@ -54,6 +54,6 @@ - - libsasldb_la_SOURCES = allockey.c sasldb.h - EXTRA_libsasldb_la_SOURCES = $(extra_common_sources) --libsasldb_la_DEPENDENCIES = $(SASL_DB_BACKEND) --libsasldb_la_LIBADD = $(SASL_DB_BACKEND) -+libsasldb_la_DEPENDENCIES = $(SASL_DB_BACKEND) $(SASL_DB_LIB) -+libsasldb_la_LIBADD = $(SASL_DB_BACKEND) $(SASL_DB_LIB) - libsasldb_la_LDFLAGS = -no-undefined diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.27-autotools_fixes.patch b/main/cyrus-sasl/cyrus-sasl-2.1.27-autotools_fixes.patch deleted file mode 100644 index 2ce971efc5b..00000000000 --- a/main/cyrus-sasl/cyrus-sasl-2.1.27-autotools_fixes.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- cyrus-sasl-2.1.27/configure.ac -+++ cyrus-sasl-2.1.27/configure.ac -@@ -44,6 +44,8 @@ - - AC_PREREQ(2.63) - -+AC_CONFIG_MACRO_DIR([config]) -+ - dnl - dnl REMINDER: When changing the version number here, please also update - dnl the values in win32/include/config.h and include/sasl.h as well. ---- cyrus-sasl-2.1.27/Makefile.am -+++ cyrus-sasl-2.1.27/Makefile.am -@@ -44,6 +44,8 @@ - # - ################################################################ - -+ACLOCAL_AMFLAGS = -I config -+ - if SASLAUTHD - SAD = saslauthd - else ---- cyrus-sasl-2.1.27/saslauthd/Makefile.am -+++ cyrus-sasl-2.1.27/saslauthd/Makefile.am -@@ -1,4 +1,6 @@ - AUTOMAKE_OPTIONS = 1.7 -+ACLOCAL_AMFLAGS = -I ../config -+ - sbin_PROGRAMS = saslauthd testsaslauthd - EXTRA_PROGRAMS = saslcache - diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.27-avoid_pic_overwrite.patch b/main/cyrus-sasl/cyrus-sasl-2.1.27-avoid_pic_overwrite.patch deleted file mode 100644 index c331039e2f1..00000000000 --- a/main/cyrus-sasl/cyrus-sasl-2.1.27-avoid_pic_overwrite.patch +++ /dev/null @@ -1,17 +0,0 @@ -Author: Fabian Fagerholm <fabbe@debian.org> -Description: This patch makes sure the non-PIC version of libsasldb.a, which -is created out of non-PIC objects, is not going to overwrite the PIC version, -which is created out of PIC objects. The PIC version is placed in .libs, and -the non-PIC version in the current directory. This ensures that both non-PIC -and PIC versions are available in the correct locations. ---- cyrus-sasl-2.1.27/lib/Makefile.am -+++ cyrus-sasl-2.1.27/lib/Makefile.am -@@ -98,7 +98,7 @@ - - libsasl2.a: libsasl2.la $(SASL_STATIC_OBJS) - @echo adding static plugins and dependencies -- $(AR) cru .libs/$@ $(SASL_STATIC_OBJS) -+ $(AR) cru $@ $(SASL_STATIC_OBJS) - @for i in ./libsasl2.la ../common/libplugin_common.la ../sasldb/libsasldb.la ../plugins/lib*.la; do \ - if test ! -f $$i; then continue; fi; . $$i; \ - for j in $$dependency_libs foo; do \ diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.27-doc_build_fix.patch b/main/cyrus-sasl/cyrus-sasl-2.1.27-doc_build_fix.patch deleted file mode 100644 index bdd02f77966..00000000000 --- a/main/cyrus-sasl/cyrus-sasl-2.1.27-doc_build_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- cyrus-sasl-2.1.27/docsrc/exts/sphinxlocal/writers/manpage.py -+++ cyrus-sasl-2.1.27/docsrc/exts/sphinxlocal/writers/manpage.py -@@ -23,7 +23,7 @@ - from sphinx import addnodes - from sphinx.locale import admonitionlabels, _ - from sphinx.util.osutil import ustrftime --from sphinx.util.compat import docutils_version -+#from sphinx.util.compat import docutils_version - - class CyrusManualPageWriter(ManualPageWriter): - diff --git a/main/cyrus-sasl/cyrus-sasl-2.1.27-gss_c_nt_hostbased_service.patch b/main/cyrus-sasl/cyrus-sasl-2.1.27-gss_c_nt_hostbased_service.patch deleted file mode 100644 index c585cb158e1..00000000000 --- a/main/cyrus-sasl/cyrus-sasl-2.1.27-gss_c_nt_hostbased_service.patch +++ /dev/null @@ -1,16 +0,0 @@ -Gentoo bug #389349 ---- cyrus-sasl-2.1.27/m4/sasl2.m4 -+++ cyrus-sasl-2.1.27/m4/sasl2.m4 -@@ -220,7 +220,11 @@ - [AC_WARN([Cybersafe define not found])]) - - elif test "$ac_cv_header_gssapi_h" = "yes"; then -- AC_EGREP_HEADER(GSS_C_NT_HOSTBASED_SERVICE, gssapi.h, -+ AC_EGREP_CPP(hostbased_service_gss_nt_yes, gssapi.h, -+ [#include <gssapi.h> -+ #ifdef GSS_C_NT_HOSTBASED_SERVICE -+ hostbased_service_gss_nt_yes -+ #endif], - [AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE,, - [Define if your GSSAPI implementation defines GSS_C_NT_HOSTBASED_SERVICE])]) - elif test "$ac_cv_header_gssapi_gssapi_h"; then diff --git a/main/dahdi-linux-lts/APKBUILD b/main/dahdi-linux-lts/APKBUILD index 3ca1f199bf4..c0c3a0d5fdf 100644 --- a/main/dahdi-linux-lts/APKBUILD +++ b/main/dahdi-linux-lts/APKBUILD @@ -9,7 +9,7 @@ _rel=0 _flavor=${FLAVOR:-lts} _kpkg=linux-$_flavor -_kver=5.4.143 +_kver=5.4.192 _krel=0 _kpkgver="$_kver-r$_krel" diff --git a/main/drbd-lts/APKBUILD b/main/drbd-lts/APKBUILD index 5b326e8afe6..974da3748a6 100644 --- a/main/drbd-lts/APKBUILD +++ b/main/drbd-lts/APKBUILD @@ -8,7 +8,7 @@ _rel=0 _flavor=${FLAVOR:-lts} _kpkg=linux-$_flavor -_kver=5.4.143 +_kver=5.4.192 _krel=0 _kabi="$_kver-$_krel-$_flavor" _kpkgver="$_kver-r$_krel" diff --git a/main/esh/APKBUILD b/main/esh/APKBUILD index fc6c53e03b7..ebaa57ad5fc 100644 --- a/main/esh/APKBUILD +++ b/main/esh/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Jakub Jirutka <jakub@jirutka.cz> # Maintainer: Jakub Jirutka <jakub@jirutka.cz> pkgname=esh -pkgver=0.3.1 +pkgver=0.3.2 pkgrel=0 pkgdesc="Simple template system based on shell" url="https://github.com/jirutka/esh" @@ -22,4 +22,6 @@ package() { make DESTDIR="$pkgdir" prefix=/usr install } -sha512sums="a29f8b028ceba305c8a37f2df20be95701fa3bdaeefd9853e05cc6423a6c685b33954deabda9af25c31baeae2321084e2a2badee216010c8efd75e58888effa3 esh-0.3.1.tar.gz" +sha512sums=" +f93835f0c28b75fa4b4ab2fdccd860050e4dde25634074065b182f289dd36d05074c7a5762f6cd35f409ae2ef239de5e0799af70ec6a96ba63df50fc8c123784 esh-0.3.2.tar.gz +" diff --git a/main/expat/APKBUILD b/main/expat/APKBUILD index 35cb8bcf659..c59fd1b7324 100644 --- a/main/expat/APKBUILD +++ b/main/expat/APKBUILD @@ -1,16 +1,47 @@ # Maintainer: Carlo Landmeter <clandmeter@gmail.com> pkgname=expat -pkgver=2.2.9 -pkgrel=1 +pkgver=2.2.10 +pkgrel=4 pkgdesc="An XML Parser library written in C" url="http://www.libexpat.org/" arch="all" license='MIT' checkdepends="bash" -source="https://downloads.sourceforge.net/project/expat/expat/$pkgver/expat-$pkgver.tar.bz2" +source="https://github.com/libexpat/libexpat/releases/download/R_${pkgver//./_}/expat-$pkgver.tar.xz + CVE-2021-45960.patch + CVE-2021-46143.patch + CVE-2022-22822.patch + CVE-2022-23852.patch + CVE-2022-23990.patch + CVE-2022-25235.patch + CVE-2022-25236.patch + CVE-2022-25236-regression.patch + CVE-2022-25313.patch + CVE-2022-25313-regression.patch + CVE-2022-25314.patch + CVE-2022-25315.patch + " subpackages="$pkgname-static $pkgname-dev $pkgname-doc" # secfixes: +# 2.2.10-r2: +# - CVE-2022-25235 +# - CVE-2022-25236 +# - CVE-2022-25313 +# - CVE-2022-25314 +# - CVE-2022-25315 +# 2.2.10-r1: +# - CVE-2022-23852 +# - CVE-2022-23990 +# 2.2.10-r0: +# - CVE-2021-45960 +# - CVE-2021-46143 +# - CVE-2022-22822 +# - CVE-2022-22823 +# - CVE-2022-22824 +# - CVE-2022-22825 +# - CVE-2022-22826 +# - CVE-2022-22827 # 2.2.7-r1: # - CVE-2019-15903 # 2.2.7-r0: @@ -39,4 +70,18 @@ package() { make DESTDIR="$pkgdir/" install } -sha512sums="8ea4b89a171dfda8267c8b7a0295516d169bf7f46587ebe460fe0ae7a31478a119ae2a7eaa09b3ce46b107ec7cd2274ea66d91c08b8a4ad6b98ba984cdd4e15b expat-2.2.9.tar.bz2" +sha512sums=" +a8e0c8a9cf7e6fbacdc6e709f3c99c533ab550fba52557d24259bb8b360f9697624c7500c0e9886fa57ee2b529aadd0d1835d66fe8112e15c20df75cd3eb090f expat-2.2.10.tar.xz +4afd3777fc682a2f9057d4cc42afe6e04680d7d24f93dc11a2677cb8b1a4b400921f6d689e2953aff4a3312118ea801c9e161f85774360b3b5c2d3bd0067f7ad CVE-2021-45960.patch +dd0339a0cdf5b18638a5732f2f9930af7adb5b20aa3bf102317a571f0f7d4f453313f0d8fdaa60f89c7a8f2e59eeaaca4b9c2e427a45594b7e21ed7c253d547a CVE-2021-46143.patch +dcf6bfc07b4919b1248dba5fc6d4e425d09975b09255d77456bb44b40495e92b4d4ffae6a9e949b204770848b70edfc4be1869c191cb01ebe967b1906ffc9d59 CVE-2022-22822.patch +cb079c0b9fe7df6afe2e06d706461489527802dce811d894587221b6316784b6cf1c7cf70573f41a276b5d97f7530d17c7ed854273f4eeae9652d971f64ef282 CVE-2022-23852.patch +7de120a34b5fc2fcb3779e259b24d47d8f40f38aab490b738eea52c55542b9cac45c897d90cb129c17c2d0057518f59b013c2af87a579c70b28a9aa70c1f27cb CVE-2022-23990.patch +c3ed585a62d5aadd9e1d1d589b636e37ffba5b5cc0c4d264a151cf308a9bfcfe9859704f43fd6d4e1ed86633fa4672378288bdc05b5e47dcb42c75f8258035f5 CVE-2022-25235.patch +016ca726fde03ef9049404faff7122e4f6e9b8a89d4a188e1ffa7bcf4d177fe79e00a3e1f90b45424ec60586cdde7615c6f5a39db1be1e585713f1a7385aa14c CVE-2022-25236.patch +36d441df896a6734091c15c3cd84515114d805349123a98eb43b61a268533f36b1ae0ac437e99b26a1792863e6d23c8d0a38eac902942b768e551cf2f2ea6187 CVE-2022-25236-regression.patch +4db9ad13e5e1461339ab93554d14acacbbdc121824a1dfd8a1d9df3194452711606da1f9f9ed5c03c0c5ca8de61237ef588897bbde95f89109160dc685fde25f CVE-2022-25313.patch +a0a41683fbef105a3577e845dd4d4d7a8a94561e8d578e5cd5efb77b02b6229ae26c9dc2dcb852f3dd72f155f9a886b9e68f7a54173d074528aee0d1f470ce05 CVE-2022-25313-regression.patch +ac7d03f3ef8be557bda0294247a645db820470be47ea7fa3dab8047f7f11ada831e4f0a4cd4b82e3b2f7715ada08435b8292257a64714c0242407ef58a661b72 CVE-2022-25314.patch +946e0983f9159ae4b01627581a99594f0e7263438ddfd40a1705b8de39ee9c6739af08598d3bc4f145a8ff142209d3fde85c20bbebe2932d9e60596f192db5b5 CVE-2022-25315.patch +" diff --git a/main/expat/CVE-2021-45960.patch b/main/expat/CVE-2021-45960.patch new file mode 100644 index 00000000000..7c366ab3903 --- /dev/null +++ b/main/expat/CVE-2021-45960.patch @@ -0,0 +1,59 @@ +From 0adcb34c49bee5b19bd29b16a578c510c23597ea Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Mon, 27 Dec 2021 20:15:02 +0100 +Subject: [PATCH] lib: Detect and prevent troublesome left shifts in function + storeAtts (CVE-2021-45960) + +--- + expat/lib/xmlparse.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index d730f41c3..b47c31b05 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + if (nPrefixes) { + int j; /* hash table index */ + unsigned long version = parser->m_nsAttsVersion; +- int nsAttsSize = (int)1 << parser->m_nsAttsPower; ++ ++ /* Detect and prevent invalid shift */ ++ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ unsigned int nsAttsSize = 1u << parser->m_nsAttsPower; + unsigned char oldNsAttsPower = parser->m_nsAttsPower; + /* size of hash table must be at least 2 * (# of prefixed attributes) */ + if ((nPrefixes << 1) +@@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + ; + if (parser->m_nsAttsPower < 3) + parser->m_nsAttsPower = 3; +- nsAttsSize = (int)1 << parser->m_nsAttsPower; ++ ++ /* Detect and prevent invalid shift */ ++ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) { ++ /* Restore actual size of memory in m_nsAtts */ ++ parser->m_nsAttsPower = oldNsAttsPower; ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ nsAttsSize = 1u << parser->m_nsAttsPower; ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) { ++ /* Restore actual size of memory in m_nsAtts */ ++ parser->m_nsAttsPower = oldNsAttsPower; ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, + nsAttsSize * sizeof(NS_ATT)); + if (! temp) { diff --git a/main/expat/CVE-2021-46143.patch b/main/expat/CVE-2021-46143.patch new file mode 100644 index 00000000000..d6bafba0ffb --- /dev/null +++ b/main/expat/CVE-2021-46143.patch @@ -0,0 +1,43 @@ +From 85ae9a2d7d0e9358f356b33977b842df8ebaec2b Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Sat, 25 Dec 2021 20:52:08 +0100 +Subject: [PATCH] lib: Prevent integer overflow on m_groupSize in function + doProlog (CVE-2021-46143) + +--- + expat/lib/xmlparse.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index b47c31b0..8f243126 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -5046,6 +5046,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + if (parser->m_prologState.level >= parser->m_groupSize) { + if (parser->m_groupSize) { + { ++ /* Detect and prevent integer overflow */ ++ if (parser->m_groupSize > (unsigned int)(-1) / 2u) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + char *const new_connector = (char *)REALLOC( + parser, parser->m_groupConnector, parser->m_groupSize *= 2); + if (new_connector == NULL) { +@@ -5056,6 +5061,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + } + + if (dtd->scaffIndex) { ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + int *const new_scaff_index = (int *)REALLOC( + parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); + if (new_scaff_index == NULL) diff --git a/main/expat/CVE-2022-22822.patch b/main/expat/CVE-2022-22822.patch new file mode 100644 index 00000000000..4fed22e63c4 --- /dev/null +++ b/main/expat/CVE-2022-22822.patch @@ -0,0 +1,250 @@ +From 9f93e8036e842329863bf20395b8fb8f73834d9e Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Thu, 30 Dec 2021 22:46:03 +0100 +Subject: [PATCH] lib: Prevent integer overflow at multiple places + (CVE-2022-22822 to CVE-2022-22827) + +The involved functions are: +- addBinding (CVE-2022-22822) +- build_model (CVE-2022-22823) +- defineAttribute (CVE-2022-22824) +- lookup (CVE-2022-22825) +- nextScaffoldPart (CVE-2022-22826) +- storeAtts (CVE-2022-22827) +--- + expat/lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 151 insertions(+), 2 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 8f243126..575e73ee 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3261,13 +3261,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts); ++ ++ /* Detect and prevent integer overflow */ ++ if (n > INT_MAX - nDefaultAtts) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + if (n + nDefaultAtts > parser->m_attsSize) { + int oldAttsSize = parser->m_attsSize; + ATTRIBUTE *temp; + #ifdef XML_ATTR_INFO + XML_AttrInfo *temp2; + #endif ++ ++ /* Detect and prevent integer overflow */ ++ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE) ++ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { ++ parser->m_attsSize = oldAttsSize; ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, + parser->m_attsSize * sizeof(ATTRIBUTE)); + if (temp == NULL) { +@@ -3276,6 +3301,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + } + parser->m_atts = temp; + #ifdef XML_ATTR_INFO ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++# if UINT_MAX >= SIZE_MAX ++ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { ++ parser->m_attsSize = oldAttsSize; ++ return XML_ERROR_NO_MEMORY; ++ } ++# endif ++ + temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, + parser->m_attsSize * sizeof(XML_AttrInfo)); + if (temp2 == NULL) { +@@ -3610,9 +3646,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + tagNamePtr->prefixLen = prefixLen; + for (i = 0; localPart[i++];) + ; /* i includes null terminator */ ++ ++ /* Detect and prevent integer overflow */ ++ if (binding->uriLen > INT_MAX - prefixLen ++ || i > INT_MAX - (binding->uriLen + prefixLen)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + n = i + binding->uriLen + prefixLen; + if (n > binding->uriAlloc) { + TAG *p; ++ ++ /* Detect and prevent integer overflow */ ++ if (n > INT_MAX - EXPAND_SPARE) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); + if (! uri) + return XML_ERROR_NO_MEMORY; +@@ -3708,6 +3766,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + if (parser->m_freeBindingList) { + b = parser->m_freeBindingList; + if (len > b->uriAlloc) { ++ /* Detect and prevent integer overflow */ ++ if (len > INT_MAX - EXPAND_SPARE) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + XML_Char *temp = (XML_Char *)REALLOC( + parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (temp == NULL) +@@ -3720,6 +3793,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + b = (BINDING *)MALLOC(parser, sizeof(BINDING)); + if (! b) + return XML_ERROR_NO_MEMORY; ++ ++ /* Detect and prevent integer overflow */ ++ if (len > INT_MAX - EXPAND_SPARE) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + b->uri + = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (! b->uri) { +@@ -6141,7 +6229,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, + } + } else { + DEFAULT_ATTRIBUTE *temp; ++ ++ /* Detect and prevent integer overflow */ ++ if (type->allocDefaultAtts > INT_MAX / 2) { ++ return 0; ++ } ++ + int count = type->allocDefaultAtts * 2; ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { ++ return 0; ++ } ++#endif ++ + temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, + (count * sizeof(DEFAULT_ATTRIBUTE))); + if (temp == NULL) +@@ -6792,8 +6897,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { + /* check for overflow (table is half full) */ + if (table->used >> (table->power - 1)) { + unsigned char newPower = table->power + 1; ++ ++ /* Detect and prevent invalid shift */ ++ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) { ++ return NULL; ++ } ++ + size_t newSize = (size_t)1 << newPower; + unsigned long newMask = (unsigned long)newSize - 1; ++ ++ /* Detect and prevent integer overflow */ ++ if (newSize > (size_t)(-1) / sizeof(NAMED *)) { ++ return NULL; ++ } ++ + size_t tsize = newSize * sizeof(NAMED *); + NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); + if (! newV) +@@ -7143,6 +7260,20 @@ nextScaffoldPart(XML_Parser parser) { + if (dtd->scaffCount >= dtd->scaffSize) { + CONTENT_SCAFFOLD *temp; + if (dtd->scaffold) { ++ /* Detect and prevent integer overflow */ ++ if (dtd->scaffSize > UINT_MAX / 2u) { ++ return -1; ++ } ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { ++ return -1; ++ } ++#endif ++ + temp = (CONTENT_SCAFFOLD *)REALLOC( + parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) +@@ -7212,8 +7343,26 @@ build_model(XML_Parser parser) { + XML_Content *ret; + XML_Content *cpos; + XML_Char *str; +- int allocsize = (dtd->scaffCount * sizeof(XML_Content) +- + (dtd->contentStringLen * sizeof(XML_Char))); ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { ++ return NULL; ++ } ++ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { ++ return NULL; ++ } ++#endif ++ if (dtd->scaffCount * sizeof(XML_Content) ++ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { ++ return NULL; ++ } ++ ++ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) ++ + (dtd->contentStringLen * sizeof(XML_Char))); + + ret = (XML_Content *)MALLOC(parser, allocsize); + if (! ret) diff --git a/main/expat/CVE-2022-23852.patch b/main/expat/CVE-2022-23852.patch new file mode 100644 index 00000000000..fe020c441ed --- /dev/null +++ b/main/expat/CVE-2022-23852.patch @@ -0,0 +1,27 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/847a645152f5ebc10ac63b74b604d0c1a79fae40 +From 847a645152f5ebc10ac63b74b604d0c1a79fae40 Mon Sep 17 00:00:00 2001 +From: Samanta Navarro <ferivoz@riseup.net> +Date: Sat, 22 Jan 2022 17:48:00 +0100 +Subject: [PATCH] lib: Detect and prevent integer overflow in XML_GetBuffer + (CVE-2022-23852) + +--- + expat/lib/xmlparse.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index d54af683..5ce31402 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -2067,6 +2067,11 @@ XML_GetBuffer(XML_Parser parser, int len) { + keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; ++ /* Detect and prevent integer overflow */ ++ if (keep > INT_MAX - neededSize) { ++ parser->m_errorCode = XML_ERROR_NO_MEMORY; ++ return NULL; ++ } + neededSize += keep; + #endif /* defined XML_CONTEXT_BYTES */ + if (neededSize diff --git a/main/expat/CVE-2022-23990.patch b/main/expat/CVE-2022-23990.patch new file mode 100644 index 00000000000..f8cff18cb44 --- /dev/null +++ b/main/expat/CVE-2022-23990.patch @@ -0,0 +1,42 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/ede41d1e186ed2aba88a06e84cac839b770af3a1 +From ede41d1e186ed2aba88a06e84cac839b770af3a1 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Wed, 26 Jan 2022 02:36:43 +0100 +Subject: [PATCH] lib: Prevent integer overflow in doProlog (CVE-2022-23990) + +The change from "int nameLen" to "size_t nameLen" +addresses the overflow on "nameLen++" in code +"for (; name[nameLen++];)" right above the second +change in the patch. +--- + expat/lib/xmlparse.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 5ce31402..d1d17005 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -5372,7 +5372,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + if (dtd->in_eldecl) { + ELEMENT_TYPE *el; + const XML_Char *name; +- int nameLen; ++ size_t nameLen; + const char *nxt + = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar); + int myindex = nextScaffoldPart(parser); +@@ -5388,7 +5388,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + nameLen = 0; + for (; name[nameLen++];) + ; +- dtd->contentStringLen += nameLen; ++ ++ /* Detect and prevent integer overflow */ ++ if (nameLen > UINT_MAX - dtd->contentStringLen) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ dtd->contentStringLen += (unsigned)nameLen; + if (parser->m_elementDeclHandler) + handleDefault = XML_FALSE; + } diff --git a/main/expat/CVE-2022-25235.patch b/main/expat/CVE-2022-25235.patch new file mode 100644 index 00000000000..191ad980050 --- /dev/null +++ b/main/expat/CVE-2022-25235.patch @@ -0,0 +1,43 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/3f0a0cb644438d4d8e3294cd0b1245d0edb0c6c6 +From 3f0a0cb644438d4d8e3294cd0b1245d0edb0c6c6 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Tue, 8 Feb 2022 04:32:20 +0100 +Subject: [PATCH] lib: Add missing validation of encoding (CVE-2022-25235) + +--- + expat/lib/xmltok_impl.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/expat/lib/xmltok_impl.c b/expat/lib/xmltok_impl.c +index 0430591b4..64a3b2c15 100644 +--- a/lib/xmltok_impl.c ++++ b/lib/xmltok_impl.c +@@ -69,7 +69,7 @@ + case BT_LEAD##n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ +- if (! IS_NAME_CHAR(enc, ptr, n)) { \ ++ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ +@@ -98,7 +98,7 @@ + case BT_LEAD##n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ +- if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \ ++ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ +@@ -1142,6 +1142,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, + case BT_LEAD##n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ ++ if (IS_INVALID_CHAR(enc, ptr, n)) { \ ++ *nextTokPtr = ptr; \ ++ return XML_TOK_INVALID; \ ++ } \ + if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NAME; \ diff --git a/main/expat/CVE-2022-25236-regression.patch b/main/expat/CVE-2022-25236-regression.patch new file mode 100644 index 00000000000..2bcab601161 --- /dev/null +++ b/main/expat/CVE-2022-25236-regression.patch @@ -0,0 +1,171 @@ +non-code patches skipped +--- + +From 2ba6c76fca21397959145e18c5ef376201209020 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Sun, 27 Feb 2022 16:58:08 +0100 +Subject: [PATCH 1/5] lib: Relax fix to CVE-2022-25236 with regard to RFC 3986 + URI characters + +--- + expat/lib/xmlparse.c | 139 ++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 131 insertions(+), 8 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 59da19c8..6fe2cf1e 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3705,6 +3705,117 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + return XML_ERROR_NONE; + } + ++static XML_Bool ++is_rfc3986_uri_char(XML_Char candidate) { ++ // For the RFC 3986 ANBF grammar see ++ // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A ++ ++ switch (candidate) { ++ // From rule "ALPHA" (uppercase half) ++ case 'A': ++ case 'B': ++ case 'C': ++ case 'D': ++ case 'E': ++ case 'F': ++ case 'G': ++ case 'H': ++ case 'I': ++ case 'J': ++ case 'K': ++ case 'L': ++ case 'M': ++ case 'N': ++ case 'O': ++ case 'P': ++ case 'Q': ++ case 'R': ++ case 'S': ++ case 'T': ++ case 'U': ++ case 'V': ++ case 'W': ++ case 'X': ++ case 'Y': ++ case 'Z': ++ ++ // From rule "ALPHA" (lowercase half) ++ case 'a': ++ case 'b': ++ case 'c': ++ case 'd': ++ case 'e': ++ case 'f': ++ case 'g': ++ case 'h': ++ case 'i': ++ case 'j': ++ case 'k': ++ case 'l': ++ case 'm': ++ case 'n': ++ case 'o': ++ case 'p': ++ case 'q': ++ case 'r': ++ case 's': ++ case 't': ++ case 'u': ++ case 'v': ++ case 'w': ++ case 'x': ++ case 'y': ++ case 'z': ++ ++ // From rule "DIGIT" ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ ++ // From rule "pct-encoded" ++ case '%': ++ ++ // From rule "unreserved" ++ case '-': ++ case '.': ++ case '_': ++ case '~': ++ ++ // From rule "gen-delims" ++ case ':': ++ case '/': ++ case '?': ++ case '#': ++ case '[': ++ case ']': ++ case '@': ++ ++ // From rule "sub-delims" ++ case '!': ++ case '$': ++ case '&': ++ case '\'': ++ case '(': ++ case ')': ++ case '*': ++ case '+': ++ case ',': ++ case ';': ++ case '=': ++ return XML_TRUE; ++ ++ default: ++ return XML_FALSE; ++ } ++} ++ + /* addBinding() overwrites the value of prefix->binding without checking. + Therefore one must keep track of the old value outside of addBinding(). + */ +@@ -3763,14 +3874,26 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) + isXMLNS = XML_FALSE; + +- // NOTE: While Expat does not validate namespace URIs against RFC 3986, +- // we have to at least make sure that the XML processor on top of +- // Expat (that is splitting tag names by namespace separator into +- // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused +- // by an attacker putting additional namespace separator characters +- // into namespace declarations. That would be ambiguous and not to +- // be expected. +- if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) { ++ // NOTE: While Expat does not validate namespace URIs against RFC 3986 ++ // today (and is not REQUIRED to do so with regard to the XML 1.0 ++ // namespaces specification) we have to at least make sure, that ++ // the application on top of Expat (that is likely splitting expanded ++ // element names ("qualified names") of form ++ // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces ++ // in its element handler code) cannot be confused by an attacker ++ // putting additional namespace separator characters into namespace ++ // declarations. That would be ambiguous and not to be expected. ++ // ++ // While the HTML API docs of function XML_ParserCreateNS have been ++ // advising against use of a namespace separator character that can ++ // appear in a URI for >20 years now, some widespread applications ++ // are using URI characters (':' (colon) in particular) for a ++ // namespace separator, in practice. To keep these applications ++ // functional, we only reject namespaces URIs containing the ++ // application-chosen namespace separator if the chosen separator ++ // is a non-URI character with regard to RFC 3986. ++ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator) ++ && ! is_rfc3986_uri_char(uri[len])) { + return XML_ERROR_SYNTAX; + } + } + diff --git a/main/expat/CVE-2022-25236.patch b/main/expat/CVE-2022-25236.patch new file mode 100644 index 00000000000..ad91fc195fa --- /dev/null +++ b/main/expat/CVE-2022-25236.patch @@ -0,0 +1,33 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/a2fe525e660badd64b6c557c2b1ec26ddc07f6e4 +From a2fe525e660badd64b6c557c2b1ec26ddc07f6e4 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Sat, 12 Feb 2022 01:09:29 +0100 +Subject: [PATCH] lib: Protect against malicious namespace declarations + (CVE-2022-25236) + +--- + expat/lib/xmlparse.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index c768f856..a3aef88c 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3754,6 +3754,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + if (! mustBeXML && isXMLNS + && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) + isXMLNS = XML_FALSE; ++ ++ // NOTE: While Expat does not validate namespace URIs against RFC 3986, ++ // we have to at least make sure that the XML processor on top of ++ // Expat (that is splitting tag names by namespace separator into ++ // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused ++ // by an attacker putting additional namespace separator characters ++ // into namespace declarations. That would be ambiguous and not to ++ // be expected. ++ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) { ++ return XML_ERROR_SYNTAX; ++ } + } + isXML = isXML && len == xmlLen; + isXMLNS = isXMLNS && len == xmlnsLen; diff --git a/main/expat/CVE-2022-25313-regression.patch b/main/expat/CVE-2022-25313-regression.patch new file mode 100644 index 00000000000..eb313a4fe0a --- /dev/null +++ b/main/expat/CVE-2022-25313-regression.patch @@ -0,0 +1,242 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/9288cd5474bf6d3d0c037c247f9581d5e4df5097 +Patch 3/3 skipped due it being only a Changes readme change. +--- + +From b12f34fe32821a69dc12ff9a021daca0856de238 Mon Sep 17 00:00:00 2001 +From: Samanta Navarro <ferivoz@riseup.net> +Date: Sat, 19 Feb 2022 23:59:25 +0000 +Subject: [PATCH 1/3] Fix build_model regression. + +The iterative approach in build_model failed to fill children arrays +correctly. A preorder traversal is not required and turned out to be the +culprit. Use an easier algorithm: + +Add nodes from scaffold tree starting at index 0 (root) to the target +array whenever children are encountered. This ensures that children +are adjacent to each other. This complies with the recursive version. + +Store only the scaffold index in numchildren field to prevent a direct +processing of these children, which would require a recursive solution. +This allows the algorithm to iterate through the target array from start +to end without jumping back and forth, converting on the fly. + +Co-authored-by: Sebastian Pipping <sebastian@pipping.org> +--- + expat/lib/xmlparse.c | 79 ++++++++++++++++++++++++++------------------ + 1 file changed, 47 insertions(+), 32 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index c479a258..84885b5a 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -7373,39 +7373,58 @@ build_model(XML_Parser parser) { + * + * The iterative approach works as follows: + * +- * - We use space in the target array for building a temporary stack structure +- * while that space is still unused. +- * The stack grows from the array's end downwards and the "actual data" +- * grows from the start upwards, sequentially. +- * (Because stack grows downwards, pushing onto the stack is a decrement +- * while popping off the stack is an increment.) ++ * - We have two writing pointers, both walking up the result array; one does ++ * the work, the other creates "jobs" for its colleague to do, and leads ++ * the way: + * +- * - A stack element appears as a regular XML_Content node on the outside, +- * but only uses a single field -- numchildren -- to store the source +- * tree node array index. These are the breadcrumbs leading the way back +- * during pre-order (node first) depth-first traversal. ++ * - The faster one, pointer jobDest, always leads and writes "what job ++ * to do" by the other, once they reach that place in the ++ * array: leader "jobDest" stores the source node array index (relative ++ * to array dtd->scaffold) in field "numchildren". + * +- * - The reason we know the stack will never grow into (or overlap with) +- * the area with data of value at the start of the array is because +- * the overall number of elements to process matches the size of the array, +- * and the sum of fully processed nodes and yet-to-be processed nodes +- * on the stack, cannot be more than the total number of nodes. +- * It is possible for the top of the stack and the about-to-write node +- * to meet, but that is safe because we get the source index out +- * before doing any writes on that node. ++ * - The slower one, pointer dest, looks at the value stored in the ++ * "numchildren" field (which actually holds a source node array index ++ * at that time) and puts the real data from dtd->scaffold in. ++ * ++ * - Before the loop starts, jobDest writes source array index 0 ++ * (where the root node is located) so that dest will have something to do ++ * when it starts operation. ++ * ++ * - Whenever nodes with children are encountered, jobDest appends ++ * them as new jobs, in order. As a result, tree node siblings are ++ * adjacent in the resulting array, for example: ++ * ++ * [0] root, has two children ++ * [1] first child of 0, has three children ++ * [3] first child of 1, does not have children ++ * [4] second child of 1, does not have children ++ * [5] third child of 1, does not have children ++ * [2] second child of 0, does not have children ++ * ++ * Or (the same data) presented in flat array view: ++ * ++ * [0] root, has two children ++ * ++ * [1] first child of 0, has three children ++ * [2] second child of 0, does not have children ++ * ++ * [3] first child of 1, does not have children ++ * [4] second child of 1, does not have children ++ * [5] third child of 1, does not have children ++ * ++ * - The algorithm repeats until all target array indices have been processed. + */ + XML_Content *dest = ret; /* tree node writing location, moves upwards */ + XML_Content *const destLimit = &ret[dtd->scaffCount]; +- XML_Content *const stackBottom = &ret[dtd->scaffCount]; +- XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */ ++ XML_Content *jobDest = ret; /* next free writing location in target array */ + str = (XML_Char *)&ret[dtd->scaffCount]; + +- /* Push source tree root node index onto the stack */ +- (--stackTop)->numchildren = 0; ++ /* Add the starting job, the root node (index 0) of the source tree */ ++ (jobDest++)->numchildren = 0; + + for (; dest < destLimit; dest++) { +- /* Pop source tree node index off the stack */ +- const int src_node = (int)(stackTop++)->numchildren; ++ /* Retrieve source tree array index from job storage */ ++ const int src_node = (int)dest->numchildren; + + /* Convert item */ + dest->type = dtd->scaffold[src_node].type; +@@ -7427,16 +7446,12 @@ build_model(XML_Parser parser) { + int cn; + dest->name = NULL; + dest->numchildren = dtd->scaffold[src_node].childcnt; +- dest->children = &dest[1]; ++ dest->children = jobDest; + +- /* Push children to the stack +- * in a way where the first child ends up at the top of the +- * (downwards growing) stack, in order to be processed first. */ +- stackTop -= dest->numchildren; ++ /* Append scaffold indices of children to array */ + for (i = 0, cn = dtd->scaffold[src_node].firstchild; +- i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) { +- (stackTop + i)->numchildren = (unsigned int)cn; +- } ++ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) ++ (jobDest++)->numchildren = (unsigned int)cn; + } + } + + +From 154e565f6ef329c9ec97e6534c411ddde0b320c8 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Sun, 20 Feb 2022 03:26:57 +0100 +Subject: [PATCH 2/3] tests: Protect against nested element declaration model + regressions + +--- + expat/tests/runtests.c | 77 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c +index 2cd4acbe..e28670d2 100644 +--- a/tests/runtests.c ++++ b/tests/runtests.c +@@ -2664,6 +2664,82 @@ START_TEST(test_dtd_elements) { + } + END_TEST + ++static void XMLCALL ++element_decl_check_model(void *userData, const XML_Char *name, ++ XML_Content *model) { ++ UNUSED_P(userData); ++ uint32_t errorFlags = 0; ++ ++ /* Expected model array structure is this: ++ * [0] (type 6, quant 0) ++ * [1] (type 5, quant 0) ++ * [3] (type 4, quant 0, name "bar") ++ * [4] (type 4, quant 0, name "foo") ++ * [5] (type 4, quant 3, name "xyz") ++ * [2] (type 4, quant 2, name "zebra") ++ */ ++ errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0)); ++ errorFlags |= ((model != NULL) ? 0 : (1u << 1)); ++ ++ errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2)); ++ errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3)); ++ errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4)); ++ errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5)); ++ errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6)); ++ ++ errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7)); ++ errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8)); ++ errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9)); ++ errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10)); ++ errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11)); ++ ++ errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12)); ++ errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13)); ++ errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14)); ++ errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15)); ++ errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16)); ++ ++ errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17)); ++ errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18)); ++ errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19)); ++ errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20)); ++ errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21)); ++ ++ errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22)); ++ errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23)); ++ errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24)); ++ errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25)); ++ errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26)); ++ ++ errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27)); ++ errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28)); ++ errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29)); ++ errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30)); ++ errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31)); ++ ++ XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags); ++ XML_FreeContentModel(g_parser, model); ++} ++ ++START_TEST(test_dtd_elements_nesting) { ++ // Payload inspired by a test in Perl's XML::Parser ++ const char *text = "<!DOCTYPE foo [\n" ++ "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n" ++ "]>\n" ++ "<foo/>"; ++ ++ XML_SetUserData(g_parser, (void *)(uintptr_t)-1); ++ ++ XML_SetElementDeclHandler(g_parser, element_decl_check_model); ++ if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) ++ == XML_STATUS_ERROR) ++ xml_failure(g_parser); ++ ++ if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0) ++ fail("Element declaration model regression detected"); ++} ++END_TEST ++ + /* Test foreign DTD handling */ + START_TEST(test_set_foreign_dtd) { + const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"; +@@ -11863,6 +11939,7 @@ make_suite(void) { + tcase_add_test(tc_basic, test_memory_allocation); + tcase_add_test(tc_basic, test_default_current); + tcase_add_test(tc_basic, test_dtd_elements); ++ tcase_add_test(tc_basic, test_dtd_elements_nesting); + tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd); + tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone); + tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd); + diff --git a/main/expat/CVE-2022-25313.patch b/main/expat/CVE-2022-25313.patch new file mode 100644 index 00000000000..d0431bc0b2d --- /dev/null +++ b/main/expat/CVE-2022-25313.patch @@ -0,0 +1,223 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/bbdfcfef4747d2d66e81c19f4a55e29e291aa171 +From 9b4ce651b26557f16103c3a366c91934ecd439ab Mon Sep 17 00:00:00 2001 +From: Samanta Navarro <ferivoz@riseup.net> +Date: Tue, 15 Feb 2022 11:54:29 +0000 +Subject: [PATCH] Prevent stack exhaustion in build_model + +It is possible to trigger stack exhaustion in build_model function if +depth of nested children in DTD element is large enough. This happens +because build_node is a recursively called function within build_model. + +The code has been adjusted to run iteratively. It uses the already +allocated heap space as temporary stack (growing from top to bottom). + +Output is identical to recursive version. No new fields in data +structures were added, i.e. it keeps full API and ABI compatibility. +Instead the numchildren variable is used to temporarily keep the +index of items (uint vs int). + +Documentation and readability improvements kindly added by Sebastian. + +Proof of Concept: + +1. Compile poc binary which parses XML file line by line + +``` +cat > poc.c << EOF + #include <err.h> + #include <expat.h> + #include <stdio.h> + + XML_Parser parser; + + static void XMLCALL + dummy_element_decl_handler(void *userData, const XML_Char *name, + XML_Content *model) { + XML_FreeContentModel(parser, model); + } + + int main(int argc, char *argv[]) { + FILE *fp; + char *p = NULL; + size_t s = 0; + ssize_t l; + if (argc != 2) + errx(1, "usage: poc poc.xml"); + if ((parser = XML_ParserCreate(NULL)) == NULL) + errx(1, "XML_ParserCreate"); + XML_SetElementDeclHandler(parser, dummy_element_decl_handler); + if ((fp = fopen(argv[1], "r")) == NULL) + err(1, "fopen"); + while ((l = getline(&p, &s, fp)) > 0) + if (XML_Parse(parser, p, (int)l, XML_FALSE) != XML_STATUS_OK) + errx(1, "XML_Parse"); + XML_ParserFree(parser); + free(p); + fclose(fp); + return 0; + } +EOF +cc -std=c11 -D_POSIX_C_SOURCE=200809L -lexpat -o poc poc.c +``` + +2. Create XML file with a lot of nested groups in DTD element + +``` +cat > poc.xml.zst.b64 << EOF +KLUv/aQkACAAPAEA+DwhRE9DVFlQRSB1d3UgWwo8IUVMRU1FTlQgdXd1CigBAHv/58AJAgAQKAIA +ECgCABAoAgAQKAIAECgCABAoAgAQKHwAAChvd28KKQIA2/8gV24XBAIAECkCABApAgAQKQIAECkC +ABApAgAQKQIAEClVAAAgPl0+CgEA4A4I2VwwnQ== +EOF +base64 -d poc.xml.zst.b64 | zstd -d > poc.xml +``` + +3. Run Proof of Concept + +``` +./poc poc.xml +``` + +Co-authored-by: Sebastian Pipping <sebastian@pipping.org> +--- + expat/lib/xmlparse.c | 116 +++++++++++++++++++++++++++++-------------- + 1 file changed, 79 insertions(+), 37 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 4b43e613..594cf12c 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -7317,44 +7317,15 @@ nextScaffoldPart(XML_Parser parser) { + return next; + } + +-static void +-build_node(XML_Parser parser, int src_node, XML_Content *dest, +- XML_Content **contpos, XML_Char **strpos) { +- DTD *const dtd = parser->m_dtd; /* save one level of indirection */ +- dest->type = dtd->scaffold[src_node].type; +- dest->quant = dtd->scaffold[src_node].quant; +- if (dest->type == XML_CTYPE_NAME) { +- const XML_Char *src; +- dest->name = *strpos; +- src = dtd->scaffold[src_node].name; +- for (;;) { +- *(*strpos)++ = *src; +- if (! *src) +- break; +- src++; +- } +- dest->numchildren = 0; +- dest->children = NULL; +- } else { +- unsigned int i; +- int cn; +- dest->numchildren = dtd->scaffold[src_node].childcnt; +- dest->children = *contpos; +- *contpos += dest->numchildren; +- for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren; +- i++, cn = dtd->scaffold[cn].nextsib) { +- build_node(parser, cn, &(dest->children[i]), contpos, strpos); +- } +- dest->name = NULL; +- } +-} +- + static XML_Content * + build_model(XML_Parser parser) { ++ /* Function build_model transforms the existing parser->m_dtd->scaffold ++ * array of CONTENT_SCAFFOLD tree nodes into a new array of ++ * XML_Content tree nodes followed by a gapless list of zero-terminated ++ * strings. */ + DTD *const dtd = parser->m_dtd; /* save one level of indirection */ + XML_Content *ret; +- XML_Content *cpos; +- XML_Char *str; ++ XML_Char *str; /* the current string writing location */ + + /* Detect and prevent integer overflow. + * The preprocessor guard addresses the "always false" warning +@@ -7380,10 +7351,81 @@ build_model(XML_Parser parser) { + if (! ret) + return NULL; + +- str = (XML_Char *)(&ret[dtd->scaffCount]); +- cpos = &ret[1]; ++ /* What follows is an iterative implementation (of what was previously done ++ * recursively in a dedicated function called "build_node". The old recursive ++ * build_node could be forced into stack exhaustion from input as small as a ++ * few megabyte, and so that was a security issue. Hence, a function call ++ * stack is avoided now by resolving recursion.) ++ * ++ * The iterative approach works as follows: ++ * ++ * - We use space in the target array for building a temporary stack structure ++ * while that space is still unused. ++ * The stack grows from the array's end downwards and the "actual data" ++ * grows from the start upwards, sequentially. ++ * (Because stack grows downwards, pushing onto the stack is a decrement ++ * while popping off the stack is an increment.) ++ * ++ * - A stack element appears as a regular XML_Content node on the outside, ++ * but only uses a single field -- numchildren -- to store the source ++ * tree node array index. These are the breadcrumbs leading the way back ++ * during pre-order (node first) depth-first traversal. ++ * ++ * - The reason we know the stack will never grow into (or overlap with) ++ * the area with data of value at the start of the array is because ++ * the overall number of elements to process matches the size of the array, ++ * and the sum of fully processed nodes and yet-to-be processed nodes ++ * on the stack, cannot be more than the total number of nodes. ++ * It is possible for the top of the stack and the about-to-write node ++ * to meet, but that is safe because we get the source index out ++ * before doing any writes on that node. ++ */ ++ XML_Content *dest = ret; /* tree node writing location, moves upwards */ ++ XML_Content *const destLimit = &ret[dtd->scaffCount]; ++ XML_Content *const stackBottom = &ret[dtd->scaffCount]; ++ XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */ ++ str = (XML_Char *)&ret[dtd->scaffCount]; ++ ++ /* Push source tree root node index onto the stack */ ++ (--stackTop)->numchildren = 0; ++ ++ for (; dest < destLimit; dest++) { ++ /* Pop source tree node index off the stack */ ++ const int src_node = (int)(stackTop++)->numchildren; ++ ++ /* Convert item */ ++ dest->type = dtd->scaffold[src_node].type; ++ dest->quant = dtd->scaffold[src_node].quant; ++ if (dest->type == XML_CTYPE_NAME) { ++ const XML_Char *src; ++ dest->name = str; ++ src = dtd->scaffold[src_node].name; ++ for (;;) { ++ *str++ = *src; ++ if (! *src) ++ break; ++ src++; ++ } ++ dest->numchildren = 0; ++ dest->children = NULL; ++ } else { ++ unsigned int i; ++ int cn; ++ dest->name = NULL; ++ dest->numchildren = dtd->scaffold[src_node].childcnt; ++ dest->children = &dest[1]; ++ ++ /* Push children to the stack ++ * in a way where the first child ends up at the top of the ++ * (downwards growing) stack, in order to be processed first. */ ++ stackTop -= dest->numchildren; ++ for (i = 0, cn = dtd->scaffold[src_node].firstchild; ++ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) { ++ (stackTop + i)->numchildren = (unsigned int)cn; ++ } ++ } ++ } + +- build_node(parser, 0, ret, &cpos, &str); + return ret; + } + diff --git a/main/expat/CVE-2022-25314.patch b/main/expat/CVE-2022-25314.patch new file mode 100644 index 00000000000..25674a43837 --- /dev/null +++ b/main/expat/CVE-2022-25314.patch @@ -0,0 +1,25 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/d477fdd284468f2ab822024e75702f2c1b254f42 +From efcb347440ade24b9f1054671e6bd05e60b4cafd Mon Sep 17 00:00:00 2001 +From: Samanta Navarro <ferivoz@riseup.net> +Date: Tue, 15 Feb 2022 11:56:57 +0000 +Subject: [PATCH] Prevent integer overflow in copyString + +The copyString function is only used for encoding string supplied by +the library user. +--- + expat/lib/xmlparse.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 4b43e613..a39377c2 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -7412,7 +7412,7 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, + + static XML_Char * + copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { +- int charsRequired = 0; ++ size_t charsRequired = 0; + XML_Char *result; + + /* First determine how long the string is */ diff --git a/main/expat/CVE-2022-25315.patch b/main/expat/CVE-2022-25315.patch new file mode 100644 index 00000000000..fe0e8f298a2 --- /dev/null +++ b/main/expat/CVE-2022-25315.patch @@ -0,0 +1,139 @@ +Patch-Source: https://github.com/libexpat/libexpat/commit/89214940efd13e3b83fa078fd70eb4dbdc04c4a5 +From eb0362808b4f9f1e2345a0cf203b8cc196d776d9 Mon Sep 17 00:00:00 2001 +From: Samanta Navarro <ferivoz@riseup.net> +Date: Tue, 15 Feb 2022 11:55:46 +0000 +Subject: [PATCH] Prevent integer overflow in storeRawNames + +It is possible to use an integer overflow in storeRawNames for out of +boundary heap writes. Default configuration is affected. If compiled +with XML_UNICODE then the attack does not work. Compiling with +-fsanitize=address confirms the following proof of concept. + +The problem can be exploited by abusing the m_buffer expansion logic. +Even though the initial size of m_buffer is a power of two, eventually +it can end up a little bit lower, thus allowing allocations very close +to INT_MAX (since INT_MAX/2 can be surpassed). This means that tag +names can be parsed which are almost INT_MAX in size. + +Unfortunately (from an attacker point of view) INT_MAX/2 is also a +limitation in string pools. Having a tag name of INT_MAX/2 characters +or more is not possible. + +Expat can convert between different encodings. UTF-16 documents which +contain only ASCII representable characters are twice as large as their +ASCII encoded counter-parts. + +The proof of concept works by taking these three considerations into +account: + +1. Move the m_buffer size slightly below a power of two by having a + short root node <a>. This allows the m_buffer to grow very close + to INT_MAX. +2. The string pooling forbids tag names longer than or equal to + INT_MAX/2, so keep the attack tag name smaller than that. +3. To be able to still overflow INT_MAX even though the name is + limited at INT_MAX/2-1 (nul byte) we use UTF-16 encoding and a tag + which only contains ASCII characters. UTF-16 always stores two + bytes per character while the tag name is converted to using only + one. Our attack node byte count must be a bit higher than + 2/3 INT_MAX so the converted tag name is around INT_MAX/3 which + in sum can overflow INT_MAX. + +Thanks to our small root node, m_buffer can handle 2/3 INT_MAX bytes +without running into INT_MAX boundary check. The string pooling is +able to store INT_MAX/3 as tag name because the amount is below +INT_MAX/2 limitation. And creating the sum of both eventually overflows +in storeRawNames. + +Proof of Concept: + +1. Compile expat with -fsanitize=address. + +2. Create Proof of Concept binary which iterates through input + file 16 MB at once for better performance and easier integer + calculations: + +``` +cat > poc.c << EOF + #include <err.h> + #include <expat.h> + #include <stdlib.h> + #include <stdio.h> + + #define CHUNK (16 * 1024 * 1024) + int main(int argc, char *argv[]) { + XML_Parser parser; + FILE *fp; + char *buf; + int i; + + if (argc != 2) + errx(1, "usage: poc file.xml"); + if ((parser = XML_ParserCreate(NULL)) == NULL) + errx(1, "failed to create expat parser"); + if ((fp = fopen(argv[1], "r")) == NULL) { + XML_ParserFree(parser); + err(1, "failed to open file"); + } + if ((buf = malloc(CHUNK)) == NULL) { + fclose(fp); + XML_ParserFree(parser); + err(1, "failed to allocate buffer"); + } + i = 0; + while (fread(buf, CHUNK, 1, fp) == 1) { + printf("iteration %d: XML_Parse returns %d\n", ++i, + XML_Parse(parser, buf, CHUNK, XML_FALSE)); + } + free(buf); + fclose(fp); + XML_ParserFree(parser); + return 0; + } +EOF +gcc -fsanitize=address -lexpat -o poc poc.c +``` + +3. Construct specially prepared UTF-16 XML file: + +``` +dd if=/dev/zero bs=1024 count=794624 | tr '\0' 'a' > poc-utf8.xml +echo -n '<a><' | dd conv=notrunc of=poc-utf8.xml +echo -n '><' | dd conv=notrunc of=poc-utf8.xml bs=1 seek=805306368 +iconv -f UTF-8 -t UTF-16LE poc-utf8.xml > poc-utf16.xml +``` + +4. Run proof of concept: + +``` +./poc poc-utf16.xml +``` +--- + expat/lib/xmlparse.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 4b43e613..f34d6ab5 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -2563,6 +2563,7 @@ storeRawNames(XML_Parser parser) { + while (tag) { + int bufSize; + int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); ++ size_t rawNameLen; + char *rawNameBuf = tag->buf + nameLen; + /* Stop if already stored. Since m_tagStack is a stack, we can stop + at the first entry that has already been copied; everything +@@ -2574,7 +2575,11 @@ storeRawNames(XML_Parser parser) { + /* For re-use purposes we need to ensure that the + size of tag->buf is a multiple of sizeof(XML_Char). + */ +- bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); ++ rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); ++ /* Detect and prevent integer overflow. */ ++ if (rawNameLen > (size_t)INT_MAX - nameLen) ++ return XML_FALSE; ++ bufSize = nameLen + (int)rawNameLen; + if (bufSize > tag->bufEnd - tag->buf) { + char *temp = (char *)REALLOC(parser, tag->buf, bufSize); + if (temp == NULL) diff --git a/main/flac/APKBUILD b/main/flac/APKBUILD index d358fe2167e..2e62156cfb2 100644 --- a/main/flac/APKBUILD +++ b/main/flac/APKBUILD @@ -1,6 +1,6 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=flac -pkgver=1.3.3 +pkgver=1.3.4 pkgrel=0 pkgdesc="Free Lossless Audio Codec" url="https://xiph.org/flac/" @@ -12,6 +12,9 @@ makedepends="libogg-dev !libiconv" source="http://downloads.xiph.org/releases/flac/flac-$pkgver.tar.xz" # secfixes: +# 1.3.4-r0: +# - CVE-2020-0499 +# - CVE-2021-0561 # 1.3.2-r2: # - CVE-2017-6888 @@ -47,4 +50,6 @@ package() { install -Dm0644 COPYING.Xiph \ "$pkgdir"/usr/share/licenses/$pkgname/COPYING.Xiph } -sha512sums="d6417e14fab0c41b2df369e5e39ce62a5f588e491af4d465b0162f74e171e5549b2f061867f344bfbf8aaccd246bf5f2acd697e532a2c7901c920c69429b1a28 flac-1.3.3.tar.xz" +sha512sums=" +4a626e8a1bd126e234c0e5061e3b46f3a27c2065fdfa228fd8cf00d3c7fa2c05fafb5cec36acce7bfce4914bfd7db0b2a27ee15decf2d8c4caad630f62d44ec9 flac-1.3.4.tar.xz +" diff --git a/main/freetype/APKBUILD b/main/freetype/APKBUILD index 4f4a39fe785..798c89fae90 100644 --- a/main/freetype/APKBUILD +++ b/main/freetype/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Carlo Landmeter <clandmeter@gmail.com> pkgname=freetype pkgver=2.10.4 -pkgrel=0 +pkgrel=2 pkgdesc="TrueType font rendering library" url="https://www.freetype.org/" arch="all" @@ -13,9 +13,17 @@ subpackages="$pkgname-static $pkgname-dev $pkgname-doc" source="https://download.savannah.gnu.org/releases/freetype/freetype-$pkgver.tar.xz 0001-Enable-table-validation-modules.patch subpixel.patch + CVE-2022-27404.patch + CVE-2022-27405.patch + CVE-2022-27406.patch " # secfixes: +# 2.10.4-r2: +# - CVE-2022-27405 +# - CVE-2022-27406 +# 2.10.4-r1: +# - CVE-2022-27404 # 2.10.4-r0: # - CVE-2020-15999 # 2.9-r1: @@ -51,6 +59,11 @@ package() { make DESTDIR="$pkgdir" install } -sha512sums="827cda734aa6b537a8bcb247549b72bc1e082a5b32ab8d3cccb7cc26d5f6ee087c19ce34544fa388a1eb4ecaf97600dbabc3e10e950f2ba692617fee7081518f freetype-2.10.4.tar.xz +sha512sums=" +827cda734aa6b537a8bcb247549b72bc1e082a5b32ab8d3cccb7cc26d5f6ee087c19ce34544fa388a1eb4ecaf97600dbabc3e10e950f2ba692617fee7081518f freetype-2.10.4.tar.xz 580fe59acddfd41966e387bdb6a88336b8bc119cc3d60d8689be20c96fb0dd07c5138ea31f6cb9c854f497ecb41c3adc49eb3ec16a34b2e010e8294851770763 0001-Enable-table-validation-modules.patch -72883fa203fd2552a7b1b8c39b4aaa68d407c62c289236031cd0fa1c8cdc6ad38e90d3b53f8ee682064986d09c9455961f4941c80566b150d15d5539a716c190 subpixel.patch" +72883fa203fd2552a7b1b8c39b4aaa68d407c62c289236031cd0fa1c8cdc6ad38e90d3b53f8ee682064986d09c9455961f4941c80566b150d15d5539a716c190 subpixel.patch +a00040fddd30f8b7add990c4614cbe69a04d702c471064eaf1f28b70a24c35e25e430bc8ae1d90f198b3e432d90c8884519db30fab2e41e467892d79f5cdee8f CVE-2022-27404.patch +4e4ed4b325ca8dbbd7362782867901b90eef48cb78d6a030769c33add029d4f61ddafe590c1cca35edd8e2b0c128106b7e01874acf52ac7c2b475f4ca6cf8cdf CVE-2022-27405.patch +574f0a93a022ba8bae4440012dd4062841187e1af4e906e5a8f117549a7e528e9d4a0bd35833294248f3a71b299175cbf6d144231af29d8d2dd350bc7dc5b804 CVE-2022-27406.patch +" diff --git a/main/freetype/CVE-2022-27404.patch b/main/freetype/CVE-2022-27404.patch new file mode 100644 index 00000000000..841ab4c5932 --- /dev/null +++ b/main/freetype/CVE-2022-27404.patch @@ -0,0 +1,44 @@ +Patch-Source: https://gitlab.freedesktop.org/freetype/freetype/-/commit/53dfdcd8198d2b3201a23c4bad9190519ba918db +From 53dfdcd8198d2b3201a23c4bad9190519ba918db Mon Sep 17 00:00:00 2001 +From: Werner Lemberg <wl@gnu.org> +Date: Thu, 17 Mar 2022 19:24:16 +0100 +Subject: [PATCH] [sfnt] Avoid invalid face index. + +Fixes #1138. + +* src/sfnt/sfobjs.c (sfnt_init_face), src/sfnt/sfwoff2.c (woff2_open_font): +Check `face_index` before decrementing. +--- + src/sfnt/sfobjs.c | 2 +- + src/sfnt/sfwoff2.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c +index f9d4d3858..9771c35df 100644 +--- a/src/sfnt/sfobjs.c ++++ b/src/sfnt/sfobjs.c +@@ -566,7 +566,7 @@ + face_index = FT_ABS( face_instance_index ) & 0xFFFF; + + /* value -(N+1) requests information on index N */ +- if ( face_instance_index < 0 ) ++ if ( face_instance_index < 0 && face_index > 0 ) + face_index--; + + if ( face_index >= face->ttc_header.count ) +diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c +index cb1e0664a..165b875e5 100644 +--- a/src/sfnt/sfwoff2.c ++++ b/src/sfnt/sfwoff2.c +@@ -2085,7 +2085,7 @@ + /* Validate requested face index. */ + *num_faces = woff2.num_fonts; + /* value -(N+1) requests information on index N */ +- if ( *face_instance_index < 0 ) ++ if ( *face_instance_index < 0 && face_index > 0 ) + face_index--; + + if ( face_index >= woff2.num_fonts ) +-- +GitLab + diff --git a/main/freetype/CVE-2022-27405.patch b/main/freetype/CVE-2022-27405.patch new file mode 100644 index 00000000000..47668676013 --- /dev/null +++ b/main/freetype/CVE-2022-27405.patch @@ -0,0 +1,36 @@ +From 22a0cccb4d9d002f33c1ba7a4b36812c7d4f46b5 Mon Sep 17 00:00:00 2001 +From: Werner Lemberg <wl@gnu.org> +Date: Sat, 19 Mar 2022 06:40:17 +0100 +Subject: [PATCH] * src/base/ftobjs.c (ft_open_face_internal): Properly guard + `face_index`. + +We must ensure that the cast to `FT_Int` doesn't change the sign. + +Fixes #1139. +--- + src/base/ftobjs.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c +index 2c0f0e6c9..10952a6c6 100644 +--- a/src/base/ftobjs.c ++++ b/src/base/ftobjs.c +@@ -2527,6 +2527,15 @@ + #endif + + ++ /* only use lower 31 bits together with sign bit */ ++ if ( face_index > 0 ) ++ face_index &= 0x7FFFFFFFL; ++ else ++ { ++ face_index &= 0x7FFFFFFFL; ++ face_index = -face_index; ++ } ++ + #ifdef FT_DEBUG_LEVEL_TRACE + FT_TRACE3(( "FT_Open_Face: " )); + if ( face_index < 0 ) +-- +GitLab + diff --git a/main/freetype/CVE-2022-27406.patch b/main/freetype/CVE-2022-27406.patch new file mode 100644 index 00000000000..0fdef7d2164 --- /dev/null +++ b/main/freetype/CVE-2022-27406.patch @@ -0,0 +1,27 @@ +From 0c2bdb01a2e1d24a3e592377a6d0822856e10df2 Mon Sep 17 00:00:00 2001 +From: Werner Lemberg <wl@gnu.org> +Date: Sat, 19 Mar 2022 09:37:28 +0100 +Subject: [PATCH] * src/base/ftobjs.c (FT_Request_Size): Guard `face->size`. + +Fixes #1140. +--- + src/base/ftobjs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c +index 6492a1517..282c9121a 100644 +--- a/src/base/ftobjs.c ++++ b/src/base/ftobjs.c +@@ -3409,6 +3409,9 @@ + if ( !face ) + return FT_THROW( Invalid_Face_Handle ); + ++ if ( !face->size ) ++ return FT_THROW( Invalid_Size_Handle ); ++ + if ( !req || req->width < 0 || req->height < 0 || + req->type >= FT_SIZE_REQUEST_TYPE_MAX ) + return FT_THROW( Invalid_Argument ); +-- +GitLab + diff --git a/main/gcc/APKBUILD b/main/gcc/APKBUILD index fe52d00a805..afffad628f6 100644 --- a/main/gcc/APKBUILD +++ b/main/gcc/APKBUILD @@ -14,7 +14,7 @@ license="GPL-2.0-or-later LGPL-2.1-or-later" _gccrel=$pkgver-r$pkgrel depends="binutils$_target isl" makedepends_build="gcc$_cross g++$_cross paxmark bison flex texinfo gawk zip gmp-dev mpfr-dev mpc1-dev zlib-dev" -makedepends_host="linux-headers gmp-dev mpfr-dev mpc1-dev isl-dev zlib-dev !gettext-dev $pkgname-gnat-bootstrap" +makedepends_host="linux-headers gmp-dev mpfr-dev mpc1-dev isl-dev zlib-dev !gettext-dev" subpackages=" " [ "$CHOST" = "$CTARGET" ] && subpackages="gcc-doc$_target" replaces="libstdc++ binutils" @@ -144,7 +144,8 @@ fi if $LANG_ADA; then subpackages="$subpackages libgnat::$CTARGET_ARCH gcc-gnat$_target:gnat" _languages="$_languages,ada" - makedepends_build="$makedepends_build gcc-gnat gcc-gnat$_cross" + [ "$CBUILD" = "$CTARGET" ] && makedepends_build="$makedepends_build gcc-gnat-bootstrap" + [ "$CBUILD" != "$CTARGET" ] && makedepends_build="$makedepends_build gcc-gnat gcc-gnat$_cross" fi makedepends="$makedepends_build $makedepends_host" diff --git a/main/git/APKBUILD b/main/git/APKBUILD index 855bd6037c7..997df31b0e7 100644 --- a/main/git/APKBUILD +++ b/main/git/APKBUILD @@ -2,6 +2,8 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> # # secfixes: +# 2.26.3-r1: +# - CVE-2021-40330 # 2.26.3-r0: # - CVE-2021-21300 # 2.26.2-r0: @@ -27,10 +29,11 @@ # - CVE-2017-1000117 # 0: # - CVE-2021-29468 +# - CVE-2021-46101 pkgname=git pkgver=2.26.3 -pkgrel=0 +pkgrel=1 pkgdesc="Distributed version control system" url="https://www.git-scm.com/" arch="all" @@ -61,6 +64,7 @@ subpackages="$pkgname-doc source="https://www.kernel.org/pub/software/scm/git/git-$pkgver.tar.xz git-daemon.initd git-daemon.confd + CVE-2021-40330.patch " _gitcoredir=/usr/libexec/git-core @@ -288,4 +292,5 @@ _perl_config() { sha512sums="a88f8ab156f12770590110b30da83631f19a349f3b7af25fd0a5e8f03c78daec0a4935e9a1a5637f100c147cc57fca4aa3386e18756a6382983e7baa7456e398 git-2.26.3.tar.xz 89528cdd14c51fd568aa61cf6c5eae08ea0844e59f9af9292da5fc6c268261f4166017d002d494400945e248df6b844e2f9f9cd2d9345d516983f5a110e4c42a git-daemon.initd -fbf1f425206a76e2a8f82342537ed939ff7e623d644c086ca2ced5f69b36734695f9f80ebda1728f75a94d6cd2fcb71bf845b64239368caab418e4d368c141ec git-daemon.confd" +fbf1f425206a76e2a8f82342537ed939ff7e623d644c086ca2ced5f69b36734695f9f80ebda1728f75a94d6cd2fcb71bf845b64239368caab418e4d368c141ec git-daemon.confd +739ed7c43e97384d970058b0edd58a665b1f879f87cd469e85991e6be3a3714be8c52326217f107861afd08c815ddd7a98230286cacd5a21757e5a1739152159 CVE-2021-40330.patch" diff --git a/main/git/CVE-2021-40330.patch b/main/git/CVE-2021-40330.patch new file mode 100644 index 00000000000..1722b530e4c --- /dev/null +++ b/main/git/CVE-2021-40330.patch @@ -0,0 +1,101 @@ +From a02ea577174ab8ed18f847cf1693f213e0b9c473 Mon Sep 17 00:00:00 2001 +From: Jeff King <peff@peff.net> +Date: Thu, 7 Jan 2021 04:43:58 -0500 +Subject: [PATCH] git_connect_git(): forbid newlines in host and path + +When we connect to a git:// server, we send an initial request that +looks something like: + + 002dgit-upload-pack repo.git\0host=example.com + +If the repo path contains a newline, then it's included literally, and +we get: + + 002egit-upload-pack repo + .git\0host=example.com + +This works fine if you really do have a newline in your repository name; +the server side uses the pktline framing to parse the string, not +newlines. However, there are many _other_ protocols in the wild that do +parse on newlines, such as HTTP. So a carefully constructed git:// URL +can actually turn into a valid HTTP request. For example: + + git://localhost:1234/%0d%0a%0d%0aGET%20/%20HTTP/1.1 %0d%0aHost:localhost%0d%0a%0d%0a + +becomes: + + 0050git-upload-pack / + GET / HTTP/1.1 + Host:localhost + + host=localhost:1234 + +on the wire. Again, this isn't a problem for a real Git server, but it +does mean that feeding a malicious URL to Git (e.g., through a +submodule) can cause it to make unexpected cross-protocol requests. +Since repository names with newlines are presumably quite rare (and +indeed, we already disallow them in git-over-http), let's just disallow +them over this protocol. + +Hostnames could likewise inject a newline, but this is unlikely a +problem in practice; we'd try resolving the hostname with a newline in +it, which wouldn't work. Still, it doesn't hurt to err on the side of +caution there, since we would not expect them to work in the first +place. + +The ssh and local code paths are unaffected by this patch. In both cases +we're trying to run upload-pack via a shell, and will quote the newline +so that it makes it intact. An attacker can point an ssh url at an +arbitrary port, of course, but unless there's an actual ssh server +there, we'd never get as far as sending our shell command anyway. We +_could_ similarly restrict newlines in those protocols out of caution, +but there seems little benefit to doing so. + +The new test here is run alongside the git-daemon tests, which cover the +same protocol, but it shouldn't actually contact the daemon at all. In +theory we could make the test more robust by setting up an actual +repository with a newline in it (so that our clone would succeed if our +new check didn't kick in). But a repo directory with newline in it is +likely not portable across all filesystems. Likewise, we could check +git-daemon's log that it was not contacted at all, but we do not +currently record the log (and anyway, it would make the test racy with +the daemon's log write). We'll just check the client-side stderr to make +sure we hit the expected code path. + +Reported-by: Harold Kim <h.kim@flatt.tech> +Signed-off-by: Jeff King <peff@peff.net> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +--- + connect.c | 2 ++ + t/t5570-git-daemon.sh | 5 +++++ + 2 files changed, 7 insertions(+) + +diff --git a/connect.c b/connect.c +index 79f1b3b24257a..7b4b65751d43d 100644 +--- a/connect.c ++++ b/connect.c +@@ -1063,6 +1063,8 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport, + target_host = xstrdup(hostandport); + + transport_check_allowed("git"); ++ if (strchr(target_host, '\n') || strchr(path, '\n')) ++ die(_("newline is forbidden in git:// hosts and repo paths")); + + /* + * These underlying connection commands die() if they +diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh +index 7466aad111fe4..336d417a90f87 100755 +--- a/t/t5570-git-daemon.sh ++++ b/t/t5570-git-daemon.sh +@@ -102,6 +102,11 @@ test_expect_success 'fetch notices corrupt idx' ' + ) + ' + ++test_expect_success 'client refuses to ask for repo with newline' ' ++ test_must_fail git clone "$GIT_DAEMON_URL/repo$LF.git" dst 2>stderr && ++ test_i18ngrep newline.is.forbidden stderr ++' ++ + test_remote_error() + { + do_export=YesPlease diff --git a/main/gmp/APKBUILD b/main/gmp/APKBUILD index 3dc82ba612b..691d934d618 100644 --- a/main/gmp/APKBUILD +++ b/main/gmp/APKBUILD @@ -1,17 +1,22 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=gmp -pkgver=6.2.0 -pkgrel=0 -pkgdesc="A free library for arbitrary precision arithmetic" +pkgver=6.2.1 +pkgrel=1 +pkgdesc="free library for arbitrary precision arithmetic" url="https://gmplib.org/" arch="all" -license="LGPL-3.0-or-later" +license="LGPL-3.0-or-later OR GPL-2.0-or-later" makedepends="m4 texinfo libtool" subpackages="$pkgname-doc $pkgname-dev libgmpxx" source="https://gmplib.org/download/gmp/gmp-$pkgver.tar.xz + CVE-2021-43618.patch::https://gmplib.org/repo/gmp-6.2/raw-rev/561a9c25298e " replaces="gmp5" +# secfixes: +# 6.2.1-r1: +# - CVE-2021-43618 + prepare() { default_prepare # force update to libtool with fixed cross-build support @@ -33,7 +38,7 @@ build() { } package() { - make -j1 DESTDIR="$pkgdir" install + make DESTDIR="$pkgdir" install } check() { @@ -51,4 +56,5 @@ doc() { replaces="gmp5-doc" } -sha512sums="a066f0456f0314a1359f553c49fc2587e484ff8ac390ff88537266a146ea373f97a1c0ba24608bf6756f4eab11c9056f103c8deb99e5b57741b4f7f0ec44b90c gmp-6.2.0.tar.xz" +sha512sums="c99be0950a1d05a0297d65641dd35b75b74466f7bf03c9e8a99895a3b2f9a0856cd17887738fa51cf7499781b65c049769271cbcb77d057d2e9f1ec52e07dd84 gmp-6.2.1.tar.xz +3956190d9c266feb62f8965c3cd32d0a9260f76ffb0d3e32211974bb53ddd5c6eaa657f7e00ba8fa7c914c0e1375155d25de6a81cdb9b03d6a5bbc16ac121447 CVE-2021-43618.patch" diff --git a/main/gzip/APKBUILD b/main/gzip/APKBUILD index 2ea52d44caf..92a548f46d6 100644 --- a/main/gzip/APKBUILD +++ b/main/gzip/APKBUILD @@ -1,22 +1,21 @@ # Contributor: Leonardo Arena <rnalrd@alpinelinux.org> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=gzip -pkgver=1.10 +pkgver=1.12 pkgrel=0 -pkgdesc="A popular data compression program" +pkgdesc="Popular data compression program" subpackages="$pkgname-doc" url="https://www.gnu.org/software/gzip/" arch="all" -license="GPL-2.0" -depends= -makedepends= -checkdepends="less" -install= -source="https://ftp.gnu.org/gnu/gzip/gzip-$pkgver.tar.gz" +license="GPL-3.0-or-later" +depends="less" +source="https://ftp.gnu.org/gnu/gzip/gzip-$pkgver.tar.xz" -build() { - cd "$builddir" +# secfixes: +# 1.12-r0: +# - CVE-2022-1271 +build() { # avoid text relocation export DEFS="NO_ASM" ./configure \ @@ -29,12 +28,10 @@ build() { } check() { - cd "$builddir" make check } package() { - cd "$builddir" make DESTDIR=$pkgdir install rm -rf "$pkgdir"/usr/lib/charset.alias @@ -49,4 +46,6 @@ package() { ln -sf /bin/gunzip "$pkgdir"/usr/bin/uncompress } -sha512sums="7939043e74554ced0c1c05d354ab4eb36cd6dce89ad79d02ccdc5ed6b7ee390759689b2d47c07227b9b44a62851afe7c76c4cae9f92527d999f3f1b4df1cccff gzip-1.10.tar.gz" +sha512sums=" +116326fe991828227de150336a0c016f4fe932dfbb728a16b4a84965256d9929574a4f5cfaf3cf6bb4154972ef0d110f26ab472c93e62ec9a5fd7a5d65abea24 gzip-1.12.tar.xz +" diff --git a/main/haproxy/APKBUILD b/main/haproxy/APKBUILD index b6d0bc80145..e831425ecf8 100644 --- a/main/haproxy/APKBUILD +++ b/main/haproxy/APKBUILD @@ -2,9 +2,9 @@ # Contributor: Natanael Copa <ncopa@alpinelinux.org> # Maintainer: Milan P. Stanić <mps@arvanta.net> pkgname=haproxy -pkgver=2.2.17 +pkgver=2.2.24 _pkgmajorver=${pkgver%.*} -pkgrel=1 +pkgrel=0 pkgdesc="A TCP/HTTP reverse proxy for high availability environments" url="https://www.haproxy.org/" arch="all" @@ -19,6 +19,8 @@ source="https://www.haproxy.org/download/$_pkgmajorver/src/haproxy-$pkgver.tar.g haproxy.cfg" # secfixes: +# 2.2.21-r0: +# - CVE-2022-0711 # 2.1.4-r0: # - CVE-2020-11100 @@ -54,7 +56,7 @@ package() { } sha512sums=" -174197e1e0915a6ae6062b9a070f16102ac7f3429f991f36cdb2e2cce587bd26059bd1dc71a368f904bcdecd292ab5926715160400ae96d498d902aac356864f haproxy-2.2.17.tar.gz +021d065e53503248de122fdd9431786b9f375a5f87aca76f870e17e44c8c4001a778bfb4e430b28af781a3f175f3643a549e363e964210c717f212c5966e68d8 haproxy-2.2.24.tar.gz 3ab277bf77fe864ec6c927118dcd70bdec0eb3c54535812d1c3c0995fa66a3ea91a73c342edeb8944caeb097d2dd1a7761099182df44af5e3ef42de6e2176d26 haproxy.initd 26bc8f8ac504fcbaec113ecbb9bb59b9da47dc8834779ebbb2870a8cadf2ee7561b3a811f01e619358a98c6c7768e8fdd90ab447098c05b82e788c8212c4c41f haproxy.cfg " diff --git a/main/hostapd/0001-crypto-Add-more-bignum-EC-helper-functions.patch b/main/hostapd/0001-crypto-Add-more-bignum-EC-helper-functions.patch new file mode 100644 index 00000000000..9f4b0c29599 --- /dev/null +++ b/main/hostapd/0001-crypto-Add-more-bignum-EC-helper-functions.patch @@ -0,0 +1,318 @@ +From 208e5687ff2e48622e28d8888ce5444a54353bbd Mon Sep 17 00:00:00 2001 +From: Jouni Malinen <jouni@codeaurora.org> +Date: Tue, 27 Aug 2019 16:33:15 +0300 +Subject: [PATCH 1/4] crypto: Add more bignum/EC helper functions + +These are needed for implementing SAE hash-to-element. + +Signed-off-by: Jouni Malinen <jouni@codeaurora.org> +--- + src/crypto/crypto.h | 45 ++++++++++++++++++ + src/crypto/crypto_openssl.c | 94 +++++++++++++++++++++++++++++++++++++ + src/crypto/crypto_wolfssl.c | 66 ++++++++++++++++++++++++++ + 3 files changed, 205 insertions(+) + +diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h +index 15f8ad04cea4..68476dbce96c 100644 +--- a/src/crypto/crypto.h ++++ b/src/crypto/crypto.h +@@ -518,6 +518,13 @@ struct crypto_bignum * crypto_bignum_init(void); + */ + struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len); + ++/** ++ * crypto_bignum_init_set - Allocate memory for bignum and set the value (uint) ++ * @val: Value to set ++ * Returns: Pointer to allocated bignum or %NULL on failure ++ */ ++struct crypto_bignum * crypto_bignum_init_uint(unsigned int val); ++ + /** + * crypto_bignum_deinit - Free bignum + * @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set() +@@ -612,6 +619,19 @@ int crypto_bignum_div(const struct crypto_bignum *a, + const struct crypto_bignum *b, + struct crypto_bignum *c); + ++/** ++ * crypto_bignum_addmod - d = a + b (mod c) ++ * @a: Bignum ++ * @b: Bignum ++ * @c: Bignum ++ * @d: Bignum; used to store the result of (a + b) % c ++ * Returns: 0 on success, -1 on failure ++ */ ++int crypto_bignum_addmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ const struct crypto_bignum *c, ++ struct crypto_bignum *d); ++ + /** + * crypto_bignum_mulmod - d = a * b (mod c) + * @a: Bignum +@@ -625,6 +645,28 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, + const struct crypto_bignum *c, + struct crypto_bignum *d); + ++/** ++ * crypto_bignum_sqrmod - c = a^2 (mod b) ++ * @a: Bignum ++ * @b: Bignum ++ * @c: Bignum; used to store the result of a^2 % b ++ * Returns: 0 on success, -1 on failure ++ */ ++int crypto_bignum_sqrmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c); ++ ++/** ++ * crypto_bignum_sqrtmod - returns sqrt(a) (mod b) ++ * @a: Bignum ++ * @b: Bignum ++ * @c: Bignum; used to store the result ++ * Returns: 0 on success, -1 on failure ++ */ ++int crypto_bignum_sqrtmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c); ++ + /** + * crypto_bignum_rshift - r = a >> n + * @a: Bignum +@@ -731,6 +773,9 @@ const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e); + */ + const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e); + ++const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e); ++const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e); ++ + /** + * struct crypto_ec_point - Elliptic curve point + * +diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c +index bab33a537293..ed463105e8f1 100644 +--- a/src/crypto/crypto_openssl.c ++++ b/src/crypto/crypto_openssl.c +@@ -1283,6 +1283,24 @@ struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) + } + + ++struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) ++{ ++ BIGNUM *bn; ++ ++ if (TEST_FAIL()) ++ return NULL; ++ ++ bn = BN_new(); ++ if (!bn) ++ return NULL; ++ if (BN_set_word(bn, val) != 1) { ++ BN_free(bn); ++ return NULL; ++ } ++ return (struct crypto_bignum *) bn; ++} ++ ++ + void crypto_bignum_deinit(struct crypto_bignum *n, int clear) + { + if (clear) +@@ -1449,6 +1467,28 @@ int crypto_bignum_div(const struct crypto_bignum *a, + } + + ++int crypto_bignum_addmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ const struct crypto_bignum *c, ++ struct crypto_bignum *d) ++{ ++ int res; ++ BN_CTX *bnctx; ++ ++ if (TEST_FAIL()) ++ return -1; ++ ++ bnctx = BN_CTX_new(); ++ if (!bnctx) ++ return -1; ++ res = BN_mod_add((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, ++ (const BIGNUM *) c, bnctx); ++ BN_CTX_free(bnctx); ++ ++ return res ? 0 : -1; ++} ++ ++ + int crypto_bignum_mulmod(const struct crypto_bignum *a, + const struct crypto_bignum *b, + const struct crypto_bignum *c, +@@ -1472,6 +1512,48 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, + } + + ++int crypto_bignum_sqrmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ int res; ++ BN_CTX *bnctx; ++ ++ if (TEST_FAIL()) ++ return -1; ++ ++ bnctx = BN_CTX_new(); ++ if (!bnctx) ++ return -1; ++ res = BN_mod_sqr((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, ++ bnctx); ++ BN_CTX_free(bnctx); ++ ++ return res ? 0 : -1; ++} ++ ++ ++int crypto_bignum_sqrtmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ BN_CTX *bnctx; ++ BIGNUM *res; ++ ++ if (TEST_FAIL()) ++ return -1; ++ ++ bnctx = BN_CTX_new(); ++ if (!bnctx) ++ return -1; ++ res = BN_mod_sqrt((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, ++ bnctx); ++ BN_CTX_free(bnctx); ++ ++ return res ? 0 : -1; ++} ++ ++ + int crypto_bignum_rshift(const struct crypto_bignum *a, int n, + struct crypto_bignum *r) + { +@@ -1682,6 +1764,18 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) + } + + ++const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *) e->a; ++} ++ ++ ++const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *) e->b; ++} ++ ++ + void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) + { + if (clear) +diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c +index 4cedab4367cd..e9894b335e53 100644 +--- a/src/crypto/crypto_wolfssl.c ++++ b/src/crypto/crypto_wolfssl.c +@@ -1042,6 +1042,26 @@ struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) + } + + ++struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) ++{ ++ mp_int *a; ++ ++ if (TEST_FAIL()) ++ return NULL; ++ ++ a = (mp_int *) crypto_bignum_init(); ++ if (!a) ++ return NULL; ++ ++ if (mp_set_int(a, val) != MP_OKAY) { ++ os_free(a); ++ a = NULL; ++ } ++ ++ return (struct crypto_bignum *) a; ++} ++ ++ + void crypto_bignum_deinit(struct crypto_bignum *n, int clear) + { + if (!n) +@@ -1168,6 +1188,19 @@ int crypto_bignum_div(const struct crypto_bignum *a, + } + + ++int crypto_bignum_addmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ const struct crypto_bignum *c, ++ struct crypto_bignum *d) ++{ ++ if (TEST_FAIL()) ++ return -1; ++ ++ return mp_addmod((mp_int *) a, (mp_int *) b, (mp_int *) c, ++ (mp_int *) d) == MP_OKAY ? 0 : -1; ++} ++ ++ + int crypto_bignum_mulmod(const struct crypto_bignum *a, + const struct crypto_bignum *b, + const struct crypto_bignum *m, +@@ -1181,6 +1214,27 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, + } + + ++int crypto_bignum_sqrmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ if (TEST_FAIL()) ++ return -1; ++ ++ return mp_sqrmod((mp_int *) a, (mp_int *) b, ++ (mp_int *) c) == MP_OKAY ? 0 : -1; ++} ++ ++ ++int crypto_bignum_sqrtmod(const struct crypto_bignum *a, ++ const struct crypto_bignum *b, ++ struct crypto_bignum *c) ++{ ++ /* TODO */ ++ return -1; ++} ++ ++ + int crypto_bignum_rshift(const struct crypto_bignum *a, int n, + struct crypto_bignum *r) + { +@@ -1386,6 +1440,18 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) + } + + ++const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *) &e->a; ++} ++ ++ ++const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) ++{ ++ return (const struct crypto_bignum *) &e->b; ++} ++ ++ + void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) + { + ecc_point *point = (ecc_point *) p; +-- +2.25.1 + diff --git a/main/hostapd/0002-dragonfly-Add-sqrt-helper-function.patch b/main/hostapd/0002-dragonfly-Add-sqrt-helper-function.patch new file mode 100644 index 00000000000..6c8509b8c20 --- /dev/null +++ b/main/hostapd/0002-dragonfly-Add-sqrt-helper-function.patch @@ -0,0 +1,72 @@ +From 2232d3d5f188b65dbb6c823ac62175412739eb16 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen <j@w1.fi> +Date: Fri, 7 Jan 2022 13:47:16 +0200 +Subject: [PATCH 2/4] dragonfly: Add sqrt() helper function + +This is a backport of "SAE: Move sqrt() implementation into a helper +function" to introduce the helper function needed for the following +patches. + +Signed-off-by: Jouni Malinen <j@w1.fi> +--- + src/common/dragonfly.c | 34 ++++++++++++++++++++++++++++++++++ + src/common/dragonfly.h | 2 ++ + 2 files changed, 36 insertions(+) + +diff --git a/src/common/dragonfly.c b/src/common/dragonfly.c +index 547be66f1561..1e842716668e 100644 +--- a/src/common/dragonfly.c ++++ b/src/common/dragonfly.c +@@ -213,3 +213,37 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, + "dragonfly: Unable to get randomness for own scalar"); + return -1; + } ++ ++ ++/* res = sqrt(val) */ ++int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, ++ struct crypto_bignum *res) ++{ ++ const struct crypto_bignum *prime; ++ struct crypto_bignum *tmp, *one; ++ int ret = 0; ++ u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; ++ size_t prime_len; ++ ++ /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ ++ ++ prime = crypto_ec_get_prime(ec); ++ prime_len = crypto_ec_prime_len(ec); ++ tmp = crypto_bignum_init(); ++ one = crypto_bignum_init_uint(1); ++ ++ if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), ++ prime_len) < 0 || ++ (prime_bin[prime_len - 1] & 0x03) != 3 || ++ !tmp || !one || ++ /* tmp = (p+1)/4 */ ++ crypto_bignum_add(prime, one, tmp) < 0 || ++ crypto_bignum_rshift(tmp, 2, tmp) < 0 || ++ /* res = sqrt(val) */ ++ crypto_bignum_exptmod(val, tmp, prime, res) < 0) ++ ret = -1; ++ ++ crypto_bignum_deinit(tmp, 0); ++ crypto_bignum_deinit(one, 0); ++ return ret; ++} +diff --git a/src/common/dragonfly.h b/src/common/dragonfly.h +index ec3dd593eda4..84d67f575c54 100644 +--- a/src/common/dragonfly.h ++++ b/src/common/dragonfly.h +@@ -27,5 +27,7 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, + struct crypto_bignum *_rand, + struct crypto_bignum *_mask, + struct crypto_bignum *scalar); ++int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, ++ struct crypto_bignum *res); + + #endif /* DRAGONFLY_H */ +-- +2.25.1 + diff --git a/main/hostapd/0003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch b/main/hostapd/0003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch new file mode 100644 index 00000000000..f2a9cb3a9fe --- /dev/null +++ b/main/hostapd/0003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch @@ -0,0 +1,99 @@ +From fe534b0baaa8c0e6ddeb24cf529d6e50e33dc501 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen <j@w1.fi> +Date: Fri, 7 Jan 2022 13:47:16 +0200 +Subject: [PATCH 3/4] SAE: Derive the y coordinate for PWE with own + implementation + +The crypto_ec_point_solve_y_coord() wrapper function might not use +constant time operations in the crypto library and as such, could leak +side channel information about the password that is used to generate the +PWE in the hunting and pecking loop. As such, calculate the two possible +y coordinate values and pick the correct one to use with constant time +selection. + +Signed-off-by: Jouni Malinen <j@w1.fi> +--- + src/common/sae.c | 47 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 33 insertions(+), 14 deletions(-) + +diff --git a/src/common/sae.c b/src/common/sae.c +index 08fdbfd18173..8d79ed962768 100644 +--- a/src/common/sae.c ++++ b/src/common/sae.c +@@ -286,14 +286,16 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, + int pwd_seed_odd = 0; + u8 prime[SAE_MAX_ECC_PRIME_LEN]; + size_t prime_len; +- struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; ++ struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL; + u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; + u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; + u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; + u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; ++ u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; + int res = -1; + u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* + * mask */ ++ unsigned int is_eq; + + os_memset(x_bin, 0, sizeof(x_bin)); + +@@ -402,25 +404,42 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, + goto fail; + } + +- if (!sae->tmp->pwe_ecc) +- sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); +- if (!sae->tmp->pwe_ecc) +- res = -1; +- else +- res = crypto_ec_point_solve_y_coord(sae->tmp->ec, +- sae->tmp->pwe_ecc, x, +- pwd_seed_odd); +- if (res < 0) { +- /* +- * This should not happen since we already checked that there +- * is a result. +- */ ++ /* y = sqrt(x^3 + ax + b) mod p ++ * if LSB(save) == LSB(y): PWE = (x, y) ++ * else: PWE = (x, p - y) ++ * ++ * Calculate y and the two possible values for PWE and after that, ++ * use constant time selection to copy the correct alternative. ++ */ ++ y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x); ++ if (!y || ++ dragonfly_sqrt(sae->tmp->ec, y, y) < 0 || ++ crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN, ++ prime_len) < 0 || ++ crypto_bignum_sub(sae->tmp->prime, y, y) < 0 || ++ crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN, ++ SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); ++ goto fail; ++ } ++ ++ is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01); ++ const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN, ++ prime_len, x_y + prime_len); ++ os_memcpy(x_y, x_bin, prime_len); ++ wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len); ++ crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); ++ sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y); ++ if (!sae->tmp->pwe_ecc) { ++ wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); ++ res = -1; + } + + fail: ++ forced_memzero(x_y, sizeof(x_y)); + crypto_bignum_deinit(qr, 0); + crypto_bignum_deinit(qnr, 0); ++ crypto_bignum_deinit(y, 1); + os_free(dummy_password); + bin_clear_free(tmp_password, password_len); + crypto_bignum_deinit(x, 1); +-- +2.25.1 + diff --git a/main/hostapd/0004-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch b/main/hostapd/0004-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch new file mode 100644 index 00000000000..71d22b0864b --- /dev/null +++ b/main/hostapd/0004-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch @@ -0,0 +1,113 @@ +From 603cd880e7f90595482658a7136fa6a7be5cb485 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen <j@w1.fi> +Date: Fri, 7 Jan 2022 18:52:27 +0200 +Subject: [PATCH 4/4] EAP-pwd: Derive the y coordinate for PWE with own + implementation + +The crypto_ec_point_solve_y_coord() wrapper function might not use +constant time operations in the crypto library and as such, could leak +side channel information about the password that is used to generate the +PWE in the hunting and pecking loop. As such, calculate the two possible +y coordinate values and pick the correct one to use with constant time +selection. + +Signed-off-by: Jouni Malinen <j@w1.fi> +--- + src/eap_common/eap_pwd_common.c | 46 ++++++++++++++++++++++++++------- + 1 file changed, 36 insertions(+), 10 deletions(-) + +diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c +index 2b2b8efdbd01..ff22b29b087a 100644 +--- a/src/eap_common/eap_pwd_common.c ++++ b/src/eap_common/eap_pwd_common.c +@@ -127,7 +127,8 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, + u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN]; + u8 x_bin[MAX_ECC_PRIME_LEN]; + u8 prime_bin[MAX_ECC_PRIME_LEN]; +- struct crypto_bignum *tmp2 = NULL; ++ u8 x_y[2 * MAX_ECC_PRIME_LEN]; ++ struct crypto_bignum *tmp2 = NULL, *y = NULL; + struct crypto_hash *hash; + unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; + int ret = 0, res; +@@ -139,6 +140,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, + u8 found_ctr = 0, is_odd = 0; + int cmp_prime; + unsigned int in_range; ++ unsigned int is_eq; + + if (grp->pwe) + return -1; +@@ -151,11 +153,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, + if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), + primebytelen) < 0) + return -1; +- grp->pwe = crypto_ec_point_init(grp->group); +- if (!grp->pwe) { +- wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); +- goto fail; +- } + + if ((prfbuf = os_malloc(primebytelen)) == NULL) { + wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " +@@ -261,10 +258,37 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, + */ + crypto_bignum_deinit(x_candidate, 1); + x_candidate = crypto_bignum_init_set(x_bin, primebytelen); +- if (!x_candidate || +- crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate, +- is_odd) != 0) { +- wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y"); ++ if (!x_candidate) ++ goto fail; ++ ++ /* y = sqrt(x^3 + ax + b) mod p ++ * if LSB(y) == LSB(pwd-seed): PWE = (x, y) ++ * else: PWE = (x, p - y) ++ * ++ * Calculate y and the two possible values for PWE and after that, ++ * use constant time selection to copy the correct alternative. ++ */ ++ y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate); ++ if (!y || ++ dragonfly_sqrt(grp->group, y, y) < 0 || ++ crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 || ++ crypto_bignum_sub(prime, y, y) < 0 || ++ crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, ++ MAX_ECC_PRIME_LEN, primebytelen) < 0) { ++ wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); ++ goto fail; ++ } ++ ++ /* Constant time selection of the y coordinate from the two ++ * options */ ++ is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01); ++ const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN, ++ primebytelen, x_y + primebytelen); ++ os_memcpy(x_y, x_bin, primebytelen); ++ wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen); ++ grp->pwe = crypto_ec_point_from_bin(grp->group, x_y); ++ if (!grp->pwe) { ++ wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE"); + goto fail; + } + +@@ -289,6 +313,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, + /* cleanliness and order.... */ + crypto_bignum_deinit(x_candidate, 1); + crypto_bignum_deinit(tmp2, 1); ++ crypto_bignum_deinit(y, 1); + crypto_bignum_deinit(qr, 1); + crypto_bignum_deinit(qnr, 1); + bin_clear_free(prfbuf, primebytelen); +@@ -296,6 +321,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, + os_memset(qnr_bin, 0, sizeof(qnr_bin)); + os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin)); + os_memset(pwe_digest, 0, sizeof(pwe_digest)); ++ forced_memzero(x_y, sizeof(x_y)); + + return ret; + } +-- +2.25.1 + diff --git a/main/hostapd/APKBUILD b/main/hostapd/APKBUILD index 848cd883e69..7d122c95eda 100644 --- a/main/hostapd/APKBUILD +++ b/main/hostapd/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=hostapd pkgver=2.9 -pkgrel=3 +pkgrel=4 pkgdesc="daemon for wireless software access points" url="https://w1.fi/hostapd/" arch="all" @@ -16,11 +16,19 @@ source="https://w1.fi/releases/$pkgname-$pkgver.tar.gz 0002-WPS-UPnP-Fix-event-message-generation-using-a-long-U.patch 0003-WPS-UPnP-Handle-HTTP-initiation-failures-for-events-.patch CVE-2021-30004.patch::https://w1.fi/cgit/hostap/patch/?id=a0541334a6394f8237a4393b7372693cd7e96f15 + + 0001-crypto-Add-more-bignum-EC-helper-functions.patch + 0002-dragonfly-Add-sqrt-helper-function.patch + 0003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch + 0004-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch " options="!check" #no testsuite builddir="$srcdir"/$pkgname-$pkgver/hostapd # secfixes: +# 2.9-r4: +# - CVE-2022-23303 +# - CVE-2022-23304 # 2.9-r3: # - CVE-2021-30004 # 2.9-r2: @@ -103,11 +111,17 @@ package() { && install -Dm644 hostapd_cli.1 \ "$pkgdir"/usr/share/man/man1/hostapd_cli } -sha512sums="66c729380152db18b64520bda55dfa00af3b0264f97b5de100b81a46e2593571626c4bdcf900f0988ea2131e30bc8788f75d8489dd1f57e37fd56e8098e48a9c hostapd-2.9.tar.gz +sha512sums=" +66c729380152db18b64520bda55dfa00af3b0264f97b5de100b81a46e2593571626c4bdcf900f0988ea2131e30bc8788f75d8489dd1f57e37fd56e8098e48a9c hostapd-2.9.tar.gz b54b7c6aa17e5cb86a9b354a516eb2dbefb544df18471339c61d82776de447011a2ac290bea1e6c8beae4b6cebefafb8174683ea42fb773e9e8fe6c679f33ba3 hostapd.initd 0882263bbd7c0b05bf51f51d66e11a23a0b8ca7da2a3b8a30166d2c5f044c0c134e6bccb1d02c9e81819ca8fb0c0fb55c7121a08fe7233ccaa73ff8ab9a238fe hostapd.confd 63710cfb0992f2c346a9807d8c97cbeaed032fa376a0e93a2e56f7742ce515e9c4dfadbdb1af03ba272281f639aab832f0178f67634c222a5d99e1d462aa9e38 CVE-2019-16275.patch b76bbca282a74ef16c0303e5dbd2ccd33a62461595964d52c1481b0bfa4f41deacde56830b85409b288803b87ceb6f33cf0ccc69c5b17ec632c2d4784b872f3c 0001-WPS-UPnP-Do-not-allow-event-subscriptions-with-URLs-.patch 00cc739e78c42353a555c0de2f29defecff372927040e14407a231d1ead7ff32a37c9fd46bea7cdf1c24e3ac891bc3d483800d44fc6d2c8a12d2ae886523b12c 0002-WPS-UPnP-Fix-event-message-generation-using-a-long-U.patch 69243af20cdcfa837c51917a3723779f4825e11436fb83311355b4ffe8f7a4b7a5747a976f7bf923038c410c9e9055b13b866d9a396913ad08bdec3a70e9f6e0 0003-WPS-UPnP-Handle-HTTP-initiation-failures-for-events-.patch -88608529763a6fd9e8cb1e9c9a35630dc2e311a260e023e2a69002d0db700d5f58fc7723a00433b4ea895b92c371cf1db221f38742490b4ed9b4b049892b65e1 CVE-2021-30004.patch" +88608529763a6fd9e8cb1e9c9a35630dc2e311a260e023e2a69002d0db700d5f58fc7723a00433b4ea895b92c371cf1db221f38742490b4ed9b4b049892b65e1 CVE-2021-30004.patch +540ddb5ddde8aa8e2292ab01f632b63ac2e390aecd63506ac4e736b4677125d10be44c4dee153f135e51b510e6b62d4926f921e4bbd117ed0864b5becc9b873e 0001-crypto-Add-more-bignum-EC-helper-functions.patch +77402d5917144850d3d521b6f880c942de809d058eb09c6e79e5d54898165e21c06eb997eb089f9bf3f9ef387bc8b3697e62f1a80dbb319892a72e5b5f0ff14c 0002-dragonfly-Add-sqrt-helper-function.patch +9dd05d81597a13552d094735dd6da0e298e2c372ee0ed0f191ead149dd5ec32f4002f2950d327fdebfd942ba47ec87c5064f6cd512eef41867e9568a75e61352 0003-SAE-Derive-the-y-coordinate-for-PWE-with-own-impleme.patch +55879aacd970ba6a926ed6936204e8507736551aa24d8d384d80d790da8c7362dd80f247b84e8bb51ea527fa516d37163d5b82bc595a85a432116cc5e042606e 0004-EAP-pwd-Derive-the-y-coordinate-for-PWE-with-own-imp.patch +" diff --git a/main/krb5/APKBUILD b/main/krb5/APKBUILD index 417d166ba84..aca74e1edf7 100644 --- a/main/krb5/APKBUILD +++ b/main/krb5/APKBUILD @@ -1,6 +1,6 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=krb5 -pkgver=1.18.4 +pkgver=1.18.5 pkgrel=0 pkgdesc="The Kerberos network authentication system" url="https://web.mit.edu/kerberos/www/" @@ -30,6 +30,8 @@ source="https://web.mit.edu/kerberos/dist/krb5/$_maj_min/krb5-$pkgver.tar.gz builddir="$srcdir/$pkgname-$pkgver/src" # secfixes: +# 1.18.5-r0: +# - CVE-2021-37750 # 1.18.4-r0: # - CVE-2021-36222 # 1.18.3-r0: @@ -114,7 +116,7 @@ libs() { } sha512sums=" -7d9f1e937ba122f5af1340b5025420903a4cc3692bdf4093289921ad09b3fd02c8684b65a783d4b397ba15c4cf29c728cbf24a6405c5fff72fb882137703539e krb5-1.18.4.tar.gz +7fd25944ac66074bf21465824f226aa3456a253a7517e7d3cacb7664103b8b033076cc23ee7c7806e7c9f884747c05eac5b1f1cf771b3d1989e5129c36de4bb2 krb5-1.18.5.tar.gz 5c62cbcbf1ef0462323f3392a362b42ed301967a1de80ddcb27eece4fad23efeeb5f04f5af521cfffff36b918bb93813262aa62785e59d6cb5af437a2c9e886d mit-krb5_krb5-config_LDFLAGS.patch 43b9885b7eb8d0d60920def688de482f2b1701288f9acb1bb21dc76b2395428ff304961959eb04ba5eafd0412bae35668d6d2c8223424b9337bc051eadf51682 krb5kadmind.initd ede15f15bbbc9d0227235067abe15245bb9713aea260d397379c63275ce74aea0db6c91c15d599e40c6e89612d76f3a0f8fdd21cbafa3f30d426d4310d3e2cec krb5kdc.initd diff --git a/main/libxml2/APKBUILD b/main/libxml2/APKBUILD index b088f2173f4..28c5567153b 100644 --- a/main/libxml2/APKBUILD +++ b/main/libxml2/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Carlo Landmeter <clandmeter@gmail.com> # Maintainer: Carlo Landmeter <clandmeter@gmail.com> pkgname=libxml2 -pkgver=2.9.12 +pkgver=2.9.14 pkgrel=0 pkgdesc="XML parsing library, version 2" url="http://www.xmlsoft.org/" @@ -13,12 +13,15 @@ makedepends="$depends_dev python3-dev" subpackages="$pkgname-dbg $pkgname-doc $pkgname-dev $pkgname-utils py3-$pkgname:_py3" options="!strip" -source="http://xmlsoft.org/sources/libxml2-$pkgver.tar.gz - revert-Make-xmlFreeNodeList-non-recursive.patch +source="https://download.gnome.org/sources/libxml2/${pkgver%.*}/libxml2-$pkgver.tar.xz libxml2-2.9.8-python3-unicode-errors.patch " # secfixes: +# 2.9.14-r0: +# - CVE-2022-29824 +# 2.9.13-r0: +# - CVE-2022-23308 # 2.9.12-r0: # - CVE-2021-3541 # 2.9.10-r6: @@ -97,7 +100,6 @@ utils() { } sha512sums=" -df1c6486e80f0fcf3c506f3599bcfb94b620c00d0b5d26831bc983daa78d58ec58b5057b1ec7c1a26c694f40199c6234ee2a6dcabf65abfa10c447cb5705abbd libxml2-2.9.12.tar.gz -347178e432379d543683cba21b902e7305202c03e8dbd724ae395963d677096a5cfc4e345e208d498163ca5174683c167610fc2b297090476038bc2bb7c84b4f revert-Make-xmlFreeNodeList-non-recursive.patch +d08e6cafb289c499fdc5b3a12181e032a34f7a249bc66758859f964d3e71e19fd69be79921e1a9d8ab1e692d15b13f5fae95eeb10c3236974d89e218f5107606 libxml2-2.9.14.tar.xz a205c97fa1488fb8907cfa08b5f82e2055c80b86213dc3cc5c4b526fe6aa786bcc4e4eeb226c44635a1d021307b39e3940f706c42fb60e9e3e9b490a84164df7 libxml2-2.9.8-python3-unicode-errors.patch " diff --git a/main/libxml2/revert-Make-xmlFreeNodeList-non-recursive.patch b/main/libxml2/revert-Make-xmlFreeNodeList-non-recursive.patch deleted file mode 100644 index 102abdb3134..00000000000 --- a/main/libxml2/revert-Make-xmlFreeNodeList-non-recursive.patch +++ /dev/null @@ -1,64 +0,0 @@ -This is a revert of -https://github.com/GNOME/libxml2/commit/0762c9b69ba01628f72eada1c64ff3d361fb5716 - -This fixes perl-xml-libxslt test suite -https://bugzilla.suse.com/show_bug.cgi?id=1157450 - -diff --git a/tree.c b/tree.c -index 08b1a50..f2b1457 100644 ---- a/tree.c -+++ b/tree.c -@@ -3664,9 +3664,7 @@ xmlNextElementSibling(xmlNodePtr node) { - void - xmlFreeNodeList(xmlNodePtr cur) { - xmlNodePtr next; -- xmlNodePtr parent; - xmlDictPtr dict = NULL; -- size_t depth = 0; - - if (cur == NULL) return; - if (cur->type == XML_NAMESPACE_DECL) { -@@ -3682,21 +3680,16 @@ xmlFreeNodeList(xmlNodePtr cur) { - return; - } - if (cur->doc != NULL) dict = cur->doc->dict; -- while (1) { -- while ((cur->children != NULL) && -- (cur->type != XML_DTD_NODE) && -- (cur->type != XML_ENTITY_REF_NODE)) { -- cur = cur->children; -- depth += 1; -- } -- -+ while (cur != NULL) { - next = cur->next; -- parent = cur->parent; - if (cur->type != XML_DTD_NODE) { - - if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) - xmlDeregisterNodeDefaultValue(cur); - -+ if ((cur->children != NULL) && -+ (cur->type != XML_ENTITY_REF_NODE)) -+ xmlFreeNodeList(cur->children); - if (((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_XINCLUDE_START) || - (cur->type == XML_XINCLUDE_END)) && -@@ -3727,16 +3720,7 @@ xmlFreeNodeList(xmlNodePtr cur) { - DICT_FREE(cur->name) - xmlFree(cur); - } -- -- if (next != NULL) { -- cur = next; -- } else { -- if ((depth == 0) || (parent == NULL)) -- break; -- depth -= 1; -- cur = parent; -- cur->children = NULL; -- } -+ cur = next; - } - } - diff --git a/main/libxslt/APKBUILD b/main/libxslt/APKBUILD index 1a59b967c79..b43d3f92099 100644 --- a/main/libxslt/APKBUILD +++ b/main/libxslt/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> # Contributor: Francesco Colista <fcolista@alpinelinux.org> pkgname=libxslt -pkgver=1.1.34 +pkgver=1.1.35 pkgrel=0 pkgdesc="XML stylesheet transformation library" url="http://xmlsoft.org/XSLT/" @@ -9,9 +9,11 @@ arch="all" license="custom" makedepends="libxml2-dev libgcrypt-dev libgpg-error-dev" subpackages="$pkgname-dev $pkgname-doc" -source="http://xmlsoft.org/sources/libxslt-$pkgver.tar.gz" +source="https://download.gnome.org/sources/libxslt/${pkgver%.*}/libxslt-$pkgver.tar.xz" # secfixes: +# 1.1.35-r0: +# - CVE-2021-30560 # 1.1.34-r0: # - CVE-2019-13117 # - CVE-2019-13118 @@ -43,4 +45,6 @@ package() { make DESTDIR="$pkgdir" install install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING } -sha512sums="1516a11ad608b04740674060d2c5d733b88889de5e413b9a4e8bf8d1a90d712149df6d2b1345b615f529d7c7d3fa6dae12e544da828b39c7d415e54c0ee0776b libxslt-1.1.34.tar.gz" +sha512sums=" +9dd4a699235f50ae9b75b25137e387471635b4b2da0a4e4380879cd49f1513470fcfbfd775269b066eac513a1ffa6860c77ec42747168e2348248f09f60c8c96 libxslt-1.1.35.tar.xz +" diff --git a/main/linux-lts/APKBUILD b/main/linux-lts/APKBUILD index c9ceacf4d29..57f4e8ce9be 100644 --- a/main/linux-lts/APKBUILD +++ b/main/linux-lts/APKBUILD @@ -2,7 +2,7 @@ _flavor=lts pkgname=linux-${_flavor} -pkgver=5.4.143 +pkgver=5.4.192 case $pkgver in *.*.*) _kernver=${pkgver%.*};; *.*) _kernver=$pkgver;; @@ -223,16 +223,16 @@ _dev() { sha512sums="9f60f77e8ab972b9438ac648bed17551c8491d6585a5e85f694b2eaa4c623fbc61eb18419b2656b6795eac5deec0edaa04547fc6723fbda52256bd7f3486898f linux-5.4.tar.xz d19365fe94431008768c96a2c88955652f70b6df6677457ee55ee95246a64fdd2c6fed9b3bef37c29075178294a7fc91f148ead636382530ebfa822be4ad8c2f 0002-powerpc-config-defang-gcc-check-for-stack-protector-.patch -748ec78861d04a6db073ba6392fcfa790376015e66f442c297fe7733122aa99057a4e6a3986833f8114c881a69f1307dfba10a9cd90fd3af653ef4b64b386889 config-lts.aarch64 +e54f8a3bf528a492c21ba3c0391082b7bc77d602e3c2af2d2f99decf23e4ecbc6ddaaa80edabefdacb7d34e262f353cf3d2e56690291874d9895144e3f4ee3cd config-lts.aarch64 ebdadeda46194bcc7ddf3c2db401ba1d32e1eeebee0c7fa3d103ac9fcf08bf53dbd83b5dddc3f990d40c06aace12ba91f6eb7d917d19e7991def3de64990fe85 config-lts.armv7 -f9a090756f5c6d504b9af8bff7ce1ac98c45dfb5540bd03de515a859504f6e9d59e8d77983c90b36e2d5fe1d1975f41ac7351e27e67d264bdb3946b10ee125d2 config-lts.x86 -b5c92c8278f605e15d50695eff0dbf84872422eef357e98fa46642fd37b516f5616215bd98c79b7b6516d52e0efe8b5b8dfe9049eb319535d1e2acb74ecfee1e config-lts.x86_64 +5285b544d4e91d9829fa5bbd446c8ab782761631466473f5be5c7bef4eed2f7cfa5037f195c21d17b433b03b9262aee22f51e219a6f89b115aba00e12fe357c8 config-lts.x86 +4424ba69ea1765eb39c6b2eb491b20a57d3e8901a3ba6878dc4dbd2bf60e5a775f8bc2404b2d194ec83c309cd62ccea8368a8c53d90f94511c830da12e16d688 config-lts.x86_64 1912e515aa5dedaaa15151c9b160aebbf7b45e4bd1616fc562c30dbf4b38cd59c3b04a892ef6207bcbe90fa42b4628a924777f22f980753387890e6aceaae0ff config-lts.ppc64le 1f7291fcb6dd4a0226ca9846116ada50ef03a6b67028e16d6c6c3e0fe59e45c94f54f6ef8ed6a067e16332bf6da7adc3bb7c43c2ed8fa4b743d6bb22d4ebeeb4 config-lts.s390x 2121ff443bbc617cb0f5f77b698120f71b1cdc4d18bd4312cc6ab5659635f74995d7a194820128b7aa7790f5912d5e30f00b11d6d225dab88ab9a00dc5a9c717 config-lts.mips64 1fc4cf98951ff88ceaaaca01a884c41d71f26da1d6e6c772012dead5bb530244388d5be54346c29a37df7781d05e35c83aa00e8b5f0358fa3280007423f243b7 config-lts.mips -e19a0e494bfead5846770fef9a8d4fa8ab9e7290b78a14403404f61dc71c3d667f5f199f29a817c1fbced901ed6871c70fe1e1baade78a967a2426f510e93f18 config-virt.aarch64 -3a9bad315329228b368e399854c94ecbdf3f211de35c2f70cb1287f5ecbe5f50cb31f97b02f99e880ca1cf1772dd3341c8d888509718baaf78593664bc822d70 config-virt.armv7 -bbf2b9b8d1cf45e95d02438c23c8b5646dc21b51b16ac34498213f8517ea94f4769781e8902a6d8a32b5f7c1b174e15afde147aeefde221024af2dc686f1b575 config-virt.x86 -8a64728776209d1305f10d8310694088ec38ada723da0ef9caf1ac4390c580704cefb0f8487bd9632974fac31b6db4684e650ab2db222a63e3223658254dc8d7 config-virt.x86_64 -5850c88f4cfe6d26e543bb96b77691d846e5f3d506a607a7a083fc54561113f4b5afb48e93a963b056f34beb4f75cc64dd693f128ae5be795cdd8274c5955330 patch-5.4.143.xz" +946535fa2dbb5bd0e8a6bf15ec9250474246560a52593f1e2da2a2af03acea4c87374b0fa8d53430a99f190a6f6781a6d9aeb10d256bf0fc1d66fefafe790c3a config-virt.aarch64 +3d48882396fc646f8e3ac6613f2785f0ea1276f1afaaaf86703a266b247a699c103b1f90e14370780faf8102a39655c1548fc0a52bfe25f76f10395a5ee1157e config-virt.armv7 +00c97879db8e9f626066e489aceeade8979feb3904bd4b1898cdcef765574e1afdf638382e79fb78b3a3c4c5079601425c570212fe98fcdf14c8867a7ee8567f config-virt.x86 +7989643880fdbfd706dce1762e2e1b4a969cea05498fa9763d5e89cb050810680fca1a999a1492c773c3f027c03b25caaf1108aed5abd407749a725d7a95d80d config-virt.x86_64 +81b274390c5a60f654ccbd396dc32c142240fe8fd968b641a5c3be164ff82e3358200af0fa5a2594738fddbbdfb717b507c168e22563e8b9297707b42c983199 patch-5.4.192.xz" diff --git a/main/linux-lts/config-lts.aarch64 b/main/linux-lts/config-lts.aarch64 index 4caadac48d0..f40efe9adab 100644 --- a/main/linux-lts/config-lts.aarch64 +++ b/main/linux-lts/config-lts.aarch64 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 5.4.143 Kernel Configuration +# Linux/arm64 5.4.182 Kernel Configuration # # @@ -206,6 +206,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y @@ -6319,7 +6320,7 @@ CONFIG_I2C_HID=m CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y +CONFIG_USB_COMMON=m CONFIG_USB_LED_TRIG=y # CONFIG_USB_ULPI_BUS is not set # CONFIG_USB_CONN_GPIO is not set diff --git a/main/linux-lts/config-lts.x86 b/main/linux-lts/config-lts.x86 index f9e30c3c3c3..44789f3aa52 100644 --- a/main/linux-lts/config-lts.x86 +++ b/main/linux-lts/config-lts.x86 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.4.143 Kernel Configuration +# Linux/x86 5.4.182 Kernel Configuration # # @@ -209,6 +209,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y diff --git a/main/linux-lts/config-lts.x86_64 b/main/linux-lts/config-lts.x86_64 index 35dc076f4df..43863557387 100644 --- a/main/linux-lts/config-lts.x86_64 +++ b/main/linux-lts/config-lts.x86_64 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 5.4.143 Kernel Configuration +# Linux/x86_64 5.4.182 Kernel Configuration # # @@ -222,6 +222,7 @@ CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y @@ -6202,7 +6203,7 @@ CONFIG_INTEL_ISH_HID=m CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y +CONFIG_USB_COMMON=m CONFIG_USB_LED_TRIG=y # CONFIG_USB_ULPI_BUS is not set # CONFIG_USB_CONN_GPIO is not set diff --git a/main/linux-lts/config-virt.aarch64 b/main/linux-lts/config-virt.aarch64 index bf1b27db9ba..4ab98fc2305 100644 --- a/main/linux-lts/config-virt.aarch64 +++ b/main/linux-lts/config-virt.aarch64 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 5.4.143 Kernel Configuration +# Linux/arm64 5.4.182 Kernel Configuration # # @@ -199,6 +199,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y diff --git a/main/linux-lts/config-virt.armv7 b/main/linux-lts/config-virt.armv7 index fdda900065c..2e546c7fe9a 100644 --- a/main/linux-lts/config-virt.armv7 +++ b/main/linux-lts/config-virt.armv7 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.4.143 Kernel Configuration +# Linux/arm 5.4.182 Kernel Configuration # # @@ -189,6 +189,7 @@ CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_FUTEX_PI=y +CONFIG_HAVE_FUTEX_CMPXCHG=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y @@ -203,6 +204,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y diff --git a/main/linux-lts/config-virt.x86 b/main/linux-lts/config-virt.x86 index 177958aea39..743ed6264cc 100644 --- a/main/linux-lts/config-virt.x86 +++ b/main/linux-lts/config-virt.x86 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 5.4.143 Kernel Configuration +# Linux/x86 5.4.182 Kernel Configuration # # @@ -206,6 +206,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y diff --git a/main/linux-lts/config-virt.x86_64 b/main/linux-lts/config-virt.x86_64 index e472491596c..7be704e5dea 100644 --- a/main/linux-lts/config-virt.x86_64 +++ b/main/linux-lts/config-virt.x86_64 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 5.4.143 Kernel Configuration +# Linux/x86_64 5.4.182 Kernel Configuration # # @@ -218,6 +218,7 @@ CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # CONFIG_USERFAULTFD is not set CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_RSEQ=y diff --git a/main/logrotate/APKBUILD b/main/logrotate/APKBUILD index 3126b45d284..bb80d981682 100644 --- a/main/logrotate/APKBUILD +++ b/main/logrotate/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=logrotate pkgver=3.16.0 -pkgrel=0 +pkgrel=1 pkgdesc="Tool to rotate logfiles" url="https://github.com/logrotate/logrotate" arch="all" @@ -43,8 +43,7 @@ package() { install -Dm644 "$srcdir"/logrotate.confd \ "$pkgdir"/etc/conf.d/logrotate } - sha512sums="2f6afbd6f14a693e3571aa813ed94b85a041a00e31bb274ee0f3055d0eeeb7e79a202eed0d63c0bd5818e96d70855f252b15f70f4320372c9814809153739070 logrotate-3.16.0.tar.xz f4d708594fb2b240cfc2928f38a180d27c2cecb9867e048dc29a32c0147244db4d2f6d92e7bff27e1f2623537587db87b2f8fc9bb988f98eff0c98f79f5a5bf2 logrotate.cron -9e6a1d024b1cf1ddb8b631fdc1379bfecbfeb1af873930d2a19d32313b26881926df5c21b47b55ada2b6012be981ec2d6d8fa2f249a68b61fd2c97c32f52a957 logrotate.conf +e91c1648a088410d1f5ad16d05b67e316977be5cc0cbbb21a4e1fda2267415fb7945553aa4b4a4701d658fd6bfe35e3d9a304e0cf2a9c7f1be5a5753c3dbc7cb logrotate.conf be9f0043b594d26b4f64e07a2188d19c3c43af75ef726305e4d98f744fc16cee9f280227116858e2f5b781c0a7b58e0209d7e9ab1285dfa7ba55a9dfda700229 logrotate.confd" diff --git a/main/logrotate/logrotate.conf b/main/logrotate/logrotate.conf index ba75a0c2cb8..30cf9c99049 100644 --- a/main/logrotate/logrotate.conf +++ b/main/logrotate/logrotate.conf @@ -17,9 +17,6 @@ tabooext + .apk-new # uncomment this if you want your log files compressed compress -# main log file -/var/log/messages {} - # apk packages drop log rotation information into this directory include /etc/logrotate.d diff --git a/main/lz4/APKBUILD b/main/lz4/APKBUILD index b3b89891c04..49eaa4af3e8 100644 --- a/main/lz4/APKBUILD +++ b/main/lz4/APKBUILD @@ -2,16 +2,20 @@ # Maintainer: Stuart Cardall <developer@it-offshore.co.uk> pkgname=lz4 pkgver=1.9.2 -pkgrel=0 +pkgrel=1 pkgdesc="LZ4 is lossless compression algorithm with fast decoder @ multiple GB/s per core." url="https://github.com/lz4/lz4" arch="all" license="BSD-2-Clause GPL-2.0-only" checkdepends="diffutils" subpackages="$pkgname-static $pkgname-dev $pkgname-doc $pkgname-libs $pkgname-tests:tests" -source="$pkgname-$pkgver.tar.gz::https://github.com/lz4/lz4/archive/v$pkgver.tar.gz" +source="$pkgname-$pkgver.tar.gz::https://github.com/lz4/lz4/archive/v$pkgver.tar.gz + CVE-2021-3520.patch + " # secfixes: +# 1.9.2-r1: +# - CVE-2021-3520 # 1.9.2-r0: # - CVE-2019-17543 @@ -34,4 +38,5 @@ package() { make PREFIX="/usr" DESTDIR="$pkgdir" install } -sha512sums="ae714c61ec8e33ed91359b63f2896cfa102d66b730dce112b74696ec5850e59d88bd5527173e01e354a70fbe8f036557a47c767ee0766bc5f9c257978116c3c1 lz4-1.9.2.tar.gz" +sha512sums="ae714c61ec8e33ed91359b63f2896cfa102d66b730dce112b74696ec5850e59d88bd5527173e01e354a70fbe8f036557a47c767ee0766bc5f9c257978116c3c1 lz4-1.9.2.tar.gz +29038d80c4399ded52b49e69d0f0d80bef8bf424e3540de366ef539706c8c1119784d6137c96130f131239d74a4c110dd9790cae5c9b17c102820446582c5637 CVE-2021-3520.patch" diff --git a/main/lz4/CVE-2021-3520.patch b/main/lz4/CVE-2021-3520.patch new file mode 100644 index 00000000000..053958dfe87 --- /dev/null +++ b/main/lz4/CVE-2021-3520.patch @@ -0,0 +1,22 @@ +From 8301a21773ef61656225e264f4f06ae14462bca7 Mon Sep 17 00:00:00 2001 +From: Jasper Lievisse Adriaanse <j@jasper.la> +Date: Fri, 26 Feb 2021 15:21:20 +0100 +Subject: [PATCH] Fix potential memory corruption with negative memmove() size + +--- + lib/lz4.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/lz4.c b/lib/lz4.c +index 5f524d01d..c2f504ef3 100644 +--- a/lib/lz4.c ++++ b/lib/lz4.c +@@ -1749,7 +1749,7 @@ LZ4_decompress_generic( + const size_t dictSize /* note : = 0 if noDict */ + ) + { +- if (src == NULL) { return -1; } ++ if ((src == NULL) || (outputSize < 0)) { return -1; } + + { const BYTE* ip = (const BYTE*) src; + const BYTE* const iend = ip + srcSize; diff --git a/main/mariadb/APKBUILD b/main/mariadb/APKBUILD index a31189fade9..6c57ab093ea 100644 --- a/main/mariadb/APKBUILD +++ b/main/mariadb/APKBUILD @@ -7,7 +7,7 @@ # Contributor: Jake Buchholz <tomalok@gmail.com> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=mariadb -pkgver=10.4.21 +pkgver=10.4.25 pkgrel=0 pkgdesc="A fast SQL database server" url="https://www.mariadb.org/" @@ -37,7 +37,7 @@ case "$CARCH" in ;; esac -source="https://downloads.mariadb.org/interstitial/mariadb-$pkgver/source/mariadb-$pkgver.tar.gz +source="https://archive.mariadb.org/mariadb-$pkgver/source/mariadb-$pkgver.tar.gz $pkgname.initd pcre.cmake.patch ppc-remove-glibc-dep.patch @@ -46,6 +46,44 @@ source="https://downloads.mariadb.org/interstitial/mariadb-$pkgver/source/mariad #options="!check" # secfixes: +# 10.4.25-r0: +# - CVE-2022-21427 +# - CVE-2022-27376 +# - CVE-2022-27377 +# - CVE-2022-27378 +# - CVE-2022-27379 +# - CVE-2022-27380 +# - CVE-2022-27381 +# - CVE-2022-27382 +# - CVE-2022-27383 +# - CVE-2022-27384 +# - CVE-2022-27386 +# - CVE-2022-27387 +# - CVE-2022-27444 +# - CVE-2022-27445 +# - CVE-2022-27446 +# - CVE-2022-27447 +# - CVE-2022-27448 +# - CVE-2022-27449 +# - CVE-2022-27451 +# - CVE-2022-27452 +# - CVE-2022-27455 +# - CVE-2022-27456 +# - CVE-2022-27457 +# - CVE-2022-27458 +# 10.4.24-r0: +# - CVE-2021-46659 +# - CVE-2021-46661 +# - CVE-2021-46663 +# - CVE-2021-46664 +# - CVE-2021-46665 +# - CVE-2021-46668 +# - CVE-2022-24048 +# - CVE-2022-24050 +# - CVE-2022-24051 +# - CVE-2022-24052 +# 10.4.22-r0: +# - CVE-2021-35604 # 10.4.21-r0: # - CVE-2021-2372 # - CVE-2021-2389 @@ -463,7 +501,7 @@ _plugin_rocksdb() { } sha512sums=" -2be398cd80f0b8c938ab310f47ccd410f0209f8308bfc202014b71aee3f0bea7f535d1eceb82a4407202d9732c77874d773c6f13e54cf556fc79ed0d49390345 mariadb-10.4.21.tar.gz +27ad62985e19c877623d1512adcbec44e714ca50da9d303eab12bc2ad67dcae45d48a1aa010ad554341c46a1c5db7ee26c14570b9fa55fb71caf9979dd12671e mariadb-10.4.25.tar.gz c352969f6665b0ffa387f7b185a5dea7751f4b16c12c809627857b27321efa09159369d7dd5c852d6159a9f173cb895fb601f0c52a1fa6e3527899520030964c mariadb.initd 70da971aa78815495098205bcbd28428430aa83c3f1050fec0231ca86af9d9def2d2108a48ee08d86812c8dc5ad8ab1ef4e17a49b4936ed5187ae0f6a7ef8f63 pcre.cmake.patch dbd0970ea34e8bc8510431b3dc78f90b68be6f84bd27909a88516a469c2d5b402cfa62c548d78bac1e3eb717bb1b361cc375a3a77321a497e16dfba883233949 ppc-remove-glibc-dep.patch diff --git a/main/mbedtls/APKBUILD b/main/mbedtls/APKBUILD index 0455d8bd273..b35e34be09f 100644 --- a/main/mbedtls/APKBUILD +++ b/main/mbedtls/APKBUILD @@ -2,7 +2,7 @@ # Contributor: Łukasz Jendrysik <scadu@yandex.com> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=mbedtls -pkgver=2.16.9 +pkgver=2.16.12 pkgrel=0 pkgdesc="Light-weight cryptographic and SSL/TLS library" url="https://tls.mbed.org" @@ -10,13 +10,14 @@ arch="all" license="Apache-2.0" makedepends="cmake perl python3" subpackages="$pkgname-static $pkgname-dev $pkgname-utils" -source="$pkgname-$pkgver.tar.gz::https://github.com/ARMmbed/mbedtls/archive/mbedtls-$pkgver.tar.gz" -builddir="$srcdir/mbedtls-mbedtls-$pkgver" +source="$pkgname-$pkgver.tar.gz::https://github.com/ARMmbed/mbedtls/archive/v$pkgver.tar.gz" # Track security issues # https://tls.mbed.org/security # secfixes: +# 2.16.12-r0: +# - CVE-2021-44732 # 2.16.8-r0: # - CVE-2020-16150 # 2.16.6-r0: @@ -81,4 +82,4 @@ static() { chmod -x "$subpkgdir"/usr/lib/*.a } -sha512sums="f72538851c7a24ac14b5c153220260a49a083bfff44a52e9c1e77c51109bac779b5b4caac21f995176fe8f9d27843f3495692d6c7e9dc733cbcec896823ff0e0 mbedtls-2.16.9.tar.gz" +sha512sums="8d96d8cd906cc0999134320e4e1f550631426d166eab5da6e65469ee7286093810fcc6ac4bd5500ee55972d159f8bef7f9e53245f7f0eec72f72c35265b4313b mbedtls-2.16.12.tar.gz" diff --git a/main/mqtt-exec/APKBUILD b/main/mqtt-exec/APKBUILD index 98f35288f43..28dc57d3af8 100644 --- a/main/mqtt-exec/APKBUILD +++ b/main/mqtt-exec/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=mqtt-exec pkgver=0.4 -pkgrel=5 +pkgrel=6 pkgdesc="simple MQTT client that executes a command on messages" url="https://github.com/ncopa/mqtt-exec" arch="all" @@ -15,6 +15,7 @@ source="mqtt-exec-$pkgver.tar.gz::https://github.com/ncopa/mqtt-exec/archive/v$p 0001-authentication-expose-authentication-with-credential.patch 0001-Let-library-generate-client-id-when-unset.patch mqtt-exec.initd + mqtt-exec.confd " builddir="$srcdir"/mqtt-exec-$pkgver @@ -31,7 +32,10 @@ package() { "$pkgdir"/etc/init.d/mqtt-exec || return 1 } -sha512sums="1448b2dda0f27a5275c113331ea2bc073ec1740797c1bb5b472ee3e0fd4d3ef4bcdfa6dc42e7540ee154b291c3d70df89f0646899ebb1bfe585d1384797de5e7 mqtt-exec-0.4.tar.gz +sha512sums=" +1448b2dda0f27a5275c113331ea2bc073ec1740797c1bb5b472ee3e0fd4d3ef4bcdfa6dc42e7540ee154b291c3d70df89f0646899ebb1bfe585d1384797de5e7 mqtt-exec-0.4.tar.gz 418058ecc05922df186d0dcbfeab7656977256a143f0346406598d1cf7331d3ba95a9b004bf3b6581be2e3cb2fbf5e69d7954b4c7ac488863f0318506c7f1c7c 0001-authentication-expose-authentication-with-credential.patch 7007ad1afcba6b5c0e6224a30e3a6c1b9ce178603b27f575bb76d7b979b8e7f4c4c1226afa3ff8cf1f217fff832d0a69cff1cfbc205203dcb8a98afbf6f345ed 0001-Let-library-generate-client-id-when-unset.patch -7e0c461d5ed73fb8bac1da5f78bb7d8204f692fc3980ee916057c19c3673591d4143a71cc846f863566abfcc9ada22281bb690bc146e9ae37f43896248e5ed4a mqtt-exec.initd" +f8cab7fe709fc80b3a75f1d65d55e10c05a4b27e319a9190d3ee78050fea86d8c6512e3d624b8b413dab01b2043bed5f672453090251b93d261d79125f9f0d17 mqtt-exec.initd +e5cce69f5ad1f0fcf0eb0be7675c2f4ca4ba5518e8303adb16673b7e402dbe8d48b57c4b4512a0d3aba4541241d2ddeca68b88354d089606f67a5549508b44b5 mqtt-exec.confd +" diff --git a/main/mqtt-exec/mqtt-exec.confd b/main/mqtt-exec/mqtt-exec.confd new file mode 100644 index 00000000000..10a14760bbb --- /dev/null +++ b/main/mqtt-exec/mqtt-exec.confd @@ -0,0 +1,23 @@ +# The MQTT broker to connect to +#mqtt_broker=msg.alpinelinux.org + +# The topics to subscribe to. Separate topics by whitespace. +#mqtt_topics= + +# Set the topic for the Will +#will_topic= + +# Whether the Will should be retained or not +#will_retain=yes + +# The message in the Will +#will_payload= + +# QOS level for the Will +#will_qos= + +# Optional username to authenticate as +#mqtt_user= + +# Password for the user +#export MQTT_EXEC_PASSWORD= diff --git a/main/mqtt-exec/mqtt-exec.initd b/main/mqtt-exec/mqtt-exec.initd index ff94d01d449..c9d4e941cb9 100644 --- a/main/mqtt-exec/mqtt-exec.initd +++ b/main/mqtt-exec/mqtt-exec.initd @@ -34,6 +34,9 @@ start_pre() { if [ -n "$will_qos" ]; then set -- "$@" --will-qos "$will_qos" fi + if [ -n "$mqtt_user" ]; then + set -- "$@" --username "$mqtt_user" + fi set -- "$@" -- ${exec_command} diff --git a/main/ncurses/APKBUILD b/main/ncurses/APKBUILD index a8736fda6c3..62557c5ecf8 100644 --- a/main/ncurses/APKBUILD +++ b/main/ncurses/APKBUILD @@ -2,7 +2,7 @@ pkgname=ncurses pkgver=6.2_p20200523 _ver=${pkgver/_p/-} -pkgrel=0 +pkgrel=1 pkgdesc="Console display library" url="https://invisible-island.net/ncurses/" arch="all" @@ -11,10 +11,13 @@ license="MIT" makedepends_build="ncurses" subpackages="$pkgname-static $pkgname-dev $pkgname-doc $pkgname-libs $pkgname-terminfo-base:base:noarch $pkgname-terminfo:terminfo:noarch" -source="https://invisible-mirror.net/archives/ncurses/current/ncurses-$_ver.tgz" +source="https://invisible-mirror.net/archives/ncurses/current/ncurses-$_ver.tgz + CVE-2021-39537.patch" builddir="$srcdir"/ncurses-$_ver # secfixes: +# 6.2_p20200523-r1: +# - CVE-2021-39537 # 6.1_p20180414-r0: # - CVE-2018-10754 # 6.0_p20171125-r0: @@ -110,4 +113,5 @@ static() { mv "$pkgdir"/usr/lib/*.a "$subpkgdir"/usr/lib/ } -sha512sums="bcfee078ba4b4152909aad636dc6e354a9a0499e228db4c710d73d171fa73e208b4e62f403e0f90d16f8e367414bf2b6297f1acd47d9ba58e60b88d560862fb4 ncurses-6.2-20200523.tgz" +sha512sums="bcfee078ba4b4152909aad636dc6e354a9a0499e228db4c710d73d171fa73e208b4e62f403e0f90d16f8e367414bf2b6297f1acd47d9ba58e60b88d560862fb4 ncurses-6.2-20200523.tgz +8019db1f739c5e8ad0078d8266875bb1132a063406403ff1fd0686b6650eccd44cc3381a16adf89f3476fdf708bbac73cb29cf1fb48c28ab224637869c1e7714 CVE-2021-39537.patch" diff --git a/main/ncurses/CVE-2021-39537.patch b/main/ncurses/CVE-2021-39537.patch new file mode 100644 index 00000000000..f37cca21451 --- /dev/null +++ b/main/ncurses/CVE-2021-39537.patch @@ -0,0 +1,26 @@ +$NetBSD: patch-ncurses_tinfo_captoinfo.c,v 1.1 2021/10/09 07:52:36 wiz Exp $ + +Fix for CVE-2021-39537 from upstream: +https://github.com/ThomasDickey/ncurses-snapshots/commit/63ca9e061f4644795d6f3f559557f3e1ed8c738b#diff-7e95c7bc5f213e9be438e69a9d5d0f261a14952bcbd692f7b9014217b8047340 + +--- ./ncurses/tinfo/captoinfo.c.orig 2020-02-02 23:34:34.000000000 +0000 ++++ ./ncurses/tinfo/captoinfo.c +@@ -216,12 +216,15 @@ cvtchar(register const char *sp) + } + break; + case '^': ++ len = 2; + c = UChar(*++sp); +- if (c == '?') ++ if (c == '?') { + c = 127; +- else ++ } else if (c == '\0') { ++ len = 1; ++ } else { + c &= 0x1f; +- len = 2; ++ } + break; + default: + c = UChar(*sp); diff --git a/main/nettle/APKBUILD b/main/nettle/APKBUILD index 79c643351ca..70077290143 100644 --- a/main/nettle/APKBUILD +++ b/main/nettle/APKBUILD @@ -3,7 +3,7 @@ # Maintainer: Fabian Affolter <fabian@affolter-engineering.ch> pkgname=nettle pkgver=3.5.1 -pkgrel=1 +pkgrel=2 pkgdesc="A low-level cryptographic library" url="https://www.lysator.liu.se/~nisse/nettle/" arch="all" @@ -11,9 +11,16 @@ license="LGPL-2.0-or-later" depends_dev="gmp-dev" makedepends="$depends_dev m4" subpackages="$pkgname-static $pkgname-dev $pkgname-utils" -source="https://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz" +source="https://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz + CVE-2021-3580.patch + " + builddir="$srcdir/$pkgname-$pkgver" +# secfixes: +# 3.5.1-r2: +# - CVE-2021-3580 + build() { ./configure \ --build=$CBUILD \ @@ -48,4 +55,7 @@ utils() { mv "$pkgdir"/usr/bin "$subpkgdir"/usr/ } -sha512sums="f738121b9091cbe79435fb5d46b45cf6f10912320c233829356908127bab1cac6946ca56e022a832380c44f2c10f21d2feef64cb0f4f41e3da4a681dc0131784 nettle-3.5.1.tar.gz" +sha512sums=" +f738121b9091cbe79435fb5d46b45cf6f10912320c233829356908127bab1cac6946ca56e022a832380c44f2c10f21d2feef64cb0f4f41e3da4a681dc0131784 nettle-3.5.1.tar.gz +bfea56c22da1125fa4a3bda76c79fb432f49ede0dbc032c8e90a8048dacab6ac3544d19758b90763cccd99d4dc97ec988ecb6d4224715e0193ed9222b096a223 CVE-2021-3580.patch +" diff --git a/main/nettle/CVE-2021-3580.patch b/main/nettle/CVE-2021-3580.patch new file mode 100644 index 00000000000..fb7dcd60b18 --- /dev/null +++ b/main/nettle/CVE-2021-3580.patch @@ -0,0 +1,520 @@ +Patch-Source: https://git.lysator.liu.se/nettle/nettle/-/commit/fd6d9ba7ca92912762c072fcf74490bc5d63d633 +Patch-Source: https://git.lysator.liu.se/nettle/nettle/-/commit/cd6059aebdd3059fbcf674dddb850b821c13b6c2 +Patch-Source: https://git.lysator.liu.se/nettle/nettle/-/commit/c80961c646b0962ab152619ac0a7c6a21850a380 + +changelogs trimmed +--- + +From fd6d9ba7ca92912762c072fcf74490bc5d63d633 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> +Date: Thu, 6 May 2021 21:30:23 +0200 +Subject: [PATCH] Add check that message length to _pkcs1_sec_decrypt is valid. + +* pkcs1-sec-decrypt.c (_pkcs1_sec_decrypt): Check that message +length is valid, for given key size. +* testsuite/rsa-sec-decrypt-test.c (test_main): Add test cases for +calls to rsa_sec_decrypt specifying a too large message length. + +(cherry picked from commit 7616541e6eff73353bf682c62e3a68e4fe696707) +--- + ChangeLog | 8 ++++++++ + pkcs1-sec-decrypt.c | 4 +++- + testsuite/rsa-sec-decrypt-test.c | 17 ++++++++++++++++- + 3 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/pkcs1-sec-decrypt.c b/pkcs1-sec-decrypt.c +index 4f13080e..16833691 100644 +--- a/pkcs1-sec-decrypt.c ++++ b/pkcs1-sec-decrypt.c +@@ -63,7 +63,9 @@ _pkcs1_sec_decrypt (size_t length, uint8_t *message, + volatile int ok; + size_t i, t; + +- assert (padded_message_length >= length); ++ /* Message independent branch */ ++ if (length + 11 > padded_message_length) ++ return 0; + + t = padded_message_length - length - 1; + +diff --git a/testsuite/rsa-sec-decrypt-test.c b/testsuite/rsa-sec-decrypt-test.c +index fb0ed3a1..3419322e 100644 +--- a/testsuite/rsa-sec-decrypt-test.c ++++ b/testsuite/rsa-sec-decrypt-test.c +@@ -55,6 +55,7 @@ rsa_decrypt_for_test(const struct rsa_public_key *pub, + #endif + + #define PAYLOAD_SIZE 50 ++#define DECRYPTED_SIZE 256 + void + test_main(void) + { +@@ -63,7 +64,7 @@ test_main(void) + struct knuth_lfib_ctx random_ctx; + + uint8_t plaintext[PAYLOAD_SIZE]; +- uint8_t decrypted[PAYLOAD_SIZE]; ++ uint8_t decrypted[DECRYPTED_SIZE]; + uint8_t verifybad[PAYLOAD_SIZE]; + unsigned n_size = 1024; + mpz_t gibberish; +@@ -99,6 +100,20 @@ test_main(void) + PAYLOAD_SIZE, decrypted, gibberish) == 1); + ASSERT (MEMEQ (PAYLOAD_SIZE, plaintext, decrypted)); + ++ ASSERT (pub.size > 10); ++ ASSERT (pub.size <= DECRYPTED_SIZE); ++ ++ /* Check that too large message length is rejected, largest ++ valid size is pub.size - 11. */ ++ ASSERT (!rsa_decrypt_for_test (&pub, &key, &random_ctx, ++ (nettle_random_func *) knuth_lfib_random, ++ pub.size - 10, decrypted, gibberish)); ++ ++ /* This case used to result in arithmetic underflow and a crash. */ ++ ASSERT (!rsa_decrypt_for_test (&pub, &key, &random_ctx, ++ (nettle_random_func *) knuth_lfib_random, ++ pub.size, decrypted, gibberish)); ++ + /* bad one */ + memcpy(decrypted, verifybad, PAYLOAD_SIZE); + nettle_mpz_random_size(garbage, &random_ctx, +-- +GitLab + +From cd6059aebdd3059fbcf674dddb850b821c13b6c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> +Date: Tue, 8 Jun 2021 21:31:39 +0200 +Subject: [PATCH] Change _rsa_sec_compute_root_tr to take a fix input size. + +Improves consistency with _rsa_sec_compute_root, and fixes zero-input bug. + +(cherry picked from commit 485b5e2820a057e873b1ba812fdb39cae4adf98c) +--- + ChangeLog | 17 +++++++++- + rsa-decrypt-tr.c | 7 ++--- + rsa-internal.h | 4 +-- + rsa-sec-decrypt.c | 9 ++++-- + rsa-sign-tr.c | 61 +++++++++++++++++------------------- + testsuite/rsa-encrypt-test.c | 14 ++++++++- + 6 files changed, 69 insertions(+), 43 deletions(-) + +diff --git a/rsa-decrypt-tr.c b/rsa-decrypt-tr.c +index 0224c0b7..927a8915 100644 +--- a/rsa-decrypt-tr.c ++++ b/rsa-decrypt-tr.c +@@ -52,14 +52,13 @@ rsa_decrypt_tr(const struct rsa_public_key *pub, + mp_size_t key_limb_size; + int res; + +- key_limb_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size); ++ key_limb_size = mpz_size(pub->n); + + TMP_GMP_ALLOC (m, key_limb_size); + TMP_GMP_ALLOC (em, key->size); ++ mpz_limbs_copy(m, gibberish, key_limb_size); + +- res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, +- mpz_limbs_read(gibberish), +- mpz_size(gibberish)); ++ res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, m); + + mpn_get_base256 (em, key->size, m, key_limb_size); + +diff --git a/rsa-internal.h b/rsa-internal.h +index b828e451..f66a7df0 100644 +--- a/rsa-internal.h ++++ b/rsa-internal.h +@@ -78,11 +78,11 @@ _rsa_sec_compute_root(const struct rsa_private_key *key, + mp_limb_t *scratch); + + /* Safe side-channel silent variant, using RSA blinding, and checking the +- * result after CRT. */ ++ * result after CRT. In-place calls, with x == m, is allowed. */ + int + _rsa_sec_compute_root_tr(const struct rsa_public_key *pub, + const struct rsa_private_key *key, + void *random_ctx, nettle_random_func *random, +- mp_limb_t *x, const mp_limb_t *m, size_t mn); ++ mp_limb_t *x, const mp_limb_t *m); + + #endif /* NETTLE_RSA_INTERNAL_H_INCLUDED */ +diff --git a/rsa-sec-decrypt.c b/rsa-sec-decrypt.c +index 6866e7c8..fc4757a0 100644 +--- a/rsa-sec-decrypt.c ++++ b/rsa-sec-decrypt.c +@@ -58,9 +58,12 @@ rsa_sec_decrypt(const struct rsa_public_key *pub, + TMP_GMP_ALLOC (m, mpz_size(pub->n)); + TMP_GMP_ALLOC (em, key->size); + +- res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, +- mpz_limbs_read(gibberish), +- mpz_size(gibberish)); ++ /* We need a copy because m can be shorter than key_size, ++ * but _rsa_sec_compute_root_tr expect all inputs to be ++ * normalized to a key_size long buffer length */ ++ mpz_limbs_copy(m, gibberish, mpz_size(pub->n)); ++ ++ res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, m, m); + + mpn_get_base256 (em, key->size, m, mpz_size(pub->n)); + +diff --git a/rsa-sign-tr.c b/rsa-sign-tr.c +index f824c4ca..9e137c7a 100644 +--- a/rsa-sign-tr.c ++++ b/rsa-sign-tr.c +@@ -131,35 +131,34 @@ int + _rsa_sec_compute_root_tr(const struct rsa_public_key *pub, + const struct rsa_private_key *key, + void *random_ctx, nettle_random_func *random, +- mp_limb_t *x, const mp_limb_t *m, size_t mn) ++ mp_limb_t *x, const mp_limb_t *m) + { ++ mp_size_t nn; + mpz_t mz; + mpz_t xz; + int res; + +- mpz_init(mz); + mpz_init(xz); + +- mpn_copyi(mpz_limbs_write(mz, mn), m, mn); +- mpz_limbs_finish(mz, mn); ++ nn = mpz_size (pub->n); + +- res = rsa_compute_root_tr(pub, key, random_ctx, random, xz, mz); ++ res = rsa_compute_root_tr(pub, key, random_ctx, random, xz, ++ mpz_roinit_n(mz, m, nn)); + + if (res) +- mpz_limbs_copy(x, xz, mpz_size(pub->n)); ++ mpz_limbs_copy(x, xz, nn); + +- mpz_clear(mz); + mpz_clear(xz); + return res; + } + #else + /* Blinds m, by computing c = m r^e (mod n), for a random r. Also +- returns the inverse (ri), for use by rsa_unblind. */ ++ returns the inverse (ri), for use by rsa_unblind. Must have c != m, ++ no in-place operation.*/ + static void + rsa_sec_blind (const struct rsa_public_key *pub, + void *random_ctx, nettle_random_func *random, +- mp_limb_t *c, mp_limb_t *ri, const mp_limb_t *m, +- mp_size_t mn) ++ mp_limb_t *c, mp_limb_t *ri, const mp_limb_t *m) + { + const mp_limb_t *ep = mpz_limbs_read (pub->e); + const mp_limb_t *np = mpz_limbs_read (pub->n); +@@ -177,15 +176,15 @@ rsa_sec_blind (const struct rsa_public_key *pub, + + /* c = m*(r^e) mod n */ + itch = mpn_sec_powm_itch(nn, ebn, nn); +- i2 = mpn_sec_mul_itch(nn, mn); ++ i2 = mpn_sec_mul_itch(nn, nn); + itch = MAX(itch, i2); +- i2 = mpn_sec_div_r_itch(nn + mn, nn); ++ i2 = mpn_sec_div_r_itch(2*nn, nn); + itch = MAX(itch, i2); + i2 = mpn_sec_invert_itch(nn); + itch = MAX(itch, i2); + +- TMP_GMP_ALLOC (tp, nn + mn + itch); +- scratch = tp + nn + mn; ++ TMP_GMP_ALLOC (tp, 2*nn + itch); ++ scratch = tp + 2*nn; + + /* ri = r^(-1) */ + do +@@ -198,9 +197,8 @@ rsa_sec_blind (const struct rsa_public_key *pub, + while (!mpn_sec_invert (ri, tp, np, nn, 2 * nn * GMP_NUMB_BITS, scratch)); + + mpn_sec_powm (c, rp, nn, ep, ebn, np, nn, scratch); +- /* normally mn == nn, but m can be smaller in some cases */ +- mpn_sec_mul (tp, c, nn, m, mn, scratch); +- mpn_sec_div_r (tp, nn + mn, np, nn, scratch); ++ mpn_sec_mul (tp, c, nn, m, nn, scratch); ++ mpn_sec_div_r (tp, 2*nn, np, nn, scratch); + mpn_copyi(c, tp, nn); + + TMP_GMP_FREE (r); +@@ -208,7 +206,7 @@ rsa_sec_blind (const struct rsa_public_key *pub, + TMP_GMP_FREE (tp); + } + +-/* m = c ri mod n */ ++/* m = c ri mod n. Allows x == c. */ + static void + rsa_sec_unblind (const struct rsa_public_key *pub, + mp_limb_t *x, mp_limb_t *ri, const mp_limb_t *c) +@@ -299,7 +297,7 @@ int + _rsa_sec_compute_root_tr(const struct rsa_public_key *pub, + const struct rsa_private_key *key, + void *random_ctx, nettle_random_func *random, +- mp_limb_t *x, const mp_limb_t *m, size_t mn) ++ mp_limb_t *x, const mp_limb_t *m) + { + TMP_GMP_DECL (c, mp_limb_t); + TMP_GMP_DECL (ri, mp_limb_t); +@@ -307,7 +305,7 @@ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub, + size_t key_limb_size; + int ret; + +- key_limb_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size); ++ key_limb_size = mpz_size(pub->n); + + /* mpz_powm_sec handles only odd moduli. If p, q or n is even, the + key is invalid and rejected by rsa_private_key_prepare. However, +@@ -321,19 +319,18 @@ _rsa_sec_compute_root_tr(const struct rsa_public_key *pub, + } + + assert(mpz_size(pub->n) == key_limb_size); +- assert(mn <= key_limb_size); + + TMP_GMP_ALLOC (c, key_limb_size); + TMP_GMP_ALLOC (ri, key_limb_size); + TMP_GMP_ALLOC (scratch, _rsa_sec_compute_root_itch(key)); + +- rsa_sec_blind (pub, random_ctx, random, x, ri, m, mn); ++ rsa_sec_blind (pub, random_ctx, random, c, ri, m); + +- _rsa_sec_compute_root(key, c, x, scratch); ++ _rsa_sec_compute_root(key, x, c, scratch); + +- ret = rsa_sec_check_root(pub, c, x); ++ ret = rsa_sec_check_root(pub, x, c); + +- rsa_sec_unblind(pub, x, ri, c); ++ rsa_sec_unblind(pub, x, ri, x); + + cnd_mpn_zero(1 - ret, x, key_limb_size); + +@@ -357,17 +354,17 @@ rsa_compute_root_tr(const struct rsa_public_key *pub, + mpz_t x, const mpz_t m) + { + TMP_GMP_DECL (l, mp_limb_t); ++ mp_size_t nn = mpz_size(pub->n); + int res; + +- mp_size_t l_size = NETTLE_OCTET_SIZE_TO_LIMB_SIZE(key->size); +- TMP_GMP_ALLOC (l, l_size); ++ TMP_GMP_ALLOC (l, nn); ++ mpz_limbs_copy(l, m, nn); + +- res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, l, +- mpz_limbs_read(m), mpz_size(m)); ++ res = _rsa_sec_compute_root_tr (pub, key, random_ctx, random, l, l); + if (res) { +- mp_limb_t *xp = mpz_limbs_write (x, l_size); +- mpn_copyi (xp, l, l_size); +- mpz_limbs_finish (x, l_size); ++ mp_limb_t *xp = mpz_limbs_write (x, nn); ++ mpn_copyi (xp, l, nn); ++ mpz_limbs_finish (x, nn); + } + + TMP_GMP_FREE (l); +diff --git a/testsuite/rsa-encrypt-test.c b/testsuite/rsa-encrypt-test.c +index 87525f78..d3bc374b 100644 +--- a/testsuite/rsa-encrypt-test.c ++++ b/testsuite/rsa-encrypt-test.c +@@ -19,6 +19,7 @@ test_main(void) + uint8_t after; + + mpz_t gibberish; ++ mpz_t zero; + + rsa_private_key_init(&key); + rsa_public_key_init(&pub); +@@ -101,6 +102,17 @@ test_main(void) + ASSERT(decrypted[decrypted_length] == after); + ASSERT(decrypted[0] == 'A'); + ++ /* Test zero input. */ ++ mpz_init_set_ui (zero, 0); ++ decrypted_length = msg_length; ++ ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, zero)); ++ ASSERT(!rsa_decrypt_tr(&pub, &key, ++ &lfib, (nettle_random_func *) knuth_lfib_random, ++ &decrypted_length, decrypted, zero)); ++ ASSERT(!rsa_sec_decrypt(&pub, &key, ++ &lfib, (nettle_random_func *) knuth_lfib_random, ++ decrypted_length, decrypted, zero)); ++ ASSERT(decrypted_length == msg_length); + + /* Test invalid key. */ + mpz_add_ui (key.q, key.q, 2); +@@ -112,6 +124,6 @@ test_main(void) + rsa_private_key_clear(&key); + rsa_public_key_clear(&pub); + mpz_clear(gibberish); ++ mpz_clear(zero); + free(decrypted); + } +- +-- +GitLab + +From c80961c646b0962ab152619ac0a7c6a21850a380 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> +Date: Tue, 8 Jun 2021 21:32:38 +0200 +Subject: [PATCH] Add input check to rsa_decrypt family of functions. + +(cherry picked from commit 0ad0b5df315665250dfdaa4a1e087f4799edaefe) +--- + ChangeLog | 10 +++++++++- + rsa-decrypt-tr.c | 4 ++++ + rsa-decrypt.c | 10 ++++++++++ + rsa-sec-decrypt.c | 4 ++++ + rsa.h | 5 +++-- + testsuite/rsa-encrypt-test.c | 38 ++++++++++++++++++++++++++++++------ + 6 files changed, 62 insertions(+), 9 deletions(-) + +diff --git a/rsa-decrypt-tr.c b/rsa-decrypt-tr.c +index 927a8915..4a9e9d74 100644 +--- a/rsa-decrypt-tr.c ++++ b/rsa-decrypt-tr.c +@@ -52,6 +52,10 @@ rsa_decrypt_tr(const struct rsa_public_key *pub, + mp_size_t key_limb_size; + int res; + ++ /* First check that input is in range. */ ++ if (mpz_sgn (gibberish) < 0 || mpz_cmp (gibberish, pub->n) >= 0) ++ return 0; ++ + key_limb_size = mpz_size(pub->n); + + TMP_GMP_ALLOC (m, key_limb_size); +diff --git a/rsa-decrypt.c b/rsa-decrypt.c +index 7681439d..540d8baa 100644 +--- a/rsa-decrypt.c ++++ b/rsa-decrypt.c +@@ -48,6 +48,16 @@ rsa_decrypt(const struct rsa_private_key *key, + int res; + + mpz_init(m); ++ ++ /* First check that input is in range. Since we don't have the ++ public key available here, we need to reconstruct n. */ ++ mpz_mul (m, key->p, key->q); ++ if (mpz_sgn (gibberish) < 0 || mpz_cmp (gibberish, m) >= 0) ++ { ++ mpz_clear (m); ++ return 0; ++ } ++ + rsa_compute_root(key, m, gibberish); + + res = pkcs1_decrypt (key->size, m, length, message); +diff --git a/rsa-sec-decrypt.c b/rsa-sec-decrypt.c +index fc4757a0..4c98958d 100644 +--- a/rsa-sec-decrypt.c ++++ b/rsa-sec-decrypt.c +@@ -55,6 +55,10 @@ rsa_sec_decrypt(const struct rsa_public_key *pub, + TMP_GMP_DECL (em, uint8_t); + int res; + ++ /* First check that input is in range. */ ++ if (mpz_sgn (gibberish) < 0 || mpz_cmp (gibberish, pub->n) >= 0) ++ return 0; ++ + TMP_GMP_ALLOC (m, mpz_size(pub->n)); + TMP_GMP_ALLOC (em, key->size); + +diff --git a/rsa.h b/rsa.h +index 3b10155f..2dd35a2d 100644 +--- a/rsa.h ++++ b/rsa.h +@@ -428,13 +428,14 @@ rsa_sec_decrypt(const struct rsa_public_key *pub, + size_t length, uint8_t *message, + const mpz_t gibberish); + +-/* Compute x, the e:th root of m. Calling it with x == m is allowed. */ ++/* Compute x, the e:th root of m. Calling it with x == m is allowed. ++ It is required that 0 <= m < n. */ + void + rsa_compute_root(const struct rsa_private_key *key, + mpz_t x, const mpz_t m); + + /* Safer variant, using RSA blinding, and checking the result after +- CRT. */ ++ CRT. It is required that 0 <= m < n. */ + int + rsa_compute_root_tr(const struct rsa_public_key *pub, + const struct rsa_private_key *key, +diff --git a/testsuite/rsa-encrypt-test.c b/testsuite/rsa-encrypt-test.c +index d3bc374b..d1a440f6 100644 +--- a/testsuite/rsa-encrypt-test.c ++++ b/testsuite/rsa-encrypt-test.c +@@ -19,11 +19,12 @@ test_main(void) + uint8_t after; + + mpz_t gibberish; +- mpz_t zero; ++ mpz_t bad_input; + + rsa_private_key_init(&key); + rsa_public_key_init(&pub); + mpz_init(gibberish); ++ mpz_init(bad_input); + + knuth_lfib_init(&lfib, 17); + +@@ -103,15 +104,40 @@ test_main(void) + ASSERT(decrypted[0] == 'A'); + + /* Test zero input. */ +- mpz_init_set_ui (zero, 0); ++ mpz_set_ui (bad_input, 0); + decrypted_length = msg_length; +- ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, zero)); ++ ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, bad_input)); + ASSERT(!rsa_decrypt_tr(&pub, &key, + &lfib, (nettle_random_func *) knuth_lfib_random, +- &decrypted_length, decrypted, zero)); ++ &decrypted_length, decrypted, bad_input)); + ASSERT(!rsa_sec_decrypt(&pub, &key, + &lfib, (nettle_random_func *) knuth_lfib_random, +- decrypted_length, decrypted, zero)); ++ decrypted_length, decrypted, bad_input)); ++ ASSERT(decrypted_length == msg_length); ++ ++ /* Test input that is slightly larger than n */ ++ mpz_add(bad_input, gibberish, pub.n); ++ decrypted_length = msg_length; ++ ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, bad_input)); ++ ASSERT(!rsa_decrypt_tr(&pub, &key, ++ &lfib, (nettle_random_func *) knuth_lfib_random, ++ &decrypted_length, decrypted, bad_input)); ++ ASSERT(!rsa_sec_decrypt(&pub, &key, ++ &lfib, (nettle_random_func *) knuth_lfib_random, ++ decrypted_length, decrypted, bad_input)); ++ ASSERT(decrypted_length == msg_length); ++ ++ /* Test input that is considerably larger than n */ ++ mpz_mul_2exp (bad_input, pub.n, 100); ++ mpz_add (bad_input, bad_input, gibberish); ++ decrypted_length = msg_length; ++ ASSERT(!rsa_decrypt(&key, &decrypted_length, decrypted, bad_input)); ++ ASSERT(!rsa_decrypt_tr(&pub, &key, ++ &lfib, (nettle_random_func *) knuth_lfib_random, ++ &decrypted_length, decrypted, bad_input)); ++ ASSERT(!rsa_sec_decrypt(&pub, &key, ++ &lfib, (nettle_random_func *) knuth_lfib_random, ++ decrypted_length, decrypted, bad_input)); + ASSERT(decrypted_length == msg_length); + + /* Test invalid key. */ +@@ -124,6 +150,6 @@ test_main(void) + rsa_private_key_clear(&key); + rsa_public_key_clear(&pub); + mpz_clear(gibberish); +- mpz_clear(zero); ++ mpz_clear(bad_input); + free(decrypted); + } +-- +GitLab + diff --git a/main/nodejs/APKBUILD b/main/nodejs/APKBUILD index a4154f99ae5..4b26ab9f30c 100644 --- a/main/nodejs/APKBUILD +++ b/main/nodejs/APKBUILD @@ -6,6 +6,13 @@ # Maintainer: Jakub Jirutka <jakub@jirutka.cz> # # secfixes: +# 12.22.10-r0: +# - CVE-2021-22959 +# - CVE-2021-22960 +# - CVE-2021-44531 +# - CVE-2021-44532 +# - CVE-2021-44533 +# - CVE-2022-21824 # 12.22.6-r0: # - CVE-2021-37701 # - CVE-2021-37712 @@ -78,7 +85,7 @@ pkgname=nodejs # Note: Update only to even-numbered versions (e.g. 6.y.z, 8.y.z)! # Odd-numbered versions are supported only for 9 months by upstream. -pkgver=12.22.6 +pkgver=12.22.12 pkgrel=0 pkgdesc="JavaScript runtime built on V8 engine - LTS version" url="https://nodejs.org/" @@ -181,7 +188,7 @@ npm() { } sha512sums=" -8d0c40147960c4aeed100321054c1d5cc473d66d6513bca13f81409e067d8bbd76f7247208b6e1d7fac4f1f8a4000aedbbf3fc259d4b483b37da96d0a5475968 node-v12.22.6.tar.gz +cb45e8d0aa1808439def6b0e770bf5c15c7a03b4d399efee604b10e11c706a241d780d867597dc209d856bcbc66cf737cb2a996bad6f2737b4d912c96d8e1cd9 node-v12.22.12.tar.gz fc5848ced3e591e732b6a9af27679ca82f7605a4b2cd2f7eb6a411664b7c065892fb67a1db5aec7a26207582eecd8377476ed550c1dfb6c7917ba7babfa66a2d dont-run-gyp-files-for-bundled-deps.patch a63b42c08b55139c1c363f6ba8aba9d85a0621b383ed514f7562cfa02f0cc290785d7cfe09892ac39962980d1b318957511f57b3f9b9d1fbc8704c0603597c9a link-with-libatomic-on-mips32.patch 30ca1ce7f9512c943950b8eec98bca99d24c740ebaa14619292fe5ed931dcf603ca90afb1d704ca7f545e421752ba4dde81c0c5bbb5242eb1726739ca627e15f fix-build-with-system-c-ares.patch diff --git a/main/nss/APKBUILD b/main/nss/APKBUILD index 53385534deb..3fbfb5eb75a 100644 --- a/main/nss/APKBUILD +++ b/main/nss/APKBUILD @@ -2,8 +2,8 @@ # Contributor: Rasmus Thomsen <oss@cogitri.dev> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=nss -pkgver=3.60 -pkgrel=1 +pkgver=3.68.3 +pkgrel=0 pkgdesc="Mozilla Network Security Services" url="https://developer.mozilla.org/docs/Mozilla/Projects/NSS" arch="all" @@ -23,6 +23,10 @@ source="https://ftp.mozilla.org/pub/security/nss/releases/NSS_${pkgver//./_}_RTM options="!strip !check" # secfixes: +# 3.68.3-r0: +# - CVE-2022-1097 +# 3.60-r2: +# - CVE-2021-43527 # 3.58-r0: # - CVE-2020-25648 # 3.55-r0: @@ -179,8 +183,10 @@ tools() { mv "$pkgdir"/usr/bin "$subpkgdir"/usr/ } -sha512sums="6463b2da28b5d9f1f20d45f77a3179e2b93c874af5742c7fc51eb7c44cef93270acacf79174dc63905f227256cbcee23a36f98f1cfed10dd5c56ffc0a76e2695 nss-3.60.tar.gz +sha512sums=" +70fa8ab48d45249c04424979640583e8bc867432b7e3f26c1602db49a13861dd070f081ed82660bb7451f835dc859b5788ae12a67f9ddab1f6bd1a7afb1174d2 nss-3.68.3.tar.gz 75dbd648a461940647ff373389cc73bc8ec609139cd46c91bcce866af02be6bcbb0524eb3dfb721fbd5b0bc68c20081ed6f7debf6b24317f2a7ba823e8d3c531 nss.pc.in 0f2efa8563b11da68669d281b4459289a56f5a3a906eb60382126f3adcfe47420cdcedc6ab57727a3afeeffa2bbb4c750b43bef8b5f343a75c968411dfa30e09 nss-util.pc.in 09c69d4cc39ec9deebc88696a80d0f15eb2d8c94d9daa234a2adfec941b63805eb4ce7f2e1943857b938bddcaee1beac246a0ec627b71563d9f846e6119a4a15 nss-softokn.pc.in -2971669e128f06a9af40a5ba88218fa7c9eecfeeae8b0cf42e14f31ed12bf6fa4c5ce60289e078f50e2669a9376b56b45d7c29d726a7eac69ebe1d1e22dc710b nss-config.in" +2971669e128f06a9af40a5ba88218fa7c9eecfeeae8b0cf42e14f31ed12bf6fa4c5ce60289e078f50e2669a9376b56b45d7c29d726a7eac69ebe1d1e22dc710b nss-config.in +" diff --git a/main/openldap/APKBUILD b/main/openldap/APKBUILD index cc756f83a8e..6c111d5923f 100644 --- a/main/openldap/APKBUILD +++ b/main/openldap/APKBUILD @@ -20,8 +20,8 @@ # - CVE-2017-9287 # pkgname=openldap -pkgver=2.4.50 -pkgrel=2 +pkgver=2.4.58 +pkgrel=0 pkgdesc="LDAP Server" url="https://www.openldap.org" arch="all" @@ -60,10 +60,6 @@ source="https://www.openldap.org/software/download/OpenLDAP/openldap-release/ope fix-manpages.patch configs.patch cacheflush.patch - CVE-2020-25709.patch - CVE-2020-25710.patch - CVE-2020-25692.patch - CVE-2021-27212.patch slapd.initd slapd.confd @@ -153,7 +149,6 @@ build() { package() { make DESTDIR="$pkgdir" install - # Install MQTT overlay. make DESTDIR="$pkgdir" prefix=/usr libexec=/usr/lib \ -C contrib/slapd-modules/mqtt install @@ -277,16 +272,14 @@ _submv() { done } -sha512sums="f528043ff9de36f7b65d8816c9a9c24f0ac400041b2969965178ee6eae62c92a11af33a0a883e4954e5fff98a0738a9f9aa2faf5b385d21974754e045aab31ae openldap-2.4.50.tgz +sha512sums=" +2fa2aa36117692eca44e55559f162c8c796f78469e6c2aee91b06d46f2b755d416979c913a3d89bbf9db14cc84881ecffee69af75b48e1d16b7aa9d2e3873baa openldap-2.4.58.tgz 5d34d49eabe7cb66cf8284cc3bd9730fa23df4932df68549e242d250ee50d40c434ae074ebc720d5fbcd9d16587c9333c5598d30a5f1177caa61461ab7771f38 openldap-2.4-ppolicy.patch 44d97efb25d4f39ab10cd5571db43f3bfa7c617a5bb087085ae16c0298aca899b55c8742a502121ba743a73e6d77cd2056bc96cee63d6d0862dabc8fb5574357 openldap-2.4.11-libldap_r.patch 9c7f41279e91ed995c91e9a8c543c797d9294a93cf260afdc03ab5777e45ed045a4d6a4d4d0180b5dc387dc04babca01d818fbfa8168309df44f4500d2a430a4 openldap-mqtt-overlay.patch 8c4244d316a05870dd1147b2ab7ddbcfd7626b5dce2f5a0e72f066dc635c2edb4f1ea3be88c6fec2d5ab016001be16bedef70f2ce0695c3cd96f69e1614ff177 fix-manpages.patch -fd1c1ba368148d42c24071a8a8f668232347f4c48268cd189b6be4a48bb51fc11e8c29074e70db69e1a2c249210bc7d4b4d55a0712e5e97a9df04cc8f743fa70 configs.patch +5e8694502f6837a4e818c6de261029f720e47279d001008a502bb60d6e33a987e64245379ae623abad2ac4a0a2a12f2d69bafb3c714cfc44842ace004b4bf52b configs.patch 60c1ec62003a33036de68402544e25a71715ed124a3139056a94ed1ba02fb8148ee510ab8f182a308105a2f744b9787e67112bcd8cd0d800cdb6f5409c4f63ff cacheflush.patch -61d2d02b733011eefaac0681b7f6274e416dac4d420b354e37f51b07cc42dab61c798fbe5fab36f47079962046f309373b41886b4632e86dc08d5bfe59b275f7 CVE-2020-25709.patch -abb7f43b6379fe6c03e583dc3a2c861c573ad6b83710954e35928e0449a1b78e259d8d5c6b7c33747b347ab67388d4894980a954d5ddb24b51a693b9c43798f2 CVE-2020-25710.patch -023b32e1a8e61c96b77723dfe39d33de170af684e29defdb34c14719b77fa0e9a101f8aaafe378afb30bf5ca732cf7209ef291089d7524b2301a97c102f5f6e4 CVE-2020-25692.patch -c207a7d7b07a72fdd89f9d7e80b09c5c9110bf36cef8ad79c1ea3fd25896f6c2242873d17ba7822aea12ba37486272637112a37ad293fbe2ddd6fa50c7824239 CVE-2021-27212.patch 2d286ff7cc56153204f3ab79c464d083801a40cc9bbb0b5cc1fb19de63d6e81c953b1ab0edd256d9ba48144bbda9a0c0d628bfec1342129aa2727344dea5fa9e slapd.initd -64dc4c0aa0abe3d9f7d2aef25fe4c8e23c53df2421067947ac4d096c9e942b26356cb8577ebc41b52d88d0b0a03b2a3e435fe86242671f9b36555a5f82ee0e3a slapd.confd" +64dc4c0aa0abe3d9f7d2aef25fe4c8e23c53df2421067947ac4d096c9e942b26356cb8577ebc41b52d88d0b0a03b2a3e435fe86242671f9b36555a5f82ee0e3a slapd.confd +" diff --git a/main/openldap/CVE-2020-25692.patch b/main/openldap/CVE-2020-25692.patch deleted file mode 100644 index 941a4f56be3..00000000000 --- a/main/openldap/CVE-2020-25692.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 4c774220a752bf8e3284984890dc0931fe73165d Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@openldap.org> -Date: Mon, 19 Oct 2020 14:03:41 +0100 -Subject: [PATCH] ITS#9370 check for equality rule on old_rdn - -Just skip normalization if there's no equality rule. We accept -DNs without equality rules already. ---- - servers/slapd/modrdn.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c -index c73dd8dba..a22975540 100644 ---- a/servers/slapd/modrdn.c -+++ b/servers/slapd/modrdn.c -@@ -505,7 +505,7 @@ slap_modrdn2mods( - mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) ); - ber_dupbv( &mod_tmp->sml_values[0], &old_rdn[d_cnt]->la_value ); - mod_tmp->sml_values[1].bv_val = NULL; -- if( desc->ad_type->sat_equality->smr_normalize) { -+ if( desc->ad_type->sat_equality && desc->ad_type->sat_equality->smr_normalize) { - mod_tmp->sml_nvalues = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) ); - (void) (*desc->ad_type->sat_equality->smr_normalize)( - SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, --- -GitLab - diff --git a/main/openldap/CVE-2020-25709.patch b/main/openldap/CVE-2020-25709.patch deleted file mode 100644 index d38c9d241da..00000000000 --- a/main/openldap/CVE-2020-25709.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 67670f4544e28fb09eb7319c39f404e1d3229e65 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@openldap.org> -Date: Mon, 2 Nov 2020 13:12:10 +0000 -Subject: [PATCH] ITS#9383 remove assert in certificateListValidate - ---- - servers/slapd/schema_init.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c -index ea0d67aa6..28f9e71a1 100644 ---- a/servers/slapd/schema_init.c -+++ b/servers/slapd/schema_init.c -@@ -371,8 +371,7 @@ certificateListValidate( Syntax *syntax, struct berval *in ) - /* Optional version */ - if ( tag == LBER_INTEGER ) { - tag = ber_get_int( ber, &version ); -- assert( tag == LBER_INTEGER ); -- if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; -+ if ( tag != LBER_INTEGER || version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX; - } - tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ - if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; --- -GitLab - diff --git a/main/openldap/CVE-2020-25710.patch b/main/openldap/CVE-2020-25710.patch deleted file mode 100644 index 9b9bae8b31f..00000000000 --- a/main/openldap/CVE-2020-25710.patch +++ /dev/null @@ -1,27 +0,0 @@ -From bdb0d459187522a6063df13871b82ba8dcc6efe2 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@openldap.org> -Date: Mon, 2 Nov 2020 16:01:14 +0000 -Subject: [PATCH] ITS#9384 remove assert in obsolete csnNormalize23() - ---- - servers/slapd/schema_init.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c -index 5812bc4b6..ea0d67aa6 100644 ---- a/servers/slapd/schema_init.c -+++ b/servers/slapd/schema_init.c -@@ -5327,8 +5327,8 @@ csnNormalize23( - } - *ptr = '\0'; - -- assert( ptr == &bv.bv_val[bv.bv_len] ); -- if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { -+ if ( ptr != &bv.bv_val[bv.bv_len] || -+ csnValidate( syntax, &bv ) != LDAP_SUCCESS ) { - return LDAP_INVALID_SYNTAX; - } - --- -GitLab - diff --git a/main/openldap/CVE-2021-27212.patch b/main/openldap/CVE-2021-27212.patch deleted file mode 100644 index 59f6d84e162..00000000000 --- a/main/openldap/CVE-2021-27212.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 9badb73425a67768c09bcaed1a9c26c684af6c30 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@openldap.org> -Date: Sat, 6 Feb 2021 20:52:06 +0000 -Subject: [PATCH] ITS#9454 fix issuerAndThisUpdateCheck - ---- - servers/slapd/schema_init.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c -index 31be1154e..8b1e25539 100644 ---- a/servers/slapd/schema_init.c -+++ b/servers/slapd/schema_init.c -@@ -3900,6 +3900,8 @@ issuerAndThisUpdateCheck( - break; - } - } -+ if ( tu->bv_len < STRLENOF("YYYYmmddHHmmssZ") ) return LDAP_INVALID_SYNTAX; -+ - x.bv_val += tu->bv_len + 1; - x.bv_len -= tu->bv_len + 1; - --- -GitLab - diff --git a/main/openldap/configs.patch b/main/openldap/configs.patch index 8f0c2bfdbbd..ed811f10f7e 100644 --- a/main/openldap/configs.patch +++ b/main/openldap/configs.patch @@ -63,7 +63,7 @@ # # Do not enable referrals until AFTER you have a working directory # service AND an understanding of referrals. -@@ -26,22 +27,23 @@ +@@ -26,16 +26,17 @@ # # Load dynamic backend modules: # @@ -71,24 +71,26 @@ -#objectClass: olcModuleList -#cn: module -#olcModulepath: %MODULEDIR% --#olcModuleload: back_bdb.la --#olcModuleload: back_hdb.la --#olcModuleload: back_ldap.la --#olcModuleload: back_passwd.la --#olcModuleload: back_shell.la +-#olcModuleload: back_mdb.la +dn: cn=module,cn=config +objectClass: olcModuleList +cn: module +olcModulepath: /usr/lib/openldap + #olcModuleload: back_bdb.la +-#olcModuleload: back_hdb.la +-#olcModuleload: back_ldap.la +-#olcModuleload: back_passwd.la +-#olcModuleload: back_shell.la +#olcModuleload: back_bdb.so +#olcModuleload: back_hdb.so +#olcModuleload: back_ldap.so -+olcModuleload: back_mdb.so ++olcModuleload: back_mdb.so +#olcModuleload: back_passwd.so +#olcModuleload: back_shell.so dn: cn=schema,cn=config +@@ -42,7 +42,7 @@ objectClass: olcSchemaConfig cn: schema diff --git a/main/openrc/CVE-2018-21269.patch b/main/openrc/0012-CVE-2018-21269.patch index 9975d7bf81b..9975d7bf81b 100644 --- a/main/openrc/CVE-2018-21269.patch +++ b/main/openrc/0012-CVE-2018-21269.patch diff --git a/main/openrc/0013-fix-typo-synbolic-symbolic.patch b/main/openrc/0013-fix-typo-synbolic-symbolic.patch new file mode 100644 index 00000000000..46f90974b8f --- /dev/null +++ b/main/openrc/0013-fix-typo-synbolic-symbolic.patch @@ -0,0 +1,22 @@ +From ac7ca6d901d72b1bc4ed13be5438e825c07fc0da Mon Sep 17 00:00:00 2001 +From: Michael Orlitzky <michael@orlitzky.com> +Date: Wed, 25 Nov 2020 07:11:55 -0500 +Subject: [PATCH] src/rc/checkpath.c: fix typo "synbolic" -> "symbolic". + +--- + src/rc/checkpath.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c +index ff54a8922..6422446a1 100644 +--- a/src/rc/checkpath.c ++++ b/src/rc/checkpath.c +@@ -117,7 +117,7 @@ static int get_dirfd(char *path, bool symlinks) { + strerror(errno)); + if (S_ISLNK(st.st_mode) ) { + if (st.st_uid != 0) +- eerrorx("%s: %s: synbolic link %s not owned by root", ++ eerrorx("%s: %s: symbolic link %s not owned by root", + applet, path, str); + linksize = st.st_size+1; + if (linkpath) diff --git a/main/openrc/0014-checkpath-replace-mkdir-with-mkdirat.patch b/main/openrc/0014-checkpath-replace-mkdir-with-mkdirat.patch new file mode 100644 index 00000000000..8f3d55db5de --- /dev/null +++ b/main/openrc/0014-checkpath-replace-mkdir-with-mkdirat.patch @@ -0,0 +1,33 @@ +From 00ea2166081856774f24f7243126f701c7fe6db9 Mon Sep 17 00:00:00 2001 +From: Michael Orlitzky <michael@orlitzky.com> +Date: Wed, 25 Nov 2020 07:15:50 -0500 +Subject: [PATCH] src/rc/checkpath.c: replace mkdir() with mkdirat(). + +The do_check() function recently gained some defenses against symlink +replacement attacks that involve the use of *at functions in place of +their vanilla counterparts; openat() instead of open(), for example. +One opportunity to replace mkdir() with mkdirat() was missed, however, +and this commit replaces it. + +This fixes #386. +--- + src/rc/checkpath.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c +index 6422446a1..1e570de92 100644 +--- a/src/rc/checkpath.c ++++ b/src/rc/checkpath.c +@@ -197,10 +197,10 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, + mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; + u = umask(0); + /* We do not recursively create parents */ +- r = mkdir(path, mode); ++ r = mkdirat(dirfd, name, mode); + umask(u); + if (r == -1 && errno != EEXIST) { +- eerror("%s: mkdir: %s", applet, ++ eerror("%s: mkdirat: %s", applet, + strerror (errno)); + return -1; + } diff --git a/main/openrc/0015-checkpath-remove-extra-slashes.patch b/main/openrc/0015-checkpath-remove-extra-slashes.patch new file mode 100644 index 00000000000..6643f564752 --- /dev/null +++ b/main/openrc/0015-checkpath-remove-extra-slashes.patch @@ -0,0 +1,106 @@ +From 63db2d99e730547339d1bdd28e8437999c380cae Mon Sep 17 00:00:00 2001 +From: William Hubbs <w.d.hubbs@gmail.com> +Date: Tue, 13 Apr 2021 17:13:20 -0500 +Subject: [PATCH] checkpath: remove extra slashes from paths + +This fixes #418. +--- + src/rc/checkpath.c | 49 ++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 10 deletions(-) + +diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c +index f8eb0e81..b2d1dd23 100644 +--- a/src/rc/checkpath.c ++++ b/src/rc/checkpath.c +@@ -93,13 +93,13 @@ static int get_dirfd(char *path, bool symlinks) + if (dirfd == -1) + eerrorx("%s: unable to open the root directory: %s", + applet, strerror(errno)); +- path_dupe = xstrdup(path); +- ch = path_dupe; ++ ch = path; + while (*ch) { + if (*ch == '/') + components++; + ch++; + } ++ path_dupe = xstrdup(path); + item = strtok(path_dupe, "/"); + #ifdef O_PATH + flags |= O_PATH; +@@ -136,18 +136,44 @@ static int get_dirfd(char *path, bool symlinks) + dirfd = new_dirfd; + free(linkpath); + linkpath = NULL; +- item = strtok(NULL, "/"); +- components--; + } ++ item = strtok(NULL, "/"); ++ components--; + } + free(path_dupe); +- if (linkpath) { +- free(linkpath); +- linkpath = NULL; +- } ++ free(linkpath); + return dirfd; + } + ++static char *clean_path(char *path) ++{ ++ char *ch; ++ char *ch2; ++ char *str; ++ str = xmalloc(strlen(path)); ++ ch = path; ++ ch2 = str; ++ while (true) { ++ *ch2 = *ch; ++ ch++; ++ ch2++; ++ if (!*(ch-1)) ++ break; ++ while (*(ch - 1) == '/' && *ch == '/') ++ ch++; ++ } ++ /* get rid of trailing / characters */ ++ while ((ch = strrchr(str, '/'))) { ++ if (ch == str) ++ break; ++ if (!*(ch+1)) ++ *ch = 0; ++ else ++ break; ++ } ++ return str; ++} ++ + static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, + inode_t type, bool trunc, bool chowner, bool symlinks, bool selinux_on) + { +@@ -345,6 +371,7 @@ int main(int argc, char **argv) + bool symlinks = false; + bool writable = false; + bool selinux_on = false; ++ char *path = NULL; + + applet = basename_c(argv[0]); + while ((opt = getopt_long(argc, argv, getoptstring, +@@ -407,12 +434,14 @@ int main(int argc, char **argv) + selinux_on = true; + + while (optind < argc) { ++ path = clean_path(argv[optind]); + if (writable) +- exit(!is_writable(argv[optind])); +- if (do_check(argv[optind], uid, gid, mode, type, trunc, chowner, ++ exit(!is_writable(path)); ++ if (do_check(path, uid, gid, mode, type, trunc, chowner, + symlinks, selinux_on)) + retval = EXIT_FAILURE; + optind++; ++ free(path); + } + + if (selinux_on) diff --git a/main/openrc/0016-checkpath-fix-code-to-walk-the-directory-path.patch b/main/openrc/0016-checkpath-fix-code-to-walk-the-directory-path.patch new file mode 100644 index 00000000000..4cfd18bee92 --- /dev/null +++ b/main/openrc/0016-checkpath-fix-code-to-walk-the-directory-path.patch @@ -0,0 +1,32 @@ +From 55ceac775c388191090fe37aef489d721ee9299d Mon Sep 17 00:00:00 2001 +From: William Hubbs <w.d.hubbs@gmail.com> +Date: Thu, 15 Apr 2021 17:39:51 -0500 +Subject: [PATCH] checkpath: fix code to walk the directory path + +X-Gentoo-Bug: 782808 +X-Gentoo-Bug-URL: https://bugs.gentoo.org/782808 +--- + src/rc/checkpath.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c +index 48275ca9..6856d034 100644 +--- a/src/rc/checkpath.c ++++ b/src/rc/checkpath.c +@@ -131,13 +131,14 @@ static int get_dirfd(char *path, bool symlinks) { + */ + close(new_dirfd); + } else { ++ /* now walk down the directory path */ + close(dirfd); + dirfd = new_dirfd; + free(linkpath); + linkpath = NULL; ++ item = strtok(NULL, "/"); ++ components--; + } +- item = strtok(NULL, "/"); +- components--; + } + free(path_dupe); + free(linkpath); diff --git a/main/openrc/APKBUILD b/main/openrc/APKBUILD index eaa1406b030..1865d71a8be 100644 --- a/main/openrc/APKBUILD +++ b/main/openrc/APKBUILD @@ -2,12 +2,12 @@ pkgname=openrc pkgver=0.42.1 _ver=${pkgver/_git*/} -pkgrel=12 +pkgrel=14 pkgdesc="OpenRC manages the services, startup and shutdown of a host" url="https://github.com/OpenRC/openrc" arch="all" license="BSD-2-Clause" -makedepends="bsd-compat-headers" +makedepends="bsd-compat-headers linux-headers" subpackages="$pkgname-doc $pkgname-dev $pkgname-zsh-completion:zshcomp:noarch $pkgname-bash-completion:bashcomp:noarch" @@ -24,8 +24,13 @@ source="$pkgname-$pkgver.tar.gz::https://github.com/OpenRC/openrc/archive/$pkgve 0009-Support-early-loading-of-keymap-if-kdb-is-installed.patch 0010-rc-mount-make-timeout-invocation-compatible-with-bus.patch 0011-vrf.patch + 0012-CVE-2018-21269.patch + 0013-fix-typo-synbolic-symbolic.patch + 0014-checkpath-replace-mkdir-with-mkdirat.patch + 0015-checkpath-remove-extra-slashes.patch + 0016-checkpath-fix-code-to-walk-the-directory-path.patch - CVE-2018-21269.patch + seedrng.patch openrc.logrotate hostname.initd @@ -132,7 +137,12 @@ d2b8700f56b05579926352855de8fcee5cf78f0c13200643a5195f8c60e2b5082d476b42cc77b132 667085d89e194f7e2255d5c098c3d8de272f54cb925710cb98d5e7a6b58982d0acfe15f97b574cfc646b139cd7aa5b527ba700ef9b8048a6d6d9dee8cc74913c 0009-Support-early-loading-of-keymap-if-kdb-is-installed.patch ff9bf2f6e4f55633a9641385398f70a2e591e2b3b56b1903f168a97b07bd56dc5a65d151deeab94229452b2e892b597c16dc3d57d5d47ec35a48cf5343190c36 0010-rc-mount-make-timeout-invocation-compatible-with-bus.patch 34c5b1157d9f1e26f9c9121b649f7a31c32f3bdd62a17f451d3391f276ec8ca82623c1b917506867647523d18a1ee665a17d261ac12ff1732ab5c19cfaf91aac 0011-vrf.patch -715016b4f481a6d4d2ab37d23659e6cacc023b02fa6908b566391ee2744369076ea74e54f0fe576e2cc1d3371d4d9e3818395ca3f417233358fc70a9edc4dba6 CVE-2018-21269.patch +715016b4f481a6d4d2ab37d23659e6cacc023b02fa6908b566391ee2744369076ea74e54f0fe576e2cc1d3371d4d9e3818395ca3f417233358fc70a9edc4dba6 0012-CVE-2018-21269.patch +95a5e825836be935009d233d8e4e00707bf2fda0ff3f01f97a10a4a3a0a42eded0a235a008345bf4b89a60bc363bad05ff0a98c00dd179a4b56c573523f17630 0013-fix-typo-synbolic-symbolic.patch +cdad2ee011efa0ec38c27243cfec6f4353b6a1d9de3bff29e79e1c341e45bd4ef29aa1f641363a50246a3a876b8668b66971f59c857e979a2beb41fb5a25a327 0014-checkpath-replace-mkdir-with-mkdirat.patch +3c502dda023387c852e1fe92e873ca88ff9e6311a870f3f5317e9529b9513e0c42b8b7241ba6546129530e42a64f7c61b074fc1cb262c3228aabaf83db1cc1d8 0015-checkpath-remove-extra-slashes.patch +90e50369c04a4b2c4e5924f9ae084d69f6d3d09a3bd7c902a7e3797d5d52c725e1a4033e5c554f104807f3a7ecbb3ab2ecb89636680d69024fd0ec123866a35b 0016-checkpath-fix-code-to-walk-the-directory-path.patch +e204fef5e5d1e8da140c43f42f0eb97283cb56c02193d137f56217cfd7b9ae0dfad5954fb8d1ce0fcb63c20537551ba706e7fd09f3f012fc2a6a0c1106d2540b seedrng.patch 12bb6354e808fbf47bbab963de55ee7901738b4a912659982c57ef2777fff9a670e867fcb8ec316a76b151032c92dc89a950d7d1d835ef53f753a8f3b41d2cec openrc.logrotate 493f27d588e64bb2bb542b32493ed05873f4724e8ad1751002982d7b4e07963cfb72f93603b2d678f305177cf9556d408a87b793744c6b7cd46cf9be4b744c02 hostname.initd c06eac7264f6cc6888563feeae5ca745aae538323077903de1b19102e4f16baa34c18b8c27af5dd5423e7670834e2261e9aa55f2b1ec8d8fdc2be105fe894d55 hwdrivers.initd diff --git a/main/openrc/seedrng.patch b/main/openrc/seedrng.patch new file mode 100644 index 00000000000..4f06f1e8016 --- /dev/null +++ b/main/openrc/seedrng.patch @@ -0,0 +1,619 @@ +From 076c2552aeff88a27fe275dfaae61dedf4bb4bd5 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" <Jason@zx2c4.com> +Date: Thu, 24 Mar 2022 22:07:16 -0600 +Subject: [PATCH] Use seedrng for seeding the random number generator + +The RNG can't actually be seeded from a shell script, due to the +reliance on ioctls. For this reason, the seedrng project provides a +basic script meant to be copy and pasted into projects like OpenRC and +tweaked as needed: https://git.zx2c4.com/seedrng/about/ + +This commit imports it into OpenRC and wires up /etc/init.d/urandom to +call it. It shouldn't be called by other things on the system, so it +lives in rc_sbindir. + +Closes #506. +Closes #507. + +Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> +--- + AUTHORS | 1 + + conf.d/urandom | 9 +- + init.d/urandom.in | 41 ++-- + src/rc/Makefile | 6 +- + src/rc/meson.build | 10 +- + src/rc/seedrng.c | 453 +++++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 499 insertions(+), 21 deletions(-) + create mode 100644 src/rc/seedrng.c + +diff --git a/AUTHORS b/AUTHORS +index 0616d5175..ede0f471b 100644 +--- a/AUTHORS ++++ b/AUTHORS +@@ -43,6 +43,7 @@ Ian Stakenvicius <axs@gentoo.org> + Jakob Drexel <jake42@rommel.stw.uni-erlangen.de> + James Le Cuirot <chewi@aura-online.co.uk> + Jan Psota <jasiu@belsznica.pl> ++Jason A. Donenfeld <Jason@zx2c4.com> + Jason Zaman <jason@perfinion.com> + Joe Harvell <jharvell@dogpad.net> + Joe M <joe9mail@gmail.com> +diff --git a/conf.d/urandom b/conf.d/urandom +index f721a2491..744e4f702 100644 +--- a/conf.d/urandom ++++ b/conf.d/urandom +@@ -2,4 +2,11 @@ + # (say for crypt swap), so you will need to customize this + # behavior. If you have /var on a separate partition, then + # make sure this path lives on your root device somewhere. +-urandom_seed="/var/lib/misc/random-seed" ++seed_dir="/var/lib/seedrng" ++lock_file="/var/run/seedrng.lock" ++ ++# Set this to true if you do not want seed files to actually ++# credit the RNG. Set this if you plan to replicate this ++# file system image and do not have the wherewithal to first ++# delete the contents of /var/lib/seedrng. ++skip_credit="false" +diff --git a/init.d/urandom.in b/init.d/urandom.in +index 0d6ab66e0..cda431fdb 100644 +--- a/init.d/urandom.in ++++ b/init.d/urandom.in +@@ -1,5 +1,5 @@ + #!@SBINDIR@/openrc-run +-# Copyright (c) 2007-2015 The OpenRC Authors. ++# Copyright (c) 2007-2022 The OpenRC Authors. + # See the Authors file at the top-level directory of this distribution and + # https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS + # +@@ -9,7 +9,10 @@ + # This file may not be copied, modified, propagated, or distributed + # except according to the terms contained in the LICENSE file. + +-: ${urandom_seed:=${URANDOM_SEED:-/var/lib/misc/random-seed}} ++export SEEDRNG_SEED_DIR="${seed_dir:-/var/lib/seedrng}" ++export SEEDRNG_LOCK_FILE="${lock_file:-/var/run/seedrng.lock}" ++export SEEDRNG_SKIP_CREDIT="${skip_credit:-false}" ++: ${urandom_seed:=${SEEDRNG_SEED_DIR}/../misc/random-seed} + description="Initializes the random number generator." + + depend() +@@ -21,33 +24,35 @@ depend() + + save_seed() + { +- local psz=1 +- +- if [ -e /proc/sys/kernel/random/poolsize ]; then +- : $(( psz = $(cat /proc/sys/kernel/random/poolsize) / 4096 )) +- fi +- + ( # sub shell to prevent umask pollution + umask 077 +- dd if=/dev/urandom of="$urandom_seed" count=${psz} 2>/dev/null ++ dd if=/dev/urandom of="$urandom_seed" count=1 2>/dev/null + ) + } + + start() + { +- [ -c /dev/urandom ] || return +- if [ -f "$urandom_seed" ]; then +- ebegin "Initializing random number generator" +- cat "$urandom_seed" > /dev/urandom +- eend $? "Error initializing random number generator" ++ if [ "$RC_UNAME" = Linux ]; then ++ seedrng ++ else ++ [ -c /dev/urandom ] || return ++ if [ -f "$urandom_seed" ]; then ++ ebegin "Initializing random number generator" ++ cat "$urandom_seed" > /dev/urandom ++ eend $? "Error initializing random number generator" ++ fi ++ rm -f "$urandom_seed" && save_seed + fi +- rm -f "$urandom_seed" && save_seed + return 0 + } + + stop() + { +- ebegin "Saving random seed" +- save_seed +- eend $? "Failed to save random seed" ++ if [ "$RC_UNAME" = Linux ]; then ++ seedrng ++ else ++ ebegin "Saving random seed" ++ save_seed ++ eend $? "Failed to save random seed" ++ fi + } +diff --git a/src/rc/Makefile b/src/rc/Makefile +index fd796d920..62539f134 100644 +--- a/src/rc/Makefile ++++ b/src/rc/Makefile +@@ -15,7 +15,7 @@ endif + + ifeq (${OS},Linux) + SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-sysvinit.c broadcast.c \ +- rc-wtmp.c ++ rc-wtmp.c seedrng.c + endif + + CLEANFILES= version.h rc-selinux.o +@@ -47,6 +47,7 @@ RC_SBINPROGS= mark_service_starting mark_service_started \ + + ifeq (${OS},Linux) + RC_BINPROGS+= kill_all ++RC_SBINPROGS+= seedrng + SBINPROGS+= openrc-init openrc-shutdown + endif + +@@ -180,3 +181,6 @@ shell_var: shell_var.o + + swclock: swclock.o _usage.o rc-misc.o + ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ++ ++seedrng: seedrng.o ++ ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} +diff --git a/src/rc/seedrng.c b/src/rc/seedrng.c +new file mode 100644 +index 000000000..c1f941457 +--- /dev/null ++++ b/src/rc/seedrng.c +@@ -0,0 +1,453 @@ ++/* ++ * seedrng.c ++ * Seed kernel RNG from seed file, based on code from: ++ * https://git.zx2c4.com/seedrng/about/ ++ */ ++ ++/* ++ * Copyright (c) 2022 The OpenRC Authors. ++ * See the Authors file at the top-level directory of this distribution and ++ * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS ++ * ++ * This file is part of OpenRC. It is subject to the license terms in ++ * the LICENSE file found in the top-level directory of this ++ * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE ++ * This file may not be copied, modified, propagated, or distributed ++ * except according to the terms contained in the LICENSE file. ++ */ ++ ++#include <linux/random.h> ++#include <sys/random.h> ++#include <sys/ioctl.h> ++#include <sys/file.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++#include <fcntl.h> ++#include <poll.h> ++#include <unistd.h> ++#include <time.h> ++#include <errno.h> ++#include <endian.h> ++#include <stdbool.h> ++#include <stdint.h> ++#include <string.h> ++#include <stdio.h> ++#include <stdlib.h> ++ ++#include "rc.h" ++#include "einfo.h" ++#include "helpers.h" ++ ++#ifndef GRND_INSECURE ++#define GRND_INSECURE 0x0004 /* Apparently some headers don't ship with this yet. */ ++#endif ++ ++static const char *SEED_DIR; ++static const char *LOCK_FILE; ++static char *CREDITABLE_SEED; ++static char *NON_CREDITABLE_SEED; ++ ++enum blake2s_lengths { ++ BLAKE2S_BLOCK_LEN = 64, ++ BLAKE2S_HASH_LEN = 32, ++ BLAKE2S_KEY_LEN = 32 ++}; ++ ++enum seedrng_lengths { ++ MAX_SEED_LEN = 512, ++ MIN_SEED_LEN = BLAKE2S_HASH_LEN ++}; ++ ++struct blake2s_state { ++ uint32_t h[8]; ++ uint32_t t[2]; ++ uint32_t f[2]; ++ uint8_t buf[BLAKE2S_BLOCK_LEN]; ++ unsigned int buflen; ++ unsigned int outlen; ++}; ++ ++#define le32_to_cpup(a) le32toh(*(a)) ++#define cpu_to_le32(a) htole32(a) ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++#endif ++#ifndef DIV_ROUND_UP ++#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) ++#endif ++ ++static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words) ++{ ++ while (words--) { ++ *buf = cpu_to_le32(*buf); ++ ++buf; ++ } ++} ++ ++static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words) ++{ ++ while (words--) { ++ *buf = le32_to_cpup(buf); ++ ++buf; ++ } ++} ++ ++static inline uint32_t ror32(uint32_t word, unsigned int shift) ++{ ++ return (word >> (shift & 31)) | (word << ((-shift) & 31)); ++} ++ ++static const uint32_t blake2s_iv[8] = { ++ 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, ++ 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL ++}; ++ ++static const uint8_t blake2s_sigma[10][16] = { ++ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, ++ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, ++ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, ++ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, ++ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, ++ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, ++ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, ++ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, ++ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, ++ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, ++}; ++ ++static void blake2s_set_lastblock(struct blake2s_state *state) ++{ ++ state->f[0] = -1; ++} ++ ++static void blake2s_increment_counter(struct blake2s_state *state, const uint32_t inc) ++{ ++ state->t[0] += inc; ++ state->t[1] += (state->t[0] < inc); ++} ++ ++static void blake2s_init_param(struct blake2s_state *state, const uint32_t param) ++{ ++ int i; ++ ++ memset(state, 0, sizeof(*state)); ++ for (i = 0; i < 8; ++i) ++ state->h[i] = blake2s_iv[i]; ++ state->h[0] ^= param; ++} ++ ++static void blake2s_init(struct blake2s_state *state, const size_t outlen) ++{ ++ blake2s_init_param(state, 0x01010000 | outlen); ++ state->outlen = outlen; ++} ++ ++static void blake2s_compress(struct blake2s_state *state, const uint8_t *block, size_t nblocks, const uint32_t inc) ++{ ++ uint32_t m[16]; ++ uint32_t v[16]; ++ int i; ++ ++ while (nblocks > 0) { ++ blake2s_increment_counter(state, inc); ++ memcpy(m, block, BLAKE2S_BLOCK_LEN); ++ le32_to_cpu_array(m, ARRAY_SIZE(m)); ++ memcpy(v, state->h, 32); ++ v[ 8] = blake2s_iv[0]; ++ v[ 9] = blake2s_iv[1]; ++ v[10] = blake2s_iv[2]; ++ v[11] = blake2s_iv[3]; ++ v[12] = blake2s_iv[4] ^ state->t[0]; ++ v[13] = blake2s_iv[5] ^ state->t[1]; ++ v[14] = blake2s_iv[6] ^ state->f[0]; ++ v[15] = blake2s_iv[7] ^ state->f[1]; ++ ++#define G(r, i, a, b, c, d) do { \ ++ a += b + m[blake2s_sigma[r][2 * i + 0]]; \ ++ d = ror32(d ^ a, 16); \ ++ c += d; \ ++ b = ror32(b ^ c, 12); \ ++ a += b + m[blake2s_sigma[r][2 * i + 1]]; \ ++ d = ror32(d ^ a, 8); \ ++ c += d; \ ++ b = ror32(b ^ c, 7); \ ++} while (0) ++ ++#define ROUND(r) do { \ ++ G(r, 0, v[0], v[ 4], v[ 8], v[12]); \ ++ G(r, 1, v[1], v[ 5], v[ 9], v[13]); \ ++ G(r, 2, v[2], v[ 6], v[10], v[14]); \ ++ G(r, 3, v[3], v[ 7], v[11], v[15]); \ ++ G(r, 4, v[0], v[ 5], v[10], v[15]); \ ++ G(r, 5, v[1], v[ 6], v[11], v[12]); \ ++ G(r, 6, v[2], v[ 7], v[ 8], v[13]); \ ++ G(r, 7, v[3], v[ 4], v[ 9], v[14]); \ ++} while (0) ++ ROUND(0); ++ ROUND(1); ++ ROUND(2); ++ ROUND(3); ++ ROUND(4); ++ ROUND(5); ++ ROUND(6); ++ ROUND(7); ++ ROUND(8); ++ ROUND(9); ++ ++#undef G ++#undef ROUND ++ ++ for (i = 0; i < 8; ++i) ++ state->h[i] ^= v[i] ^ v[i + 8]; ++ ++ block += BLAKE2S_BLOCK_LEN; ++ --nblocks; ++ } ++} ++ ++static void blake2s_update(struct blake2s_state *state, const void *inp, size_t inlen) ++{ ++ const size_t fill = BLAKE2S_BLOCK_LEN - state->buflen; ++ const uint8_t *in = inp; ++ ++ if (!inlen) ++ return; ++ if (inlen > fill) { ++ memcpy(state->buf + state->buflen, in, fill); ++ blake2s_compress(state, state->buf, 1, BLAKE2S_BLOCK_LEN); ++ state->buflen = 0; ++ in += fill; ++ inlen -= fill; ++ } ++ if (inlen > BLAKE2S_BLOCK_LEN) { ++ const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_LEN); ++ blake2s_compress(state, in, nblocks - 1, BLAKE2S_BLOCK_LEN); ++ in += BLAKE2S_BLOCK_LEN * (nblocks - 1); ++ inlen -= BLAKE2S_BLOCK_LEN * (nblocks - 1); ++ } ++ memcpy(state->buf + state->buflen, in, inlen); ++ state->buflen += inlen; ++} ++ ++static void blake2s_final(struct blake2s_state *state, uint8_t *out) ++{ ++ blake2s_set_lastblock(state); ++ memset(state->buf + state->buflen, 0, BLAKE2S_BLOCK_LEN - state->buflen); ++ blake2s_compress(state, state->buf, 1, state->buflen); ++ cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); ++ memcpy(out, state->h, state->outlen); ++} ++ ++static size_t determine_optimal_seed_len(void) ++{ ++ size_t ret = 0; ++ char poolsize_str[11] = { 0 }; ++ int fd = open("/proc/sys/kernel/random/poolsize", O_RDONLY); ++ ++ if (fd < 0 || read(fd, poolsize_str, sizeof(poolsize_str) - 1) < 0) { ++ ewarn("Unable to determine pool size, falling back to %u bits: %s", MIN_SEED_LEN * 8, strerror(errno)); ++ ret = MIN_SEED_LEN; ++ } else ++ ret = DIV_ROUND_UP(strtoul(poolsize_str, NULL, 10), 8); ++ if (fd >= 0) ++ close(fd); ++ if (ret < MIN_SEED_LEN) ++ ret = MIN_SEED_LEN; ++ else if (ret > MAX_SEED_LEN) ++ ret = MAX_SEED_LEN; ++ return ret; ++} ++ ++static int read_new_seed(uint8_t *seed, size_t len, bool *is_creditable) ++{ ++ ssize_t ret; ++ int urandom_fd; ++ ++ *is_creditable = false; ++ ret = getrandom(seed, len, GRND_NONBLOCK); ++ if (ret == (ssize_t)len) { ++ *is_creditable = true; ++ return 0; ++ } ++ if (ret == -1 && errno == ENOSYS) { ++ struct pollfd random_fd = { ++ .fd = open("/dev/random", O_RDONLY), ++ .events = POLLIN ++ }; ++ if (random_fd.fd < 0) ++ return -errno; ++ *is_creditable = poll(&random_fd, 1, 0) == 1; ++ close(random_fd.fd); ++ } else if (getrandom(seed, len, GRND_INSECURE) == (ssize_t)len) ++ return 0; ++ urandom_fd = open("/dev/urandom", O_RDONLY); ++ if (urandom_fd < 0) ++ return -errno; ++ ret = read(urandom_fd, seed, len); ++ if (ret == (ssize_t)len) ++ ret = 0; ++ else ++ ret = -errno ? -errno : -EIO; ++ close(urandom_fd); ++ return ret; ++} ++ ++static int seed_rng(uint8_t *seed, size_t len, bool credit) ++{ ++ struct { ++ int entropy_count; ++ int buf_size; ++ uint8_t buffer[MAX_SEED_LEN]; ++ } req = { ++ .entropy_count = credit ? len * 8 : 0, ++ .buf_size = len ++ }; ++ int random_fd, ret; ++ ++ if (len > sizeof(req.buffer)) ++ return -EFBIG; ++ memcpy(req.buffer, seed, len); ++ ++ random_fd = open("/dev/random", O_RDWR); ++ if (random_fd < 0) ++ return -errno; ++ ret = ioctl(random_fd, RNDADDENTROPY, &req); ++ if (ret) ++ ret = -errno ? -errno : -EIO; ++ close(random_fd); ++ return ret; ++} ++ ++static int seed_from_file_if_exists(const char *filename, bool credit, struct blake2s_state *hash) ++{ ++ uint8_t seed[MAX_SEED_LEN]; ++ ssize_t seed_len; ++ int fd, dfd, ret = 0; ++ ++ fd = open(filename, O_RDONLY); ++ if (fd < 0 && errno == ENOENT) ++ return 0; ++ else if (fd < 0) { ++ ret = -errno; ++ eerror("Unable to open seed file: %s", strerror(errno)); ++ return ret; ++ } ++ dfd = open(SEED_DIR, O_DIRECTORY | O_RDONLY); ++ if (dfd < 0) { ++ ret = -errno; ++ close(fd); ++ eerror("Unable to open seed directory: %s", strerror(errno)); ++ return ret; ++ } ++ seed_len = read(fd, seed, sizeof(seed)); ++ if (seed_len < 0) { ++ ret = -errno; ++ eerror("Unable to read seed file: %s", strerror(errno)); ++ } ++ close(fd); ++ if (ret) { ++ close(dfd); ++ return ret; ++ } ++ if ((unlink(filename) < 0 || fsync(dfd) < 0) && seed_len) { ++ ret = -errno; ++ eerror("Unable to remove seed after reading, so not seeding: %s", strerror(errno)); ++ } ++ close(dfd); ++ if (ret) ++ return ret; ++ if (!seed_len) ++ return 0; ++ ++ blake2s_update(hash, &seed_len, sizeof(seed_len)); ++ blake2s_update(hash, seed, seed_len); ++ ++ einfo("Seeding %zd bits %s crediting", seed_len * 8, credit ? "and" : "without"); ++ ret = seed_rng(seed, seed_len, credit); ++ if (ret < 0) ++ eerror("Unable to seed: %s", strerror(-ret)); ++ return ret; ++} ++ ++static void populate_global_paths(void) ++{ ++ SEED_DIR = getenv("SEEDRNG_SEED_DIR"); ++ if (!SEED_DIR || !*SEED_DIR) ++ SEED_DIR = "/var/lib/seedrng"; ++ LOCK_FILE = getenv("SEEDRNG_LOCK_FILE"); ++ if (!LOCK_FILE || !*LOCK_FILE) ++ LOCK_FILE = "/var/run/seedrng.lock"; ++ xasprintf(&CREDITABLE_SEED, "%s/seed.credit", SEED_DIR); ++ xasprintf(&NON_CREDITABLE_SEED, "%s/seed.no-credit", SEED_DIR); ++} ++ ++int main(int argc _unused, char *argv[] _unused) ++{ ++ static const char seedrng_prefix[] = "SeedRNG v1 Old+New Prefix"; ++ static const char seedrng_failure[] = "SeedRNG v1 No New Seed Failure"; ++ int ret, fd, lock, program_ret = 0; ++ uint8_t new_seed[MAX_SEED_LEN]; ++ size_t new_seed_len; ++ bool new_seed_creditable; ++ struct timespec realtime = { 0 }, boottime = { 0 }; ++ struct blake2s_state hash; ++ ++ umask(0077); ++ if (getuid()) ++ eerrorx("This rc helper program requires root"); ++ ++ populate_global_paths(); ++ blake2s_init(&hash, BLAKE2S_HASH_LEN); ++ blake2s_update(&hash, seedrng_prefix, strlen(seedrng_prefix)); ++ clock_gettime(CLOCK_REALTIME, &realtime); ++ clock_gettime(CLOCK_BOOTTIME, &boottime); ++ blake2s_update(&hash, &realtime, sizeof(realtime)); ++ blake2s_update(&hash, &boottime, sizeof(boottime)); ++ ++ if (mkdir(SEED_DIR, 0700) < 0 && errno != EEXIST) ++ eerrorx("Unable to create \"%s\" directory: %s", SEED_DIR, strerror(errno)); ++ ++ lock = open(LOCK_FILE, O_WRONLY | O_CREAT, 0000); ++ if (lock < 0 || flock(lock, LOCK_EX) < 0) ++ eerrorx("Unable to open lock file: %s", strerror(errno)); ++ ++ ret = seed_from_file_if_exists(NON_CREDITABLE_SEED, false, &hash); ++ if (ret < 0) ++ program_ret |= 1 << 1; ++ ret = seed_from_file_if_exists(CREDITABLE_SEED, !rc_yesno(getenv("SEEDRNG_SKIP_CREDIT")), &hash); ++ if (ret < 0) ++ program_ret |= 1 << 2; ++ ++ new_seed_len = determine_optimal_seed_len(); ++ ret = read_new_seed(new_seed, new_seed_len, &new_seed_creditable); ++ if (ret < 0) { ++ eerror("Unable to read new seed: %s", strerror(-ret)); ++ new_seed_len = BLAKE2S_HASH_LEN; ++ strncpy((char *)new_seed, seedrng_failure, new_seed_len); ++ program_ret |= 1 << 3; ++ } ++ blake2s_update(&hash, &new_seed_len, sizeof(new_seed_len)); ++ blake2s_update(&hash, new_seed, new_seed_len); ++ blake2s_final(&hash, new_seed + new_seed_len - BLAKE2S_HASH_LEN); ++ ++ einfo("Saving %zu bits of %s seed for next boot", new_seed_len * 8, new_seed_creditable ? "creditable" : "non-creditable"); ++ fd = open(NON_CREDITABLE_SEED, O_WRONLY | O_CREAT | O_TRUNC, 0400); ++ if (fd < 0) { ++ eerror("Unable to open seed file for writing: %s", strerror(errno)); ++ program_ret |= 1 << 4; ++ goto out; ++ } ++ if (write(fd, new_seed, new_seed_len) != (ssize_t)new_seed_len || fsync(fd) < 0) { ++ eerror("Unable to write seed file: %s", strerror(errno)); ++ program_ret |= 1 << 5; ++ goto out; ++ } ++ if (new_seed_creditable && rename(NON_CREDITABLE_SEED, CREDITABLE_SEED) < 0) { ++ ewarn("Unable to make new seed creditable: %s", strerror(errno)); ++ program_ret |= 1 << 6; ++ } ++out: ++ close(fd); ++ close(lock); ++ return program_ret; ++} diff --git a/main/openssl/APKBUILD b/main/openssl/APKBUILD index da22526bd3b..6a0fe12a128 100644 --- a/main/openssl/APKBUILD +++ b/main/openssl/APKBUILD @@ -1,6 +1,6 @@ # Maintainer: Timo Teras <timo.teras@iki.fi> pkgname=openssl -pkgver=1.1.1l +pkgver=1.1.1o _abiver=${pkgver%.*} pkgrel=0 pkgdesc="Toolkit for Transport Layer Security (TLS)" @@ -18,6 +18,8 @@ source="https://www.openssl.org/source/openssl-$pkgver.tar.gz " # secfixes: +# 1.1.1n-r0: +# - CVE-2022-0778 # 1.1.1l-r0: # - CVE-2021-3711 # - CVE-2021-3712 @@ -43,6 +45,8 @@ source="https://www.openssl.org/source/openssl-$pkgver.tar.gz # 1.1.1a-r0: # - CVE-2018-0734 # - CVE-2018-0735 +# 0: +# - CVE-2022-1292 build() { local _target _optflags @@ -123,6 +127,6 @@ _libssl() { } sha512sums=" -d9611f393e37577cca05004531388d3e0ebbf714894cab9f95f4903909cd4f45c214faab664c0cbc3ad3cca309d500b9e6d0ecbf9a0a0588d1677dc6b047f9e0 openssl-1.1.1l.tar.gz +75b2f1499cb4640229eb6cd35d85cbff2e19db17b959ac4d04b60f1b395b73567f9003521452a0fcfeea9b31b26de0a7bccf476ecf9caae02298f3647cfb7e23 openssl-1.1.1o.tar.gz 43c3255118db6f5f340dc865c0f25ccbcafe5bf7507585244ca59b4d27daf533d6c3171aa32a8685cbb6200104bec535894b633de13feaadff87ab86739a445a man-section.patch " diff --git a/main/openvpn/APKBUILD b/main/openvpn/APKBUILD index bdacba533b5..ba0e7fde079 100644 --- a/main/openvpn/APKBUILD +++ b/main/openvpn/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Valery Kartel <valery.kartel@gmail.com> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=openvpn -pkgver=2.4.11 +pkgver=2.4.12 pkgrel=0 pkgdesc="A robust, and highly configurable VPN (Virtual Private Network)" url="https://openvpn.net/" @@ -19,6 +19,8 @@ source="https://swupdate.openvpn.net/community/releases/openvpn-$pkgver.tar.xz " # secfixes: +# 2.4.12-r0: +# - CVE-2022-0547 # 2.4.11-r0: # - CVE-2020-15078 # 2.4.9-r0: @@ -69,8 +71,10 @@ pam() { "$subpkgdir"/usr/lib/openvpn/plugins/ } -sha512sums="aeeefd32e71b0595a577bfbf5871c78c633efa863584a57b7a47fc825fdac35c2aa1fb7decbd0269ec5be35e3fc2a42cf2a1e7d9a8547aaff4e1481a247bc5da openvpn-2.4.11.tar.xz +sha512sums=" +4c8418c869a7cdce880d3c08e825dfccbced2694f0604532476598d2ab0299f1bbb77d91b2212394e08507cfe97f661ec45bdcd8e314b0ad0715106ed5664ba3 openvpn-2.4.12.tar.xz 111a1ce79bdb41b8a03c0d43f1fd87de8a0d5592a8b1bd878113af79adce3d0a3109badd92b5af9a0f80b6585473a1e01638f7e78e6baa8aac439f0708bc2a72 openvpn.initd 1f14d4bd7a4a026c276af048ce647501c15358c6b0d184e95c49be5b8184188c8edafb76ed94835cdbb314187ee3b5b3ccd852e3a47add0599814c402309bece openvpn.confd cdb73c9a5b1eb56e9cbd29955d94297ce5a87079419cd626d6a0b6680d88cbf310735a53f794886df02030b687eaea553c7c569a8ea1282a149441add1c65760 openvpn.up -4456880d5c2db061219ba94e4052786700efa5e685f03b0d12d75a6023e3c0fc7b5242cc3d2bd3988e42fcd99701ab13a6257b1a0943b812318d30c64843ad27 openvpn.down" +4456880d5c2db061219ba94e4052786700efa5e685f03b0d12d75a6023e3c0fc7b5242cc3d2bd3988e42fcd99701ab13a6257b1a0943b812318d30c64843ad27 openvpn.down +" diff --git a/main/postfix/APKBUILD b/main/postfix/APKBUILD index 277722a3794..01a3b7ed0b1 100644 --- a/main/postfix/APKBUILD +++ b/main/postfix/APKBUILD @@ -2,7 +2,7 @@ # Contributor: Łukasz Jendrysik <scadu@yandex.com> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=postfix -pkgver=3.5.12 +pkgver=3.5.16 pkgrel=0 pkgdesc="Secure and fast drop-in replacement for Sendmail (MTA)" url="http://www.postfix.org/" @@ -191,7 +191,7 @@ stone() { } sha512sums=" -8f545e79031689b41122cd8ea87512968bcdc8e06ef836a648a9eb8f2e664009c84ba42f14294b5b215d4efd5a2138acb4d0b0f97552eff45dadafcea518cda6 postfix-3.5.12.tar.gz +81e482b2474df0fb711c86e83c585669b3934d3de1c74fc1bc0bef216225a91809fe802b53e9134bad6916d3dd889267b89dd83f78876f361f18a3192b07cefc postfix-3.5.16.tar.gz 2752e69c4e1857bdcf29444ffb458bca818bc60b9c77c20823c5f5b87c36cb5e0f3217a625a7fe5788d5bfcef7570a1f2149e1233fcd23ccf7ee14190aff47a2 postfix.initd 25cd34f23ca909d4e33aaf3239d1e397260abc7796d9a4456dee4f005682fd3a58aab8106126e5218c95bdddae415a3ef7e2223cd3b0d7b1e2bd76158bb7eaf8 postfix-install.patch " diff --git a/main/postgresql/APKBUILD b/main/postgresql/APKBUILD index 1cbd6b7db4b..dda8fb04805 100644 --- a/main/postgresql/APKBUILD +++ b/main/postgresql/APKBUILD @@ -2,7 +2,7 @@ # Contributor: G.J.R. Timmer <gjr.timmer@gmail.com> # Contributor: Jakub Jirutka <jakub@jirutka.cz> pkgname=postgresql -pkgver=12.8 +pkgver=12.10 pkgrel=0 pkgdesc="A sophisticated object-relational DBMS" url="https://www.postgresql.org/" @@ -33,6 +33,9 @@ source="https://ftp.postgresql.org/pub/source/v$pkgver/postgresql-$pkgver.tar.bz " # secfixes: +# 12.9-r0: +# - CVE-2021-23214 +# - CVE-2021-23222 # 12.8-r0: # - CVE-2021-3677 # 12.7-r0: @@ -269,7 +272,7 @@ _run_tests() { } sha512sums=" -970fe1041e427ac1c8a786c93e2079b0a9c8b3fcaf9d38877894eb02e8a9afc7cd73d7ac28078c455845a922a1b7d9c1e22cb7990d8d523dd6496af9442fba01 postgresql-12.8.tar.bz2 +befedb14320aa033dc55bbb93bbbec4e67d9cfced63be0e4f631c7495a0fbc6fe280bd6d2fb941d7a2e6b2ac570b7f40d8db7f07a192a81bd9cd63c6c244a9c5 postgresql-12.10.tar.bz2 1f8e7dc58f5b0a12427cf2fd904ffa898a34f23f3332c8382b94e0d991c007289e7913a69e04498f3d93fc5701855796c207b4b1cc4a0b366f586050124d7fcc initdb.patch 5f9d8bb4957194069d01af8ab3abc6d4d83a7e7f8bd7ebe1caae5361d621a3e58f91b14b952958138a794e0a80bc154fbb7e3e78d211e2a95b9b7901335de854 perl-rpath.patch 8439a6fdfdea0a4867daeb8bc23d6c825f30c00d91d4c39f48653f5ee77341f23282ce03a77aad94b5369700f11d2cb28d5aee360e59138352a9ab331a9f9d0f conf-unix_socket_directories.patch diff --git a/main/privoxy/APKBUILD b/main/privoxy/APKBUILD index c896a5fd6b7..e19fa387da6 100644 --- a/main/privoxy/APKBUILD +++ b/main/privoxy/APKBUILD @@ -1,9 +1,9 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=privoxy -pkgver=3.0.32 +pkgver=3.0.33 pkgrel=0 pkgdesc="A web proxy with advanced filtering capabilities" -url="https://www.privoxy.org" +url="https://www.privoxy.org/" arch="all" license="GPL" pkgusers="privoxy" @@ -20,6 +20,11 @@ options="!check" # No test suite builddir="$srcdir/$pkgname-$pkgver-stable" # secfixes: +# 3.0.33-r0: +# - CVE-2021-44540 +# - CVE-2021-44541 +# - CVE-2021-44542 +# - CVE-2021-44543 # 3.0.32-r0: # - CVE-2021-20272 # - CVE-2021-20273 @@ -40,7 +45,6 @@ builddir="$srcdir/$pkgname-$pkgver-stable" prepare() { cd "$builddir" - update_config_sub default_prepare aclocal && autoheader && autoconf @@ -81,7 +85,9 @@ package() { "$pkgdir"/etc/privoxy } -sha512sums="da41c0045bf593219df64718645eff984b5df43737811cc0fa12fce7e8ae1ab59eefbe20f23d6ce8f62216cfd81f1a9c319688d15693c25eed36010f3e1d5ffd privoxy-3.0.32-stable-src.tar.gz +sha512sums=" +9684455dbce7f6d8f5defd31aa9a7316e0c1dc896525ab4d562d0359462b541b1c366dea9db07b798f3e00b9cbcc44f494d8c431bcb10f2cb05b5bca3cfeaf75 privoxy-3.0.33-stable-src.tar.gz 346bda3a2108547569af3397c77e092c54fa0c20bc6d3bb1d4c202b4e2b8d9c13018eab0a326cd9632310ec8052600ee7db4b6011610faec386c399cdd01af9c privoxy.initd 118caaeac3aba751584c5bdfc737bf5bfeddf1a62fda1f44bcd4654ae2e33183bc1ce6fc66d4a1bdd79766e42e669b1615a6d46d528a1bd49cabdf98385a3bb9 privoxy.logrotate -1059feed20a31d7d2b5d1f44b7b1af40373d87dbd9e7e83c8998ac1b4e27dfbfdfeb6a9ea7934e15d0c14fed1fd03fb63d2ec8d2a6b53e5884a21dc8df4828fc privoxy-alpine.patch" +1059feed20a31d7d2b5d1f44b7b1af40373d87dbd9e7e83c8998ac1b4e27dfbfdfeb6a9ea7934e15d0c14fed1fd03fb63d2ec8d2a6b53e5884a21dc8df4828fc privoxy-alpine.patch +" diff --git a/main/py3-pillow/APKBUILD b/main/py3-pillow/APKBUILD index e5874205bcc..a9b988728e6 100644 --- a/main/py3-pillow/APKBUILD +++ b/main/py3-pillow/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Fabian Affolter <fabian@affolter-engineering.ch> pkgname=py3-pillow pkgver=7.1.2 -pkgrel=1 +pkgrel=2 pkgdesc="Python Imaging Library" options="!check" url="https://python-pillow.org/" @@ -15,6 +15,7 @@ makedepends="python3-dev py3-setuptools freetype-dev checkdepends="py3-pytest py3-numpy" source="https://files.pythonhosted.org/packages/source/P/Pillow/Pillow-$pkgver.tar.gz CVE-2020-35655.patch + cve-2021-23437.patch " builddir="$srcdir/Pillow-$pkgver" @@ -22,6 +23,8 @@ provides="py-pillow=$pkgver-r$pkgrel" # backwards compatibility replaces="py-pillow" # backwards compatiblity # secfixes: +# 7.1.2-r2: +# - CVE-2021-23437 # 7.1.2-r1: # - CVE-2020-35655 # 6.2.2-r0: @@ -46,5 +49,8 @@ package() { python3 setup.py install --prefix=/usr --root="$pkgdir" } -sha512sums="75d88c5c967d600b84caf9af62eeda6f235fb1357ba7ca47656be6d48018f2df6f2442df2d2ea50d4cc0955f55dce05c2e2676f9b4bca5aa72bfda61e407dd97 Pillow-7.1.2.tar.gz -89984ca666bafc356ba8af50a3f96dc84965b882577f488c10550558a316982c52378bf52ec24b5ed53a4f8b1019e9e5e03bbff6e32c4009ea8ef71093f33f18 CVE-2020-35655.patch" +sha512sums=" +75d88c5c967d600b84caf9af62eeda6f235fb1357ba7ca47656be6d48018f2df6f2442df2d2ea50d4cc0955f55dce05c2e2676f9b4bca5aa72bfda61e407dd97 Pillow-7.1.2.tar.gz +89984ca666bafc356ba8af50a3f96dc84965b882577f488c10550558a316982c52378bf52ec24b5ed53a4f8b1019e9e5e03bbff6e32c4009ea8ef71093f33f18 CVE-2020-35655.patch +0c991bf55bd2b73e1f5539f8c2110c47ef48029ff1a91710384d1612903850b1bbedeacef90359e738a02faacffd2e3a1d48d14a800681cd04f0f98c453b609b cve-2021-23437.patch +" diff --git a/main/py3-pillow/cve-2021-23437.patch b/main/py3-pillow/cve-2021-23437.patch new file mode 100644 index 00000000000..9933ed8ceda --- /dev/null +++ b/main/py3-pillow/cve-2021-23437.patch @@ -0,0 +1,40 @@ +From 1dc6564eb7ee8f28fb16eeffaf3572f3e1d5aa29 Mon Sep 17 00:00:00 2001 +From: Hugo van Kemenade <hugovk@users.noreply.github.com> +Date: Mon, 23 Aug 2021 19:10:49 +0300 +Subject: [PATCH] Raise ValueError if color specifier is too long + +--- + Tests/test_imagecolor.py | 9 +++++++++ + src/PIL/ImageColor.py | 2 ++ + 2 files changed, 11 insertions(+) + +diff --git a/Tests/test_imagecolor.py b/Tests/test_imagecolor.py +index b5d69379655..dbe8b9e957b 100644 +--- a/Tests/test_imagecolor.py ++++ b/Tests/test_imagecolor.py +@@ -191,3 +191,12 @@ def test_rounding_errors(): + assert (255, 255) == ImageColor.getcolor("white", "LA") + assert (163, 33) == ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA") + Image.new("LA", (1, 1), "white") ++ ++ ++def test_color_too_long(): ++ # Arrange ++ color_too_long = "hsl(" + "1" * 100 + ")" ++ ++ # Act / Assert ++ with pytest.raises(ValueError): ++ ImageColor.getrgb(color_too_long) +diff --git a/src/PIL/ImageColor.py b/src/PIL/ImageColor.py +index 51df4404039..25f92f2c732 100644 +--- a/src/PIL/ImageColor.py ++++ b/src/PIL/ImageColor.py +@@ -32,6 +32,8 @@ def getrgb(color): + :param color: A color string + :return: ``(red, green, blue[, alpha])`` + """ ++ if len(color) > 100: ++ raise ValueError("color specifier is too long") + color = color.lower() + + rgb = colormap.get(color, None) diff --git a/main/rdiff-backup/APKBUILD b/main/rdiff-backup/APKBUILD index 735b48c32d6..40825ebf81e 100644 --- a/main/rdiff-backup/APKBUILD +++ b/main/rdiff-backup/APKBUILD @@ -2,12 +2,13 @@ # Maintainer: Jeremy Thomerson <jeremy@thomersonfamily.com> pkgname=rdiff-backup pkgver=2.0.3 -pkgrel=0 +pkgrel=1 pkgdesc="Reverse differential backup tool" options="!check" # Requires unpacakged 'xattr' url="https://rdiff-backup.net/" arch="all" license="GPL-2.0-or-later" +depends="python3" makedepends="librsync-dev python3-dev py3-setuptools" subpackages=" $pkgname-doc diff --git a/main/rsyslog/APKBUILD b/main/rsyslog/APKBUILD index 5f8368b8647..4cdca6b5b57 100644 --- a/main/rsyslog/APKBUILD +++ b/main/rsyslog/APKBUILD @@ -6,7 +6,7 @@ # Maintainer: Cameron Banta <cbanta@gmail.com> pkgname=rsyslog pkgver=8.2004.0 -pkgrel=0 +pkgrel=2 pkgdesc="Enhanced multi-threaded syslogd with database support and more." url="https://www.rsyslog.com/" arch="all !s390x" # limited by czmq @@ -49,6 +49,7 @@ source="$pkgname-$pkgver.tar.gz::https://github.com/rsyslog/rsyslog/archive/v$pk $pkgname.conf musl-fix.patch queue.patch + CVE-2022-24903.patch " # <subpackage>[:<module>...] @@ -92,6 +93,8 @@ for _i in $_plugins; do done # secfixes: +# 8.2004.0-r2: +# - CVE-2022-24903 # 8.1908.0-r1: # - CVE-2019-17040 # - CVE-2019-17041 @@ -187,9 +190,12 @@ _plugin() { done } -sha512sums="ade8a7beef641cba701341c12b7fd48f02cf8cdc083b290f965914f1f7f2c73f9866f8f1f1aa26a349c30cc06ffc3780bee9e0319acde9588dc583dfdf182207 rsyslog-8.2004.0.tar.gz +sha512sums=" +ade8a7beef641cba701341c12b7fd48f02cf8cdc083b290f965914f1f7f2c73f9866f8f1f1aa26a349c30cc06ffc3780bee9e0319acde9588dc583dfdf182207 rsyslog-8.2004.0.tar.gz bcd63c8df2ac63b80f3cb51ba7f544988df6cd875f4e81020e762dff30d7537f21b72c95a4b1c08baf15f4ed5f03defbf3f061673aabada5841f45ab9f579374 rsyslog.initd -198ad8f617b9edb93c9231118a9b3bb80b1e00e6517d2a79c393cbfef4417b8f0d08f231fb33843f8e9b09c7f9bc69dd501057ffe9eef583108af34996fee59d rsyslog.logrotate +6bf69f14746d0523a4e9189593bc62e14a6e05c7e17922e4398df4b951abdde165e826290f6b6cdc8149199288f555d098178d93d2fae202463ebc523626161b rsyslog.logrotate 517e3c9fced414d397ce946eed50534ea821cd1a7aee2e873d5ffa4c4df3b4433b4f2a2e063825641ce6aaeddd5bd1fd2508ad34099fe30d0d3d615d25121f67 rsyslog.conf 15745c8cdb730ae548d038ca4c04f9f48ef55c6e04949a8e86df356877563c0fcb9660445e47d3f9530925092d6dd80b2b2fc3f64a114ee85103d137327524cb musl-fix.patch -ef2e000b1c42cb5beffb26393952c2a692791e78972ee4b6f187ca53e338122b2004cc5216381c042195f12cc58f37f186a04e12a65b5bdfdcdf76b73393efb7 queue.patch" +ef2e000b1c42cb5beffb26393952c2a692791e78972ee4b6f187ca53e338122b2004cc5216381c042195f12cc58f37f186a04e12a65b5bdfdcdf76b73393efb7 queue.patch +42448f12a88c8c845001d903da70533b302bdf34097aa6bb7b69162df2e95ea2b3c0f89331ba374cab5a1178b99315b6f73418f18028b2c5cfefcc026147608d CVE-2022-24903.patch +" diff --git a/main/rsyslog/CVE-2022-24903.patch b/main/rsyslog/CVE-2022-24903.patch new file mode 100644 index 00000000000..2a8f1b6ce56 --- /dev/null +++ b/main/rsyslog/CVE-2022-24903.patch @@ -0,0 +1,42 @@ +Patch-Source: https://github.com/rsyslog/rsyslog/commit/89955b0bcb1ff105e1374aad7e0e993faa6a038f +From 89955b0bcb1ff105e1374aad7e0e993faa6a038f Mon Sep 17 00:00:00 2001 +From: Rainer Gerhards <rgerhards@adiscon.com> +Date: Fri, 22 Apr 2022 09:49:46 +0200 +Subject: [PATCH] net bugfix: potential buffer overrun + +--- + contrib/imhttp/imhttp.c | 4 +++- + plugins/imptcp/imptcp.c | 4 +++- + runtime/tcps_sess.c | 4 +++- + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c +index 2df46a236c..c32dec5851 100644 +--- a/plugins/imptcp/imptcp.c ++++ b/plugins/imptcp/imptcp.c +@@ -1107,7 +1107,9 @@ processDataRcvd(ptcpsess_t *const __restrict__ pThis, + if(pThis->iOctetsRemain <= 200000000) { + pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0'; + } +- *(pThis->pMsg + pThis->iMsg++) = c; ++ if(pThis->iMsg < iMaxLine) { ++ *(pThis->pMsg + pThis->iMsg++) = c; ++ } + } else { /* done with the octet count, so this must be the SP terminator */ + DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain); + prop.GetString(pThis->peerName, &propPeerName, &lenPeerName); +diff --git a/runtime/tcps_sess.c b/runtime/tcps_sess.c +index 0efa2c23c4..c5442f7638 100644 +--- a/runtime/tcps_sess.c ++++ b/runtime/tcps_sess.c +@@ -390,7 +390,9 @@ processDataRcvd(tcps_sess_t *pThis, + if(pThis->iOctetsRemain <= 200000000) { + pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0'; + } +- *(pThis->pMsg + pThis->iMsg++) = c; ++ if(pThis->iMsg < iMaxLine) { ++ *(pThis->pMsg + pThis->iMsg++) = c; ++ } + } else { /* done with the octet count, so this must be the SP terminator */ + DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain); + prop.GetString(pThis->fromHost, &propPeerName, &lenPeerName); diff --git a/main/rsyslog/rsyslog.logrotate b/main/rsyslog/rsyslog.logrotate index e2842b88dc0..8450db8e70c 100644 --- a/main/rsyslog/rsyslog.logrotate +++ b/main/rsyslog/rsyslog.logrotate @@ -1,3 +1,4 @@ +/var/log/messages /var/log/auth.log /var/log/cron.log /var/log/kern.log diff --git a/main/ruby/APKBUILD b/main/ruby/APKBUILD index 0b6ac7c9896..b8256f9cf5b 100644 --- a/main/ruby/APKBUILD +++ b/main/ruby/APKBUILD @@ -1,8 +1,15 @@ # Contributor: Carlo Landmeter <clandmeter@gmail.com> # Contributor: Jakub Jirutka <jakub@jirutka.cz> +# Contributor: Nulo <git@nulo.in> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> # # secfixes: +# 2.7.6-r0: +# - CVE-2022-28739 +# 2.7.5-r0: +# - CVE-2021-41817 +# - CVE-2021-41816 +# - CVE-2021-41819 # 2.7.4-r0: # - CVE-2021-31799 # - CVE-2021-31810 @@ -43,7 +50,7 @@ # - CVE-2017-17405 # pkgname=ruby -pkgver=2.7.4 +pkgver=2.7.6 _abiver="${pkgver%.*}.0" pkgrel=0 pkgdesc="An object-oriented language for quick and easy programming" @@ -378,7 +385,7 @@ _mvgem() { } sha512sums=" -a317752e9a32c8d1261e67ca89c396722ee779ec8ba4594987812d065b73751f51485a1ede8044aae14b3b16e8d049c6953cef530ae1b82abb135b446c653f8a ruby-2.7.4.tar.gz +94810bb204cec55b5bbec8d51a5f5cc696613d1812b152399441a5cc7e4eddd2b376bc85e16d8da0b12f1938d19bf0d056b49a028809c036fb5a446a65bffbee ruby-2.7.6.tar.gz cfdc5ea3b2e2ea69c51f38e8e2180cb1dc27008ca55cc6301f142ebafdbab31c3379b3b6bba9ff543153876dd98ed2ad194df3255b7ea77a62e931c935f80538 rubygems-avoid-platform-specific-gems.patch 814fe6359505b70d8ff680adf22f20a74b4dbd3fecc9a63a6c2456ee9824257815929917b6df5394ed069a6869511b8c6dce5b95b4acbbb7867c1f3a975a0150 test_insns-lower-recursion-depth.patch 8d730f02f76e53799f1c220eb23e3d2305940bb31216a7ab1e42d3256149c0721c7d173cdbfe505023b1af2f5cb3faa233dcc1b5d560fa8f980c17c2d29a9d81 fix-get_main_stack.patch diff --git a/main/snmptt/APKBUILD b/main/snmptt/APKBUILD index 5b9eeb924e6..b8b1326ce3e 100644 --- a/main/snmptt/APKBUILD +++ b/main/snmptt/APKBUILD @@ -1,7 +1,7 @@ # Contributor: Jeff Bilyk <jbilyk at gmail> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=snmptt -pkgver=1.4 +pkgver=1.4.2 pkgrel=0 pkgdesc="Translates traps received from snmptrapd into easy to understand messages" url="http://www.snmptt.org" @@ -17,6 +17,10 @@ source="https://downloads.sourceforge.net/$pkgname/${pkgname}_$pkgver.tgz snmptt.confd " +# secfixes: +# 1.4.2-r0: +# - CVE-2020-24361 + build() { return 0 } @@ -36,6 +40,6 @@ package() { install -D -m644 ../snmptt.confd "$pkgdir"/etc/conf.d/snmptt } -sha512sums="200ebe565766c15f85b9b9cbc178baeef740663efc951af4c790c4b28d27398c14a95c4b38306ec3503cefe9b86634d5f24ec5f2482694f07789e9025ea39a80 snmptt_1.4.tgz +sha512sums="b8782aa5789227253c1b65c98771de7eba319f1f29b56224415f89d0c687515cd099f0ba7d0e304d43a9d054fa66335fe09d99545f50415745ac86b8b56a2b9d snmptt_1.4.2.tgz 233e781150fdb217991e0d9eae4de1430e01f54c9ae7354a6ebef6676595c5497863a4ab2a829e67473c7a901c120b2dbb7aa51e67fd49fd7643ff9efca633f8 snmptt.initd 905f9c10b6daa43b112166c90d569c0737d569117c320a4a652ca22533195b559fe62628bf67bfc4df107db6af88a44ac4ffc58514c8dcc5bb45981240b90776 snmptt.confd" diff --git a/main/strongswan/APKBUILD b/main/strongswan/APKBUILD index 2ac8c184781..7143fb44172 100644 --- a/main/strongswan/APKBUILD +++ b/main/strongswan/APKBUILD @@ -3,7 +3,7 @@ pkgname=strongswan pkgver=5.8.4 _pkgver=${pkgver//_rc/rc} -pkgrel=2 +pkgrel=3 pkgdesc="IPsec-based VPN solution focused on security and ease of use, supporting IKEv1/IKEv2 and MOBIKE" url="https://www.strongswan.org/" arch="all" @@ -16,8 +16,11 @@ makedepends="linux-headers python3 sqlite-dev openssl-dev curl-dev install="$pkgname.pre-install" subpackages="$pkgname-doc $pkgname-dbg $pkgname-logfile $pkgname-openrc" source="https://download.strongswan.org/strongswan-$_pkgver.tar.bz2 + https://download.strongswan.org/security/CVE-2021-41990/strongswan-5.6.1-5.9.3_gmp-rsa-ssa-salt-len.patch + https://download.strongswan.org/security/CVE-2021-41991/strongswan-4.4.1-5.9.3_cert-cache-random.patch 0001-file-logger-Set-owner-group-of-log-file.patch 0205-ike-Adhere-to-IKE_SA-limit-when-checking-out-by-conf.patch + 1001-charon-add-optional-source-and-remote-overrides-for-.patch 1002-vici-send-certificates-for-ike-sa-events.patch 1003-vici-add-support-for-individual-sa-state-changes.patch @@ -29,6 +32,9 @@ source="https://download.strongswan.org/strongswan-$_pkgver.tar.bz2 " # secfixes: +# 5.8.4-r3: +# - CVE-2021-41990 +# - CVE-2021-41991 # 5.7.1-r0: # - CVE-2018-17540 # 5.7.0-r0: @@ -123,7 +129,10 @@ logfile() { install -m 2750 -o ipsec -g wheel -d "$subpkgdir/var/log/ipsec" } -sha512sums="15e866b0d6cc4ea94f17856b519d926ae08c15d3b62f675f62685d0722ca8fa26b46afb1ad1c866e9d5f347d77a747f57d0c6d7f6bd57762f37d7798f9e28103 strongswan-5.8.4.tar.bz2 +sha512sums=" +15e866b0d6cc4ea94f17856b519d926ae08c15d3b62f675f62685d0722ca8fa26b46afb1ad1c866e9d5f347d77a747f57d0c6d7f6bd57762f37d7798f9e28103 strongswan-5.8.4.tar.bz2 +42bb9dc02e04735183cb2966e23f26bdb2b14b56b10dc3df770cfbea066a690130ce84dc3a17b1369c2d45852bcd8a2902f19368099a1e71c858293decdb48ee strongswan-5.6.1-5.9.3_gmp-rsa-ssa-salt-len.patch +39f607625bc6aa128b71e65e9806c60051015378d0250961bafbe787aa652141e1b3126d235b9cede08e4fe816b3220dbae54e40492b0aeb48f034220f1ee446 strongswan-4.4.1-5.9.3_cert-cache-random.patch 7ea3cecb6ed1d730b4417699715ec1f02f592848a7736448187c3fff8df7c194983021c370019a63cc56ee3cfec881e13e950ac31ba49a5ecae75abab64dbcfc 0001-file-logger-Set-owner-group-of-log-file.patch c829b59d33f5dcffd86fbc81d824b51397ed48dc94da6271ec2d7d70e5975cff0c13d235147f92e1981b391857d5573507972593fed0ce831968da10d119da0f 0205-ike-Adhere-to-IKE_SA-limit-when-checking-out-by-conf.patch cdc8b9d56fbd7c079dfa37e8de822cfa925d3b6741ff7d04afbc8b856d717ed090750e85b19af2296e28ee030c2d91597d2492f4b9b3540a5647b120bf609556 1001-charon-add-optional-source-and-remote-overrides-for-.patch @@ -132,4 +141,5 @@ da39b5654c6f39d175c5491dabd5ed5c1b552857af7cbe7eeb8d0ecb34dad265bb8cd7725930eb75 8b61e3ffbb39b837733e602ec329e626dc519bf7308d3d4192b497d18f38176789d23ef5afec51f8463ee1ddaf4d74546b965c03184132e217cbc27017e886c9 strongswan.initd 4ac8dc83f08998fe672d5446dc6071f95a6a437b9df7c19d5f1a41707fb44451ec37aa237d0b86b0a9edf36a9ce7c29ba8959a38b04536c994dd4300daf737e5 charon.initd 0417de0c0aa779602b216f29b1ad58cc842f0b0fbb8f5238d39199125dac30eaae89d869b337f8f504f8427f074ee7a363f55e3b3875516fe1ed5f0ed7f34c6f charon.logrotate -5896a9c5ecbef1a6c36b7bd31c83e18603f49105aedd4af80c42b0036c75950eac6e92abccfca09c9cb5bb3f3c4010f0daba068208e7dff05e7b1849d5a6e363 charon-logfile.conf" +5896a9c5ecbef1a6c36b7bd31c83e18603f49105aedd4af80c42b0036c75950eac6e92abccfca09c9cb5bb3f3c4010f0daba068208e7dff05e7b1849d5a6e363 charon-logfile.conf +" diff --git a/main/tcpdump/APKBUILD b/main/tcpdump/APKBUILD index 4fde221f31b..3832bb72d8c 100644 --- a/main/tcpdump/APKBUILD +++ b/main/tcpdump/APKBUILD @@ -17,33 +17,33 @@ source="https://www.tcpdump.org/release/tcpdump-$pkgver.tar.gz # 4.9.3-r1: # - CVE-2020-8037 # 4.9.3-r0: -# - CVE-2017-16808 (AoE) -# - CVE-2018-14468 (FrameRelay) -# - CVE-2018-14469 (IKEv1) -# - CVE-2018-14470 (BABEL) -# - CVE-2018-14466 (AFS/RX) -# - CVE-2018-14461 (LDP) -# - CVE-2018-14462 (ICMP) -# - CVE-2018-14465 (RSVP) -# - CVE-2018-14881 (BGP) -# - CVE-2018-14464 (LMP) -# - CVE-2018-14463 (VRRP) -# - CVE-2018-14467 (BGP) -# - CVE-2018-10103 (SMB - partially fixed, but SMB printing disabled) -# - CVE-2018-10105 (SMB - too unreliably reproduced, SMB printing disabled) -# - CVE-2018-14880 (OSPF6) -# - CVE-2018-16451 (SMB) -# - CVE-2018-14882 (RPL) -# - CVE-2018-16227 (802.11) -# - CVE-2018-16229 (DCCP) -# - CVE-2018-16301 (was fixed in libpcap) -# - CVE-2018-16230 (BGP) -# - CVE-2018-16452 (SMB) -# - CVE-2018-16300 (BGP) -# - CVE-2018-16228 (HNCP) -# - CVE-2019-15166 (LMP) -# - CVE-2019-15167 (VRRP) -# - CVE-2018-14879 (tcpdump -V) +# - CVE-2017-16808 # (AoE) +# - CVE-2018-14468 # (FrameRelay) +# - CVE-2018-14469 # (IKEv1) +# - CVE-2018-14470 # (BABEL) +# - CVE-2018-14466 # (AFS/RX) +# - CVE-2018-14461 # (LDP) +# - CVE-2018-14462 # (ICMP) +# - CVE-2018-14465 # (RSVP) +# - CVE-2018-14881 # (BGP) +# - CVE-2018-14464 # (LMP) +# - CVE-2018-14463 # (VRRP) +# - CVE-2018-14467 # (BGP) +# - CVE-2018-10103 # (SMB - partially fixed, but SMB printing disabled) +# - CVE-2018-10105 # (SMB - too unreliably reproduced, SMB printing disabled) +# - CVE-2018-14880 # (OSPF6) +# - CVE-2018-16451 # (SMB) +# - CVE-2018-14882 # (RPL) +# - CVE-2018-16227 # (802.11) +# - CVE-2018-16229 # (DCCP) +# - CVE-2018-16301 # (was fixed in libpcap) +# - CVE-2018-16230 # (BGP) +# - CVE-2018-16452 # (SMB) +# - CVE-2018-16300 # (BGP) +# - CVE-2018-16228 # (HNCP) +# - CVE-2019-15166 # (LMP) +# - CVE-2019-15167 # (VRRP) +# - CVE-2018-14879 # (tcpdump -V) # 4.9.0-r0: # - CVE-2016-7922 # - CVE-2016-7923 diff --git a/main/tiny-cloud/APKBUILD b/main/tiny-cloud/APKBUILD new file mode 100644 index 00000000000..0de6134400b --- /dev/null +++ b/main/tiny-cloud/APKBUILD @@ -0,0 +1,65 @@ +# Contributor: Mike Crute <mike@crute.us> +# Contributor: Jake Buchholz Göktürk <tomalok@gmail.com> +# Maintainer: Jake Buchholz Göktürk <tomalok@gmail.com> +pkgname=tiny-cloud +pkgver=2.0.0 +pkgrel=0 +pkgdesc="Tiny Cloud instance bootstrapper" +url="https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud" +arch="noarch" +license="MIT" +options="!check" # no tests provided +depends="e2fsprogs-extra util-linux sfdisk" +source="$url/-/archive/$pkgver/$pkgname-$pkgver.tar.gz" +subpackages=" + $pkgname-network + $pkgname-openrc + $pkgname-aws + $pkgname-azure + $pkgname-gcp + $pkgname-oci +" + +package() { + make PREFIX="$pkgdir" core openrc +} + +network() { + pkgdesc="Tiny Cloud - networking module" + depends="ifupdown iproute2 $pkgname=$pkgver-r$pkgrel" + cd "$builddir" + make PREFIX="$subpkgdir" network +} + +aws() { + pkgdesc="Tiny Cloud - Amazon Web Services module" + depends="nvme-cli $pkgname-network=$pkgver-r$pkgrel" + provides="tiny-ec2-bootstrap" + cd "$builddir" + make PREFIX="$subpkgdir" aws +} + +azure() { + pkgdesc="Tiny Cloud - Azure module" + depends="$pkgname=$pkgver-r$pkgrel" + cd "$builddir" + make PREFIX="$subpkgdir" azure +} + +gcp() { + pkgdesc="Tiny Cloud - Google Cloud Platform module" + depends="$pkgname=$pkgver-r$pkgrel" + cd "$builddir" + make PREFIX="$subpkgdir" gcp +} + +oci() { + pkgdesc="Tiny Cloud - Oracle Cloud Infrastructure module" + depends="$pkgname=$pkgver-r$pkgrel" + cd "$builddir" + make PREFIX="$subpkgdir" oci +} + +sha512sums=" +d3c1eb1daf1d298f34459ab2b54c1077b3bc037bbe0df3591cade85ba9d351a47f9ce42fabe5480505236731795679a32f0144998de689f35139aa28ac490d48 tiny-cloud-2.0.0.tar.gz +" diff --git a/main/tiny-cloud/out b/main/tiny-cloud/out new file mode 100644 index 00000000000..52784f874e8 --- /dev/null +++ b/main/tiny-cloud/out @@ -0,0 +1,220 @@ +>>> tiny-cloud: Checking sanity of /home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/APKBUILD... +>>> tiny-cloud: Cleaning up srcdir +>>> tiny-cloud: Cleaning up pkgdir +>>> tiny-cloud: Fetching https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud/-/archive/2.0.0/tiny-cloud-2.0.0.tar.gz +>>> tiny-cloud: Fetching https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud/-/archive/2.0.0/tiny-cloud-2.0.0.tar.gz +>>> tiny-cloud: Checking sha512sums... +tiny-cloud-2.0.0.tar.gz: OK +>>> tiny-cloud: Preparing build chroot... +fetch http://dl-cdn.alpinelinux.org/alpine/edge/main/x86_64/APKINDEX.tar.gz +WARNING: Ignoring /home/tomalok/packages//main: No such file or directory +(1/91) Installing musl (1.2.2-r7) +(2/91) Installing fakeroot (1.25.3-r3) +(3/91) Installing scanelf (1.3.3-r0) +(4/91) Installing libcrypto1.1 (1.1.1m-r1) +(5/91) Installing libssl1.1 (1.1.1m-r1) +(6/91) Installing openssl (1.1.1m-r1) +(7/91) Installing ca-certificates-bundle (20211220-r0) +(8/91) Installing zlib (1.2.11-r3) +(9/91) Installing apk-tools (2.12.9-r1) +(10/91) Installing musl-utils (1.2.2-r7) +(11/91) Installing libc-utils (0.7.2-r3) +(12/91) Installing libattr (2.5.1-r1) +(13/91) Installing attr (2.5.1-r1) +(14/91) Installing libacl (2.2.53-r0) +(15/91) Installing tar (1.34-r0) +(16/91) Installing pkgconf (1.8.0-r0) +(17/91) Installing patch (2.7.6-r7) +(18/91) Installing libgcc (11.2.1_git20220117-r0) +(19/91) Installing libstdc++ (11.2.1_git20220117-r0) +(20/91) Installing lzip (1.22-r1) +(21/91) Installing busybox (1.35.0-r1) +Executing busybox-1.35.0-r1.post-install +(22/91) Installing libretls (3.4.2-r0) +(23/91) Installing ssl_client (1.35.0-r1) +(24/91) Installing ca-certificates (20211220-r0) +(25/91) Installing brotli-libs (1.0.9-r6) +(26/91) Installing nghttp2-libs (1.46.0-r0) +(27/91) Installing libcurl (7.81.0-r0) +(28/91) Installing curl (7.81.0-r0) +(29/91) Installing abuild (3.9.0-r0) +Executing abuild-3.9.0-r0.pre-install +(30/91) Installing alpine-baselayout (3.2.0-r18) +Executing alpine-baselayout-3.2.0-r18.pre-install +Executing alpine-baselayout-3.2.0-r18.post-install +(31/91) Installing ifupdown-ng (0.11.3-r0) +(32/91) Installing openrc (0.44.10-r0) +Executing openrc-0.44.10-r0.post-install +(33/91) Installing alpine-conf (3.13.0-r0) +(34/91) Installing busybox-suid (1.35.0-r1) +(35/91) Installing busybox-initscripts (4.0-r5) +Executing busybox-initscripts-4.0-r5.post-install +(36/91) Installing alpine-keys (2.4-r1) +(37/91) Installing alpine-base (3.15.0-r1) +(38/91) Installing binutils (2.37-r4) +(39/91) Installing libmagic (5.41-r0) +(40/91) Installing file (5.41-r0) +(41/91) Installing libgomp (11.2.1_git20220117-r0) +(42/91) Installing libatomic (11.2.1_git20220117-r0) +(43/91) Installing libucontext (1.1-r0) +(44/91) Installing libgphobos (11.2.1_git20220117-r0) +(45/91) Installing gmp (6.2.1-r1) +(46/91) Installing isl22 (0.22-r0) +(47/91) Installing mpfr4 (4.1.0-r0) +(48/91) Installing mpc1 (1.2.1-r0) +(49/91) Installing gcc (11.2.1_git20220117-r0) +(50/91) Installing musl-dev (1.2.2-r7) +(51/91) Installing libc-dev (0.7.2-r3) +(52/91) Installing g++ (11.2.1_git20220117-r0) +(53/91) Installing make (4.3-r0) +(54/91) Installing fortify-headers (1.1-r1) +(55/91) Installing build-base (0.5-r2) +(56/91) Installing libblkid (2.37.3-r0) +(57/91) Installing libcom_err (1.46.5-r0) +(58/91) Installing e2fsprogs-libs (1.46.5-r0) +(59/91) Installing libuuid (2.37.3-r0) +(60/91) Installing e2fsprogs (1.46.5-r0) +(61/91) Installing e2fsprogs-extra (1.46.5-r0) +(62/91) Installing expat (2.4.4-r0) +(63/91) Installing pcre2 (10.39-r0) +(64/91) Installing git (2.35.1-r0) +(65/91) Installing libfdisk (2.37.3-r0) +(66/91) Installing ncurses-terminfo-base (6.3_p20220115-r0) +(67/91) Installing ncurses-libs (6.3_p20220115-r0) +(68/91) Installing libsmartcols (2.37.3-r0) +(69/91) Installing sfdisk (2.37.3-r0) +(70/91) Installing util-linux (2.37.3-r0) +(71/91) Installing libmount (2.37.3-r0) +(72/91) Installing util-linux-misc (2.37.3-r0) +(73/91) Installing libeconf (0.4.4-r0) +(74/91) Installing linux-pam (1.5.2-r0) +(75/91) Installing runuser (2.37.3-r0) +(76/91) Installing hexdump (2.37.3-r0) +(77/91) Installing uuidgen (2.37.3-r0) +(78/91) Installing blkid (2.37.3-r0) +(79/91) Installing mcookie (2.37.3-r0) +(80/91) Installing agetty (2.37.3-r0) +(81/91) Installing agetty-openrc (0.44.10-r0) +(82/91) Installing wipefs (2.37.3-r0) +(83/91) Installing cfdisk (2.37.3-r0) +(84/91) Installing util-linux-openrc (2.37.3-r0) +(85/91) Installing flock (2.37.3-r0) +(86/91) Installing lsblk (2.37.3-r0) +(87/91) Installing libcap-ng (0.8.2-r0) +(88/91) Installing setpriv (2.37.3-r0) +(89/91) Installing logger (2.37.3-r0) +(90/91) Installing partx (2.37.3-r0) +(91/91) Installing findmnt (2.37.3-r0) +Executing busybox-1.35.0-r1.trigger +Executing ca-certificates-20211220-r0.trigger +OK: 223 MiB in 91 packages +>>> tiny-cloud: Fetching https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud/-/archive/2.0.0/tiny-cloud-2.0.0.tar.gz +>>> tiny-cloud: Checking sha512sums... +tiny-cloud-2.0.0.tar.gz: OK +>>> tiny-cloud: Unpacking /var/cache/distfiles/tiny-cloud-2.0.0.tar.gz... +>>> tiny-cloud: Entering fakeroot... +install -Dm755 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud"/bin \ + bin/imds +install -Dm755 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud"/etc/init.d \ + etc/init.d/* +install -Dm644 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud"/etc/conf.d \ + etc/conf.d/tiny-cloud.example +install -Dm644 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud"/lib/tiny-cloud \ + lib/tiny-cloud/common \ + lib/tiny-cloud/init-* \ + lib/tiny-cloud/mdev +>>> tiny-cloud-network*: Running split function network... +install -Dm644 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-network"/etc/network/interfaces.d \ + etc/network/interfaces.d/* +install -Dm755 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-network"/lib/mdev \ + lib/mdev/vnic-eth-hotplug +install -Dm755 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-network"/sbin \ + sbin/* +install -Dm755 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-network"/usr/libexec/ifupdown-ng \ + usr/libexec/ifupdown-ng/imds +>>> tiny-cloud-network*: Preparing subpackage tiny-cloud-network... +>>> tiny-cloud-network*: Running postcheck for tiny-cloud-network +>>> tiny-cloud-openrc*: Running split function openrc... +>>> tiny-cloud-openrc*: Preparing subpackage tiny-cloud-openrc... +>>> tiny-cloud-openrc*: Running postcheck for tiny-cloud-openrc +>>> tiny-cloud-aws*: Running split function aws... +mkdir -p "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-aws"/etc/conf.d +install -Dm755 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-aws"/lib/mdev \ + lib/mdev/nvme-ebs-links +install -Dm644 -t "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-aws"/lib/tiny-cloud/aws \ + lib/tiny-cloud/aws/* +sed -Ee 's/^#?CLOUD=.*/CLOUD=aws/' \ + -Ee 's/^#?HOTPLUG_MODULES=.*/HOTPLUG_MODULES="vnic_eth_hotplug nvme_ebs_links"/' \ + etc/conf.d/tiny-cloud.example > "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-aws"/etc/conf.d/tiny-cloud +>>> tiny-cloud-aws*: Preparing subpackage tiny-cloud-aws... +>>> tiny-cloud-aws*: Running postcheck for tiny-cloud-aws +>>> WARNING: tiny-cloud-aws*: Found OpenRC directory (/etc/conf.d or /etc/init.d) but name doesn't end with -openrc +>>> tiny-cloud-azure*: Running split function azure... +mkdir -p "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-azure"/etc/conf.d +install -Dm644 -t /home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-azure/lib/tiny-cloud/azure \ + lib/tiny-cloud/azure/* +sed -Ee 's/^#?CLOUD=.*/CLOUD=azure/' \ + etc/conf.d/tiny-cloud.example > "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-azure"/etc/conf.d/tiny-cloud +>>> tiny-cloud-azure*: Preparing subpackage tiny-cloud-azure... +>>> tiny-cloud-azure*: Running postcheck for tiny-cloud-azure +>>> WARNING: tiny-cloud-azure*: Found OpenRC directory (/etc/conf.d or /etc/init.d) but name doesn't end with -openrc +>>> tiny-cloud-gcp*: Running split function gcp... +mkdir -p "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-gcp"/etc/conf.d +install -Dm644 -t /home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-gcp/lib/tiny-cloud/gcp \ + lib/tiny-cloud/gcp/* +sed -Ee 's/^#?CLOUD=.*/CLOUD=gcp/' \ + etc/conf.d/tiny-cloud.example > "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-gcp"/etc/conf.d/tiny-cloud +>>> tiny-cloud-gcp*: Preparing subpackage tiny-cloud-gcp... +>>> tiny-cloud-gcp*: Running postcheck for tiny-cloud-gcp +>>> WARNING: tiny-cloud-gcp*: Found OpenRC directory (/etc/conf.d or /etc/init.d) but name doesn't end with -openrc +>>> tiny-cloud-oci*: Running split function oci... +mkdir -p "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-oci"/etc/conf.d +install -Dm644 -t /home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-oci/lib/tiny-cloud/oci \ + lib/tiny-cloud/oci/* +sed -Ee 's/^#?CLOUD=.*/CLOUD=oci/' \ + etc/conf.d/tiny-cloud.example > "/home/tomalok/git/alpinelinux/3.12-stable/main/tiny-cloud/pkg/tiny-cloud-oci"/etc/conf.d/tiny-cloud +>>> tiny-cloud-oci*: Preparing subpackage tiny-cloud-oci... +>>> tiny-cloud-oci*: Running postcheck for tiny-cloud-oci +>>> WARNING: tiny-cloud-oci*: Found OpenRC directory (/etc/conf.d or /etc/init.d) but name doesn't end with -openrc +>>> tiny-cloud*: Running postcheck for tiny-cloud +>>> tiny-cloud*: Preparing package tiny-cloud... +>>> tiny-cloud-aws*: Tracing dependencies... +>>> tiny-cloud-aws*: Package size: 44.0 KB +>>> tiny-cloud-aws*: Compressing data... +>>> tiny-cloud-aws*: Create checksum... +>>> tiny-cloud-aws*: Create tiny-cloud-aws-2.0.0-r0.apk +>>> tiny-cloud-azure*: Tracing dependencies... +>>> tiny-cloud-azure*: Package size: 32.0 KB +>>> tiny-cloud-azure*: Compressing data... +>>> tiny-cloud-azure*: Create checksum... +>>> tiny-cloud-azure*: Create tiny-cloud-azure-2.0.0-r0.apk +>>> tiny-cloud-gcp*: Tracing dependencies... +>>> tiny-cloud-gcp*: Package size: 32.0 KB +>>> tiny-cloud-gcp*: Compressing data... +>>> tiny-cloud-gcp*: Create checksum... +>>> tiny-cloud-gcp*: Create tiny-cloud-gcp-2.0.0-r0.apk +>>> tiny-cloud-network*: Tracing dependencies... +>>> tiny-cloud-network*: Package size: 64.0 KB +>>> tiny-cloud-network*: Compressing data... +>>> tiny-cloud-network*: Create checksum... +>>> tiny-cloud-network*: Create tiny-cloud-network-2.0.0-r0.apk +>>> tiny-cloud-oci*: Tracing dependencies... +>>> tiny-cloud-oci*: Package size: 32.0 KB +>>> tiny-cloud-oci*: Compressing data... +>>> tiny-cloud-oci*: Create checksum... +>>> tiny-cloud-oci*: Create tiny-cloud-oci-2.0.0-r0.apk +>>> tiny-cloud-openrc*: Tracing dependencies... +>>> tiny-cloud-openrc*: Package size: 32.0 KB +>>> tiny-cloud-openrc*: Compressing data... +>>> tiny-cloud-openrc*: Create checksum... +>>> tiny-cloud-openrc*: Create tiny-cloud-openrc-2.0.0-r0.apk +>>> tiny-cloud*: Tracing dependencies... +>>> tiny-cloud*: Package size: 48.0 KB +>>> tiny-cloud*: Compressing data... +>>> tiny-cloud*: Create checksum... +>>> tiny-cloud*: Create tiny-cloud-2.0.0-r0.apk +>>> tiny-cloud: Updating the main/x86_64 repository index... +>>> tiny-cloud: Signing the index... +>>> tiny-cloud: Cleaning up srcdir +>>> tiny-cloud: Cleaning up build chroot +>>> tiny-cloud: Cleaning up pkgdir diff --git a/main/tiny-ec2-bootstrap/APKBUILD b/main/tiny-ec2-bootstrap/APKBUILD index 9e85c2af163..3e881287964 100644 --- a/main/tiny-ec2-bootstrap/APKBUILD +++ b/main/tiny-ec2-bootstrap/APKBUILD @@ -1,19 +1,22 @@ +# Contributor: Jake Buchholz Göktürk <tomalok@gmail.com> # Contributor: Mike Crute <mike@crute.us> # Maintainer: Mike Crute <mike@crute.us> pkgname=tiny-ec2-bootstrap -pkgver=1.4.3 +pkgver=1.4.4 pkgrel=0 pkgdesc="A tiny EC2 instance bootstrapper that uses instance metadata" -url="https://github.com/mcrute/tiny-ec2-bootstrap" +url="https://gitlab.alpinelinux.org/alpine/cloud/tiny-ec2-bootstrap" arch="noarch" license="MIT" options="!check" # no tests provided -depends="openrc e2fsprogs-extra" -source="$pkgname-$pkgver.tar.gz::https://github.com/mcrute/tiny-ec2-bootstrap/archive/release-$pkgver.tar.gz" +depends="openrc e2fsprogs-extra sfdisk util-linux" +source="https://gitlab.alpinelinux.org/alpine/cloud/tiny-ec2-bootstrap/-/archive/release-$pkgver/tiny-ec2-bootstrap-release-$pkgver.tar.gz" builddir="$srcdir/$pkgname-release-$pkgver" package() { make PREFIX=$pkgdir install } -sha512sums="6b15eaae722975b5f9deb6650cfd2319a37cab24084c3638ee3264e7784637cadfda863777909fc2cb09f1c27755082591b645342da697be040687da7a9936f3 tiny-ec2-bootstrap-1.4.3.tar.gz" +sha512sums=" +c9758bf4869a34bd68a010c7fb34ef8934f2af0393e2aa3b84c7ba89e0f9ab7e2af47c86975d0ffa5931a3ed2d276febfc04dddb41083a42988b5412c1b573aa tiny-ec2-bootstrap-release-1.4.4.tar.gz +" diff --git a/main/tzdata/APKBUILD b/main/tzdata/APKBUILD index 9af8c02be86..1dec5d6eff6 100644 --- a/main/tzdata/APKBUILD +++ b/main/tzdata/APKBUILD @@ -2,8 +2,8 @@ # Contributor: Natanael Copa <ncopa@alpinelinux.org> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=tzdata -pkgver=2021c -_tzcodever=2021c +pkgver=2022a +_tzcodever=2022a _ptzver=0.5 pkgrel=0 pkgdesc="Timezone data" @@ -51,8 +51,8 @@ package() { } sha512sums=" -9ed7677744058c58656b47d77d464bad6ef503f2892b53c6abe694e68e73fa123dfc5c11bbcbbb7798f0a6bf1da72b81f8f1c63670839b967e15e58d6d36adad tzcode2021c.tar.gz -e8de3a17c38f530b2ec39605699742dd32da5ee92ecf64accaaa5b012a1dac51d1f594adc52660602c3425016520346ab6ad614fa475eb310e17ccdcae93e6ca tzdata2021c.tar.gz +3f047a6f414ae3df4a3d6bb9b39a1790833d191ae48e6320ab9438cd326dc455475186a02c44e4cde96b48101ab000880919b1e0e8092aed7254443ed2c831ed tzcode2022a.tar.gz +542e4559beac8fd8c4af7d08d816fd12cfe7ffcb6f20bba4ff1c20eba717749ef96e5cf599b2fe03b5b8469c0467f8cb1c893008160da281055a123dd9e810d9 tzdata2022a.tar.gz 68dbaab9f4aef166ac2f2d40b49366527b840bebe17a47599fe38345835e4adb8a767910745ece9c384b57af815a871243c3e261a29f41d71f8054df3061b3fd posixtz-0.5.tar.xz 0f2a10ee2bb4007f57b59123d1a0b8ef6accf99e568f21537f0bb19f290fff46e24050f55f12569d7787be600e1b62aa790ea85a333153f3ea081a812c81b1b5 0001-posixtz-ensure-the-file-offset-we-pass-to-lseek-is-o.patch fb322ab7867517ba39265d56d3576cbcea107c205d524e87015c1819bbb7361f7322232ee3b86ea9b8df2886e7e06a6424e3ac83b2006be290a33856c7d40ac4 0002-fix-implicit-declaration-warnings-by-including-strin.patch diff --git a/main/util-linux/APKBUILD b/main/util-linux/APKBUILD index 545af2f435b..d9e944d23ea 100644 --- a/main/util-linux/APKBUILD +++ b/main/util-linux/APKBUILD @@ -2,7 +2,7 @@ # Contributor: Leonardo Arena <rnalrd@alpinelinux.org> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=util-linux -pkgver=2.35.2 +pkgver=2.37.4 case $pkgver in *.*.*) _v=${pkgver%.*};; @@ -16,7 +16,7 @@ arch="all" license="GPL-3.0-or-later AND GPL-2.0-or-later AND GPL-2.0-only AND LGPL-2.1-or-later AND BSD-3-Clause AND BSD-4-Clause-UC AND Public-Domain" depends="blkid setpriv findmnt mcookie hexdump lsblk sfdisk cfdisk" -makedepends_build="autoconf automake libtool" +makedepends_build="autoconf automake libtool asciidoctor" makedepends_host="zlib-dev ncurses-dev linux-headers libcap-ng-dev" options="suid" source="https://www.kernel.org/pub/linux/utils/util-linux/v$_v/util-linux-$pkgver.tar.xz @@ -46,6 +46,13 @@ else fi makedepends="$makedepends_build $makedepends_host" +# secfixes: +# 2.37.4-r0: +# - CVE-2022-0563 +# 2.37.3-r0: +# - CVE-2021-3995 +# - CVE-2021-3996 + prepare() { default_prepare @@ -137,5 +144,7 @@ _py3() { mv "$pkgdir"/usr/lib/python* "$subpkgdir"/usr/lib/ } -sha512sums="59e038ba71aa74c9af6f927b357483a965f675ab3ffcd25cf0c1b043656312d2d2d07c55659fd3da69ede165bec313e0ae7e1cd73758e49681ae610604b399a2 util-linux-2.35.2.tar.xz -876bb9041eca1b2cca1e9aac898f282db576f7860aba690a95c0ac629d7c5b2cdeccba504dda87ff55c2a10b67165985ce16ca41a0694a267507e1e0cafd46d9 ttydefaults.h" +sha512sums=" +ada2629b0a8e83ea83513e04f7b1ccceb3b8ab82acd119c5d8389d1abc48c92d0b591f39fb34b1fd65db3ab630f03a672a9f3dacf1a6e4f124bdb083fc1be6d7 util-linux-2.37.4.tar.xz +876bb9041eca1b2cca1e9aac898f282db576f7860aba690a95c0ac629d7c5b2cdeccba504dda87ff55c2a10b67165985ce16ca41a0694a267507e1e0cafd46d9 ttydefaults.h +" diff --git a/main/varnish/0001-Mark-req-doclose-when-failing-to-ignore-req-body.patch b/main/varnish/0001-Mark-req-doclose-when-failing-to-ignore-req-body.patch new file mode 100644 index 00000000000..c8d3fde7f18 --- /dev/null +++ b/main/varnish/0001-Mark-req-doclose-when-failing-to-ignore-req-body.patch @@ -0,0 +1,31 @@ +From fceaefd4d59a3b5d5a4903a3f420e35eb430d0d4 Mon Sep 17 00:00:00 2001 +From: Martin Blix Grydeland <martin@varnish-software.com> +Date: Fri, 17 Dec 2021 22:10:16 +0100 +Subject: [PATCH 1/2] Mark req doclose when failing to ignore req body + +Previously we would ignore errors to iterate the request body into +oblivion in VRB_Ignore(), keeping the connection open. This opens an +out-of-sync vulnerability on H/1 connections. + +This patch tests the status of the request body in VRB_Ignore(), marking +the request failed and that it should be closed on errors. +--- + bin/varnishd/cache/cache_req_body.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/bin/varnishd/cache/cache_req_body.c b/bin/varnishd/cache/cache_req_body.c +index 6391f928d..5ffd08b77 100644 +--- a/bin/varnishd/cache/cache_req_body.c ++++ b/bin/varnishd/cache/cache_req_body.c +@@ -254,6 +254,8 @@ VRB_Ignore(struct req *req) + if (req->req_body_status->avail > 0) + (void)VRB_Iterate(req->wrk, req->vsl, req, + httpq_req_body_discard, NULL); ++ if (req->req_body_status == BS_ERROR) ++ req->doclose = SC_RX_BODY; + return (0); + } + +-- +2.35.0 + diff --git a/main/varnish/0002-VRB_Ignore-errors-and-connection-close-test-case.patch b/main/varnish/0002-VRB_Ignore-errors-and-connection-close-test-case.patch new file mode 100644 index 00000000000..7343dc0ba4a --- /dev/null +++ b/main/varnish/0002-VRB_Ignore-errors-and-connection-close-test-case.patch @@ -0,0 +1,75 @@ +From 1020be7e886399a4e94407ae0dfbfd1475cc5756 Mon Sep 17 00:00:00 2001 +From: Martin Blix Grydeland <martin@varnish-software.com> +Date: Fri, 17 Dec 2021 22:10:27 +0100 +Subject: [PATCH 2/2] VRB_Ignore() errors and connection close test case + +--- + bin/varnishtest/tests/f00008.vtc | 56 ++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + create mode 100644 bin/varnishtest/tests/f00008.vtc + +diff --git a/bin/varnishtest/tests/f00008.vtc b/bin/varnishtest/tests/f00008.vtc +new file mode 100644 +index 000000000..4d6161a35 +--- /dev/null ++++ b/bin/varnishtest/tests/f00008.vtc +@@ -0,0 +1,56 @@ ++varnishtest "VRB_Ignore and connection close" ++ ++server s1 { ++ rxreq ++ txresp -body HIT ++} -start ++ ++varnish v1 -arg "-p timeout_idle=1" -vcl+backend { ++ sub vcl_recv { ++ if (req.url == "/synth") { ++ return (synth(200, "SYNTH")); ++ } ++ } ++} -start ++ ++# Prime an object ++client c1 { ++ txreq -url /hit ++ rxresp ++ expect resp.status == 200 ++ expect resp.body == HIT ++} -run ++ ++# Test synth ++client c2 { ++ txreq -req POST -url /synth -hdr "Content-Length: 2" ++ # Send 1 byte ++ send a ++ # Wait timeout_idle ++ delay 1.1 ++ # Send 1 byte ++ send b ++ rxresp ++ expect resp.status == 200 ++ expect resp.reason == SYNTH ++ expect resp.http.connection == close ++ timeout 0.5 ++ expect_close ++} -run ++ ++# Test cache hit ++client c3 { ++ txreq -req GET -url /hit -hdr "Content-Length: 2" ++ # Send 1 byte ++ send a ++ # Wait timeout_idle ++ delay 1.1 ++ # Send 1 byte ++ send b ++ rxresp ++ expect resp.status == 200 ++ expect resp.body == HIT ++ expect resp.http.connection == close ++ timeout 0.5 ++ expect_close ++} -run +-- +2.35.0 + diff --git a/main/varnish/APKBUILD b/main/varnish/APKBUILD index 47030bdb329..0aad693f469 100644 --- a/main/varnish/APKBUILD +++ b/main/varnish/APKBUILD @@ -4,7 +4,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=varnish pkgver=6.5.2 -pkgrel=0 +pkgrel=1 pkgdesc="High-performance HTTP accelerator" url="https://www.varnish-cache.org/" arch="all" @@ -27,10 +27,14 @@ source="https://varnish-cache.org/_downloads/varnish-$pkgver.tgz varnishncsa.initd varnishncsa.confd varnishd.logrotate - maxminddb.vcl" + maxminddb.vcl + 0001-Mark-req-doclose-when-failing-to-ignore-req-body.patch + 0002-VRB_Ignore-errors-and-connection-close-test-case.patch" # secfixes: +# 6.5.2-r1: +# - CVE-2022-23959 # 6.5.2-r0: # - CVE-2021-36740 # 6.2.1-r0: @@ -109,4 +113,6 @@ e0b7d67bbd710f0a17b77837c581f128e6b746eff2b12e81d03d1ad040037e95bb00fb8007d89bc6 a5426ff66b89d2afb6273f05e4117b3eec5ce0162a624d52c92b418960f72e58bd01224165613221af76ec241bd98e1eb985b2ef7b83a5b615e9ece67234dcc8 varnishncsa.confd 51cc6d46ff7439de93977ab87dfb0af399458c1e446475696f73342ae7a0c1a8ca8fc6e79e593659f1af30716a5f8a1ee5e3b1f5e7b35df40b45d47e7b0f2ffd varnishd.logrotate 69f088819cff6d4441813be284f4117f232d08908515bd15d96bd5bb9d41ba7100657a52fd408d44c396d004366062ae22fbf08e2a983cd8023b554539ccf596 maxminddb.vcl +62f8c3f86d283b20f25db20504434095392c1aacbf4c91cea0ee9ba3cfd22ad1de928cb56ff4e1a226a5b31cc25466dcae0f28a8ebf575faa8655a9676ea896c 0001-Mark-req-doclose-when-failing-to-ignore-req-body.patch +010d96023cd03c5350da9d779cbb05f0ce47b36d47869ace01e2c7cd841fffb610f28b39118bf9bc36617f778ab59a5d913b14ae2e71467852f6390021f7a295 0002-VRB_Ignore-errors-and-connection-close-test-case.patch " diff --git a/main/vim/APKBUILD b/main/vim/APKBUILD index add81d3932e..4bd8d8dbe7a 100644 --- a/main/vim/APKBUILD +++ b/main/vim/APKBUILD @@ -3,7 +3,7 @@ # Contributor: Sören Tempel <soeren+alpine@soeren-tempel.net> # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=vim -pkgver=8.2.3437 +pkgver=8.2.4836 pkgrel=0 pkgdesc="Improved vi-style text editor" url="https://www.vim.org/" @@ -18,6 +18,55 @@ source="$pkgname-$pkgver.tar.gz::https://github.com/vim/vim/archive/v$pkgver.tar " # secfixes: +# 8.2.4836-r0: +# - CVE-2022-1381 +# 8.2.4708-r0: +# - CVE-2022-1154 +# - CVE-2022-1160 +# 8.2.4619-r0: +# - CVE-2022-0943 +# - CVE-2022-0572 +# - CVE-2022-0629 +# - CVE-2022-0685 +# - CVE-2022-0696 +# - CVE-2022-0714 +# - CVE-2022-0729 +# - CVE-2022-0359 +# - CVE-2022-0361 +# - CVE-2022-0368 +# - CVE-2022-0392 +# - CVE-2022-0393 +# - CVE-2022-0407 +# - CVE-2022-0408 +# - CVE-2022-0413 +# - CVE-2022-0417 +# - CVE-2022-0443 +# 8.2.4173-r0: +# - CVE-2021-4069 +# - CVE-2021-4136 +# - CVE-2021-4166 +# - CVE-2021-4173 +# - CVE-2021-4187 +# - CVE-2021-4192 +# - CVE-2021-4193 +# - CVE-2021-46059 +# - CVE-2022-0128 +# - CVE-2022-0156 +# - CVE-2022-0158 +# - CVE-2022-0213 +# 8.2.3779-r0: +# - CVE-2021-4019 +# 8.2.3650-r0: +# - CVE-2021-3927 +# - CVE-2021-3928 +# - CVE-2021-3968 +# - CVE-2021-3973 +# - CVE-2021-3974 +# - CVE-2021-3984 +# 8.2.3567-r0: +# - CVE-2021-3903 +# 8.2.3500-r0: +# - CVE-2021-3875 # 8.2.3437-r0: # - CVE-2021-3770 # - CVE-2021-3778 @@ -113,6 +162,6 @@ xxd() { } sha512sums=" -7f6fc24f8f4a4fa01d20702684cc09aa5c3b51cdc2c96f3afcb484bc60874fab5dcafc33a9daa5ff25f7ae7b90ba0b124a7667d33d9fa5d9553a11be9a1ee069 vim-8.2.3437.tar.gz +e1afe03a3140c91fa928d88a8b3ad5e7c8808e5de5b7a07726b2a4f8f402adfdef2890be6a279e52848cc75346d15d4653f579f96da409544d58aba036abbbf7 vim-8.2.4836.tar.gz d9586b777881973cb5e48e18750336a522ed72c3127b2d6b6991e2b943468ca5b694476e7fa39ab469178c1375fc8f52627484e0fe377aea5811a513e35a7b02 vimrc " diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD index 5054641f7ff..eef40589474 100644 --- a/main/xen/APKBUILD +++ b/main/xen/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=xen pkgver=4.13.4 -pkgrel=0 +pkgrel=3 pkgdesc="Xen hypervisor" url="https://www.xenproject.org/" arch="x86_64 armhf aarch64" # enable armv7 when builds with gcc8 @@ -116,35 +116,35 @@ options="!strip" # 4.10.1-r0: # - CVE-2018-10472 XSA-258 # - CVE-2018-10471 XSA-259 -# 4.10-1-r1: +# 4.10.1-r1: # - CVE-2018-8897 XSA-260 # - CVE-2018-10982 XSA-261 # - CVE-2018-10981 XSA-262 # 4.11.0-r0: -# - CVE-2018-3639 XSA-263 -# - CVE-2018-12891 XSA-264 -# - CVE-2018-12893 XSA-265 -# - CVE-2018-12892 XSA-266 -# - CVE-2018-3665 XSA-267 +# - CVE-2018-3639 XSA-263 +# - CVE-2018-12891 XSA-264 +# - CVE-2018-12893 XSA-265 +# - CVE-2018-12892 XSA-266 +# - CVE-2018-3665 XSA-267 # 4.11.1-r0: -# - CVE-2018-15469 XSA-268 -# - CVE-2018-15468 XSA-269 -# - CVE-2018-15470 XSA-272 -# - CVE-2018-3620 XSA-273 -# - CVE-2018-3646 XSA-273 -# - CVE-2018-19961 XSA-275 -# - CVE-2018-19962 XSA-275 -# - CVE-2018-19963 XSA-276 -# - CVE-2018-19964 XSA-277 -# - CVE-2018-18883 XSA-278 -# - CVE-2018-19965 XSA-279 -# - CVE-2018-19966 XSA-280 -# - CVE-2018-19967 XSA-282 +# - CVE-2018-15469 XSA-268 +# - CVE-2018-15468 XSA-269 +# - CVE-2018-15470 XSA-272 +# - CVE-2018-3620 XSA-273 +# - CVE-2018-3646 XSA-273 +# - CVE-2018-19961 XSA-275 +# - CVE-2018-19962 XSA-275 +# - CVE-2018-19963 XSA-276 +# - CVE-2018-19964 XSA-277 +# - CVE-2018-18883 XSA-278 +# - CVE-2018-19965 XSA-279 +# - CVE-2018-19966 XSA-280 +# - CVE-2018-19967 XSA-282 # 4.12.0-r2: -# - CVE-2018-12126 XSA-297 -# - CVE-2018-12127 XSA-297 -# - CVE-2018-12130 XSA-297 -# - CVE-2019-11091 XSA-297 +# - CVE-2018-12126 XSA-297 +# - CVE-2018-12127 XSA-297 +# - CVE-2018-12130 XSA-297 +# - CVE-2019-11091 XSA-297 # 4.12.1-r0: # - CVE-2019-17349 CVE-2019-17350 XSA-295 # 4.13.0-r0: @@ -167,9 +167,9 @@ options="!strip" # - CVE-2020-11743 XSA-316 # - CVE-2020-11742 XSA-318 # 4.13.1-r0: -# - CVE-????-????? XSA-312 +# - XSA-312 # 4.13.1-r1: -# - CVE-2020-0543 XSA-320 +# - CVE-2020-0543 XSA-320 # 4.13.1-r2: # - CVE-2020-15566 XSA-317 # - CVE-2020-15563 XSA-319 @@ -211,7 +211,7 @@ options="!strip" # - CVE-2020-29570 XSA-358 # - CVE-2020-29571 XSA-359 # 4.13.2-r4: -# - CVE-2021-3308 XSA-360 +# - CVE-2021-3308 XSA-360 # 4.13.2-r5: # - CVE-2021-26933 XSA-364 # 4.13.3-r0: @@ -219,7 +219,7 @@ options="!strip" # 4.13.3-r1: # - CVE-2021-28693 XSA-372 # - CVE-2021-28692 XSA-373 -# - CVE-2021-0089 XSA-375 +# - CVE-2021-0089 XSA-375 # - CVE-2021-28690 XSA-377 # 4.13.3-r2: # - CVE-2021-28694 XSA-378 @@ -231,6 +231,29 @@ options="!strip" # - CVE-2021-28700 XSA-383 # 4.13.3-r3: # - CVE-2021-28701 XSA-384 +# 4.13.4-r0: +# - CVE-2021-28703 XSA-387 +# 4.13.4-r1: +# - CVE-2021-28702 XSA-386 +# 4.13.4-r2: +# - CVE-2021-28704 XSA-388 +# - CVE-2021-28707 XSA-388 +# - CVE-2021-28708 XSA-388 +# - CVE-2021-28705 XSA-389 +# - CVE-2021-28706 XSA-389 +# 4.13.4-r3: +# - CVE-2021-28706 XSA-385 +# - CVE-2022-23033 XSA-393 +# - CVE-2022-23034 XSA-394 +# - CVE-2022-23035 XSA-395 +# - CVE-2022-26356 XSA-397 +# - CVE-2022-23960 XSA-398 +# - CVE-2022-26401 XSA-398 +# - CVE-2022-26357 XSA-399 +# - CVE-2022-26358 XSA-400 +# - CVE-2022-26359 XSA-400 +# - CVE-2022-26360 XSA-400 +# - CVE-2022-26361 XSA-400 case "$CARCH" in @@ -297,6 +320,8 @@ source="https://downloads.xenproject.org/release/xen/$pkgver/xen-$pkgver.tar.gz drop-test.py.patch py3-compat.patch + xen-stable-4.13_git20220408.patch + xenstored.initd xenstored.confd xenconsoled.initd @@ -544,6 +569,7 @@ e76816c6ad0e91dc5f81947f266da3429b20e6d976c3e8c41202c6179532eec878a3f0913921ef3a 8c9cfc6afca325df1d8026e21ed03fa8cd2c7e1a21a56cc1968301c5ab634bfe849951899e75d328951d7a41273d1e49a2448edbadec0029ed410c43c0549812 hotplug-Linux-iscsi-block-handle-lun-1.patch 61f66bab603778fb41bfe8e85320c15f2bf3e5d8583e077b56a93784dbdb9b2c7c5e55ce18f06b87501429086f8410d102d3ed5f2a77d54bcfa328bc07681f4d drop-test.py.patch 8cb12dbfc05a53898a97d47d71ab6b8a6f81c5e5579fd765b37303faea95c645cb8dedc05e3d064bdf070e93814e00bf8939767acc1127513375bab0fe2f4436 py3-compat.patch +f02f939fc9f788e99c7363e1e385e83acaa5725594eb4b37597b824ec8f853ba0f91ee0d17ebcf59c3ae4ed08eaa4ae79e3572602a67d51ed46ed900a63054e1 xen-stable-4.13_git20220408.patch 52c43beb2596d645934d0f909f2d21f7587b6898ed5e5e7046799a8ed6d58f7a09c5809e1634fa26152f3fd4f3e7cfa07da7076f01b4a20cc8f5df8b9cb77e50 xenstored.initd 093f7fbd43faf0a16a226486a0776bade5dc1681d281c5946a3191c32d74f9699c6bf5d0ab8de9d1195a2461165d1660788e92a3156c9b3c7054d7b2d52d7ff0 xenstored.confd 3c86ed48fbee0af4051c65c4a3893f131fa66e47bf083caf20c9b6aa4b63fdead8832f84a58d0e27964bc49ec8397251b34e5be5c212c139f556916dc8da9523 xenconsoled.initd diff --git a/main/xen/xen-stable-4.13_git20220408.patch b/main/xen/xen-stable-4.13_git20220408.patch new file mode 100644 index 00000000000..33c1738ac2c --- /dev/null +++ b/main/xen/xen-stable-4.13_git20220408.patch @@ -0,0 +1,5414 @@ +From b4bb02d5999a56c93f0733b589b717e7cece9c09 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Fri, 1 Oct 2021 15:05:42 +0200 +Subject: [PATCH 01/32] VT-d: fix deassign of device with RMRR + +Ignoring a specific error code here was not meant to short circuit +deassign to _just_ the unmapping of RMRRs. This bug was previously +hidden by the bogus (potentially indefinite) looping in +pci_release_devices(), until f591755823a7 ("IOMMU/PCI: don't let domain +cleanup continue when device de-assignment failed") fixed that loop. + +This is CVE-2021-28702 / XSA-386. + +Fixes: 8b99f4400b69 ("VT-d: fix RMRR related error handling") +Reported-by: Ivan Kardykov <kardykov@tabit.pro> +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Tested-by: Ivan Kardykov <kardykov@tabit.pro> +(cherry picked from commit 24ebe875a77833696bbe5c9372e9e1590a7e7101) +--- + xen/drivers/passthrough/vtd/iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index 98787ce3a8..af8b9ca0e4 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -2393,7 +2393,7 @@ static int reassign_device_ownership( + ret = iommu_identity_mapping(source, p2m_access_x, + rmrr->base_address, + rmrr->end_address, 0); +- if ( ret != -ENOENT ) ++ if ( ret && ret != -ENOENT ) + return ret; + } + } +-- +2.35.2 + + +From 0b28069aa7c26288376040e6ee9ca145245db39e Mon Sep 17 00:00:00 2001 +From: Julien Grall <jgrall@amazon.com> +Date: Tue, 23 Nov 2021 13:32:26 +0100 +Subject: [PATCH 02/32] xen/page_alloc: Harden assign_pages() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +domain_tot_pages() and d->max_pages are 32-bit values. While the order +should always be quite small, it would still be possible to overflow +if domain_tot_pages() is near to (2^32 - 1). + +As this code may be called by a guest via XENMEM_increase_reservation +and XENMEM_populate_physmap, we want to make sure the guest is not going +to be able to allocate more than it is allowed. + +Rework the allocation check to avoid any possible overflow. While the +check domain_tot_pages() < d->max_pages should technically not be +necessary, it is probably best to have it to catch any possible +inconsistencies in the future. + +This is CVE-2021-28706 / part of XSA-385. + +Signed-off-by: Julien Grall <jgrall@amazon.com> +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 143501861d48e1bfef495849fd68584baac05849 +master date: 2021-11-22 11:11:05 +0000 +--- + xen/common/grant_table.c | 7 ++++--- + xen/common/page_alloc.c | 19 ++++++++++++++----- + 2 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c +index d2853a664a..7b775a8c35 100644 +--- a/xen/common/grant_table.c ++++ b/xen/common/grant_table.c +@@ -2286,7 +2286,8 @@ gnttab_transfer( + * pages when it is dying. + */ + if ( unlikely(e->is_dying) || +- unlikely(e->tot_pages >= e->max_pages) ) ++ unlikely(e->tot_pages >= e->max_pages) || ++ unlikely(!(e->tot_pages + 1)) ) + { + spin_unlock(&e->page_alloc_lock); + +@@ -2295,8 +2296,8 @@ gnttab_transfer( + e->domain_id); + else + gdprintk(XENLOG_INFO, +- "Transferee d%d has no headroom (tot %u, max %u)\n", +- e->domain_id, e->tot_pages, e->max_pages); ++ "Transferee %pd has no headroom (tot %u, max %u)\n", ++ e, e->tot_pages, e->max_pages); + + gop.status = GNTST_general_error; + goto unlock_and_copyback; +diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c +index 1563188f4f..0976bf6489 100644 +--- a/xen/common/page_alloc.c ++++ b/xen/common/page_alloc.c +@@ -2276,16 +2276,25 @@ int assign_pages( + + if ( !(memflags & MEMF_no_refcount) ) + { +- if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) ) ++ unsigned int nr = 1u << order; ++ ++ if ( unlikely(d->tot_pages > d->max_pages) ) ++ { ++ gprintk(XENLOG_INFO, "Inconsistent allocation for %pd: %u > %u\n", ++ d, d->tot_pages, d->max_pages); ++ rc = -EPERM; ++ goto out; ++ } ++ ++ if ( unlikely(nr > d->max_pages - d->tot_pages) ) + { +- gprintk(XENLOG_INFO, "Over-allocation for domain %u: " +- "%u > %u\n", d->domain_id, +- d->tot_pages + (1 << order), d->max_pages); ++ gprintk(XENLOG_INFO, "Over-allocation for %pd: %Lu > %u\n", ++ d, d->tot_pages + 0ull + nr, d->max_pages); + rc = -E2BIG; + goto out; + } + +- if ( unlikely(domain_adjust_tot_pages(d, 1 << order) == (1 << order)) ) ++ if ( unlikely(domain_adjust_tot_pages(d, nr) == nr) ) + get_knownalive_domain(d); + } + +-- +2.35.2 + + +From d94d006ed36084914c2931641b724ae262e3fb80 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 23 Nov 2021 13:32:54 +0100 +Subject: [PATCH 03/32] x86/PoD: deal with misaligned GFNs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Users of XENMEM_decrease_reservation and XENMEM_populate_physmap aren't +required to pass in order-aligned GFN values. (While I consider this +bogus, I don't think we can fix this there, as that might break existing +code, e.g Linux'es swiotlb, which - while affecting PV only - until +recently had been enforcing only page alignment on the original +allocation.) Only non-PoD code paths (guest_physmap_{add,remove}_page(), +p2m_set_entry()) look to be dealing with this properly (in part by being +implemented inefficiently, handling every 4k page separately). + +Introduce wrappers taking care of splitting the incoming request into +aligned chunks, without putting much effort in trying to determine the +largest possible chunk at every iteration. + +Also "handle" p2m_set_entry() failure for non-order-0 requests by +crashing the domain in one more place. Alongside putting a log message +there, also add one to the other similar path. + +Note regarding locking: This is left in the actual worker functions on +the assumption that callers aren't guaranteed atomicity wrt acting on +multiple pages at a time. For mis-aligned GFNs gfn_lock() wouldn't have +locked the correct GFN range anyway, if it didn't simply resolve to +p2m_lock(), and for well-behaved callers there continues to be only a +single iteration, i.e. behavior is unchanged for them. (FTAOD pulling +out just pod_lock() into p2m_pod_decrease_reservation() would result in +a lock order violation.) + +This is CVE-2021-28704 and CVE-2021-28707 / part of XSA-388. + +Fixes: 3c352011c0d3 ("x86/PoD: shorten certain operations on higher order ranges") +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 182c737b9ba540ebceb1433f3940fbed6eac4ea9 +master date: 2021-11-22 12:27:30 +0000 +--- + xen/arch/x86/mm/p2m-pod.c | 75 ++++++++++++++++++++++++++++++++------- + 1 file changed, 63 insertions(+), 12 deletions(-) + +diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c +index 007cdd87d0..c14801f5ff 100644 +--- a/xen/arch/x86/mm/p2m-pod.c ++++ b/xen/arch/x86/mm/p2m-pod.c +@@ -495,7 +495,7 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, gfn_t gfn); + + + /* +- * This function is needed for two reasons: ++ * This pair of functions is needed for two reasons: + * + To properly handle clearing of PoD entries + * + To "steal back" memory being freed for the PoD cache, rather than + * releasing it. +@@ -503,8 +503,8 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, gfn_t gfn); + * Once both of these functions have been completed, we can return and + * allow decrease_reservation() to handle everything else. + */ +-unsigned long +-p2m_pod_decrease_reservation(struct domain *d, gfn_t gfn, unsigned int order) ++static unsigned long ++decrease_reservation(struct domain *d, gfn_t gfn, unsigned int order) + { + unsigned long ret = 0, i, n; + struct p2m_domain *p2m = p2m_get_hostp2m(d); +@@ -557,8 +557,10 @@ p2m_pod_decrease_reservation(struct domain *d, gfn_t gfn, unsigned int order) + * All PoD: Mark the whole region invalid and tell caller + * we're done. + */ +- if ( p2m_set_entry(p2m, gfn, INVALID_MFN, order, p2m_invalid, +- p2m->default_access) ) ++ int rc = p2m_set_entry(p2m, gfn, INVALID_MFN, order, p2m_invalid, ++ p2m->default_access); ++ ++ if ( rc ) + { + /* + * If this fails, we can't tell how much of the range was changed. +@@ -566,7 +568,12 @@ p2m_pod_decrease_reservation(struct domain *d, gfn_t gfn, unsigned int order) + * impossible. + */ + if ( order != 0 ) ++ { ++ printk(XENLOG_G_ERR ++ "%pd: marking GFN %#lx (order %u) as non-PoD failed: %d\n", ++ d, gfn_x(gfn), order, rc); + domain_crash(d); ++ } + goto out_unlock; + } + ret = 1UL << order; +@@ -674,6 +681,22 @@ out_unlock: + return ret; + } + ++unsigned long ++p2m_pod_decrease_reservation(struct domain *d, gfn_t gfn, unsigned int order) ++{ ++ unsigned long left = 1UL << order, ret = 0; ++ unsigned int chunk_order = find_first_set_bit(gfn_x(gfn) | left); ++ ++ do { ++ ret += decrease_reservation(d, gfn, chunk_order); ++ ++ left -= 1UL << chunk_order; ++ gfn = gfn_add(gfn, 1UL << chunk_order); ++ } while ( left ); ++ ++ return ret; ++} ++ + void p2m_pod_dump_data(struct domain *d) + { + struct p2m_domain *p2m = p2m_get_hostp2m(d); +@@ -1269,19 +1292,15 @@ remap_and_retry: + return true; + } + +- +-int +-guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn_l, +- unsigned int order) ++static int ++mark_populate_on_demand(struct domain *d, unsigned long gfn_l, ++ unsigned int order) + { + struct p2m_domain *p2m = p2m_get_hostp2m(d); + gfn_t gfn = _gfn(gfn_l); + unsigned long i, n, pod_count = 0; + int rc = 0; + +- if ( !paging_mode_translate(d) ) +- return -EINVAL; +- + gfn_lock(p2m, gfn, order); + + P2M_DEBUG("mark pod gfn=%#lx\n", gfn_l); +@@ -1319,6 +1338,17 @@ guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn_l, + BUG_ON(p2m->pod.entry_count < 0); + pod_unlock(p2m); + } ++ else if ( order ) ++ { ++ /* ++ * If this failed, we can't tell how much of the range was changed. ++ * Best to crash the domain. ++ */ ++ printk(XENLOG_G_ERR ++ "%pd: marking GFN %#lx (order %u) as PoD failed: %d\n", ++ d, gfn_l, order, rc); ++ domain_crash(d); ++ } + + out: + gfn_unlock(p2m, gfn, order); +@@ -1326,6 +1356,27 @@ out: + return rc; + } + ++int ++guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, ++ unsigned int order) ++{ ++ unsigned long left = 1UL << order; ++ unsigned int chunk_order = find_first_set_bit(gfn | left); ++ int rc; ++ ++ if ( !paging_mode_translate(d) ) ++ return -EINVAL; ++ ++ do { ++ rc = mark_populate_on_demand(d, gfn, chunk_order); ++ ++ left -= 1UL << chunk_order; ++ gfn += 1UL << chunk_order; ++ } while ( !rc && left ); ++ ++ return rc; ++} ++ + void p2m_pod_init(struct p2m_domain *p2m) + { + unsigned int i; +-- +2.35.2 + + +From d3cfb4b3a680d3e2ddd36f18201d48441f36aea0 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 23 Nov 2021 13:33:14 +0100 +Subject: [PATCH 04/32] x86/PoD: handle intermediate page orders in + p2m_pod_cache_add() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +p2m_pod_decrease_reservation() may pass pages to the function which +aren't 4k, 2M, or 1G. Handle all intermediate orders as well, to avoid +hitting the BUG() at the switch() statement's "default" case. + +This is CVE-2021-28708 / part of XSA-388. + +Fixes: 3c352011c0d3 ("x86/PoD: shorten certain operations on higher order ranges") +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 8ec13f68e0b026863d23e7f44f252d06478bc809 +master date: 2021-11-22 12:27:30 +0000 +--- + xen/arch/x86/mm/p2m-pod.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c +index c14801f5ff..c981200087 100644 +--- a/xen/arch/x86/mm/p2m-pod.c ++++ b/xen/arch/x86/mm/p2m-pod.c +@@ -111,15 +111,13 @@ p2m_pod_cache_add(struct p2m_domain *p2m, + /* Then add to the appropriate populate-on-demand list. */ + switch ( order ) + { +- case PAGE_ORDER_1G: +- for ( i = 0; i < (1UL << PAGE_ORDER_1G); i += 1UL << PAGE_ORDER_2M ) ++ case PAGE_ORDER_2M ... PAGE_ORDER_1G: ++ for ( i = 0; i < (1UL << order); i += 1UL << PAGE_ORDER_2M ) + page_list_add_tail(page + i, &p2m->pod.super); + break; +- case PAGE_ORDER_2M: +- page_list_add_tail(page, &p2m->pod.super); +- break; +- case PAGE_ORDER_4K: +- page_list_add_tail(page, &p2m->pod.single); ++ case PAGE_ORDER_4K ... PAGE_ORDER_2M - 1: ++ for ( i = 0; i < (1UL << order); i += 1UL << PAGE_ORDER_4K ) ++ page_list_add_tail(page + i, &p2m->pod.single); + break; + default: + BUG(); +-- +2.35.2 + + +From d3c2319ea1657f31ae3899713afc23789b771c10 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 23 Nov 2021 13:33:33 +0100 +Subject: [PATCH 05/32] x86/P2M: deal with partial success of p2m_set_entry() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +M2P and PoD stats need to remain in sync with P2M; if an update succeeds +only partially, respective adjustments need to be made. If updates get +made before the call, they may also need undoing upon complete failure +(i.e. including the single-page case). + +Log-dirty state would better also be kept in sync. + +Note that the change to set_typed_p2m_entry() may not be strictly +necessary (due to the order restriction enforced near the top of the +function), but is being kept here to be on the safe side. + +This is CVE-2021-28705 and CVE-2021-28709 / XSA-389. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 74a11c43fd7e074b1f77631b446dd2115eacb9e8 +master date: 2021-11-22 12:27:30 +0000 +--- + xen/arch/x86/mm/p2m.c | 116 +++++++++++++++++++++++++++++++++++++----- + 1 file changed, 102 insertions(+), 14 deletions(-) + +diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c +index a68b4fe526..a6bfda010a 100644 +--- a/xen/arch/x86/mm/p2m.c ++++ b/xen/arch/x86/mm/p2m.c +@@ -781,6 +781,7 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn_l, unsigned long mfn, + gfn_t gfn = _gfn(gfn_l); + p2m_type_t t; + p2m_access_t a; ++ int rc; + + /* IOMMU for PV guests is handled in get_page_type() and put_page(). */ + if ( !paging_mode_translate(p2m->domain) ) +@@ -812,8 +813,27 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn_l, unsigned long mfn, + set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY); + } + } +- return p2m_set_entry(p2m, gfn, INVALID_MFN, page_order, p2m_invalid, +- p2m->default_access); ++ rc = p2m_set_entry(p2m, gfn, INVALID_MFN, page_order, p2m_invalid, ++ p2m->default_access); ++ if ( likely(!rc) || !mfn_valid(_mfn(mfn)) ) ++ return rc; ++ ++ /* ++ * The operation may have partially succeeded. For the failed part we need ++ * to undo the M2P update and, out of precaution, mark the pages dirty ++ * again. ++ */ ++ for ( i = 0; i < (1UL << page_order); ++i ) ++ { ++ p2m->get_entry(p2m, gfn_add(gfn, i), &t, &a, 0, NULL, NULL); ++ if ( !p2m_is_hole(t) && !p2m_is_special(t) && !p2m_is_shared(t) ) ++ { ++ set_gpfn_from_mfn(mfn + i, gfn_l + i); ++ paging_mark_pfn_dirty(p2m->domain, _pfn(gfn_l + i)); ++ } ++ } ++ ++ return rc; + } + + int +@@ -1002,13 +1022,8 @@ guest_physmap_add_entry(struct domain *d, gfn_t gfn, mfn_t mfn, + + /* Now, actually do the two-way mapping */ + rc = p2m_set_entry(p2m, gfn, mfn, page_order, t, p2m->default_access); +- if ( rc == 0 ) ++ if ( likely(!rc) ) + { +- pod_lock(p2m); +- p2m->pod.entry_count -= pod_count; +- BUG_ON(p2m->pod.entry_count < 0); +- pod_unlock(p2m); +- + if ( !p2m_is_grant(t) ) + { + for ( i = 0; i < (1UL << page_order); i++ ) +@@ -1016,6 +1031,42 @@ guest_physmap_add_entry(struct domain *d, gfn_t gfn, mfn_t mfn, + gfn_x(gfn_add(gfn, i))); + } + } ++ else ++ { ++ /* ++ * The operation may have partially succeeded. For the successful part ++ * we need to update M2P and dirty state, while for the failed part we ++ * may need to adjust PoD stats as well as undo the earlier M2P update. ++ */ ++ for ( i = 0; i < (1UL << page_order); ++i ) ++ { ++ omfn = p2m->get_entry(p2m, gfn_add(gfn, i), &ot, &a, 0, NULL, NULL); ++ if ( p2m_is_pod(ot) ) ++ { ++ BUG_ON(!pod_count); ++ --pod_count; ++ } ++ else if ( mfn_eq(omfn, mfn_add(mfn, i)) && ot == t && ++ a == p2m->default_access && !p2m_is_grant(t) ) ++ { ++ set_gpfn_from_mfn(mfn_x(omfn), gfn_x(gfn) + i); ++ paging_mark_pfn_dirty(d, _pfn(gfn_x(gfn) + i)); ++ } ++ else if ( p2m_is_ram(ot) && !p2m_is_paged(ot) ) ++ { ++ ASSERT(mfn_valid(omfn)); ++ set_gpfn_from_mfn(mfn_x(omfn), gfn_x(gfn) + i); ++ } ++ } ++ } ++ ++ if ( pod_count ) ++ { ++ pod_lock(p2m); ++ p2m->pod.entry_count -= pod_count; ++ BUG_ON(p2m->pod.entry_count < 0); ++ pod_unlock(p2m); ++ } + + out: + p2m_unlock(p2m); +@@ -1307,6 +1358,49 @@ static int set_typed_p2m_entry(struct domain *d, unsigned long gfn_l, + return 0; + } + } ++ ++ P2M_DEBUG("set %d %lx %lx\n", gfn_p2mt, gfn_l, mfn_x(mfn)); ++ rc = p2m_set_entry(p2m, gfn, mfn, order, gfn_p2mt, access); ++ if ( unlikely(rc) ) ++ { ++ gdprintk(XENLOG_ERR, "p2m_set_entry: %#lx:%u -> %d (0x%"PRI_mfn")\n", ++ gfn_l, order, rc, mfn_x(mfn)); ++ ++ /* ++ * The operation may have partially succeeded. For the successful part ++ * we need to update PoD stats, M2P, and dirty state. ++ */ ++ if ( order != PAGE_ORDER_4K ) ++ { ++ unsigned long i; ++ ++ for ( i = 0; i < (1UL << order); ++i ) ++ { ++ p2m_type_t t; ++ mfn_t cmfn = p2m->get_entry(p2m, gfn_add(gfn, i), &t, &a, 0, ++ NULL, NULL); ++ ++ if ( !mfn_eq(cmfn, mfn_add(mfn, i)) || t != gfn_p2mt || ++ a != access ) ++ continue; ++ ++ if ( p2m_is_ram(ot) ) ++ { ++ ASSERT(mfn_valid(mfn_add(omfn, i))); ++ set_gpfn_from_mfn(mfn_x(omfn) + i, INVALID_M2P_ENTRY); ++ } ++#ifdef CONFIG_HVM ++ else if ( p2m_is_pod(ot) ) ++ { ++ pod_lock(p2m); ++ BUG_ON(!p2m->pod.entry_count); ++ --p2m->pod.entry_count; ++ pod_unlock(p2m); ++ } ++#endif ++ } ++ } ++ } + else if ( p2m_is_ram(ot) ) + { + unsigned long i; +@@ -1317,12 +1411,6 @@ static int set_typed_p2m_entry(struct domain *d, unsigned long gfn_l, + set_gpfn_from_mfn(mfn_x(omfn) + i, INVALID_M2P_ENTRY); + } + } +- +- P2M_DEBUG("set %d %lx %lx\n", gfn_p2mt, gfn_l, mfn_x(mfn)); +- rc = p2m_set_entry(p2m, gfn, mfn, order, gfn_p2mt, access); +- if ( rc ) +- gdprintk(XENLOG_ERR, "p2m_set_entry: %#lx:%u -> %d (0x%"PRI_mfn")\n", +- gfn_l, order, rc, mfn_x(mfn)); + #ifdef CONFIG_HVM + else if ( p2m_is_pod(ot) ) + { +-- +2.35.2 + + +From d0e2c2762b981abd984af66a844ac12d8bf8f813 Mon Sep 17 00:00:00 2001 +From: Ian Jackson <iwj@xenproject.org> +Date: Mon, 6 Dec 2021 14:40:24 +0000 +Subject: [PATCH 06/32] MAINTAINERS: Resign from tools stable branch + maintainership + +Signed-off-by: Ian Jackson <iwj@xenproject.org> +Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> +(cherry picked from commit c623a84c2a4fda1cd25f5347a6298706218eb5fb) +(cherry picked from commit c4cf5388652e8434652e30c73aa79635b4253675) +--- + MAINTAINERS | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 806e02b4f8..bdd885ddff 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -60,7 +60,7 @@ The maintainer for this branch is: + + Tools backport requests should also be copied to: + +- Ian Jackson <Ian.Jackson@eu.citrix.com> ++ TODO - Loooking for new tools stable maintainer + + + Unstable Subsystem Maintainers +-- +2.35.2 + + +From 2d601a5ca15e02820d08232ad64add8b8374b81c Mon Sep 17 00:00:00 2001 +From: Julien Grall <jgrall@amazon.com> +Date: Tue, 25 Jan 2022 14:44:21 +0100 +Subject: [PATCH 07/32] xen/arm: p2m: Always clear the P2M entry when the + mapping is removed + +Commit 2148a125b73b ("xen/arm: Track page accessed between batch of +Set/Way operations") allowed an entry to be invalid from the CPU PoV +(lpae_is_valid()) but valid for Xen (p2m_is_valid()). This is useful +to track which page is accessed and only perform an action on them +(e.g. clean & invalidate the cache after a set/way instruction). + +Unfortunately, __p2m_set_entry() is only zeroing the P2M entry when +lpae_is_valid() returns true. This means the entry will not be zeroed +if the entry was valid from Xen PoV but invalid from the CPU PoV for +tracking purpose. + +As a consequence, this will allow a domain to continue to access the +page after it was removed. + +Resolve the issue by always zeroing the entry if it the LPAE bit is +set or the entry is about to be removed. + +This is CVE-2022-23033 / XSA-393. + +Reported-by: Dmytro Firsov <Dmytro_Firsov@epam.com> +Fixes: 2148a125b73b ("xen/arm: Track page accessed between batch of Set/Way operations") +Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> +Signed-off-by: Julien Grall <jgrall@amazon.com> +master commit: a428b913a002eb2b7425b48029c20a52eeee1b5a +master date: 2022-01-25 13:25:01 +0100 +--- + xen/arch/arm/p2m.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c +index ce59f2b503..993fe4ded2 100644 +--- a/xen/arch/arm/p2m.c ++++ b/xen/arch/arm/p2m.c +@@ -1012,7 +1012,7 @@ static int __p2m_set_entry(struct p2m_domain *p2m, + * sequence when updating the translation table (D4.7.1 in ARM DDI + * 0487A.j). + */ +- if ( lpae_is_valid(orig_pte) ) ++ if ( lpae_is_valid(orig_pte) || removing_mapping ) + p2m_remove_pte(entry, p2m->clean_pte); + + if ( removing_mapping ) +-- +2.35.2 + + +From e48c7878e54a5f970c00abed2cfd747858f0d592 Mon Sep 17 00:00:00 2001 +From: Julien Grall <jgrall@amazon.com> +Date: Tue, 25 Jan 2022 14:44:47 +0100 +Subject: [PATCH 08/32] xen/grant-table: Only decrement the refcounter when + grant is fully unmapped + +The grant unmapping hypercall (GNTTABOP_unmap_grant_ref) is not a +simple revert of the changes done by the grant mapping hypercall +(GNTTABOP_map_grant_ref). + +Instead, it is possible to partially (or even not) clear some flags. +This will leave the grant is mapped until a future call where all +the flags would be cleared. + +XSA-380 introduced a refcounting that is meant to only be dropped +when the grant is fully unmapped. Unfortunately, unmap_common() will +decrement the refcount for every successful call. + +A consequence is a domain would be able to underflow the refcount +and trigger a BUG(). + +Looking at the code, it is not clear to me why a domain would +want to partially clear some flags in the grant-table. But as +this is part of the ABI, it is better to not change the behavior +for now. + +Fix it by checking if the maptrack handle has been released before +decrementing the refcounting. + +This is CVE-2022-23034 / XSA-394. + +Fixes: 9781b51efde2 ("gnttab: replace mapkind()") +Signed-off-by: Julien Grall <jgrall@amazon.com> +Reviewed-by: Jan Beulich <jbeulich@suse.com> +master commit: 975a8fb45ca186b3476e5656c6ad5dad1122dbfd +master date: 2022-01-25 13:25:49 +0100 +--- + xen/common/grant_table.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c +index 7b775a8c35..cbb2ce17c0 100644 +--- a/xen/common/grant_table.c ++++ b/xen/common/grant_table.c +@@ -1438,8 +1438,15 @@ unmap_common( + if ( put_handle ) + put_maptrack_handle(lgt, op->handle); + +- /* See the respective comment in map_grant_ref(). */ +- if ( rc == GNTST_okay && ld != rd && gnttab_need_iommu_mapping(ld) ) ++ /* ++ * map_grant_ref() will only increment the refcount (and update the ++ * IOMMU) once per mapping. So we only want to decrement it once the ++ * maptrack handle has been put, alongside the further IOMMU update. ++ * ++ * For the second and third check, see the respective comment in ++ * map_grant_ref(). ++ */ ++ if ( put_handle && ld != rd && gnttab_need_iommu_mapping(ld) ) + { + void **slot; + union maptrack_node node; +-- +2.35.2 + + +From ce49a1d6d819f4587436b4ff73334d3676c1aab6 Mon Sep 17 00:00:00 2001 +From: Julien Grall <jgrall@amazon.com> +Date: Tue, 25 Jan 2022 14:45:07 +0100 +Subject: [PATCH 09/32] passthrough/x86: stop pirq iteration immediately in + case of error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +pt_pirq_iterate() will iterate in batch over all the PIRQs. The outer +loop will bail out if 'rc' is non-zero but the inner loop will continue. + +This means 'rc' will get clobbered and we may miss any errors (such as +-ERESTART in the case of the callback pci_clean_dpci_irq()). + +This is CVE-2022-23035 / XSA-395. + +Fixes: c24536b636f2 ("replace d->nr_pirqs sized arrays with radix tree") +Fixes: f6dd295381f4 ("dpci: replace tasklet with softirq") +Signed-off-by: Julien Grall <jgrall@amazon.com> +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 9480a1a519cf016623f657dc544cb372a82b5708 +master date: 2022-01-25 13:27:02 +0100 +--- + xen/drivers/passthrough/io.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c +index 71eaf2c17e..b6e88ebc86 100644 +--- a/xen/drivers/passthrough/io.c ++++ b/xen/drivers/passthrough/io.c +@@ -810,7 +810,11 @@ int pt_pirq_iterate(struct domain *d, + + pirq = pirqs[i]->pirq; + if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) ) ++ { + rc = cb(d, pirq_dpci, arg); ++ if ( rc ) ++ break; ++ } + } + } while ( !rc && ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) ); + +-- +2.35.2 + + +From 9a8804a92fed77f77afe9fc525c6891bb60f68d3 Mon Sep 17 00:00:00 2001 +From: Bertrand Marquis <bertrand.marquis@arm.com> +Date: Tue, 15 Feb 2022 10:37:51 +0000 +Subject: [PATCH 10/32] xen/arm: Introduce new Arm processors + +Add some new processor identifiers in processor.h and sync Xen +definitions with status of Linux 5.17 (declared in +arch/arm64/include/asm/cputype.h). + +This is part of XSA-398 / CVE-2022-23960. + +Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> +Acked-by: Julien Grall <julien@xen.org> +(cherry picked from commit 35d1b85a6b43483f6bd007d48757434e54743e98) +--- + xen/include/asm-arm/processor.h | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h +index 87c8136022..17cc5cf486 100644 +--- a/xen/include/asm-arm/processor.h ++++ b/xen/include/asm-arm/processor.h +@@ -53,6 +53,7 @@ + #define ARM_CPU_PART_CORTEX_A17 0xC0E + #define ARM_CPU_PART_CORTEX_A15 0xC0F + #define ARM_CPU_PART_CORTEX_A53 0xD03 ++#define ARM_CPU_PART_CORTEX_A35 0xD04 + #define ARM_CPU_PART_CORTEX_A55 0xD05 + #define ARM_CPU_PART_CORTEX_A57 0xD07 + #define ARM_CPU_PART_CORTEX_A72 0xD08 +@@ -60,11 +61,20 @@ + #define ARM_CPU_PART_CORTEX_A75 0xD0A + #define ARM_CPU_PART_CORTEX_A76 0xD0B + #define ARM_CPU_PART_NEOVERSE_N1 0xD0C ++#define ARM_CPU_PART_CORTEX_A77 0xD0D ++#define ARM_CPU_PART_NEOVERSE_V1 0xD40 ++#define ARM_CPU_PART_CORTEX_A78 0xD41 ++#define ARM_CPU_PART_CORTEX_X1 0xD44 ++#define ARM_CPU_PART_CORTEX_A710 0xD47 ++#define ARM_CPU_PART_CORTEX_X2 0xD48 ++#define ARM_CPU_PART_NEOVERSE_N2 0xD49 ++#define ARM_CPU_PART_CORTEX_A78C 0xD4B + + #define MIDR_CORTEX_A12 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A12) + #define MIDR_CORTEX_A17 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A17) + #define MIDR_CORTEX_A15 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A15) + #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) ++#define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35) + #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55) + #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) + #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) +@@ -72,6 +82,14 @@ + #define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75) + #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) + #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) ++#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) ++#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1) ++#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) ++#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) ++#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) ++#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) ++#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) ++#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) + + /* MPIDR Multiprocessor Affinity Register */ + #define _MPIDR_UP (30) +-- +2.35.2 + + +From 03db21387b8653d663e8da89c964d611ba509130 Mon Sep 17 00:00:00 2001 +From: Bertrand Marquis <bertrand.marquis@arm.com> +Date: Tue, 15 Feb 2022 10:39:47 +0000 +Subject: [PATCH 11/32] xen/arm: move errata CSV2 check earlier + +CSV2 availability check is done after printing to the user that +workaround 1 will be used. Move the check before to prevent saying to the +user that workaround 1 is used when it is not because it is not needed. +This will also allow to reuse install_bp_hardening_vec function for +other use cases. + +Code previously returning "true", now returns "0" to conform to +enable_smccc_arch_workaround_1 returning an int and surrounding code +doing a "return 0" if workaround is not needed. + +This is part of XSA-398 / CVE-2022-23960. + +Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> +Reviewed-by: Julien Grall <julien@xen.org> +(cherry picked from commit 599616d70eb886b9ad0ef9d6b51693ce790504ba) +--- + xen/arch/arm/cpuerrata.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c +index f94bcf74cc..79620889b4 100644 +--- a/xen/arch/arm/cpuerrata.c ++++ b/xen/arch/arm/cpuerrata.c +@@ -102,13 +102,6 @@ install_bp_hardening_vec(const struct arm_cpu_capabilities *entry, + printk(XENLOG_INFO "CPU%u will %s on exception entry\n", + smp_processor_id(), desc); + +- /* +- * No need to install hardened vector when the processor has +- * ID_AA64PRF0_EL1.CSV2 set. +- */ +- if ( cpu_data[smp_processor_id()].pfr64.csv2 ) +- return true; +- + spin_lock(&bp_lock); + + /* +@@ -167,6 +160,13 @@ static int enable_smccc_arch_workaround_1(void *data) + if ( !entry->matches(entry) ) + return 0; + ++ /* ++ * No need to install hardened vector when the processor has ++ * ID_AA64PRF0_EL1.CSV2 set. ++ */ ++ if ( cpu_data[smp_processor_id()].pfr64.csv2 ) ++ return 0; ++ + if ( smccc_ver < SMCCC_VERSION(1, 1) ) + goto warn; + +-- +2.35.2 + + +From d99df7d50d366c7a8dc71f5bdc3454f469b00a00 Mon Sep 17 00:00:00 2001 +From: Bertrand Marquis <bertrand.marquis@arm.com> +Date: Wed, 23 Feb 2022 09:42:18 +0000 +Subject: [PATCH 12/32] xen/arm: Add ECBHB and CLEARBHB ID fields + +Introduce ID coprocessor register ID_AA64ISAR2_EL1. +Add definitions in cpufeature and sysregs of ECBHB field in mmfr1 and +CLEARBHB in isar2 ID coprocessor registers. + +This is part of XSA-398 / CVE-2022-23960. + +Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> +Acked-by: Julien Grall <julien@xen.org> +(cherry picked from commit 4b68d12d98b8790d8002fcc2c25a9d713374a4d7) +--- + xen/arch/arm/cpufeature.c | 1 + + xen/include/asm-arm/arm64/sysregs.h | 4 ++++ + xen/include/asm-arm/cpufeature.h | 20 +++++++++++++++++--- + 3 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c +index 44126dbf07..13dac7ccaf 100644 +--- a/xen/arch/arm/cpufeature.c ++++ b/xen/arch/arm/cpufeature.c +@@ -117,6 +117,7 @@ void identify_cpu(struct cpuinfo_arm *c) + + c->isa64.bits[0] = READ_SYSREG64(ID_AA64ISAR0_EL1); + c->isa64.bits[1] = READ_SYSREG64(ID_AA64ISAR1_EL1); ++ c->isa64.bits[2] = READ_SYSREG64(ID_AA64ISAR2_EL1); + #endif + + c->pfr32.bits[0] = READ_SYSREG32(ID_PFR0_EL1); +diff --git a/xen/include/asm-arm/arm64/sysregs.h b/xen/include/asm-arm/arm64/sysregs.h +index c60029d38f..cfd2e1d486 100644 +--- a/xen/include/asm-arm/arm64/sysregs.h ++++ b/xen/include/asm-arm/arm64/sysregs.h +@@ -57,6 +57,10 @@ + #define ICH_AP1R2_EL2 __AP1Rx_EL2(2) + #define ICH_AP1R3_EL2 __AP1Rx_EL2(3) + ++#ifndef ID_AA64ISAR2_EL1 ++#define ID_AA64ISAR2_EL1 S3_0_C0_C6_2 ++#endif ++ + /* Access to system registers */ + + #define READ_SYSREG32(name) ((uint32_t)READ_SYSREG64(name)) +diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeature.h +index 29753fee78..8519d2987b 100644 +--- a/xen/include/asm-arm/cpufeature.h ++++ b/xen/include/asm-arm/cpufeature.h +@@ -183,12 +183,26 @@ struct cpuinfo_arm { + unsigned long lo:4; + unsigned long pan:4; + unsigned long __res1:8; +- unsigned long __res2:32; ++ unsigned long __res2:28; ++ unsigned long ecbhb:4; + }; + } mm64; + +- struct { +- uint64_t bits[2]; ++ union { ++ uint64_t bits[3]; ++ struct { ++ /* ISAR0 */ ++ unsigned long __res0:64; ++ ++ /* ISAR1 */ ++ unsigned long __res1:64; ++ ++ /* ISAR2 */ ++ unsigned long __res3:28; ++ unsigned long clearbhb:4; ++ ++ unsigned long __res4:32; ++ }; + } isa64; + + #endif +-- +2.35.2 + + +From 47125f5fb2073abb9d5d3f65824cd066e7ec62f1 Mon Sep 17 00:00:00 2001 +From: Rahul Singh <rahul.singh@arm.com> +Date: Mon, 14 Feb 2022 18:47:32 +0000 +Subject: [PATCH 13/32] xen/arm: Add Spectre BHB handling + +This commit is adding Spectre BHB handling to Xen on Arm. +The commit is introducing new alternative code to be executed during +exception entry: +- SMCC workaround 3 call +- loop workaround (with 8, 24 or 32 iterations) +- use of new clearbhb instruction + +Cpuerrata is modified by this patch to apply the required workaround for +CPU affected by Spectre BHB when CONFIG_ARM64_HARDEN_BRANCH_PREDICTOR is +enabled. + +To do this the system previously used to apply smcc workaround 1 is +reused and new alternative code to be copied in the exception handler is +introduced. + +To define the type of workaround required by a processor, 4 new cpu +capabilities are introduced (for each number of loop and for smcc +workaround 3). + +When a processor is affected, enable_spectre_bhb_workaround is called +and if the processor does not have CSV2 set to 3 or ECBHB feature (which +would mean that the processor is doing what is required in hardware), +the proper code is enabled at exception entry. + +In the case where workaround 3 is not supported by the firmware, we +enable workaround 1 when possible as it will also mitigate Spectre BHB +on systems without CSV2. + +This is part of XSA-398 / CVE-2022-23960. + +Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> +Signed-off-by: Rahul Singh <rahul.singh@arm.com> +Acked-by: Julien Grall <julien@xen.org> +(cherry picked from commit 62c91eb66a2904eefb1d1d9642e3697a1e3c3a3c) +--- + xen/arch/arm/arm64/bpi.S | 32 +++++- + xen/arch/arm/cpuerrata.c | 170 +++++++++++++++++++++++++++-- + xen/include/asm-arm/arm64/macros.h | 5 + + xen/include/asm-arm/cpufeature.h | 6 +- + xen/include/asm-arm/smccc.h | 6 + + 5 files changed, 207 insertions(+), 12 deletions(-) + +diff --git a/xen/arch/arm/arm64/bpi.S b/xen/arch/arm/arm64/bpi.S +index d8743d955c..4e63825220 100644 +--- a/xen/arch/arm/arm64/bpi.S ++++ b/xen/arch/arm/arm64/bpi.S +@@ -58,16 +58,42 @@ ENTRY(__bp_harden_hyp_vecs_start) + .endr + ENTRY(__bp_harden_hyp_vecs_end) + +-ENTRY(__smccc_workaround_1_smc_start) ++.macro mitigate_spectre_bhb_loop count ++ENTRY(__mitigate_spectre_bhb_loop_start_\count) ++ stp x0, x1, [sp, #-16]! ++ mov x0, \count ++.Lspectre_bhb_loop\@: ++ b . + 4 ++ subs x0, x0, #1 ++ b.ne .Lspectre_bhb_loop\@ ++ sb ++ ldp x0, x1, [sp], #16 ++ENTRY(__mitigate_spectre_bhb_loop_end_\count) ++.endm ++ ++.macro smccc_workaround num smcc_id ++ENTRY(__smccc_workaround_smc_start_\num) + sub sp, sp, #(8 * 4) + stp x0, x1, [sp, #(8 * 2)] + stp x2, x3, [sp, #(8 * 0)] +- mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1_FID ++ mov w0, \smcc_id + smc #0 + ldp x2, x3, [sp, #(8 * 0)] + ldp x0, x1, [sp, #(8 * 2)] + add sp, sp, #(8 * 4) +-ENTRY(__smccc_workaround_1_smc_end) ++ENTRY(__smccc_workaround_smc_end_\num) ++.endm ++ ++ENTRY(__mitigate_spectre_bhb_clear_insn_start) ++ clearbhb ++ isb ++ENTRY(__mitigate_spectre_bhb_clear_insn_end) ++ ++mitigate_spectre_bhb_loop 8 ++mitigate_spectre_bhb_loop 24 ++mitigate_spectre_bhb_loop 32 ++smccc_workaround 1, #ARM_SMCCC_ARCH_WORKAROUND_1_FID ++smccc_workaround 3, #ARM_SMCCC_ARCH_WORKAROUND_3_FID + + /* + * Local variables: +diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c +index 79620889b4..8d9e977b77 100644 +--- a/xen/arch/arm/cpuerrata.c ++++ b/xen/arch/arm/cpuerrata.c +@@ -144,7 +144,16 @@ install_bp_hardening_vec(const struct arm_cpu_capabilities *entry, + return ret; + } + +-extern char __smccc_workaround_1_smc_start[], __smccc_workaround_1_smc_end[]; ++extern char __smccc_workaround_smc_start_1[], __smccc_workaround_smc_end_1[]; ++extern char __smccc_workaround_smc_start_3[], __smccc_workaround_smc_end_3[]; ++extern char __mitigate_spectre_bhb_clear_insn_start[], ++ __mitigate_spectre_bhb_clear_insn_end[]; ++extern char __mitigate_spectre_bhb_loop_start_8[], ++ __mitigate_spectre_bhb_loop_end_8[]; ++extern char __mitigate_spectre_bhb_loop_start_24[], ++ __mitigate_spectre_bhb_loop_end_24[]; ++extern char __mitigate_spectre_bhb_loop_start_32[], ++ __mitigate_spectre_bhb_loop_end_32[]; + + static int enable_smccc_arch_workaround_1(void *data) + { +@@ -176,8 +185,8 @@ static int enable_smccc_arch_workaround_1(void *data) + if ( (int)res.a0 < 0 ) + goto warn; + +- return !install_bp_hardening_vec(entry,__smccc_workaround_1_smc_start, +- __smccc_workaround_1_smc_end, ++ return !install_bp_hardening_vec(entry,__smccc_workaround_smc_start_1, ++ __smccc_workaround_smc_end_1, + "call ARM_SMCCC_ARCH_WORKAROUND_1"); + + warn: +@@ -192,6 +201,93 @@ warn: + return 0; + } + ++/* ++ * Spectre BHB Mitigation ++ * ++ * CPU is either: ++ * - Having CVS2.3 so it is not affected. ++ * - Having ECBHB and is clearing the branch history buffer when an exception ++ * to a different exception level is happening so no mitigation is needed. ++ * - Mitigating using a loop on exception entry (number of loop depending on ++ * the CPU). ++ * - Mitigating using the firmware. ++ */ ++static int enable_spectre_bhb_workaround(void *data) ++{ ++ const struct arm_cpu_capabilities *entry = data; ++ ++ /* ++ * Enable callbacks are called on every CPU based on the capabilities, so ++ * double-check whether the CPU matches the entry. ++ */ ++ if ( !entry->matches(entry) ) ++ return 0; ++ ++ if ( cpu_data[smp_processor_id()].pfr64.csv2 == 3 ) ++ return 0; ++ ++ if ( cpu_data[smp_processor_id()].mm64.ecbhb ) ++ return 0; ++ ++ if ( cpu_data[smp_processor_id()].isa64.clearbhb ) ++ return !install_bp_hardening_vec(entry, ++ __mitigate_spectre_bhb_clear_insn_start, ++ __mitigate_spectre_bhb_clear_insn_end, ++ "use clearBHB instruction"); ++ ++ /* Apply solution depending on hwcaps set on arm_errata */ ++ if ( cpus_have_cap(ARM_WORKAROUND_BHB_LOOP_8) ) ++ return !install_bp_hardening_vec(entry, ++ __mitigate_spectre_bhb_loop_start_8, ++ __mitigate_spectre_bhb_loop_end_8, ++ "use 8 loops workaround"); ++ ++ if ( cpus_have_cap(ARM_WORKAROUND_BHB_LOOP_24) ) ++ return !install_bp_hardening_vec(entry, ++ __mitigate_spectre_bhb_loop_start_24, ++ __mitigate_spectre_bhb_loop_end_24, ++ "use 24 loops workaround"); ++ ++ if ( cpus_have_cap(ARM_WORKAROUND_BHB_LOOP_32) ) ++ return !install_bp_hardening_vec(entry, ++ __mitigate_spectre_bhb_loop_start_32, ++ __mitigate_spectre_bhb_loop_end_32, ++ "use 32 loops workaround"); ++ ++ if ( cpus_have_cap(ARM_WORKAROUND_BHB_SMCC_3) ) ++ { ++ struct arm_smccc_res res; ++ ++ if ( smccc_ver < SMCCC_VERSION(1, 1) ) ++ goto warn; ++ ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID, ++ ARM_SMCCC_ARCH_WORKAROUND_3_FID, &res); ++ /* The return value is in the lower 32-bits. */ ++ if ( (int)res.a0 < 0 ) ++ { ++ /* ++ * On processor affected with CSV2=0, workaround 1 will mitigate ++ * both Spectre v2 and BHB so use it when available ++ */ ++ if ( enable_smccc_arch_workaround_1(data) ) ++ return 1; ++ ++ goto warn; ++ } ++ ++ return !install_bp_hardening_vec(entry,__smccc_workaround_smc_start_3, ++ __smccc_workaround_smc_end_3, ++ "call ARM_SMCCC_ARCH_WORKAROUND_3"); ++ } ++ ++warn: ++ printk_once("**** No support for any spectre BHB workaround. ****\n" ++ "**** Please update your firmware. ****\n"); ++ ++ return 0; ++} ++ + #endif /* CONFIG_ARM64_HARDEN_BRANCH_PREDICTOR */ + + /* Hardening Branch predictor code for Arm32 */ +@@ -437,19 +533,77 @@ static const struct arm_cpu_capabilities arm_errata[] = { + }, + { + .capability = ARM_HARDEN_BRANCH_PREDICTOR, +- MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), ++ MIDR_RANGE(MIDR_CORTEX_A72, 0, 1 << MIDR_VARIANT_SHIFT), + .enable = enable_smccc_arch_workaround_1, + }, + { +- .capability = ARM_HARDEN_BRANCH_PREDICTOR, ++ .capability = ARM_WORKAROUND_BHB_SMCC_3, + MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), +- .enable = enable_smccc_arch_workaround_1, ++ .enable = enable_spectre_bhb_workaround, + }, + { +- .capability = ARM_HARDEN_BRANCH_PREDICTOR, ++ .capability = ARM_WORKAROUND_BHB_SMCC_3, + MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), +- .enable = enable_smccc_arch_workaround_1, ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ /* spectre BHB */ ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_8, ++ MIDR_RANGE(MIDR_CORTEX_A72, 1 << MIDR_VARIANT_SHIFT, ++ (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_24, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_24, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), ++ .enable = enable_spectre_bhb_workaround, + }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_24, ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ { ++ .capability = ARM_WORKAROUND_BHB_LOOP_32, ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), ++ .enable = enable_spectre_bhb_workaround, ++ }, ++ + #endif + #ifdef CONFIG_ARM32_HARDEN_BRANCH_PREDICTOR + { +diff --git a/xen/include/asm-arm/arm64/macros.h b/xen/include/asm-arm/arm64/macros.h +index f981b4f43e..5100aed6e3 100644 +--- a/xen/include/asm-arm/arm64/macros.h ++++ b/xen/include/asm-arm/arm64/macros.h +@@ -21,6 +21,11 @@ + ldr \dst, [\dst, \tmp] + .endm + ++ /* clearbhb instruction clearing the branch history */ ++ .macro clearbhb ++ hint #22 ++ .endm ++ + /* + * Register aliases. + */ +diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeature.h +index 8519d2987b..a1fa3bc1cf 100644 +--- a/xen/include/asm-arm/cpufeature.h ++++ b/xen/include/asm-arm/cpufeature.h +@@ -46,8 +46,12 @@ + #define ARM_SMCCC_1_1 8 + #define ARM64_WORKAROUND_AT_SPECULATE 9 + #define ARM_WORKAROUND_858921 10 ++#define ARM_WORKAROUND_BHB_LOOP_8 11 ++#define ARM_WORKAROUND_BHB_LOOP_24 12 ++#define ARM_WORKAROUND_BHB_LOOP_32 13 ++#define ARM_WORKAROUND_BHB_SMCC_3 14 + +-#define ARM_NCAPS 11 ++#define ARM_NCAPS 15 + + #ifndef __ASSEMBLY__ + +diff --git a/xen/include/asm-arm/smccc.h b/xen/include/asm-arm/smccc.h +index 126399dd70..2abbffc3bd 100644 +--- a/xen/include/asm-arm/smccc.h ++++ b/xen/include/asm-arm/smccc.h +@@ -334,6 +334,12 @@ void __arm_smccc_1_0_smc(register_t a0, register_t a1, register_t a2, + ARM_SMCCC_OWNER_ARCH, \ + 0x7FFF) + ++#define ARM_SMCCC_ARCH_WORKAROUND_3_FID \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_CONV_32, \ ++ ARM_SMCCC_OWNER_ARCH, \ ++ 0x3FFF) ++ + /* SMCCC error codes */ + #define ARM_SMCCC_NOT_REQUIRED (-2) + #define ARM_SMCCC_ERR_UNKNOWN_FUNCTION (-1) +-- +2.35.2 + + +From fbabb62dd9e57180400f145a8756624c82de888f Mon Sep 17 00:00:00 2001 +From: Bertrand Marquis <bertrand.marquis@arm.com> +Date: Thu, 17 Feb 2022 14:52:54 +0000 +Subject: [PATCH 14/32] xen/arm: Allow to discover and use + SMCCC_ARCH_WORKAROUND_3 + +Allow guest to discover whether or not SMCCC_ARCH_WORKAROUND_3 is +supported and create a fastpath in the code to handle guests request to +do the workaround. + +The function SMCCC_ARCH_WORKAROUND_3 will be called by the guest for +flushing the branch history. So we want the handling to be as fast as +possible. + +As the mitigation is applied on every guest exit, we can check for the +call before saving all context and return very early. + +This is part of XSA-398 / CVE-2022-23960. + +Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> +Reviewed-by: Julien Grall <julien@xen.org> +(cherry picked from commit c0a56ea0fd92ecb471936b7355ddbecbaea3707c) +--- + xen/arch/arm/arm64/entry.S | 21 ++++++++++++++------- + xen/arch/arm/vsmc.c | 5 +++++ + 2 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S +index 175ea2981e..a8c2145067 100644 +--- a/xen/arch/arm/arm64/entry.S ++++ b/xen/arch/arm/arm64/entry.S +@@ -338,16 +338,26 @@ guest_sync: + cbnz x1, guest_sync_slowpath /* should be 0 for HVC #0 */ + + /* +- * Fastest path possible for ARM_SMCCC_ARCH_WORKAROUND_1. +- * The workaround has already been applied on the exception ++ * Fastest path possible for ARM_SMCCC_ARCH_WORKAROUND_1 and ++ * ARM_SMCCC_ARCH_WORKAROUND_3. ++ * The workaround needed has already been applied on the exception + * entry from the guest, so let's quickly get back to the guest. + * + * Note that eor is used because the function identifier cannot + * be encoded as an immediate for cmp. + */ + eor w0, w0, #ARM_SMCCC_ARCH_WORKAROUND_1_FID +- cbnz w0, check_wa2 ++ cbz w0, fastpath_out_workaround + ++ /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ ++ eor w0, w0, #(ARM_SMCCC_ARCH_WORKAROUND_1_FID ^ ARM_SMCCC_ARCH_WORKAROUND_2_FID) ++ cbz w0, wa2_ssbd ++ ++ /* Fastpath out for ARM_SMCCC_ARCH_WORKAROUND_3 */ ++ eor w0, w0, #(ARM_SMCCC_ARCH_WORKAROUND_2_FID ^ ARM_SMCCC_ARCH_WORKAROUND_3_FID) ++ cbnz w0, guest_sync_slowpath ++ ++fastpath_out_workaround: + /* + * Clobber both x0 and x1 to prevent leakage. Note that thanks + * the eor, x0 = 0. +@@ -356,10 +366,7 @@ guest_sync: + eret + sb + +-check_wa2: +- /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ +- eor w0, w0, #(ARM_SMCCC_ARCH_WORKAROUND_1_FID ^ ARM_SMCCC_ARCH_WORKAROUND_2_FID) +- cbnz w0, guest_sync_slowpath ++wa2_ssbd: + #ifdef CONFIG_ARM_SSBD + alternative_cb arm_enable_wa2_handling + b wa2_end +diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c +index a36db15fff..b633ff2fe8 100644 +--- a/xen/arch/arm/vsmc.c ++++ b/xen/arch/arm/vsmc.c +@@ -124,6 +124,10 @@ static bool handle_arch(struct cpu_user_regs *regs) + break; + } + break; ++ case ARM_SMCCC_ARCH_WORKAROUND_3_FID: ++ if ( cpus_have_cap(ARM_WORKAROUND_BHB_SMCC_3) ) ++ ret = 0; ++ break; + } + + set_user_reg(regs, 0, ret); +@@ -132,6 +136,7 @@ static bool handle_arch(struct cpu_user_regs *regs) + } + + case ARM_SMCCC_ARCH_WORKAROUND_1_FID: ++ case ARM_SMCCC_ARCH_WORKAROUND_3_FID: + /* No return value */ + return true; + +-- +2.35.2 + + +From 7b9814b250a5a28277bd0866d341a5cfc0f4c1ac Mon Sep 17 00:00:00 2001 +From: Andrew Cooper <andrew.cooper3@citrix.com> +Date: Mon, 7 Mar 2022 16:35:52 +0000 +Subject: [PATCH 15/32] x86/spec-ctrl: Cease using thunk=lfence on AMD + +AMD have updated their Spectre v2 guidance, and lfence/jmp is no longer +considered safe. AMD are recommending using retpoline everywhere. + +Update the default heuristics to never select THUNK_LFENCE. + +This is part of XSA-398 / CVE-2021-26401. + +Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> +Reviewed-by: Jan Beulich <jbeulich@suse.com> +(cherry picked from commit 8d03080d2a339840d3a59e0932a94f804e45110d) +--- + docs/misc/xen-command-line.pandoc | 6 +++--- + xen/arch/x86/spec_ctrl.c | 10 ++-------- + 2 files changed, 5 insertions(+), 11 deletions(-) + +diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc +index cf9dea62db..eead69ada2 100644 +--- a/docs/misc/xen-command-line.pandoc ++++ b/docs/misc/xen-command-line.pandoc +@@ -2077,9 +2077,9 @@ to use. + + If Xen was compiled with INDIRECT_THUNK support, `bti-thunk=` can be used to + select which of the thunks gets patched into the `__x86_indirect_thunk_%reg` +-locations. The default thunk is `retpoline` (generally preferred for Intel +-hardware), with the alternatives being `jmp` (a `jmp *%reg` gadget, minimal +-overhead), and `lfence` (an `lfence; jmp *%reg` gadget, preferred for AMD). ++locations. The default thunk is `retpoline` (generally preferred), with the ++alternatives being `jmp` (a `jmp *%reg` gadget, minimal overhead), and ++`lfence` (an `lfence; jmp *%reg` gadget). + + On hardware supporting IBRS (Indirect Branch Restricted Speculation), the + `ibrs=` option can be used to force or prevent Xen using the feature itself. +diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c +index 1cfd02d7d7..7447d4a8e5 100644 +--- a/xen/arch/x86/spec_ctrl.c ++++ b/xen/arch/x86/spec_ctrl.c +@@ -908,16 +908,10 @@ void __init init_speculation_mitigations(void) + if ( IS_ENABLED(CONFIG_INDIRECT_THUNK) ) + { + /* +- * AMD's recommended mitigation is to set lfence as being dispatch +- * serialising, and to use IND_THUNK_LFENCE. +- */ +- if ( cpu_has_lfence_dispatch ) +- thunk = THUNK_LFENCE; +- /* +- * On Intel hardware, we'd like to use retpoline in preference to ++ * On all hardware, we'd like to use retpoline in preference to + * IBRS, but only if it is safe on this hardware. + */ +- else if ( retpoline_safe(caps) ) ++ if ( retpoline_safe(caps) ) + thunk = THUNK_RETPOLINE; + else if ( boot_cpu_has(X86_FEATURE_IBRSB) ) + ibrs = true; +-- +2.35.2 + + +From 8ed46cc1ef14fb8463cc847d82cbd2491054547a Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:19:40 +0200 +Subject: [PATCH 16/32] VT-d: split domid map cleanup check into a function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This logic will want invoking from elsewhere. + +No functional change intended. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +master commit: 9fdc10abe9457e4c9879a266f82372cb08e88ffb +master date: 2021-11-24 11:06:20 +0100 +--- + xen/drivers/passthrough/vtd/iommu.c | 70 +++++++++++++++++++---------- + 1 file changed, 47 insertions(+), 23 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index af8b9ca0e4..234a4fbae5 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -147,6 +147,51 @@ static void cleanup_domid_map(struct domain *domain, struct vtd_iommu *iommu) + } + } + ++static bool any_pdev_behind_iommu(const struct domain *d, ++ const struct pci_dev *exclude, ++ const struct vtd_iommu *iommu) ++{ ++ const struct pci_dev *pdev; ++ ++ for_each_pdev ( d, pdev ) ++ { ++ const struct acpi_drhd_unit *drhd; ++ ++ if ( pdev == exclude ) ++ continue; ++ ++ drhd = acpi_find_matched_drhd_unit(pdev); ++ if ( drhd && drhd->iommu == iommu ) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * If no other devices under the same iommu owned by this domain, ++ * clear iommu in iommu_bitmap and clear domain_id in domid_bitmap. ++ */ ++static void check_cleanup_domid_map(struct domain *d, ++ const struct pci_dev *exclude, ++ struct vtd_iommu *iommu) ++{ ++ bool found = any_pdev_behind_iommu(d, exclude, iommu); ++ ++ /* ++ * Hidden devices are associated with DomXEN but usable by the hardware ++ * domain. Hence they need considering here as well. ++ */ ++ if ( !found && is_hardware_domain(d) ) ++ found = any_pdev_behind_iommu(dom_xen, exclude, iommu); ++ ++ if ( !found ) ++ { ++ clear_bit(iommu->index, &dom_iommu(d)->arch.iommu_bitmap); ++ cleanup_domid_map(d, iommu); ++ } ++} ++ + static int iommus_incoherent; + + static void sync_cache(const void *addr, unsigned int size) +@@ -1679,7 +1724,6 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + struct vtd_iommu *iommu; + int ret = 0; + u8 seg = pdev->seg, bus = pdev->bus, tmp_bus, tmp_devfn, secbus; +- int found = 0; + + drhd = acpi_find_matched_drhd_unit(pdev); + if ( !drhd ) +@@ -1763,28 +1807,8 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + if ( ret ) + goto out; + +- /* +- * if no other devices under the same iommu owned by this domain, +- * clear iommu in iommu_bitmap and clear domain_id in domid_bitmp +- */ +- for_each_pdev ( domain, pdev ) +- { +- if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn ) +- continue; +- +- drhd = acpi_find_matched_drhd_unit(pdev); +- if ( drhd && drhd->iommu == iommu ) +- { +- found = 1; +- break; +- } +- } +- +- if ( found == 0 ) +- { +- clear_bit(iommu->index, &dom_iommu(domain)->arch.iommu_bitmap); +- cleanup_domid_map(domain, iommu); +- } ++ if ( !ret ) ++ check_cleanup_domid_map(domain, pdev, iommu); + + out: + return ret; +-- +2.35.2 + + +From 2ce2aec8c148a0a291eae2a0631802e0ffb42133 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com> +Date: Tue, 5 Apr 2022 15:20:10 +0200 +Subject: [PATCH 17/32] x86/hap: do not switch on log dirty for VRAM tracking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +XEN_DMOP_track_dirty_vram possibly calls into paging_log_dirty_enable +when using HAP mode, and it can interact badly with other ongoing +paging domctls, as XEN_DMOP_track_dirty_vram is not holding the domctl +lock. + +This was detected as a result of the following assert triggering when +doing repeated migrations of a HAP HVM domain with a stubdom: + +Assertion 'd->arch.paging.log_dirty.allocs == 0' failed at paging.c:198 +----[ Xen-4.17-unstable x86_64 debug=y Not tainted ]---- +CPU: 34 +RIP: e008:[<ffff82d040314b3b>] arch/x86/mm/paging.c#paging_free_log_dirty_bitmap+0x606/0x6 +RFLAGS: 0000000000010206 CONTEXT: hypervisor (d0v23) +[...] +Xen call trace: + [<ffff82d040314b3b>] R arch/x86/mm/paging.c#paging_free_log_dirty_bitmap+0x606/0x63a + [<ffff82d040279f96>] S xsm/flask/hooks.c#domain_has_perm+0x5a/0x67 + [<ffff82d04031577f>] F paging_domctl+0x251/0xd41 + [<ffff82d04031640c>] F paging_domctl_continuation+0x19d/0x202 + [<ffff82d0403202fa>] F pv_hypercall+0x150/0x2a7 + [<ffff82d0403a729d>] F lstar_enter+0x12d/0x140 + +Such assert triggered because the stubdom used +XEN_DMOP_track_dirty_vram while dom0 was in the middle of executing +XEN_DOMCTL_SHADOW_OP_OFF, and so log dirty become enabled while +retiring the old structures, thus leading to new entries being +populated in already clear slots. + +Fix this by not enabling log dirty for VRAM tracking, similar to what +is done when using shadow instead of HAP. Call +p2m_enable_hardware_log_dirty when enabling VRAM tracking in order to +get some hardware assistance if available. As a side effect the memory +pressure on the p2m pool should go down if only VRAM tracking is +enabled, as the dirty bitmap is no longer allocated. + +Note that paging_log_dirty_range (used to get the dirty bitmap for +VRAM tracking) doesn't use the log dirty bitmap, and instead relies on +checking whether each gfn on the range has been switched from +p2m_ram_logdirty to p2m_ram_rw in order to account for dirty pages. + +This is CVE-2022-26356 / XSA-397. + +Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Jan Beulich <jbeulich@suse.com> +master commit: 4f4db53784d912c4f409a451c36ebfd4754e0a42 +master date: 2022-04-05 14:11:30 +0200 +--- + xen/arch/x86/mm/hap/hap.c | 11 ++++------- + xen/arch/x86/mm/paging.c | 2 +- + xen/include/asm-x86/paging.h | 3 --- + 3 files changed, 5 insertions(+), 11 deletions(-) + +diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c +index 3d93f3451c..9aac006d65 100644 +--- a/xen/arch/x86/mm/hap/hap.c ++++ b/xen/arch/x86/mm/hap/hap.c +@@ -69,13 +69,6 @@ int hap_track_dirty_vram(struct domain *d, + { + int size = (nr + BITS_PER_BYTE - 1) / BITS_PER_BYTE; + +- if ( !paging_mode_log_dirty(d) ) +- { +- rc = paging_log_dirty_enable(d, false); +- if ( rc ) +- goto out; +- } +- + rc = -ENOMEM; + dirty_bitmap = vzalloc(size); + if ( !dirty_bitmap ) +@@ -107,6 +100,10 @@ int hap_track_dirty_vram(struct domain *d, + + paging_unlock(d); + ++ domain_pause(d); ++ p2m_enable_hardware_log_dirty(d); ++ domain_unpause(d); ++ + if ( oend > ostart ) + p2m_change_type_range(d, ostart, oend, + p2m_ram_logdirty, p2m_ram_rw); +diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c +index 469bb76429..8596e52458 100644 +--- a/xen/arch/x86/mm/paging.c ++++ b/xen/arch/x86/mm/paging.c +@@ -209,7 +209,7 @@ static int paging_free_log_dirty_bitmap(struct domain *d, int rc) + return rc; + } + +-int paging_log_dirty_enable(struct domain *d, bool log_global) ++static int paging_log_dirty_enable(struct domain *d, bool log_global) + { + int ret; + +diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h +index 7544f73121..a16929eaa7 100644 +--- a/xen/include/asm-x86/paging.h ++++ b/xen/include/asm-x86/paging.h +@@ -156,9 +156,6 @@ void paging_log_dirty_range(struct domain *d, + unsigned long nr, + uint8_t *dirty_bitmap); + +-/* enable log dirty */ +-int paging_log_dirty_enable(struct domain *d, bool log_global); +- + /* log dirty initialization */ + void paging_log_dirty_init(struct domain *d, const struct log_dirty_ops *ops); + +-- +2.35.2 + + +From 920e93df4e16c03811665e459c414feced6bc9b6 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:20:42 +0200 +Subject: [PATCH 18/32] VT-d: correct ordering of operations in + cleanup_domid_map() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function may be called without any locks held (leaving aside the +domctl one, which we surely don't want to depend on here), so needs to +play safe wrt other accesses to domid_map[] and domid_bitmap[]. This is +to avoid context_set_domain_id()'s writing of domid_map[] to be reset to +zero right away in the case of it racing the freeing of a DID. + +For the interaction with context_set_domain_id() and did_to_domain_id() +see the code comment. + +{check_,}cleanup_domid_map() are called with pcidevs_lock held or during +domain cleanup only (and pcidevs_lock is also held around +context_set_domain_id()), i.e. racing calls with the same (dom, iommu) +tuple cannot occur. + +domain_iommu_domid(), besides its use by cleanup_domid_map(), has its +result used only to control flushing, and hence a stale result would +only lead to a stray extra flush. + +This is CVE-2022-26357 / XSA-399. + +Fixes: b9c20c78789f ("VT-d: per-iommu domain-id") +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: d9eca7bb6c6636eb87bb17b08ba7de270f47ecd0 +master date: 2022-04-05 14:12:27 +0200 +--- + xen/drivers/passthrough/vtd/iommu.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index 234a4fbae5..68f9a524b8 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -142,8 +142,14 @@ static void cleanup_domid_map(struct domain *domain, struct vtd_iommu *iommu) + + if ( iommu_domid >= 0 ) + { ++ /* ++ * Update domid_map[] /before/ domid_bitmap[] to avoid a race with ++ * context_set_domain_id(), setting the slot to DOMID_INVALID for ++ * ->domid_map[] reads to produce a suitable value while the bit is ++ * still set. ++ */ ++ iommu->domid_map[iommu_domid] = DOMID_INVALID; + clear_bit(iommu_domid, iommu->domid_bitmap); +- iommu->domid_map[iommu_domid] = 0; + } + } + +-- +2.35.2 + + +From 650b888c8a0a03d796632597e6adfd0075f13954 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:21:21 +0200 +Subject: [PATCH 19/32] VT-d: fix (de)assign ordering when RMRRs are in use +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the event that the RMRR mappings are essential for device operation, +they should be established before updating the device's context entry, +while they should be torn down only after the device's context entry was +successfully updated. + +Also adjust a related log message. + +This is CVE-2022-26358 / part of XSA-400. + +Fixes: 8b99f4400b69 ("VT-d: fix RMRR related error handling") +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +master commit: 78a40f8b5dfa1a3aec43528663f39473d4429101 +master date: 2022-04-05 14:15:33 +0200 +--- + xen/drivers/passthrough/vtd/iommu.c | 56 ++++++++++++++++++----------- + 1 file changed, 36 insertions(+), 20 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index 68f9a524b8..50e21bf1d9 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -2392,6 +2392,10 @@ static int reassign_device_ownership( + { + int ret; + ++ ret = domain_context_unmap(source, devfn, pdev); ++ if ( ret ) ++ return ret; ++ + /* + * Devices assigned to untrusted domains (here assumed to be any domU) + * can attempt to send arbitrary LAPIC/MSI messages. We are unprotected +@@ -2428,10 +2432,6 @@ static int reassign_device_ownership( + } + } + +- ret = domain_context_unmap(source, devfn, pdev); +- if ( ret ) +- return ret; +- + if ( devfn == pdev->devfn && pdev->domain != dom_io ) + { + list_move(&pdev->domain_list, &dom_io->pdev_list); +@@ -2508,9 +2508,8 @@ static int intel_iommu_assign_device( + } + } + +- ret = reassign_device_ownership(s, d, devfn, pdev); +- if ( ret || d == dom_io ) +- return ret; ++ if ( d == dom_io ) ++ return reassign_device_ownership(s, d, devfn, pdev); + + /* Setup rmrr identity mapping */ + for_each_rmrr_device( rmrr, bdf, i ) +@@ -2523,20 +2522,37 @@ static int intel_iommu_assign_device( + rmrr->end_address, flag); + if ( ret ) + { +- int rc; +- +- rc = reassign_device_ownership(d, s, devfn, pdev); + printk(XENLOG_G_ERR VTDPREFIX +- " cannot map reserved region (%"PRIx64",%"PRIx64"] for Dom%d (%d)\n", +- rmrr->base_address, rmrr->end_address, +- d->domain_id, ret); +- if ( rc ) +- { +- printk(XENLOG_ERR VTDPREFIX +- " failed to reclaim %04x:%02x:%02x.%u from %pd (%d)\n", +- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), d, rc); +- domain_crash(d); +- } ++ "%pd: cannot map reserved region [%"PRIx64",%"PRIx64"]: %d\n", ++ d, rmrr->base_address, rmrr->end_address, ret); ++ break; ++ } ++ } ++ } ++ ++ if ( !ret ) ++ ret = reassign_device_ownership(s, d, devfn, pdev); ++ ++ /* See reassign_device_ownership() for the hwdom aspect. */ ++ if ( !ret || is_hardware_domain(d) ) ++ return ret; ++ ++ for_each_rmrr_device( rmrr, bdf, i ) ++ { ++ if ( rmrr->segment == seg && ++ PCI_BUS(bdf) == bus && ++ PCI_DEVFN2(bdf) == devfn ) ++ { ++ int rc = iommu_identity_mapping(d, p2m_access_x, ++ rmrr->base_address, ++ rmrr->end_address, 0); ++ ++ if ( rc && rc != -ENOENT ) ++ { ++ printk(XENLOG_ERR VTDPREFIX ++ "%pd: cannot unmap reserved region [%"PRIx64",%"PRIx64"]: %d\n", ++ d, rmrr->base_address, rmrr->end_address, rc); ++ domain_crash(d); + break; + } + } +-- +2.35.2 + + +From 81918cead1a5c2c3fb6648b078501af81f520849 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:22:31 +0200 +Subject: [PATCH 20/32] VT-d: fix add/remove ordering when RMRRs are in use +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the event that the RMRR mappings are essential for device operation, +they should be established before updating the device's context entry, +while they should be torn down only after the device's context entry was +successfully cleared. + +Also switch to %pd in related log messages. + +Fixes: fa88cfadf918 ("vt-d: Map RMRR in intel_iommu_add_device() if the device has RMRR") +Fixes: 8b99f4400b69 ("VT-d: fix RMRR related error handling") +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +master commit: 3221f270cf2eba0a22fd4f92319d664eacb92889 +master date: 2022-04-05 14:16:10 +0200 +--- + xen/drivers/passthrough/vtd/iommu.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index 50e21bf1d9..f7d40414ef 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -1993,14 +1993,6 @@ static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev) + if ( !pdev->domain ) + return -EINVAL; + +- ret = domain_context_mapping(pdev->domain, devfn, pdev); +- if ( ret ) +- { +- dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n", +- pdev->domain->domain_id); +- return ret; +- } +- + for_each_rmrr_device ( rmrr, bdf, i ) + { + if ( rmrr->segment == pdev->seg && +@@ -2017,12 +2009,17 @@ static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev) + rmrr->base_address, rmrr->end_address, + 0); + if ( ret ) +- dprintk(XENLOG_ERR VTDPREFIX, "d%d: RMRR mapping failed\n", +- pdev->domain->domain_id); ++ dprintk(XENLOG_ERR VTDPREFIX, "%pd: RMRR mapping failed\n", ++ pdev->domain); + } + } + +- return 0; ++ ret = domain_context_mapping(pdev->domain, devfn, pdev); ++ if ( ret ) ++ dprintk(XENLOG_ERR VTDPREFIX, "%pd: context mapping failed\n", ++ pdev->domain); ++ ++ return ret; + } + + static int intel_iommu_enable_device(struct pci_dev *pdev) +@@ -2044,11 +2041,15 @@ static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) + { + struct acpi_rmrr_unit *rmrr; + u16 bdf; +- int i; ++ int ret, i; + + if ( !pdev->domain ) + return -EINVAL; + ++ ret = domain_context_unmap(pdev->domain, devfn, pdev); ++ if ( ret ) ++ return ret; ++ + for_each_rmrr_device ( rmrr, bdf, i ) + { + if ( rmrr->segment != pdev->seg || +@@ -2064,7 +2065,7 @@ static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) + rmrr->end_address, 0); + } + +- return domain_context_unmap(pdev->domain, devfn, pdev); ++ return 0; + } + + static int __hwdom_init setup_hwdom_device(u8 devfn, struct pci_dev *pdev) +-- +2.35.2 + + +From 33c13654cb6d7d2a5731614f55aace4866c93d97 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:23:26 +0200 +Subject: [PATCH 21/32] VT-d: drop ownership checking from + domain_context_mapping_one() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Despite putting in quite a bit of effort it was not possible to +establish why exactly this code exists (beyond possibly sanity +checking). Instead of a subsequent change further complicating this +logic, simply get rid of it. + +Take the opportunity and move the respective unmap_vtd_domain_page() out +of the locked region. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +master commit: a680b8134b2d1828bbbf443a97feea66e8a85c75 +master date: 2022-04-05 14:17:21 +0200 +--- + xen/drivers/passthrough/vtd/iommu.c | 66 +---------------------------- + 1 file changed, 2 insertions(+), 64 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index f7d40414ef..b729ae173a 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -114,28 +114,6 @@ static int context_set_domain_id(struct context_entry *context, + return 0; + } + +-static int context_get_domain_id(struct context_entry *context, +- struct vtd_iommu *iommu) +-{ +- unsigned long dom_index, nr_dom; +- int domid = -1; +- +- if (iommu && context) +- { +- nr_dom = cap_ndoms(iommu->cap); +- +- dom_index = context_domain_id(*context); +- +- if ( dom_index < nr_dom && iommu->domid_map ) +- domid = iommu->domid_map[dom_index]; +- else +- dprintk(XENLOG_DEBUG VTDPREFIX, +- "dom_index %lu exceeds nr_dom %lu or iommu has no domid_map\n", +- dom_index, nr_dom); +- } +- return domid; +-} +- + static void cleanup_domid_map(struct domain *domain, struct vtd_iommu *iommu) + { + int iommu_domid = domain_iommu_domid(domain, iommu); +@@ -1392,49 +1370,9 @@ int domain_context_mapping_one( + + if ( context_present(*context) ) + { +- int res = 0; +- +- /* Try to get domain ownership from device structure. If that's +- * not available, try to read it from the context itself. */ +- if ( pdev ) +- { +- if ( pdev->domain != domain ) +- { +- printk(XENLOG_G_INFO VTDPREFIX +- "d%d: %04x:%02x:%02x.%u owned by d%d!", +- domain->domain_id, +- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), +- pdev->domain ? pdev->domain->domain_id : -1); +- res = -EINVAL; +- } +- } +- else +- { +- int cdomain; +- cdomain = context_get_domain_id(context, iommu); +- +- if ( cdomain < 0 ) +- { +- printk(XENLOG_G_WARNING VTDPREFIX +- "d%d: %04x:%02x:%02x.%u mapped, but can't find owner!\n", +- domain->domain_id, +- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); +- res = -EINVAL; +- } +- else if ( cdomain != domain->domain_id ) +- { +- printk(XENLOG_G_INFO VTDPREFIX +- "d%d: %04x:%02x:%02x.%u already mapped to d%d!", +- domain->domain_id, +- seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), +- cdomain); +- res = -EINVAL; +- } +- } +- +- unmap_vtd_domain_page(context_entries); + spin_unlock(&iommu->lock); +- return res; ++ unmap_vtd_domain_page(context_entries); ++ return 0; + } + + if ( iommu_hwdom_passthrough && is_hardware_domain(domain) ) +-- +2.35.2 + + +From 235aa158e0f71ee2bf20155ce6b0b429acf59d37 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:23:57 +0200 +Subject: [PATCH 22/32] VT-d: re-assign devices directly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Devices with RMRRs, due to it being unspecified how/when the specified +memory regions may get accessed, may not be left disconnected from their +respective mappings (as long as it's not certain that the device has +been fully quiesced). Hence rather than unmapping the old context and +then mapping the new one, re-assignment needs to be done in a single +step. + +This is CVE-2022-26359 / part of XSA-400. + +Reported-by: Roger Pau Monné <roger.pau@citrix.com> + +Similarly quarantining scratch-page mode relies on page tables to be +continuously wired up. + +To avoid complicating things more than necessary, treat all devices +mostly equally, i.e. regardless of their association with any RMRRs. The +main difference is when it comes to updating context entries, which need +to be atomic when there are RMRRs. Yet atomicity can only be achieved +with CMPXCHG16B, availability of which we can't take for given. + +The seemingly complicated choice of non-negative return values for +domain_context_mapping_one() is to limit code churn: This way callers +passing NULL for pdev don't need fiddling with. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 8f41e481b4852173909363b88c1ab3da747d3a05 +master date: 2022-04-05 14:17:42 +0200 +--- + xen/drivers/passthrough/vtd/extern.h | 7 +- + xen/drivers/passthrough/vtd/iommu.c | 268 +++++++++++++++++++++------ + xen/drivers/passthrough/vtd/iommu.h | 8 +- + xen/drivers/passthrough/vtd/quirks.c | 14 +- + xen/drivers/passthrough/vtd/vtd.h | 10 +- + 5 files changed, 233 insertions(+), 74 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/extern.h b/xen/drivers/passthrough/vtd/extern.h +index 1cac22a02f..f51f8aae0d 100644 +--- a/xen/drivers/passthrough/vtd/extern.h ++++ b/xen/drivers/passthrough/vtd/extern.h +@@ -85,7 +85,8 @@ void free_pgtable_maddr(u64 maddr); + void *map_vtd_domain_page(u64 maddr); + void unmap_vtd_domain_page(void *va); + int domain_context_mapping_one(struct domain *domain, struct vtd_iommu *iommu, +- u8 bus, u8 devfn, const struct pci_dev *); ++ uint8_t bus, uint8_t devfn, ++ const struct pci_dev *pdev, unsigned int mode); + int domain_context_unmap_one(struct domain *domain, struct vtd_iommu *iommu, + u8 bus, u8 devfn); + int intel_iommu_get_reserved_device_memory(iommu_grdm_t *func, void *ctxt); +@@ -105,8 +106,8 @@ int is_igd_vt_enabled_quirk(void); + void platform_quirks_init(void); + void vtd_ops_preamble_quirk(struct vtd_iommu *iommu); + void vtd_ops_postamble_quirk(struct vtd_iommu *iommu); +-int __must_check me_wifi_quirk(struct domain *domain, +- u8 bus, u8 devfn, int map); ++int __must_check me_wifi_quirk(struct domain *domain, uint8_t bus, ++ uint8_t devfn, unsigned int mode); + void pci_vtd_quirk(const struct pci_dev *); + void quirk_iommu_caps(struct vtd_iommu *iommu); + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index b729ae173a..17deda92d8 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -110,6 +110,7 @@ static int context_set_domain_id(struct context_entry *context, + } + + set_bit(i, iommu->domid_bitmap); ++ context->hi &= ~(((1 << DID_FIELD_WIDTH) - 1) << DID_HIGH_OFFSET); + context->hi |= (i & ((1 << DID_FIELD_WIDTH) - 1)) << DID_HIGH_OFFSET; + return 0; + } +@@ -1350,15 +1351,27 @@ static void __hwdom_init intel_iommu_hwdom_init(struct domain *d) + } + } + ++/* ++ * This function returns ++ * - a negative errno value upon error, ++ * - zero upon success when previously the entry was non-present, or this isn't ++ * the "main" request for a device (pdev == NULL), or for no-op quarantining ++ * assignments, ++ * - positive (one) upon success when previously the entry was present and this ++ * is the "main" request for a device (pdev != NULL). ++ */ + int domain_context_mapping_one( + struct domain *domain, + struct vtd_iommu *iommu, +- u8 bus, u8 devfn, const struct pci_dev *pdev) ++ uint8_t bus, uint8_t devfn, const struct pci_dev *pdev, ++ unsigned int mode) + { + struct domain_iommu *hd = dom_iommu(domain); +- struct context_entry *context, *context_entries; ++ struct context_entry *context, *context_entries, lctxt; ++ __uint128_t old; + u64 maddr, pgd_maddr; +- u16 seg = iommu->drhd->segment; ++ uint16_t seg = iommu->drhd->segment, prev_did = 0; ++ struct domain *prev_dom = NULL; + int agaw, rc, ret; + bool_t flush_dev_iotlb; + +@@ -1367,17 +1380,32 @@ int domain_context_mapping_one( + maddr = bus_to_context_maddr(iommu, bus); + context_entries = (struct context_entry *)map_vtd_domain_page(maddr); + context = &context_entries[devfn]; ++ old = (lctxt = *context).full; + +- if ( context_present(*context) ) ++ if ( context_present(lctxt) ) + { +- spin_unlock(&iommu->lock); +- unmap_vtd_domain_page(context_entries); +- return 0; ++ domid_t domid; ++ ++ prev_did = context_domain_id(lctxt); ++ domid = iommu->domid_map[prev_did]; ++ if ( domid < DOMID_FIRST_RESERVED ) ++ prev_dom = rcu_lock_domain_by_id(domid); ++ else if ( domid == DOMID_IO ) ++ prev_dom = rcu_lock_domain(dom_io); ++ if ( !prev_dom ) ++ { ++ spin_unlock(&iommu->lock); ++ unmap_vtd_domain_page(context_entries); ++ dprintk(XENLOG_DEBUG VTDPREFIX, ++ "no domain for did %u (nr_dom %u)\n", ++ prev_did, cap_ndoms(iommu->cap)); ++ return -ESRCH; ++ } + } + + if ( iommu_hwdom_passthrough && is_hardware_domain(domain) ) + { +- context_set_translation_type(*context, CONTEXT_TT_PASS_THRU); ++ context_set_translation_type(lctxt, CONTEXT_TT_PASS_THRU); + agaw = level_to_agaw(iommu->nr_pt_levels); + } + else +@@ -1394,6 +1422,8 @@ int domain_context_mapping_one( + spin_unlock(&hd->arch.mapping_lock); + spin_unlock(&iommu->lock); + unmap_vtd_domain_page(context_entries); ++ if ( prev_dom ) ++ rcu_unlock_domain(prev_dom); + return -ENOMEM; + } + } +@@ -1411,33 +1441,102 @@ int domain_context_mapping_one( + goto nomem; + } + +- context_set_address_root(*context, pgd_maddr); ++ context_set_address_root(lctxt, pgd_maddr); + if ( ats_enabled && ecap_dev_iotlb(iommu->ecap) ) +- context_set_translation_type(*context, CONTEXT_TT_DEV_IOTLB); ++ context_set_translation_type(lctxt, CONTEXT_TT_DEV_IOTLB); + else +- context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL); ++ context_set_translation_type(lctxt, CONTEXT_TT_MULTI_LEVEL); + + spin_unlock(&hd->arch.mapping_lock); + } + +- if ( context_set_domain_id(context, domain, iommu) ) ++ rc = context_set_domain_id(&lctxt, domain, iommu); ++ if ( rc ) + { ++ unlock: + spin_unlock(&iommu->lock); + unmap_vtd_domain_page(context_entries); +- return -EFAULT; ++ if ( prev_dom ) ++ rcu_unlock_domain(prev_dom); ++ return rc; ++ } ++ ++ if ( !prev_dom ) ++ { ++ context_set_address_width(lctxt, agaw); ++ context_set_fault_enable(lctxt); ++ context_set_present(lctxt); ++ } ++ else if ( prev_dom == domain ) ++ { ++ ASSERT(lctxt.full == context->full); ++ rc = !!pdev; ++ goto unlock; ++ } ++ else ++ { ++ ASSERT(context_address_width(lctxt) == agaw); ++ ASSERT(!context_fault_disable(lctxt)); ++ } ++ ++ if ( cpu_has_cx16 ) ++ { ++ __uint128_t res = cmpxchg16b(context, &old, &lctxt.full); ++ ++ /* ++ * Hardware does not update the context entry behind our backs, ++ * so the return value should match "old". ++ */ ++ if ( res != old ) ++ { ++ if ( pdev ) ++ check_cleanup_domid_map(domain, pdev, iommu); ++ printk(XENLOG_ERR ++ "%04x:%02x:%02x.%u: unexpected context entry %016lx_%016lx (expected %016lx_%016lx)\n", ++ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ++ (uint64_t)(res >> 64), (uint64_t)res, ++ (uint64_t)(old >> 64), (uint64_t)old); ++ rc = -EILSEQ; ++ goto unlock; ++ } ++ } ++ else if ( !prev_dom || !(mode & MAP_WITH_RMRR) ) ++ { ++ context_clear_present(*context); ++ iommu_sync_cache(context, sizeof(*context)); ++ ++ write_atomic(&context->hi, lctxt.hi); ++ /* No barrier should be needed between these two. */ ++ write_atomic(&context->lo, lctxt.lo); ++ } ++ else /* Best effort, updating DID last. */ ++ { ++ /* ++ * By non-atomically updating the context entry's DID field last, ++ * during a short window in time TLB entries with the old domain ID ++ * but the new page tables may be inserted. This could affect I/O ++ * of other devices using this same (old) domain ID. Such updating ++ * therefore is not a problem if this was the only device associated ++ * with the old domain ID. Diverting I/O of any of a dying domain's ++ * devices to the quarantine page tables is intended anyway. ++ */ ++ if ( !(mode & (MAP_OWNER_DYING | MAP_SINGLE_DEVICE)) ) ++ printk(XENLOG_WARNING VTDPREFIX ++ " %04x:%02x:%02x.%u: reassignment may cause %pd data corruption\n", ++ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), prev_dom); ++ ++ write_atomic(&context->lo, lctxt.lo); ++ /* No barrier should be needed between these two. */ ++ write_atomic(&context->hi, lctxt.hi); + } + +- context_set_address_width(*context, agaw); +- context_set_fault_enable(*context); +- context_set_present(*context); + iommu_sync_cache(context, sizeof(struct context_entry)); + spin_unlock(&iommu->lock); + +- /* Context entry was previously non-present (with domid 0). */ +- rc = iommu_flush_context_device(iommu, 0, PCI_BDF2(bus, devfn), +- DMA_CCMD_MASK_NOBIT, 1); ++ rc = iommu_flush_context_device(iommu, prev_did, PCI_BDF2(bus, devfn), ++ DMA_CCMD_MASK_NOBIT, !prev_dom); + flush_dev_iotlb = !!find_ats_dev_drhd(iommu); +- ret = iommu_flush_iotlb_dsi(iommu, 0, 1, flush_dev_iotlb); ++ ret = iommu_flush_iotlb_dsi(iommu, prev_did, !prev_dom, flush_dev_iotlb); + + /* + * The current logic for returns: +@@ -1458,12 +1557,21 @@ int domain_context_mapping_one( + unmap_vtd_domain_page(context_entries); + + if ( !seg && !rc ) +- rc = me_wifi_quirk(domain, bus, devfn, MAP_ME_PHANTOM_FUNC); ++ rc = me_wifi_quirk(domain, bus, devfn, mode); + + if ( rc ) +- domain_context_unmap_one(domain, iommu, bus, devfn); ++ { ++ if ( !prev_dom ) ++ domain_context_unmap_one(domain, iommu, bus, devfn); ++ else if ( prev_dom != domain ) /* Avoid infinite recursion. */ ++ domain_context_mapping_one(prev_dom, iommu, bus, devfn, pdev, ++ mode & MAP_WITH_RMRR); ++ } + +- return rc; ++ if ( prev_dom ) ++ rcu_unlock_domain(prev_dom); ++ ++ return rc ?: pdev && prev_dom; + } + + static int domain_context_unmap(struct domain *d, uint8_t devfn, +@@ -1473,8 +1581,11 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + struct pci_dev *pdev) + { + struct acpi_drhd_unit *drhd; ++ const struct acpi_rmrr_unit *rmrr; + int ret = 0; +- u8 seg = pdev->seg, bus = pdev->bus, secbus; ++ unsigned int i, mode = 0; ++ uint16_t seg = pdev->seg, bdf; ++ uint8_t bus = pdev->bus, secbus; + + drhd = acpi_find_matched_drhd_unit(pdev); + if ( !drhd ) +@@ -1493,8 +1604,29 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + + ASSERT(pcidevs_locked()); + ++ for_each_rmrr_device( rmrr, bdf, i ) ++ { ++ if ( rmrr->segment != pdev->seg || bdf != pdev->sbdf.bdf ) ++ continue; ++ ++ mode |= MAP_WITH_RMRR; ++ break; ++ } ++ ++ if ( domain != pdev->domain ) ++ { ++ if ( pdev->domain->is_dying ) ++ mode |= MAP_OWNER_DYING; ++ else if ( drhd && ++ !any_pdev_behind_iommu(pdev->domain, pdev, drhd->iommu) && ++ !pdev->phantom_stride ) ++ mode |= MAP_SINGLE_DEVICE; ++ } ++ + switch ( pdev->type ) + { ++ bool prev_present; ++ + case DEV_TYPE_PCI_HOST_BRIDGE: + if ( iommu_debug ) + printk(VTDPREFIX "d%d:Hostbridge: skip %04x:%02x:%02x.%u map\n", +@@ -1515,7 +1647,9 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + domain->domain_id, seg, bus, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn, +- pdev); ++ pdev, mode); ++ if ( ret > 0 ) ++ ret = 0; + if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 ) + enable_ats_device(pdev, &drhd->iommu->ats_devices); + +@@ -1528,9 +1662,10 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn, +- pdev); +- if ( ret ) ++ pdev, mode); ++ if ( ret < 0 ) + break; ++ prev_present = ret; + + if ( (ret = find_upstream_bridge(seg, &bus, &devfn, &secbus)) < 1 ) + { +@@ -1538,6 +1673,15 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + break; + ret = -ENXIO; + } ++ /* ++ * Strictly speaking if the device is the only one behind this bridge ++ * and the only one with this (secbus,0,0) tuple, it could be allowed ++ * to be re-assigned regardless of RMRR presence. But let's deal with ++ * that case only if it is actually found in the wild. ++ */ ++ else if ( prev_present && (mode & MAP_WITH_RMRR) && ++ domain != pdev->domain ) ++ ret = -EOPNOTSUPP; + + /* + * Mapping a bridge should, if anything, pass the struct pci_dev of +@@ -1546,7 +1690,7 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + */ + if ( ret >= 0 ) + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn, +- NULL); ++ NULL, mode); + + /* + * Devices behind PCIe-to-PCI/PCIx bridge may generate different +@@ -1561,10 +1705,15 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + if ( !ret && pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE && + (secbus != pdev->bus || pdev->devfn != 0) ) + ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0, +- NULL); ++ NULL, mode); + + if ( ret ) +- domain_context_unmap(domain, devfn, pdev); ++ { ++ if ( !prev_present ) ++ domain_context_unmap(domain, devfn, pdev); ++ else if ( pdev->domain != domain ) /* Avoid infinite recursion. */ ++ domain_context_mapping(pdev->domain, devfn, pdev); ++ } + + break; + +@@ -2331,9 +2480,8 @@ static int reassign_device_ownership( + { + int ret; + +- ret = domain_context_unmap(source, devfn, pdev); +- if ( ret ) +- return ret; ++ if ( !has_arch_pdevs(target) ) ++ vmx_pi_hooks_assign(target); + + /* + * Devices assigned to untrusted domains (here assumed to be any domU) +@@ -2343,6 +2491,31 @@ static int reassign_device_ownership( + if ( (target != hardware_domain) && !iommu_intremap ) + untrusted_msi = true; + ++ ret = domain_context_mapping(target, devfn, pdev); ++ if ( ret ) ++ { ++ if ( !has_arch_pdevs(target) ) ++ vmx_pi_hooks_deassign(target); ++ return ret; ++ } ++ ++ if ( pdev->devfn == devfn ) ++ { ++ const struct acpi_drhd_unit *drhd = acpi_find_matched_drhd_unit(pdev); ++ ++ if ( drhd ) ++ check_cleanup_domid_map(source, pdev, drhd->iommu); ++ } ++ ++ if ( devfn == pdev->devfn && pdev->domain != target ) ++ { ++ list_move(&pdev->domain_list, &target->pdev_list); ++ pdev->domain = target; ++ } ++ ++ if ( !has_arch_pdevs(source) ) ++ vmx_pi_hooks_deassign(source); ++ + /* + * If the device belongs to the hardware domain, and it has RMRR, don't + * remove it from the hardware domain, because BIOS may use RMRR at +@@ -2371,34 +2544,7 @@ static int reassign_device_ownership( + } + } + +- if ( devfn == pdev->devfn && pdev->domain != dom_io ) +- { +- list_move(&pdev->domain_list, &dom_io->pdev_list); +- pdev->domain = dom_io; +- } +- +- if ( !has_arch_pdevs(source) ) +- vmx_pi_hooks_deassign(source); +- +- if ( !has_arch_pdevs(target) ) +- vmx_pi_hooks_assign(target); +- +- ret = domain_context_mapping(target, devfn, pdev); +- if ( ret ) +- { +- if ( !has_arch_pdevs(target) ) +- vmx_pi_hooks_deassign(target); +- +- return ret; +- } +- +- if ( devfn == pdev->devfn && pdev->domain != target ) +- { +- list_move(&pdev->domain_list, &target->pdev_list); +- pdev->domain = target; +- } +- +- return ret; ++ return 0; + } + + static int intel_iommu_assign_device( +diff --git a/xen/drivers/passthrough/vtd/iommu.h b/xen/drivers/passthrough/vtd/iommu.h +index 32b39c606a..503b07ffb7 100644 +--- a/xen/drivers/passthrough/vtd/iommu.h ++++ b/xen/drivers/passthrough/vtd/iommu.h +@@ -202,8 +202,12 @@ struct root_entry { + do {(root).val |= ((value) & PAGE_MASK_4K);} while(0) + + struct context_entry { +- u64 lo; +- u64 hi; ++ union { ++ struct { ++ uint64_t lo, hi; ++ }; ++ __uint128_t full; ++ }; + }; + #define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry)) + #define context_present(c) ((c).lo & 1) +diff --git a/xen/drivers/passthrough/vtd/quirks.c b/xen/drivers/passthrough/vtd/quirks.c +index 435e449ca3..99e159b4e9 100644 +--- a/xen/drivers/passthrough/vtd/quirks.c ++++ b/xen/drivers/passthrough/vtd/quirks.c +@@ -343,7 +343,8 @@ void __init platform_quirks_init(void) + */ + + static int __must_check map_me_phantom_function(struct domain *domain, +- u32 dev, int map) ++ unsigned int dev, ++ unsigned int mode) + { + struct acpi_drhd_unit *drhd; + struct pci_dev *pdev; +@@ -354,9 +355,9 @@ static int __must_check map_me_phantom_function(struct domain *domain, + drhd = acpi_find_matched_drhd_unit(pdev); + + /* map or unmap ME phantom function */ +- if ( map ) ++ if ( !(mode & UNMAP_ME_PHANTOM_FUNC) ) + rc = domain_context_mapping_one(domain, drhd->iommu, 0, +- PCI_DEVFN(dev, 7), NULL); ++ PCI_DEVFN(dev, 7), NULL, mode); + else + rc = domain_context_unmap_one(domain, drhd->iommu, 0, + PCI_DEVFN(dev, 7)); +@@ -364,7 +365,8 @@ static int __must_check map_me_phantom_function(struct domain *domain, + return rc; + } + +-int me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map) ++int me_wifi_quirk(struct domain *domain, uint8_t bus, uint8_t devfn, ++ unsigned int mode) + { + u32 id; + int rc = 0; +@@ -388,7 +390,7 @@ int me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map) + case 0x423b8086: + case 0x423c8086: + case 0x423d8086: +- rc = map_me_phantom_function(domain, 3, map); ++ rc = map_me_phantom_function(domain, 3, mode); + break; + default: + break; +@@ -414,7 +416,7 @@ int me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map) + case 0x42388086: /* Puma Peak */ + case 0x422b8086: + case 0x422c8086: +- rc = map_me_phantom_function(domain, 22, map); ++ rc = map_me_phantom_function(domain, 22, mode); + break; + default: + break; +diff --git a/xen/drivers/passthrough/vtd/vtd.h b/xen/drivers/passthrough/vtd/vtd.h +index bb8889f350..e4ab242fee 100644 +--- a/xen/drivers/passthrough/vtd/vtd.h ++++ b/xen/drivers/passthrough/vtd/vtd.h +@@ -22,8 +22,14 @@ + + #include <xen/iommu.h> + +-#define MAP_ME_PHANTOM_FUNC 1 +-#define UNMAP_ME_PHANTOM_FUNC 0 ++/* ++ * Values for domain_context_mapping_one()'s and me_wifi_quirk()'s "mode" ++ * parameters. ++ */ ++#define MAP_WITH_RMRR (1u << 0) ++#define MAP_OWNER_DYING (1u << 1) ++#define MAP_SINGLE_DEVICE (1u << 2) ++#define UNMAP_ME_PHANTOM_FUNC (1u << 3) + + /* Allow for both IOAPIC and IOSAPIC. */ + #define IO_xAPIC_route_entry IO_APIC_route_entry +-- +2.35.2 + + +From 73e25ecaef14d4df521235b6dbe5ceaaa3f02e8a Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:24:23 +0200 +Subject: [PATCH 23/32] AMD/IOMMU: re-assign devices directly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Devices with unity map ranges, due to it being unspecified how/when +these memory ranges may get accessed, may not be left disconnected from +their unity mappings (as long as it's not certain that the device has +been fully quiesced). Hence rather than tearing down the old root page +table pointer and then establishing the new one, re-assignment needs to +be done in a single step. + +This is CVE-2022-26360 / part of XSA-400. + +Reported-by: Roger Pau Monné <roger.pau@citrix.com> + +Similarly quarantining scratch-page mode relies on page tables to be +continuously wired up. + +To avoid complicating things more than necessary, treat all devices +mostly equally, i.e. regardless of their association with any unity map +ranges. The main difference is when it comes to updating DTEs, which need +to be atomic when there are unity mappings. Yet atomicity can only be +achieved with CMPXCHG16B, availability of which we can't take for given. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 1fa6e9aa36233fe9c29a204fcb2697e985b8345f +master date: 2022-04-05 14:18:04 +0200 +--- + xen/drivers/passthrough/amd/iommu_map.c | 67 ++++++- + xen/drivers/passthrough/amd/pci_amd_iommu.c | 180 +++++++++++++----- + xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 10 +- + 3 files changed, 200 insertions(+), 57 deletions(-) + +diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c +index ac30cac05b..45559f9678 100644 +--- a/xen/drivers/passthrough/amd/iommu_map.c ++++ b/xen/drivers/passthrough/amd/iommu_map.c +@@ -103,10 +103,69 @@ static unsigned int set_iommu_pte_present(unsigned long pt_mfn, + return flush_flags; + } + +-void amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, +- uint64_t root_ptr, uint16_t domain_id, +- uint8_t paging_mode, bool valid) ++/* ++ * This function returns ++ * - -errno for errors, ++ * - 0 for a successful update, atomic when necessary ++ * - 1 for a successful but non-atomic update, which may need to be warned ++ * about by the caller. ++ */ ++int amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, ++ uint64_t root_ptr, uint16_t domain_id, ++ uint8_t paging_mode, unsigned int flags) + { ++ bool valid = flags & SET_ROOT_VALID; ++ ++ if ( dte->v && dte->tv && ++ (cpu_has_cx16 || (flags & SET_ROOT_WITH_UNITY_MAP)) ) ++ { ++ union { ++ struct amd_iommu_dte dte; ++ uint64_t raw64[4]; ++ __uint128_t raw128[2]; ++ } ldte = { .dte = *dte }; ++ __uint128_t old = ldte.raw128[0]; ++ int ret = 0; ++ ++ ldte.dte.domain_id = domain_id; ++ ldte.dte.pt_root = paddr_to_pfn(root_ptr); ++ ldte.dte.iw = true; ++ ldte.dte.ir = true; ++ ldte.dte.paging_mode = paging_mode; ++ ldte.dte.v = valid; ++ ++ if ( cpu_has_cx16 ) ++ { ++ __uint128_t res = cmpxchg16b(dte, &old, &ldte.raw128[0]); ++ ++ /* ++ * Hardware does not update the DTE behind our backs, so the ++ * return value should match "old". ++ */ ++ if ( res != old ) ++ { ++ printk(XENLOG_ERR ++ "Dom%d: unexpected DTE %016lx_%016lx (expected %016lx_%016lx)\n", ++ domain_id, ++ (uint64_t)(res >> 64), (uint64_t)res, ++ (uint64_t)(old >> 64), (uint64_t)old); ++ ret = -EILSEQ; ++ } ++ } ++ else /* Best effort, updating domain_id last. */ ++ { ++ uint64_t *ptr = (void *)dte; ++ ++ write_atomic(ptr + 0, ldte.raw64[0]); ++ /* No barrier should be needed between these two. */ ++ write_atomic(ptr + 1, ldte.raw64[1]); ++ ++ ret = 1; ++ } ++ ++ return ret; ++ } ++ + if ( valid || dte->v ) + { + dte->tv = false; +@@ -121,6 +180,8 @@ void amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, + smp_wmb(); + dte->tv = true; + dte->v = valid; ++ ++ return 0; + } + + void amd_iommu_set_intremap_table( +diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c +index beafb0171d..14483e85ae 100644 +--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c ++++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c +@@ -85,40 +85,81 @@ int get_dma_requestor_id(uint16_t seg, uint16_t bdf) + return req_id; + } + +-static void amd_iommu_setup_domain_device( ++static int __must_check allocate_domain_resources(struct domain_iommu *hd) ++{ ++ int rc; ++ ++ spin_lock(&hd->arch.mapping_lock); ++ rc = amd_iommu_alloc_root(hd); ++ spin_unlock(&hd->arch.mapping_lock); ++ ++ return rc; ++} ++ ++static bool any_pdev_behind_iommu(const struct domain *d, ++ const struct pci_dev *exclude, ++ const struct amd_iommu *iommu) ++{ ++ const struct pci_dev *pdev; ++ ++ for_each_pdev ( d, pdev ) ++ { ++ if ( pdev == exclude ) ++ continue; ++ ++ if ( find_iommu_for_device(pdev->seg, pdev->sbdf.bdf) == iommu ) ++ return true; ++ } ++ ++ return false; ++} ++ ++static int __must_check amd_iommu_setup_domain_device( + struct domain *domain, struct amd_iommu *iommu, + uint8_t devfn, struct pci_dev *pdev) + { + struct amd_iommu_dte *table, *dte; + unsigned long flags; +- int req_id, valid = 1; ++ unsigned int req_id, sr_flags; ++ int rc; + u8 bus = pdev->bus; +- const struct domain_iommu *hd = dom_iommu(domain); ++ struct domain_iommu *hd = dom_iommu(domain); ++ const struct ivrs_mappings *ivrs_dev; ++ ++ BUG_ON(!hd->arch.paging_mode || !iommu->dev_table.buffer); + +- BUG_ON( !hd->arch.root_table || !hd->arch.paging_mode || +- !iommu->dev_table.buffer ); ++ rc = allocate_domain_resources(hd); ++ if ( rc ) ++ return rc; + +- if ( iommu_hwdom_passthrough && is_hardware_domain(domain) ) +- valid = 0; ++ req_id = get_dma_requestor_id(iommu->seg, pdev->sbdf.bdf); ++ ivrs_dev = &get_ivrs_mappings(iommu->seg)[req_id]; ++ sr_flags = (iommu_hwdom_passthrough && is_hardware_domain(domain) ++ ? 0 : SET_ROOT_VALID) ++ | (ivrs_dev->unity_map ? SET_ROOT_WITH_UNITY_MAP : 0); + + /* get device-table entry */ + req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn)); + table = iommu->dev_table.buffer; + dte = &table[req_id]; ++ ivrs_dev = &get_ivrs_mappings(iommu->seg)[req_id]; + + spin_lock_irqsave(&iommu->lock, flags); + + if ( !dte->v || !dte->tv ) + { +- const struct ivrs_mappings *ivrs_dev; +- + /* bind DTE to domain page-tables */ +- amd_iommu_set_root_page_table( +- dte, page_to_maddr(hd->arch.root_table), domain->domain_id, +- hd->arch.paging_mode, valid); ++ rc = amd_iommu_set_root_page_table( ++ dte, page_to_maddr(hd->arch.root_table), ++ domain->domain_id, hd->arch.paging_mode, sr_flags); ++ if ( rc ) ++ { ++ ASSERT(rc < 0); ++ spin_unlock_irqrestore(&iommu->lock, flags); ++ return rc; ++ } + + /* Undo what amd_iommu_disable_domain_device() may have done. */ +- ivrs_dev = &get_ivrs_mappings(iommu->seg)[req_id]; + if ( dte->it_root ) + { + dte->int_ctl = IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED; +@@ -133,17 +174,74 @@ static void amd_iommu_setup_domain_device( + dte->i = ats_enabled; + + amd_iommu_flush_device(iommu, req_id); ++ } ++ else if ( dte->pt_root != mfn_x(page_to_mfn(hd->arch.root_table)) ) ++ { ++ /* ++ * Strictly speaking if the device is the only one with this requestor ++ * ID, it could be allowed to be re-assigned regardless of unity map ++ * presence. But let's deal with that case only if it is actually ++ * found in the wild. ++ */ ++ if ( req_id != PCI_BDF2(bus, devfn) && ++ (sr_flags & SET_ROOT_WITH_UNITY_MAP) ) ++ rc = -EOPNOTSUPP; ++ else ++ rc = amd_iommu_set_root_page_table( ++ dte, page_to_maddr(hd->arch.root_table), ++ domain->domain_id, hd->arch.paging_mode, sr_flags); ++ if ( rc < 0 ) ++ { ++ spin_unlock_irqrestore(&iommu->lock, flags); ++ return rc; ++ } ++ if ( rc && ++ domain != pdev->domain && ++ /* ++ * By non-atomically updating the DTE's domain ID field last, ++ * during a short window in time TLB entries with the old domain ++ * ID but the new page tables may have been inserted. This could ++ * affect I/O of other devices using this same (old) domain ID. ++ * Such updating therefore is not a problem if this was the only ++ * device associated with the old domain ID. Diverting I/O of any ++ * of a dying domain's devices to the quarantine page tables is ++ * intended anyway. ++ */ ++ !pdev->domain->is_dying && ++ (any_pdev_behind_iommu(pdev->domain, pdev, iommu) || ++ pdev->phantom_stride) ) ++ printk(" %04x:%02x:%02x.%u: reassignment may cause %pd data corruption\n", ++ pdev->seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), ++ pdev->domain); ++ ++ /* ++ * Check remaining settings are still in place from an earlier call ++ * here. They're all independent of the domain, so should not have ++ * changed. ++ */ ++ if ( dte->it_root ) ++ ASSERT(dte->int_ctl == IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED); ++ ASSERT(dte->iv == iommu_intremap); ++ ASSERT(dte->ex == ivrs_dev->dte_allow_exclusion); ++ ASSERT(dte->sys_mgt == MASK_EXTR(ivrs_dev->device_flags, ++ ACPI_IVHD_SYSTEM_MGMT)); + +- AMD_IOMMU_DEBUG("Setup I/O page table: device id = %#x, type = %#x, " +- "root table = %#"PRIx64", " +- "domain = %d, paging mode = %d\n", +- req_id, pdev->type, +- page_to_maddr(hd->arch.root_table), +- domain->domain_id, hd->arch.paging_mode); ++ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && ++ iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) ) ++ ASSERT(dte->i == ats_enabled); ++ ++ amd_iommu_flush_device(iommu, req_id); + } + + spin_unlock_irqrestore(&iommu->lock, flags); + ++ AMD_IOMMU_DEBUG("Setup I/O page table: device id = %#x, type = %#x, " ++ "root table = %#"PRIx64", " ++ "domain = %d, paging mode = %d\n", ++ req_id, pdev->type, ++ page_to_maddr(hd->arch.root_table), ++ domain->domain_id, hd->arch.paging_mode); ++ + ASSERT(pcidevs_locked()); + + if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && +@@ -154,6 +252,8 @@ static void amd_iommu_setup_domain_device( + + amd_iommu_flush_iotlb(devfn, pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0); + } ++ ++ return 0; + } + + int __init acpi_ivrs_init(void) +@@ -223,17 +323,6 @@ int amd_iommu_alloc_root(struct domain_iommu *hd) + return 0; + } + +-static int __must_check allocate_domain_resources(struct domain_iommu *hd) +-{ +- int rc; +- +- spin_lock(&hd->arch.mapping_lock); +- rc = amd_iommu_alloc_root(hd); +- spin_unlock(&hd->arch.mapping_lock); +- +- return rc; +-} +- + int __read_mostly amd_iommu_min_paging_mode = 1; + + static int amd_iommu_domain_init(struct domain *d) +@@ -333,7 +422,6 @@ static int reassign_device(struct domain *source, struct domain *target, + { + struct amd_iommu *iommu; + int bdf, rc; +- struct domain_iommu *t = dom_iommu(target); + const struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(pdev->seg); + + bdf = PCI_BDF2(pdev->bus, pdev->devfn); +@@ -347,7 +435,15 @@ static int reassign_device(struct domain *source, struct domain *target, + return -ENODEV; + } + +- amd_iommu_disable_domain_device(source, iommu, devfn, pdev); ++ rc = amd_iommu_setup_domain_device(target, iommu, devfn, pdev); ++ if ( rc ) ++ return rc; ++ ++ if ( devfn == pdev->devfn && pdev->domain != target ) ++ { ++ list_move(&pdev->domain_list, &target->pdev_list); ++ pdev->domain = target; ++ } + + /* + * If the device belongs to the hardware domain, and it has a unity mapping, +@@ -363,27 +459,10 @@ static int reassign_device(struct domain *source, struct domain *target, + return rc; + } + +- if ( devfn == pdev->devfn && pdev->domain != dom_io ) +- { +- list_move(&pdev->domain_list, &dom_io->pdev_list); +- pdev->domain = dom_io; +- } +- +- rc = allocate_domain_resources(t); +- if ( rc ) +- return rc; +- +- amd_iommu_setup_domain_device(target, iommu, devfn, pdev); + AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n", + pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + source->domain_id, target->domain_id); + +- if ( devfn == pdev->devfn && pdev->domain != target ) +- { +- list_move(&pdev->domain_list, &target->pdev_list); +- pdev->domain = target; +- } +- + return 0; + } + +@@ -547,8 +626,7 @@ static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev) + spin_unlock_irqrestore(&iommu->lock, flags); + } + +- amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev); +- return 0; ++ return amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev); + } + + static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev) +diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +index 3983293540..52c889ade0 100644 +--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h ++++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +@@ -79,9 +79,13 @@ void amd_iommu_set_intremap_table(struct amd_iommu_dte *dte, + const void *ptr, + const struct amd_iommu *iommu, + bool valid); +-void amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, +- uint64_t root_ptr, uint16_t domain_id, +- uint8_t paging_mode, bool valid); ++#define SET_ROOT_VALID (1u << 0) ++#define SET_ROOT_WITH_UNITY_MAP (1u << 1) ++int __must_check amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, ++ uint64_t root_ptr, ++ uint16_t domain_id, ++ uint8_t paging_mode, ++ unsigned int flags); + void iommu_dte_add_device_entry(struct amd_iommu_dte *dte, + const struct ivrs_mappings *ivrs_dev); + void iommu_dte_set_guest_cr3(struct amd_iommu_dte *dte, uint16_t dom_id, +-- +2.35.2 + + +From 92acf6b23154d65066ec4702fdca5cf232856d90 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:24:54 +0200 +Subject: [PATCH 24/32] VT-d: prepare for per-device quarantine page tables + (part I) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Arrange for domain ID and page table root to be passed around, the latter in +particular to domain_pgd_maddr() such that taking it from the per-domain +fields can be overridden. + +No functional change intended. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +master commit: eb19326a328d49a6a4dc3930391b340f3bcd8948 +master date: 2022-04-05 14:18:26 +0200 +--- + xen/drivers/passthrough/vtd/extern.h | 8 ++-- + xen/drivers/passthrough/vtd/iommu.c | 62 ++++++++++++++++++---------- + xen/drivers/passthrough/vtd/quirks.c | 13 +++--- + 3 files changed, 54 insertions(+), 29 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/extern.h b/xen/drivers/passthrough/vtd/extern.h +index f51f8aae0d..897dcff9ff 100644 +--- a/xen/drivers/passthrough/vtd/extern.h ++++ b/xen/drivers/passthrough/vtd/extern.h +@@ -86,9 +86,10 @@ void *map_vtd_domain_page(u64 maddr); + void unmap_vtd_domain_page(void *va); + int domain_context_mapping_one(struct domain *domain, struct vtd_iommu *iommu, + uint8_t bus, uint8_t devfn, +- const struct pci_dev *pdev, unsigned int mode); ++ const struct pci_dev *pdev, domid_t domid, ++ paddr_t pgd_maddr, unsigned int mode); + int domain_context_unmap_one(struct domain *domain, struct vtd_iommu *iommu, +- u8 bus, u8 devfn); ++ uint8_t bus, uint8_t devfn, domid_t domid); + int intel_iommu_get_reserved_device_memory(iommu_grdm_t *func, void *ctxt); + + unsigned int io_apic_read_remap_rte(unsigned int apic, unsigned int reg); +@@ -107,7 +108,8 @@ void platform_quirks_init(void); + void vtd_ops_preamble_quirk(struct vtd_iommu *iommu); + void vtd_ops_postamble_quirk(struct vtd_iommu *iommu); + int __must_check me_wifi_quirk(struct domain *domain, uint8_t bus, +- uint8_t devfn, unsigned int mode); ++ uint8_t devfn, domid_t domid, paddr_t pgd_maddr, ++ unsigned int mode); + void pci_vtd_quirk(const struct pci_dev *); + void quirk_iommu_caps(struct vtd_iommu *iommu); + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index 17deda92d8..ac2c73e32a 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -1364,12 +1364,12 @@ int domain_context_mapping_one( + struct domain *domain, + struct vtd_iommu *iommu, + uint8_t bus, uint8_t devfn, const struct pci_dev *pdev, +- unsigned int mode) ++ domid_t domid, paddr_t pgd_maddr, unsigned int mode) + { + struct domain_iommu *hd = dom_iommu(domain); + struct context_entry *context, *context_entries, lctxt; + __uint128_t old; +- u64 maddr, pgd_maddr; ++ uint64_t maddr; + uint16_t seg = iommu->drhd->segment, prev_did = 0; + struct domain *prev_dom = NULL; + int agaw, rc, ret; +@@ -1410,10 +1410,12 @@ int domain_context_mapping_one( + } + else + { ++ paddr_t root = pgd_maddr; ++ + spin_lock(&hd->arch.mapping_lock); + + /* Ensure we have pagetables allocated down to leaf PTE. */ +- if ( hd->arch.pgd_maddr == 0 ) ++ if ( !root ) + { + addr_to_dma_page_maddr(domain, 0, 1); + if ( hd->arch.pgd_maddr == 0 ) +@@ -1426,22 +1428,24 @@ int domain_context_mapping_one( + rcu_unlock_domain(prev_dom); + return -ENOMEM; + } ++ ++ root = hd->arch.pgd_maddr; + } + + /* Skip top levels of page tables for 2- and 3-level DRHDs. */ +- pgd_maddr = hd->arch.pgd_maddr; + for ( agaw = level_to_agaw(4); + agaw != level_to_agaw(iommu->nr_pt_levels); + agaw-- ) + { +- struct dma_pte *p = map_vtd_domain_page(pgd_maddr); +- pgd_maddr = dma_pte_addr(*p); ++ struct dma_pte *p = map_vtd_domain_page(root); ++ ++ root = dma_pte_addr(*p); + unmap_vtd_domain_page(p); +- if ( pgd_maddr == 0 ) ++ if ( !root ) + goto nomem; + } + +- context_set_address_root(lctxt, pgd_maddr); ++ context_set_address_root(lctxt, root); + if ( ats_enabled && ecap_dev_iotlb(iommu->ecap) ) + context_set_translation_type(lctxt, CONTEXT_TT_DEV_IOTLB); + else +@@ -1557,15 +1561,21 @@ int domain_context_mapping_one( + unmap_vtd_domain_page(context_entries); + + if ( !seg && !rc ) +- rc = me_wifi_quirk(domain, bus, devfn, mode); ++ rc = me_wifi_quirk(domain, bus, devfn, domid, pgd_maddr, mode); + + if ( rc ) + { + if ( !prev_dom ) +- domain_context_unmap_one(domain, iommu, bus, devfn); ++ domain_context_unmap_one(domain, iommu, bus, devfn, ++ domain->domain_id); + else if ( prev_dom != domain ) /* Avoid infinite recursion. */ ++ { ++ hd = dom_iommu(prev_dom); + domain_context_mapping_one(prev_dom, iommu, bus, devfn, pdev, ++ domain->domain_id, ++ hd->arch.pgd_maddr, + mode & MAP_WITH_RMRR); ++ } + } + + if ( prev_dom ) +@@ -1582,6 +1592,7 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + { + struct acpi_drhd_unit *drhd; + const struct acpi_rmrr_unit *rmrr; ++ paddr_t pgd_maddr = dom_iommu(domain)->arch.pgd_maddr; + int ret = 0; + unsigned int i, mode = 0; + uint16_t seg = pdev->seg, bdf; +@@ -1647,7 +1658,8 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + domain->domain_id, seg, bus, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn, +- pdev, mode); ++ pdev, domain->domain_id, pgd_maddr, ++ mode); + if ( ret > 0 ) + ret = 0; + if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 ) +@@ -1662,7 +1674,8 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn, +- pdev, mode); ++ pdev, domain->domain_id, pgd_maddr, ++ mode); + if ( ret < 0 ) + break; + prev_present = ret; +@@ -1690,7 +1703,8 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + */ + if ( ret >= 0 ) + ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn, +- NULL, mode); ++ NULL, domain->domain_id, pgd_maddr, ++ mode); + + /* + * Devices behind PCIe-to-PCI/PCIx bridge may generate different +@@ -1705,7 +1719,8 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + if ( !ret && pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE && + (secbus != pdev->bus || pdev->devfn != 0) ) + ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0, +- NULL, mode); ++ NULL, domain->domain_id, pgd_maddr, ++ mode); + + if ( ret ) + { +@@ -1734,7 +1749,7 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + int domain_context_unmap_one( + struct domain *domain, + struct vtd_iommu *iommu, +- u8 bus, u8 devfn) ++ uint8_t bus, uint8_t devfn, domid_t domid) + { + struct context_entry *context, *context_entries; + u64 maddr; +@@ -1792,7 +1807,7 @@ int domain_context_unmap_one( + unmap_vtd_domain_page(context_entries); + + if ( !iommu->drhd->segment && !rc ) +- rc = me_wifi_quirk(domain, bus, devfn, UNMAP_ME_PHANTOM_FUNC); ++ rc = me_wifi_quirk(domain, bus, devfn, domid, 0, UNMAP_ME_PHANTOM_FUNC); + + if ( rc && !is_hardware_domain(domain) && domain != dom_io ) + { +@@ -1844,7 +1859,8 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + printk(VTDPREFIX "d%d:PCIe: unmap %04x:%02x:%02x.%u\n", + domain->domain_id, seg, bus, + PCI_SLOT(devfn), PCI_FUNC(devfn)); +- ret = domain_context_unmap_one(domain, iommu, bus, devfn); ++ ret = domain_context_unmap_one(domain, iommu, bus, devfn, ++ domain->domain_id); + if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 ) + disable_ats_device(pdev); + +@@ -1854,7 +1870,8 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + if ( iommu_debug ) + printk(VTDPREFIX "d%d:PCI: unmap %04x:%02x:%02x.%u\n", + domain->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); +- ret = domain_context_unmap_one(domain, iommu, bus, devfn); ++ ret = domain_context_unmap_one(domain, iommu, bus, devfn, ++ domain->domain_id); + if ( ret ) + break; + +@@ -1880,12 +1897,15 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + /* PCIe to PCI/PCIx bridge */ + if ( pdev_type(seg, tmp_bus, tmp_devfn) == DEV_TYPE_PCIe2PCI_BRIDGE ) + { +- ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn); ++ ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn, ++ domain->domain_id); + if ( !ret ) +- ret = domain_context_unmap_one(domain, iommu, secbus, 0); ++ ret = domain_context_unmap_one(domain, iommu, secbus, 0, ++ domain->domain_id); + } + else /* Legacy PCI bridge */ +- ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn); ++ ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn, ++ domain->domain_id); + + break; + +diff --git a/xen/drivers/passthrough/vtd/quirks.c b/xen/drivers/passthrough/vtd/quirks.c +index 99e159b4e9..4d54c21136 100644 +--- a/xen/drivers/passthrough/vtd/quirks.c ++++ b/xen/drivers/passthrough/vtd/quirks.c +@@ -344,6 +344,8 @@ void __init platform_quirks_init(void) + + static int __must_check map_me_phantom_function(struct domain *domain, + unsigned int dev, ++ domid_t domid, ++ paddr_t pgd_maddr, + unsigned int mode) + { + struct acpi_drhd_unit *drhd; +@@ -357,16 +359,17 @@ static int __must_check map_me_phantom_function(struct domain *domain, + /* map or unmap ME phantom function */ + if ( !(mode & UNMAP_ME_PHANTOM_FUNC) ) + rc = domain_context_mapping_one(domain, drhd->iommu, 0, +- PCI_DEVFN(dev, 7), NULL, mode); ++ PCI_DEVFN(dev, 7), NULL, ++ domid, pgd_maddr, mode); + else + rc = domain_context_unmap_one(domain, drhd->iommu, 0, +- PCI_DEVFN(dev, 7)); ++ PCI_DEVFN(dev, 7), domid); + + return rc; + } + + int me_wifi_quirk(struct domain *domain, uint8_t bus, uint8_t devfn, +- unsigned int mode) ++ domid_t domid, paddr_t pgd_maddr, unsigned int mode) + { + u32 id; + int rc = 0; +@@ -390,7 +393,7 @@ int me_wifi_quirk(struct domain *domain, uint8_t bus, uint8_t devfn, + case 0x423b8086: + case 0x423c8086: + case 0x423d8086: +- rc = map_me_phantom_function(domain, 3, mode); ++ rc = map_me_phantom_function(domain, 3, domid, pgd_maddr, mode); + break; + default: + break; +@@ -416,7 +419,7 @@ int me_wifi_quirk(struct domain *domain, uint8_t bus, uint8_t devfn, + case 0x42388086: /* Puma Peak */ + case 0x422b8086: + case 0x422c8086: +- rc = map_me_phantom_function(domain, 22, mode); ++ rc = map_me_phantom_function(domain, 22, domid, pgd_maddr, mode); + break; + default: + break; +-- +2.35.2 + + +From ab37463eec5724036059d7df027ca13d66368211 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:25:26 +0200 +Subject: [PATCH 25/32] VT-d: prepare for per-device quarantine page tables + (part II) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace the passing of struct domain * by domid_t in preparation of +per-device quarantine page tables also requiring per-device pseudo +domain IDs, which aren't going to be associated with any struct domain +instances. + +No functional change intended (except for slightly adjusted log message +text). + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 7131163c4806e3c7de24873164d1a003d2a27dee +master date: 2022-04-05 14:18:48 +0200 +--- + xen/drivers/passthrough/vtd/iommu.c | 33 ++++++++++++++--------------- + 1 file changed, 16 insertions(+), 17 deletions(-) + +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index ac2c73e32a..6388d97d26 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -52,8 +52,8 @@ static struct tasklet vtd_fault_tasklet; + static int setup_hwdom_device(u8 devfn, struct pci_dev *); + static void setup_hwdom_rmrr(struct domain *d); + +-static int domain_iommu_domid(struct domain *d, +- struct vtd_iommu *iommu) ++static int get_iommu_did(domid_t domid, const struct vtd_iommu *iommu, ++ bool warn) + { + unsigned long nr_dom, i; + +@@ -61,16 +61,16 @@ static int domain_iommu_domid(struct domain *d, + i = find_first_bit(iommu->domid_bitmap, nr_dom); + while ( i < nr_dom ) + { +- if ( iommu->domid_map[i] == d->domain_id ) ++ if ( iommu->domid_map[i] == domid ) + return i; + + i = find_next_bit(iommu->domid_bitmap, nr_dom, i+1); + } + +- if ( !d->is_dying ) ++ if ( warn ) + dprintk(XENLOG_ERR VTDPREFIX, +- "Cannot get valid iommu %u domid: %pd\n", +- iommu->index, d); ++ "No valid iommu %u domid for Dom%d\n", ++ iommu->index, domid); + + return -1; + } +@@ -78,8 +78,7 @@ static int domain_iommu_domid(struct domain *d, + #define DID_FIELD_WIDTH 16 + #define DID_HIGH_OFFSET 8 + static int context_set_domain_id(struct context_entry *context, +- struct domain *d, +- struct vtd_iommu *iommu) ++ domid_t domid, struct vtd_iommu *iommu) + { + unsigned long nr_dom, i; + int found = 0; +@@ -90,7 +89,7 @@ static int context_set_domain_id(struct context_entry *context, + i = find_first_bit(iommu->domid_bitmap, nr_dom); + while ( i < nr_dom ) + { +- if ( iommu->domid_map[i] == d->domain_id ) ++ if ( iommu->domid_map[i] == domid ) + { + found = 1; + break; +@@ -106,7 +105,7 @@ static int context_set_domain_id(struct context_entry *context, + dprintk(XENLOG_ERR VTDPREFIX, "IOMMU: no free domain ids\n"); + return -EFAULT; + } +- iommu->domid_map[i] = d->domain_id; ++ iommu->domid_map[i] = domid; + } + + set_bit(i, iommu->domid_bitmap); +@@ -115,9 +114,9 @@ static int context_set_domain_id(struct context_entry *context, + return 0; + } + +-static void cleanup_domid_map(struct domain *domain, struct vtd_iommu *iommu) ++static void cleanup_domid_map(domid_t domid, struct vtd_iommu *iommu) + { +- int iommu_domid = domain_iommu_domid(domain, iommu); ++ int iommu_domid = get_iommu_did(domid, iommu, false); + + if ( iommu_domid >= 0 ) + { +@@ -173,7 +172,7 @@ static void check_cleanup_domid_map(struct domain *d, + if ( !found ) + { + clear_bit(iommu->index, &dom_iommu(d)->arch.iommu_bitmap); +- cleanup_domid_map(d, iommu); ++ cleanup_domid_map(d->domain_id, iommu); + } + } + +@@ -630,7 +629,7 @@ static int __must_check iommu_flush_iotlb(struct domain *d, dfn_t dfn, + continue; + + flush_dev_iotlb = !!find_ats_dev_drhd(iommu); +- iommu_domid= domain_iommu_domid(d, iommu); ++ iommu_domid = get_iommu_did(d->domain_id, iommu, !d->is_dying); + if ( iommu_domid == -1 ) + continue; + +@@ -1454,7 +1453,7 @@ int domain_context_mapping_one( + spin_unlock(&hd->arch.mapping_lock); + } + +- rc = context_set_domain_id(&lctxt, domain, iommu); ++ rc = context_set_domain_id(&lctxt, domid, iommu); + if ( rc ) + { + unlock: +@@ -1774,7 +1773,7 @@ int domain_context_unmap_one( + context_clear_entry(*context); + iommu_sync_cache(context, sizeof(struct context_entry)); + +- iommu_domid= domain_iommu_domid(domain, iommu); ++ iommu_domid = get_iommu_did(domid, iommu, !domain->is_dying); + if ( iommu_domid == -1 ) + { + spin_unlock(&iommu->lock); +@@ -1948,7 +1947,7 @@ static void iommu_domain_teardown(struct domain *d) + spin_unlock(&hd->arch.mapping_lock); + + for_each_drhd_unit ( drhd ) +- cleanup_domid_map(d, drhd->iommu); ++ cleanup_domid_map(d->domain_id, drhd->iommu); + } + + static int __must_check intel_iommu_map_page(struct domain *d, dfn_t dfn, +-- +2.35.2 + + +From 7cfe3570b1c0b4b19317145fbe4c776f09768fd5 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:25:54 +0200 +Subject: [PATCH 26/32] IOMMU/x86: maintain a per-device pseudo domain ID +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In order to subsequently enable per-device quarantine page tables, we'll +need domain-ID-like identifiers to be inserted in the respective device +(AMD) or context (Intel) table entries alongside the per-device page +table root addresses. + +Make use of "real" domain IDs occupying only half of the value range +coverable by domid_t. + +Note that in VT-d's iommu_alloc() I didn't want to introduce new memory +leaks in case of error, but existing ones don't get plugged - that'll be +the subject of a later change. + +The VT-d changes are slightly asymmetric, but this way we can avoid +assigning pseudo domain IDs to devices which would never be mapped while +still avoiding to add a new parameter to domain_context_unmap(). + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 97af062b89d52c0ecf7af254b53345c97d438e33 +master date: 2022-04-05 14:19:10 +0200 +--- + xen/drivers/passthrough/amd/iommu_detect.c | 8 +++ + xen/drivers/passthrough/amd/pci_amd_iommu.c | 22 ++++++- + xen/drivers/passthrough/pci.c | 11 +++- + xen/drivers/passthrough/vtd/iommu.c | 69 +++++++++++++++++---- + xen/drivers/passthrough/vtd/iommu.h | 1 + + xen/drivers/passthrough/x86/iommu.c | 47 ++++++++++++++ + xen/include/asm-x86/amd-iommu.h | 1 + + xen/include/asm-x86/iommu.h | 4 ++ + xen/include/asm-x86/pci.h | 6 ++ + xen/include/public/xen.h | 3 + + 10 files changed, 156 insertions(+), 16 deletions(-) + +diff --git a/xen/drivers/passthrough/amd/iommu_detect.c b/xen/drivers/passthrough/amd/iommu_detect.c +index d782e66eee..0df10f25b0 100644 +--- a/xen/drivers/passthrough/amd/iommu_detect.c ++++ b/xen/drivers/passthrough/amd/iommu_detect.c +@@ -183,6 +183,11 @@ int __init amd_iommu_detect_one_acpi( + if ( rt ) + goto out; + ++ iommu->domid_map = iommu_init_domid(); ++ rt = -ENOMEM; ++ if ( !iommu->domid_map ) ++ goto out; ++ + rt = pci_ro_device(iommu->seg, bus, PCI_DEVFN(dev, func)); + if ( rt ) + printk(XENLOG_ERR +@@ -194,7 +199,10 @@ int __init amd_iommu_detect_one_acpi( + + out: + if ( rt ) ++ { ++ xfree(iommu->domid_map); + xfree(iommu); ++ } + + return rt; + } +diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c +index 14483e85ae..b07091e71e 100644 +--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c ++++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c +@@ -563,6 +563,8 @@ static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev) + struct amd_iommu *iommu; + u16 bdf; + struct ivrs_mappings *ivrs_mappings; ++ bool fresh_domid = false; ++ int ret; + + if ( !pdev->domain ) + return -EINVAL; +@@ -626,7 +628,22 @@ static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev) + spin_unlock_irqrestore(&iommu->lock, flags); + } + +- return amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev); ++ if ( iommu_quarantine && pdev->arch.pseudo_domid == DOMID_INVALID ) ++ { ++ pdev->arch.pseudo_domid = iommu_alloc_domid(iommu->domid_map); ++ if ( pdev->arch.pseudo_domid == DOMID_INVALID ) ++ return -ENOSPC; ++ fresh_domid = true; ++ } ++ ++ ret = amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev); ++ if ( ret && fresh_domid ) ++ { ++ iommu_free_domid(pdev->arch.pseudo_domid, iommu->domid_map); ++ pdev->arch.pseudo_domid = DOMID_INVALID; ++ } ++ ++ return ret; + } + + static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev) +@@ -651,6 +668,9 @@ static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev) + + amd_iommu_disable_domain_device(pdev->domain, iommu, devfn, pdev); + ++ iommu_free_domid(pdev->arch.pseudo_domid, iommu->domid_map); ++ pdev->arch.pseudo_domid = DOMID_INVALID; ++ + ivrs_mappings = get_ivrs_mappings(pdev->seg); + bdf = PCI_BDF2(pdev->bus, devfn); + if ( amd_iommu_perdev_intremap && +diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c +index 32510351cf..97e42261eb 100644 +--- a/xen/drivers/passthrough/pci.c ++++ b/xen/drivers/passthrough/pci.c +@@ -338,6 +338,7 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn) + *((u8*) &pdev->bus) = bus; + *((u8*) &pdev->devfn) = devfn; + pdev->domain = NULL; ++ pdev->arch.pseudo_domid = DOMID_INVALID; + INIT_LIST_HEAD(&pdev->msi_list); + + pos = pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), +@@ -1353,9 +1354,13 @@ static int _dump_pci_devices(struct pci_seg *pseg, void *arg) + + list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list ) + { +- printk("%04x:%02x:%02x.%u - %pd - node %-3d - MSIs < ", +- pseg->nr, pdev->bus, +- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->domain, ++ printk("%04x:%02x:%02x.%u - ", pseg->nr, pdev->bus, ++ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); ++ if ( pdev->domain == dom_io ) ++ printk("DomIO:%x", pdev->arch.pseudo_domid); ++ else ++ printk("%pd", pdev->domain); ++ printk(" - node %-3d - MSIs < ", + (pdev->node != NUMA_NO_NODE) ? pdev->node : -1); + list_for_each_entry ( msi, &pdev->msi_list, list ) + printk("%d ", msi->irq); +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index 6388d97d26..fc89f3e4c5 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -22,6 +22,7 @@ + #include <xen/sched.h> + #include <xen/xmalloc.h> + #include <xen/domain_page.h> ++#include <xen/err.h> + #include <xen/iocap.h> + #include <xen/iommu.h> + #include <xen/numa.h> +@@ -1192,7 +1193,7 @@ int __init iommu_alloc(struct acpi_drhd_unit *drhd) + { + struct vtd_iommu *iommu; + unsigned long sagaw, nr_dom; +- int agaw; ++ int agaw, rc; + + if ( nr_iommus >= MAX_IOMMUS ) + { +@@ -1285,7 +1286,16 @@ int __init iommu_alloc(struct acpi_drhd_unit *drhd) + if ( !iommu->domid_map ) + return -ENOMEM; + ++ iommu->pseudo_domid_map = iommu_init_domid(); ++ rc = -ENOMEM; ++ if ( !iommu->pseudo_domid_map ) ++ goto free; ++ + return 0; ++ ++ free: ++ iommu_free(drhd); ++ return rc; + } + + void __init iommu_free(struct acpi_drhd_unit *drhd) +@@ -1308,6 +1318,7 @@ void __init iommu_free(struct acpi_drhd_unit *drhd) + + xfree(iommu->domid_bitmap); + xfree(iommu->domid_map); ++ xfree(iommu->pseudo_domid_map); + + if ( iommu->msi.irq >= 0 ) + destroy_irq(iommu->msi.irq); +@@ -1583,8 +1594,8 @@ int domain_context_mapping_one( + return rc ?: pdev && prev_dom; + } + +-static int domain_context_unmap(struct domain *d, uint8_t devfn, +- struct pci_dev *pdev); ++static const struct acpi_drhd_unit *domain_context_unmap( ++ struct domain *d, uint8_t devfn, struct pci_dev *pdev); + + static int domain_context_mapping(struct domain *domain, u8 devfn, + struct pci_dev *pdev) +@@ -1592,6 +1603,7 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + struct acpi_drhd_unit *drhd; + const struct acpi_rmrr_unit *rmrr; + paddr_t pgd_maddr = dom_iommu(domain)->arch.pgd_maddr; ++ domid_t orig_domid = pdev->arch.pseudo_domid; + int ret = 0; + unsigned int i, mode = 0; + uint16_t seg = pdev->seg, bdf; +@@ -1652,6 +1664,14 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + break; + + case DEV_TYPE_PCIe_ENDPOINT: ++ if ( iommu_quarantine && orig_domid == DOMID_INVALID ) ++ { ++ pdev->arch.pseudo_domid = ++ iommu_alloc_domid(drhd->iommu->pseudo_domid_map); ++ if ( pdev->arch.pseudo_domid == DOMID_INVALID ) ++ return -ENOSPC; ++ } ++ + if ( iommu_debug ) + printk(VTDPREFIX "d%d:PCIe: map %04x:%02x:%02x.%u\n", + domain->domain_id, seg, bus, +@@ -1667,6 +1687,14 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + break; + + case DEV_TYPE_PCI: ++ if ( iommu_quarantine && orig_domid == DOMID_INVALID ) ++ { ++ pdev->arch.pseudo_domid = ++ iommu_alloc_domid(drhd->iommu->pseudo_domid_map); ++ if ( pdev->arch.pseudo_domid == DOMID_INVALID ) ++ return -ENOSPC; ++ } ++ + if ( iommu_debug ) + printk(VTDPREFIX "d%d:PCI: map %04x:%02x:%02x.%u\n", + domain->domain_id, seg, bus, +@@ -1742,6 +1770,13 @@ static int domain_context_mapping(struct domain *domain, u8 devfn, + if ( !ret && devfn == pdev->devfn ) + pci_vtd_quirk(pdev); + ++ if ( ret && drhd && orig_domid == DOMID_INVALID ) ++ { ++ iommu_free_domid(pdev->arch.pseudo_domid, ++ drhd->iommu->pseudo_domid_map); ++ pdev->arch.pseudo_domid = DOMID_INVALID; ++ } ++ + return ret; + } + +@@ -1824,8 +1859,10 @@ int domain_context_unmap_one( + return rc; + } + +-static int domain_context_unmap(struct domain *domain, u8 devfn, +- struct pci_dev *pdev) ++static const struct acpi_drhd_unit *domain_context_unmap( ++ struct domain *domain, ++ uint8_t devfn, ++ struct pci_dev *pdev) + { + struct acpi_drhd_unit *drhd; + struct vtd_iommu *iommu; +@@ -1834,7 +1871,7 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + + drhd = acpi_find_matched_drhd_unit(pdev); + if ( !drhd ) +- return -ENODEV; ++ return ERR_PTR(-ENODEV); + iommu = drhd->iommu; + + switch ( pdev->type ) +@@ -1845,7 +1882,7 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + domain->domain_id, seg, bus, + PCI_SLOT(devfn), PCI_FUNC(devfn)); + if ( !is_hardware_domain(domain) ) +- return -EPERM; ++ return ERR_PTR(-EPERM); + goto out; + + case DEV_TYPE_PCIe_BRIDGE: +@@ -1923,7 +1960,7 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, + check_cleanup_domid_map(domain, pdev, iommu); + + out: +- return ret; ++ return ret ? ERR_PTR(ret) : drhd; + } + + static void iommu_domain_teardown(struct domain *d) +@@ -2145,16 +2182,17 @@ static int intel_iommu_enable_device(struct pci_dev *pdev) + + static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) + { ++ const struct acpi_drhd_unit *drhd; + struct acpi_rmrr_unit *rmrr; + u16 bdf; +- int ret, i; ++ unsigned int i; + + if ( !pdev->domain ) + return -EINVAL; + +- ret = domain_context_unmap(pdev->domain, devfn, pdev); +- if ( ret ) +- return ret; ++ drhd = domain_context_unmap(pdev->domain, devfn, pdev); ++ if ( IS_ERR(drhd) ) ++ return PTR_ERR(drhd); + + for_each_rmrr_device ( rmrr, bdf, i ) + { +@@ -2171,6 +2209,13 @@ static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) + rmrr->end_address, 0); + } + ++ if ( drhd ) ++ { ++ iommu_free_domid(pdev->arch.pseudo_domid, ++ drhd->iommu->pseudo_domid_map); ++ pdev->arch.pseudo_domid = DOMID_INVALID; ++ } ++ + return 0; + } + +diff --git a/xen/drivers/passthrough/vtd/iommu.h b/xen/drivers/passthrough/vtd/iommu.h +index 503b07ffb7..be44fc017f 100644 +--- a/xen/drivers/passthrough/vtd/iommu.h ++++ b/xen/drivers/passthrough/vtd/iommu.h +@@ -535,6 +535,7 @@ struct vtd_iommu { + } flush; + + struct list_head ats_devices; ++ unsigned long *pseudo_domid_map; /* "pseudo" domain id bitmap */ + unsigned long *domid_bitmap; /* domain id bitmap */ + u16 *domid_map; /* domain id mapping array */ + uint32_t version; +diff --git a/xen/drivers/passthrough/x86/iommu.c b/xen/drivers/passthrough/x86/iommu.c +index 818d28f770..f900bff60b 100644 +--- a/xen/drivers/passthrough/x86/iommu.c ++++ b/xen/drivers/passthrough/x86/iommu.c +@@ -346,6 +346,53 @@ void __hwdom_init arch_iommu_hwdom_init(struct domain *d) + return; + } + ++unsigned long *__init iommu_init_domid(void) ++{ ++ if ( !iommu_quarantine ) ++ return ZERO_BLOCK_PTR; ++ ++ BUILD_BUG_ON(DOMID_MASK * 2U >= UINT16_MAX); ++ ++ return xzalloc_array(unsigned long, ++ BITS_TO_LONGS(UINT16_MAX - DOMID_MASK)); ++} ++ ++domid_t iommu_alloc_domid(unsigned long *map) ++{ ++ /* ++ * This is used uniformly across all IOMMUs, such that on typical ++ * systems we wouldn't re-use the same ID very quickly (perhaps never). ++ */ ++ static unsigned int start; ++ unsigned int idx = find_next_zero_bit(map, UINT16_MAX - DOMID_MASK, start); ++ ++ ASSERT(pcidevs_locked()); ++ ++ if ( idx >= UINT16_MAX - DOMID_MASK ) ++ idx = find_first_zero_bit(map, UINT16_MAX - DOMID_MASK); ++ if ( idx >= UINT16_MAX - DOMID_MASK ) ++ return DOMID_INVALID; ++ ++ __set_bit(idx, map); ++ ++ start = idx + 1; ++ ++ return idx | (DOMID_MASK + 1); ++} ++ ++void iommu_free_domid(domid_t domid, unsigned long *map) ++{ ++ ASSERT(pcidevs_locked()); ++ ++ if ( domid == DOMID_INVALID ) ++ return; ++ ++ ASSERT(domid > DOMID_MASK); ++ ++ if ( !__test_and_clear_bit(domid & DOMID_MASK, map) ) ++ BUG(); ++} ++ + /* + * Local variables: + * mode: C +diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h +index 829e1b1755..452ce97c02 100644 +--- a/xen/include/asm-x86/amd-iommu.h ++++ b/xen/include/asm-x86/amd-iommu.h +@@ -94,6 +94,7 @@ struct amd_iommu { + struct ring_buffer cmd_buffer; + struct ring_buffer event_log; + struct ring_buffer ppr_log; ++ unsigned long *domid_map; + + int exclusion_enable; + int exclusion_allow_all; +diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h +index aaf9455b8e..389417d198 100644 +--- a/xen/include/asm-x86/iommu.h ++++ b/xen/include/asm-x86/iommu.h +@@ -130,6 +130,10 @@ int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq, + iommu_vcall(ops, sync_cache, addr, size); \ + }) + ++unsigned long *iommu_init_domid(void); ++domid_t iommu_alloc_domid(unsigned long *map); ++void iommu_free_domid(domid_t domid, unsigned long *map); ++ + #endif /* !__ARCH_X86_IOMMU_H__ */ + /* + * Local variables: +diff --git a/xen/include/asm-x86/pci.h b/xen/include/asm-x86/pci.h +index cc05045e9c..70ed48e309 100644 +--- a/xen/include/asm-x86/pci.h ++++ b/xen/include/asm-x86/pci.h +@@ -15,6 +15,12 @@ + + struct arch_pci_dev { + vmask_t used_vectors; ++ /* ++ * These fields are (de)initialized under pcidevs-lock. Other uses of ++ * them don't race (de)initialization and hence don't strictly need any ++ * locking. ++ */ ++ domid_t pseudo_domid; + }; + + int pci_conf_write_intercept(unsigned int seg, unsigned int bdf, +diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h +index d2198dffad..75b1619d0d 100644 +--- a/xen/include/public/xen.h ++++ b/xen/include/public/xen.h +@@ -614,6 +614,9 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t); + /* Idle domain. */ + #define DOMID_IDLE xen_mk_uint(0x7FFF) + ++/* Mask for valid domain id values */ ++#define DOMID_MASK xen_mk_uint(0x7FFF) ++ + #ifndef __ASSEMBLY__ + + typedef uint16_t domid_t; +-- +2.35.2 + + +From e6d6b5ba030a8d2d81bf902e4bc2a8530b3576ae Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:26:41 +0200 +Subject: [PATCH 27/32] IOMMU/x86: drop TLB flushes from quarantine_init() + hooks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The page tables just created aren't hooked up yet anywhere, so there's +nothing that could be present in any TLB, and hence nothing to flush. +Dropping this flush is, at least on the VT-d side, a prereq to per- +device domain ID use when quarantining devices, as dom_io isn't going +to be assigned a DID anymore: The warning in get_iommu_did() would +trigger. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +master commit: 54c5cef49239e2f27ec3b3fc8804bf57aa4bf46d +master date: 2022-04-05 14:19:42 +0200 +--- + xen/drivers/passthrough/amd/iommu_map.c | 2 -- + xen/drivers/passthrough/vtd/iommu.c | 5 +---- + 2 files changed, 1 insertion(+), 6 deletions(-) + +diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c +index 45559f9678..3c7cd7ed9e 100644 +--- a/xen/drivers/passthrough/amd/iommu_map.c ++++ b/xen/drivers/passthrough/amd/iommu_map.c +@@ -595,8 +595,6 @@ int __init amd_iommu_quarantine_init(struct domain *d) + out: + spin_unlock(&hd->arch.mapping_lock); + +- amd_iommu_flush_all_pages(d); +- + /* Pages leaked in failure case */ + return level ? -ENOMEM : 0; + } +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index fc89f3e4c5..e5c50429d2 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -2894,7 +2894,6 @@ static int __init intel_iommu_quarantine_init(struct domain *d) + struct dma_pte *parent; + unsigned int agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH); + unsigned int level = agaw_to_level(agaw); +- int rc; + + if ( hd->arch.pgd_maddr ) + { +@@ -2941,10 +2940,8 @@ static int __init intel_iommu_quarantine_init(struct domain *d) + out: + spin_unlock(&hd->arch.mapping_lock); + +- rc = iommu_flush_iotlb_all(d); +- + /* Pages leaked in failure case */ +- return level ? -ENOMEM : rc; ++ return level ? -ENOMEM : 0; + } + + const struct iommu_ops __initconstrel intel_iommu_ops = { +-- +2.35.2 + + +From 454d5351a93d2438778630843cf3e77da0772167 Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:27:09 +0200 +Subject: [PATCH 28/32] AMD/IOMMU: abstract maximum number of page table levels + +We will want to use the constant elsewhere. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +master commit: a038b514c1e970a8dc32229cbd31f6769ee61ad5 +master date: 2022-04-05 14:20:04 +0200 +--- + xen/drivers/passthrough/amd/iommu_map.c | 2 +- + xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 1 + + xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 2 +- + 3 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c +index 3c7cd7ed9e..db396dd1d4 100644 +--- a/xen/drivers/passthrough/amd/iommu_map.c ++++ b/xen/drivers/passthrough/amd/iommu_map.c +@@ -260,7 +260,7 @@ static int iommu_pde_from_dfn(struct domain *d, unsigned long dfn, + table = hd->arch.root_table; + level = hd->arch.paging_mode; + +- BUG_ON( table == NULL || level < 1 || level > 6 ); ++ BUG_ON( table == NULL || level < 1 || level > IOMMU_MAX_PT_LEVELS ); + + /* + * A frame number past what the current page tables can represent can't +diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +index a54d6e9fc6..c46247cb24 100644 +--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h ++++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +@@ -110,6 +110,7 @@ struct amd_iommu_dte { + bool tv:1; + unsigned int :5; + unsigned int had:2; ++#define IOMMU_MAX_PT_LEVELS 6 + unsigned int paging_mode:3; + uint64_t pt_root:40; + bool ppr:1; +diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +index 52c889ade0..2a3bc47ab5 100644 +--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h ++++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +@@ -193,7 +193,7 @@ static inline int amd_iommu_get_paging_mode(unsigned long max_frames) + while ( max_frames > PTE_PER_TABLE_SIZE ) + { + max_frames = PTE_PER_TABLE_ALIGN(max_frames) >> PTE_PER_TABLE_SHIFT; +- if ( ++level > 6 ) ++ if ( ++level > IOMMU_MAX_PT_LEVELS ) + return -ENOMEM; + } + +-- +2.35.2 + + +From 169a2834ef5d723091f187a5d6493ae77825757a Mon Sep 17 00:00:00 2001 +From: Jan Beulich <jbeulich@suse.com> +Date: Tue, 5 Apr 2022 15:27:36 +0200 +Subject: [PATCH 29/32] IOMMU/x86: use per-device page tables for quarantining +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Devices with RMRRs / unity mapped regions, due to it being unspecified +how/when these memory regions may be accessed, may not be left +disconnected from the mappings of these regions (as long as it's not +certain that the device has been fully quiesced). Hence even the page +tables used when quarantining such devices need to have mappings of +those regions. This implies installing page tables in the first place +even when not in scratch-page quarantining mode. + +This is CVE-2022-26361 / part of XSA-400. + +While for the purpose here it would be sufficient to have devices with +RMRRs / unity mapped regions use per-device page tables, extend this to +all devices (in scratch-page quarantining mode). This allows the leaf +pages to be mapped r/w, thus covering also memory writes (rather than +just reads) issued by non-quiescent devices. + +Set up quarantine page tables as late as possible, yet early enough to +not encounter failure during de-assign. This means setup generally +happens in assign_device(), while (for now) the one in deassign_device() +is there mainly to be on the safe side. + +In VT-d's DID allocation function don't require the IOMMU lock to be +held anymore: All involved code paths hold pcidevs_lock, so this way we +avoid the need to acquire the IOMMU lock around the new call to +context_set_domain_id(). + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Reviewed-by: Paul Durrant <paul@xen.org> +Reviewed-by: Kevin Tian <kevin.tian@intel.com> +Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> +master commit: 14dd241aad8af447680ac73e8579990e2c09c1e7 +master date: 2022-04-05 14:24:18 +0200 +--- + xen/arch/x86/mm/p2m.c | 2 +- + xen/drivers/passthrough/amd/iommu_map.c | 155 ++++++++--- + xen/drivers/passthrough/amd/pci_amd_iommu.c | 35 ++- + xen/drivers/passthrough/iommu.c | 18 +- + xen/drivers/passthrough/pci.c | 20 +- + xen/drivers/passthrough/vtd/iommu.c | 247 +++++++++++++----- + xen/drivers/passthrough/vtd/iommu.h | 2 +- + xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 3 +- + xen/include/asm-x86/pci.h | 13 + + xen/include/xen/iommu.h | 3 +- + 10 files changed, 363 insertions(+), 135 deletions(-) + +diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c +index a6bfda010a..91f7b7760c 100644 +--- a/xen/arch/x86/mm/p2m.c ++++ b/xen/arch/x86/mm/p2m.c +@@ -1453,7 +1453,7 @@ int set_identity_p2m_entry(struct domain *d, unsigned long gfn_l, + struct p2m_domain *p2m = p2m_get_hostp2m(d); + int ret; + +- if ( !paging_mode_translate(p2m->domain) ) ++ if ( !paging_mode_translate(d) ) + { + if ( !is_iommu_enabled(d) ) + return 0; +diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c +index db396dd1d4..8b7d5b7c7b 100644 +--- a/xen/drivers/passthrough/amd/iommu_map.c ++++ b/xen/drivers/passthrough/amd/iommu_map.c +@@ -539,64 +539,137 @@ int amd_iommu_reserve_domain_unity_unmap(struct domain *d, + return rc; + } + +-int __init amd_iommu_quarantine_init(struct domain *d) ++static int fill_qpt(union amd_iommu_pte *this, unsigned int level, ++ struct page_info *pgs[IOMMU_MAX_PT_LEVELS], ++ struct pci_dev *pdev) + { +- struct domain_iommu *hd = dom_iommu(d); ++ unsigned int i; ++ int rc = 0; ++ ++ for ( i = 0; !rc && i < PTE_PER_TABLE_SIZE; ++i ) ++ { ++ union amd_iommu_pte *pte = &this[i], *next; ++ ++ if ( !pte->pr ) ++ { ++ if ( !pgs[level] ) ++ { ++ /* ++ * The pgtable allocator is fine for the leaf page, as well as ++ * page table pages, and the resulting allocations are always ++ * zeroed. ++ */ ++ pgs[level] = alloc_amd_iommu_pgtable(); ++ if ( !pgs[level] ) ++ { ++ rc = -ENOMEM; ++ break; ++ } ++ ++ page_list_add(pgs[level], &pdev->arch.pgtables_list); ++ ++ if ( level ) ++ { ++ next = __map_domain_page(pgs[level]); ++ rc = fill_qpt(next, level - 1, pgs, pdev); ++ unmap_domain_page(next); ++ } ++ } ++ ++ /* ++ * PDEs are essentially a subset of PTEs, so this function ++ * is fine to use even at the leaf. ++ */ ++ set_iommu_pde_present(pte, mfn_x(page_to_mfn(pgs[level])), level, ++ true, true); ++ } ++ else if ( level && pte->next_level ) ++ { ++ page_list_add(mfn_to_page(_mfn(pte->mfn)), ++ &pdev->arch.pgtables_list); ++ next = map_domain_page(_mfn(pte->mfn)); ++ rc = fill_qpt(next, level - 1, pgs, pdev); ++ unmap_domain_page(next); ++ } ++ } ++ ++ return rc; ++} ++ ++int amd_iommu_quarantine_init(struct pci_dev *pdev) ++{ ++ struct domain_iommu *hd = dom_iommu(dom_io); + unsigned long end_gfn = + 1ul << (DEFAULT_DOMAIN_ADDRESS_WIDTH - PAGE_SHIFT); + unsigned int level = amd_iommu_get_paging_mode(end_gfn); +- union amd_iommu_pte *table; ++ unsigned int req_id = get_dma_requestor_id(pdev->seg, pdev->sbdf.bdf); ++ const struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(pdev->seg); ++ int rc; ++ ++ ASSERT(pcidevs_locked()); ++ ASSERT(!hd->arch.root_table); + +- if ( hd->arch.root_table ) ++ ASSERT(pdev->arch.pseudo_domid != DOMID_INVALID); ++ ++ if ( pdev->arch.amd.root_table ) + { +- ASSERT_UNREACHABLE(); ++ clear_domain_page(pdev->arch.leaf_mfn); + return 0; + } + +- spin_lock(&hd->arch.mapping_lock); ++ pdev->arch.amd.root_table = alloc_amd_iommu_pgtable(); ++ if ( !pdev->arch.amd.root_table ) ++ return -ENOMEM; + +- hd->arch.root_table = alloc_amd_iommu_pgtable(); +- if ( !hd->arch.root_table ) +- goto out; ++ /* Transiently install the root into DomIO, for iommu_identity_mapping(). */ ++ hd->arch.root_table = pdev->arch.amd.root_table; ++ ++ rc = amd_iommu_reserve_domain_unity_map(dom_io, ++ ivrs_mappings[req_id].unity_map, ++ 0); + +- table = __map_domain_page(hd->arch.root_table); +- while ( level ) ++ iommu_identity_map_teardown(dom_io); ++ hd->arch.root_table = NULL; ++ ++ if ( rc ) ++ printk("%04x:%02x:%02x.%u: quarantine unity mapping failed\n", ++ pdev->seg, pdev->bus, ++ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); ++ else + { +- struct page_info *pg; +- unsigned int i; +- +- /* +- * The pgtable allocator is fine for the leaf page, as well as +- * page table pages, and the resulting allocations are always +- * zeroed. +- */ +- pg = alloc_amd_iommu_pgtable(); +- if ( !pg ) +- break; +- +- for ( i = 0; i < PTE_PER_TABLE_SIZE; i++ ) +- { +- union amd_iommu_pte *pde = &table[i]; ++ union amd_iommu_pte *root; ++ struct page_info *pgs[IOMMU_MAX_PT_LEVELS] = {}; + +- /* +- * PDEs are essentially a subset of PTEs, so this function +- * is fine to use even at the leaf. +- */ +- set_iommu_pde_present(pde, mfn_x(page_to_mfn(pg)), level - 1, +- false, true); +- } ++ spin_lock(&hd->arch.mapping_lock); + +- unmap_domain_page(table); +- table = __map_domain_page(pg); +- level--; ++ root = __map_domain_page(pdev->arch.amd.root_table); ++ rc = fill_qpt(root, level - 1, pgs, pdev); ++ unmap_domain_page(root); ++ ++ pdev->arch.leaf_mfn = page_to_mfn(pgs[0]); ++ ++ spin_unlock(&hd->arch.mapping_lock); + } +- unmap_domain_page(table); + +- out: +- spin_unlock(&hd->arch.mapping_lock); ++ if ( rc ) ++ amd_iommu_quarantine_teardown(pdev); ++ ++ return rc; ++} ++ ++void amd_iommu_quarantine_teardown(struct pci_dev *pdev) ++{ ++ struct page_info *pg; ++ ++ ASSERT(pcidevs_locked()); ++ ++ if ( !pdev->arch.amd.root_table ) ++ return; ++ ++ while ( (pg = page_list_remove_head(&pdev->arch.pgtables_list)) ) ++ free_amd_iommu_pgtable(pg); + +- /* Pages leaked in failure case */ +- return level ? -ENOMEM : 0; ++ pdev->arch.amd.root_table = NULL; + } + + /* +diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c +index b07091e71e..e5c02ca710 100644 +--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c ++++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c +@@ -125,6 +125,8 @@ static int __must_check amd_iommu_setup_domain_device( + u8 bus = pdev->bus; + struct domain_iommu *hd = dom_iommu(domain); + const struct ivrs_mappings *ivrs_dev; ++ const struct page_info *root_pg; ++ domid_t domid; + + BUG_ON(!hd->arch.paging_mode || !iommu->dev_table.buffer); + +@@ -144,14 +146,25 @@ static int __must_check amd_iommu_setup_domain_device( + dte = &table[req_id]; + ivrs_dev = &get_ivrs_mappings(iommu->seg)[req_id]; + ++ if ( domain != dom_io ) ++ { ++ root_pg = hd->arch.root_table; ++ domid = domain->domain_id; ++ } ++ else ++ { ++ root_pg = pdev->arch.amd.root_table; ++ domid = pdev->arch.pseudo_domid; ++ } ++ + spin_lock_irqsave(&iommu->lock, flags); + + if ( !dte->v || !dte->tv ) + { + /* bind DTE to domain page-tables */ + rc = amd_iommu_set_root_page_table( +- dte, page_to_maddr(hd->arch.root_table), +- domain->domain_id, hd->arch.paging_mode, sr_flags); ++ dte, page_to_maddr(root_pg), domid, ++ hd->arch.paging_mode, sr_flags); + if ( rc ) + { + ASSERT(rc < 0); +@@ -175,7 +188,7 @@ static int __must_check amd_iommu_setup_domain_device( + + amd_iommu_flush_device(iommu, req_id); + } +- else if ( dte->pt_root != mfn_x(page_to_mfn(hd->arch.root_table)) ) ++ else if ( dte->pt_root != mfn_x(page_to_mfn(root_pg)) ) + { + /* + * Strictly speaking if the device is the only one with this requestor +@@ -188,8 +201,8 @@ static int __must_check amd_iommu_setup_domain_device( + rc = -EOPNOTSUPP; + else + rc = amd_iommu_set_root_page_table( +- dte, page_to_maddr(hd->arch.root_table), +- domain->domain_id, hd->arch.paging_mode, sr_flags); ++ dte, page_to_maddr(root_pg), domid, ++ hd->arch.paging_mode, sr_flags); + if ( rc < 0 ) + { + spin_unlock_irqrestore(&iommu->lock, flags); +@@ -208,6 +221,7 @@ static int __must_check amd_iommu_setup_domain_device( + * intended anyway. + */ + !pdev->domain->is_dying && ++ pdev->domain != dom_io && + (any_pdev_behind_iommu(pdev->domain, pdev, iommu) || + pdev->phantom_stride) ) + printk(" %04x:%02x:%02x.%u: reassignment may cause %pd data corruption\n", +@@ -238,9 +252,8 @@ static int __must_check amd_iommu_setup_domain_device( + AMD_IOMMU_DEBUG("Setup I/O page table: device id = %#x, type = %#x, " + "root table = %#"PRIx64", " + "domain = %d, paging mode = %d\n", +- req_id, pdev->type, +- page_to_maddr(hd->arch.root_table), +- domain->domain_id, hd->arch.paging_mode); ++ req_id, pdev->type, page_to_maddr(root_pg), ++ domid, hd->arch.paging_mode); + + ASSERT(pcidevs_locked()); + +@@ -313,7 +326,7 @@ static int iov_enable_xt(void) + + int amd_iommu_alloc_root(struct domain_iommu *hd) + { +- if ( unlikely(!hd->arch.root_table) ) ++ if ( unlikely(!hd->arch.root_table) && hd != dom_iommu(dom_io) ) + { + hd->arch.root_table = alloc_amd_iommu_pgtable(); + if ( !hd->arch.root_table ) +@@ -404,7 +417,7 @@ static void amd_iommu_disable_domain_device(const struct domain *domain, + + AMD_IOMMU_DEBUG("Disable: device id = %#x, " + "domain = %d, paging mode = %d\n", +- req_id, domain->domain_id, ++ req_id, dte->domain_id, + dom_iommu(domain)->arch.paging_mode); + } + spin_unlock_irqrestore(&iommu->lock, flags); +@@ -668,6 +681,8 @@ static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev) + + amd_iommu_disable_domain_device(pdev->domain, iommu, devfn, pdev); + ++ amd_iommu_quarantine_teardown(pdev); ++ + iommu_free_domid(pdev->arch.pseudo_domid, iommu->domid_map); + pdev->arch.pseudo_domid = DOMID_INVALID; + +diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c +index 93d4377978..9aef696d90 100644 +--- a/xen/drivers/passthrough/iommu.c ++++ b/xen/drivers/passthrough/iommu.c +@@ -450,21 +450,21 @@ int iommu_iotlb_flush_all(struct domain *d, unsigned int flush_flags) + return rc; + } + +-static int __init iommu_quarantine_init(void) ++int iommu_quarantine_dev_init(device_t *dev) + { + const struct domain_iommu *hd = dom_iommu(dom_io); +- int rc; + +- dom_io->options |= XEN_DOMCTL_CDF_iommu; ++ if ( !iommu_quarantine || !hd->platform_ops->quarantine_init ) ++ return 0; + +- rc = iommu_domain_init(dom_io, 0); +- if ( rc ) +- return rc; ++ return iommu_call(hd->platform_ops, quarantine_init, dev); ++} + +- if ( !hd->platform_ops->quarantine_init ) +- return 0; ++static int __init iommu_quarantine_init(void) ++{ ++ dom_io->options |= XEN_DOMCTL_CDF_iommu; + +- return hd->platform_ops->quarantine_init(dom_io); ++ return iommu_domain_init(dom_io, 0); + } + + int __init iommu_setup(void) +diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c +index 97e42261eb..1a1a387458 100644 +--- a/xen/drivers/passthrough/pci.c ++++ b/xen/drivers/passthrough/pci.c +@@ -929,9 +929,16 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus, + return -ENODEV; + + /* De-assignment from dom_io should de-quarantine the device */ +- target = ((pdev->quarantine || iommu_quarantine) && +- pdev->domain != dom_io) ? +- dom_io : hardware_domain; ++ if ( (pdev->quarantine || iommu_quarantine) && pdev->domain != dom_io ) ++ { ++ ret = iommu_quarantine_dev_init(pci_to_dev(pdev)); ++ if ( ret ) ++ return ret; ++ ++ target = dom_io; ++ } ++ else ++ target = hardware_domain; + + while ( pdev->phantom_stride ) + { +@@ -1547,6 +1554,13 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag) + msixtbl_init(d); + } + ++ if ( pdev->domain != dom_io ) ++ { ++ rc = iommu_quarantine_dev_init(pci_to_dev(pdev)); ++ if ( rc ) ++ goto done; ++ } ++ + pdev->fault.count = 0; + + if ( (rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev), flag)) ) +diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c +index e5c50429d2..6571b5dde4 100644 +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -43,6 +43,12 @@ + #include "vtd.h" + #include "../ats.h" + ++#define DEVICE_DOMID(d, pdev) ((d) != dom_io ? (d)->domain_id \ ++ : (pdev)->arch.pseudo_domid) ++#define DEVICE_PGTABLE(d, pdev) ((d) != dom_io \ ++ ? dom_iommu(d)->arch.pgd_maddr \ ++ : (pdev)->arch.vtd.pgd_maddr) ++ + /* Possible unfiltered LAPIC/MSI messages from untrusted sources? */ + bool __read_mostly untrusted_msi; + +@@ -78,13 +84,18 @@ static int get_iommu_did(domid_t domid, const struct vtd_iommu *iommu, + + #define DID_FIELD_WIDTH 16 + #define DID_HIGH_OFFSET 8 ++ ++/* ++ * This function may have "context" passed as NULL, to merely obtain a DID ++ * for "domid". ++ */ + static int context_set_domain_id(struct context_entry *context, + domid_t domid, struct vtd_iommu *iommu) + { + unsigned long nr_dom, i; + int found = 0; + +- ASSERT(spin_is_locked(&iommu->lock)); ++ ASSERT(pcidevs_locked()); + + nr_dom = cap_ndoms(iommu->cap); + i = find_first_bit(iommu->domid_bitmap, nr_dom); +@@ -110,8 +121,13 @@ static int context_set_domain_id(struct context_entry *context, + } + + set_bit(i, iommu->domid_bitmap); +- context->hi &= ~(((1 << DID_FIELD_WIDTH) - 1) << DID_HIGH_OFFSET); +- context->hi |= (i & ((1 << DID_FIELD_WIDTH) - 1)) << DID_HIGH_OFFSET; ++ ++ if ( context ) ++ { ++ context->hi &= ~(((1 << DID_FIELD_WIDTH) - 1) << DID_HIGH_OFFSET); ++ context->hi |= (i & ((1 << DID_FIELD_WIDTH) - 1)) << DID_HIGH_OFFSET; ++ } ++ + return 0; + } + +@@ -161,8 +177,12 @@ static void check_cleanup_domid_map(struct domain *d, + const struct pci_dev *exclude, + struct vtd_iommu *iommu) + { +- bool found = any_pdev_behind_iommu(d, exclude, iomm |