summaryrefslogtreecommitdiffstats
path: root/src/libnftables.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2023-09-14 11:42:15 +0200
committerFlorian Westphal <fw@strlen.de>2023-09-29 12:52:13 +0200
commit149b1c95d129f8ec8a3df16aeca0e9063e8d45bf (patch)
tree2d49ad0b7d72ad697449fd1d4e1b56c8008674d7 /src/libnftables.c
parent4e8aa050312822400124260bf6b630c3c05cb04d (diff)
libnftables: refuse to open onput files other than named pipes or regular files
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>
Diffstat (limited to 'src/libnftables.c')
-rw-r--r--src/libnftables.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/libnftables.c b/src/libnftables.c
index 4b4cf5b6..41f54c0c 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -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;