From: Greg Kroah-Hartman Date: Thu, 18 Jun 2020 14:54:36 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.228~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=13893f013e7ad50a771bb2b5cbc88097801f3b6d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: btrfs-send-emit-file-capabilities-after-chown.patch --- diff --git a/queue-4.14/btrfs-send-emit-file-capabilities-after-chown.patch b/queue-4.14/btrfs-send-emit-file-capabilities-after-chown.patch new file mode 100644 index 00000000000..ac00a75e899 --- /dev/null +++ b/queue-4.14/btrfs-send-emit-file-capabilities-after-chown.patch @@ -0,0 +1,154 @@ +From 89efda52e6b6930f80f5adda9c3c9edfb1397191 Mon Sep 17 00:00:00 2001 +From: Marcos Paulo de Souza +Date: Sun, 10 May 2020 23:15:07 -0300 +Subject: btrfs: send: emit file capabilities after chown + +From: Marcos Paulo de Souza + +commit 89efda52e6b6930f80f5adda9c3c9edfb1397191 upstream. + +Whenever a chown is executed, all capabilities of the file being touched +are lost. When doing incremental send with a file with capabilities, +there is a situation where the capability can be lost on the receiving +side. The sequence of actions bellow shows the problem: + + $ mount /dev/sda fs1 + $ mount /dev/sdb fs2 + + $ touch fs1/foo.bar + $ setcap cap_sys_nice+ep fs1/foo.bar + $ btrfs subvolume snapshot -r fs1 fs1/snap_init + $ btrfs send fs1/snap_init | btrfs receive fs2 + + $ chgrp adm fs1/foo.bar + $ setcap cap_sys_nice+ep fs1/foo.bar + + $ btrfs subvolume snapshot -r fs1 fs1/snap_complete + $ btrfs subvolume snapshot -r fs1 fs1/snap_incremental + + $ btrfs send fs1/snap_complete | btrfs receive fs2 + $ btrfs send -p fs1/snap_init fs1/snap_incremental | btrfs receive fs2 + +At this point, only a chown was emitted by "btrfs send" since only the +group was changed. This makes the cap_sys_nice capability to be dropped +from fs2/snap_incremental/foo.bar + +To fix that, only emit capabilities after chown is emitted. The current +code first checks for xattrs that are new/changed, emits them, and later +emit the chown. Now, __process_new_xattr skips capabilities, letting +only finish_inode_if_needed to emit them, if they exist, for the inode +being processed. + +This behavior was being worked around in "btrfs receive" side by caching +the capability and only applying it after chown. Now, xattrs are only +emmited _after_ chown, making that workaround not needed anymore. + +Link: https://github.com/kdave/btrfs-progs/issues/202 +CC: stable@vger.kernel.org # 4.4+ +Suggested-by: Filipe Manana +Reviewed-by: Filipe Manana +Signed-off-by: Marcos Paulo de Souza +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/send.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -35,6 +35,7 @@ + #include "btrfs_inode.h" + #include "transaction.h" + #include "compression.h" ++#include "xattr.h" + + /* + * Maximum number of references an extent can have in order for us to attempt to +@@ -4554,6 +4555,10 @@ static int __process_new_xattr(int num, + struct fs_path *p; + struct posix_acl_xattr_header dummy_acl; + ++ /* Capabilities are emitted by finish_inode_if_needed */ ++ if (!strncmp(name, XATTR_NAME_CAPS, name_len)) ++ return 0; ++ + p = fs_path_alloc(); + if (!p) + return -ENOMEM; +@@ -5096,6 +5101,64 @@ static int send_extent_data(struct send_ + return 0; + } + ++/* ++ * Search for a capability xattr related to sctx->cur_ino. If the capability is ++ * found, call send_set_xattr function to emit it. ++ * ++ * Return 0 if there isn't a capability, or when the capability was emitted ++ * successfully, or < 0 if an error occurred. ++ */ ++static int send_capabilities(struct send_ctx *sctx) ++{ ++ struct fs_path *fspath = NULL; ++ struct btrfs_path *path; ++ struct btrfs_dir_item *di; ++ struct extent_buffer *leaf; ++ unsigned long data_ptr; ++ char *buf = NULL; ++ int buf_len; ++ int ret = 0; ++ ++ path = alloc_path_for_send(); ++ if (!path) ++ return -ENOMEM; ++ ++ di = btrfs_lookup_xattr(NULL, sctx->send_root, path, sctx->cur_ino, ++ XATTR_NAME_CAPS, strlen(XATTR_NAME_CAPS), 0); ++ if (!di) { ++ /* There is no xattr for this inode */ ++ goto out; ++ } else if (IS_ERR(di)) { ++ ret = PTR_ERR(di); ++ goto out; ++ } ++ ++ leaf = path->nodes[0]; ++ buf_len = btrfs_dir_data_len(leaf, di); ++ ++ fspath = fs_path_alloc(); ++ buf = kmalloc(buf_len, GFP_KERNEL); ++ if (!fspath || !buf) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, fspath); ++ if (ret < 0) ++ goto out; ++ ++ data_ptr = (unsigned long)(di + 1) + btrfs_dir_name_len(leaf, di); ++ read_extent_buffer(leaf, buf, data_ptr, buf_len); ++ ++ ret = send_set_xattr(sctx, fspath, XATTR_NAME_CAPS, ++ strlen(XATTR_NAME_CAPS), buf, buf_len); ++out: ++ kfree(buf); ++ fs_path_free(fspath); ++ btrfs_free_path(path); ++ return ret; ++} ++ + static int clone_range(struct send_ctx *sctx, + struct clone_root *clone_root, + const u64 disk_byte, +@@ -5907,6 +5970,10 @@ static int finish_inode_if_needed(struct + goto out; + } + ++ ret = send_capabilities(sctx); ++ if (ret < 0) ++ goto out; ++ + /* + * If other directory inodes depended on our current directory + * inode's move/rename, now do their move/rename operations. diff --git a/queue-4.14/series b/queue-4.14/series index b3a1de61887..8a1596256e7 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -137,3 +137,4 @@ spi-dw-return-any-value-retrieved-from-the-dma_trans.patch cpuidle-fix-three-reference-count-leaks.patch platform-x86-hp-wmi-convert-simple_strtoul-to-kstrto.patch string.h-fix-incompatibility-between-fortify_source-.patch +btrfs-send-emit-file-capabilities-after-chown.patch diff --git a/queue-4.14/string.h-fix-incompatibility-between-fortify_source-.patch b/queue-4.14/string.h-fix-incompatibility-between-fortify_source-.patch index 196a06873c6..3f39b9960c3 100644 --- a/queue-4.14/string.h-fix-incompatibility-between-fortify_source-.patch +++ b/queue-4.14/string.h-fix-incompatibility-between-fortify_source-.patch @@ -145,14 +145,12 @@ Link: http://lkml.kernel.org/r/20200423154503.5103-3-dja@axtens.net Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- - include/linux/string.h | 60 +++++++++++++++++++++++++++++++++--------- + include/linux/string.h | 60 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 12 deletions(-) -diff --git a/include/linux/string.h b/include/linux/string.h -index 3d43329c20be..315fef3aff4e 100644 --- a/include/linux/string.h +++ b/include/linux/string.h -@@ -238,6 +238,31 @@ void __read_overflow3(void) __compiletime_error("detected read beyond size of ob +@@ -238,6 +238,31 @@ void __read_overflow3(void) __compiletim void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter"); #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE) @@ -184,7 +182,7 @@ index 3d43329c20be..315fef3aff4e 100644 __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size) { size_t p_size = __builtin_object_size(p, 0); -@@ -245,14 +270,14 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size) +@@ -245,14 +270,14 @@ __FORTIFY_INLINE char *strncpy(char *p, __write_overflow(); if (p_size < size) fortify_panic(__func__); @@ -201,7 +199,7 @@ index 3d43329c20be..315fef3aff4e 100644 if (strlcat(p, q, p_size) >= p_size) fortify_panic(__func__); return p; -@@ -266,7 +291,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p) +@@ -266,7 +291,7 @@ __FORTIFY_INLINE __kernel_size_t strlen( /* Work around gcc excess stack consumption issue */ if (p_size == (size_t)-1 || (__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0')) @@ -210,7 +208,7 @@ index 3d43329c20be..315fef3aff4e 100644 ret = strnlen(p, p_size); if (p_size <= ret) fortify_panic(__func__); -@@ -299,7 +324,7 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size) +@@ -299,7 +324,7 @@ __FORTIFY_INLINE size_t strlcpy(char *p, __write_overflow(); if (len >= p_size) fortify_panic(__func__); @@ -219,7 +217,7 @@ index 3d43329c20be..315fef3aff4e 100644 p[len] = '\0'; } return ret; -@@ -312,12 +337,12 @@ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count) +@@ -312,12 +337,12 @@ __FORTIFY_INLINE char *strncat(char *p, size_t p_size = __builtin_object_size(p, 0); size_t q_size = __builtin_object_size(q, 0); if (p_size == (size_t)-1 && q_size == (size_t)-1) @@ -234,7 +232,7 @@ index 3d43329c20be..315fef3aff4e 100644 p[p_len + copy_len] = '\0'; return p; } -@@ -329,7 +354,7 @@ __FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size) +@@ -329,7 +354,7 @@ __FORTIFY_INLINE void *memset(void *p, i __write_overflow(); if (p_size < size) fortify_panic(__func__); @@ -243,7 +241,7 @@ index 3d43329c20be..315fef3aff4e 100644 } __FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size) -@@ -344,7 +369,7 @@ __FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size) +@@ -344,7 +369,7 @@ __FORTIFY_INLINE void *memcpy(void *p, c } if (p_size < size || q_size < size) fortify_panic(__func__); @@ -252,7 +250,7 @@ index 3d43329c20be..315fef3aff4e 100644 } __FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size) -@@ -359,7 +384,7 @@ __FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size) +@@ -359,7 +384,7 @@ __FORTIFY_INLINE void *memmove(void *p, } if (p_size < size || q_size < size) fortify_panic(__func__); @@ -261,7 +259,7 @@ index 3d43329c20be..315fef3aff4e 100644 } extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan); -@@ -385,7 +410,7 @@ __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size) +@@ -385,7 +410,7 @@ __FORTIFY_INLINE int memcmp(const void * } if (p_size < size || q_size < size) fortify_panic(__func__); @@ -270,7 +268,7 @@ index 3d43329c20be..315fef3aff4e 100644 } __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size) -@@ -395,7 +420,7 @@ __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size) +@@ -395,7 +420,7 @@ __FORTIFY_INLINE void *memchr(const void __read_overflow(); if (p_size < size) fortify_panic(__func__); @@ -279,7 +277,7 @@ index 3d43329c20be..315fef3aff4e 100644 } void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv); -@@ -426,11 +451,22 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) +@@ -426,11 +451,22 @@ __FORTIFY_INLINE char *strcpy(char *p, c size_t p_size = __builtin_object_size(p, 0); size_t q_size = __builtin_object_size(q, 0); if (p_size == (size_t)-1 && q_size == (size_t)-1) @@ -303,6 +301,3 @@ index 3d43329c20be..315fef3aff4e 100644 #endif /** --- -2.25.1 -