1ac27a0ecSDave Kleikamp /* 2617ba13bSMingming Cao * linux/fs/ext4/symlink.c 3ac27a0ecSDave Kleikamp * 4ac27a0ecSDave Kleikamp * Only fast symlinks left here - the rest is done by generic code. AV, 1999 5ac27a0ecSDave Kleikamp * 6ac27a0ecSDave Kleikamp * Copyright (C) 1992, 1993, 1994, 1995 7ac27a0ecSDave Kleikamp * Remy Card (card@masi.ibp.fr) 8ac27a0ecSDave Kleikamp * Laboratoire MASI - Institut Blaise Pascal 9ac27a0ecSDave Kleikamp * Universite Pierre et Marie Curie (Paris VI) 10ac27a0ecSDave Kleikamp * 11ac27a0ecSDave Kleikamp * from 12ac27a0ecSDave Kleikamp * 13ac27a0ecSDave Kleikamp * linux/fs/minix/symlink.c 14ac27a0ecSDave Kleikamp * 15ac27a0ecSDave Kleikamp * Copyright (C) 1991, 1992 Linus Torvalds 16ac27a0ecSDave Kleikamp * 17617ba13bSMingming Cao * ext4 symlink handling code 18ac27a0ecSDave Kleikamp */ 19ac27a0ecSDave Kleikamp 20ac27a0ecSDave Kleikamp #include <linux/fs.h> 21ac27a0ecSDave Kleikamp #include <linux/namei.h> 223dcf5451SChristoph Hellwig #include "ext4.h" 23ac27a0ecSDave Kleikamp #include "xattr.h" 24ac27a0ecSDave Kleikamp 25f348c252STheodore Ts'o #ifdef CONFIG_EXT4_FS_ENCRYPTION 266b255391SAl Viro static const char *ext4_encrypted_get_link(struct dentry *dentry, 27*fceef393SAl Viro struct inode *inode, 28*fceef393SAl Viro struct delayed_call *done) 29ac27a0ecSDave Kleikamp { 30f348c252STheodore Ts'o struct page *cpage = NULL; 31f348c252STheodore Ts'o char *caddr, *paddr = NULL; 32f348c252STheodore Ts'o struct ext4_str cstr, pstr; 33f348c252STheodore Ts'o struct ext4_encrypted_symlink_data *sd; 34f348c252STheodore Ts'o loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1); 35f348c252STheodore Ts'o int res; 36f348c252STheodore Ts'o u32 plen, max_size = inode->i_sb->s_blocksize; 37f348c252STheodore Ts'o 386b255391SAl Viro if (!dentry) 396b255391SAl Viro return ERR_PTR(-ECHILD); 406b255391SAl Viro 41c936e1ecSTheodore Ts'o res = ext4_get_encryption_info(inode); 42b7236e21STheodore Ts'o if (res) 43b7236e21STheodore Ts'o return ERR_PTR(res); 44f348c252STheodore Ts'o 45f348c252STheodore Ts'o if (ext4_inode_is_fast_symlink(inode)) { 469ec3a646SLinus Torvalds caddr = (char *) EXT4_I(inode)->i_data; 479ec3a646SLinus Torvalds max_size = sizeof(EXT4_I(inode)->i_data); 48f348c252STheodore Ts'o } else { 49f348c252STheodore Ts'o cpage = read_mapping_page(inode->i_mapping, 0, NULL); 50b7236e21STheodore Ts'o if (IS_ERR(cpage)) 51680baacbSAl Viro return ERR_CAST(cpage); 5221fc61c7SAl Viro caddr = page_address(cpage); 53f348c252STheodore Ts'o caddr[size] = 0; 54f348c252STheodore Ts'o } 55f348c252STheodore Ts'o 56f348c252STheodore Ts'o /* Symlink is encrypted */ 57f348c252STheodore Ts'o sd = (struct ext4_encrypted_symlink_data *)caddr; 58f348c252STheodore Ts'o cstr.name = sd->encrypted_path; 59f348c252STheodore Ts'o cstr.len = le32_to_cpu(sd->len); 60f348c252STheodore Ts'o if ((cstr.len + 61f348c252STheodore Ts'o sizeof(struct ext4_encrypted_symlink_data) - 1) > 62f348c252STheodore Ts'o max_size) { 63f348c252STheodore Ts'o /* Symlink data on the disk is corrupted */ 646a797d27SDarrick J. Wong res = -EFSCORRUPTED; 65f348c252STheodore Ts'o goto errout; 66f348c252STheodore Ts'o } 67f348c252STheodore Ts'o plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ? 68f348c252STheodore Ts'o EXT4_FNAME_CRYPTO_DIGEST_SIZE*2 : cstr.len; 69f348c252STheodore Ts'o paddr = kmalloc(plen + 1, GFP_NOFS); 70f348c252STheodore Ts'o if (!paddr) { 71f348c252STheodore Ts'o res = -ENOMEM; 72f348c252STheodore Ts'o goto errout; 73f348c252STheodore Ts'o } 74f348c252STheodore Ts'o pstr.name = paddr; 75d2299590STheodore Ts'o pstr.len = plen; 76b7236e21STheodore Ts'o res = _ext4_fname_disk_to_usr(inode, NULL, &cstr, &pstr); 77f348c252STheodore Ts'o if (res < 0) 78f348c252STheodore Ts'o goto errout; 79f348c252STheodore Ts'o /* Null-terminate the name */ 80f348c252STheodore Ts'o if (res <= plen) 81f348c252STheodore Ts'o paddr[res] = '\0'; 8221fc61c7SAl Viro if (cpage) 83f348c252STheodore Ts'o page_cache_release(cpage); 84*fceef393SAl Viro set_delayed_call(done, kfree_link, paddr); 85*fceef393SAl Viro return paddr; 86f348c252STheodore Ts'o errout: 8721fc61c7SAl Viro if (cpage) 88f348c252STheodore Ts'o page_cache_release(cpage); 89f348c252STheodore Ts'o kfree(paddr); 90f348c252STheodore Ts'o return ERR_PTR(res); 91f348c252STheodore Ts'o } 92f348c252STheodore Ts'o 93a7a67e8aSAl Viro const struct inode_operations ext4_encrypted_symlink_inode_operations = { 94a7a67e8aSAl Viro .readlink = generic_readlink, 956b255391SAl Viro .get_link = ext4_encrypted_get_link, 96a7a67e8aSAl Viro .setattr = ext4_setattr, 97a7a67e8aSAl Viro .setxattr = generic_setxattr, 98a7a67e8aSAl Viro .getxattr = generic_getxattr, 99a7a67e8aSAl Viro .listxattr = ext4_listxattr, 100a7a67e8aSAl Viro .removexattr = generic_removexattr, 101a7a67e8aSAl Viro }; 102f348c252STheodore Ts'o #endif 103f348c252STheodore Ts'o 104754661f1SArjan van de Ven const struct inode_operations ext4_symlink_inode_operations = { 105ac27a0ecSDave Kleikamp .readlink = generic_readlink, 1066b255391SAl Viro .get_link = page_get_link, 107256a4535SDmitry Monakhov .setattr = ext4_setattr, 108ac27a0ecSDave Kleikamp .setxattr = generic_setxattr, 109ac27a0ecSDave Kleikamp .getxattr = generic_getxattr, 110617ba13bSMingming Cao .listxattr = ext4_listxattr, 111ac27a0ecSDave Kleikamp .removexattr = generic_removexattr, 112ac27a0ecSDave Kleikamp }; 113ac27a0ecSDave Kleikamp 114754661f1SArjan van de Ven const struct inode_operations ext4_fast_symlink_inode_operations = { 115ac27a0ecSDave Kleikamp .readlink = generic_readlink, 1166b255391SAl Viro .get_link = simple_get_link, 117256a4535SDmitry Monakhov .setattr = ext4_setattr, 118ac27a0ecSDave Kleikamp .setxattr = generic_setxattr, 119ac27a0ecSDave Kleikamp .getxattr = generic_getxattr, 120617ba13bSMingming Cao .listxattr = ext4_listxattr, 121ac27a0ecSDave Kleikamp .removexattr = generic_removexattr, 122ac27a0ecSDave Kleikamp }; 123