Make sure destination buffers are NULL-terminated by replacing strcpy()
with strncat() (if destination is guaranteed to be zeroed) or explicitly
set last byte in buffer to zero.

While being at it, replace two direct calls to calloc() with
xtables_calloc() since that takes care of error checking.

Signed-off-by: Phil Sutter <p...@nwl.cc>
---
 iptables/ip6tables.c         | 12 ++++++++----
 iptables/iptables.c          | 12 ++++++++----
 iptables/nft-ipv4.c          |  2 ++
 iptables/nft-ipv6.c          |  2 ++
 iptables/nft-shared.c        | 20 ++++++--------------
 iptables/xshared.c           |  3 ++-
 iptables/xtables-eb.c        |  2 +-
 iptables/xtables-translate.c |  3 ++-
 iptables/xtables.c           | 12 ++++++++----
 libiptc/libiptc.c            |  5 ++++-
 libxtables/xtables.c         |  5 +++--
 11 files changed, 46 insertions(+), 32 deletions(-)

diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index f447bc7474c25..5e0dfd4ff31f7 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -1238,9 +1238,11 @@ static void command_jump(struct iptables_command_state 
*cs)
        cs->target->t = xtables_calloc(1, size);
        cs->target->t->u.target_size = size;
        if (cs->target->real_name == NULL) {
-               strcpy(cs->target->t->u.user.name, cs->jumpto);
+               strncat(cs->target->t->u.user.name, cs->jumpto,
+                       XT_EXTENSION_MAXNAMELEN - 1);
        } else {
-               strcpy(cs->target->t->u.user.name, cs->target->real_name);
+               strncat(cs->target->t->u.user.name, cs->target->real_name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
                        fprintf(stderr, "Notice: The %s target is converted 
into %s target "
                                "in rule listing and saving.\n",
@@ -1275,9 +1277,11 @@ static void command_match(struct iptables_command_state 
*cs)
        m->m = xtables_calloc(1, size);
        m->m->u.match_size = size;
        if (m->real_name == NULL) {
-               strcpy(m->m->u.user.name, m->name);
+               strncat(m->m->u.user.name, m->name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
        } else {
-               strcpy(m->m->u.user.name, m->real_name);
+               strncat(m->m->u.user.name, m->real_name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                if (!(m->ext_flags & XTABLES_EXT_ALIAS))
                        fprintf(stderr, "Notice: The %s match is converted into 
%s match "
                                "in rule listing and saving.\n", m->name, 
m->real_name);
diff --git a/iptables/iptables.c b/iptables/iptables.c
index 144550fcc92ad..9a443716774ad 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -1229,10 +1229,12 @@ static void command_jump(struct iptables_command_state 
*cs)
        cs->target->t = xtables_calloc(1, size);
        cs->target->t->u.target_size = size;
        if (cs->target->real_name == NULL) {
-               strcpy(cs->target->t->u.user.name, cs->jumpto);
+               strncat(cs->target->t->u.user.name, cs->jumpto,
+                       XT_EXTENSION_MAXNAMELEN - 1);
        } else {
                /* Alias support for userspace side */
-               strcpy(cs->target->t->u.user.name, cs->target->real_name);
+               strncat(cs->target->t->u.user.name, cs->target->real_name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
                        fprintf(stderr, "Notice: The %s target is converted 
into %s target "
                                "in rule listing and saving.\n",
@@ -1268,9 +1270,11 @@ static void command_match(struct iptables_command_state 
*cs)
        m->m = xtables_calloc(1, size);
        m->m->u.match_size = size;
        if (m->real_name == NULL) {
-               strcpy(m->m->u.user.name, m->name);
+               strncat(m->m->u.user.name, m->name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
        } else {
-               strcpy(m->m->u.user.name, m->real_name);
+               strncat(m->m->u.user.name, m->real_name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                if (!(m->ext_flags & XTABLES_EXT_ALIAS))
                        fprintf(stderr, "Notice: the %s match is converted into 
%s match "
                                "in rule listing and saving.\n", m->name, 
m->real_name);
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 20ed9428425dd..3db31bd38d016 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -349,10 +349,12 @@ static void nft_ipv4_post_parse(int command,
        cs->fw.ip.invflags = args->invflags;
 
        strncpy(cs->fw.ip.iniface, args->iniface, IFNAMSIZ);
+       cs->fw.ip.iniface[IFNAMSIZ - 1] = '\0';
        memcpy(cs->fw.ip.iniface_mask,
               args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
 
        strncpy(cs->fw.ip.outiface, args->outiface, IFNAMSIZ);
+       cs->fw.ip.outiface[IFNAMSIZ - 1] = '\0';
        memcpy(cs->fw.ip.outiface_mask,
               args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
 
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 1952164e199b9..4b9bc27ce0afa 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -294,10 +294,12 @@ static void nft_ipv6_post_parse(int command, struct 
iptables_command_state *cs,
        cs->fw6.ipv6.invflags = args->invflags;
 
        strncpy(cs->fw6.ipv6.iniface, args->iniface, IFNAMSIZ);
+       cs->fw6.ipv6.iniface[IFNAMSIZ - 1] = '\0';
        memcpy(cs->fw6.ipv6.iniface_mask,
               args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
 
        strncpy(cs->fw6.ipv6.outiface, args->outiface, IFNAMSIZ);
+       cs->fw6.ipv6.outiface[IFNAMSIZ - 1] = '\0';
        memcpy(cs->fw6.ipv6.outiface_mask,
               args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
 
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index fdd4522ce24f4..c02bd551160f0 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -319,15 +319,11 @@ void nft_parse_target(struct nft_xt_ctx *ctx, struct 
nftnl_expr *e)
 
        size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len;
 
-       t = calloc(1, size);
-       if (t == NULL) {
-               fprintf(stderr, "OOM");
-               exit(EXIT_FAILURE);
-       }
+       t = xtables_calloc(1, size);
        memcpy(&t->data, targinfo, tg_len);
        t->u.target_size = size;
        t->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
-       strcpy(t->u.user.name, target->name);
+       strncat(t->u.user.name, target->name, XT_EXTENSION_MAXNAMELEN - 1);
 
        target->t = t;
 
@@ -361,16 +357,11 @@ void nft_parse_match(struct nft_xt_ctx *ctx, struct 
nftnl_expr *e)
        if (match == NULL)
                return;
 
-       m = calloc(1, sizeof(struct xt_entry_match) + mt_len);
-       if (m == NULL) {
-               fprintf(stderr, "OOM");
-               exit(EXIT_FAILURE);
-       }
-
+       m = xtables_calloc(1, sizeof(struct xt_entry_match) + mt_len);
        memcpy(&m->data, mt_info, mt_len);
        m->u.match_size = mt_len + XT_ALIGN(sizeof(struct xt_entry_match));
        m->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
-       strcpy(m->u.user.name, match->name);
+       strncat(m->u.user.name, match->name, XT_EXTENSION_MAXNAMELEN - 1);
 
        match->m = m;
 
@@ -587,7 +578,8 @@ static void nft_parse_limit(struct nft_xt_ctx *ctx, struct 
nftnl_expr *e)
        size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size;
        match->m = xtables_calloc(1, size);
        match->m->u.match_size = size;
-       strcpy(match->m->u.user.name, match->name);
+       strncat(match->m->u.user.name, match->name,
+               XT_EXTENSION_MAXNAMELEN - 1);
        match->m->u.user.revision = match->revision;
        xs_init_match(match);
 
diff --git a/iptables/xshared.c b/iptables/xshared.c
index a10e425c383a2..c34c474f0d07c 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -152,7 +152,8 @@ int command_default(struct iptables_command_state *cs,
 
                m->m = xtables_calloc(1, size);
                m->m->u.match_size = size;
-               strcpy(m->m->u.user.name, m->name);
+               strncat(m->m->u.user.name, m->name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                m->m->u.user.revision = m->revision;
                xs_init_match(m);
 
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 6aa1cba3e5b9d..820779315f6e5 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -590,7 +590,7 @@ static void ebt_load_match(const char *name)
        size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
        m->m = xtables_calloc(1, size);
        m->m->u.match_size = size;
-       strcpy(m->m->u.user.name, m->name);
+       strncat(m->m->u.user.name, m->name, XT_EXTENSION_MAXNAMELEN - 1);
        m->m->u.user.revision = m->revision;
        xs_init_match(m);
 
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index f4c0f9cf5a181..ccb9ffe17f662 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -38,7 +38,8 @@ void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, 
const char *ifname,
        if (ifname[0] == '\0')
                return;
 
-       strcpy(iface, ifname);
+       strncpy(iface, ifname, IFNAMSIZ);
+       iface[IFNAMSIZ - 1] = '\0';
        ifaclen = strlen(iface);
        if (iface[ifaclen - 1] == '+')
                iface[ifaclen - 1] = '*';
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 313b985bbaa85..0c16bb5a682fd 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -620,10 +620,12 @@ static void command_jump(struct iptables_command_state 
*cs)
        cs->target->t = xtables_calloc(1, size);
        cs->target->t->u.target_size = size;
        if (cs->target->real_name == NULL) {
-               strcpy(cs->target->t->u.user.name, cs->jumpto);
+               strncat(cs->target->t->u.user.name, cs->jumpto,
+                       XT_EXTENSION_MAXNAMELEN - 1);
        } else {
                /* Alias support for userspace side */
-               strcpy(cs->target->t->u.user.name, cs->target->real_name);
+               strncat(cs->target->t->u.user.name, cs->target->real_name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
                        fprintf(stderr, "Notice: The %s target is converted 
into %s target "
                                "in rule listing and saving.\n",
@@ -658,9 +660,11 @@ static void command_match(struct iptables_command_state 
*cs)
        m->m = xtables_calloc(1, size);
        m->m->u.match_size = size;
        if (m->real_name == NULL) {
-               strcpy(m->m->u.user.name, m->name);
+               strncat(m->m->u.user.name, m->name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
        } else {
-               strcpy(m->m->u.user.name, m->real_name);
+               strncat(m->m->u.user.name, m->real_name,
+                       XT_EXTENSION_MAXNAMELEN - 1);
                if (!(m->ext_flags & XTABLES_EXT_ALIAS))
                        fprintf(stderr, "Notice: the %s match is converted into 
%s match "
                                "in rule listing and saving.\n", m->name, 
m->real_name);
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
index 7c3cb9e7cf076..f16dacbb73fe1 100644
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -161,6 +161,7 @@ static struct chain_head *iptcc_alloc_chain_head(const char 
*name, int hooknum)
        memset(c, 0, sizeof(*c));
 
        strncpy(c->name, name, TABLE_MAXNAMELEN);
+       c->name[TABLE_MAXNAMELEN - 1] = '\0';
        c->hooknum = hooknum;
        INIT_LIST_HEAD(&c->rules);
 
@@ -1150,7 +1151,9 @@ static int iptcc_compile_chain(struct xtc_handle *h, 
STRUCT_REPLACE *repl, struc
                strcpy(head->name.target.u.user.name, ERROR_TARGET);
                head->name.target.u.target_size =
                                ALIGN(sizeof(struct xt_error_target));
-               strcpy(head->name.errorname, c->name);
+               strncpy(head->name.errorname, c->name,
+                       XT_FUNCTION_MAXNAMELEN - 1);
+               head->name.errorname[XT_FUNCTION_MAXNAMELEN - 1] = '\0';
        } else {
                repl->hook_entry[c->hooknum-1] = c->head_offset;
                repl->underflow[c->hooknum-1] = c->foot_offset;
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index ffd8fbcf29465..8d0f945682a24 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -845,7 +845,8 @@ int xtables_compatible_revision(const char *name, uint8_t 
revision, int opt)
 
        xtables_load_ko(xtables_modprobe_program, true);
 
-       strcpy(rev.name, name);
+       strncpy(rev.name, name, XT_EXTENSION_MAXNAMELEN);
+       rev.name[XT_EXTENSION_MAXNAMELEN - 1] = '\0';
        rev.revision = revision;
 
        max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
@@ -1731,7 +1732,7 @@ const char *xtables_ip6mask_to_numeric(const struct 
in6_addr *addrp)
 
        if (l == -1) {
                strcpy(buf, "/");
-               strcat(buf, xtables_ip6addr_to_numeric(addrp));
+               strncat(buf, xtables_ip6addr_to_numeric(addrp), 50);
                return buf;
        }
        /* we don't want to see "/128" */
-- 
2.18.0

Reply via email to