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 256b255391SAl Viro static const char *ext4_encrypted_get_link(struct dentry *dentry, 26fceef393SAl Viro struct inode *inode, 27fceef393SAl Viro struct delayed_call *done) 28ac27a0ecSDave Kleikamp { 29f348c252STheodore Ts'o struct page *cpage = NULL; 30f348c252STheodore Ts'o char *caddr, *paddr = NULL; 31a7550b30SJaegeuk Kim struct fscrypt_str cstr, pstr; 32a7550b30SJaegeuk Kim struct fscrypt_symlink_data *sd; 33f348c252STheodore Ts'o int res; 34a7550b30SJaegeuk Kim u32 max_size = inode->i_sb->s_blocksize; 35f348c252STheodore Ts'o 366b255391SAl Viro if (!dentry) 376b255391SAl Viro return ERR_PTR(-ECHILD); 386b255391SAl Viro 39a7550b30SJaegeuk Kim res = fscrypt_get_encryption_info(inode); 40b7236e21STheodore Ts'o if (res) 41b7236e21STheodore Ts'o return ERR_PTR(res); 42f348c252STheodore Ts'o 43f348c252STheodore Ts'o if (ext4_inode_is_fast_symlink(inode)) { 449ec3a646SLinus Torvalds caddr = (char *) EXT4_I(inode)->i_data; 459ec3a646SLinus Torvalds max_size = sizeof(EXT4_I(inode)->i_data); 46f348c252STheodore Ts'o } else { 47f348c252STheodore Ts'o cpage = read_mapping_page(inode->i_mapping, 0, NULL); 48b7236e21STheodore Ts'o if (IS_ERR(cpage)) 49680baacbSAl Viro return ERR_CAST(cpage); 5021fc61c7SAl Viro caddr = page_address(cpage); 51f348c252STheodore Ts'o } 52f348c252STheodore Ts'o 53f348c252STheodore Ts'o /* Symlink is encrypted */ 54a7550b30SJaegeuk Kim sd = (struct fscrypt_symlink_data *)caddr; 55f348c252STheodore Ts'o cstr.name = sd->encrypted_path; 565a1c7f47SAl Viro cstr.len = le16_to_cpu(sd->len); 57a7550b30SJaegeuk Kim if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) { 58f348c252STheodore Ts'o /* Symlink data on the disk is corrupted */ 596a797d27SDarrick J. Wong res = -EFSCORRUPTED; 60f348c252STheodore Ts'o goto errout; 61f348c252STheodore Ts'o } 62a7550b30SJaegeuk Kim 63a7550b30SJaegeuk Kim res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr); 64a7550b30SJaegeuk Kim if (res) 65f348c252STheodore Ts'o goto errout; 66dcce7a46SEric Biggers paddr = pstr.name; 67a7550b30SJaegeuk Kim 68a7550b30SJaegeuk Kim res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr); 69ef1eb3aaSEric Biggers if (res) 70f348c252STheodore Ts'o goto errout; 71a7550b30SJaegeuk Kim 72f348c252STheodore Ts'o /* Null-terminate the name */ 73ef1eb3aaSEric Biggers paddr[pstr.len] = '\0'; 7421fc61c7SAl Viro if (cpage) 7509cbfeafSKirill A. Shutemov put_page(cpage); 76fceef393SAl Viro set_delayed_call(done, kfree_link, paddr); 77fceef393SAl Viro return paddr; 78f348c252STheodore Ts'o errout: 7921fc61c7SAl Viro if (cpage) 8009cbfeafSKirill A. Shutemov put_page(cpage); 81f348c252STheodore Ts'o kfree(paddr); 82f348c252STheodore Ts'o return ERR_PTR(res); 83f348c252STheodore Ts'o } 84f348c252STheodore Ts'o 85a7a67e8aSAl Viro const struct inode_operations ext4_encrypted_symlink_inode_operations = { 866b255391SAl Viro .get_link = ext4_encrypted_get_link, 87a7a67e8aSAl Viro .setattr = ext4_setattr, 88*99652ea5SDavid Howells .getattr = ext4_getattr, 89a7a67e8aSAl Viro .listxattr = ext4_listxattr, 90a7a67e8aSAl Viro }; 91f348c252STheodore Ts'o 92754661f1SArjan van de Ven const struct inode_operations ext4_symlink_inode_operations = { 936b255391SAl Viro .get_link = page_get_link, 94256a4535SDmitry Monakhov .setattr = ext4_setattr, 95*99652ea5SDavid Howells .getattr = ext4_getattr, 96617ba13bSMingming Cao .listxattr = ext4_listxattr, 97ac27a0ecSDave Kleikamp }; 98ac27a0ecSDave Kleikamp 99754661f1SArjan van de Ven const struct inode_operations ext4_fast_symlink_inode_operations = { 1006b255391SAl Viro .get_link = simple_get_link, 101256a4535SDmitry Monakhov .setattr = ext4_setattr, 102*99652ea5SDavid Howells .getattr = ext4_getattr, 103617ba13bSMingming Cao .listxattr = ext4_listxattr, 104ac27a0ecSDave Kleikamp }; 105