]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
libnftables: refuse to open onput files other than named pipes or regular files
authorFlorian Westphal <fw@strlen.de>
Thu, 14 Sep 2023 09:42:15 +0000 (11:42 +0200)
committerFlorian Westphal <fw@strlen.de>
Fri, 29 Sep 2023 10:52:13 +0000 (12:52 +0200)
Don't start e.g. parsing a block device.
nftables is typically run as privileged user, exit early if we
get unexpected input.

Only exception: Allow character device if input is /dev/stdin.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1664
Signed-off-by: Florian Westphal <fw@strlen.de>
src/libnftables.c

index 4b4cf5b67ef8b08494b8cfb0bf5b197cda910e6e..41f54c0c73706c2baa034d8c77f1d4af5e1acda6 100644 (file)
@@ -16,6 +16,7 @@
 #include <iface.h>
 #include <cmd.h>
 #include <errno.h>
+#include <sys/stat.h>
 
 static int nft_netlink(struct nft_ctx *nft,
                       struct list_head *cmds, struct list_head *msgs)
@@ -660,13 +661,46 @@ retry:
        return rc;
 }
 
+/* need to use stat() to, fopen() will block for named fifos and
+ * libjansson makes no checks before or after open either.
+ */
+static struct error_record *filename_is_useable(struct nft_ctx *nft, const char *name)
+{
+       unsigned int type;
+       struct stat sb;
+       int err;
+
+       err = stat(name, &sb);
+       if (err)
+               return error(&internal_location, "Could not open file \"%s\": %s\n",
+                            name, strerror(errno));
+
+       type = sb.st_mode & S_IFMT;
+
+       if (type == S_IFREG || type == S_IFIFO)
+               return NULL;
+
+       if (type == S_IFCHR && 0 == strcmp(name, "/dev/stdin"))
+               return NULL;
+
+       return error(&internal_location, "Not a regular file: \"%s\"\n", name);
+}
+
 static int __nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
 {
+       struct error_record *erec;
        struct cmd *cmd, *next;
        int rc, parser_rc;
        LIST_HEAD(msgs);
        LIST_HEAD(cmds);
 
+       erec = filename_is_useable(nft, filename);
+       if (erec) {
+               erec_print(&nft->output, erec, nft->debug_mask);
+               erec_destroy(erec);
+               return -1;
+       }
+
        rc = load_cmdline_vars(nft, &msgs);
        if (rc < 0)
                goto err;