1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2ac27a0ecSDave Kleikamp /* 3617ba13bSMingming Cao * linux/fs/ext4/symlink.c 4ac27a0ecSDave Kleikamp * 5ac27a0ecSDave Kleikamp * Only fast symlinks left here - the rest is done by generic code. AV, 1999 6ac27a0ecSDave Kleikamp * 7ac27a0ecSDave Kleikamp * Copyright (C) 1992, 1993, 1994, 1995 8ac27a0ecSDave Kleikamp * Remy Card (card@masi.ibp.fr) 9ac27a0ecSDave Kleikamp * Laboratoire MASI - Institut Blaise Pascal 10ac27a0ecSDave Kleikamp * Universite Pierre et Marie Curie (Paris VI) 11ac27a0ecSDave Kleikamp * 12ac27a0ecSDave Kleikamp * from 13ac27a0ecSDave Kleikamp * 14ac27a0ecSDave Kleikamp * linux/fs/minix/symlink.c 15ac27a0ecSDave Kleikamp * 16ac27a0ecSDave Kleikamp * Copyright (C) 1991, 1992 Linus Torvalds 17ac27a0ecSDave Kleikamp * 18617ba13bSMingming Cao * ext4 symlink handling code 19ac27a0ecSDave Kleikamp */ 20ac27a0ecSDave Kleikamp 21ac27a0ecSDave Kleikamp #include <linux/fs.h> 22ac27a0ecSDave Kleikamp #include <linux/namei.h> 233dcf5451SChristoph Hellwig #include "ext4.h" 24ac27a0ecSDave Kleikamp #include "xattr.h" 25ac27a0ecSDave Kleikamp 266b255391SAl Viro static const char *ext4_encrypted_get_link(struct dentry *dentry, 27fceef393SAl Viro struct inode *inode, 28fceef393SAl Viro struct delayed_call *done) 29ac27a0ecSDave Kleikamp { 30*6493792dSZhang Yi struct buffer_head *bh = NULL; 316a9269c8SEric Biggers const void *caddr; 326a9269c8SEric Biggers unsigned int max_size; 336a9269c8SEric Biggers const char *paddr; 34f348c252STheodore Ts'o 356b255391SAl Viro if (!dentry) 366b255391SAl Viro return ERR_PTR(-ECHILD); 376b255391SAl Viro 38f348c252STheodore Ts'o if (ext4_inode_is_fast_symlink(inode)) { 396a9269c8SEric Biggers caddr = EXT4_I(inode)->i_data; 409ec3a646SLinus Torvalds max_size = sizeof(EXT4_I(inode)->i_data); 41f348c252STheodore Ts'o } else { 42*6493792dSZhang Yi bh = ext4_bread(NULL, inode, 0, 0); 43*6493792dSZhang Yi if (IS_ERR(bh)) 44*6493792dSZhang Yi return ERR_CAST(bh); 45*6493792dSZhang Yi if (!bh) { 46*6493792dSZhang Yi EXT4_ERROR_INODE(inode, "bad symlink."); 47*6493792dSZhang Yi return ERR_PTR(-EFSCORRUPTED); 48*6493792dSZhang Yi } 49*6493792dSZhang Yi caddr = bh->b_data; 506a9269c8SEric Biggers max_size = inode->i_sb->s_blocksize; 51f348c252STheodore Ts'o } 52f348c252STheodore Ts'o 536a9269c8SEric Biggers paddr = fscrypt_get_symlink(inode, caddr, max_size, done); 54*6493792dSZhang Yi brelse(bh); 55fceef393SAl Viro return paddr; 56f348c252STheodore Ts'o } 57f348c252STheodore Ts'o 588c4bca10SEric Biggers static int ext4_encrypted_symlink_getattr(struct user_namespace *mnt_userns, 598c4bca10SEric Biggers const struct path *path, 608c4bca10SEric Biggers struct kstat *stat, u32 request_mask, 618c4bca10SEric Biggers unsigned int query_flags) 628c4bca10SEric Biggers { 638c4bca10SEric Biggers ext4_getattr(mnt_userns, path, stat, request_mask, query_flags); 648c4bca10SEric Biggers 658c4bca10SEric Biggers return fscrypt_symlink_getattr(path, stat); 668c4bca10SEric Biggers } 678c4bca10SEric Biggers 68*6493792dSZhang Yi static void ext4_free_link(void *bh) 69*6493792dSZhang Yi { 70*6493792dSZhang Yi brelse(bh); 71*6493792dSZhang Yi } 72*6493792dSZhang Yi 73*6493792dSZhang Yi static const char *ext4_get_link(struct dentry *dentry, struct inode *inode, 74*6493792dSZhang Yi struct delayed_call *callback) 75*6493792dSZhang Yi { 76*6493792dSZhang Yi struct buffer_head *bh; 77*6493792dSZhang Yi 78*6493792dSZhang Yi if (!dentry) { 79*6493792dSZhang Yi bh = ext4_getblk(NULL, inode, 0, EXT4_GET_BLOCKS_CACHED_NOWAIT); 80*6493792dSZhang Yi if (IS_ERR(bh)) 81*6493792dSZhang Yi return ERR_CAST(bh); 82*6493792dSZhang Yi if (!bh || !ext4_buffer_uptodate(bh)) 83*6493792dSZhang Yi return ERR_PTR(-ECHILD); 84*6493792dSZhang Yi } else { 85*6493792dSZhang Yi bh = ext4_bread(NULL, inode, 0, 0); 86*6493792dSZhang Yi if (IS_ERR(bh)) 87*6493792dSZhang Yi return ERR_CAST(bh); 88*6493792dSZhang Yi if (!bh) { 89*6493792dSZhang Yi EXT4_ERROR_INODE(inode, "bad symlink."); 90*6493792dSZhang Yi return ERR_PTR(-EFSCORRUPTED); 91*6493792dSZhang Yi } 92*6493792dSZhang Yi } 93*6493792dSZhang Yi 94*6493792dSZhang Yi set_delayed_call(callback, ext4_free_link, bh); 95*6493792dSZhang Yi nd_terminate_link(bh->b_data, inode->i_size, 96*6493792dSZhang Yi inode->i_sb->s_blocksize - 1); 97*6493792dSZhang Yi return bh->b_data; 98*6493792dSZhang Yi } 99*6493792dSZhang Yi 100a7a67e8aSAl Viro const struct inode_operations ext4_encrypted_symlink_inode_operations = { 1016b255391SAl Viro .get_link = ext4_encrypted_get_link, 102a7a67e8aSAl Viro .setattr = ext4_setattr, 1038c4bca10SEric Biggers .getattr = ext4_encrypted_symlink_getattr, 104a7a67e8aSAl Viro .listxattr = ext4_listxattr, 105a7a67e8aSAl Viro }; 106f348c252STheodore Ts'o 107754661f1SArjan van de Ven const struct inode_operations ext4_symlink_inode_operations = { 108*6493792dSZhang Yi .get_link = ext4_get_link, 109256a4535SDmitry Monakhov .setattr = ext4_setattr, 11099652ea5SDavid Howells .getattr = ext4_getattr, 111617ba13bSMingming Cao .listxattr = ext4_listxattr, 112ac27a0ecSDave Kleikamp }; 113ac27a0ecSDave Kleikamp 114754661f1SArjan van de Ven const struct inode_operations ext4_fast_symlink_inode_operations = { 1156b255391SAl Viro .get_link = simple_get_link, 116256a4535SDmitry Monakhov .setattr = ext4_setattr, 11799652ea5SDavid Howells .getattr = ext4_getattr, 118617ba13bSMingming Cao .listxattr = ext4_listxattr, 119ac27a0ecSDave Kleikamp }; 120