Date: Mon, 5 May 2014 09:02:04 +0400 From: Chagin Dmitry <dchagin@freebsd.org> To: Mateusz Guzik <mjguzik@gmail.com> Cc: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: Re: svn commit: r265327 - in user/dchagin/lemul/sys: amd64/linux amd64/linux32 compat/linux conf i386/linux modules/linux modules/linux64 Message-ID: <20140505050204.GA1307@dchagin.static.corbina.net> In-Reply-To: <20140504180749.GA17835@dft-labs.eu> References: <201405041559.s44FxWdj053353@svn.freebsd.org> <20140504180749.GA17835@dft-labs.eu>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] On Sun, May 04, 2014 at 08:07:49PM +0200, Mateusz Guzik wrote: > On Sun, May 04, 2014 at 03:59:32PM +0000, Dmitry Chagin wrote: > > Author: dchagin > > Date: Sun May 4 15:59:32 2014 > > New Revision: 265327 > > URL: http://svnweb.freebsd.org/changeset/base/265327 > > > > Log: > > Implement epoll family system calls. This is a tiny wrapper around kqueue > > to implement epoll subset of functionality. The kqueue user data are > > 32bit on i386 which is not enough for epoll user data, so we keep user > > data in the proc emuldata. > > > > Initial patch developed by rdivacky in 2007, then extended by > > Yuri Victorovich @ r255672 and finished by me. > > > > I'm not happy with this. The code is full of fp <-> fd lookup races. > Hi, Mateusz. Thanks for the reply. As far as I understand you, check epfd against fd is useless. FreeBSD does not check that it's the same file.But we must. Is it correct?: diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c index ee70b9c..054df14 100644 --- a/sys/compat/linux/linux_event.c +++ b/sys/compat/linux/linux_event.c @@ -339,9 +339,6 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) int nchanges = 0; int error; - if (args->epfd == args->fd) - return (EINVAL); - if (args->op != LINUX_EPOLL_CTL_DEL) { error = copyin(args->event, &le, sizeof(le)); if (error != 0) @@ -359,6 +356,12 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) if (error != 0) goto leave1; + /* Linux disallows spying on himself */ + if (epfp == fp) { + error = EINVAL; + goto leave0; + } + ciargs.changelist = kev; switch (args->op) { > Example: > > linux_epoll_ctl > if (args->epfd == args->fd) > return (EINVAL); > [..] > error = fget(td, args->epfd, &rights, &epfp); > if (error != 0) > return (error); > > /* Protect user data vector from incorrectly supplied fd. */ > error = fget(td, args->fd, &rights, &fp); > if (error != 0) > goto leave1; > > fds could resolve to the same fp right from the start and even if that > was note done an attacker could arrange that after the check. > > There is no validation you got epoll fd either. > > Further down: > switch (args->op) { > case LINUX_EPOLL_CTL_MOD: > /* > * We don't memorize which events were set for this FD > * on this level, so just delete all we could have set: > * EVFILT_READ and EVFILT_WRITE, ignoring any errors > */ > error = epoll_delete_all_events(td, epfp, args->fd); > > Again a lookup. > > Whether this particular problem could be used to do something nasty I don't > know, but playing like this is asking for trouble. > > The only solution I see is to modify kqueue functions to accept fps. > reason? to prevent extra fget? or something else? -- Have fun! chd [-- Attachment #2 --] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEARECAAYFAlNnG0wACgkQ0t2Tb3OO/O2PuwCfauKJvtLm+crix2mZFef8JMxu 2bkAoL4pn6gZZwydAeVQlS/HLQef5bWV =EmRZ -----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140505050204.GA1307>
