[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: luajit fdopen luaposix
- From: Mike Belopuhov <mike.belopuhov@...>
- Date: Thu, 26 Nov 2015 11:44:44 +0100
On Wed, Nov 25, 2015 at 15:52 -0800, William Ahern wrote:
> On Wed, Nov 25, 2015 at 12:54:25PM +0100, Mike Belopuhov wrote:
> > Hi,
> >
> > As many of you have most probably stumbled upon the problem with fdopen
> > from the luaposix package on luajit and some of you have most probably
> > solved it one way or another, I'd like to post my solution to this problem
> > just for the purpose of archiving it and hopefully helping others.
> >
> > But first a bit of a disclaimer: I do not consider myself an experienced
> > Lua programmer and perhaps there are better solutions to this problem (-;
> >
> > local stdio = require("posix.stdio")
> > local unistd = require("posix.unistd")
> >
> > function mikes_fdopen(fd)
> > local fh, rv
> >
> > fh = io.tmpfile()
> > if (not fh) then
> > return nil
> > end
> > fh:flush()
> > rv = unistd.dup2(fd, stdio.fileno(fh))
> > if (not rv) then
> > fh:close()
> > return nil
> > end
> > unistd.close(fd)
> > return fh
> > end
> <snip>
> > I'm open to any public criticism or a public discussion regarding this.
> > Let me also say sorry in advance if this has already been presented
> > before, that would just mean that my google-fu wasn't strong enough.
>
> Several people have come up with similar solutions, but I don't think that
> fact reflects poorly on your google-fu. ;)
>
> Some comments:
>
> 1) POSIX fdopen takes a mode argument. You're only partially implementing
> the interface by dup'ing the descriptor over the pre-existing descriptor.
>
> 2) In jailed environments there may be no /tmp or even any writable
> directories at all.
>
All good points, indeed.
> The solution I arrived at in my own C-based Unix bindings module[1] is here
>
> https://github.com/wahern/lunix/blob/tag-20150923/src/unix.c#L3642
>
Thanks for the link. Building a C module is something we wanted to
avoid for now. The other solution is obviously Foreign Function
Interface, however this is not portable to PUC-Rio Lua, and portability
was a primary objective for us.
> It attempts to open "." or "/dev/null" to get a blessed LuaJIT object using
> io.open. Visibility or read permissions aren't guaranteed, but more likely
> to work in a jailed environment. Then it replaces that FILE handle
> completely with a newly fdopen'd handle rather than dup'ing over the
> descriptor.
>
On our platform (OpenBSD) opening directories read-write (with open(2),
fopen(3) or io.open for that matter) doesn't work and generally speaking
would be a wrong thing to do anyways since there's no specified interface
for modifying directory entries via the write(2) system call. "/dev/null"
is also generally not available in [proper] chroot environments, however
it can be created manually of course.
> [1] lunix is thread-safe[2], provides common extensions not defined by POSIX
> (with custom implementations if needed to make them "portable"), and is
> regularly tested on many non-Linux platforms--AIX, OS X, Solaris, and
> several different BSDs.
>
> [2] At least as much as possible. The LuaJIT hack, for example, doesn't
> permit properly emulating the "x" (O_CLOEXEC) flag to fdopen, which could
> allow the temporary descriptor to be unintentionally inherited if another
> thread calls forks at the same time. Although I just realized that LuaJIT
> doesn't appear to check the contents of mode, so I should probably try to
> pass it through. (And maybe also add a runtime check to see if the x flag is
> supported by libc.)
>
The lack of explicit CLOEXEC handling can be circumvented by calling
posix.fcntl with a F_SETFD and FD_CLOEXEC. This is a POSIX interface:
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html
and is implemented by luaposix since Jul 4, 2015.