void asroot_ethtool() { struct ifreq ifr = {}; struct ethtool_cmd ethc = {}; int len, rc, sock = -1; char *ifname; must_read(PRIV_PRIVILEGED, &len, sizeof(int)); if ((ifname = (char*)malloc(len + 1)) == NULL) fatal("privsep", NULL); must_read(PRIV_PRIVILEGED, ifname, len); ifname[len] = '\0'; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); free(ifname); ifr.ifr_data = (caddr_t)ðc; ethc.cmd = ETHTOOL_GSET; if (((rc = sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) || (rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) { if (sock != -1) close(sock); must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); return; } close(sock); must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); must_write(PRIV_PRIVILEGED, ðc, sizeof(struct ethtool_cmd)); }
static void read_server_setup_reply_cb(EV_P_ ev_io *w, int revents) { struct connstate *connstate = (struct connstate *)w->data; xcb_setup_failed_t setup_failed; must_read(readall_into(&setup_failed, sizeof(setup_failed), w->fd)); switch (setup_failed.status) { case 0: errx(EXIT_FAILURE, "error authenticating at the X11 server"); case 2: errx(EXIT_FAILURE, "two-factor auth not implemented"); case 1: must_write(writeall(connstate->clientw->fd, &setup_failed, sizeof(xcb_setup_failed_t))); const size_t len = (setup_failed.length * 4); void *buf = smalloc(len); must_read(readall_into(buf, len, w->fd)); must_write(writeall(connstate->clientw->fd, buf, len)); free(buf); ev_set_cb(connstate->clientw, read_client_x11_packet_cb); ev_set_cb(connstate->serverw, read_server_x11_packet_cb); ev_io_start(EV_A_ connstate->clientw); break; default: errx(EXIT_FAILURE, "X11 protocol error: expected setup_failed.status in [0..2], got %d", setup_failed.status); } }
void asroot_iface_mac() { struct ifreq ifr = {}; int len, rc, sock = -1; char *ifname; struct ethtool_perm_addr *epaddr; must_read(PRIV_PRIVILEGED, &len, sizeof(int)); if ((ifname = (char*)malloc(len + 1)) == NULL) fatal("privsep", NULL); must_read(PRIV_PRIVILEGED, ifname, len); ifname[len] = '\0'; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); free(ifname); if ((epaddr = malloc(sizeof(struct ethtool_perm_addr) + ETHER_ADDR_LEN)) == NULL) fatal("privsep", NULL); epaddr->cmd = ETHTOOL_GPERMADDR; epaddr->size = ETHER_ADDR_LEN; ifr.ifr_data = (caddr_t)epaddr; if (((rc = sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) || (rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) { if (sock != -1) close(sock); free(epaddr); must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); return; } close(sock); must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); must_write(PRIV_PRIVILEGED, epaddr->data, ETHER_ADDR_LEN); free(epaddr); }
static void parent_bind(int fd) { int sock, status; struct sockaddr_storage ss; socklen_t sslen; int er; logmsg(LOG_DEBUG, "[priv]: msg PRIV_BIND received"); sock = receive_fd(fd); must_read(fd, &sslen, sizeof(sslen)); if (sslen == 0 || sslen > sizeof(ss)) _exit(1); must_read(fd, &ss, sslen); if (check_bind((struct sockaddr *) &ss, sslen)) _exit(1); status = bind(sock, (struct sockaddr *)&ss, sslen); er = errno; must_write(fd, &er, sizeof(er)); must_write(fd, &status, sizeof(status)); if (sock >= 0) close(sock); }
void asroot_open() { const char* authorized[] = { "/proc/sys/net/ipv4/ip_forward", "/proc/net/bonding/[^.][^/]*", "/proc/self/net/bonding/[^.][^/]*", #ifdef ENABLE_OLDIES SYSFS_CLASS_NET "[^.][^/]*/brforward", SYSFS_CLASS_NET "[^.][^/]*/brport", SYSFS_CLASS_NET "[^.][^/]*/brif/[^.][^/]*/port_no", #endif SYSFS_CLASS_DMI "product_version", SYSFS_CLASS_DMI "product_serial", SYSFS_CLASS_DMI "product_name", SYSFS_CLASS_DMI "bios_version", SYSFS_CLASS_DMI "sys_vendor", SYSFS_CLASS_DMI "chassis_asset_tag", NULL }; const char **f; char *file; int fd, len, rc; regex_t preg; must_read(PRIV_PRIVILEGED, &len, sizeof(len)); if ((file = (char *)malloc(len + 1)) == NULL) fatal("privsep", NULL); must_read(PRIV_PRIVILEGED, file, len); file[len] = '\0'; for (f=authorized; *f != NULL; f++) { if (regcomp(&preg, *f, REG_NOSUB) != 0) /* Should not happen */ fatal("privsep", "unable to compile a regex"); if (regexec(&preg, file, 0, NULL, 0) == 0) { regfree(&preg); break; } regfree(&preg); } if (*f == NULL) { log_warnx("privsep", "not authorized to open %s", file); rc = -1; must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); free(file); return; } if ((fd = open(file, O_RDONLY)) == -1) { rc = -1; must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); free(file); return; } free(file); must_write(PRIV_PRIVILEGED, &fd, sizeof(int)); send_fd(PRIV_PRIVILEGED, fd); close(fd); }
/* * privileged part of priv_pcap_setfilter, compile the filter * expression, and return it to the parent. Note that we fake an hpcap * and use it to capture the error messages, and pass the error back * to client. */ int setfilter(int bpfd, int sock, char *filter) { struct bpf_program fcode; int oflag, snap, link; u_int32_t netmask; pcap_t hpcap; must_read(sock, &oflag, sizeof(oflag)); must_read(sock, &netmask, sizeof(netmask)); must_read(sock, &snap, sizeof(snap)); must_read(sock, &link, sizeof(link)); if (snap < 0) { snprintf(hpcap.errbuf, PCAP_ERRBUF_SIZE, "invalid snaplen"); goto err; } /* fake hpcap, it only needs errbuf, snaplen, and linktype to * compile a filter expression */ /* XXX messing with pcap internals */ hpcap.snapshot = snap; hpcap.linktype = link; if (pcap_compile(&hpcap, &fcode, filter, oflag, netmask)) goto err; /* if bpf descriptor is open, set the filter XXX check oflag? */ if (bpfd >= 0 && ioctl(bpfd, BIOCSETF, &fcode)) { snprintf(hpcap.errbuf, PCAP_ERRBUF_SIZE, "ioctl: BIOCSETF: %s", strerror(errno)); pcap_freecode(&fcode); goto err; } if (fcode.bf_len > 0) { /* write the filter */ must_write(sock, &fcode.bf_len, sizeof(fcode.bf_len)); must_write(sock, fcode.bf_insns, fcode.bf_len * sizeof(struct bpf_insn)); } else { snprintf(hpcap.errbuf, PCAP_ERRBUF_SIZE, "Invalid filter size"); pcap_freecode(&fcode); goto err; } pcap_freecode(&fcode); return (0); err: fcode.bf_len = 0; must_write(sock, &fcode.bf_len, sizeof(fcode.bf_len)); /* write back the error string */ write_string(sock, hpcap.errbuf); return (1); }
/* * filter is compiled and set in the privileged process. * get the compiled output and set it locally for filtering dumps etc. */ struct bpf_program * priv_pcap_setfilter(pcap_t *hpcap, int oflag, u_int32_t netmask) { struct bpf_program *fcode = NULL; int snap, link; char *ebuf; if (priv_fd < 0) errx(1, "%s: called from privileged portion", __func__); ebuf = pcap_geterr(hpcap); snap = pcap_snapshot(hpcap); link = pcap_datalink(hpcap); fcode = calloc(1, sizeof(*fcode)); if (fcode == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "out of memory"); return (NULL); } write_command(priv_fd, PRIV_SETFILTER); /* send oflag, netmask, snaplen and linktype */ must_write(priv_fd, &oflag, sizeof(oflag)); must_write(priv_fd, &netmask, sizeof(netmask)); must_write(priv_fd, &snap, sizeof(snap)); must_write(priv_fd, &link, sizeof(link)); /* receive compiled filter */ must_read(priv_fd, &fcode->bf_len, sizeof(fcode->bf_len)); if (fcode->bf_len <= 0) { int len; len = read_string(priv_fd, ebuf, PCAP_ERRBUF_SIZE, __func__); if (len == 0) snprintf(ebuf, PCAP_ERRBUF_SIZE, "pcap compile error"); goto err; } fcode->bf_insns = calloc(fcode->bf_len, sizeof(struct bpf_insn)); if (fcode->bf_insns == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "out of memory"); goto err; } must_read(priv_fd, fcode->bf_insns, fcode->bf_len * sizeof(struct bpf_insn)); pcap_setfilter(hpcap, fcode); return (fcode); err: free(fcode); return (NULL); }
/* Proxy for gethostbyname */ char * 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)); if ((buf = (char*)realloc(buf, rc+1)) == NULL) fatal("privsep", NULL); must_read(buf, rc+1); return buf; }
// https://www.x.org/releases/current/doc/xproto/x11protocol.html#Encoding::Connection_Setup static void read_client_setup_request_cb(EV_P_ ev_io *w, int revents) { ev_io_stop(EV_A_ w); struct connstate *connstate = (struct connstate *)w->data; /* Read X11 setup request in its entirety. */ xcb_setup_request_t setup_request; must_read(readall_into(&setup_request, sizeof(setup_request), w->fd)); /* Establish a connection to X11. */ int fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { err(EXIT_FAILURE, "socket()"); } char *host; int displayp; if (xcb_parse_display(getenv("DISPLAY"), &host, &displayp, NULL) == 0) { errx(EXIT_FAILURE, "Could not parse DISPLAY=%s", getenv("DISPLAY")); } free(host); struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/.X11-unix/X%d", displayp); if (connect(fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { err(EXIT_FAILURE, "connect(%s)", addr.sun_path); } /* Relay setup request. */ must_write(writeall(fd, &setup_request, sizeof(setup_request))); if (setup_request.authorization_protocol_name_len > 0 || setup_request.authorization_protocol_data_len > 0) { const size_t authlen = setup_request.authorization_protocol_name_len + XCB_PAD(setup_request.authorization_protocol_name_len) + setup_request.authorization_protocol_data_len + XCB_PAD(setup_request.authorization_protocol_data_len); void *buf = smalloc(authlen); must_read(readall_into(buf, authlen, w->fd)); must_write(writeall(fd, buf, authlen)); free(buf); } /* Wait for a response from the X11 server. */ ev_io *serverw = scalloc(1, sizeof(ev_io)); connstate->serverw = serverw; serverw->data = connstate; ev_io_init(serverw, read_server_setup_reply_cb, fd, EV_READ); ev_io_start(EV_A_ serverw); }
static void asroot_snmp_socket() { int sock, rc; static struct sockaddr_un *addr = NULL; struct sockaddr_un bogus; if (!addr) { addr = (struct sockaddr_un *)malloc(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(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(PRIV_PRIVILEGED, &sock, sizeof(int)); return; } if ((rc = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_un))) != 0) { log_info("privsep", "cannot connect to %s: %s", addr->sun_path, strerror(errno)); close(sock); rc = -1; must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); return; } int flags; if ((flags = fcntl(sock, F_GETFL, NULL)) < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) { log_warn("privsep", "cannot set sock %s to non-block : %s", addr->sun_path, strerror(errno)); close(sock); rc = -1; must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); return; } must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); send_fd(PRIV_PRIVILEGED, sock); close(sock); }
static void asroot_iface_init() { int rc = -1, fd = -1; int ifindex; char name[IFNAMSIZ]; must_read(&ifindex, sizeof(ifindex)); must_read(&name, sizeof(name)); name[sizeof(name) - 1] = '\0'; rc = asroot_iface_init_os(ifindex, name, &fd); must_write(&rc, sizeof(rc)); if (rc == 0 && fd >=0) send_fd(fd); if (fd >= 0) close(fd); }
/* Proxy for gethostname */ char * priv_gethostname() { static char *buf = NULL; int rc; enum priv_cmd cmd = PRIV_GET_HOSTNAME; must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd)); priv_wait(); must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int)); if ((buf = (char*)realloc(buf, rc+1)) == NULL) fatal("privsep", NULL); must_read(PRIV_UNPRIVILEGED, buf, rc); buf[rc] = '\0'; return buf; }
int monitor_readdir(char *file, size_t size) { int fd; size_t len; must_read(&len, sizeof len); if (len == 0) return -1; if (len >= size) log_fatal("monitor_readdir: received bad length from monitor"); must_read(file, len); file[len] = '\0'; fd = mm_receive_fd(m_state.s); return fd; }
/* Proxy to get permanent MAC address */ int priv_iface_mac(char *ifname, void *mac, size_t length) { int rc, len; enum priv_cmd cmd = PRIV_IFACE_MAC; must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd)); len = strlen(ifname); must_write(PRIV_UNPRIVILEGED, &len, sizeof(int)); must_write(PRIV_UNPRIVILEGED, ifname, len); priv_wait(); must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int)); if (rc != 0) return rc; must_read(PRIV_UNPRIVILEGED, mac, length); return rc; }
/* Proxy for ethtool ioctl (GSET only) */ int priv_ethtool(char *ifname, void *ethc, size_t length) { int rc, len; enum priv_cmd cmd = PRIV_ETHTOOL; must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd)); len = strlen(ifname); must_write(PRIV_UNPRIVILEGED, &len, sizeof(int)); must_write(PRIV_UNPRIVILEGED, ifname, len); priv_wait(); must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int)); if (rc != 0) return rc; must_read(PRIV_UNPRIVILEGED, ethc, length); return rc; }
static void asroot_iface_init() { int rc = -1, fd = -1; int ifindex; char name[IFNAMSIZ]; 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(PRIV_PRIVILEGED, &rc, sizeof(rc)); if (rc == 0 && fd >=0) send_fd(PRIV_PRIVILEGED, fd); if (fd >= 0) close(fd); }
pcap_dumper_t * priv_pcap_dump_open(pcap_t *p, char *fname) { int fd, err; FILE *f; if (priv_fd < 0) errx(1, "%s: called from privileged portion", __func__); if (fname[0] == '-' && fname[1] == '\0') { f = stdout; priv_init_done(); } else { write_command(priv_fd, PRIV_OPEN_OUTPUT); fd = receive_fd(priv_fd); must_read(priv_fd, &err, sizeof(err)); if (fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Failed to open output file %s: %s", fname, strerror(err)); return (NULL); } f = fdopen(fd, "w"); if (f == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, pcap_strerror(errno)); close(fd); return (NULL); } } (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot); return ((pcap_dumper_t *)f); }
static void asroot_iface_description() { char name[IFNAMSIZ]; char *description; int len, rc; must_read(&name, sizeof(name)); name[sizeof(name) - 1] = '\0'; must_read(&len, sizeof(int)); if ((description = (char*)malloc(len+1)) == NULL) fatal("description", NULL); must_read(description, len); description[len] = 0; rc = asroot_iface_description_os(name, description); must_write(&rc, sizeof(rc)); }
/* This function is where the privileged process waits(loops) indefinitely. */ void monitor_loop(int debug) { int msgcode; if (!debug) log_to(0); for (;;) { must_read(&msgcode, sizeof msgcode); switch (msgcode) { case MONITOR_GET_FD: m_priv_getfd(); break; case MONITOR_PFKEY_OPEN: LOG_DBG((LOG_MISC, 80, "monitor_loop: MONITOR_PFKEY_OPEN")); m_priv_pfkey_open(); break; case MONITOR_SETSOCKOPT: LOG_DBG((LOG_MISC, 80, "monitor_loop: MONITOR_SETSOCKOPT")); m_priv_setsockopt(); break; case MONITOR_BIND: LOG_DBG((LOG_MISC, 80, "monitor_loop: MONITOR_BIND")); m_priv_bind(); break; case MONITOR_REQ_READDIR: LOG_DBG((LOG_MISC, 80, "monitor_loop: MONITOR_REQ_READDIR")); m_priv_req_readdir(); break; case MONITOR_INIT_DONE: LOG_DBG((LOG_MISC, 80, "monitor_loop: MONITOR_INIT_DONE")); break; case MONITOR_SHUTDOWN: LOG_DBG((LOG_MISC, 80, "monitor_loop: MONITOR_SHUTDOWN")); break; default: log_print("monitor_loop: got unknown code %d", msgcode); } } exit(0); }
/* Privileged: called by monitor_loop. */ static void m_priv_setsockopt(void) { int sock, level, optname, v; int err = 0; char *optval = 0; socklen_t optlen; sock = mm_receive_fd(m_state.s); if (sock < 0) { log_print("m_priv_setsockopt: read/write error"); return; } must_read(&level, sizeof level); must_read(&optname, sizeof optname); must_read(&optlen, sizeof optlen); optval = (char *)malloc(optlen); if (!optval) { log_print("m_priv_setsockopt: malloc failed"); close(sock); return; } must_read(optval, optlen); if (m_priv_check_sockopt(level, optname) != 0) { err = EACCES; v = -1; } else { v = setsockopt(sock, level, optname, optval, optlen); if (v < 0) err = errno; } close(sock); sock = -1; must_write(&err, sizeof err); must_write(&v, sizeof v); free(optval); return; }
static void read_server_x11_packet_cb(EV_P_ ev_io *w, int revents) { struct connstate *connstate = (struct connstate *)w->data; // all packets from the server are at least 32 bytes in length size_t len = 32; void *packet = smalloc(len); must_read(readall_into(packet, len, connstate->serverw->fd)); switch (((generic_x11_reply_t *)packet)->code) { case 0: // error break; case 1: // reply len += ((generic_x11_reply_t *)packet)->length * 4; if (len > 32) { packet = srealloc(packet, len); must_read(readall_into(packet + 32, len - 32, connstate->serverw->fd)); } /* BEGIN RandR 1.5 specific */ const uint16_t sequence = ((generic_x11_reply_t *)packet)->sequence; if (sequence == connstate->getext_randr) { xcb_query_extension_reply_t *reply = packet; connstate->randr_major_opcode = reply->major_opcode; } if (sequence == connstate->getmonitors) { printf("RRGetMonitors reply!\n"); if (injected_reply != NULL) { printf("injecting reply\n"); ((generic_x11_reply_t *)injected_reply)->sequence = sequence; must_write(writeall(connstate->clientw->fd, injected_reply, injected_reply_len)); free(packet); return; } } /* END RandR 1.5 specific */ break; default: // event break; } must_write(writeall(connstate->clientw->fd, packet, len)); free(packet); }
/* Proxies */ static void priv_ping() { int rc; enum priv_cmd cmd = PRIV_PING; must_write(&cmd, sizeof(enum priv_cmd)); must_read(&rc, sizeof(int)); log_debug("privsep", "monitor ready"); }
/* Proxies */ static void priv_ping() { int rc; enum priv_cmd cmd = PRIV_PING; must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd)); priv_wait(); must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int)); log_debug("privsep", "monitor ready"); }
static void asroot_iface_promisc() { char name[IFNAMSIZ]; int rc; must_read(PRIV_PRIVILEGED, &name, sizeof(name)); name[sizeof(name) - 1] = '\0'; rc = asroot_iface_promisc_os(name); must_write(PRIV_PRIVILEGED, &rc, sizeof(rc)); }
/* Proxy for ctl_cleanup */ void 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)); }
/* Privileged: called by monitor_loop. */ static void m_priv_bind(void) { int sock, v, err = 0; struct sockaddr *name = 0; socklen_t namelen; sock = mm_receive_fd(m_state.s); if (sock < 0) { log_print("m_priv_bind: read/write error"); return; } must_read(&namelen, sizeof namelen); name = (struct sockaddr *)malloc(namelen); if (!name) { log_print("m_priv_bind: malloc failed"); close(sock); return; } must_read((char *)name, namelen); if (m_priv_check_bind(name, namelen) != 0) { err = EACCES; v = -1; } else { v = bind(sock, name, namelen); if (v < 0) { log_error("m_priv_bind: bind(%d,%p,%d) returned %d", sock, name, namelen, v); err = errno; } } close(sock); sock = -1; must_write(&err, sizeof err); must_write(&v, sizeof v); free(name); return; }
static void asroot_iface_description() { char name[IFNAMSIZ]; char *description; int len, rc; must_read(PRIV_PRIVILEGED, &name, sizeof(name)); name[sizeof(name) - 1] = '\0'; must_read(PRIV_PRIVILEGED, &len, sizeof(int)); if ((description = (char*)malloc(len+1)) == NULL) fatal("description", NULL); 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(PRIV_PRIVILEGED, &rc, sizeof(rc)); free(description); }
int monitor_req_readdir(const char *filename) { int cmd, err; size_t len; cmd = MONITOR_REQ_READDIR; must_write(&cmd, sizeof cmd); len = strlen(filename); must_write(&len, sizeof len); must_write(filename, len); must_read(&err, sizeof err); if (err == -1) must_read(&errno, sizeof errno); return err; }
static void asroot_ctl_cleanup() { int len; char *ctlname; int rc = 0; must_read(PRIV_PRIVILEGED, &len, sizeof(int)); if ((ctlname = (char*)malloc(len+1)) == NULL) fatal("ctlname", NULL); must_read(PRIV_PRIVILEGED, ctlname, len); ctlname[len] = 0; ctl_cleanup(ctlname); free(ctlname); /* Ack */ must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); }
/* Proxy for ctl_cleanup */ void priv_ctl_cleanup(const char *ctlname) { int rc, len = strlen(ctlname); enum priv_cmd cmd = PRIV_DELETE_CTL_SOCKET; must_write(PRIV_UNPRIVILEGED, &cmd, sizeof(enum priv_cmd)); must_write(PRIV_UNPRIVILEGED, &len, sizeof(int)); must_write(PRIV_UNPRIVILEGED, ctlname, len); priv_wait(); must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int)); }