Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp773962ybl; Wed, 14 Aug 2019 05:52:56 -0700 (PDT) X-Google-Smtp-Source: APXvYqyxAy5nY+TXeoa8Cwtv1sdizzedxZR20KnEIrFy56M3/uMYsK/nCFznF3ABhDwR7Zd71DGO X-Received: by 2002:a62:83c9:: with SMTP id h192mr20551636pfe.57.1565787176669; Wed, 14 Aug 2019 05:52:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565787176; cv=none; d=google.com; s=arc-20160816; b=Qa3MMRKUJnfK0Onyi0EDMfrMGg03y7Ek+LeuJKWBaIe9VITlm6xNILkGNrP2IaeNWN 1cHNSeKGNhMISAWYI2GinHl9nVxmrW4P2PJ5BkIzipwqTsA5x2qgSTbE7bVVGcdninmh 7FIhEMpwp87l7HzGV8wGA4Ka3+dV37Ddz2+Zxbpa6iQAUcWI3VnzwdZCHSH8lnUxPLH0 zwst6pvz7n9P/qyWqevFm44WMOmfA7CAM2g4eSDNUsOFXHThE1ncoCnbo78xTqfMQlg5 QbDzfYI2mdnbO0FqJfA3YXxjrryzN1bYIwadxFbTN0TBMP0NhfWX40Wk4+Gh+ukLwEzu K/7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature; bh=/+aArS/+ZpXWQrNyAPbe/FVozsbsHho1Pyh+D5yt+eM=; b=kWpf0IK+yfiavQfU69z8xPjvNrd60+42nvconUW+q8LhvJ/XEoG/vTLUTDUtSN7lKb etG3iK6kF7VL4+3gNgTt3MFFLNSPuQlCC3TSyRnWBdgZUYSHOjjwOr4fcV2Gci+Xe1dQ GPd1u63xkSsw7i8TGaOD2/prbThGlDgWIDzDZC4Y8umALklwW+fqlQ1XuAffOkqDIX3B uVbBxs3aLuMH8fZGQSOktzhPuPR6Xbiq7zyosDFzBHuTWPcHJVg/ipaAk5DlWO7zVpJH sA0dBX+8IBr0IUhzxaZamLr08iYp06cz9nBRN91SmyE5cFaFv81aaSylsDmAwzjmL6oc RpWg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@digidescorp.com header.s=google header.b=Q46RYsE2; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q38si54545503pgk.63.2019.08.14.05.52.40; Wed, 14 Aug 2019 05:52:56 -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; dkim=pass header.i=@digidescorp.com header.s=google header.b=Q46RYsE2; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727826AbfHNMuN (ORCPT + 99 others); Wed, 14 Aug 2019 08:50:13 -0400 Received: from mail-oi1-f196.google.com ([209.85.167.196]:38036 "EHLO mail-oi1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726365AbfHNMuM (ORCPT ); Wed, 14 Aug 2019 08:50:12 -0400 Received: by mail-oi1-f196.google.com with SMTP id p124so3498972oig.5 for ; Wed, 14 Aug 2019 05:50:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=digidescorp.com; s=google; h=from:to:cc:subject:date:message-id; bh=/+aArS/+ZpXWQrNyAPbe/FVozsbsHho1Pyh+D5yt+eM=; b=Q46RYsE22MhQi0qPL9mOVIvPiWIAlcb6XvRg2G1Kab100w6d33bkV6Nj7WbfBhZLFS DePA24isLJdfXVfQiu01V6rvCiv+SNWBYE1TAmyt7D0OP0KaZLFg3PB7+pLJD+GF+OWk MGcqJVVXmPl35qlkvYbT7sQLmXWlVgITTelZI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=/+aArS/+ZpXWQrNyAPbe/FVozsbsHho1Pyh+D5yt+eM=; b=dWtD1asWUbTT9lBT74LlMsFYxyaBXE2YIJ1bhpXiqUfP0GDMngbAL9gnyNoRPJgp4Z x9/KlwDq1OfANpJ7Hn9ORqjyU7Q2dxiHhm32grjKip/8tZA0XX6pkKhFmt1BWNehUZHr aUA10kUbT12410uiE48ZBnzW4LRLFXzdVyrIQ0h3PBLSMYBOhp4DQnVvGXE5egpbNOix 6nEMOHx4uFLhtvWrrIJLIDpey0m3yn/uK/lZ9Eus5wUSfH+IQeBFJcNhssdtdp65lmz6 AvcEYrD3D5VOX1LHv4Anay7fBxxUGoMAFNn0fxep+Y8ma0eGLxXgp37jMTxortwOyxDa RwGw== X-Gm-Message-State: APjAAAU0WeCUVbmb7E5y5lSgHRMIG712RNVUlrOaMynNoVu6f83IQ85g xPma/13PkyW8EVju7GEs/uqvog== X-Received: by 2002:a02:9981:: with SMTP id a1mr3295802jal.17.1565787011740; Wed, 14 Aug 2019 05:50:11 -0700 (PDT) Received: from iscandar.digidescorp.com ([50.73.98.161]) by smtp.googlemail.com with ESMTPSA id j5sm83102558iom.69.2019.08.14.05.50.10 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 14 Aug 2019 05:50:11 -0700 (PDT) From: "Steven J. Magnani" X-Google-Original-From: "Steven J. Magnani" To: Jan Kara Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, "Steven J . Magnani" Subject: [PATCH v2] udf: reduce leakage of blocks related to named streams Date: Wed, 14 Aug 2019 07:50:02 -0500 Message-Id: <20190814125002.10869-1-steve@digidescorp.com> X-Mailer: git-send-email 2.17.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Windows is capable of creating UDF files having named streams. One example is the "Zone.Identifier" stream attached automatically to files downloaded from a network. See: https://msdn.microsoft.com/en-us/library/dn392609.aspx Modification of a file having one or more named streams in Linux causes the stream directory to become detached from the file, essentially leaking all blocks pertaining to the file's streams. Fix by saving off information about an inode's streams when reading it, for later use when its on-disk data is updated. Changes from v1: Remove modifications that would limit leakage of all inode blocks on deletion. This restricts the patch to preservation of stream data during inode modification. Signed-off-by: Steven J. Magnani --- a/fs/udf/udf_i.h 2019-07-26 11:35:28.257563879 -0500 +++ b/fs/udf/udf_i.h 2019-08-06 14:35:55.579654263 -0500 @@ -42,12 +42,15 @@ struct udf_inode_info { unsigned i_efe : 1; /* extendedFileEntry */ unsigned i_use : 1; /* unallocSpaceEntry */ unsigned i_strat4096 : 1; - unsigned reserved : 26; + unsigned i_streamdir : 1; + unsigned reserved : 25; union { struct short_ad *i_sad; struct long_ad *i_lad; __u8 *i_data; } i_ext; + struct kernel_lb_addr i_locStreamdir; + __u64 i_lenStreams; struct rw_semaphore i_data_sem; struct udf_ext_cache cached_extent; /* Spinlock for protecting extent cache */ --- a/fs/udf/super.c 2019-07-26 11:35:28.253563792 -0500 +++ b/fs/udf/super.c 2019-08-06 15:04:30.851086957 -0500 @@ -151,9 +151,13 @@ static struct inode *udf_alloc_inode(str ei->i_unique = 0; ei->i_lenExtents = 0; + ei->i_lenStreams = 0; ei->i_next_alloc_block = 0; ei->i_next_alloc_goal = 0; ei->i_strat4096 = 0; + ei->i_streamdir = 0; + ei->i_locStreamdir.logicalBlockNum = 0xFFFFFFFF; + ei->i_locStreamdir.partitionReferenceNum = 0xFFFF; init_rwsem(&ei->i_data_sem); ei->cached_extent.lstart = -1; spin_lock_init(&ei->i_extent_cache_lock); --- a/fs/udf/inode.c 2019-07-26 11:35:28.253563792 -0500 +++ b/fs/udf/inode.c 2019-08-06 15:04:30.851086957 -0500 @@ -1485,6 +1485,10 @@ reread: iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); + iinfo->i_streamdir = 0; + iinfo->i_lenStreams = 0; + iinfo->i_locStreamdir.logicalBlockNum = 0xFFFFFFFF; + iinfo->i_locStreamdir.partitionReferenceNum = 0xFFFF; } else { inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); @@ -1498,6 +1502,16 @@ reread: iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); + + /* Named streams */ + iinfo->i_streamdir = (efe->streamDirectoryICB.extLength != 0); + iinfo->i_locStreamdir = + lelb_to_cpu(efe->streamDirectoryICB.extLocation); + iinfo->i_lenStreams = le64_to_cpu(efe->objectSize); + if (iinfo->i_lenStreams >= inode->i_size) + iinfo->i_lenStreams -= inode->i_size; + else + iinfo->i_lenStreams = 0; } inode->i_generation = iinfo->i_unique; @@ -1760,9 +1774,19 @@ static int udf_update_inode(struct inode iinfo->i_ext.i_data, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); - efe->objectSize = cpu_to_le64(inode->i_size); + efe->objectSize = + cpu_to_le64(inode->i_size + iinfo->i_lenStreams); efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); + if (iinfo->i_streamdir) { + struct long_ad *icb_lad = &efe->streamDirectoryICB; + + icb_lad->extLocation = + cpu_to_lelb(iinfo->i_locStreamdir); + icb_lad->extLength = + cpu_to_le32(inode->i_sb->s_blocksize); + } + udf_adjust_time(iinfo, inode->i_atime); udf_adjust_time(iinfo, inode->i_mtime); udf_adjust_time(iinfo, inode->i_ctime);