]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 7 Jun 2026 07:41:06 +0000 (09:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 7 Jun 2026 07:41:06 +0000 (09:41 +0200)
added patches:
hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch
hwmon-pmbus-adm1266-serialize-nvmem-blackbox-read-with-pmbus_lock.patch
hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch
memfd-deny-writeable-mappings-when-implying-seal_write.patch
mm-memfd-fix-spelling-and-grammatical-issues.patch
mm-perform-all-memfd-seal-checks-in-a-single-place.patch

queue-6.12/hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch [new file with mode: 0644]
queue-6.12/hwmon-pmbus-adm1266-serialize-nvmem-blackbox-read-with-pmbus_lock.patch [new file with mode: 0644]
queue-6.12/hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch [new file with mode: 0644]
queue-6.12/memfd-deny-writeable-mappings-when-implying-seal_write.patch [new file with mode: 0644]
queue-6.12/mm-memfd-fix-spelling-and-grammatical-issues.patch [new file with mode: 0644]
queue-6.12/mm-perform-all-memfd-seal-checks-in-a-single-place.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch b/queue-6.12/hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch
new file mode 100644 (file)
index 0000000..bf4443a
--- /dev/null
@@ -0,0 +1,140 @@
+From stable+bounces-259653-greg=kroah.com@vger.kernel.org Mon Jun  1 21:59:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  1 Jun 2026 15:59:14 -0400
+Subject: hwmon: (pmbus/adm1266) serialize GPIO PMBus accesses with pmbus_lock
+To: stable@vger.kernel.org
+Cc: Abdurrahman Hussain <abdurrahman@nexthop.ai>, Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>, Guenter Roeck <linux@roeck-us.net>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260601195914.1214650-1-sashal@kernel.org>
+
+From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+
+[ Upstream commit bab8c6fb5af8df7e753d196c1262cb78e92ca872 ]
+
+adm1266_gpio_get(), adm1266_gpio_get_multiple(), and
+adm1266_gpio_dbg_show() all issue PMBus reads against the device but
+none of them take pmbus_lock.  The pmbus_core framework holds
+pmbus_lock around its own multi-transaction sequences (notably the
+"set PAGE, then read paged register" pattern used by hwmon
+attributes), so an unlocked GPIO accessor can land between a PAGE
+write and the subsequent paged read in another thread and corrupt
+either side's view of the device state machine.
+
+Take pmbus_lock at the top of each of the three accessors via the
+scope-based guard().  The lock is uncontended in the common case and
+adds only a single mutex round-trip per call.
+
+Fixes: d98dfad35c38 ("hwmon: (pmbus/adm1266) Add support for GPIOs")
+Cc: stable@vger.kernel.org
+Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260518-adm1266-gpio-fixes-v3-6-e425e4f88139@nexthop.ai
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+[ open-coded each `guard(pmbus_lock)(data->client)` as explicit `pmbus_lock_interruptible()`/`pmbus_unlock()` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwmon/pmbus/adm1266.c |   40 ++++++++++++++++++++++++++++++++++------
+ 1 file changed, 34 insertions(+), 6 deletions(-)
+
+--- a/drivers/hwmon/pmbus/adm1266.c
++++ b/drivers/hwmon/pmbus/adm1266.c
+@@ -173,7 +173,12 @@ static int adm1266_gpio_get(struct gpio_
+       else
+               pmbus_cmd = ADM1266_PDIO_STATUS;
++      ret = pmbus_lock_interruptible(data->client);
++      if (ret)
++              return ret;
++
+       ret = i2c_smbus_read_block_data(data->client, pmbus_cmd, read_buf);
++      pmbus_unlock(data->client);
+       if (ret < 0)
+               return ret;
+       if (ret < 2)
+@@ -195,11 +200,19 @@ static int adm1266_gpio_get_multiple(str
+       unsigned int gpio_nr;
+       int ret;
++      ret = pmbus_lock_interruptible(data->client);
++      if (ret)
++              return ret;
++
+       ret = i2c_smbus_read_block_data(data->client, ADM1266_GPIO_STATUS, read_buf);
+-      if (ret < 0)
++      if (ret < 0) {
++              pmbus_unlock(data->client);
+               return ret;
+-      if (ret < 2)
++      }
++      if (ret < 2) {
++              pmbus_unlock(data->client);
+               return -EIO;
++      }
+       status = read_buf[0] + (read_buf[1] << 8);
+@@ -210,10 +223,14 @@ static int adm1266_gpio_get_multiple(str
+       }
+       ret = i2c_smbus_read_block_data(data->client, ADM1266_PDIO_STATUS, read_buf);
+-      if (ret < 0)
++      if (ret < 0) {
++              pmbus_unlock(data->client);
+               return ret;
+-      if (ret < 2)
++      }
++      if (ret < 2) {
++              pmbus_unlock(data->client);
+               return -EIO;
++      }
+       status = read_buf[0] + (read_buf[1] << 8);
+@@ -222,6 +239,8 @@ static int adm1266_gpio_get_multiple(str
+                       set_bit(gpio_nr, bits);
+       }
++      pmbus_unlock(data->client);
++
+       return 0;
+ }
+@@ -236,11 +255,16 @@ static void adm1266_gpio_dbg_show(struct
+       int ret;
+       int i;
++      if (pmbus_lock_interruptible(data->client))
++              return;
++
+       for (i = 0; i < ADM1266_GPIO_NR; i++) {
+               write_cmd = adm1266_gpio_mapping[i][1];
+               ret = adm1266_pmbus_block_xfer(data, ADM1266_GPIO_CONFIG, 1, &write_cmd, read_buf);
+-              if (ret != 2)
++              if (ret != 2) {
++                      pmbus_unlock(data->client);
+                       return;
++              }
+               gpio_config = read_buf[0];
+               seq_puts(s, adm1266_names[i]);
+@@ -262,8 +286,10 @@ static void adm1266_gpio_dbg_show(struct
+       write_cmd = 0xFF;
+       ret = adm1266_pmbus_block_xfer(data, ADM1266_PDIO_CONFIG, 1, &write_cmd, read_buf);
+-      if (ret != 32)
++      if (ret != 32) {
++              pmbus_unlock(data->client);
+               return;
++      }
+       for (i = 0; i < ADM1266_PDIO_NR; i++) {
+               seq_puts(s, adm1266_names[ADM1266_GPIO_NR + i]);
+@@ -286,6 +312,8 @@ static void adm1266_gpio_dbg_show(struct
+               seq_puts(s, ")\n");
+       }
++
++      pmbus_unlock(data->client);
+ }
+ static int adm1266_config_gpio(struct adm1266_data *data)
diff --git a/queue-6.12/hwmon-pmbus-adm1266-serialize-nvmem-blackbox-read-with-pmbus_lock.patch b/queue-6.12/hwmon-pmbus-adm1266-serialize-nvmem-blackbox-read-with-pmbus_lock.patch
new file mode 100644 (file)
index 0000000..41d0311
--- /dev/null
@@ -0,0 +1,80 @@
+From stable+bounces-259619-greg=kroah.com@vger.kernel.org Mon Jun  1 18:39:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  1 Jun 2026 12:28:40 -0400
+Subject: hwmon: (pmbus/adm1266) serialize NVMEM blackbox read with pmbus_lock
+To: stable@vger.kernel.org
+Cc: Abdurrahman Hussain <abdurrahman@nexthop.ai>, Guenter Roeck <linux@roeck-us.net>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260601162840.975891-1-sashal@kernel.org>
+
+From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+
+[ Upstream commit 9f1dd8f9491eb840cbea7ffdf4cad031e25f8ae0 ]
+
+adm1266_nvmem_read() is the reg_read callback the NVMEM core invokes
+when userspace reads /sys/bus/nvmem/devices/.../nvmem on this chip.
+On the first byte of every read it does a memset of data->dev_mem,
+walks the device blackbox through adm1266_nvmem_read_blackbox()
+(which issues a chain of PMBus block transactions), and then memcpys
+the refreshed buffer out to userspace.  None of that runs under
+pmbus_lock today.
+
+Two consequences:
+
+  - The PMBus traffic the refresh issues is not serialised against
+    pmbus_core's own multi-step PAGE+register sequences.  A paged
+    hwmon attribute read from another thread can land between a
+    PAGE write and the paged read in either direction and corrupt
+    one side's view of the device state machine.
+
+  - The NVMEM core does not serialise concurrent reg_read calls, so
+    two userspace readers racing at offset 0 can interleave the
+    memset of data->dev_mem with another reader's
+    adm1266_nvmem_read_blackbox() refill or memcpy out, returning
+    torn data to userspace.
+
+Take pmbus_lock at the top of adm1266_nvmem_read() via the
+scope-based guard().  Patch 5 of this series moves
+adm1266_config_nvmem() past pmbus_do_probe() so the lock is
+guaranteed to be live before the callback is reachable from
+userspace.
+
+Fixes: 15609d189302 ("hwmon: (pmbus/adm1266) read blackbox")
+Cc: stable@vger.kernel.org
+Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+Link: https://lore.kernel.org/r/20260518-adm1266-gpio-fixes-v3-7-e425e4f88139@nexthop.ai
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+[ changed `guard(pmbus_lock)(data->client)` to explicit `pmbus_lock_interruptible()`/`pmbus_unlock()` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwmon/pmbus/adm1266.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/hwmon/pmbus/adm1266.c
++++ b/drivers/hwmon/pmbus/adm1266.c
+@@ -398,18 +398,25 @@ static int adm1266_nvmem_read(void *priv
+       if (offset + bytes > data->nvmem_config.size)
+               return -EINVAL;
++      ret = pmbus_lock_interruptible(data->client);
++      if (ret)
++              return ret;
++
+       if (offset == 0) {
+               memset(data->dev_mem, 0, data->nvmem_config.size);
+               ret = adm1266_nvmem_read_blackbox(data, data->dev_mem);
+               if (ret) {
+                       dev_err(&data->client->dev, "Could not read blackbox!");
++                      pmbus_unlock(data->client);
+                       return ret;
+               }
+       }
+       memcpy(val, data->dev_mem + offset, bytes);
++      pmbus_unlock(data->client);
++
+       return 0;
+ }
diff --git a/queue-6.12/hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch b/queue-6.12/hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch
new file mode 100644 (file)
index 0000000..f61e2b1
--- /dev/null
@@ -0,0 +1,54 @@
+From stable+bounces-259583-greg=kroah.com@vger.kernel.org Mon Jun  1 16:51:58 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  1 Jun 2026 10:46:51 -0400
+Subject: hwmon: (pmbus/adm1266) serialize sequencer_state debugfs read with pmbus_lock
+To: stable@vger.kernel.org
+Cc: Abdurrahman Hussain <abdurrahman@nexthop.ai>, Guenter Roeck <linux@roeck-us.net>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260601144651.887662-1-sashal@kernel.org>
+
+From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+
+[ Upstream commit 4e4af55aaca7f6d7673d5f9889ad0529db86a048 ]
+
+adm1266_state_read() backs the sequencer_state debugfs entry and
+issues an i2c_smbus_read_word_data(client, ADM1266_READ_STATE)
+against the device without taking pmbus_lock.  pmbus_core holds
+pmbus_lock around its own multi-transaction sequences (notably the
+"set PAGE, then read paged register" pattern used by hwmon
+attributes), so an unlocked debugfs reader can land between a PAGE
+write and the subsequent paged read in another thread.  READ_STATE
+itself is not paged, so it cannot corrupt PAGE in flight, but the
+same defensive serialisation that applies to the GPIO accessors
+applies here: any direct device access from outside pmbus_core
+should be ordered with respect to pmbus_core's own.
+
+Take pmbus_lock at the top of adm1266_state_read() via the
+scope-based guard().
+
+Fixes: ed1ff457e187 ("hwmon: (pmbus/adm1266) add debugfs for states")
+Cc: stable@vger.kernel.org
+Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+Link: https://lore.kernel.org/r/20260518-adm1266-gpio-fixes-v3-8-e425e4f88139@nexthop.ai
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+[ replaced `guard(pmbus_lock)(client)` with manual `pmbus_lock_interruptible()`/`pmbus_unlock()` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwmon/pmbus/adm1266.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/hwmon/pmbus/adm1266.c
++++ b/drivers/hwmon/pmbus/adm1266.c
+@@ -328,7 +328,12 @@ static int adm1266_state_read(struct seq
+       struct i2c_client *client = to_i2c_client(dev);
+       int ret;
++      ret = pmbus_lock_interruptible(client);
++      if (ret)
++              return ret;
++
+       ret = i2c_smbus_read_word_data(client, ADM1266_READ_STATE);
++      pmbus_unlock(client);
+       if (ret < 0)
+               return ret;
diff --git a/queue-6.12/memfd-deny-writeable-mappings-when-implying-seal_write.patch b/queue-6.12/memfd-deny-writeable-mappings-when-implying-seal_write.patch
new file mode 100644 (file)
index 0000000..f4f47d4
--- /dev/null
@@ -0,0 +1,71 @@
+From stable+bounces-260503-greg=kroah.com@vger.kernel.org Thu Jun  4 16:15:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 09:54:21 -0400
+Subject: memfd: deny writeable mappings when implying SEAL_WRITE
+To: stable@vger.kernel.org
+Cc: "Pratyush Yadav (Google)" <pratyush@kernel.org>, Pasha Tatashin <pasha.tatashin@soleen.com>, Jeff Xu <jeffxu@google.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, Brendan Jackman <jackmanb@google.com>, Greg Thelen <gthelen@google.com>, Hugh Dickins <hughd@google.com>, Kees Cook <kees@kernel.org>, "David Hildenbrand (Arm)" <david@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604135421.3490773-3-sashal@kernel.org>
+
+From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
+
+[ Upstream commit 3b041514cb6eae45869b020f743c14d983363222 ]
+
+When SEAL_EXEC is added, SEAL_WRITE is implied to make W^X.  But the
+implied seal is set after the check that makes sure the memfd can not have
+any writable mappings.  This means one can use SEAL_EXEC to apply
+SEAL_WRITE while having writeable mappings.
+
+This breaks the contract that SEAL_WRITE provides and can be used by an
+attacker to pass a memfd that appears to be write sealed but can still be
+modified arbitrarily.
+
+Fix this by adding the implied seals before the call for
+mapping_deny_writable() is done.
+
+Link: https://lore.kernel.org/20260505133922.797635-1-pratyush@kernel.org
+Fixes: c4f75bc8bd6b ("mm/memfd: add write seals when apply SEAL_EXEC to executable memfd")
+Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
+Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
+Acked-by: Jeff Xu <jeffxu@google.com>
+Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Greg Thelen <gthelen@google.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: "David Hildenbrand (Arm)" <david@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memfd.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/mm/memfd.c
++++ b/mm/memfd.c
+@@ -273,6 +273,12 @@ static int memfd_add_seals(struct file *
+               goto unlock;
+       }
++      /*
++       * SEAL_EXEC implies SEAL_WRITE, making W^X from the start.
++       */
++      if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
++              seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
++
+       if ((seals & F_SEAL_WRITE) && !(*file_seals & F_SEAL_WRITE)) {
+               error = mapping_deny_writable(file->f_mapping);
+               if (error)
+@@ -285,12 +291,6 @@ static int memfd_add_seals(struct file *
+               }
+       }
+-      /*
+-       * SEAL_EXEC implies SEAL_WRITE, making W^X from the start.
+-       */
+-      if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
+-              seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
+-
+       *file_seals |= seals;
+       error = 0;
diff --git a/queue-6.12/mm-memfd-fix-spelling-and-grammatical-issues.patch b/queue-6.12/mm-memfd-fix-spelling-and-grammatical-issues.patch
new file mode 100644 (file)
index 0000000..999212f
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-260502-greg=kroah.com@vger.kernel.org Thu Jun  4 16:15:53 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 09:54:20 -0400
+Subject: mm/memfd: fix spelling and grammatical issues
+To: stable@vger.kernel.org
+Cc: Liu Ye <liuye@kylinos.cn>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604135421.3490773-2-sashal@kernel.org>
+
+From: Liu Ye <liuye@kylinos.cn>
+
+[ Upstream commit 33c9b01ed2fcbc101cdfeb497f4581e981e7c1e7 ]
+
+The comment "If a private mapping then writability is irrelevant" contains
+a typo.  It should be "If a private mapping then writability is
+irrelevant".  The comment "SEAL_EXEC implys SEAL_WRITE, making W^X from
+the start." contains a typo.  It should be "SEAL_EXEC implies SEAL_WRITE,
+making W^X from the start."
+
+Link: https://lkml.kernel.org/r/20250206060958.98010-1-liuye@kylinos.cn
+Signed-off-by: Liu Ye <liuye@kylinos.cn>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3b041514cb6e ("memfd: deny writeable mappings when implying SEAL_WRITE")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memfd.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/mm/memfd.c
++++ b/mm/memfd.c
+@@ -286,7 +286,7 @@ static int memfd_add_seals(struct file *
+       }
+       /*
+-       * SEAL_EXEC implys SEAL_WRITE, making W^X from the start.
++       * SEAL_EXEC implies SEAL_WRITE, making W^X from the start.
+        */
+       if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
+               seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
+@@ -364,7 +364,7 @@ static int check_write_seal(unsigned lon
+       unsigned long vm_flags = *vm_flags_ptr;
+       unsigned long mask = vm_flags & (VM_SHARED | VM_WRITE);
+-      /* If a private matting then writability is irrelevant. */
++      /* If a private mapping then writability is irrelevant. */
+       if (!(mask & VM_SHARED))
+               return 0;
diff --git a/queue-6.12/mm-perform-all-memfd-seal-checks-in-a-single-place.patch b/queue-6.12/mm-perform-all-memfd-seal-checks-in-a-single-place.patch
new file mode 100644 (file)
index 0000000..4a8c151
--- /dev/null
@@ -0,0 +1,299 @@
+From stable+bounces-260501-greg=kroah.com@vger.kernel.org Thu Jun  4 16:16:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 09:54:19 -0400
+Subject: mm: perform all memfd seal checks in a single place
+To: stable@vger.kernel.org
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>, "Isaac J. Manjarres" <isaacmanjarres@google.com>, Hugh Dickins <hughd@google.com>, Jann Horn <jannh@google.com>, Kalesh Singh <kaleshsingh@google.com>, "Liam R. Howlett" <Liam.Howlett@Oracle.com>, Muchun Song <muchun.song@linux.dev>, Vlastimil Babka <vbabka@suse.cz>, Jeff Xu <jeffxu@chromium.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604135421.3490773-1-sashal@kernel.org>
+
+From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+
+[ Upstream commit fa00b8ef1803fe133b4897c25227aa0d298dd093 ]
+
+We no longer actually need to perform these checks in the f_op->mmap()
+hook any longer.
+
+We already moved the operation which clears VM_MAYWRITE on a read-only
+mapping of a write-sealed memfd in order to work around the restrictions
+imposed by commit 5de195060b2e ("mm: resolve faulty mmap_region() error
+path behaviour").
+
+There is no reason for us not to simply go ahead and additionally check to
+see if any pre-existing seals are in place here rather than defer this to
+the f_op->mmap() hook.
+
+By doing this we remove more logic from shmem_mmap() which doesn't belong
+there, as well as doing the same for hugetlbfs_file_mmap().  We also
+remove dubious shared logic in mm.h which simply does not belong there
+either.
+
+It makes sense to do these checks at the earliest opportunity, we know
+these are shmem (or hugetlbfs) mappings whose relevant VMA flags will not
+change from the invoking do_mmap() so there is simply no need to wait.
+
+This also means the implementation of further memfd seal flags can be done
+within mm/memfd.c and also have the opportunity to modify VMA flags as
+necessary early in the mapping logic.
+
+[lorenzo.stoakes@oracle.com: fix typos in !memfd inline stub]
+  Link: https://lkml.kernel.org/r/7dee6c5d-480b-4c24-b98e-6fa47dbd8a23@lucifer.local
+Link: https://lkml.kernel.org/r/20241206212846.210835-1-lorenzo.stoakes@oracle.com
+Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Tested-by: Isaac J. Manjarres <isaacmanjarres@google.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: Kalesh Singh <kaleshsingh@google.com>
+Cc: Liam R. Howlett <Liam.Howlett@Oracle.com>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Jeff Xu <jeffxu@chromium.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3b041514cb6e ("memfd: deny writeable mappings when implying SEAL_WRITE")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/hugetlbfs/inode.c  |    5 ----
+ include/linux/memfd.h |   23 ++++++++++----------
+ include/linux/mm.h    |   55 --------------------------------------------------
+ mm/memfd.c            |   44 +++++++++++++++++++++++++++++++++++++++-
+ mm/mmap.c             |   12 ++++++++--
+ mm/shmem.c            |    6 -----
+ 6 files changed, 63 insertions(+), 82 deletions(-)
+
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -96,7 +96,6 @@ static const struct fs_parameter_spec hu
+ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+       struct inode *inode = file_inode(file);
+-      struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
+       loff_t len, vma_len;
+       int ret;
+       struct hstate *h = hstate_file(file);
+@@ -113,10 +112,6 @@ static int hugetlbfs_file_mmap(struct fi
+       vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND);
+       vma->vm_ops = &hugetlb_vm_ops;
+-      ret = seal_check_write(info->seals, vma);
+-      if (ret)
+-              return ret;
+-
+       /*
+        * page based offset in vm_pgoff could be sufficiently large to
+        * overflow a loff_t when converted to byte offset.  This can
+--- a/include/linux/memfd.h
++++ b/include/linux/memfd.h
+@@ -7,7 +7,14 @@
+ #ifdef CONFIG_MEMFD_CREATE
+ extern long memfd_fcntl(struct file *file, unsigned int cmd, unsigned int arg);
+ struct folio *memfd_alloc_folio(struct file *memfd, pgoff_t idx);
+-unsigned int *memfd_file_seals_ptr(struct file *file);
++/*
++ * Check for any existing seals on mmap, return an error if access is denied due
++ * to sealing, or 0 otherwise.
++ *
++ * We also update VMA flags if appropriate by manipulating the VMA flags pointed
++ * to by vm_flags_ptr.
++ */
++int memfd_check_seals_mmap(struct file *file, unsigned long *vm_flags_ptr);
+ #else
+ static inline long memfd_fcntl(struct file *f, unsigned int c, unsigned int a)
+ {
+@@ -17,19 +24,11 @@ static inline struct folio *memfd_alloc_
+ {
+       return ERR_PTR(-EINVAL);
+ }
+-
+-static inline unsigned int *memfd_file_seals_ptr(struct file *file)
++static inline int memfd_check_seals_mmap(struct file *file,
++                                       unsigned long *vm_flags_ptr)
+ {
+-      return NULL;
++      return 0;
+ }
+ #endif
+-/* Retrieve memfd seals associated with the file, if any. */
+-static inline unsigned int memfd_file_seals(struct file *file)
+-{
+-      unsigned int *sealsp = memfd_file_seals_ptr(file);
+-
+-      return sealsp ? *sealsp : 0;
+-}
+-
+ #endif /* __LINUX_MEMFD_H */
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -4140,61 +4140,6 @@ void mem_dump_obj(void *object);
+ static inline void mem_dump_obj(void *object) {}
+ #endif
+-static inline bool is_write_sealed(int seals)
+-{
+-      return seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE);
+-}
+-
+-/**
+- * is_readonly_sealed - Checks whether write-sealed but mapped read-only,
+- *                      in which case writes should be disallowing moving
+- *                      forwards.
+- * @seals: the seals to check
+- * @vm_flags: the VMA flags to check
+- *
+- * Returns whether readonly sealed, in which case writess should be disallowed
+- * going forward.
+- */
+-static inline bool is_readonly_sealed(int seals, vm_flags_t vm_flags)
+-{
+-      /*
+-       * Since an F_SEAL_[FUTURE_]WRITE sealed memfd can be mapped as
+-       * MAP_SHARED and read-only, take care to not allow mprotect to
+-       * revert protections on such mappings. Do this only for shared
+-       * mappings. For private mappings, don't need to mask
+-       * VM_MAYWRITE as we still want them to be COW-writable.
+-       */
+-      if (is_write_sealed(seals) &&
+-          ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_SHARED))
+-              return true;
+-
+-      return false;
+-}
+-
+-/**
+- * seal_check_write - Check for F_SEAL_WRITE or F_SEAL_FUTURE_WRITE flags and
+- *                    handle them.
+- * @seals: the seals to check
+- * @vma: the vma to operate on
+- *
+- * Check whether F_SEAL_WRITE or F_SEAL_FUTURE_WRITE are set; if so, do proper
+- * check/handling on the vma flags.  Return 0 if check pass, or <0 for errors.
+- */
+-static inline int seal_check_write(int seals, struct vm_area_struct *vma)
+-{
+-      if (!is_write_sealed(seals))
+-              return 0;
+-
+-      /*
+-       * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
+-       * write seals are active.
+-       */
+-      if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
+-              return -EPERM;
+-
+-      return 0;
+-}
+-
+ #ifdef CONFIG_ANON_VMA_NAME
+ int madvise_set_anon_name(struct mm_struct *mm, unsigned long start,
+                         unsigned long len_in,
+--- a/mm/memfd.c
++++ b/mm/memfd.c
+@@ -197,7 +197,7 @@ static int memfd_wait_for_pins(struct ad
+       return error;
+ }
+-unsigned int *memfd_file_seals_ptr(struct file *file)
++static unsigned int *memfd_file_seals_ptr(struct file *file)
+ {
+       if (shmem_file(file))
+               return &SHMEM_I(file_inode(file))->seals;
+@@ -354,6 +354,48 @@ static int check_sysctl_memfd_noexec(uns
+       return 0;
+ }
++static inline bool is_write_sealed(unsigned int seals)
++{
++      return seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE);
++}
++
++static int check_write_seal(unsigned long *vm_flags_ptr)
++{
++      unsigned long vm_flags = *vm_flags_ptr;
++      unsigned long mask = vm_flags & (VM_SHARED | VM_WRITE);
++
++      /* If a private matting then writability is irrelevant. */
++      if (!(mask & VM_SHARED))
++              return 0;
++
++      /*
++       * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
++       * write seals are active.
++       */
++      if (mask & VM_WRITE)
++              return -EPERM;
++
++      /*
++       * This is a read-only mapping, disallow mprotect() from making a
++       * write-sealed mapping writable in future.
++       */
++      *vm_flags_ptr &= ~VM_MAYWRITE;
++
++      return 0;
++}
++
++int memfd_check_seals_mmap(struct file *file, unsigned long *vm_flags_ptr)
++{
++      int err = 0;
++      unsigned int *seals_ptr = memfd_file_seals_ptr(file);
++      unsigned int seals = seals_ptr ? *seals_ptr : 0;
++
++      if (is_write_sealed(seals))
++              err = check_write_seal(vm_flags_ptr);
++
++      return err;
++}
++
+ SYSCALL_DEFINE2(memfd_create,
+               const char __user *, uname,
+               unsigned int, flags)
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -369,8 +369,8 @@ unsigned long do_mmap(struct file *file,
+       if (file) {
+               struct inode *inode = file_inode(file);
+-              unsigned int seals = memfd_file_seals(file);
+               unsigned long flags_mask;
++              int err;
+               if (!file_mmap_ok(file, inode, pgoff, len))
+                       return -EOVERFLOW;
+@@ -410,8 +410,6 @@ unsigned long do_mmap(struct file *file,
+                       vm_flags |= VM_SHARED | VM_MAYSHARE;
+                       if (!(file->f_mode & FMODE_WRITE))
+                               vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
+-                      else if (is_readonly_sealed(seals, vm_flags))
+-                              vm_flags &= ~VM_MAYWRITE;
+                       fallthrough;
+               case MAP_PRIVATE:
+                       if (!(file->f_mode & FMODE_READ))
+@@ -431,6 +429,14 @@ unsigned long do_mmap(struct file *file,
+               default:
+                       return -EINVAL;
+               }
++
++              /*
++               * Check to see if we are violating any seals and update VMA
++               * flags if necessary to avoid future seal violations.
++               */
++              err = memfd_check_seals_mmap(file, &vm_flags);
++              if (err)
++                      return (unsigned long)err;
+       } else {
+               switch (flags & MAP_TYPE) {
+               case MAP_SHARED:
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -2820,12 +2820,6 @@ out_nomem:
+ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+       struct inode *inode = file_inode(file);
+-      struct shmem_inode_info *info = SHMEM_I(inode);
+-      int ret;
+-
+-      ret = seal_check_write(info->seals, vma);
+-      if (ret)
+-              return ret;
+       file_accessed(file);
+       /* This is anonymous shared memory if it is unlinked at the time of mmap */
index 332f4ae5cf8053cc99983fc61ec23cd527dd5cda..cbc0088a5d3f488e3a5594929402faecffa77b59 100644 (file)
@@ -299,3 +299,9 @@ scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.pat
 usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch
 x86-alternatives-rename-apply_relocation-to-text_poke_apply_relocation.patch
 x86-ftrace-relocate-rip-relative-percpu-refs-in-dynamic-trampolines.patch
+hwmon-pmbus-adm1266-serialize-sequencer_state-debugfs-read-with-pmbus_lock.patch
+hwmon-pmbus-adm1266-serialize-nvmem-blackbox-read-with-pmbus_lock.patch
+hwmon-pmbus-adm1266-serialize-gpio-pmbus-accesses-with-pmbus_lock.patch
+mm-perform-all-memfd-seal-checks-in-a-single-place.patch
+mm-memfd-fix-spelling-and-grammatical-issues.patch
+memfd-deny-writeable-mappings-when-implying-seal_write.patch