On Wed, Jun 3, 2020 at 11:46 PM Vivek Goyal vgoyal@redhat.com wrote:
On Wed, Jun 03, 2020 at 07:47:14PM +0200, glider@google.com wrote:
Under certain circumstances (we found this out running Docker on a Clang-built kernel with CONFIG_INIT_STACK_ALL) ovl_copy_xattr() may return uninitialized value of |error| from ovl_copy_xattr().
If we are returning uninitialized value of error, doesn't that mean that somewhere in the function we are returning without setting error. And that probably means that's a bug and we should fix it?
Could be. My understanding of that code is quite limited, so I'm happy to change the patch if necessary.
I am wondering if this is triggered by loop finishing because all the xattr on the file are ovl_is_private_xattr().
Yes, that's the case. The loop makes one iteration, then ovl_is_private_xattr() returns true, then the loop ends.
In that case, we will come out of the loop without setting error. This is in fact success and we should return 0 instead of some random error?
Thanks for letting me know. I'll change that to 0 then.
Thanks Vivek
It is then returned by ovl_create() to lookup_open(), which casts it to an invalid dentry pointer, that can be further read or written by the lookup_open() callers.
Signed-off-by: Alexander Potapenko glider@google.com Cc: Kees Cook keescook@chromium.org Cc: Roy Yang royyang@google.com Cc: stable@vger.kernel.org # 4.1
It's unclear to me whether error should be initially 0 or some error code (both seem to work), but I thought returning an error makes sense, as the situation wasn't anticipated by the code authors.
The bug seem to date back to at least v4.1 where the annotation has been introduced (i.e. the compilers started noticing error could be used before being initialized). I hovever didn't try to prove that the problem is actually reproducible on such ancient kernels. We've seen it on a real machine running v4.4 as well.
fs/overlayfs/copy_up.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 9709cf22cab3..428d43e2d016 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -47,7 +47,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) { ssize_t list_size, size, value_size = 0; char *buf, *name, *value = NULL;
int uninitialized_var(error);
int error = -EINVAL; size_t slen; if (!(old->d_inode->i_opflags & IOP_XATTR) ||
-- 2.27.0.rc2.251.g90737beb825-goog