]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.18-stable patches
authorSasha Levin <sashal@kernel.org>
Tue, 6 Nov 2018 06:33:12 +0000 (01:33 -0500)
committerSasha Levin <sashal@kernel.org>
Tue, 6 Nov 2018 06:33:12 +0000 (01:33 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.18/bpf-fix-partial-copy-of-map_ptr-when-dst-is-scalar.patch [new file with mode: 0644]
queue-4.18/eeprom-at24-add-support-for-address-width-property.patch [new file with mode: 0644]
queue-4.18/series [new file with mode: 0644]
queue-4.18/vfs-swap-names-of-do-vfs-_clone_file_range.patch [new file with mode: 0644]

diff --git a/queue-4.18/bpf-fix-partial-copy-of-map_ptr-when-dst-is-scalar.patch b/queue-4.18/bpf-fix-partial-copy-of-map_ptr-when-dst-is-scalar.patch
new file mode 100644 (file)
index 0000000..201d2dc
--- /dev/null
@@ -0,0 +1,93 @@
+From 64dbc262b657daca4aa9d65bed298377f23994f0 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Thu, 1 Nov 2018 22:29:53 +0100
+Subject: bpf: fix partial copy of map_ptr when dst is scalar
+
+commit 0962590e553331db2cc0aef2dc35c57f6300dbbe upstream.
+
+ALU operations on pointers such as scalar_reg += map_value_ptr are
+handled in adjust_ptr_min_max_vals(). Problem is however that map_ptr
+and range in the register state share a union, so transferring state
+through dst_reg->range = ptr_reg->range is just buggy as any new
+map_ptr in the dst_reg is then truncated (or null) for subsequent
+checks. Fix this by adding a raw member and use it for copying state
+over to dst_reg.
+
+Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Edward Cree <ecree@solarflare.com>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Acked-by: Edward Cree <ecree@solarflare.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf_verifier.h |  3 +++
+ kernel/bpf/verifier.c        | 10 ++++++----
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
+index 38b04f559ad3..1fd6fa822d2c 100644
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -50,6 +50,9 @@ struct bpf_reg_state {
+                *   PTR_TO_MAP_VALUE_OR_NULL
+                */
+               struct bpf_map *map_ptr;
++
++              /* Max size from any of the above. */
++              unsigned long raw;
+       };
+       /* Fixed part of pointer offset, pointer types only */
+       s32 off;
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 82e8edef6ea0..b000686fa1a1 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2731,7 +2731,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+                       dst_reg->umax_value = umax_ptr;
+                       dst_reg->var_off = ptr_reg->var_off;
+                       dst_reg->off = ptr_reg->off + smin_val;
+-                      dst_reg->range = ptr_reg->range;
++                      dst_reg->raw = ptr_reg->raw;
+                       break;
+               }
+               /* A new variable offset is created.  Note that off_reg->off
+@@ -2761,10 +2761,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               dst_reg->var_off = tnum_add(ptr_reg->var_off, off_reg->var_off);
+               dst_reg->off = ptr_reg->off;
++              dst_reg->raw = ptr_reg->raw;
+               if (reg_is_pkt_pointer(ptr_reg)) {
+                       dst_reg->id = ++env->id_gen;
+                       /* something was added to pkt_ptr, set range to zero */
+-                      dst_reg->range = 0;
++                      dst_reg->raw = 0;
+               }
+               break;
+       case BPF_SUB:
+@@ -2793,7 +2794,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+                       dst_reg->var_off = ptr_reg->var_off;
+                       dst_reg->id = ptr_reg->id;
+                       dst_reg->off = ptr_reg->off - smin_val;
+-                      dst_reg->range = ptr_reg->range;
++                      dst_reg->raw = ptr_reg->raw;
+                       break;
+               }
+               /* A new variable offset is created.  If the subtrahend is known
+@@ -2819,11 +2820,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+               }
+               dst_reg->var_off = tnum_sub(ptr_reg->var_off, off_reg->var_off);
+               dst_reg->off = ptr_reg->off;
++              dst_reg->raw = ptr_reg->raw;
+               if (reg_is_pkt_pointer(ptr_reg)) {
+                       dst_reg->id = ++env->id_gen;
+                       /* something was added to pkt_ptr, set range to zero */
+                       if (smin_val < 0)
+-                              dst_reg->range = 0;
++                              dst_reg->raw = 0;
+               }
+               break;
+       case BPF_AND:
+-- 
+2.17.1
+
diff --git a/queue-4.18/eeprom-at24-add-support-for-address-width-property.patch b/queue-4.18/eeprom-at24-add-support-for-address-width-property.patch
new file mode 100644 (file)
index 0000000..8b3f82f
--- /dev/null
@@ -0,0 +1,49 @@
+From 4fc7d6351b8743d20565ca9b9f3aada68de053e4 Mon Sep 17 00:00:00 2001
+From: Alan Chiang <alanx.chiang@intel.com>
+Date: Wed, 25 Jul 2018 11:20:22 +0800
+Subject: eeprom: at24: Add support for address-width property
+
+[ Upstream commit a2b3bf4846e5eed62ea6abb096af2c950961033c ]
+
+Provide a flexible way to determine the addressing bits of eeprom.
+Pass the addressing bits to driver through address-width property.
+
+Signed-off-by: Alan Chiang <alanx.chiang@intel.com>
+Signed-off-by: Andy Yeh <andy.yeh@intel.com>
+Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/eeprom/at24.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index f5cc517d1131..7e50e1d6f58c 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -478,6 +478,23 @@ static void at24_properties_to_pdata(struct device *dev,
+       if (device_property_present(dev, "no-read-rollover"))
+               chip->flags |= AT24_FLAG_NO_RDROL;
++      err = device_property_read_u32(dev, "address-width", &val);
++      if (!err) {
++              switch (val) {
++              case 8:
++                      if (chip->flags & AT24_FLAG_ADDR16)
++                              dev_warn(dev, "Override address width to be 8, while default is 16\n");
++                      chip->flags &= ~AT24_FLAG_ADDR16;
++                      break;
++              case 16:
++                      chip->flags |= AT24_FLAG_ADDR16;
++                      break;
++              default:
++                      dev_warn(dev, "Bad \"address-width\" property: %u\n",
++                               val);
++              }
++      }
++
+       err = device_property_read_u32(dev, "size", &val);
+       if (!err)
+               chip->byte_len = val;
+-- 
+2.17.1
+
diff --git a/queue-4.18/series b/queue-4.18/series
new file mode 100644 (file)
index 0000000..2cb3598
--- /dev/null
@@ -0,0 +1,3 @@
+eeprom-at24-add-support-for-address-width-property.patch
+vfs-swap-names-of-do-vfs-_clone_file_range.patch
+bpf-fix-partial-copy-of-map_ptr-when-dst-is-scalar.patch
diff --git a/queue-4.18/vfs-swap-names-of-do-vfs-_clone_file_range.patch b/queue-4.18/vfs-swap-names-of-do-vfs-_clone_file_range.patch
new file mode 100644 (file)
index 0000000..741952b
--- /dev/null
@@ -0,0 +1,152 @@
+From 3e2ce0fd043394534bf58ca6ab557d5912f5e1a5 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Mon, 22 Oct 2018 20:56:46 +0300
+Subject: vfs: swap names of {do,vfs}_clone_file_range()
+
+commit a725356b6659469d182d662f22d770d83d3bc7b5 upstream.
+
+Commit 031a072a0b8a ("vfs: call vfs_clone_file_range() under freeze
+protection") created a wrapper do_clone_file_range() around
+vfs_clone_file_range() moving the freeze protection to former, so
+overlayfs could call the latter.
+
+The more common vfs practice is to call do_xxx helpers from vfs_xxx
+helpers, where freeze protecction is taken in the vfs_xxx helper, so
+this anomality could be a source of confusion.
+
+It seems that commit 8ede205541ff ("ovl: add reflink/copyfile/dedup
+support") may have fallen a victim to this confusion -
+ovl_clone_file_range() calls the vfs_clone_file_range() helper in the
+hope of getting freeze protection on upper fs, but in fact results in
+overlayfs allowing to bypass upper fs freeze protection.
+
+Swap the names of the two helpers to conform to common vfs practice
+and call the correct helpers from overlayfs and nfsd.
+
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Fixes: 031a072a0b8a ("vfs: call vfs_clone_file_range() under freeze...")
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ioctl.c             |  2 +-
+ fs/nfsd/vfs.c          |  3 ++-
+ fs/overlayfs/copy_up.c |  2 +-
+ fs/read_write.c        | 17 +++++++++++++++--
+ include/linux/fs.h     | 17 +++--------------
+ 5 files changed, 22 insertions(+), 19 deletions(-)
+
+diff --git a/fs/ioctl.c b/fs/ioctl.c
+index b445b13fc59b..5444fec607ce 100644
+--- a/fs/ioctl.c
++++ b/fs/ioctl.c
+@@ -229,7 +229,7 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
+       ret = -EXDEV;
+       if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
+               goto fdput;
+-      ret = do_clone_file_range(src_file.file, off, dst_file, destoff, olen);
++      ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen);
+ fdput:
+       fdput(src_file);
+       return ret;
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index b0555d7d8200..613d2fe2dddd 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -541,7 +541,8 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
+               u64 dst_pos, u64 count)
+ {
+-      return nfserrno(do_clone_file_range(src, src_pos, dst, dst_pos, count));
++      return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos,
++                                           count));
+ }
+ ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index ddaddb4ce4c3..26b477f2538d 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -156,7 +156,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
+       }
+       /* Try to use clone_file_range to clone up within the same fs */
+-      error = vfs_clone_file_range(old_file, 0, new_file, 0, len);
++      error = do_clone_file_range(old_file, 0, new_file, 0, len);
+       if (!error)
+               goto out;
+       /* Couldn't clone, so now we try to copy the data */
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 153f8f690490..c9d489684335 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -1818,8 +1818,8 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
+ }
+ EXPORT_SYMBOL(vfs_clone_file_prep_inodes);
+-int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
+-              struct file *file_out, loff_t pos_out, u64 len)
++int do_clone_file_range(struct file *file_in, loff_t pos_in,
++                      struct file *file_out, loff_t pos_out, u64 len)
+ {
+       struct inode *inode_in = file_inode(file_in);
+       struct inode *inode_out = file_inode(file_out);
+@@ -1866,6 +1866,19 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
+       return ret;
+ }
++EXPORT_SYMBOL(do_clone_file_range);
++
++int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
++                       struct file *file_out, loff_t pos_out, u64 len)
++{
++      int ret;
++
++      file_start_write(file_out);
++      ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len);
++      file_end_write(file_out);
++
++      return ret;
++}
+ EXPORT_SYMBOL(vfs_clone_file_range);
+ /*
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index a3afa50bb79f..e73363bd8646 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1813,8 +1813,10 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *,
+ extern int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
+                                     struct inode *inode_out, loff_t pos_out,
+                                     u64 *len, bool is_dedupe);
++extern int do_clone_file_range(struct file *file_in, loff_t pos_in,
++                             struct file *file_out, loff_t pos_out, u64 len);
+ extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
+-              struct file *file_out, loff_t pos_out, u64 len);
++                              struct file *file_out, loff_t pos_out, u64 len);
+ extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
+                                        struct inode *dest, loff_t destoff,
+                                        loff_t len, bool *is_same);
+@@ -2755,19 +2757,6 @@ static inline void file_end_write(struct file *file)
+       __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+ }
+-static inline int do_clone_file_range(struct file *file_in, loff_t pos_in,
+-                                    struct file *file_out, loff_t pos_out,
+-                                    u64 len)
+-{
+-      int ret;
+-
+-      file_start_write(file_out);
+-      ret = vfs_clone_file_range(file_in, pos_in, file_out, pos_out, len);
+-      file_end_write(file_out);
+-
+-      return ret;
+-}
+-
+ /*
+  * get_write_access() gets write permission for a file.
+  * put_write_access() releases this write permission.
+-- 
+2.17.1
+