]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
hooks: Escape interface names and use printf esc_ifname 610/head
authorJoan Lledó <jlledom@member.fsf.org>
Tue, 19 May 2026 14:21:54 +0000 (15:21 +0100)
committerRoy Marples <roy@marples.name>
Tue, 19 May 2026 14:21:54 +0000 (15:21 +0100)
In the Hurd, interface names can include invalid characters like `/`.
So those must be escaped.

13 files changed:
hooks/01-test
hooks/20-resolv.conf
hooks/29-lookup-hostname
hooks/30-hostname.in
hooks/50-dhcpcd-compat
hooks/50-ntp.conf
hooks/50-yp.conf
hooks/50-ypbind.in
hooks/dhcpcd-run-hooks.in
src/dhcp-common.c
src/dhcp-common.h
src/dhcp.c
src/script.c

index e7d53216353216696d2e528a4f00e951e2c072e3..91768fc1c9956187e34dfaa9aad7d9e97b0d50d8 100644 (file)
@@ -8,32 +8,32 @@ if [ "$reason" = "TEST" ]; then
        set | while read line; do
                case "$line" in
                interface=*|pid=*|reason=*|protocol=*|profile=*|skip_hooks=*)
-                       echo "$line";;
+                       printf '%s\n' "$line";;
                esac
        done
        # Interface flags
        set | while read line; do
                case "$line" in
                ifcarrier=*|ifflags=*|ifmetric=*|ifmtu=*|ifwireless=*|ifssid=*)
-                       echo "$line";;
+                       printf '%s\n' "$line";;
                esac
        done
        # Old lease
        set | while read line; do
                case "$line" in
-               old_*) echo "$line";;
+               old_*) printf '%s\n' "$line";;
                esac
        done
        # New lease
        set | while read line; do
                case "$line" in
-               new_*) echo "$line";;
+               new_*) printf '%s\n' "$line";;
                esac
        done
        # Router Advertisements
        set | while read line; do
                case "$line" in
-               nd[0-9]*_*) echo "$line";;
+               nd[0-9]*_*) printf '%s\n' "$line";;
                esac
        done
        exit 0
index 0ef599f8faa74d1685cd4842f219b2bad5df3910..6aae9cc1a85ff6a013a6b8c56f2616cd5dedb3ce 100644 (file)
@@ -60,17 +60,17 @@ build_resolv_conf()
        # Assemble resolv.conf using our head and tail files
        [ -f "$cf" ] && rm -f "$cf"
        [ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
-       echo "$header" > "$cf"
+       printf '%s\n' "$header" > "$cf"
        if [ -f /etc/resolv.conf.head ]; then
                cat /etc/resolv.conf.head >> "$cf"
        else
-               echo "# /etc/resolv.conf.head can replace this line" >> "$cf"
+               printf '%s\n' "# /etc/resolv.conf.head can replace this line" >> "$cf"
        fi
        printf %s "$domain$search$servers" >> "$cf"
        if [ -f /etc/resolv.conf.tail ]; then
                cat /etc/resolv.conf.tail >> "$cf"
        else
-               echo "# /etc/resolv.conf.tail can replace this line" >> "$cf"
+               printf '%s\n' "# /etc/resolv.conf.tail can replace this line" >> "$cf"
        fi
        if change_file /etc/resolv.conf "$cf"; then
                chmod 644 /etc/resolv.conf
@@ -220,7 +220,7 @@ if $if_configured; then
        if $have_resolvconf && [ "$reason" = NOCARRIER_ROAMING ]; then
                # avoid calling resolvconf -c on CARRIER unless we roam
                mkdir -p "$nocarrier_roaming_dir"
-               echo " " >"$nocarrier_roaming_dir/$interface"
+               printf ' \n' >"$nocarrier_roaming_dir/$interface"
                "$resolvconf" -C "$interface.*"
        elif $have_resolvconf && [ "$reason" = CARRIER ]; then
                # Not all resolvconf implementations support -c
index 7c6d3ab89ccfeba19e908d675e4f2d1d75a58107..a432d96e0b3a6d01b2b6483bcfb31cea65dfe603 100644 (file)
@@ -10,20 +10,20 @@ lookup_hostname()
        if command -v dig >/dev/null 2>&1; then
                h=$(dig +short -x $new_ip_address)
                if [ $? = 0 ]; then
-                       echo "$h" | sed 's/\.$//'
+                       printf '%s\n' "$h" | sed 's/\.$//'
                        return 0
                fi
        elif command -v host >/dev/null 2>&1; then
                h=$(host $new_ip_address)
                if [ $? = 0 ]; then 
-                       echo "$h" \
+                       printf '%s\n' "$h" \
                        | sed 's/.* domain name pointer \(.*\)./\1/'
                        return 0
                fi
        elif command -v getent >/dev/null 2>&1; then
                h=$(getent hosts $new_ip_address)
                if [ $? = 0 ]; then
-                       echo "$h" | sed 's/[^ ]* *\([^ ]*\).*/\1/'
+                       printf '%s\n' "$h" | sed 's/[^ ]* *\([^ ]*\).*/\1/'
                        return 0
                 fi
        fi
index 773eca2414670cfba5a99f3eb2d41b77997cc144..66e4bed49983260f93db9876df5d48e83a845bd1 100644 (file)
@@ -27,7 +27,7 @@ _hostname()
 {
        if [ -z "${1+x}" ]; then
                if [ -r /proc/sys/kernel/hostname ]; then
-                       read name </proc/sys/kernel/hostname && echo "$name"
+                       read name </proc/sys/kernel/hostname && printf '%s\n' "$name"
                elif command -v hostname >/dev/null 2>/dev/null; then
                        hostname
                elif sysctl kern.hostname >/dev/null 2>&1; then
@@ -41,7 +41,7 @@ _hostname()
        fi
 
        if [ -w /proc/sys/kernel/hostname ]; then
-               echo "$1" >/proc/sys/kernel/hostname
+               printf '%s\n' "$1" >/proc/sys/kernel/hostname
        elif [ -n "$1" ] && command -v hostname >/dev/null 2>&1; then
                hostname "$1"
        elif sysctl kern.hostname >/dev/null 2>&1; then
index e9c406fafc850d5aaebc26f7c6d830074f13c498..48e10cabd5d1b35119cff92659207551a4270958 100644 (file)
@@ -37,7 +37,7 @@ if [ "$r" != "down" ]; then
        for x in IPADDR INTERFACE NETMASK BROADCAST NETWORK DHCPSID GATEWAYS \
                DNSSERVERS DNSDOMAIN DNSSEARCH NISDOMAIN NISSERVERS \
                NTPSERVERS GATEWAY DNS; do
-               eval echo "$x=\'\$$x\'" >> /var/lib/dhcpcd-"$INTERFACE".info
+               eval printf '%s\\n' "$x=\'\$$x\'" >> /var/lib/dhcpcd-"$INTERFACE".info
        done
 fi
 
index 9000d37e7b72a5818b12d06ec275645333e17da5..8097a20f0fba145a196f95faa658a84c61f18dba 100644 (file)
@@ -96,9 +96,9 @@ build_ntp_conf()
        fi
 
        if [ -n "$servers" ]; then
-               echo "$signature_base${header:+ $from }$header" >> "$cf"
-               printf %s "$servers" >> "$cf"
-               echo "$signature_base_end${header:+ $from }$header" >> "$cf"
+               printf '%s\n' "$signature_base${header:+ $from }$header" >> "$cf"
+               printf '%s' "$servers" >> "$cf"
+               printf '%s\n' "$signature_base_end${header:+ $from }$header" >> "$cf"
        else
                [ -e "$ntp_conf" ] && [ -e "$cf" ] || return
        fi
@@ -117,7 +117,7 @@ add_ntp_conf()
        [ -d "$ntp_conf_dir" ] || mkdir -p "$ntp_conf_dir"
        if [ -n "$new_ntp_servers" ]; then
                for x in $(uniqify $new_ntp_servers); do
-                       echo "server $x" >> "$cf"
+                       printf '%s\n' "server $x" >> "$cf"
                done
        fi
        build_ntp_conf
index f91eb9a22761cb7d208a67c432ef57330130fbbb..3fdfd6bdf8d50f8daf23cbc279c8ea0249441d48 100644 (file)
@@ -14,7 +14,7 @@ make_yp_conf()
        [ -z "${new_nis_domain}${new_nis_servers}" ] && return 0
        cf=/etc/yp.conf."$ifname"
        rm -f "$cf"
-       echo "$signature" > "$cf"
+       printf '%s\n' "$signature" > "$cf"
        prefix=
        if [ -n "$new_nis_domain" ]; then
                if ! valid_domainname "$new_nis_domain"; then
@@ -26,13 +26,13 @@ make_yp_conf()
                if [ -n "$new_nis_servers" ]; then
                        prefix="domain $new_nis_domain server "
                else
-                       echo "domain $new_nis_domain broadcast" >> "$cf"
+                       printf '%s\n' "domain $new_nis_domain broadcast" >> "$cf"
                fi
        else
                prefix="ypserver "
        fi
        for x in $new_nis_servers; do
-               echo "$prefix$x" >> "$cf"
+               printf '%s\n' "$prefix$x" >> "$cf"
        done
        save_conf /etc/yp.conf
        cat "$cf" > /etc/yp.conf
index 017936a79532936136f9af5e898d1541122e7ba8..da5127df45570abbaa34f37baf408e3c2c7af334 100644 (file)
@@ -24,7 +24,7 @@ best_domain()
 make_yp_binding()
 {
        [ -d "$ypbind_dir" ] || mkdir -p "$ypbind_dir"
-       echo "$new_nis_domain" >"$ypbind_dir/$ifname"
+       printf '%s\n' "$new_nis_domain" >"$ypbind_dir/$ifname"
 
        if [ -z "$ypdomain_dir" ]; then
                false
@@ -34,7 +34,7 @@ make_yp_binding()
                        ncf="$cf.$ifname"
                        rm -f "$ncf"
                        for x in $new_nis_servers; do
-                               echo "$x" >>"$ncf"
+                               printf '%s\n' "$x" >>"$ncf"
                        done
                        change_file "$cf" "$ncf"
                else
index 999f2ec94a6a4b0513ef8c81a0be0b5151733340..bd1fcd263f62d3390bb031b3ead7bb2847a52db3 100644 (file)
@@ -28,7 +28,7 @@ uniqify()
                        *) result="$result${result:+ }$i";;
                esac
        done
-       echo "$result"
+       printf '%s\n' "$result"
 }
 
 # List interface config files in a directory.
@@ -58,7 +58,7 @@ trim()
        if [ -z "$var" ]; then
                # So it seems our shell doesn't support wctype(3) patterns
                # Fall back to sed
-               var=$(echo "$*" | sed -e 's/^[[:space:]]*//;s/[[:space:]]*$//')
+               var=$(printf '%s\n' "$*" | sed -e 's/^[[:space:]]*//;s/[[:space:]]*$//')
        fi
        printf %s "$var"
 }
@@ -76,7 +76,7 @@ key_get_value()
                for x do
                        while read line; do
                                case "$line" in
-                               "$key"*) echo "${line##$key}";;
+                               "$key"*) printf '%s\n' "${line##$key}";;
                                esac
                        done < "$x"
                done
@@ -100,7 +100,7 @@ remove_markers()
                                case "$line" in
                                "$m1"*) in_marker=1;;
                                "$m2"*) in_marker=0;;
-                               *) [ $in_marker = 0 ] && echo "$line";;
+                               *) [ $in_marker = 0 ] && printf '%s\n' "$line";;
                                esac
                        done < "$x"
                done
@@ -178,8 +178,8 @@ syslog()
        [ -n "$lvl" ] && shift
        [ -n "$*" ] || return 0
        case "$lvl" in
-       err|error)      echo "$interface: $*" >&2;;
-       *)              echo "$interface: $*";;
+       err|error)      printf '%s\n' "$interface: $*" >&2;;
+       *)              printf '%s\n' "$interface: $*";;
        esac
        if command -v logger >/dev/null 2>&1; then
                logger -i -p daemon."$lvl" -t dhcpcd-run-hooks "$interface: $*"
index 73532cb56f2e14f1d4ac918f308dd13efc8150f6..d8bcb87aecaaef9c4c33a5168b61a5a750f0fb64 100644 (file)
@@ -476,8 +476,9 @@ valid_domainname(char *lbl, int type)
  */
 static const char hexchrs[] = "0123456789abcdef";
 ssize_t
-print_string(char *dst, size_t len, int type, const uint8_t *data, size_t dl)
+print_string(char *dst, size_t len, int type, const void *data, size_t dl)
 {
+       const uint8_t *d = (const uint8_t *)data;
        char *odst;
        uint8_t c;
        const uint8_t *e;
@@ -485,10 +486,10 @@ print_string(char *dst, size_t len, int type, const uint8_t *data, size_t dl)
 
        odst = dst;
        bytes = 0;
-       e = data + dl;
+       e = d + dl;
 
-       while (data < e) {
-               c = *data++;
+       while (d < e) {
+               c = *d++;
                if (type & OT_BINHEX) {
                        if (dst) {
                                if (len == 0 || len == 1) {
@@ -856,7 +857,7 @@ dhcp_set_leasefile(char *leasefile, size_t len, int family,
        if (ifp->wireless) {
                ssid[0] = '-';
                print_string(ssid + 1, sizeof(ssid) - 1, OT_ESCFILE,
-                   (const uint8_t *)ifp->ssid, ifp->ssid_len);
+                   ifp->ssid, ifp->ssid_len);
        } else
                ssid[0] = '\0';
        return snprintf(leasefile, len,
index 841486bdc4c9c684c5bca81b69b60f02c8caf098..d3d3fd32fa0fa658099b408fccd2ea204ab1afc7 100644 (file)
@@ -121,7 +121,7 @@ int make_option_mask(const struct dhcp_opt *, size_t, const struct dhcp_opt *,
 
 size_t encode_rfc1035(const char *src, uint8_t *dst);
 ssize_t decode_rfc1035(char *, size_t, const uint8_t *, size_t);
-ssize_t print_string(char *, size_t, int, const uint8_t *, size_t);
+ssize_t print_string(char *, size_t, int, const void *, size_t);
 int dhcp_set_leasefile(char *, size_t, int, const struct interface *);
 
 void dhcp_envoption(struct dhcpcd_ctx *, FILE *, const char *, const char *,
index f7195bc7e6cb2ba186654f6215c283d318f6c51a..2733e91c6a78676e562cd7ee4e089de55034141f 100644 (file)
@@ -2971,7 +2971,7 @@ log_dhcp(int loglevel, const char *msg, const struct interface *ifp,
                                free(a);
                                return;
                        }
-                       print_string(tmp, tmpl, OT_STRING, (uint8_t *)a, al);
+                       print_string(tmp, tmpl, OT_STRING, a, al);
                        free(a);
                        a = tmp;
                }
index c1d309d6770320caa5847fe6661cd780fddb79b3..084b6238a2098d9d819b55318b681530fcd15b3e 100644 (file)
@@ -215,6 +215,7 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp,
        const struct interface *ifp2;
        int af;
        bool is_stdin = ifp->name[0] == '\0';
+       char if_name[sizeof(ifp->name) * 4];
        const char *if_up, *if_down;
        rb_tree_t ifaces;
        struct rt *rt;
@@ -330,7 +331,9 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp,
 #endif
 
        if (!is_stdin) {
-               if (efprintf(fp, "interface=%s", ifp->name) == -1)
+               print_string(if_name, sizeof(if_name), OT_ESCFILE, ifp->name,
+                   strlen(ifp->name));
+               if (efprintf(fp, "interface=%s", if_name) == -1)
                        goto eexit;
                if (protocols[protocol] != NULL) {
                        if (efprintf(fp, "protocol=%s", protocols[protocol]) ==
@@ -387,9 +390,11 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp,
                goto eexit;
        RB_TREE_FOREACH(rt, &ifaces)
        {
+               print_string(if_name, sizeof(if_name), OT_ESCFILE,
+                   rt->rt_ifp->name, strlen(rt->rt_ifp->name));
                if (rt != RB_TREE_MIN(&ifaces) && fprintf(fp, "%s", " ") == -1)
                        goto eexit;
-               if (fprintf(fp, "%s", rt->rt_ifp->name) == -1)
+               if (fprintf(fp, "%s", if_name) == -1)
                        goto eexit;
        }
        rt_headclear(&ifaces, AF_UNSPEC);