Re: [heads-up] binderfs bugs galore...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 17, 2019 at 10:40:11PM +0000, Al Viro wrote:
<snip>

Thanks for all the comments they seem really helpful. I'm currently
travelling but I will try to address them all within the next week! Does
that sound ok to you?

Thanks!
Christian

> 	1) d_make_root() does iput() on failure.  IOW, if you hit that case,
> you get double iput() in err_without_dentry.
> 
> 	2) final dput() does iput() (unsurprisingly).  IOW, anyone hitting
> err_with_dentry will get double iput() as well.
> 
> 	3) iput(NULL) is (fortunately) a no-op.  And that is the only case
> when iput() in there does not cause immediate trouble.
> 
> 	4) failure in binderfs_fill_super() leads to a call of
> deactivate_locked_super().  Which calls binderfs_kill_super(),
> which does put_ipc_ns(info->ipc_ns).  IOW,
>         put_ipc_ns(ipc_ns);
> in failure exits of binderfs_fill_super() is also a double-put...
> 
> 	5) ... if, that is, the memory that used to hold sb->s_fs_info
> until the same failure exit has kfreed it has already been stomped onto,
> in which case you get put_ipc_ns() done on arbitrary address that might've
> never held a struct ipc_namespace instance.
> 
> 	What I really don't get here is why do you go to such contortions
> in the first place.  Every single thing done in err_without_dentry is wrong.
> And the only thing done in err_with_dentry before it hits err_without_dentry
> is pointless; deactivate_locked_super() will do that dput() just fine.
> Whereas the simple return ret; (or return -ENOMEM in most of the cases)
> would've worked correctly...
> 
> 	Actually, looking at that a bit more,
> 	6) initially you have ->s_fs_info contain a pointer to
> struct ipc_namespace.  Then binderfs_fill_super() tries to allocate
> a struct binderfs_info instance and stick *that* in place of
> ->s_fs_info, moving the original value into info->ipc_ns.  That's
> Not Nice(tm) towards the poor binderfs_kill_super(), which has no
> fscking way to tell which kind of pointer is it going to find
> there.  As it is, it assumes that replacement has been done and
> drops ->ipc_ns it finds in there.  Guess what happens if you
> fail on attempt to allocate struct binderfs_info in the first
> place?
> 
> 	7) binderfs_test_super() also assumes that all superblocks it
> is asked to look at will have ->s_fs_info pointing to struct binderfs_info.
> binderfs_set_super(), OTOH, sets it to struct ipc_namespace pointer it
> (ultimately - sget_userns()) has been passed as 'data'.  So if two mounts
> race, you'll get a false negative out of binderfs_test_super().
> 
> 	8) binderfs_binder_ctl_create() is a no-op on subsequent
> calls (if there had been any).  And the first call is done before
> we unlock the superblock, so locking the root is completely pointless.
> 
> 	9) the one thing ->s_fs_info can't be in the whole thing is NULL.
> There are two assignments - one in binderfs_set_super(), where we set
> it to the last argument of sget_userns() and another in binderfs_fill_super()
> where we set it to 'info'.  In both cases we have that pointer dereferenced
> a little bit earlier - while evaluating the next-to-last argument of the
> same sget_userns() call or in setting info->root_uid in the other place.
> Both would've obviously oopsed before storing NULL there.  IOW, checking
> whether it's NULL is pointless both in binderfs_test_super() and in
> binderfs_kill_super().
> 
> 	10) your ->unlink() checks if the victim is ->control_dentry.
> Your ->rename(), OTOH, does not, which renders the check in ->unlink()
> trivial to bypass.
> 
> 	11) speaking of the tests that are there in ->rename(),
>         /* binderfs doesn't support directories. */
>         if (d_is_dir(old_dentry))
>                 return -EPERM;
> is... interesting.  If the comment is correct, the check is pointless.
> And AFAICS the comment *is* correct...  Another check in there
>         if (!simple_empty(new_dentry))
>                 return -ENOTEMPTY;
> is equally pointless, for the same reason...
> 
> 	12) what is the comment in binderfs_unlink() supposed to mean?
> In ->unlink() we *already* have parent locked...



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux