Changes in 4.19.207 ext4: fix race writing to an inline_data file while its xattrs are changing xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG gpu: ipu-v3: Fix i.MX IPU-v3 offset calculations for (semi)planar U/V formats qed: Fix the VF msix vectors flow net: macb: Add a NULL check on desc_ptp qede: Fix memset corruption perf/x86/intel/pt: Fix mask of num_address_ranges perf/x86/amd/ibs: Work around erratum #1197 cryptoloop: add a deprecation warning ARM: 8918/2: only build return_address() if needed ALSA: pcm: fix divide error in snd_pcm_lib_ioctl clk: fix build warning for orphan_list media: stkwebcam: fix memory leak in stk_camera_probe ARM: imx: add missing clk_disable_unprepare() ARM: imx: fix missing 3rd argument in macro imx_mmdc_perf_init igmp: Add ip_mc_list lock in ip_check_mc_rcu USB: serial: mos7720: improve OOM-handling in read_mos_reg() ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2) SUNRPC/nfs: Fix return value for nfs4_callback_compound() crypto: talitos - reduce max key size for SEC1 powerpc/module64: Fix comment in R_PPC64_ENTRY handling powerpc/boot: Delete unneeded .globl _zimage_start net: ll_temac: Remove left-over debug message mm/page_alloc: speed up the iteration of max_order Revert "btrfs: compression: don't try to compress if we don't have enough pages" ALSA: usb-audio: Add registration quirk for JBL Quantum 800 usb: host: xhci-rcar: Don't reload firmware after the completion usb: mtu3: use @mult for HS isoc or intr usb: mtu3: fix the wrong HS mult value x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions PCI: Call Max Payload Size-related fixup quirks early locking/mutex: Fix HANDOFF condition regmap: fix the offset of register error log crypto: mxs-dcp - Check for DMA mapping errors sched/deadline: Fix reset_on_fork reporting of DL tasks power: supply: axp288_fuel_gauge: Report register-address on readb / writeb errors crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop() sched/deadline: Fix missing clock update in migrate_task_rq_dl() hrtimer: Avoid double reprogramming in __hrtimer_start_range_ns() udf: Check LVID earlier isofs: joliet: Fix iocharset=utf8 mount option bcache: add proper error unwinding in bcache_device_init nvme-rdma: don't update queue count when failing to set io queues power: supply: max17042_battery: fix typo in MAx17042_TOFF s390/cio: add dev_busid sysfs entry for each subchannel libata: fix ata_host_start() crypto: qat - do not ignore errors from enable_vf2pf_comms() crypto: qat - handle both source of interrupt in VF ISR crypto: qat - fix reuse of completion variable crypto: qat - fix naming for init/shutdown VF to PF notifications crypto: qat - do not export adf_iov_putmsg() fcntl: fix potential deadlock for &fasync_struct.fa_lock udf_get_extendedattr() had no boundary checks. m68k: emu: Fix invalid free in nfeth_cleanup() spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_config spi: spi-pic32: Fix issue with uninitialized dma_slave_config lib/mpi: use kcalloc in mpi_resize clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock source channel crypto: qat - use proper type for vf_mask certs: Trigger creation of RSA module signing key if it's not an RSA key spi: sprd: Fix the wrong WDG_LOAD_VAL media: TDA1997x: enable EDID support soc: rockchip: ROCKCHIP_GRF should not default to y, unconditionally media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init media: dvb-usb: fix uninit-value in vp702x_read_mac_addr media: go7007: remove redundant initialization Bluetooth: sco: prevent information leak in sco_conn_defer_accept() tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos net: cipso: fix warnings in netlbl_cipsov4_add_std i2c: highlander: add IRQ check media: em28xx-input: fix refcount bug in em28xx_usb_disconnect media: venus: venc: Fix potential null pointer dereference on pointer fmt PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently PCI: PM: Enable PME if it can be signaled from D3cold soc: qcom: smsm: Fix missed interrupts if state changes while masked Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow drm/msm/dpu: make dpu_hw_ctl_clear_all_blendstages clear necessary LMs arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7 Bluetooth: fix repeated calls to sco_sock_kill drm/msm/dsi: Fix some reference counted resource leaks usb: gadget: udc: at91: add IRQ check usb: phy: fsl-usb: add IRQ check usb: phy: twl6030: add IRQ checks Bluetooth: Move shutdown callback before flushing tx and rx queue usb: host: ohci-tmio: add IRQ check usb: phy: tahvo: add IRQ check mac80211: Fix insufficient headroom issue for AMSDU usb: gadget: mv_u3d: request_irq() after initializing UDC Bluetooth: add timeout sanity check to hci_inquiry i2c: iop3xx: fix deferred probing i2c: s3c2410: fix IRQ check mmc: dw_mmc: Fix issue with uninitialized dma_slave_config mmc: moxart: Fix issue with uninitialized dma_slave_config CIFS: Fix a potencially linear read overflow i2c: mt65xx: fix IRQ check usb: ehci-orion: Handle errors of clk_prepare_enable() in probe usb: bdc: Fix an error handling path in 'bdc_probe()' when no suitable DMA config is available tty: serial: fsl_lpuart: fix the wrong mapbase value ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point() bcma: Fix memory leak for internally-handled cores ipv4: make exception cache less predictible net: sched: Fix qdisc_rate_table refcount leak when get tcf_block failed net: qualcomm: fix QCA7000 checksum handling ipv4: fix endianness issue in inet_rtm_getroute_build_skb() netns: protect netns ID lookups with RCU fscrypt: add fscrypt_symlink_getattr() for computing st_size ext4: report correct st_size for encrypted symlinks f2fs: report correct st_size for encrypted symlinks ubifs: report correct st_size for encrypted symlinks tty: Fix data race between tiocsti() and flush_to_ldisc() x86/resctrl: Fix a maybe-uninitialized build warning treated as error KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted IMA: remove -Wmissing-prototypes warning IMA: remove the dependency on CRYPTO_MD5 fbmem: don't allow too huge resolutions backlight: pwm_bl: Improve bootloader/kernel device handover clk: kirkwood: Fix a clocking boot regression rtc: tps65910: Correct driver module alias btrfs: reset replace target device to allocation state on close blk-zoned: allow zone management send operations without CAP_SYS_ADMIN blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN PCI/MSI: Skip masking MSI-X on Xen PV powerpc/perf/hv-gpci: Fix counter value parsing xen: fix setting of max_pfn in shared_info include/linux/list.h: add a macro to test if entry is pointing to the head 9p/xen: Fix end of loop tests for list_for_each_entry bpf/verifier: per-register parent pointers bpf: correct slot_type marking logic to allow more stack slot sharing bpf: Support variable offset stack access from helpers bpf: Reject indirect var_off stack access in raw mode bpf: Reject indirect var_off stack access in unpriv mode bpf: Sanity check max value for var_off stack access selftests/bpf: Test variable offset stack access bpf: track spill/fill of constants selftests/bpf: fix tests due to const spill/fill bpf: Introduce BPF nospec instruction for mitigating Spectre v4 bpf: Fix leakage due to insufficient speculative store bypass mitigation bpf: verifier: Allocate idmap scratch in verifier env bpf: Fix pointer arithmetic mask tightening under state pruning tools/thermal/tmon: Add cross compiling support soc: aspeed: lpc-ctrl: Fix boundary check for mmap arm64: head: avoid over-mapping in map_memory crypto: public_key: fix overflow during implicit conversion block: bfq: fix bfq_set_next_ioprio_data() power: supply: max17042: handle fails of reading status register dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc() VMCI: fix NULL pointer dereference when unmapping queue pair media: uvc: don't do DMA on stack media: rc-loopback: return number of emitters rather than error libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs ARM: 9105/1: atags_to_fdt: don't warn about stack size PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure PCI: xilinx-nwl: Enable the clock through CCF PCI: aardvark: Increase polling delay to 1.5s while waiting for PIO response PCI: aardvark: Fix masking and unmasking legacy INTx interrupts HID: input: do not report stylus battery state as "full" RDMA/iwcm: Release resources if iw_cm module initialization fails docs: Fix infiniband uverbs minor number pinctrl: samsung: Fix pinctrl bank pin count vfio: Use config not menuconfig for VFIO_NOIOMMU powerpc/stacktrace: Include linux/delay.h openrisc: don't printk() unconditionally pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry() scsi: qedi: Fix error codes in qedi_alloc_global_queues() platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from run_smbios_call fscache: Fix cookie key hashing f2fs: fix to account missing .skipped_gc_rwsem f2fs: fix to unmap pages from userspace process in punch_hole() MIPS: Malta: fix alignment of the devicetree buffer userfaultfd: prevent concurrent API initialization media: dib8000: rewrite the init prbs logic crypto: mxs-dcp - Use sg_mapping_iter to copy data PCI: Use pci_update_current_state() in pci_enable_device_flags() tipc: keep the skb in rcv queue until the whole data is read iio: dac: ad5624r: Fix incorrect handling of an optional regulator. ARM: dts: qcom: apq8064: correct clock names video: fbdev: kyro: fix a DoS bug by restricting user input netlink: Deal with ESRCH error in nlmsg_notify() Smack: Fix wrong semantics in smk_access_entry() usb: host: fotg210: fix the endpoint's transactional opportunities calculation usb: host: fotg210: fix the actual_length of an iso packet usb: gadget: u_ether: fix a potential null pointer dereference usb: gadget: composite: Allow bMaxPower=0 if self-powered staging: board: Fix uninitialized spinlock when attaching genpd tty: serial: jsm: hold port lock when reporting modem line changes drm/amd/amdgpu: Update debugfs link_settings output link_rate field in hex bpf/tests: Fix copy-and-paste error in double word test bpf/tests: Do not PASS tests without actually testing the result video: fbdev: asiliantfb: Error out if 'pixclock' equals zero video: fbdev: kyro: Error out if 'pixclock' equals zero video: fbdev: riva: Error out if 'pixclock' equals zero ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs() flow_dissector: Fix out-of-bounds warnings s390/jump_label: print real address in a case of a jump label bug serial: 8250: Define RX trigger levels for OxSemi 950 devices xtensa: ISS: don't panic in rs_init hvsi: don't panic on tty_register_driver failure serial: 8250_pci: make setup_port() parameters explicitly unsigned staging: ks7010: Fix the initialization of the 'sleep_status' structure samples: bpf: Fix tracex7 error raised on the missing argument ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init() Bluetooth: skip invalid hci_sync_conn_complete_evt bonding: 3ad: fix the concurrency between __bond_release_one() and bond_3ad_state_machine_handler() ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the matching in-/output media: imx258: Rectify mismatch of VTS value media: imx258: Limit the max analogue gain to 480 media: v4l2-dv-timings.c: fix wrong condition in two for-loops media: TDA1997x: fix tda1997x_query_dv_timings() return value media: tegra-cec: Handle errors of clk_prepare_enable() ARM: dts: imx53-ppd: Fix ACHC entry arm64: dts: qcom: sdm660: use reg value for memory node net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe() Bluetooth: schedule SCO timeouts with delayed_work Bluetooth: avoid circular locks in sco_sock_connect gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port() ARM: tegra: tamonten: Fix UART pad setting Bluetooth: Fix handling of LE Enhanced Connection Complete serial: sh-sci: fix break handling for sysrq tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD rpc: fix gss_svc_init cleanup on failure staging: rts5208: Fix get_ms_information() heap buffer size gfs2: Don't call dlm after protocol is unmounted of: Don't allow __of_attached_node_sysfs() without CONFIG_SYSFS mmc: sdhci-of-arasan: Check return value of non-void funtions mmc: rtsx_pci: Fix long reads when clock is prescaled selftests/bpf: Enlarge select() timeout for test_maps mmc: core: Return correct emmc response in case of ioctl error cifs: fix wrong release in sess_alloc_buffer() failed path Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set" usb: musb: musb_dsps: request_irq() after initializing musb usbip: give back URBs for unsent unlink requests during cleanup usbip:vhci_hcd USB port can get stuck in the disabled state ASoC: rockchip: i2s: Fix regmap_ops hang ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B parport: remove non-zero check on count ath9k: fix OOB read ar9300_eeprom_restore_internal ath9k: fix sleeping in atomic context net: fix NULL pointer reference in cipso_v4_doi_free net: w5100: check return value after calling platform_get_resource() parisc: fix crash with signals and alloca ovl: fix BUG_ON() in may_delete() when called from ovl_cleanup() scsi: BusLogic: Fix missing pr_cont() use scsi: qla2xxx: Sync queue idx with queue_pair_map idx cpufreq: powernv: Fix init_chip_info initialization in numa=off mm/hugetlb: initialize hugetlb_usage in mm_init memcg: enable accounting for pids in nested pid namespaces platform/chrome: cros_ec_proto: Send command again when timeout occurs drm/amdgpu: Fix BUG_ON assert dm thin metadata: Fix use-after-free in dm_bm_set_read_only xen: reset legacy rtc flag for PV domU bnx2x: Fix enabling network interfaces without VFs arm64/sve: Use correct size when reinitialising SVE state PM: base: power: don't try to use non-existing RTC for storing data PCI: Add AMD GPU multi-function power dependencies x86/mm: Fix kern_addr_valid() to cope with existing but not present entries tipc: fix an use-after-free issue in tipc_recvmsg net-caif: avoid user-triggerable WARN_ON(1) ptp: dp83640: don't define PAGE0 dccp: don't duplicate ccid when cloning dccp sock net/l2tp: Fix reference count leak in l2tp_udp_recv_core r6040: Restore MDIO clock frequency after MAC reset tipc: increase timeout in tipc_sk_enqueue() perf machine: Initialize srcline string member in add_location struct net/mlx5: Fix potential sleeping in atomic context events: Reuse value read using READ_ONCE instead of re-reading it net/af_unix: fix a data-race in unix_dgram_poll net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup tcp: fix tp->undo_retrans accounting in tcp_sacktag_one() qed: Handle management FW error ibmvnic: check failover_pending in login response net: hns3: pad the short tunnel frame before sending to hardware mm/memory_hotplug: use "unsigned long" for PFN in zone_for_pfn_range() KVM: s390: index kvm->arch.idle_mask by vcpu_idx dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation mfd: Don't use irq_create_mapping() to resolve a mapping PCI: Add ACS quirks for Cavium multi-function devices net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920 block, bfq: honor already-setup queue merges ethtool: Fix an error code in cxgb2.c NTB: perf: Fix an error code in perf_setup_inbuf() mfd: axp20x: Update AXP288 volatile ranges PCI: Fix pci_dev_str_match_path() alloc while atomic bug KVM: arm64: Handle PSCI resets before userspace touches vCPU state PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()' ARC: export clear_user_page() for modules net: dsa: b53: Fix calculating number of switch ports netfilter: socket: icmp6: fix use-after-scope fq_codel: reject silly quantum parameters qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom ip_gre: validate csum_start only on pull net: renesas: sh_eth: Fix freeing wrong tx descriptor s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant Linux 4.19.207 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I18108cb47ba9e95838ebe55aaabe34de345ee846
889 lines
27 KiB
C
889 lines
27 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* fscrypt.h: declarations for per-file encryption
|
|
*
|
|
* Filesystems that implement per-file encryption must include this header
|
|
* file.
|
|
*
|
|
* Copyright (C) 2015, Google, Inc.
|
|
*
|
|
* Written by Michael Halcrow, 2015.
|
|
* Modified by Jaegeuk Kim, 2015.
|
|
*/
|
|
#ifndef _LINUX_FSCRYPT_H
|
|
#define _LINUX_FSCRYPT_H
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/parser.h>
|
|
#include <linux/slab.h>
|
|
#include <uapi/linux/fscrypt.h>
|
|
|
|
#define FS_CRYPTO_BLOCK_SIZE 16
|
|
|
|
union fscrypt_context;
|
|
struct fscrypt_info;
|
|
struct seq_file;
|
|
|
|
struct fscrypt_str {
|
|
unsigned char *name;
|
|
u32 len;
|
|
};
|
|
|
|
struct fscrypt_name {
|
|
const struct qstr *usr_fname;
|
|
struct fscrypt_str disk_name;
|
|
u32 hash;
|
|
u32 minor_hash;
|
|
struct fscrypt_str crypto_buf;
|
|
bool is_ciphertext_name;
|
|
};
|
|
|
|
#define FSTR_INIT(n, l) { .name = n, .len = l }
|
|
#define FSTR_TO_QSTR(f) QSTR_INIT((f)->name, (f)->len)
|
|
#define fname_name(p) ((p)->disk_name.name)
|
|
#define fname_len(p) ((p)->disk_name.len)
|
|
|
|
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
|
|
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40
|
|
|
|
#ifdef CONFIG_FS_ENCRYPTION
|
|
/*
|
|
* fscrypt superblock flags
|
|
*/
|
|
#define FS_CFLG_OWN_PAGES (1U << 1)
|
|
|
|
/*
|
|
* crypto operations for filesystems
|
|
*/
|
|
struct fscrypt_operations {
|
|
unsigned int flags;
|
|
const char *key_prefix;
|
|
int (*get_context)(struct inode *inode, void *ctx, size_t len);
|
|
int (*set_context)(struct inode *inode, const void *ctx, size_t len,
|
|
void *fs_data);
|
|
const union fscrypt_context *(*get_dummy_context)(
|
|
struct super_block *sb);
|
|
bool (*empty_dir)(struct inode *inode);
|
|
unsigned int max_namelen;
|
|
bool (*has_stable_inodes)(struct super_block *sb);
|
|
void (*get_ino_and_lblk_bits)(struct super_block *sb,
|
|
int *ino_bits_ret, int *lblk_bits_ret);
|
|
bool (*inline_crypt_enabled)(struct super_block *sb);
|
|
int (*get_num_devices)(struct super_block *sb);
|
|
void (*get_devices)(struct super_block *sb,
|
|
struct request_queue **devs);
|
|
};
|
|
|
|
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
|
{
|
|
/* pairs with cmpxchg_release() in fscrypt_get_encryption_info() */
|
|
return READ_ONCE(inode->i_crypt_info) != NULL;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_needs_contents_encryption() - check whether an inode needs
|
|
* contents encryption
|
|
* @inode: the inode to check
|
|
*
|
|
* Return: %true iff the inode is an encrypted regular file and the kernel was
|
|
* built with fscrypt support.
|
|
*
|
|
* If you need to know whether the encrypt bit is set even when the kernel was
|
|
* built without fscrypt support, you must use IS_ENCRYPTED() directly instead.
|
|
*/
|
|
static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
|
|
{
|
|
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
|
|
}
|
|
|
|
static inline const union fscrypt_context *
|
|
fscrypt_get_dummy_context(struct super_block *sb)
|
|
{
|
|
if (!sb->s_cop->get_dummy_context)
|
|
return NULL;
|
|
return sb->s_cop->get_dummy_context(sb);
|
|
}
|
|
|
|
/*
|
|
* When d_splice_alias() moves a directory's encrypted alias to its decrypted
|
|
* alias as a result of the encryption key being added, DCACHE_ENCRYPTED_NAME
|
|
* must be cleared. Note that we don't have to support arbitrary moves of this
|
|
* flag because fscrypt doesn't allow encrypted aliases to be the source or
|
|
* target of a rename().
|
|
*/
|
|
static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
|
{
|
|
dentry->d_flags &= ~DCACHE_ENCRYPTED_NAME;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_is_nokey_name() - test whether a dentry is a no-key name
|
|
* @dentry: the dentry to check
|
|
*
|
|
* This returns true if the dentry is a no-key dentry. A no-key dentry is a
|
|
* dentry that was created in an encrypted directory that hasn't had its
|
|
* encryption key added yet. Such dentries may be either positive or negative.
|
|
*
|
|
* When a filesystem is asked to create a new filename in an encrypted directory
|
|
* and the new filename's dentry is a no-key dentry, it must fail the operation
|
|
* with ENOKEY. This includes ->create(), ->mkdir(), ->mknod(), ->symlink(),
|
|
* ->rename(), and ->link(). (However, ->rename() and ->link() are already
|
|
* handled by fscrypt_prepare_rename() and fscrypt_prepare_link().)
|
|
*
|
|
* This is necessary because creating a filename requires the directory's
|
|
* encryption key, but just checking for the key on the directory inode during
|
|
* the final filesystem operation doesn't guarantee that the key was available
|
|
* during the preceding dentry lookup. And the key must have already been
|
|
* available during the dentry lookup in order for it to have been checked
|
|
* whether the filename already exists in the directory and for the new file's
|
|
* dentry not to be invalidated due to it incorrectly having the no-key flag.
|
|
*
|
|
* Return: %true if the dentry is a no-key name
|
|
*/
|
|
static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
|
|
{
|
|
return dentry->d_flags & DCACHE_ENCRYPTED_NAME;
|
|
}
|
|
|
|
/* crypto.c */
|
|
void fscrypt_enqueue_decrypt_work(struct work_struct *);
|
|
|
|
struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
|
|
unsigned int len,
|
|
unsigned int offs,
|
|
gfp_t gfp_flags);
|
|
int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
|
|
unsigned int len, unsigned int offs,
|
|
u64 lblk_num, gfp_t gfp_flags);
|
|
|
|
int fscrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len,
|
|
unsigned int offs);
|
|
int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
|
|
unsigned int len, unsigned int offs,
|
|
u64 lblk_num);
|
|
|
|
static inline bool fscrypt_is_bounce_page(struct page *page)
|
|
{
|
|
return page->mapping == NULL;
|
|
}
|
|
|
|
static inline struct page *fscrypt_pagecache_page(struct page *bounce_page)
|
|
{
|
|
return (struct page *)page_private(bounce_page);
|
|
}
|
|
|
|
void fscrypt_free_bounce_page(struct page *bounce_page);
|
|
int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
|
|
|
|
/* policy.c */
|
|
int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg);
|
|
int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg);
|
|
int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg);
|
|
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
|
|
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
|
|
int fscrypt_inherit_context(struct inode *parent, struct inode *child,
|
|
void *fs_data, bool preload);
|
|
|
|
struct fscrypt_dummy_context {
|
|
const union fscrypt_context *ctx;
|
|
};
|
|
|
|
int fscrypt_set_test_dummy_encryption(struct super_block *sb,
|
|
const substring_t *arg,
|
|
struct fscrypt_dummy_context *dummy_ctx);
|
|
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
|
|
struct super_block *sb);
|
|
static inline void
|
|
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
|
|
{
|
|
kfree(dummy_ctx->ctx);
|
|
dummy_ctx->ctx = NULL;
|
|
}
|
|
|
|
/* keyring.c */
|
|
void fscrypt_sb_free(struct super_block *sb);
|
|
int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
|
|
int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg);
|
|
int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg);
|
|
int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg);
|
|
|
|
/* keysetup.c */
|
|
int fscrypt_get_encryption_info(struct inode *inode);
|
|
void fscrypt_put_encryption_info(struct inode *inode);
|
|
void fscrypt_free_inode(struct inode *inode);
|
|
int fscrypt_drop_inode(struct inode *inode);
|
|
|
|
/* fname.c */
|
|
int fscrypt_setup_filename(struct inode *inode, const struct qstr *iname,
|
|
int lookup, struct fscrypt_name *fname);
|
|
|
|
static inline void fscrypt_free_filename(struct fscrypt_name *fname)
|
|
{
|
|
kfree(fname->crypto_buf.name);
|
|
}
|
|
|
|
int fscrypt_fname_alloc_buffer(const struct inode *inode, u32 max_encrypted_len,
|
|
struct fscrypt_str *crypto_str);
|
|
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str);
|
|
int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
|
u32 hash, u32 minor_hash,
|
|
const struct fscrypt_str *iname,
|
|
struct fscrypt_str *oname);
|
|
bool fscrypt_match_name(const struct fscrypt_name *fname,
|
|
const u8 *de_name, u32 de_name_len);
|
|
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name);
|
|
|
|
/* bio.c */
|
|
void fscrypt_decrypt_bio(struct bio *bio);
|
|
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
|
sector_t pblk, unsigned int len);
|
|
|
|
/* hooks.c */
|
|
int fscrypt_file_open(struct inode *inode, struct file *filp);
|
|
int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
|
|
struct dentry *dentry);
|
|
int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
struct inode *new_dir, struct dentry *new_dentry,
|
|
unsigned int flags);
|
|
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
|
struct fscrypt_name *fname);
|
|
int fscrypt_prepare_setflags(struct inode *inode,
|
|
unsigned int oldflags, unsigned int flags);
|
|
int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
|
|
unsigned int max_len,
|
|
struct fscrypt_str *disk_link);
|
|
int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
|
|
unsigned int len, struct fscrypt_str *disk_link);
|
|
const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
|
unsigned int max_size,
|
|
struct delayed_call *done);
|
|
int fscrypt_symlink_getattr(const struct path *path, struct kstat *stat);
|
|
|
|
#else /* !CONFIG_FS_ENCRYPTION */
|
|
|
|
static inline bool fscrypt_has_encryption_key(const struct inode *inode)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline const union fscrypt_context *
|
|
fscrypt_get_dummy_context(struct super_block *sb)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline void fscrypt_handle_d_move(struct dentry *dentry)
|
|
{
|
|
}
|
|
|
|
static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* crypto.c */
|
|
static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
|
|
{
|
|
}
|
|
|
|
static inline struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
|
|
unsigned int len,
|
|
unsigned int offs,
|
|
gfp_t gfp_flags)
|
|
{
|
|
return ERR_PTR(-EOPNOTSUPP);
|
|
}
|
|
|
|
static inline int fscrypt_encrypt_block_inplace(const struct inode *inode,
|
|
struct page *page,
|
|
unsigned int len,
|
|
unsigned int offs, u64 lblk_num,
|
|
gfp_t gfp_flags)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_decrypt_pagecache_blocks(struct page *page,
|
|
unsigned int len,
|
|
unsigned int offs)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_decrypt_block_inplace(const struct inode *inode,
|
|
struct page *page,
|
|
unsigned int len,
|
|
unsigned int offs, u64 lblk_num)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline bool fscrypt_is_bounce_page(struct page *page)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline struct page *fscrypt_pagecache_page(struct page *bounce_page)
|
|
{
|
|
WARN_ON_ONCE(1);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
static inline void fscrypt_free_bounce_page(struct page *bounce_page)
|
|
{
|
|
}
|
|
|
|
/* policy.c */
|
|
static inline int fscrypt_ioctl_set_policy(struct file *filp,
|
|
const void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_get_policy_ex(struct file *filp,
|
|
void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_has_permitted_context(struct inode *parent,
|
|
struct inode *child)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int fscrypt_inherit_context(struct inode *parent,
|
|
struct inode *child,
|
|
void *fs_data, bool preload)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
struct fscrypt_dummy_context {
|
|
};
|
|
|
|
static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
|
|
char sep,
|
|
struct super_block *sb)
|
|
{
|
|
}
|
|
|
|
static inline void
|
|
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
|
|
{
|
|
}
|
|
|
|
/* keyring.c */
|
|
static inline void fscrypt_sb_free(struct super_block *sb)
|
|
{
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_add_key(struct file *filp, void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_remove_key_all_users(struct file *filp,
|
|
void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_ioctl_get_key_status(struct file *filp,
|
|
void __user *arg)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
/* keysetup.c */
|
|
static inline int fscrypt_get_encryption_info(struct inode *inode)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void fscrypt_put_encryption_info(struct inode *inode)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline void fscrypt_free_inode(struct inode *inode)
|
|
{
|
|
}
|
|
|
|
static inline int fscrypt_drop_inode(struct inode *inode)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* fname.c */
|
|
static inline int fscrypt_setup_filename(struct inode *dir,
|
|
const struct qstr *iname,
|
|
int lookup, struct fscrypt_name *fname)
|
|
{
|
|
if (IS_ENCRYPTED(dir))
|
|
return -EOPNOTSUPP;
|
|
|
|
memset(fname, 0, sizeof(*fname));
|
|
fname->usr_fname = iname;
|
|
fname->disk_name.name = (unsigned char *)iname->name;
|
|
fname->disk_name.len = iname->len;
|
|
return 0;
|
|
}
|
|
|
|
static inline void fscrypt_free_filename(struct fscrypt_name *fname)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline int fscrypt_fname_alloc_buffer(const struct inode *inode,
|
|
u32 max_encrypted_len,
|
|
struct fscrypt_str *crypto_str)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
|
|
{
|
|
return;
|
|
}
|
|
|
|
static inline int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
|
u32 hash, u32 minor_hash,
|
|
const struct fscrypt_str *iname,
|
|
struct fscrypt_str *oname)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
|
|
const u8 *de_name, u32 de_name_len)
|
|
{
|
|
/* Encryption support disabled; use standard comparison */
|
|
if (de_name_len != fname->disk_name.len)
|
|
return false;
|
|
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
|
|
}
|
|
|
|
static inline u64 fscrypt_fname_siphash(const struct inode *dir,
|
|
const struct qstr *name)
|
|
{
|
|
WARN_ON_ONCE(1);
|
|
return 0;
|
|
}
|
|
|
|
/* bio.c */
|
|
static inline void fscrypt_decrypt_bio(struct bio *bio)
|
|
{
|
|
}
|
|
|
|
static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
|
sector_t pblk, unsigned int len)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
/* hooks.c */
|
|
|
|
static inline int fscrypt_file_open(struct inode *inode, struct file *filp)
|
|
{
|
|
if (IS_ENCRYPTED(inode))
|
|
return -EOPNOTSUPP;
|
|
return 0;
|
|
}
|
|
|
|
static inline int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
|
|
struct dentry *dentry)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int __fscrypt_prepare_rename(struct inode *old_dir,
|
|
struct dentry *old_dentry,
|
|
struct inode *new_dir,
|
|
struct dentry *new_dentry,
|
|
unsigned int flags)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int __fscrypt_prepare_lookup(struct inode *dir,
|
|
struct dentry *dentry,
|
|
struct fscrypt_name *fname)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int fscrypt_prepare_setflags(struct inode *inode,
|
|
unsigned int oldflags,
|
|
unsigned int flags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline int __fscrypt_prepare_symlink(struct inode *dir,
|
|
unsigned int len,
|
|
unsigned int max_len,
|
|
struct fscrypt_str *disk_link)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
|
|
static inline int __fscrypt_encrypt_symlink(struct inode *inode,
|
|
const char *target,
|
|
unsigned int len,
|
|
struct fscrypt_str *disk_link)
|
|
{
|
|
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);
|
|
}
|
|
|
|
static inline int fscrypt_symlink_getattr(const struct path *path,
|
|
struct kstat *stat)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
#endif /* !CONFIG_FS_ENCRYPTION */
|
|
|
|
/* inline_crypt.c */
|
|
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
|
|
extern bool fscrypt_inode_uses_inline_crypto(const struct inode *inode);
|
|
|
|
extern bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode);
|
|
|
|
extern void fscrypt_set_bio_crypt_ctx(struct bio *bio,
|
|
const struct inode *inode,
|
|
u64 first_lblk, gfp_t gfp_mask);
|
|
|
|
extern void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
|
|
const struct buffer_head *first_bh,
|
|
gfp_t gfp_mask);
|
|
|
|
extern bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
|
|
u64 next_lblk);
|
|
|
|
extern bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
|
const struct buffer_head *next_bh);
|
|
|
|
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter);
|
|
|
|
int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos,
|
|
int nr_pages);
|
|
|
|
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
|
|
static inline bool fscrypt_inode_uses_inline_crypto(const struct inode *inode)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode)
|
|
{
|
|
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
|
|
}
|
|
|
|
static inline void fscrypt_set_bio_crypt_ctx(struct bio *bio,
|
|
const struct inode *inode,
|
|
u64 first_lblk, gfp_t gfp_mask) { }
|
|
|
|
static inline void fscrypt_set_bio_crypt_ctx_bh(
|
|
struct bio *bio,
|
|
const struct buffer_head *first_bh,
|
|
gfp_t gfp_mask) { }
|
|
|
|
static inline bool fscrypt_mergeable_bio(struct bio *bio,
|
|
const struct inode *inode,
|
|
u64 next_lblk)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static inline bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
|
const struct buffer_head *next_bh)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static inline bool fscrypt_dio_supported(struct kiocb *iocb,
|
|
struct iov_iter *iter)
|
|
{
|
|
const struct inode *inode = file_inode(iocb->ki_filp);
|
|
|
|
return !fscrypt_needs_contents_encryption(inode);
|
|
}
|
|
|
|
static inline int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos,
|
|
int nr_pages)
|
|
{
|
|
return nr_pages;
|
|
}
|
|
#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
|
|
|
|
#if IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_DM_DEFAULT_KEY)
|
|
static inline bool
|
|
fscrypt_inode_should_skip_dm_default_key(const struct inode *inode)
|
|
{
|
|
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
|
|
}
|
|
#else
|
|
static inline bool
|
|
fscrypt_inode_should_skip_dm_default_key(const struct inode *inode)
|
|
{
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* fscrypt_require_key() - require an inode's encryption key
|
|
* @inode: the inode we need the key for
|
|
*
|
|
* If the inode is encrypted, set up its encryption key if not already done.
|
|
* Then require that the key be present and return -ENOKEY otherwise.
|
|
*
|
|
* No locks are needed, and the key will live as long as the struct inode --- so
|
|
* it won't go away from under you.
|
|
*
|
|
* Return: 0 on success, -ENOKEY if the key is missing, or another -errno code
|
|
* if a problem occurred while setting up the encryption key.
|
|
*/
|
|
static inline int fscrypt_require_key(struct inode *inode)
|
|
{
|
|
if (IS_ENCRYPTED(inode)) {
|
|
int err = fscrypt_get_encryption_info(inode);
|
|
|
|
if (err)
|
|
return err;
|
|
if (!fscrypt_has_encryption_key(inode))
|
|
return -ENOKEY;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_prepare_link() - prepare to link an inode into a possibly-encrypted
|
|
* directory
|
|
* @old_dentry: an existing dentry for the inode being linked
|
|
* @dir: the target directory
|
|
* @dentry: negative dentry for the target filename
|
|
*
|
|
* A new link can only be added to an encrypted directory if the directory's
|
|
* encryption key is available --- since otherwise we'd have no way to encrypt
|
|
* the filename. Therefore, we first set up the directory's encryption key (if
|
|
* not already done) and return an error if it's unavailable.
|
|
*
|
|
* We also verify that the link will not violate the constraint that all files
|
|
* in an encrypted directory tree use the same encryption policy.
|
|
*
|
|
* Return: 0 on success, -ENOKEY if the directory's encryption key is missing,
|
|
* -EXDEV if the link would result in an inconsistent encryption policy, or
|
|
* another -errno code.
|
|
*/
|
|
static inline int fscrypt_prepare_link(struct dentry *old_dentry,
|
|
struct inode *dir,
|
|
struct dentry *dentry)
|
|
{
|
|
if (IS_ENCRYPTED(dir))
|
|
return __fscrypt_prepare_link(d_inode(old_dentry), dir, dentry);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_prepare_rename() - prepare for a rename between possibly-encrypted
|
|
* directories
|
|
* @old_dir: source directory
|
|
* @old_dentry: dentry for source file
|
|
* @new_dir: target directory
|
|
* @new_dentry: dentry for target location (may be negative unless exchanging)
|
|
* @flags: rename flags (we care at least about %RENAME_EXCHANGE)
|
|
*
|
|
* Prepare for ->rename() where the source and/or target directories may be
|
|
* encrypted. A new link can only be added to an encrypted directory if the
|
|
* directory's encryption key is available --- since otherwise we'd have no way
|
|
* to encrypt the filename. A rename to an existing name, on the other hand,
|
|
* *is* cryptographically possible without the key. However, we take the more
|
|
* conservative approach and just forbid all no-key renames.
|
|
*
|
|
* We also verify that the rename will not violate the constraint that all files
|
|
* in an encrypted directory tree use the same encryption policy.
|
|
*
|
|
* Return: 0 on success, -ENOKEY if an encryption key is missing, -EXDEV if the
|
|
* rename would cause inconsistent encryption policies, or another -errno code.
|
|
*/
|
|
static inline int fscrypt_prepare_rename(struct inode *old_dir,
|
|
struct dentry *old_dentry,
|
|
struct inode *new_dir,
|
|
struct dentry *new_dentry,
|
|
unsigned int flags)
|
|
{
|
|
if (IS_ENCRYPTED(old_dir) || IS_ENCRYPTED(new_dir))
|
|
return __fscrypt_prepare_rename(old_dir, old_dentry,
|
|
new_dir, new_dentry, flags);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_prepare_lookup() - prepare to lookup a name in a possibly-encrypted
|
|
* directory
|
|
* @dir: directory being searched
|
|
* @dentry: filename being looked up
|
|
* @fname: (output) the name to use to search the on-disk directory
|
|
*
|
|
* Prepare for ->lookup() in a directory which may be encrypted by determining
|
|
* the name that will actually be used to search the directory on-disk. Lookups
|
|
* can be done with or without the directory's encryption key; without the key,
|
|
* filenames are presented in encrypted form. Therefore, we'll try to set up
|
|
* the directory's encryption key, but even without it the lookup can continue.
|
|
*
|
|
* After calling this function, a filesystem should ensure that it's dentry
|
|
* operations contain fscrypt_d_revalidate if DCACHE_ENCRYPTED_NAME was set,
|
|
* so that the dentry can be invalidated if the key is later added.
|
|
*
|
|
* Return: 0 on success; -ENOENT if key is unavailable but the filename isn't a
|
|
* correctly formed encoded ciphertext name, so a negative dentry should be
|
|
* created; or another -errno code.
|
|
*/
|
|
static inline int fscrypt_prepare_lookup(struct inode *dir,
|
|
struct dentry *dentry,
|
|
struct fscrypt_name *fname)
|
|
{
|
|
if (IS_ENCRYPTED(dir))
|
|
return __fscrypt_prepare_lookup(dir, dentry, fname);
|
|
|
|
memset(fname, 0, sizeof(*fname));
|
|
fname->usr_fname = &dentry->d_name;
|
|
fname->disk_name.name = (unsigned char *)dentry->d_name.name;
|
|
fname->disk_name.len = dentry->d_name.len;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_prepare_setattr() - prepare to change a possibly-encrypted inode's
|
|
* attributes
|
|
* @dentry: dentry through which the inode is being changed
|
|
* @attr: attributes to change
|
|
*
|
|
* Prepare for ->setattr() on a possibly-encrypted inode. On an encrypted file,
|
|
* most attribute changes are allowed even without the encryption key. However,
|
|
* without the encryption key we do have to forbid truncates. This is needed
|
|
* because the size being truncated to may not be a multiple of the filesystem
|
|
* block size, and in that case we'd have to decrypt the final block, zero the
|
|
* portion past i_size, and re-encrypt it. (We *could* allow truncating to a
|
|
* filesystem block boundary, but it's simpler to just forbid all truncates ---
|
|
* and we already forbid all other contents modifications without the key.)
|
|
*
|
|
* Return: 0 on success, -ENOKEY if the key is missing, or another -errno code
|
|
* if a problem occurred while setting up the encryption key.
|
|
*/
|
|
static inline int fscrypt_prepare_setattr(struct dentry *dentry,
|
|
struct iattr *attr)
|
|
{
|
|
if (attr->ia_valid & ATTR_SIZE)
|
|
return fscrypt_require_key(d_inode(dentry));
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_prepare_symlink() - prepare to create a possibly-encrypted symlink
|
|
* @dir: directory in which the symlink is being created
|
|
* @target: plaintext symlink target
|
|
* @len: length of @target excluding null terminator
|
|
* @max_len: space the filesystem has available to store the symlink target
|
|
* @disk_link: (out) the on-disk symlink target being prepared
|
|
*
|
|
* This function computes the size the symlink target will require on-disk,
|
|
* stores it in @disk_link->len, and validates it against @max_len. An
|
|
* encrypted symlink may be longer than the original.
|
|
*
|
|
* Additionally, @disk_link->name is set to @target if the symlink will be
|
|
* unencrypted, but left NULL if the symlink will be encrypted. For encrypted
|
|
* symlinks, the filesystem must call fscrypt_encrypt_symlink() to create the
|
|
* on-disk target later. (The reason for the two-step process is that some
|
|
* filesystems need to know the size of the symlink target before creating the
|
|
* inode, e.g. to determine whether it will be a "fast" or "slow" symlink.)
|
|
*
|
|
* Return: 0 on success, -ENAMETOOLONG if the symlink target is too long,
|
|
* -ENOKEY if the encryption key is missing, or another -errno code if a problem
|
|
* occurred while setting up the encryption key.
|
|
*/
|
|
static inline int fscrypt_prepare_symlink(struct inode *dir,
|
|
const char *target,
|
|
unsigned int len,
|
|
unsigned int max_len,
|
|
struct fscrypt_str *disk_link)
|
|
{
|
|
if (IS_ENCRYPTED(dir) || fscrypt_get_dummy_context(dir->i_sb) != NULL)
|
|
return __fscrypt_prepare_symlink(dir, len, max_len, disk_link);
|
|
|
|
disk_link->name = (unsigned char *)target;
|
|
disk_link->len = len + 1;
|
|
if (disk_link->len > max_len)
|
|
return -ENAMETOOLONG;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* fscrypt_encrypt_symlink() - encrypt the symlink target if needed
|
|
* @inode: symlink inode
|
|
* @target: plaintext symlink target
|
|
* @len: length of @target excluding null terminator
|
|
* @disk_link: (in/out) the on-disk symlink target being prepared
|
|
*
|
|
* If the symlink target needs to be encrypted, then this function encrypts it
|
|
* into @disk_link->name. fscrypt_prepare_symlink() must have been called
|
|
* previously to compute @disk_link->len. If the filesystem did not allocate a
|
|
* buffer for @disk_link->name after calling fscrypt_prepare_link(), then one
|
|
* will be kmalloc()'ed and the filesystem will be responsible for freeing it.
|
|
*
|
|
* Return: 0 on success, -errno on failure
|
|
*/
|
|
static inline int fscrypt_encrypt_symlink(struct inode *inode,
|
|
const char *target,
|
|
unsigned int len,
|
|
struct fscrypt_str *disk_link)
|
|
{
|
|
if (IS_ENCRYPTED(inode))
|
|
return __fscrypt_encrypt_symlink(inode, target, len, disk_link);
|
|
return 0;
|
|
}
|
|
|
|
/* If *pagep is a bounce page, free it and set *pagep to the pagecache page */
|
|
static inline void fscrypt_finalize_bounce_page(struct page **pagep)
|
|
{
|
|
struct page *page = *pagep;
|
|
|
|
if (fscrypt_is_bounce_page(page)) {
|
|
*pagep = fscrypt_pagecache_page(page);
|
|
fscrypt_free_bounce_page(page);
|
|
}
|
|
}
|
|
|
|
#endif /* _LINUX_FSCRYPT_H */
|