diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-12 20:04:37 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-12 20:04:37 -0500 |
commit | 66cb76666d69502fe982990b2cff5b6d607fd3b1 (patch) | |
tree | eac005b64fc6e78105d77ad4e9950cb647bccdb6 /fs/ecryptfs/main.c | |
parent | d61dcce2977d9abe855a5fe3570a81242209c23b (diff) |
sanitize ecryptfs ->mount()
kill ecryptfs_read_super(), reorder code allowing to use
normal d_alloc_root() instead of opencoding it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ecryptfs/main.c')
-rw-r--r-- | fs/ecryptfs/main.c | 155 |
1 files changed, 68 insertions, 87 deletions
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 351038675376..9ed476906327 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -141,21 +141,9 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | |||
141 | return rc; | 141 | return rc; |
142 | } | 142 | } |
143 | 143 | ||
144 | /** | 144 | static inode *ecryptfs_get_inode(struct inode *lower_inode, |
145 | * ecryptfs_interpose | 145 | struct super_block *sb) |
146 | * @lower_dentry: Existing dentry in the lower filesystem | ||
147 | * @dentry: ecryptfs' dentry | ||
148 | * @sb: ecryptfs's super_block | ||
149 | * @flags: flags to govern behavior of interpose procedure | ||
150 | * | ||
151 | * Interposes upper and lower dentries. | ||
152 | * | ||
153 | * Returns zero on success; non-zero otherwise | ||
154 | */ | ||
155 | int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, | ||
156 | struct super_block *sb, u32 flags) | ||
157 | { | 146 | { |
158 | struct inode *lower_inode; | ||
159 | struct inode *inode; | 147 | struct inode *inode; |
160 | int rc = 0; | 148 | int rc = 0; |
161 | 149 | ||
@@ -189,17 +177,38 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, | |||
189 | if (special_file(lower_inode->i_mode)) | 177 | if (special_file(lower_inode->i_mode)) |
190 | init_special_inode(inode, lower_inode->i_mode, | 178 | init_special_inode(inode, lower_inode->i_mode, |
191 | lower_inode->i_rdev); | 179 | lower_inode->i_rdev); |
192 | d_set_d_op(dentry, &ecryptfs_dops); | ||
193 | fsstack_copy_attr_all(inode, lower_inode); | 180 | fsstack_copy_attr_all(inode, lower_inode); |
194 | /* This size will be overwritten for real files w/ headers and | 181 | /* This size will be overwritten for real files w/ headers and |
195 | * other metadata */ | 182 | * other metadata */ |
196 | fsstack_copy_inode_size(inode, lower_inode); | 183 | fsstack_copy_inode_size(inode, lower_inode); |
184 | return inode; | ||
185 | out: | ||
186 | return ERR_PTR(rc); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * ecryptfs_interpose | ||
191 | * @lower_dentry: Existing dentry in the lower filesystem | ||
192 | * @dentry: ecryptfs' dentry | ||
193 | * @sb: ecryptfs's super_block | ||
194 | * @flags: flags to govern behavior of interpose procedure | ||
195 | * | ||
196 | * Interposes upper and lower dentries. | ||
197 | * | ||
198 | * Returns zero on success; non-zero otherwise | ||
199 | */ | ||
200 | int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry, | ||
201 | struct super_block *sb, u32 flags) | ||
202 | { | ||
203 | struct inode *lower_inode = lower_dentry->d_inode; | ||
204 | struct inode *inode = ecryptfs_get_inode(lower_inode, sb); | ||
205 | if (IS_ERR(inode) | ||
206 | return PTR_ERR(inode); | ||
197 | if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD) | 207 | if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD) |
198 | d_add(dentry, inode); | 208 | d_add(dentry, inode); |
199 | else | 209 | else |
200 | d_instantiate(dentry, inode); | 210 | d_instantiate(dentry, inode); |
201 | out: | 211 | return 0; |
202 | return rc; | ||
203 | } | 212 | } |
204 | 213 | ||
205 | enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, | 214 | enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, |
@@ -492,59 +501,11 @@ struct kmem_cache *ecryptfs_sb_info_cache; | |||
492 | static struct file_system_type ecryptfs_fs_type; | 501 | static struct file_system_type ecryptfs_fs_type; |
493 | 502 | ||
494 | /** | 503 | /** |
495 | * ecryptfs_read_super | ||
496 | * @sb: The ecryptfs super block | ||
497 | * @dev_name: The path to mount over | ||
498 | * | ||
499 | * Read the super block of the lower filesystem, and use | ||
500 | * ecryptfs_interpose to create our initial inode and super block | ||
501 | * struct. | ||
502 | */ | ||
503 | static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) | ||
504 | { | ||
505 | struct path path; | ||
506 | int rc; | ||
507 | |||
508 | rc = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); | ||
509 | if (rc) { | ||
510 | ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n"); | ||
511 | goto out; | ||
512 | } | ||
513 | if (path.dentry->d_sb->s_type == &ecryptfs_fs_type) { | ||
514 | rc = -EINVAL; | ||
515 | printk(KERN_ERR "Mount on filesystem of type " | ||
516 | "eCryptfs explicitly disallowed due to " | ||
517 | "known incompatibilities\n"); | ||
518 | goto out_free; | ||
519 | } | ||
520 | ecryptfs_set_superblock_lower(sb, path.dentry->d_sb); | ||
521 | sb->s_maxbytes = path.dentry->d_sb->s_maxbytes; | ||
522 | sb->s_blocksize = path.dentry->d_sb->s_blocksize; | ||
523 | ecryptfs_set_dentry_lower(sb->s_root, path.dentry); | ||
524 | ecryptfs_set_dentry_lower_mnt(sb->s_root, path.mnt); | ||
525 | rc = ecryptfs_interpose(path.dentry, sb->s_root, sb, 0); | ||
526 | if (rc) | ||
527 | goto out_free; | ||
528 | rc = 0; | ||
529 | goto out; | ||
530 | out_free: | ||
531 | path_put(&path); | ||
532 | out: | ||
533 | return rc; | ||
534 | } | ||
535 | |||
536 | /** | ||
537 | * ecryptfs_get_sb | 504 | * ecryptfs_get_sb |
538 | * @fs_type | 505 | * @fs_type |
539 | * @flags | 506 | * @flags |
540 | * @dev_name: The path to mount over | 507 | * @dev_name: The path to mount over |
541 | * @raw_data: The options passed into the kernel | 508 | * @raw_data: The options passed into the kernel |
542 | * | ||
543 | * The whole ecryptfs_get_sb process is broken into 3 functions: | ||
544 | * ecryptfs_parse_options(): handle options passed to ecryptfs, if any | ||
545 | * ecryptfs_read_super(): this accesses the lower filesystem and uses | ||
546 | * ecryptfs_interpose to perform most of the linking | ||
547 | * ecryptfs_interpose(): links the lower filesystem into ecryptfs (inode.c) | ||
548 | */ | 509 | */ |
549 | static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags, | 510 | static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags, |
550 | const char *dev_name, void *raw_data) | 511 | const char *dev_name, void *raw_data) |
@@ -553,6 +514,8 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags | |||
553 | struct ecryptfs_sb_info *sbi; | 514 | struct ecryptfs_sb_info *sbi; |
554 | struct ecryptfs_dentry_info *root_info; | 515 | struct ecryptfs_dentry_info *root_info; |
555 | const char *err = "Getting sb failed"; | 516 | const char *err = "Getting sb failed"; |
517 | struct inode *inode; | ||
518 | struct path path; | ||
556 | int rc; | 519 | int rc; |
557 | 520 | ||
558 | sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL); | 521 | sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL); |
@@ -575,10 +538,8 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags | |||
575 | 538 | ||
576 | s->s_flags = flags; | 539 | s->s_flags = flags; |
577 | rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); | 540 | rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); |
578 | if (rc) { | 541 | if (rc) |
579 | deactivate_locked_super(s); | 542 | goto out1; |
580 | goto out; | ||
581 | } | ||
582 | 543 | ||
583 | ecryptfs_set_superblock_private(s, sbi); | 544 | ecryptfs_set_superblock_private(s, sbi); |
584 | s->s_bdi = &sbi->bdi; | 545 | s->s_bdi = &sbi->bdi; |
@@ -586,34 +547,54 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags | |||
586 | /* ->kill_sb() will take care of sbi after that point */ | 547 | /* ->kill_sb() will take care of sbi after that point */ |
587 | sbi = NULL; | 548 | sbi = NULL; |
588 | s->s_op = &ecryptfs_sops; | 549 | s->s_op = &ecryptfs_sops; |
550 | s->s_d_op = &ecryptfs_dops; | ||
589 | 551 | ||
590 | rc = -ENOMEM; | 552 | err = "Reading sb failed"; |
591 | s->s_root = d_alloc(NULL, &(const struct qstr) { | 553 | rc = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); |
592 | .hash = 0,.name = "/",.len = 1}); | 554 | if (rc) { |
555 | ecryptfs_printk(KERN_WARNING, "kern_path() failed\n"); | ||
556 | goto out1; | ||
557 | } | ||
558 | if (path.dentry->d_sb->s_type == &ecryptfs_fs_type) { | ||
559 | rc = -EINVAL; | ||
560 | printk(KERN_ERR "Mount on filesystem of type " | ||
561 | "eCryptfs explicitly disallowed due to " | ||
562 | "known incompatibilities\n"); | ||
563 | goto out_free; | ||
564 | } | ||
565 | ecryptfs_set_superblock_lower(s, path.dentry->d_sb); | ||
566 | s->s_maxbytes = path.dentry->d_sb->s_maxbytes; | ||
567 | s->s_blocksize = path.dentry->d_sb->s_blocksize; | ||
568 | |||
569 | inode = ecryptfs_get_inode(path.dentry->d_inode, s); | ||
570 | rc = PTR_ERR(inode); | ||
571 | if (IS_ERR(inode)) | ||
572 | goto out_free; | ||
573 | |||
574 | s->s_root = d_alloc_root(inode); | ||
593 | if (!s->s_root) { | 575 | if (!s->s_root) { |
594 | deactivate_locked_super(s); | 576 | iput(inode); |
595 | goto out; | 577 | rc = -ENOMEM; |
578 | goto out_free; | ||
596 | } | 579 | } |
597 | d_set_d_op(s->s_root, &ecryptfs_dops); | ||
598 | s->s_root->d_sb = s; | ||
599 | s->s_root->d_parent = s->s_root; | ||
600 | 580 | ||
581 | rc = -ENOMEM; | ||
601 | root_info = kmem_cache_zalloc(ecryptfs_dentry_info_cache, GFP_KERNEL); | 582 | root_info = kmem_cache_zalloc(ecryptfs_dentry_info_cache, GFP_KERNEL); |
602 | if (!root_info) { | 583 | if (!root_info) |
603 | deactivate_locked_super(s); | 584 | goto out_free; |
604 | goto out; | 585 | |
605 | } | ||
606 | /* ->kill_sb() will take care of root_info */ | 586 | /* ->kill_sb() will take care of root_info */ |
607 | ecryptfs_set_dentry_private(s->s_root, root_info); | 587 | ecryptfs_set_dentry_private(s->s_root, root_info); |
588 | ecryptfs_set_dentry_lower(s->s_root, path.dentry); | ||
589 | ecryptfs_set_dentry_lower_mnt(s->s_root, path.mnt); | ||
590 | |||
608 | s->s_flags |= MS_ACTIVE; | 591 | s->s_flags |= MS_ACTIVE; |
609 | rc = ecryptfs_read_super(s, dev_name); | ||
610 | if (rc) { | ||
611 | deactivate_locked_super(s); | ||
612 | err = "Reading sb failed"; | ||
613 | goto out; | ||
614 | } | ||
615 | return dget(s->s_root); | 592 | return dget(s->s_root); |
616 | 593 | ||
594 | out_free: | ||
595 | path_put(&path); | ||
596 | out1: | ||
597 | deactivate_locked_super(s); | ||
617 | out: | 598 | out: |
618 | if (sbi) { | 599 | if (sbi) { |
619 | ecryptfs_destroy_mount_crypt_stat(&sbi->mount_crypt_stat); | 600 | ecryptfs_destroy_mount_crypt_stat(&sbi->mount_crypt_stat); |