Source-Changes-HG archive

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

[src/trunk]: src/lib/librumpclient The following happens when sending mail wi...



details:   https://anonhg.NetBSD.org/src/rev/fcd1c1ba1dde
branches:  trunk
changeset: 761857:fcd1c1ba1dde
user:      pooka <pooka%NetBSD.org@localhost>
date:      Wed Feb 09 14:29:58 2011 +0000

description:
The following happens when sending mail with mutt via a rump
TCP/IP stack:

* mutt prepares to exec the smtp client: it forks and closes all
  file descriptors
* when the next networking syscall is done, rumpclient detects that
  the communication fd returned EBADF and does a reconnect,
  gets descriptor 0 for the socket and descriptor 1 for kqueue
* mutt opens the mail file and implicitly assumes it'll get 0-2,
  but in fact gets 2-4
* mutt execs the smtp agent which tries to read the mail from
  stdin (rumpclient communication socket) and fails

Even if mutt correctly did dup2() things would go south when trying
to communicate with the kernel server the next time, since rumpclient
would actually be talking with some mail body instead (well, it
could work, but in that case you'd need to write *really* weird
mails ;).

Hence, prevent rumpclient from using the special fd's 0-2 for its
purposes.

Should fix mutt problem reported by Alexander Nasonov.

diffstat:

 lib/librumpclient/rumpclient.c |  28 +++++++++++++++++++++++++---
 1 files changed, 25 insertions(+), 3 deletions(-)

diffs (70 lines):

diff -r 8effe6250b95 -r fcd1c1ba1dde lib/librumpclient/rumpclient.c
--- a/lib/librumpclient/rumpclient.c    Wed Feb 09 14:13:09 2011 +0000
+++ b/lib/librumpclient/rumpclient.c    Wed Feb 09 14:29:58 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpclient.c,v 1.26 2011/02/07 15:25:41 pooka Exp $   */
+/*      $NetBSD: rumpclient.c,v 1.27 2011/02/09 14:29:58 pooka Exp $   */
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -68,6 +68,7 @@
 ssize_t (*host_sendto)(int, const void *, size_t, int,
                       const struct sockaddr *, socklen_t);
 int    (*host_setsockopt)(int, int, int, const void *, socklen_t);
+int    (*host_dup)(int);
 
 int    (*host_kqueue)(void);
 int    (*host_kevent)(int, const struct kevent *, size_t,
@@ -543,6 +544,26 @@
 static unsigned ptab_idx;
 static struct sockaddr *serv_sa;
 
+/* dup until we get a "good" fd which does not collide with stdio */
+static int
+dupgood(int myfd)
+{
+       int ofds[3];
+       int i;
+
+       for (i = 0; myfd <= 2 && myfd != -1; i++) {
+               assert(i < __arraycount(ofds));
+               ofds[i] = myfd;
+               myfd = host_dup(myfd);
+       }
+
+       for (i--; i >= 0; i--) {
+               host_close(ofds[i]);
+       }
+
+       return myfd;
+}
+
 static int
 doconnect(bool noisy)
 {
@@ -590,7 +611,7 @@
        free(clispc.spc_buf);
        clispc.spc_off = 0;
 
-       s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0);
+       s = dupgood(host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0));
        if (s == -1)
                return -1;
 
@@ -645,7 +666,7 @@
        clispc.spc_reconnecting = 0;
 
        /* setup kqueue, we want all signals and the fd */
-       if ((kq = host_kqueue()) == -1) {
+       if ((kq = dupgood(host_kqueue())) == -1) {
                error = errno;
                if (noisy)
                        fprintf(stderr, "rump_sp: cannot setup kqueue");
@@ -711,6 +732,7 @@
        FINDSYM(read);
        FINDSYM(sendto);
        FINDSYM(setsockopt);
+       FINDSYM(dup);
        FINDSYM(kqueue);
 #if !__NetBSD_Prereq__(5,99,7)
        FINDSYM(kevent);



Home | Main Index | Thread Index | Old Index