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 26617ba13bSMingming Cao static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd) 27ac27a0ecSDave Kleikamp { 28f348c252STheodore Ts'o struct page *cpage = NULL; 29f348c252STheodore Ts'o char *caddr, *paddr = NULL; 30f348c252STheodore Ts'o struct ext4_str cstr, pstr; 319ec3a646SLinus Torvalds struct inode *inode = d_inode(dentry); 32f348c252STheodore Ts'o struct ext4_encrypted_symlink_data *sd; 33f348c252STheodore Ts'o loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1); 34f348c252STheodore Ts'o int res; 35f348c252STheodore Ts'o u32 plen, max_size = inode->i_sb->s_blocksize; 36f348c252STheodore Ts'o 37f348c252STheodore Ts'o if (!ext4_encrypted_inode(inode)) 38f348c252STheodore Ts'o return page_follow_link_light(dentry, nd); 39f348c252STheodore Ts'o 40*c936e1ecSTheodore Ts'o res = ext4_get_encryption_info(inode); 41b7236e21STheodore Ts'o if (res) 42b7236e21STheodore Ts'o return ERR_PTR(res); 43f348c252STheodore Ts'o 44f348c252STheodore Ts'o if (ext4_inode_is_fast_symlink(inode)) { 459ec3a646SLinus Torvalds caddr = (char *) EXT4_I(inode)->i_data; 469ec3a646SLinus Torvalds max_size = sizeof(EXT4_I(inode)->i_data); 47f348c252STheodore Ts'o } else { 48f348c252STheodore Ts'o cpage = read_mapping_page(inode->i_mapping, 0, NULL); 49b7236e21STheodore Ts'o if (IS_ERR(cpage)) 50f348c252STheodore Ts'o return cpage; 51f348c252STheodore Ts'o caddr = kmap(cpage); 52f348c252STheodore Ts'o caddr[size] = 0; 53f348c252STheodore Ts'o } 54f348c252STheodore Ts'o 55f348c252STheodore Ts'o /* Symlink is encrypted */ 56f348c252STheodore Ts'o sd = (struct ext4_encrypted_symlink_data *)caddr; 57f348c252STheodore Ts'o cstr.name = sd->encrypted_path; 58f348c252STheodore Ts'o cstr.len = le32_to_cpu(sd->len); 59f348c252STheodore Ts'o if ((cstr.len + 60f348c252STheodore Ts'o sizeof(struct ext4_encrypted_symlink_data) - 1) > 61f348c252STheodore Ts'o max_size) { 62f348c252STheodore Ts'o /* Symlink data on the disk is corrupted */ 63f348c252STheodore Ts'o res = -EIO; 64f348c252STheodore Ts'o goto errout; 65f348c252STheodore Ts'o } 66f348c252STheodore Ts'o plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ? 67f348c252STheodore Ts'o EXT4_FNAME_CRYPTO_DIGEST_SIZE*2 : cstr.len; 68f348c252STheodore Ts'o paddr = kmalloc(plen + 1, GFP_NOFS); 69f348c252STheodore Ts'o if (!paddr) { 70f348c252STheodore Ts'o res = -ENOMEM; 71f348c252STheodore Ts'o goto errout; 72f348c252STheodore Ts'o } 73f348c252STheodore Ts'o pstr.name = paddr; 74d2299590STheodore Ts'o pstr.len = plen; 75b7236e21STheodore Ts'o res = _ext4_fname_disk_to_usr(inode, NULL, &cstr, &pstr); 76f348c252STheodore Ts'o if (res < 0) 77f348c252STheodore Ts'o goto errout; 78f348c252STheodore Ts'o /* Null-terminate the name */ 79f348c252STheodore Ts'o if (res <= plen) 80f348c252STheodore Ts'o paddr[res] = '\0'; 81f348c252STheodore Ts'o nd_set_link(nd, paddr); 82f348c252STheodore Ts'o if (cpage) { 83f348c252STheodore Ts'o kunmap(cpage); 84f348c252STheodore Ts'o page_cache_release(cpage); 85f348c252STheodore Ts'o } 86f348c252STheodore Ts'o return NULL; 87f348c252STheodore Ts'o errout: 88f348c252STheodore Ts'o if (cpage) { 89f348c252STheodore Ts'o kunmap(cpage); 90f348c252STheodore Ts'o page_cache_release(cpage); 91f348c252STheodore Ts'o } 92f348c252STheodore Ts'o kfree(paddr); 93f348c252STheodore Ts'o return ERR_PTR(res); 94f348c252STheodore Ts'o } 95f348c252STheodore Ts'o 96f348c252STheodore Ts'o static void ext4_put_link(struct dentry *dentry, struct nameidata *nd, 97f348c252STheodore Ts'o void *cookie) 98f348c252STheodore Ts'o { 99f348c252STheodore Ts'o struct page *page = cookie; 100f348c252STheodore Ts'o 101f348c252STheodore Ts'o if (!page) { 102f348c252STheodore Ts'o kfree(nd_get_link(nd)); 103f348c252STheodore Ts'o } else { 104f348c252STheodore Ts'o kunmap(page); 105f348c252STheodore Ts'o page_cache_release(page); 106f348c252STheodore Ts'o } 107f348c252STheodore Ts'o } 108f348c252STheodore Ts'o #endif 109f348c252STheodore Ts'o 110f348c252STheodore Ts'o static void *ext4_follow_fast_link(struct dentry *dentry, struct nameidata *nd) 111f348c252STheodore Ts'o { 1122b0143b5SDavid Howells struct ext4_inode_info *ei = EXT4_I(d_inode(dentry)); 113ac27a0ecSDave Kleikamp nd_set_link(nd, (char *) ei->i_data); 114ac27a0ecSDave Kleikamp return NULL; 115ac27a0ecSDave Kleikamp } 116ac27a0ecSDave Kleikamp 117754661f1SArjan van de Ven const struct inode_operations ext4_symlink_inode_operations = { 118ac27a0ecSDave Kleikamp .readlink = generic_readlink, 119f348c252STheodore Ts'o #ifdef CONFIG_EXT4_FS_ENCRYPTION 120f348c252STheodore Ts'o .follow_link = ext4_follow_link, 121f348c252STheodore Ts'o .put_link = ext4_put_link, 122f348c252STheodore Ts'o #else 123ac27a0ecSDave Kleikamp .follow_link = page_follow_link_light, 124ac27a0ecSDave Kleikamp .put_link = page_put_link, 125f348c252STheodore Ts'o #endif 126256a4535SDmitry Monakhov .setattr = ext4_setattr, 127ac27a0ecSDave Kleikamp .setxattr = generic_setxattr, 128ac27a0ecSDave Kleikamp .getxattr = generic_getxattr, 129617ba13bSMingming Cao .listxattr = ext4_listxattr, 130ac27a0ecSDave Kleikamp .removexattr = generic_removexattr, 131ac27a0ecSDave Kleikamp }; 132ac27a0ecSDave Kleikamp 133754661f1SArjan van de Ven const struct inode_operations ext4_fast_symlink_inode_operations = { 134ac27a0ecSDave Kleikamp .readlink = generic_readlink, 135f348c252STheodore Ts'o .follow_link = ext4_follow_fast_link, 136256a4535SDmitry Monakhov .setattr = ext4_setattr, 137ac27a0ecSDave Kleikamp .setxattr = generic_setxattr, 138ac27a0ecSDave Kleikamp .getxattr = generic_getxattr, 139617ba13bSMingming Cao .listxattr = ext4_listxattr, 140ac27a0ecSDave Kleikamp .removexattr = generic_removexattr, 141ac27a0ecSDave Kleikamp }; 142