/* Inspired by generic filldir in fs/readdir.c */ static int ecryptfs_filldir(void *dirent, const char *lower_name, int lower_namelen, loff_t offset, u64 ino, unsigned int d_type) { struct ecryptfs_getdents_callback *buf = (struct ecryptfs_getdents_callback *)dirent; size_t name_size; char *name; int rc; buf->filldir_called++; rc = ecryptfs_decode_and_decrypt_filename(&name, &name_size, buf->dentry, lower_name, lower_namelen); if (rc) { printk(KERN_ERR "%s: Error attempting to decode and decrypt " "filename [%s]; rc = [%d]\n", __func__, lower_name, rc); goto out; } rc = buf->filldir(buf->dirent, name, name_size, offset, ino, d_type); kfree(name); if (rc >= 0) buf->entries_written++; out: return rc; }
static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, size_t *bufsiz) { struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); char *lower_buf; size_t lower_bufsiz = PATH_MAX; mm_segment_t old_fs; int rc; lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); if (!lower_buf) { rc = -ENOMEM; goto out; } old_fs = get_fs(); set_fs(get_ds()); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, lower_bufsiz); set_fs(old_fs); if (rc < 0) goto out; lower_bufsiz = rc; rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry, lower_buf, lower_bufsiz); out: kfree(lower_buf); return rc; }
static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz) { struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); char *lower_buf; char *buf; mm_segment_t old_fs; int rc; lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); if (!lower_buf) return ERR_PTR(-ENOMEM); old_fs = get_fs(); set_fs(get_ds()); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, PATH_MAX); set_fs(old_fs); if (rc < 0) goto out; rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb, lower_buf, rc); out: kfree(lower_buf); return rc ? ERR_PTR(rc) : buf; }
static int ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { char *lower_buf; struct dentry *lower_dentry; struct ecryptfs_crypt_stat *crypt_stat; char *plaintext_name; size_t plaintext_name_size; mm_segment_t old_fs; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); if (!lower_dentry->d_inode->i_op->readlink) { rc = -EINVAL; goto out; } crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; /* Released in this function */ lower_buf = kmalloc(bufsiz, GFP_KERNEL); if (lower_buf == NULL) { printk(KERN_ERR "%s: Out of memory whilst attempting to " "kmalloc [%d] bytes\n", __func__, bufsiz); rc = -ENOMEM; goto out; } old_fs = get_fs(); set_fs(get_ds()); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, bufsiz); set_fs(old_fs); if (rc >= 0) { rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, &plaintext_name_size, dentry, lower_buf, rc); if (rc) { printk(KERN_ERR "%s: Error attempting to decode and " "decrypt filename; rc = [%d]\n", __func__, rc); goto out_free_lower_buf; } rc = copy_to_user(buf, plaintext_name, plaintext_name_size); if (rc) rc = -EFAULT; else rc = plaintext_name_size; kfree(plaintext_name); fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); } out_free_lower_buf: kfree(lower_buf); out: return rc; }
static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz) { DEFINE_DELAYED_CALL(done); struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); const char *link; char *buf; int rc; link = vfs_get_link(lower_dentry, &done); if (IS_ERR(link)) return ERR_CAST(link); rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb, link, strlen(link)); do_delayed_call(&done); if (rc) return ERR_PTR(rc); return buf; }
static int ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) { char *lower_buf; size_t lower_bufsiz; struct dentry *lower_dentry; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; char *plaintext_name; size_t plaintext_name_size; mm_segment_t old_fs; int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); if (!lower_dentry->d_inode->i_op->readlink) { rc = -EINVAL; goto out; } mount_crypt_stat = &ecryptfs_superblock_to_private( dentry->d_sb)->mount_crypt_stat; /* * If the lower filename is encrypted, it will result in a significantly * longer name. If needed, truncate the name after decode and decrypt. */ if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) lower_bufsiz = PATH_MAX; else lower_bufsiz = bufsiz; /* Released in this function */ lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); if (lower_buf == NULL) { printk(KERN_ERR "%s: Out of memory whilst attempting to " "kmalloc [%zd] bytes\n", __func__, lower_bufsiz); rc = -ENOMEM; goto out; } old_fs = get_fs(); set_fs(get_ds()); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, (char __user *)lower_buf, lower_bufsiz); set_fs(old_fs); if (rc >= 0) { rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name, &plaintext_name_size, dentry, lower_buf, rc); if (rc) { printk(KERN_ERR "%s: Error attempting to decode and " "decrypt filename; rc = [%d]\n", __func__, rc); goto out_free_lower_buf; } /* Check for bufsiz <= 0 done in sys_readlinkat() */ rc = copy_to_user(buf, plaintext_name, min((size_t) bufsiz, plaintext_name_size)); if (rc) rc = -EFAULT; else rc = plaintext_name_size; kfree(plaintext_name); fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); } out_free_lower_buf: kfree(lower_buf); out: return rc; }