]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
privsep: IO should specify the context
authorVincent Bernat <bernat@luffy.cx>
Fri, 13 Dec 2013 21:48:41 +0000 (22:48 +0100)
committerVincent Bernat <bernat@luffy.cx>
Tue, 31 Dec 2013 14:17:34 +0000 (15:17 +0100)
Currently, the context is not needed because IO is always done to the
"remote" process. If we remove privilege separation, the remote process
is ourselves and we need to know which file descriptor to use.

src/daemon/lldpd.h
src/daemon/priv-linux.c
src/daemon/priv.c
src/daemon/privsep_io.c

index e37528b4e0fa1b4d6ca874a70fcb4de748de68d7..40b12bebe22f648e0dd5a67e6843687399e5470f 100644 (file)
@@ -245,12 +245,17 @@ int priv_seccomp_init(int, int);
 #endif
 
 /* privsep_io.c */
-int     may_read(void *, size_t);
-void    must_read(void *, size_t);
-void    must_write(const void *, size_t);
-void    priv_remote(int);
-int     receive_fd(void);
-void    send_fd(int);
+enum priv_context {
+       PRIV_PRIVILEGED,
+       PRIV_UNPRIVILEGED
+};
+int     may_read(enum priv_context, void *, size_t);
+void    must_read(enum priv_context, void *, size_t);
+void    must_write(enum priv_context, const void *, size_t);
+void    priv_privileged_fd(int);
+void    priv_unprivileged_fd(int);
+int     receive_fd(enum priv_context);
+void    send_fd(enum priv_context, int);
 
 /* interfaces-*.c */
 
index d17ec3885b86d8c86f7781c4111940be527a0c8d..0fbeebad832067de0670cc1d84ab8dcb7946b360 100644 (file)
@@ -35,14 +35,14 @@ priv_open(char *file)
 {
        int len, rc;
        enum priv_cmd cmd = PRIV_OPEN;
-       must_write(&cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
        len = strlen(file);
-       must_write(&len, sizeof(int));
-       must_write(file, len + 1);
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, file, len + 1);
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        if (rc == -1)
                return rc;
-       return receive_fd();
+       return receive_fd(PRIV_UNPRIVILEGED);
 }
 
 /* Proxy for ethtool ioctl */
@@ -51,14 +51,14 @@ priv_ethtool(char *ifname, void *ethc, size_t length)
 {
        int rc, len;
        enum priv_cmd cmd = PRIV_ETHTOOL;
-       must_write(&cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
        len = strlen(ifname);
-       must_write(&len, sizeof(int));
-       must_write(ifname, len + 1);
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, ifname, len + 1);
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        if (rc != 0)
                return rc;
-       must_read(ethc, length);
+       must_read(PRIV_UNPRIVILEGED, ethc, length);
        return rc;
 }
 
@@ -85,10 +85,10 @@ asroot_open()
        int fd, len, rc;
        regex_t preg;
 
-       must_read(&len, sizeof(len));
+       must_read(PRIV_PRIVILEGED, &len, sizeof(len));
        if ((file = (char *)malloc(len + 1)) == NULL)
                fatal("privsep", NULL);
-       must_read(file, len);
+       must_read(PRIV_PRIVILEGED, file, len);
        file[len] = '\0';
 
        for (f=authorized; *f != NULL; f++) {
@@ -104,19 +104,19 @@ asroot_open()
        if (*f == NULL) {
                log_warnx("privsep", "not authorized to open %s", file);
                rc = -1;
-               must_write(&rc, sizeof(int));
+               must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
                free(file);
                return;
        }
        if ((fd = open(file, O_RDONLY)) == -1) {
                rc = -1;
-               must_write(&rc, sizeof(int));
+               must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
                free(file);
                return;
        }
        free(file);
-       must_write(&fd, sizeof(int));
-       send_fd(fd);
+       must_write(PRIV_PRIVILEGED, &fd, sizeof(int));
+       send_fd(PRIV_PRIVILEGED, fd);
        close(fd);
 }
 
@@ -128,10 +128,10 @@ asroot_ethtool()
        int len, rc, sock = -1;
        char *ifname;
 
-       must_read(&len, sizeof(int));
+       must_read(PRIV_PRIVILEGED, &len, sizeof(int));
        if ((ifname = (char*)malloc(len + 1)) == NULL)
                fatal("privsep", NULL);
-       must_read(ifname, len);
+       must_read(PRIV_PRIVILEGED, ifname, len);
        ifname[len] = '\0';
        strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
        free(ifname);
@@ -140,12 +140,12 @@ asroot_ethtool()
        if (((rc = sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) ||
            (rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) {
                if (sock != -1) close(sock);
-               must_write(&rc, sizeof(int));
+               must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
                return;
        }
        close(sock);
-       must_write(&rc, sizeof(int));
-       must_write(&ethc, sizeof(struct ethtool_cmd));
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
+       must_write(PRIV_PRIVILEGED, &ethc, sizeof(struct ethtool_cmd));
 }
 
 int
@@ -156,7 +156,7 @@ asroot_iface_init_os(int ifindex, char *name, int *fd)
        if ((*fd = socket(PF_PACKET, SOCK_RAW,
                    htons(ETH_P_ALL))) < 0) {
                rc = errno;
-               must_write(&rc, sizeof(rc));
+               must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
                return rc;
        }
 
index a09e4a0c2914c6963b6891e2ad7030d2170c1ab0..5feae843fbc6576fcdc6508b45a7b19ce7caf85e 100644 (file)
@@ -75,8 +75,8 @@ priv_ping()
 {
        int rc;
        enum priv_cmd cmd = PRIV_PING;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        log_debug("privsep", "monitor ready");
 }
 
@@ -86,10 +86,10 @@ priv_ctl_cleanup(const char *ctlname)
 {
        int rc, len = strlen(ctlname);
        enum priv_cmd cmd = PRIV_DELETE_CTL_SOCKET;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_write(&len, sizeof(int));
-       must_write(ctlname, len);
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, ctlname, len);
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
 }
 
 /* Proxy for gethostbyname */
@@ -99,11 +99,11 @@ priv_gethostbyname()
        static char *buf = NULL;
        int rc;
        enum priv_cmd cmd = PRIV_GET_HOSTNAME;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        if ((buf = (char*)realloc(buf, rc+1)) == NULL)
                fatal("privsep", NULL);
-       must_read(buf, rc+1);
+       must_read(PRIV_UNPRIVILEGED, buf, rc+1);
        return buf;
 }
 
@@ -114,13 +114,13 @@ priv_iface_init(int index, char *iface)
        int rc;
        char dev[IFNAMSIZ];
        enum priv_cmd cmd = PRIV_IFACE_INIT;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_write(&index, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, &index, sizeof(int));
        strlcpy(dev, iface, IFNAMSIZ);
-       must_write(dev, IFNAMSIZ);
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, dev, IFNAMSIZ);
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        if (rc != 0) return -1;
-       return receive_fd();
+       return receive_fd(PRIV_UNPRIVILEGED);
 }
 
 int
@@ -128,11 +128,11 @@ priv_iface_multicast(const char *name, u_int8_t *mac, int add)
 {
        int rc;
        enum priv_cmd cmd = PRIV_IFACE_MULTICAST;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_write(name, IFNAMSIZ);
-       must_write(mac, ETHER_ADDR_LEN);
-       must_write(&add, sizeof(int));
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, name, IFNAMSIZ);
+       must_write(PRIV_UNPRIVILEGED, mac, ETHER_ADDR_LEN);
+       must_write(PRIV_UNPRIVILEGED, &add, sizeof(int));
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        return rc;
 }
 
@@ -141,11 +141,11 @@ priv_iface_description(const char *name, const char *description)
 {
        int rc, len = strlen(description);
        enum priv_cmd cmd = PRIV_IFACE_DESCRIPTION;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_write(name, IFNAMSIZ);
-       must_write(&len, sizeof(int));
-       must_write(description, len);
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, name, IFNAMSIZ);
+       must_write(PRIV_UNPRIVILEGED, &len, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, description, len);
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        return rc;
 }
 
@@ -154,19 +154,19 @@ priv_snmp_socket(struct sockaddr_un *addr)
 {
        int rc;
        enum priv_cmd cmd = PRIV_SNMP_SOCKET;
-       must_write(&cmd, sizeof(enum priv_cmd));
-       must_write(addr, sizeof(struct sockaddr_un));
-       must_read(&rc, sizeof(int));
+       must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd));
+       must_write(PRIV_UNPRIVILEGED, addr, sizeof(struct sockaddr_un));
+       must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        if (rc < 0)
                return rc;
-       return receive_fd();
+       return receive_fd(PRIV_UNPRIVILEGED);
 }
 
 static void
 asroot_ping()
 {
        int rc = 1;
-       must_write(&rc, sizeof(int));
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
 }
 
 static void
@@ -176,18 +176,18 @@ asroot_ctl_cleanup()
        char *ctlname;
        int rc = 0;
 
-       must_read(&len, sizeof(int));
+       must_read(PRIV_PRIVILEGED, &len, sizeof(int));
        if ((ctlname = (char*)malloc(len+1)) == NULL)
                fatal("ctlname", NULL);
 
-       must_read(ctlname, len);
+       must_read(PRIV_PRIVILEGED, ctlname, len);
        ctlname[len] = 0;
 
        ctl_cleanup(ctlname);
        free(ctlname);
 
        /* Ack */
-       must_write(&rc, sizeof(int));
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
 }
 
 static void
@@ -204,12 +204,12 @@ asroot_gethostbyname()
                res_init();
 #endif
                 len = strlen(un.nodename);
-                must_write(&len, sizeof(int));
-                must_write(un.nodename, len + 1);
+                must_write(PRIV_PRIVILEGED, &len, sizeof(int));
+                must_write(PRIV_PRIVILEGED, un.nodename, len + 1);
         } else {
                 len = strlen(hp->h_name);
-                must_write(&len, sizeof(int));
-                must_write(hp->h_name, len + 1);
+                must_write(PRIV_PRIVILEGED, &len, sizeof(int));
+                must_write(PRIV_PRIVILEGED, hp->h_name, len + 1);
         }
 }
 
@@ -219,14 +219,14 @@ asroot_iface_init()
        int rc = -1, fd = -1;
        int ifindex;
        char name[IFNAMSIZ];
-       must_read(&ifindex, sizeof(ifindex));
-       must_read(&name, sizeof(name));
+       must_read(PRIV_PRIVILEGED, &ifindex, sizeof(ifindex));
+       must_read(PRIV_PRIVILEGED, &name, sizeof(name));
        name[sizeof(name) - 1] = '\0';
 
        TRACE(LLDPD_PRIV_INTERFACE_INIT(name));
        rc = asroot_iface_init_os(ifindex, name, &fd);
-       must_write(&rc, sizeof(rc));
-       if (rc == 0 && fd >=0) send_fd(fd);
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
+       if (rc == 0 && fd >=0) send_fd(PRIV_PRIVILEGED, fd);
        if (fd >= 0) close(fd);
 }
 
@@ -235,9 +235,9 @@ asroot_iface_multicast()
 {
        int sock = -1, add, rc = 0;
        struct ifreq ifr = { .ifr_name = {} };
-       must_read(ifr.ifr_name, IFNAMSIZ);
+       must_read(PRIV_PRIVILEGED, ifr.ifr_name, IFNAMSIZ);
 #if defined HOST_OS_LINUX
-       must_read(ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+       must_read(PRIV_PRIVILEGED, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
 #elif defined HOST_OS_FREEBSD || defined HOST_OS_OSX || defined HOST_OS_DRAGONFLY
        /* Black magic from mtest.c */
        struct sockaddr_dl *dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
@@ -247,26 +247,26 @@ asroot_iface_multicast()
        dlp->sdl_nlen = 0;
        dlp->sdl_alen = ETHER_ADDR_LEN;
        dlp->sdl_slen = 0;
-       must_read(LLADDR(dlp), ETHER_ADDR_LEN);
+       must_read(PRIV_PRIVILEGED, LLADDR(dlp), ETHER_ADDR_LEN);
 #elif defined HOST_OS_OPENBSD || defined HOST_OS_NETBSD || defined HOST_OS_SOLARIS
        struct sockaddr *sap = (struct sockaddr *)&ifr.ifr_addr;
 #if ! defined HOST_OS_SOLARIS
        sap->sa_len = sizeof(struct sockaddr);
 #endif
        sap->sa_family = AF_UNSPEC;
-       must_read(sap->sa_data, ETHER_ADDR_LEN);
+       must_read(PRIV_PRIVILEGED, sap->sa_data, ETHER_ADDR_LEN);
 #else
 #error Unsupported OS
 #endif
 
-       must_read(&add, sizeof(int));
+       must_read(PRIV_PRIVILEGED, &add, sizeof(int));
        if (((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) ||
            ((ioctl(sock, (add)?SIOCADDMULTI:SIOCDELMULTI,
                    &ifr) < 0) && (errno != EADDRINUSE)))
                rc = errno;
 
        if (sock != -1) close(sock);
-       must_write(&rc, sizeof(rc));
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
 }
 
 static void
@@ -275,17 +275,17 @@ asroot_iface_description()
        char name[IFNAMSIZ];
        char *description;
        int len, rc;
-       must_read(&name, sizeof(name));
+       must_read(PRIV_PRIVILEGED, &name, sizeof(name));
        name[sizeof(name) - 1] = '\0';
-       must_read(&len, sizeof(int));
+       must_read(PRIV_PRIVILEGED, &len, sizeof(int));
        if ((description = (char*)malloc(len+1)) == NULL)
                fatal("description", NULL);
 
-       must_read(description, len);
+       must_read(PRIV_PRIVILEGED, description, len);
        description[len] = 0;
        TRACE(LLDPD_PRIV_INTERFACE_DESCRIPTION(name, description));
        rc = asroot_iface_description_os(name, description);
-       must_write(&rc, sizeof(rc));
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
        free(description);
 }
 
@@ -298,18 +298,18 @@ asroot_snmp_socket()
 
        if (!addr) {
                addr = (struct sockaddr_un *)malloc(sizeof(struct sockaddr_un));
-               must_read(addr, sizeof(struct sockaddr_un));
+               must_read(PRIV_PRIVILEGED, addr, sizeof(struct sockaddr_un));
        } else
                /* We have already been asked to connect to a socket. We will
                 * connect to the same socket. */
-               must_read(&bogus, sizeof(struct sockaddr_un));
+               must_read(PRIV_PRIVILEGED, &bogus, sizeof(struct sockaddr_un));
        if (addr->sun_family != AF_UNIX)
                fatal("privsep", "someone is trying to trick me");
        addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
 
        if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
                log_warn("privsep", "cannot open socket");
-               must_write(&sock, sizeof(int));
+               must_write(PRIV_PRIVILEGED, &sock, sizeof(int));
                return;
        }
         if ((rc = connect(sock, (struct sockaddr *) addr,
@@ -318,11 +318,11 @@ asroot_snmp_socket()
                           addr->sun_path, strerror(errno));
                close(sock);
                rc = -1;
-               must_write(&rc, sizeof(int));
+               must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
                return;
         }
-       must_write(&rc, sizeof(int));
-       send_fd(sock);
+       must_write(PRIV_PRIVILEGED, &rc, sizeof(int));
+       send_fd(PRIV_PRIVILEGED, sock);
        close(sock);
 }
 
@@ -348,17 +348,17 @@ static struct dispatch_actions actions[] = {
 
 /* Main loop, run as root */
 static void
-priv_loop(int remote)
+priv_loop(int privileged)
 {
        enum priv_cmd cmd;
        struct dispatch_actions *a;
 
        setproctitle("monitor");
 #ifdef USE_SECCOMP
-       if (priv_seccomp_init(remote, monitored) != 0)
+       if (priv_seccomp_init(privileged, monitored) != 0)
           fatal("privsep", "cannot continue without seccomp setup");
 #endif
-       while (!may_read(&cmd, sizeof(enum priv_cmd))) {
+       while (!may_read(PRIV_PRIVILEGED, &cmd, sizeof(enum priv_cmd))) {
                for (a = actions; a->function != NULL; a++) {
                        if (cmd == a->msg) {
                                a->function();
@@ -562,14 +562,14 @@ priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid)
                                fatal("privsep", "setreuid() failed");
 #endif
                }
-               priv_remote(pair[0]);
+               priv_unprivileged_fd(pair[0]);
                close(pair[1]);
                priv_ping();
                break;
        default:
                /* We are in the monitor */
                if (ctl != -1) close(ctl);
-               priv_remote(pair[1]);
+               priv_privileged_fd(pair[1]);
                close(pair[0]);
                if (atexit(priv_exit) != 0)
                        fatal("privsep", "unable to set exit function");
index ae31278c406c16f6fd5da08a03ffb5110f40f404..7600ffd24c984d1f94ef1fe35da8a2ad684d877c 100644 (file)
@@ -1,6 +1,45 @@
 /* -*- mode: c; c-file-style: "openbsd" -*- */
 
-static int remote;
+/* The following are needed by Solaris. The first to get CMSG_* and the second
+ * to keep net/if.h working */
+#define _XPG4_2
+#define __EXTENSIONS__
+#include "lldpd.h"
+
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int privileged, unprivileged;
+void
+priv_privileged_fd(int fd)
+{
+       privileged = fd;
+}
+void
+priv_unprivileged_fd(int fd)
+{
+       unprivileged = fd;
+}
+static int
+priv_fd(enum priv_context ctx)
+{
+       switch (ctx) {
+       case PRIV_PRIVILEGED: return privileged;
+       case PRIV_UNPRIVILEGED: return unprivileged;
+       }
+       return -1;              /* Not possible */
+}
 
 /*
  * Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -34,28 +73,8 @@ static int remote;
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* The following are needed by Solaris. The first to get CMSG_* and the second
- * to keep net/if.h working */
-#define _XPG4_2
-#define __EXTENSIONS__
-#include "lldpd.h"
-
-#include <sys/param.h>
-#include <sys/uio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
 void
-send_fd(int fd)
+send_fd(enum priv_context ctx, int fd)
 {
        struct msghdr msg;
        union {
@@ -87,15 +106,15 @@ send_fd(int fd)
        msg.msg_iov = &vec;
        msg.msg_iovlen = 1;
 
-       if ((n = sendmsg(remote, &msg, 0)) == -1)
-               log_warn("privsep", "sendmsg(%d)", remote);
+       if ((n = sendmsg(priv_fd(ctx), &msg, 0)) == -1)
+               log_warn("privsep", "sendmsg(%d)", priv_fd(ctx));
        if (n != sizeof(int))
                log_warnx("privsep", "sendmsg: expected sent 1 got %ld",
                    (long)n);
 }
 
 int
-receive_fd()
+receive_fd(enum priv_context ctx)
 {
        struct msghdr msg;
        union {
@@ -116,7 +135,7 @@ receive_fd()
        msg.msg_control = &cmsgbuf.buf;
        msg.msg_controllen = sizeof(cmsgbuf.buf);
 
-       if ((n = recvmsg(remote, &msg, 0)) == -1)
+       if ((n = recvmsg(priv_fd(ctx), &msg, 0)) == -1)
                log_warn("privsep", "recvmsg");
        if (n != sizeof(int))
                log_warnx("privsep", "recvmsg: expected received 1 got %ld",
@@ -158,13 +177,13 @@ receive_fd()
 
 /* Read all data or return 1 for error.  */
 int
-may_read(void *buf, size_t n)
+may_read(enum priv_context ctx, void *buf, size_t n)
 {
        char *s = buf;
        ssize_t res, pos = 0;
 
        while (n > pos) {
-               res = read(remote, s + pos, n - pos);
+               res = read(priv_fd(ctx), s + pos, n - pos);
                switch (res) {
                case -1:
                        if (errno == EINTR || errno == EAGAIN)
@@ -181,13 +200,13 @@ may_read(void *buf, size_t n)
 /* Read data with the assertion that it all must come through, or
  * else abort the process.  Based on atomicio() from openssh. */
 void
-must_read(void *buf, size_t n)
+must_read(enum priv_context ctx, void *buf, size_t n)
 {
        char *s = buf;
        ssize_t res, pos = 0;
 
        while (n > pos) {
-               res = read(remote, s + pos, n - pos);
+               res = read(priv_fd(ctx), s + pos, n - pos);
                switch (res) {
                case -1:
                        if (errno == EINTR || errno == EAGAIN)
@@ -203,13 +222,13 @@ must_read(void *buf, size_t n)
 /* Write data with the assertion that it all has to be written, or
  * else abort the process.  Based on atomicio() from openssh. */
 void
-must_write(const void *buf, size_t n)
+must_write(enum priv_context ctx, const void *buf, size_t n)
 {
        const char *s = buf;
        ssize_t res, pos = 0;
 
        while (n > pos) {
-               res = write(remote, s + pos, n - pos);
+               res = write(priv_fd(ctx), s + pos, n - pos);
                switch (res) {
                case -1:
                        if (errno == EINTR || errno == EAGAIN)
@@ -221,9 +240,3 @@ must_write(const void *buf, size_t n)
                }
        }
 }
-
-void
-priv_remote(int fd)
-{
-       remote = fd;
-}