From patchwork Fri Dec 15 17:42:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 10115695 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 362106019C for ; Fri, 15 Dec 2017 17:46:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23AC929EE1 for ; Fri, 15 Dec 2017 17:46:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 185B92A024; Fri, 15 Dec 2017 17:46:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A426629EE1 for ; Fri, 15 Dec 2017 17:46:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756104AbdLORq5 (ORCPT ); Fri, 15 Dec 2017 12:46:57 -0500 Received: from mail-pg0-f67.google.com ([74.125.83.67]:39258 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756045AbdLORqu (ORCPT ); Fri, 15 Dec 2017 12:46:50 -0500 Received: by mail-pg0-f67.google.com with SMTP id w7so6252807pgv.6; Fri, 15 Dec 2017 09:46:50 -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=l2/0wnYiHKRBOfuIg7bIXP6T0CzMxYhMySSaxKnPoq4=; b=ZVvf+mcqnB40VrgYDCnqT4qY7fqwa312QJ8IxTrsenwBOUJubHKZt+s6ua9b8x+5d/ fEJF0+1b23rlCt4FjPIb+Vx5twoKjoqQ5okR/bsQdsWxM2EIcjDyXBBXsnm9yaTcBpog KlrabKKrHaNGEC+Ipkufjoan2bas/yxJHYFFibSr8NVtJR9HewOB8xJbe2C8Gh0v0nxm Z1OcesWXmUYy6k4U+1t1E4WkN7hxJFG4+HLTd9bmhyFRZoXm83Ps8Oa/36eTgiAFXLdc TP+m5NyuyS5NYYb1B4Z9mNWC1ej8T8+/x0j+g8mjnRJokc5M2IxtJeRSfA+t0TYq8sFO SYlg== 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=l2/0wnYiHKRBOfuIg7bIXP6T0CzMxYhMySSaxKnPoq4=; b=DX3C2AwOl+sRxEBxVLLN0ZPURxdmg4Sxnip/yRLI2JEh9y1Wr8m/WPW7QaXedCXKAF fCIAYkd7ocnfBHEalVEiYC1gEo+bOUkX3k0gSiJ0QuCLDi0w8Hfk9zaDYP13gwqhQFGt 1zHH66URUWoPOVsbENlnigq3nAHXXtp2v0GkT0avWN2WbKnItY0Fruuu6Zz2ctzLdRs7 TdkjJgmcAqbBLv/G7scbho9XxXj1SXEqx/fCfKrBAj8l3LYhYp2PCt8CqgaIc1iWCNba KSP3Za6+t6S8cHAJB5nIvroevMItIHIQcxEaiZRY0kD4hpbLYsSVpDA3jky1goibcSHb 1krg== X-Gm-Message-State: AKGB3mL4NU+hEWkWlZ0KO74wWXE2nS0zZl9stBw8otaY5iqdgD9kMLaZ wvZW8koeVOXxCQf/mfdI/BO3YnZxAIo= X-Google-Smtp-Source: ACJfBou+5bg09iY1Qp+fAzR6ultTi3Z8Q15EN2nqMoViinO2ExpdVHr9WzznwqWbL9bYRE7wFUP30A== X-Received: by 10.159.231.24 with SMTP id w24mr13921569plq.434.1513360009890; Fri, 15 Dec 2017 09:46:49 -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.46.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Dec 2017 09:46:49 -0800 (PST) From: Eric Biggers To: linux-fscrypt@vger.kernel.org Cc: "Theodore Y . Ts'o" , Jaegeuk Kim , linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org, Eric Biggers Subject: [PATCH 11/24] fscrypt: new helper function - fscrypt_get_symlink() Date: Fri, 15 Dec 2017 09:42:12 -0800 Message-Id: <20171215174225.31583-12-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> Sender: linux-fscrypt-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers Filesystems also have duplicate code to support ->get_link() on encrypted symlinks. Factor it out into a new function fscrypt_get_symlink(). It takes in the contents of the encrypted symlink on-disk and provides the target (decrypted or encoded) that should be returned from ->get_link(). Signed-off-by: Eric Biggers --- fs/crypto/hooks.c | 73 +++++++++++++++++++++++++++++++++++++++++ include/linux/fscrypt_notsupp.h | 8 +++++ include/linux/fscrypt_supp.h | 3 ++ 3 files changed, 84 insertions(+) diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index 483e87d40f03..0f103a5cb1aa 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -196,3 +196,76 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, return 0; } EXPORT_SYMBOL_GPL(__fscrypt_encrypt_symlink); + +/** + * fscrypt_get_symlink - get the target of an encrypted symlink + * @inode: the symlink inode + * @caddr: the on-disk contents of the symlink + * @max_size: size of @caddr buffer + * @done: if successful, will be set up to free the returned target + * + * If the symlink's encryption key is available, we decrypt its target. + * Otherwise, we encode its target for presentation. + * + * This may sleep, so the filesystem must have dropped out of RCU mode already. + * + * Return: the presentable symlink target or an ERR_PTR() + */ +const char *fscrypt_get_symlink(struct inode *inode, const void *caddr, + unsigned int max_size, + struct delayed_call *done) +{ + const struct fscrypt_symlink_data *sd; + struct fscrypt_str cstr, pstr; + int err; + + /* This is for encrypted symlinks only */ + if (WARN_ON(!IS_ENCRYPTED(inode))) + return ERR_PTR(-EINVAL); + + /* + * Try to set up the symlink's encryption key, but we can continue + * regardless of whether the key is available or not. + */ + err = fscrypt_get_encryption_info(inode); + if (err) + return ERR_PTR(err); + + /* + * For historical reasons, encrypted symlink targets are prefixed with + * the ciphertext length, even though this is redundant with i_size. + */ + + if (max_size < sizeof(*sd)) + return ERR_PTR(-EUCLEAN); + sd = caddr; + cstr.name = (unsigned char *)sd->encrypted_path; + cstr.len = le16_to_cpu(sd->len); + + if (cstr.len == 0) + return ERR_PTR(-EUCLEAN); + + if (cstr.len + sizeof(*sd) - 1 > max_size) + return ERR_PTR(-EUCLEAN); + + err = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr); + if (err) + return ERR_PTR(err); + + err = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); + if (err) + goto err_kfree; + + err = -EUCLEAN; + if (pstr.name[0] == '\0') + goto err_kfree; + + pstr.name[pstr.len] = '\0'; + set_delayed_call(done, kfree_link, pstr.name); + return pstr.name; + +err_kfree: + kfree(pstr.name); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(fscrypt_get_symlink); diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index 02ec0aa894d8..dd106640c6ea 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -239,4 +239,12 @@ static inline int __fscrypt_encrypt_symlink(struct inode *inode, return -EOPNOTSUPP; } +static inline const char *fscrypt_get_symlink(struct inode *inode, + const void *caddr, + unsigned int max_size, + struct delayed_call *done) +{ + return ERR_PTR(-EOPNOTSUPP); +} + #endif /* _LINUX_FSCRYPT_NOTSUPP_H */ diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 7e0b67ccd816..dc2babf3f7d3 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -211,5 +211,8 @@ extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, extern int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, unsigned int len, struct fscrypt_str *disk_link); +extern const char *fscrypt_get_symlink(struct inode *inode, const void *caddr, + unsigned int max_size, + struct delayed_call *done); #endif /* _LINUX_FSCRYPT_SUPP_H */