1 /* 2 * linux/fs/ext4/symlink.c 3 * 4 * Only fast symlinks left here - the rest is done by generic code. AV, 1999 5 * 6 * Copyright (C) 1992, 1993, 1994, 1995 7 * Remy Card (card@masi.ibp.fr) 8 * Laboratoire MASI - Institut Blaise Pascal 9 * Universite Pierre et Marie Curie (Paris VI) 10 * 11 * from 12 * 13 * linux/fs/minix/symlink.c 14 * 15 * Copyright (C) 1991, 1992 Linus Torvalds 16 * 17 * ext4 symlink handling code 18 */ 19 20 #include <linux/fs.h> 21 #include <linux/namei.h> 22 #include "ext4.h" 23 #include "xattr.h" 24 25 #ifdef CONFIG_EXT4_FS_ENCRYPTION 26 static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd) 27 { 28 struct page *cpage = NULL; 29 char *caddr, *paddr = NULL; 30 struct ext4_str cstr, pstr; 31 struct inode *inode = d_inode(dentry); 32 struct ext4_fname_crypto_ctx *ctx = NULL; 33 struct ext4_encrypted_symlink_data *sd; 34 loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1); 35 int res; 36 u32 plen, max_size = inode->i_sb->s_blocksize; 37 38 if (!ext4_encrypted_inode(inode)) 39 return page_follow_link_light(dentry, nd); 40 41 ctx = ext4_get_fname_crypto_ctx(inode, inode->i_sb->s_blocksize); 42 if (IS_ERR(ctx)) 43 return ctx; 44 45 if (ext4_inode_is_fast_symlink(inode)) { 46 caddr = (char *) EXT4_I(inode)->i_data; 47 max_size = sizeof(EXT4_I(inode)->i_data); 48 } else { 49 cpage = read_mapping_page(inode->i_mapping, 0, NULL); 50 if (IS_ERR(cpage)) { 51 ext4_put_fname_crypto_ctx(&ctx); 52 return cpage; 53 } 54 caddr = kmap(cpage); 55 caddr[size] = 0; 56 } 57 58 /* Symlink is encrypted */ 59 sd = (struct ext4_encrypted_symlink_data *)caddr; 60 cstr.name = sd->encrypted_path; 61 cstr.len = le32_to_cpu(sd->len); 62 if ((cstr.len + 63 sizeof(struct ext4_encrypted_symlink_data) - 1) > 64 max_size) { 65 /* Symlink data on the disk is corrupted */ 66 res = -EIO; 67 goto errout; 68 } 69 plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ? 70 EXT4_FNAME_CRYPTO_DIGEST_SIZE*2 : cstr.len; 71 paddr = kmalloc(plen + 1, GFP_NOFS); 72 if (!paddr) { 73 res = -ENOMEM; 74 goto errout; 75 } 76 pstr.name = paddr; 77 res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr); 78 if (res < 0) 79 goto errout; 80 /* Null-terminate the name */ 81 if (res <= plen) 82 paddr[res] = '\0'; 83 nd_set_link(nd, paddr); 84 ext4_put_fname_crypto_ctx(&ctx); 85 if (cpage) { 86 kunmap(cpage); 87 page_cache_release(cpage); 88 } 89 return NULL; 90 errout: 91 ext4_put_fname_crypto_ctx(&ctx); 92 if (cpage) { 93 kunmap(cpage); 94 page_cache_release(cpage); 95 } 96 kfree(paddr); 97 return ERR_PTR(res); 98 } 99 100 static void ext4_put_link(struct dentry *dentry, struct nameidata *nd, 101 void *cookie) 102 { 103 struct page *page = cookie; 104 105 if (!page) { 106 kfree(nd_get_link(nd)); 107 } else { 108 kunmap(page); 109 page_cache_release(page); 110 } 111 } 112 #endif 113 114 static void *ext4_follow_fast_link(struct dentry *dentry, struct nameidata *nd) 115 { 116 struct ext4_inode_info *ei = EXT4_I(d_inode(dentry)); 117 nd_set_link(nd, (char *) ei->i_data); 118 return NULL; 119 } 120 121 const struct inode_operations ext4_symlink_inode_operations = { 122 .readlink = generic_readlink, 123 #ifdef CONFIG_EXT4_FS_ENCRYPTION 124 .follow_link = ext4_follow_link, 125 .put_link = ext4_put_link, 126 #else 127 .follow_link = page_follow_link_light, 128 .put_link = page_put_link, 129 #endif 130 .setattr = ext4_setattr, 131 .setxattr = generic_setxattr, 132 .getxattr = generic_getxattr, 133 .listxattr = ext4_listxattr, 134 .removexattr = generic_removexattr, 135 }; 136 137 const struct inode_operations ext4_fast_symlink_inode_operations = { 138 .readlink = generic_readlink, 139 .follow_link = ext4_follow_fast_link, 140 .setattr = ext4_setattr, 141 .setxattr = generic_setxattr, 142 .getxattr = generic_getxattr, 143 .listxattr = ext4_listxattr, 144 .removexattr = generic_removexattr, 145 }; 146