Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp1963000pxv; Sat, 24 Jul 2021 00:38:12 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwwmCh/u1HArd96go2HF2RXwVuZOt7+r4Q4ThoCR9BNPIFm71JCuc4FD+1SAHw7TYFlvkIu X-Received: by 2002:a6b:fe06:: with SMTP id x6mr6911129ioh.38.1627112292529; Sat, 24 Jul 2021 00:38:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627112292; cv=none; d=google.com; s=arc-20160816; b=cWoiusXxYONDL6ei5cRSibY87I6HVbelawn91sIXu9q+T0IJpT07+sBcad1Ux/AEK4 U3UGFYgRGDlPjTdYE4pemX2HoEo/GSA0s4Dk+6ghKeAUfYiIHV0FGq/bfmLOYBnN2XW9 2UtIQrvo+WLKEWx8YzwO5nQhmbcl0JwXQxcHOC4Izi0ee5QwXjvkMOIrILEuieMAvI/Y KHlrATCmQNG0296ZjwOuOjTlvIoaVALHkiYitTORowX/H6G4kWCMQvzZvH2uK3ZTPM4N MMJubOWkgqLyUX8m2BimbpTXWeWqK+Uwno4h3jG0WOhmsNBc4sM70C7NspGsHecibP2v F7Vg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=hxof7NWhRTN6RxBAzvdBd/VZVFmS77YjkfQAkOZin+c=; b=ZN1gAeXKqVfuqLMNMmpTTrSDf179MvBX+wY0pCvcthRxPeWe4JY91R8RkcKEYUyeom bxXRKkZtbESBiG/ca6BjvAwbROgJdPR3y96YX/HhFpn1L671KwUi88/wr5UEDcHeSOpz dOdF0+dLkAg1eaKuLSx6Wrdg+aBblA7fAnnuf7sRb5IzChyGHr9cL6dVOBG34U0HxRvy Uy+XBkndifXzVsiKGFyMzykzWvFNAb37Qarxyq1g1Yv6sxxTIPwTSYfg1YYDZH+jrlha ThqHupUWuHE3Oo4uuD8sl9QtRy6LIsgt3/mhw+Lw7Uk4nLbyzYdIohg5fw+73IybIxFH GhaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ErhKil24; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p29si36833093jal.22.2021.07.24.00.38.00; Sat, 24 Jul 2021 00:38:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ErhKil24; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234530AbhGXGzr (ORCPT + 99 others); Sat, 24 Jul 2021 02:55:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234287AbhGXGzr (ORCPT ); Sat, 24 Jul 2021 02:55:47 -0400 Received: from mail-io1-xd29.google.com (mail-io1-xd29.google.com [IPv6:2607:f8b0:4864:20::d29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9483AC061575; Sat, 24 Jul 2021 00:36:18 -0700 (PDT) Received: by mail-io1-xd29.google.com with SMTP id j21so5248786ioo.6; Sat, 24 Jul 2021 00:36:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=hxof7NWhRTN6RxBAzvdBd/VZVFmS77YjkfQAkOZin+c=; b=ErhKil24dTxaHLxEYUyIdguwf7HqrEFZ8NdTUrz15hWbzV5epVuZEqebuaR7GhOLfk fA/7s02k1d9O8GByKIteqPuyV4vTr8Kqn0mHRslWgQgDRip45cK2nsEHDuRbXJrtK1TZ Zrm1P9D13IvyTvOPFIqiWSJGwLLpenSocsyxo+cezJUB69EXTCmgHzZWygEbi1GLgZYS bdedMt73BaDGFSVp5Y+bUko/UE+jv08VvYOZMqduVgoR/Ko2dIH7M9OSdOyLco1bpDTq IvLVYk1G4KhlURnjk4lFbSmdck6aBsABrKpR/48PfojlGIT749nZAUk3SkbNJvGsPKEk mrIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=hxof7NWhRTN6RxBAzvdBd/VZVFmS77YjkfQAkOZin+c=; b=ApGLCxEutV6BQgiq2y8u1RksE3PCioD/2b5iVqZ8FkZKhNaz56Ggngu1ytBLlYMvD0 g+hKa/QdyyPeub7AsnX8Dvrk9DunmsY9+PwMN/1jNVrPOsU25aHsP9rILyTh/4Dvyl9j xCW/A6xWN9zZJpfQAjjDZIMDgA7dVy+4Cytsu13kbjnuRXi9zf53nqHF8wlr5RpEWrta xPkkjoNLC8Rj3aC+pQpgg3y9Qxy+HJTicQumxsZWP2T4Vb5tGw27IVRaSTQQfZAsbKRP DjENFU4ghQ61f6Q4hkNIoykk/a77Ku7XBJIi9+zR0mj/iF+R5MZ+DXqXdXYYUlb1U6B/ m7iw== X-Gm-Message-State: AOAM533kcKI1fsYeCkEguwWcYpC/QWsI/ckyqDefMdSJUbt46hTIOCf8 Vk6pqUiPzx0Sn5dJKS+Aby1Lgl20yqF4BjVStI8= X-Received: by 2002:a05:6602:3304:: with SMTP id b4mr6800288ioz.186.1627112177921; Sat, 24 Jul 2021 00:36:17 -0700 (PDT) MIME-Version: 1.0 References: <737687ee-3449-aa3d-ee29-bd75ca0a18a9@canonical.com> In-Reply-To: <737687ee-3449-aa3d-ee29-bd75ca0a18a9@canonical.com> From: Amir Goldstein Date: Sat, 24 Jul 2021 10:36:05 +0300 Message-ID: Subject: Re: ovl: uninitialized pointer read in ovl_lookup_real_one To: Colin Ian King Cc: Miklos Szeredi , overlayfs , "linux-kernel@vger.kernel.org" Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, Jul 24, 2021 at 1:26 AM Colin Ian King wrote: > > Hi, > > Static analysis with Coverity has detected an uninitialized pointer read > in function ovl_lookup_real_one in fs/overlayfs/export.c > > The issue was introduced with the following commit: > > commit 3985b70a3e3f58109dc6ae347eafe6e8610be41e > Author: Amir Goldstein > Date: Thu Dec 28 18:36:16 2017 +0200 > > ovl: decode connected upper dir file handles > > The analysis is as follows: > > 365static struct dentry *ovl_lookup_real_one(struct dentry *connected, > 366 struct dentry *real, > 367 const struct ovl_layer *layer) > 368{ > 369 struct inode *dir = d_inode(connected); > 370 struct dentry *this, *parent = NULL; > > 1. var_decl: Declaring variable name without initializer. > > 371 struct name_snapshot name; > 372 int err; > 373 > 374 /* > 375 * Lookup child overlay dentry by real name. The dir mutex > protects us > 376 * from racing with overlay rename. If the overlay dentry > that is above > 377 * real has already been moved to a parent that is not under the > 378 * connected overlay dir, we return -ECHILD and restart the > lookup of > 379 * connected real path from the top. > 380 */ > 381 inode_lock_nested(dir, I_MUTEX_PARENT); > 382 err = -ECHILD; > 383 parent = dget_parent(real); > > 2. Condition ovl_dentry_real_at(connected, layer->idx) != parent, > taking true branch. > > 384 if (ovl_dentry_real_at(connected, layer->idx) != parent) > > 3. Jumping to label fail. > > 385 goto fail; > 386 > 387 /* > 388 * We also need to take a snapshot of real dentry name to > protect us > 389 * from racing with underlying layer rename. In this case, we > don't > 390 * care about returning ESTALE, only from dereferencing a > free name > 391 * pointer because we hold no lock on the real dentry. > 392 */ > 393 take_dentry_name_snapshot(&name, real); > 394 this = lookup_one_len(name.name.name, connected, name.name.len); > 395 err = PTR_ERR(this); > 396 if (IS_ERR(this)) { > 397 goto fail; > 398 } else if (!this || !this->d_inode) { > 399 dput(this); > 400 err = -ENOENT; > 401 goto fail; > 402 } else if (ovl_dentry_real_at(this, layer->idx) != real) { > 403 dput(this); > 404 err = -ESTALE; > 405 goto fail; > 406 } > 407 > 408out: > > Uninitialized pointer read > 6. uninit_use_in_call: Using uninitialized value name.name.name when > calling release_dentry_name_snapshot. > > 409 release_dentry_name_snapshot(&name); > 410 dput(parent); > 411 inode_unlock(dir); > 412 return this; > 413 > 414fail: > > 4. Condition ___ratelimit(&_rs, ), taking false branch > . > 415 pr_warn_ratelimited("failed to lookup one by real (%pd2, > layer=%d, connected=%pd2, err=%i)\n", > 416 real, layer->idx, connected, err); > 417 this = ERR_PTR(err); > > 5. Jumping to label out. > > 418 goto out; > 419} > > The error exit path on line 395 ends up with an uninitialized structure > name being passed to function release_dentry_name_snapshot() on line 409 > and this accesses the pointer name.name.name, see /fs/dcache.c as follows: > > 303void release_dentry_name_snapshot(struct name_snapshot *name) > 304{ > > 1. read_value: Reading value name->name.name. > 2. Condition !!(name->name.name != name->inline_name), taking true > branch. > > 305 if (unlikely(name->name.name != name->inline_name)) { > 306 struct external_name *p; > > 3. Condition 0 /* !!(!__builtin_types_compatible_p() && > !__builtin_types_compatible_p()) */, taking false branch. > > > I suspect name should be initialized in line 371, e.g. name = { } and a > null name check should be performed on line 409 before calling > release_dentry_name_snapshot, but this seems a bit message as a fix. > Thanks for the report. A simpler fix is to move take_dentry_name_snapshot() to top of the function before goto fail. Thanks, Amir. > Colin