From: Guy Harris Date: Sat, 12 Mar 2022 00:53:11 +0000 (-0800) Subject: Set the error message for "permission denied" errors. X-Git-Tag: libpcap-1.10.2~207 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/9fffbf03961018f765be8ec174620d68a03c8078?ds=sidebyside Set the error message for "permission denied" errors. Provide a suggestion for PCAP_ERROR_PERM_DENIED and PCAP_ERROR_PROMISC_PERM_DENIED; the suggestion may be nothing more than "you might require root permission", but at least it's something. Note also what we were trying to do, to indicate that the problem might be that you need root permission to set promiscuous mode even if you don't need it to capture, or that you need CAP_NET_ADMIN permission to change the time stamp mode of an adapter on Linux even though you don't need it to capture. (The latter was done as per the discussion in issue and that triggered the same double-free bug that failing to set up the memory-mapped ring buffer caused in issue #1054.) (cherry picked from commit 92c547194ffa85c89b579658f1cc752fad98666f) --- diff --git a/pcap-bpf.c b/pcap-bpf.c index c9967ee0..7a0c2ffe 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -503,12 +503,17 @@ bpf_open(char *errbuf) ((errno != EACCES && errno != ENOENT) || (fd = open(cloning_device, O_RDONLY)) == -1)) { if (errno != ENOENT) { - if (errno == EACCES) + if (errno == EACCES) { fd = PCAP_ERROR_PERM_DENIED; - else + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed - root privileges may be required", + cloning_device); + } else { fd = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, - errno, "(cannot open device) %s", cloning_device); + pcap_fmt_errmsg_for_errno(errbuf, + PCAP_ERRBUF_SIZE, errno, + "(cannot open device) %s", cloning_device); + } return (fd); } no_cloning_bpf = 1; @@ -577,8 +582,9 @@ bpf_open(char *errbuf) * if any. */ fd = PCAP_ERROR_PERM_DENIED; - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, - errno, "(cannot open BPF device) %s", device); + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed - root privileges may be required", + device); break; default: diff --git a/pcap-dag.c b/pcap-dag.c index 108f029a..3199a70f 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -795,12 +795,16 @@ static int dag_activate(pcap_t* p) */ if (errno == ENOENT) ret = PCAP_ERROR_NO_SUCH_DEVICE; - else if (errno == EPERM || errno == EACCES) + else if (errno == EPERM || errno == EACCES) { ret = PCAP_ERROR_PERM_DENIED; - else + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed with %s - additional privileges may be required", + device, (errno == EPERM) ? "EPERM" : "EACCES"); + } else { ret = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, - errno, "dag_config_init %s", device); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "dag_config_init %s", device); + } goto fail; } diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 208a63bc..b70d1a36 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -146,7 +146,7 @@ static int dl_dohpuxbind(int, char *); static int dlpromiscon(pcap_t *, bpf_u_int32); static int dlbindreq(int, bpf_u_int32, char *); static int dlbindack(int, char *, char *, int *); -static int dlokack(int, const char *, char *, char *); +static int dlokack(int, const char *, char *, char *, int *); static int dlinforeq(int, char *); static int dlinfoack(int, char *, char *); @@ -383,12 +383,16 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf) */ cp = "/dev/dlpi"; if ((fd = open(cp, O_RDWR)) < 0) { - if (errno == EPERM || errno == EACCES) + if (errno == EPERM || errno == EACCES) { status = PCAP_ERROR_PERM_DENIED; - else + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed with %s - root privilege may be required", + cp, (errno == EPERM) ? "EPERM" : "EACCES"); + } else { status = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, - errno, "%s", cp); + pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + errno, "Attempt to open %s failed", cp); + } return (status); } @@ -432,12 +436,18 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf) /* Try device without unit number */ if ((fd = open(dname, O_RDWR)) < 0) { if (errno != ENOENT) { - if (errno == EPERM || errno == EACCES) + if (errno == EPERM || errno == EACCES) { status = PCAP_ERROR_PERM_DENIED; - else + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed with %s - root privilege may be required", + dname, + (errno == EPERM) ? "EPERM" : "EACCES"); + } else { status = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, - errno, "%s", dname); + pcap_fmt_errmsg_for_errno(errbuf, + PCAP_ERRBUF_SIZE, errno, + "Attempt to open %s failed", dname); + } return (status); } @@ -472,12 +482,19 @@ open_dlpi_device(const char *name, u_int *ppa, char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: No DLPI device found", name); } else { - if (errno == EPERM || errno == EACCES) + if (errno == EPERM || errno == EACCES) { status = PCAP_ERROR_PERM_DENIED; - else + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed with %s - root privilege may be required", + dname2, + (errno == EPERM) ? "EPERM" : "EACCES"); + } else { status = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(errbuf, - PCAP_ERRBUF_SIZE, errno, "%s", dname2); + pcap_fmt_errmsg_for_errno(errbuf, + PCAP_ERRBUF_SIZE, errno, + "Attempt to open %s failed", + dname2); + } } return (status); } @@ -915,7 +932,7 @@ dl_doattach(int fd, int ppa, char *ebuf) if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0) return (PCAP_ERROR); - err = dlokack(fd, "attach", (char *)buf, ebuf); + err = dlokack(fd, "attach", (char *)buf, ebuf, NULL); if (err < 0) return (err); return (0); @@ -980,6 +997,7 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level) dl_promiscon_req_t req; bpf_u_int32 buf[MAXDLBUF]; int err; + int uerror; req.dl_primitive = DL_PROMISCON_REQ; req.dl_level = level; @@ -987,9 +1005,16 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level) p->errbuf) < 0) return (PCAP_ERROR); err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf, - p->errbuf); - if (err < 0) + p->errbuf, &uerror); + if (err < 0) { + if (err == PCAP_ERROR_PERM_DENIED) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to set promiscuous mode failed with %s - root privilege may be required", + (uerror == EPERM) ? "EPERM" : "EACCES"); + err = PCAP_ERROR_PROMISC_PERM_DENIED; + } return (err); + } return (0); } @@ -1452,10 +1477,10 @@ dlbindack(int fd, char *bufp, char *ebuf, int *uerror) } static int -dlokack(int fd, const char *what, char *bufp, char *ebuf) +dlokack(int fd, const char *what, char *bufp, char *ebuf, int *uerror) { - return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL)); + return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, uerror)); } @@ -1490,7 +1515,7 @@ dlpassive(int fd, char *ebuf) req.dl_primitive = DL_PASSIVE_REQ; if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0) - (void) dlokack(fd, "dlpassive", (char *)buf, ebuf); + (void) dlokack(fd, "dlpassive", (char *)buf, ebuf, NULL); } #endif diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c index ef3fdac3..87ecaccf 100644 --- a/pcap-libdlpi.c +++ b/pcap-libdlpi.c @@ -111,12 +111,16 @@ pcap_activate_libdlpi(pcap_t *p) if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) status = PCAP_ERROR_NO_SUCH_DEVICE; else if (retv == DL_SYSERR && - (errno == EPERM || errno == EACCES)) + (errno == EPERM || errno == EACCES)) { status = PCAP_ERROR_PERM_DENIED; - else + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open DLPI device failed with %s - root privilege may be required", + (errno == EPERM) ? "EPERM" : "EACCES"); + } else { status = PCAP_ERROR; - pcap_libdlpi_err(p->opt.device, "dlpi_open", retv, - p->errbuf); + pcap_libdlpi_err(p->opt.device, "dlpi_open", retv, + p->errbuf); + } return (status); } pd->dlpi_hd = dh; @@ -265,12 +269,25 @@ dlpromiscon(pcap_t *p, bpf_u_int32 level) retv = dlpi_promiscon(pd->dlpi_hd, level); if (retv != DLPI_SUCCESS) { if (retv == DL_SYSERR && - (errno == EPERM || errno == EACCES)) - err = PCAP_ERROR_PERM_DENIED; - else + (errno == EPERM || errno == EACCES)) { + if (level == DL_PROMISC_PHYS) { + err = PCAP_ERROR_PROMISC_PERM_DENIED; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to set promiscuous mode failed with %s - root privilege may be required", + (errno == EPERM) ? "EPERM" : "EACCES"); + } else { + err = PCAP_ERROR_PERM_DENIED; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to set %s mode failed with %s - root privilege may be required", + (level == DL_PROMISC_MULTI) ? "multicast" : "SAP promiscuous", + (errno == EPERM) ? "EPERM" : "EACCES"); + } + } else { err = PCAP_ERROR; - pcap_libdlpi_err(p->opt.device, "dlpi_promiscon" STRINGIFY(level), - retv, p->errbuf); + pcap_libdlpi_err(p->opt.device, + "dlpi_promiscon" STRINGIFY(level), + retv, p->errbuf); + } return (err); } return (0); diff --git a/pcap-linux.c b/pcap-linux.c index 701112c2..49fe1026 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -2305,6 +2305,8 @@ activate_pf_packet(pcap_t *handle, int is_any_device) * socket. */ status = PCAP_ERROR_PERM_DENIED; + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to create packet socket failed - CAP_NET_RAW may be required"); } else { /* * Other error. @@ -3113,6 +3115,9 @@ create_ring(pcap_t *handle, int *status) pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); ifr.ifr_data = (void *)&hwconfig; + /* + * This may require CAP_NET_ADMIN. + */ if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) { switch (errno) { @@ -3125,6 +3130,8 @@ create_ring(pcap_t *handle, int *status) * try requesting hardware time stamps. */ *status = PCAP_ERROR_PERM_DENIED; + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to set hardware timestamp failed - CAP_NET_ADMIN may be required"); return -1; case EOPNOTSUPP: diff --git a/pcap-npf.c b/pcap-npf.c index 25ed4acd..499fbff6 100644 --- a/pcap-npf.c +++ b/pcap-npf.c @@ -1069,7 +1069,12 @@ pcap_activate_npf(pcap_t *p) /* * There is, but we don't have permission to * use it. + * + * XXX - we currently get ERROR_BAD_UNIT if the + * user says "no" to the UAC prompt. */ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "The helper program for \"Admin-only Mode\" must be allowed to make changes to your device"); return (PCAP_ERROR_PERM_DENIED); default: diff --git a/pcap-snit.c b/pcap-snit.c index ff0cb59a..3f4e69d7 100644 --- a/pcap-snit.c +++ b/pcap-snit.c @@ -334,12 +334,16 @@ pcap_activate_snit(pcap_t *p) if (fd < 0 && errno == EACCES) p->fd = fd = open(dev, O_RDONLY); if (fd < 0) { - if (errno == EACCES) + if (errno == EACCES) { err = PCAP_ERROR_PERM_DENIED; - else + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed with EACCES - root privileges may be required", + dev); + } else { err = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, - errno, "%s", dev); + pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "%s", dev); + } goto bad; } diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c index f15c80b6..5fd24264 100644 --- a/pcap-usb-linux.c +++ b/pcap-usb-linux.c @@ -539,6 +539,9 @@ usb_activate(pcap_t* handle) /* * We didn't have permission to open it. */ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "Attempt to open %s failed with EACCES - root privileges may be required", + full_path); return PCAP_ERROR_PERM_DENIED; default: