From: Sasha Levin Date: Tue, 6 Nov 2018 06:33:12 +0000 (-0500) Subject: 4.18-stable patches X-Git-Tag: v3.18.125~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=97c6f601aa5270d3aa7bb615d6d040dc43f3a589;p=thirdparty%2Fkernel%2Fstable-queue.git 4.18-stable patches Signed-off-by: Sasha Levin --- 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 index 00000000000..201d2dc5d45 --- /dev/null +++ b/queue-4.18/bpf-fix-partial-copy-of-map_ptr-when-dst-is-scalar.patch @@ -0,0 +1,93 @@ +From 64dbc262b657daca4aa9d65bed298377f23994f0 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +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 +Cc: Edward Cree +Acked-by: Alexei Starovoitov +Signed-off-by: Alexei Starovoitov +Acked-by: Edward Cree +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..8b3f82fa68b --- /dev/null +++ b/queue-4.18/eeprom-at24-add-support-for-address-width-property.patch @@ -0,0 +1,49 @@ +From 4fc7d6351b8743d20565ca9b9f3aada68de053e4 Mon Sep 17 00:00:00 2001 +From: Alan Chiang +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 +Signed-off-by: Andy Yeh +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2cb359839c2 --- /dev/null +++ b/queue-4.18/series @@ -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 index 00000000000..741952bd2b3 --- /dev/null +++ b/queue-4.18/vfs-swap-names-of-do-vfs-_clone_file_range.patch @@ -0,0 +1,152 @@ +From 3e2ce0fd043394534bf58ca6ab557d5912f5e1a5 Mon Sep 17 00:00:00 2001 +From: Amir Goldstein +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 +Signed-off-by: Miklos Szeredi +Fixes: 031a072a0b8a ("vfs: call vfs_clone_file_range() under freeze...") +Signed-off-by: Amir Goldstein +Signed-off-by: Sasha Levin +--- + 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 +