[libvirt] [PATCH 4/7] virfile: Adjust error path for virFileOpenForked

Eric Blake eblake at redhat.com
Thu Jan 29 20:27:57 UTC 2015


On 01/28/2015 03:25 PM, John Ferlan wrote:
> Rather than have a dummy waitpid loop and return of the failure status
> from recvfd, adjust the logic to save the recvfd error & fd and then
> in priority order:
> 
> if waitpid failed, use that
> if waitpid succeeded, but the child reported failure, use that
> regardless of recvfd status
> if waitpid succeeded and reported success, but recvfd failed with
> anything other than EACCES or ENOTCONN, use recvfd's result
> otherwise, waitpid and recvfd succeeded, return the fd
> 
> NOTE: Original logic to retry the open and force owner mode was
> "documented" as only being attempted if we had already tried opening
> with the fork+setuid, but checked flags vs. VIR_FILE_OPEN_NOFORK which
> is counter to how we would get to that point. So that code was removed.
> 
> Signed-off-by: John Ferlan <jferlan at redhat.com>
> ---
>  src/util/virfile.c | 67 +++++++++++++++++++++++++++++++-----------------------
>  1 file changed, 39 insertions(+), 28 deletions(-)
> 

> +    /*
> +     * if waitpid succeeded, but the child reported failure, use that
> +     * regardless of recvfd status
> +     */
> +    if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
> +        ret = WEXITSTATUS(status);
> +        virReportSystemError(ret,

waitpid reporting !WIFEXITED(status) is a case of the child reporting
failure (well, reporting abnormal exit due to signal), so it might
simplify things if we just do[1]:

if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {

except that then you have to distinguish between abnormal exit vs. exit
encoding a known errno value when constructing the error message.



> +
> +    /* if waitpid succeeded and reported success, but recvfd failed with
> +     * anything other than EACCES or ENOTCONN, use recvfd's result
> +     */
> +    if (WIFEXITED(status) && WEXITSTATUS(status) == 0 && fd < 0 &&
> +        !(recvfd_errno == EACCES || recvfd_errno == ENOTCONN)) {
> +        virReportSystemError(recvfd_errno,
> +                             _("failed recvfd for child creating '%s'"),
> +                             path);
> +        return -recvfd_errno;
> +    }

Hmm. It may be sufficient to just treat ALL recvfd failures as the exit
status if we get here, since if recvfd failed, then fd == -1...

> +
> +    /* Some sort of abnormal child termination */
> +    if (!WIFEXITED(status) || fd == -1) {
> +        VIR_FORCE_CLOSE(fd);
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("child exited abnormally, failed to create '%s'"),
> +                       path);
> +        return -EACCES;

...and we would be failing anyways, but losing the errno value from
recvfd.  And if you change point [1] above to catch abnormal exit, then
this entire if branch becomes dead.

So how about:

- if waitpid failed, use that errno value
- waitpid succeeded, but if the child exited abnormally, report failure
(not sure what errno value to use here)
- waitpid succeeded, but if the child reported non-zero status, report
failure (use the errno value that the child encoded into exit status)
- waitpid succeeded, but if recvfd failed, report recvfd_errno
- waitpid and recvfd succeeded, use the fd

Sorry for making you churn on this, given my first-round off-list
thoughts on the matter, but hopefully it turns out a little easier to read.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 604 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150129/14883fd4/attachment-0001.sig>


More information about the libvir-list mailing list