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 { 306493792dSZhang 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 { 426493792dSZhang Yi bh = ext4_bread(NULL, inode, 0, 0); 436493792dSZhang Yi if (IS_ERR(bh)) 446493792dSZhang Yi return ERR_CAST(bh); 456493792dSZhang Yi if (!bh) { 466493792dSZhang Yi EXT4_ERROR_INODE(inode, "bad symlink."); 476493792dSZhang Yi return ERR_PTR(-EFSCORRUPTED); 486493792dSZhang Yi } 496493792dSZhang 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); 546493792dSZhang Yi brelse(bh); 55fceef393SAl Viro return paddr; 56f348c252STheodore Ts'o } 57f348c252STheodore Ts'o 58*b74d24f7SChristian Brauner static int ext4_encrypted_symlink_getattr(struct mnt_idmap *idmap, 598c4bca10SEric Biggers const struct path *path, 608c4bca10SEric Biggers struct kstat *stat, u32 request_mask, 618c4bca10SEric Biggers unsigned int query_flags) 628c4bca10SEric Biggers { 63*b74d24f7SChristian Brauner ext4_getattr(idmap, path, stat, request_mask, query_flags); 648c4bca10SEric Biggers 658c4bca10SEric Biggers return fscrypt_symlink_getattr(path, stat); 668c4bca10SEric Biggers } 678c4bca10SEric Biggers 686493792dSZhang Yi static void ext4_free_link(void *bh) 696493792dSZhang Yi { 706493792dSZhang Yi brelse(bh); 716493792dSZhang Yi } 726493792dSZhang Yi 736493792dSZhang Yi static const char *ext4_get_link(struct dentry *dentry, struct inode *inode, 746493792dSZhang Yi struct delayed_call *callback) 756493792dSZhang Yi { 766493792dSZhang Yi struct buffer_head *bh; 775a57bca9SZhang Yi char *inline_link; 785a57bca9SZhang Yi 795a57bca9SZhang Yi /* 805a57bca9SZhang Yi * Create a new inlined symlink is not supported, just provide a 815a57bca9SZhang Yi * method to read the leftovers. 825a57bca9SZhang Yi */ 835a57bca9SZhang Yi if (ext4_has_inline_data(inode)) { 845a57bca9SZhang Yi if (!dentry) 855a57bca9SZhang Yi return ERR_PTR(-ECHILD); 865a57bca9SZhang Yi 875a57bca9SZhang Yi inline_link = ext4_read_inline_link(inode); 885a57bca9SZhang Yi if (!IS_ERR(inline_link)) 895a57bca9SZhang Yi set_delayed_call(callback, kfree_link, inline_link); 905a57bca9SZhang Yi return inline_link; 915a57bca9SZhang Yi } 926493792dSZhang Yi 936493792dSZhang Yi if (!dentry) { 946493792dSZhang Yi bh = ext4_getblk(NULL, inode, 0, EXT4_GET_BLOCKS_CACHED_NOWAIT); 956493792dSZhang Yi if (IS_ERR(bh)) 966493792dSZhang Yi return ERR_CAST(bh); 976493792dSZhang Yi if (!bh || !ext4_buffer_uptodate(bh)) 986493792dSZhang Yi return ERR_PTR(-ECHILD); 996493792dSZhang Yi } else { 1006493792dSZhang Yi bh = ext4_bread(NULL, inode, 0, 0); 1016493792dSZhang Yi if (IS_ERR(bh)) 1026493792dSZhang Yi return ERR_CAST(bh); 1036493792dSZhang Yi if (!bh) { 1046493792dSZhang Yi EXT4_ERROR_INODE(inode, "bad symlink."); 1056493792dSZhang Yi return ERR_PTR(-EFSCORRUPTED); 1066493792dSZhang Yi } 1076493792dSZhang Yi } 1086493792dSZhang Yi 1096493792dSZhang Yi set_delayed_call(callback, ext4_free_link, bh); 1106493792dSZhang Yi nd_terminate_link(bh->b_data, inode->i_size, 1116493792dSZhang Yi inode->i_sb->s_blocksize - 1); 1126493792dSZhang Yi return bh->b_data; 1136493792dSZhang Yi } 1146493792dSZhang Yi 115a7a67e8aSAl Viro const struct inode_operations ext4_encrypted_symlink_inode_operations = { 1166b255391SAl Viro .get_link = ext4_encrypted_get_link, 117a7a67e8aSAl Viro .setattr = ext4_setattr, 1188c4bca10SEric Biggers .getattr = ext4_encrypted_symlink_getattr, 119a7a67e8aSAl Viro .listxattr = ext4_listxattr, 120a7a67e8aSAl Viro }; 121f348c252STheodore Ts'o 122754661f1SArjan van de Ven const struct inode_operations ext4_symlink_inode_operations = { 1236493792dSZhang Yi .get_link = ext4_get_link, 124256a4535SDmitry Monakhov .setattr = ext4_setattr, 12599652ea5SDavid Howells .getattr = ext4_getattr, 126617ba13bSMingming Cao .listxattr = ext4_listxattr, 127ac27a0ecSDave Kleikamp }; 128ac27a0ecSDave Kleikamp 129754661f1SArjan van de Ven const struct inode_operations ext4_fast_symlink_inode_operations = { 1306b255391SAl Viro .get_link = simple_get_link, 131256a4535SDmitry Monakhov .setattr = ext4_setattr, 13299652ea5SDavid Howells .getattr = ext4_getattr, 133617ba13bSMingming Cao .listxattr = ext4_listxattr, 134ac27a0ecSDave Kleikamp }; 135