]> The Tcpdump Group git mirrors - libpcap/commitdiff
Set the error message for "permission denied" errors.
authorGuy Harris <[email protected]>
Sat, 12 Mar 2022 00:53:11 +0000 (16:53 -0800)
committerGuy Harris <[email protected]>
Wed, 16 Mar 2022 04:59:14 +0000 (21:59 -0700)
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)

pcap-bpf.c
pcap-dag.c
pcap-dlpi.c
pcap-libdlpi.c
pcap-linux.c
pcap-npf.c
pcap-snit.c
pcap-usb-linux.c

index c9967ee0851285ba3aac3465cb4ecd37fc9e02ac..7a0c2ffebaecb3c0445130496af05f577b1795d4 100644 (file)
@@ -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:
index 108f029ac8f31139a80a1f0d337c16d31e0b8544..3199a70fdf464f8c3ae28333bee6c0d7cc4e306a 100644 (file)
@@ -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;
        }
 
index 208a63bc354dd4fa0adf75dbe0b6a41e37b34ae1..b70d1a36947a8770dbfd6363628be4abda3a9191 100644 (file)
@@ -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
 
index ef3fdac3779087903e94bb29a7b33516c6ff5f62..87ecaccf16343a1dae5e47ea140577c2a3a64631 100644 (file)
@@ -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);
index 701112c235b959c20c7cbb7b61080b51e42116b5..49fe1026c100fbffa65bd3fe008c4f8aaed71343 100644 (file)
@@ -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:
index 25ed4acd241afd83db39552962ce9cf2ca4d1d67..499fbff654de5733d919d67a104d8b02699f95a0 100644 (file)
@@ -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:
index ff0cb59a43dc2fca7b7beec7b9ca31977150d349..3f4e69d7186329c8018d504652e667b1ee5c27e6 100644 (file)
@@ -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;
        }
 
index f15c80b6aaccbfbee2f3d94c400b1e634ab1d247..5fd2426473dadd1d43126f2caf3a91d52ab8d2b9 100644 (file)
@@ -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: