From patchwork Fri Dec 15 17:42:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 849325 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="gZXfh6+L"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="V3fhWob3"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fFcwsURm"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yyykV2NdGz9s03 for ; Sat, 16 Dec 2017 04:54:58 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=7D3QxpW6tVU+o5/t4MqNKpAcJP56bcMZOmO+fxrqUzs=; b=gZXfh6+LAcaScDSsisYTxbqKtW nHTonwoPzNBVdynAdsjZCS1h5FgENlcPl4gwcMIDNk+w7DCBUmYO+UagoZ5OGsgAydU9eSzhpL5o4 tuQhCoF4WF6RjmunX+8MET6/1urqYbQ6wWi2DeIB92Y2q1BkZHWifU9XNWA/NSO0xAD8jpuFpTvJV 0BlGbwGRFMkZLCu3+oCtjl3Ur00l1t0XDbXtJ1LO0VrbOLATF/phQtjGQK3ZxjwoOgj48GbE8dJq/ P0snaOHSQ2grw0rqsKjOAJlgHi4K/yC3Camdq+pJdpQcgXNzxtwQdN5u8No4m09mHzsLlQt3oe+g8 gbgbM+HQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1ePuC5-0007EZ-Pe; Fri, 15 Dec 2017 17:54:45 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ePu5F-0000Av-CX for linux-mtd@bombadil.infradead.org; Fri, 15 Dec 2017 17:47:41 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=Z2wz02sYnJj/aLtYzyINYUs05Zn2AZ2pMhjHWr3CJcE=; b=V3fhWob3Ro+FRvnE1N3X5cn4l Udch1iiBDfrRVxS2nqcKD/rRDLrjvVmEYFkPDgGS8F15fKIyTs3jCgVIj1mJISqEaofVCLG4K+o1p BWToIc+8vYT9k6Ip2yTOXv13GnhSya5kQa8nC0zY5DNJ432EsqbNaBrRj1zUaS4DeclhtQWnEJIIn xlmXFq79z1OErzBBBdTnL+eLfCAKrBqcJxlO6xS4/IitN2IMHkQIRTPzTnjwcXDNdPgNK7pcGkYh0 Ip77Uk2CEfNYrPOJWZZxCRh1R8VMdukaDI0WEoQyxZq6v5jJ89ut+z1qPP0RWj5Bfwrbl6xqHMP7u 2tdDP6VGA==; Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ePu4z-0007mZ-L9 for linux-mtd@lists.infradead.org; Fri, 15 Dec 2017 17:47:26 +0000 Received: by mail-pf0-x242.google.com with SMTP id m26so6623842pfj.11 for ; Fri, 15 Dec 2017 09:47:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Z2wz02sYnJj/aLtYzyINYUs05Zn2AZ2pMhjHWr3CJcE=; b=fFcwsURmS3U9E1++H5V4sgc7LL5uJBFuBCCnZcxR6M2pL5GsyYke2B07SPDUGqTW4B VP+TC8hAGJwKd3mx4x6Fo/Ju7+3DwDzUa7dBR3fnsIHH5KAY3wY2Y3EfT6QJIGpEXwM5 4G9zfs2N+57OZfzrVSjlMDxJeKOcUPKsE159auSmqvb2pf20l8Cm15yovrltyyAg2I4T 8zZhfbVXMQiD/94sdB+tQVkr3WKJp6nrMkE10lbOYju+voya1jpmizDyD9q+F3XR1d6X 3vC/CG0Dcb1av8WIDp8RvNvpKzbKpeTiFF6O98ZF9I8ZVHCR8FeBVkwFy7OKh56tSyNv 7bXA== 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:in-reply-to :references; bh=Z2wz02sYnJj/aLtYzyINYUs05Zn2AZ2pMhjHWr3CJcE=; b=fxcARBlkDLj/v4MGqse3QpwSnP453ix4S8CkMKVgXGzvReSeItK76xevD4lRzPMcSs AnfAg9QRdAp9kUZUuYqwH3gmhLiXtSxp1KkM5bytMQbh8eYMuIuRTbF2fzbT4TdDr0Di gSw4NAi6czsGtpxGSemaY3zoufrKPFmn454sNPqUQp+YYvjZcMNUYw6vNlW8XG7PRZTS pTVQE5fp4cuYD5iy7gCRYHTjyo8vU3kpFIBKh3pyJY8MX4Rfj7uhAKsLbhksaacS40aS 5YMYJsA1vQl5ziQIHtbKn8n9/cnDd3RhGi6erzMwyluB4vQs+HeD7GnU3Ty6NdApgtSA fpXA== X-Gm-Message-State: AKGB3mI6pTTeB+eJ8Q/vCq//QF7dQmvf/zCcw5DHD9EkiLCZ0wjki5Ty e/FTY/GWQyEjaqOx9yulZAU= X-Google-Smtp-Source: ACJfBovvAEV3njuMeK5kkbyYLjaQdI0km5fbYEexOIrvvZbiVlJ1PoEexH0/xwkzmmW0Vym4caK4Mw== X-Received: by 10.84.246.197 with SMTP id j5mr14328131plt.168.1513360021796; Fri, 15 Dec 2017 09:47:01 -0800 (PST) Received: from zzz.localdomain (c-67-185-97-198.hsd1.wa.comcast.net. [67.185.97.198]) by smtp.gmail.com with ESMTPSA id j62sm12980149pfc.18.2017.12.15.09.47.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Dec 2017 09:47:00 -0800 (PST) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Subject: [PATCH 21/24] fscrypt: calculate NUL-padding length in one place only Date: Fri, 15 Dec 2017 09:42:22 -0800 Message-Id: <20171215174225.31583-22-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171215174225.31583-1-ebiggers3@gmail.com> References: <20171215174225.31583-1-ebiggers3@gmail.com> X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.8 (-) X-Spam-Report: SpamAssassin version 3.4.1 on merlin.infradead.org summary: Content analysis details: (-1.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:400e:c00:0:0:0:242 listed in] [list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (ebiggers3[at]gmail.com) 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit (ebiggers3[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Theodore Y . Ts'o" , Eric Biggers , linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org, Jaegeuk Kim , linux-ext4@vger.kernel.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Eric Biggers Currently, when encrypting a filename (either a real filename or a symlink target) we calculate the amount of NUL-padding twice: once before encryption and once during encryption in fname_encrypt(). It is needed before encryption to allocate the needed buffer size as well as calculate the size the symlink target will take up on-disk before creating the symlink inode. Calculating the size during encryption as well is redundant. Remove this redundancy by always calculating the exact size beforehand, and making fname_encrypt() just add as much NUL padding as is needed to fill the output buffer. Signed-off-by: Eric Biggers --- fs/crypto/fname.c | 53 ++++++++++++++++++++++----------------------- fs/crypto/fscrypt_private.h | 4 ++-- fs/crypto/hooks.c | 7 +----- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index cae7d1bcc8c5..65424b89a1d1 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -30,39 +30,29 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str) /** * fname_encrypt() - encrypt a filename * - * The caller must have allocated sufficient memory for the @oname string. + * The output buffer must be at least as large as the input buffer. + * Any extra space is filled with NUL padding before encryption. * * Return: 0 on success, -errno on failure */ -int fname_encrypt(struct inode *inode, - const struct qstr *iname, struct fscrypt_str *oname) +int fname_encrypt(struct inode *inode, const struct qstr *iname, + u8 *out, unsigned int olen) { struct skcipher_request *req = NULL; DECLARE_CRYPTO_WAIT(wait); - struct fscrypt_info *ci = inode->i_crypt_info; - struct crypto_skcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = inode->i_crypt_info->ci_ctfm; int res = 0; char iv[FS_CRYPTO_BLOCK_SIZE]; struct scatterlist sg; - int padding = 4 << (ci->ci_flags & FS_POLICY_FLAGS_PAD_MASK); - unsigned int lim; - unsigned int cryptlen; - - lim = inode->i_sb->s_cop->max_namelen(inode); - if (iname->len <= 0 || iname->len > lim) - return -EIO; /* * Copy the filename to the output buffer for encrypting in-place and * pad it with the needed number of NUL bytes. */ - if (WARN_ON(oname->len < iname->len)) + if (WARN_ON(olen < iname->len)) return -ENOBUFS; - cryptlen = max_t(unsigned int, iname->len, FS_CRYPTO_BLOCK_SIZE); - cryptlen = round_up(cryptlen, padding); - cryptlen = min3(cryptlen, lim, oname->len); - memcpy(oname->name, iname->name, iname->len); - memset(oname->name + iname->len, 0, cryptlen - iname->len); + memcpy(out, iname->name, iname->len); + memset(out + iname->len, 0, olen - iname->len); /* Initialize the IV */ memset(iv, 0, FS_CRYPTO_BLOCK_SIZE); @@ -77,8 +67,8 @@ int fname_encrypt(struct inode *inode, skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait); - sg_init_one(&sg, oname->name, cryptlen); - skcipher_request_set_crypt(req, &sg, &sg, cryptlen, iv); + sg_init_one(&sg, out, olen); + skcipher_request_set_crypt(req, &sg, &sg, olen, iv); /* Do the encryption */ res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait); @@ -89,7 +79,6 @@ int fname_encrypt(struct inode *inode, return res; } - oname->len = cryptlen; return 0; } @@ -354,11 +343,21 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, return ret; if (dir->i_crypt_info) { - ret = fscrypt_fname_alloc_buffer(dir, iname->len, - &fname->crypto_buf); - if (ret) - return ret; - ret = fname_encrypt(dir, iname, &fname->crypto_buf); + unsigned int max_len = dir->i_sb->s_cop->max_namelen(dir); + + if (iname->len > max_len) + return -ENAMETOOLONG; + + fname->crypto_buf.len = + min(fscrypt_fname_encrypted_size(dir, iname->len), + max_len); + fname->crypto_buf.name = kmalloc(fname->crypto_buf.len, + GFP_NOFS); + if (!fname->crypto_buf.name) + return -ENOMEM; + + ret = fname_encrypt(dir, iname, fname->crypto_buf.name, + fname->crypto_buf.len); if (ret) goto errout; fname->disk_name.name = fname->crypto_buf.name; @@ -410,7 +409,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, return 0; errout: - fscrypt_fname_free_buffer(&fname->crypto_buf); + kfree(fname->crypto_buf.name); return ret; } EXPORT_SYMBOL(fscrypt_setup_filename); diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index cec9ce309f41..053917587200 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -108,8 +108,8 @@ extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags); /* fname.c */ -extern int fname_encrypt(struct inode *inode, - const struct qstr *iname, struct fscrypt_str *oname); +extern int fname_encrypt(struct inode *inode, const struct qstr *iname, + u8 *out, unsigned int olen); /* keyinfo.c */ extern void __exit fscrypt_essiv_cleanup(void); diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index 0f103a5cb1aa..ff20cacdea94 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -157,7 +157,6 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, struct qstr iname = { .name = target, .len = len }; struct fscrypt_symlink_data *sd; unsigned int ciphertext_len; - struct fscrypt_str oname; err = fscrypt_require_key(inode); if (err) @@ -174,16 +173,12 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, ciphertext_len = disk_link->len - sizeof(*sd); sd->len = cpu_to_le16(ciphertext_len); - oname.name = sd->encrypted_path; - oname.len = ciphertext_len; - err = fname_encrypt(inode, &iname, &oname); + err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); if (err) { if (!disk_link->name) kfree(sd); return err; } - BUG_ON(oname.len != ciphertext_len); - /* * Null-terminating the ciphertext doesn't make sense, but we still * count the null terminator in the length, so we might as well