/** * nfs_copy_dname - copy dentry name to data structure * @dentry: pointer to dentry * @data: nfs_unlinkdata */ static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data) { char *str; int len = dentry->d_name.len; str = kmemdup(dentry->d_name.name, NAME_ALLOC_LEN(len), GFP_KERNEL); if (!str) return -ENOMEM; data->args.name.len = len; data->args.name.name = str; return 0; }
struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) { char * str; struct dentry *dentry; dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); if (!dentry) return NULL; if (name->len > DNAME_INLINE_LEN-1) { str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL); if (!str) { kmem_cache_free(dentry_cache, dentry); return NULL; } } else str = dentry->d_iname; memcpy(str, name->name, name->len); str[name->len] = 0; atomic_set(&dentry->d_count, 1); dentry->d_vfs_flags = 0; dentry->d_flags = 0; dentry->d_inode = NULL; dentry->d_parent = NULL; dentry->d_sb = NULL; dentry->d_name.name = str; dentry->d_name.len = name->len; dentry->d_name.hash = name->hash; dentry->d_op = NULL; dentry->d_fsdata = NULL; dentry->d_mounted = 0; INIT_LIST_HEAD(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); INIT_LIST_HEAD(&dentry->d_alias); if (parent) { dentry->d_parent = dget(parent); dentry->d_sb = parent->d_sb; spin_lock(&dcache_lock); list_add(&dentry->d_child, &parent->d_subdirs); spin_unlock(&dcache_lock); } else INIT_LIST_HEAD(&dentry->d_child); dentry_stat.nr_dentry++; return dentry; }
char * decrypt_filename(const char *c, const unsigned char *k, int kl) { struct crypto_blkcipher *tfm = 0; struct scatterlist sgi[1], sgo[1]; unsigned char *work; unsigned char ivec[16]; int outlen = 0, rlen; unsigned int sum1, sum2; char *ret = 0, *rp = 0; struct blkcipher_desc desc[1]; int rc; tfm = crypto_alloc_blkcipher(ALG, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { printk(KERN_ERR "decrypt_filename: crypto_alloc_blkcipher (%s) failed\n", ALG); ret = (void*)tfm; /* ERR_PTR(PTR_ERR(tfm)) */ tfm = 0; goto Done; } if (crypto_blkcipher_setkey(tfm, k, kl) < 0) { printk(KERN_ERR "decrypt_filename: crypto_blkcipher_setkey failed (bad key?)\n"); ret = ERR_PTR(-EIO); goto Done; } work = b92_decode(c, &outlen); if (!work || outlen < 5) { printk(KERN_ERR "decrypt_filename: bad filename %d/<%s> %d\n", (int)strlen(c), c, outlen); ret = ERR_PTR(-ENOMEM); goto Done; } if (!work) { printk(KERN_ERR "decrypt_filename: b92_decode failed!\n"); ret = ERR_PTR(-ENOMEM); goto Done; } memcpy(ivec, work, 4); memset(ivec+4, 0, sizeof ivec-5); ivec[sizeof ivec-1]=1; rlen = NAME_ALLOC_LEN(outlen-4); rp = kmalloc(rlen, GFP_KERNEL); if (!rp) { printk(KERN_ERR "decrypt_filename: can't allocate %d bytes\n", rlen-3); ret = ERR_PTR(-ENOMEM); goto Done; } rp[outlen-4] = 0; sg_init_table(sgi, 1); sg_init_table(sgo, 1); sg_set_buf(sgi, work+4, outlen-4); sg_set_buf(sgo, rp, outlen-4); memset(desc, 0, sizeof *desc); desc->info = ivec; desc->tfm = tfm; rc = crypto_blkcipher_encrypt_iv(desc, sgo, sgi, outlen-4); if (rc) { printk(KERN_ERR "decrypt_filename: encrypt failed code=%d\n", rc); ret = ERR_PTR(rc); goto Done; } sum1 = ~crc32_le(~0, rp, outlen-4); sum2 = (((unsigned int)work[0])<<24) | (((unsigned int)work[1])<<16) | (((unsigned int)work[2])<<8) | ((unsigned int)work[3]); if (sum1 != sum2) { printk(KERN_ERR "decrypt_filename: crc didn't match! (on %x) (got %x)\n", be32_to_cpu(sum1), be32_to_cpu(sum2)); ret = ERR_PTR(-EIO); goto Done; } ret = rp; rp = 0; Done: if (work) kfree(work); if (tfm) crypto_free_blkcipher(tfm); if (rp) kfree(rp); return ret; }