Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp4746610yba; Wed, 8 May 2019 01:59:01 -0700 (PDT) X-Google-Smtp-Source: APXvYqxmgzk1GfRdkaffS7qGEGf28VVR2f+Y0ofFmNed4TZADZ9ie3fl1ReH8Oz5XHoSctF2wHkz X-Received: by 2002:a17:902:9693:: with SMTP id n19mr45406175plp.92.1557305941874; Wed, 08 May 2019 01:59:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1557305941; cv=none; d=google.com; s=arc-20160816; b=eW01FOS8oo7TSPI21IQI7B5PZlwAco+BYD3Hcu5rd4ClIZey6vqrmG9JnGLAs+oIaI /8OYTgZ/oCVp4fpA9JuzLQsXibsUs4QNbEmbcsByfqrhYENskdlWeM/ZIowLl03SRO03 IsQBOJcHe5kNwTYyycbKGXcWumD+S06Qvs/80vxzX8DMDgH9LgCdu3wk/tM9UNtINHLo vSzvBsZnyMOVHR4n4qBFlX4nIgR2tN5Fso0dYwRAT1gxJgN3RgdpkLGoCDYFX0sLh0Y6 Fi7+RbZ5WyJ060DaLB1kR5d8oP6yavYrQ/7FcNeJN7udaxXsgTD3aAx/EDqbPBYVmdyy /UgA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:to:references:message-id :content-transfer-encoding:cc:date:in-reply-to:from:subject :mime-version; bh=PEIP3gzGSTUOPGUL36azQMiRELQm/3Z3XxB+EuCVXM4=; b=ypYenRdQCSI7uRa2Cag9zcfaa3L1KQb8RYbfG0XrMe98MITK433E829ZQ08NOF8zIn OE5kQr2i0QNgj0pW7lplRcr8hXUQIu3uL5TSGlonVcajAzDPJA5GWKrTOAjmikaUkm23 DZZmujm69OzjmXK8nGhdQGTWikkfX2TEgFDzSZ7x2i3yK+quNCHO7eUub7bd9fl7R+JK XULHcnICna4Nnv8FHeMhlg2vdg5JjL/35fXO13XMaHslhJ6Tu2V+iHbTDiMDyxFdYXCX XNMzbqqofKGkFssFyOMvMY2mgjLdMZrR3x6xqq2lNQ+A5zExGCjOqXOQ7F0ITMbHq0io 1O4Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=canonical.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s31si12465311pga.207.2019.05.08.01.58.46; Wed, 08 May 2019 01:59:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=canonical.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727024AbfEHIXv (ORCPT + 99 others); Wed, 8 May 2019 04:23:51 -0400 Received: from youngberry.canonical.com ([91.189.89.112]:36152 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbfEHIXu (ORCPT ); Wed, 8 May 2019 04:23:50 -0400 Received: from mail-pg1-f199.google.com ([209.85.215.199]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1hOHrg-0008JA-8N for linux-kernel@vger.kernel.org; Wed, 08 May 2019 08:23:48 +0000 Received: by mail-pg1-f199.google.com with SMTP id l13so12220182pgp.3 for ; Wed, 08 May 2019 01:23:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=PEIP3gzGSTUOPGUL36azQMiRELQm/3Z3XxB+EuCVXM4=; b=L5J16JnRaJay87jjf5qlxPa2T3KmczcJfGfexGY8Hfp6iF7WXq1E+FPFc/NDiWQczN yGtBGqZCwGpXew2dpCtybYAJYh+lx5l1oZtM6ZP2YS/8WZAQH+U/G2nXlVTLu2d+P2ri PPEmxDd2PZImpk7K1gdIu0TfQoYHTZ+kkYaA+UQv1BiD5gonPkv8qUxvGbVfCykk1sRT znhcCUYo6ANkESDAT7QKmhvvYBuJIyOl3TqBUGUcoWAoWGNVA6NeXpaullauuiCZP0Eo 0ITCPFT/PoYrr9TJc7YRx+y8xumQaNiJ77jrCHOu//JOM/L8JQl1vVyrxR1V+L0JJsfQ NIkQ== X-Gm-Message-State: APjAAAXOOaD7JqYMofgvVKACk1QsLLBiMuJKfWxMowvcfrJdErCeS0r1 QsTrTJj6+jngMIpNu/mFt8uH6GFpNBWvzJKVr7204axiokJR5VdahY/gEfE9z5c0UqsIiKDCow/ kVWukOELDjooMm6hVsNJDfvR4xMcKDVVcHqRDD/ZhZg== X-Received: by 2002:a63:3dcf:: with SMTP id k198mr25762681pga.60.1557303826937; Wed, 08 May 2019 01:23:46 -0700 (PDT) X-Received: by 2002:a63:3dcf:: with SMTP id k198mr25762653pga.60.1557303826650; Wed, 08 May 2019 01:23:46 -0700 (PDT) Received: from 2001-b011-380f-14b9-cd39-5529-36b9-d37f.dynamic-ip6.hinet.net (2001-b011-380f-14b9-cd39-5529-36b9-d37f.dynamic-ip6.hinet.net. [2001:b011:380f:14b9:cd39:5529:36b9:d37f]) by smtp.gmail.com with ESMTPSA id e23sm19429414pfi.159.2019.05.08.01.23.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 08 May 2019 01:23:45 -0700 (PDT) Content-Type: text/plain; charset=utf-8; delsp=yes; format=flowed Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.8\)) Subject: Re: [PATCH v2] cifs: fix strcat buffer overflow and reduce raciness in smb21_set_oplock_level() From: Kai-Heng Feng In-Reply-To: Date: Wed, 8 May 2019 16:23:42 +0800 Cc: Steve French , Christoph Probst , Steve French , CIFS , samba-technical , LKML Content-Transfer-Encoding: 8bit Message-Id: References: <1557242200-26194-1-git-send-email-kernel@probst.it> To: Pavel Shilovsky X-Mailer: Apple Mail (2.3445.104.8) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org at 02:28, Pavel Shilovsky wrote: > вт, 7 мая 2019 г. в 09:13, Steve French via samba-technical > : >> merged into cifs-2.6.git for-next >> >> On Tue, May 7, 2019 at 10:17 AM Christoph Probst via samba-technical >> wrote: >>> Change strcat to strncpy in the "None" case to fix a buffer overflow >>> when cinode->oplock is reset to 0 by another thread accessing the same >>> cinode. It is never valid to append "None" to any other message. >>> >>> Consolidate multiple writes to cinode->oplock to reduce raciness. >>> >>> Signed-off-by: Christoph Probst >>> --- >>> fs/cifs/smb2ops.c | 14 ++++++++------ >>> 1 file changed, 8 insertions(+), 6 deletions(-) >>> >>> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c >>> index c36ff0d..aa61dcf 100644 >>> --- a/fs/cifs/smb2ops.c >>> +++ b/fs/cifs/smb2ops.c >>> @@ -2917,26 +2917,28 @@ smb21_set_oplock_level(struct cifsInodeInfo >>> *cinode, __u32 oplock, >>> unsigned int epoch, bool *purge_cache) >>> { >>> char message[5] = {0}; >>> + unsigned int new_oplock = 0; >>> >>> oplock &= 0xFF; >>> if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) >>> return; >>> >>> - cinode->oplock = 0; >>> if (oplock & SMB2_LEASE_READ_CACHING_HE) { >>> - cinode->oplock |= CIFS_CACHE_READ_FLG; >>> + new_oplock |= CIFS_CACHE_READ_FLG; >>> strcat(message, "R"); >>> } >>> if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) { >>> - cinode->oplock |= CIFS_CACHE_HANDLE_FLG; >>> + new_oplock |= CIFS_CACHE_HANDLE_FLG; >>> strcat(message, "H"); >>> } >>> if (oplock & SMB2_LEASE_WRITE_CACHING_HE) { >>> - cinode->oplock |= CIFS_CACHE_WRITE_FLG; >>> + new_oplock |= CIFS_CACHE_WRITE_FLG; >>> strcat(message, "W"); >>> } >>> - if (!cinode->oplock) >>> - strcat(message, "None"); >>> + if (!new_oplock) >>> + strncpy(message, "None", sizeof(message)); >>> + >>> + cinode->oplock = new_oplock; >>> cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, >>> &cinode->vfs_inode); >>> } >>> -- >>> 2.1.4 > Doesn’t the race still happen, but implicitly here? cinode->oplock = new_oplock; Is it possible to just introduce a lock to force its proper ordering? e.g. diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index bf5b8264e119..a3c3c6156d17 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -267,6 +267,7 @@ cifs_alloc_inode(struct super_block *sb) * server, can not assume caching of file data or metadata. */ cifs_set_oplock_level(cifs_inode, 0); + mutex_init(&cifs_inode->oplock_mutex); cifs_inode->flags = 0; spin_lock_init(&cifs_inode->writers_lock); cifs_inode->writers = 0; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 37b5ddf27ff1..6dfd4ab16c4f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1214,6 +1214,7 @@ struct cifsInodeInfo { struct list_head openFileList; __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ unsigned int oplock; /* oplock/lease level we have */ + struct mutex oplock_mutex; unsigned int epoch; /* used to track lease state changes */ #define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */ #define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */ diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index b20063cf774f..796b23712e71 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1901,6 +1901,7 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) return; + mutex_lock(&cinode->oplock_mutex); cinode->oplock = 0; if (oplock & SMB2_LEASE_READ_CACHING_HE) { cinode->oplock |= CIFS_CACHE_READ_FLG; @@ -1916,6 +1917,8 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, } if (!cinode->oplock) strcat(message, "None"); + mutex_unlock(&cinode->oplock_mutex); + cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, &cinode->vfs_inode); } Kai-Heng > Thanks for cleaning it up! > > Reviewed-by: Pavel Shilovsky > > -- > Best regards, > Pavel Shilovsky