Skip to content

Commit 59d833c

Browse files
committed
ncm-network: Restrictions on device naming should match kernel
That is: - Maximum 15 characters (16 including null) - No whitespace - No forward-slashes - No colons (but they _are_ allowed in filenames in order to label alias IPs) While we're at it, make the regexp in the module absolute, as we're actually matching filenames there. Similar validation should also happen in the schema as only throwing errors at runtime is _really_ unfriendly.
1 parent 124f057 commit 59d833c

File tree

3 files changed

+58
-42
lines changed

3 files changed

+58
-42
lines changed

ncm-network/src/main/pan/components/network/types/network.pan

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,15 @@ type structure_network = {
5353
"gatewaydev" ? valid_interface
5454
@{Per interface network settings.
5555
These values are used to generate the /etc/sysconfig/network-scripts/ifcfg-<interface> files
56-
when using ncm-network.}
57-
"interfaces" : network_interface{}
56+
when using ncm-network.
57+
Interface names must be no more than 15 characters in and cannot contain whitespace, ".", "/" or ":".
58+
}
59+
"interfaces" : network_interface{} with {
60+
foreach (i; _; SELF) {
61+
match(i, '^[^\s\/:]{1,15}$') || error('Device name "%s" is invalid', i);
62+
};
63+
true;
64+
}
5865
"nameserver" ? type_ip[]
5966
"nisdomain" ? string(1..64) with match(SELF, '^\S+$')
6067
@{Setting nozeroconf to true stops an interface from being assigned an automatic address in the 169.254.0.0 subnet.}

ncm-network/src/main/perl/network.pm

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ use CAF::FileEditor;
9595
use CAF::FileWriter;
9696
use CAF::Path 17.7.0;
9797
use NetAddr::IP;
98+
use File::Basename;
9899

99100
use POSIX qw(WIFEXITED WEXITSTATUS);
100101
use Readonly;
@@ -153,25 +154,16 @@ Readonly my $HARDWARE_PATH => '/hardware/cards/nic';
153154

154155
# Regexp for the supported ifcfg-<device> devices.
155156
# $1 must match the device name
157+
# Note that device names cannot contain ":", but the filenames generated may use ":" to delimit named alias IPs
156158
Readonly my $DEVICE_REGEXP => qr{
159+
^
160+
(?:ifcfg|route6?|rule6?)
157161
- # separator from e.g. ifcfg or route
158162
( # start whole match group $1
159163
( # start devicename group $2
160-
(?:
161-
eth|seth|em|
162-
bond|br|ovirtmgmt|
163-
vlan|usb|vxlan|
164-
ib|
165-
tun|
166-
p\d+p|
167-
en(?:
168-
o(?:\d+d)?| # onboard
169-
(?:p\d+)?s(?:\d+f)?(?:\d+d)? # [pci]slot[function][device]
170-
)(?:\d+np)? # [partition]
171-
)\d+| # mandatory numbering
172-
enx[[:xdigit:]]{12} # enx MAC address
164+
[^\s_:.]+
173165
)
174-
(?:_(\w+))? # opional suffix group $3
166+
(?:_(\w+))? # optional suffix group $3
175167
(?:\.\d+)? # optional VLAN
176168
(?::\w+)? # optional alias
177169
) # end whole matching group
@@ -222,26 +214,34 @@ sub _is_executable
222214
return -x $fn;
223215
}
224216

225-
# Given the configuration ifcfg/route[6]/rule[6] filename,
217+
# Given the configuration ifcfg/route[6]/rule[6] file,
226218
# Determine if this is a valid interface for ncm-network to manage,
227219
# Return arrayref tuple [interface name, ifdown/ifup name] when valid,
228220
# undef otherwise.
229221
sub is_valid_interface
230222
{
231-
my ($self, $filename) = @_;
223+
my ($self, $filepath) = @_;
224+
225+
my $filename = basename($filepath);
232226

233227
# Very primitive, based on regex only
234-
# Not even the full filename (eg ifcfg) or anything
235228
if ($filename =~ m/$DEVICE_REGEXP/) {
236229
my $ifupdownname = $1;
237-
my $name = $2;
230+
my $devicename = $2;
231+
232+
if (length($devicename) >= 16) {
233+
return;
234+
};
235+
238236
my $suffix = $3;
239237
if ($suffix && $suffix =~ m/^\d+$/) {
240-
$name .= "_$suffix";
241-
$self->verbose("Found digit-only suffix $suffix for device $name ($filename), ",
242-
"added it to the interface name");
238+
$devicename .= "_$suffix";
239+
$self->verbose(
240+
"Found digit-only suffix $suffix for device $devicename ($filename), added it to the interface name"
241+
);
243242
}
244-
return [$name, $ifupdownname];
243+
244+
return [$devicename, $ifupdownname];
245245
} else {
246246
return;
247247
};

ncm-network/src/test/perl/valid_interfaces.t

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,36 @@ my @valid_ifs = qw(eth0 seth1 em2 em2_2
2020
enxAABBCCDDEEFF);
2121

2222
foreach my $valid (@valid_ifs) {
23-
foreach my $type (qw(ifcfg route)) {
24-
is_deeply($cmp->is_valid_interface("$basedir/$type-$valid"), [$valid, $valid],
25-
"valid interface $valid from $type");
26-
is_deeply($cmp->is_valid_interface("$basedir/$type-$valid.123"), [$valid, "$valid.123"],
27-
"valid interface $valid from $type with vlan");
28-
is_deeply($cmp->is_valid_interface("$basedir/$type-$valid:alias"), [$valid, "$valid:alias"],
29-
"valid interface $valid from $type with alias");
30-
is_deeply($cmp->is_valid_interface("$basedir/$type-$valid.456:myalias"), [$valid, "$valid.456:myalias"],
31-
"valid interface $valid from $type with vlan and alias");
32-
is_deeply($cmp->is_valid_interface("$basedir/$type-${valid}_whatever.456:myalias"),
33-
[$valid =~ m/^(.*)_\d+$/ ? $1 : $valid, "${valid}_whatever.456:myalias"],
34-
"valid interface $valid from $type with suffix, vlan and alias");
23+
foreach my $type (qw(ifcfg route route6)) {
24+
is_deeply(
25+
$cmp->is_valid_interface("$basedir/$type-$valid"), [$valid, $valid],
26+
"valid interface $valid from $type"
27+
);
28+
is_deeply(
29+
$cmp->is_valid_interface("$basedir/$type-$valid.123"), [$valid, "$valid.123"],
30+
"valid interface $valid from $type with vlan"
31+
);
32+
is_deeply(
33+
$cmp->is_valid_interface("$basedir/$type-$valid:alias"), [$valid, "$valid:alias"],
34+
"valid interface $valid from $type with alias"
35+
);
36+
is_deeply(
37+
$cmp->is_valid_interface("$basedir/$type-$valid.456:myalias"), [$valid, "$valid.456:myalias"],
38+
"valid interface $valid from $type with vlan and alias"
39+
);
40+
is_deeply(
41+
$cmp->is_valid_interface("$basedir/$type-${valid}_whatever.456:myalias"),
42+
[$valid =~ m/^(.*)_\d+$/ ? $1 : $valid, "${valid}_whatever.456:myalias"],
43+
"valid interface $valid from $type with suffix, vlan and alias"
44+
);
3545
};
3646
};
3747

38-
my @invalid_ifs = ('madeup', # arbitrary name
39-
'eth', # no number
40-
'enop1', # onboard with pci
41-
'enp2', # pci without slot
42-
'enxAABBCCDDEEF', # too short MAC
43-
'enxAABBCCDDEEFFF', # too long mac
48+
my @invalid_ifs = (
49+
'contains/slash',
50+
'too-many-characters',
51+
'multiple::colons',
52+
'space in_name',
4453
);
4554
foreach my $invalid (@invalid_ifs) {
4655
ok(!defined($cmp->is_valid_interface("$basedir/ifcfg-$invalid")), "invalid interface $invalid");

0 commit comments

Comments
 (0)