Skip to contentSkip to conversation

Prevent vif-bridge from adding user-created taps to a bridge

PATCH In review Jim Fehlig 2 participants 7 messages Oct 25, 2011 – Oct 27, 2011

lore
Share & tools
lore

Jim Fehlig

author
#0 lore raw

PATCH 1/1 Prevent vif-bridge from adding user-created taps to a bridge

I previously sent this from my @suse.com mail address without having subscribed it. Sending again now that I have done so...

I received a report that vif-bridge adds any tap interface to a bridge, regardless if xen is running and who created the tap interface. E.g.

# tunctl -p -t tap42

will cause vif-bridge to be executed as per the following rule in xen-backend.rules

SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"

I'm not sure how to improve the rule to prevent execution of vif-setup in this case. But it seems better to handle it in vif-bridge anyhow, by not connecting the interface to a bridge if there is no corresponding info in xenstore. Something along the lines of the attached quick patch. Comments?

Thanks!
Jim

# HG changeset patch
# User Jim Fehlig <[email protected]>
# Date 1319581952 21600
# Node ID 74da2a3a1db1476d627f42e4a99e9e720cc6774d
# Parent 6c583d35d76dda2236c81d9437ff9d57ab02c006
Prevent vif-bridge from adding user-created tap interfaces to a bridge

Exit vif-bridge script if there is no device info in xenstore, preventing it from adding user-created taps to bridges.

tools/hotplug/Linux/vif-bridge +7 -0
diff -r 6c583d35d76d -r 74da2a3a1db1 tools/hotplug/Linux/vif-bridge
@@ -31,6 +31,13 @@
 
 dir=$(dirname "$0")
 . "$dir/vif-common.sh"
+
+domu=$(xenstore_read_default "$XENBUS_PATH/domain" "")
+if [ -z "$domu" ]
+then
+    log debug "No device details in $XENBUS_PATH, exiting."
+    exit 0
+fi
 
 bridge=${bridge:-}
 bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#1 lore raw
Quoted 10 lines · Jim Fehlig

I previously sent this from my @suse.com mail address without having subscribed it. Sending again now that I have done so...

I received a report that vif-bridge adds any tap interface to a bridge, regardless if xen is running and who created the tap interface. E.g.

# tunctl -p -t tap42

will cause vif-bridge to be executed as per the following rule in xen-backend.rules

Oh dear.

Quoted 8 lines

SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"

I'm not sure how to improve the rule to prevent execution of vif-setup in this case. But it seems better to handle it in vif-bridge anyhow, by not connecting the interface to a bridge if there is no corresponding info in xenstore. Something along the lines of the attached quick patch. Comments?

I think overall your change is an improvement, some thoughts:

For a tap device XENBUS_PATH is set in vif-common.sh:

        elif [ "$type_if" = tap ]; then
            # Check presence of compulsory args.
            : ${INTERFACE:?}
        
            # Get xenbus_path from device name.
            # The name is built like that: "tap${domid}.${devid}".
            dev_=${dev#tap}
            domid=${dev_%.*}
            devid=${dev_#*.}
        
            XENBUS_PATH="/local/domain/0/backend/vif/$domid/$devid"
        fi

Could there be false positives from this? Perhaps we should be more aggressively checking for the tapX.Y, where X and Y are integers, format as well? (that's not foolproof either though).

Perhaps the toolstack could write something to xenstore containing the literal tap device name which it asked qemu for? Then we can simply read it back here, e.g. /libxl/tap/0/tapX.Y -> $XENBUS_PATH (0 being the backend domain and the content being the xenbus path so we don't need to magic it up).

Ian.

author
#2 lore raw
Quoted 43 lines · Ian Campbell
Quoted 11 lines · Jim Fehlig

I previously sent this from my @suse.com mail address without having subscribed it. Sending again now that I have done so...

I received a report that vif-bridge adds any tap interface to a bridge, regardless if xen is running and who created the tap interface. E.g.

# tunctl -p -t tap42

will cause vif-bridge to be executed as per the following rule in xen-backend.rules

Oh dear.

Quoted 9 lines

SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"

I'm not sure how to improve the rule to prevent execution of vif-setup in this case. But it seems better to handle it in vif-bridge anyhow, by not connecting the interface to a bridge if there is no corresponding info in xenstore. Something along the lines of the attached quick patch. Comments?

I think overall your change is an improvement, some thoughts:

For a tap device XENBUS_PATH is set in vif-common.sh:

        elif [ "$type_if" = tap ]; then
            # Check presence of compulsory args.
            : ${INTERFACE:?}
        
            # Get xenbus_path from device name.
            # The name is built like that: "tap${domid}.${devid}".
            dev_=${dev#tap}
            domid=${dev_%.*}
            devid=${dev_#*.}
        
            XENBUS_PATH="/local/domain/0/backend/vif/$domid/$devid"
        fi
Quoted 1 line

Could there be false positives from this?

Hmm, yes, I think it is possible.

Quoted 4 lines

Perhaps we should be more
aggressively checking for the tapX.Y, where X and Y are integers, format as well? (that's not foolproof either though).

Yeah, I don't think that buys us much.

Quoted 6 lines

Perhaps the toolstack could write something to xenstore containing the literal tap device name which it asked qemu for? Then we can simply read it back here, e.g. /libxl/tap/0/tapX.Y -> $XENBUS_PATH (0 being the backend domain and the content being the xenbus path so we don't need to magic it up).

I think this is a better approach. But generally, we don't ask qemu for a tap device right? Only when using an emulated NIC afaik. It seems I should be able to write the info you suggested to xenstore in libxl_device_nic_add(). The front and back paths and their contents are already being created there.

Thanks,
Jim

author
#3 lore raw
Quoted 44 lines · Jim Fehlig
Quoted 42 lines · Ian Campbell
Quoted 12 lines · Jim Fehlig

I previously sent this from my @suse.com mail address without having subscribed it. Sending again now that I have done so...

I received a report that vif-bridge adds any tap interface to a bridge, regardless if xen is running and who created the tap interface. E.g.

# tunctl -p -t tap42

will cause vif-bridge to be executed as per the following rule in xen-backend.rules

Oh dear.

Quoted 10 lines

SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"

I'm not sure how to improve the rule to prevent execution of vif-setup in this case. But it seems better to handle it in vif-bridge anyhow, by not connecting the interface to a bridge if there is no corresponding info in xenstore. Something along the lines of the attached quick patch. Comments?

I think overall your change is an improvement, some thoughts:

For a tap device XENBUS_PATH is set in vif-common.sh:

        elif [ "$type_if" = tap ]; then
            # Check presence of compulsory args.
            : ${INTERFACE:?}
        
            # Get xenbus_path from device name.
            # The name is built like that: "tap${domid}.${devid}".
            dev_=${dev#tap}
            domid=${dev_%.*}
            devid=${dev_#*.}
Quoted 8 lines
Quoted 5 lines
            XENBUS_PATH="/local/domain/0/backend/vif/$domid/$devid"
        fi

Could there be false positives from this?

Hmm, yes, I think it is possible.

On second thought, maybe not. A false positive would mean two tap devices with the same name right? AFAICT, that's not permitted.

Quoted 16 lines
Quoted 6 lines

Perhaps we should be more
aggressively checking for the tapX.Y, where X and Y are integers, format as well? (that's not foolproof either though).

Yeah, I don't think that buys us much.

Quoted 6 lines

Perhaps the toolstack could write something to xenstore containing the literal tap device name which it asked qemu for? Then we can simply read it back here, e.g. /libxl/tap/0/tapX.Y -> $XENBUS_PATH (0 being the backend domain and the content being the xenbus path so we don't need to magic it up).

The toolstack already writes something in xenstore, namely $XENBUS_PATH/bridge. IMO, the problem is in vif-bridge

bridge=${bridge:-}
bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")

if [ -z "$bridge" ]
then
bridge=$(brctl show | cut -d "
" -f 2 | cut -f 1)

if [ -z "$bridge" ]
then
fatal "Could not find bridge, and none was specified"
fi
else
...

If the toolstack hasn't written anything to xenstore, vif-bridge happily connects the tap device to the first bridge it finds. Shouldn't vif-bridge just exit if no bridge is specified?

Thanks,
Jim

#4 lore raw
Quoted 48 lines · Jim Fehlig
Quoted 47 lines · Jim Fehlig
Quoted 45 lines · Ian Campbell
Quoted 12 lines · Jim Fehlig

I previously sent this from my @suse.com mail address without having subscribed it. Sending again now that I have done so...

I received a report that vif-bridge adds any tap interface to a bridge, regardless if xen is running and who created the tap interface. E.g.

# tunctl -p -t tap42

will cause vif-bridge to be executed as per the following rule in xen-backend.rules

Oh dear.

Quoted 10 lines

SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"

I'm not sure how to improve the rule to prevent execution of vif-setup in this case. But it seems better to handle it in vif-bridge anyhow, by not connecting the interface to a bridge if there is no corresponding info in xenstore. Something along the lines of the attached quick patch. Comments?

I think overall your change is an improvement, some thoughts:

For a tap device XENBUS_PATH is set in vif-common.sh:

        elif [ "$type_if" = tap ]; then
            # Check presence of compulsory args.
            : ${INTERFACE:?}
        
            # Get xenbus_path from device name.
            # The name is built like that: "tap${domid}.${devid}".
            dev_=${dev#tap}
            domid=${dev_%.*}
            devid=${dev_#*.}
        
            XENBUS_PATH="/local/domain/0/backend/vif/$domid/$devid"
        fi
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

Could there be false positives from this?

Hmm, yes, I think it is possible.

On second thought, maybe not. A false positive would mean two tap devices with the same name right? AFAICT, that's not permitted.

Oh right, we are given $dev aren't we.

Quoted 18 lines
Quoted 17 lines
Quoted 7 lines

Perhaps we should be more
aggressively checking for the tapX.Y, where X and Y are integers, format as well? (that's not foolproof either though).

Yeah, I don't think that buys us much.

Quoted 6 lines

Perhaps the toolstack could write something to xenstore containing the literal tap device name which it asked qemu for? Then we can simply read it back here, e.g. /libxl/tap/0/tapX.Y -> $XENBUS_PATH (0 being the backend domain and the content being the xenbus path so we don't need to magic it up).

Quoted 2 lines

The toolstack already writes something in xenstore, namely $XENBUS_PATH/bridge.

XENBUS_PATH here is really the vif backend path, not the tap path, although they in some way are aliased so in many cases that ok. I was just thinking it might be useful to have a backend space for the tap device only (since the guest can see the vif backend dir).

Quoted 17 lines

IMO, the problem is in vif-bridge

bridge=${bridge:-}
bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")

if [ -z "$bridge" ]
then
bridge=$(brctl show | cut -d "
" -f 2 | cut -f 1)

if [ -z "$bridge" ]
then
fatal "Could not find bridge, and none was specified"
fi
else
...

Quoted 3 lines

If the toolstack hasn't written anything to xenstore, vif-bridge happily connects the tap device to the first bridge it finds. Shouldn't vif-bridge just exit if no bridge is specified?

I think that behaviour is historical (which isn't to say it's correct). FWIW xl defaults to writing xenbr0. I don't know what xend does.

Ian.

author
#5 lore raw
Quoted 87 lines · Ian Campbell
Quoted 54 lines · Jim Fehlig
Quoted 52 lines · Jim Fehlig
Quoted 49 lines · Ian Campbell
Quoted 13 lines · Jim Fehlig

I previously sent this from my @suse.com mail address without having subscribed it. Sending again now that I have done so...

I received a report that vif-bridge adds any tap interface to a bridge, regardless if xen is running and who created the tap interface. E.g.

# tunctl -p -t tap42

will cause vif-bridge to be executed as per the following rule in xen-backend.rules

Oh dear.

Quoted 11 lines

SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"

I'm not sure how to improve the rule to prevent execution of vif-setup in this case. But it seems better to handle it in vif-bridge anyhow, by not connecting the interface to a bridge if there is no corresponding info in xenstore. Something along the lines of the attached quick patch. Comments?

I think overall your change is an improvement, some thoughts:

For a tap device XENBUS_PATH is set in vif-common.sh:

        elif [ "$type_if" = tap ]; then
            # Check presence of compulsory args.
            : ${INTERFACE:?}
        
            # Get xenbus_path from device name.
            # The name is built like that: "tap${domid}.${devid}".
            dev_=${dev#tap}
            domid=${dev_%.*}
            devid=${dev_#*.}
        
            XENBUS_PATH="/local/domain/0/backend/vif/$domid/$devid"
        fi
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines

Could there be false positives from this?

Hmm, yes, I think it is possible.

On second thought, maybe not. A false positive would mean two tap devices with the same name right? AFAICT, that's not permitted.

Oh right, we are given $dev aren't we.

Quoted 19 lines
Quoted 19 lines
Quoted 8 lines

Perhaps we should be more
aggressively checking for the tapX.Y, where X and Y are integers, format as well? (that's not foolproof either though).

Yeah, I don't think that buys us much.

Quoted 7 lines

Perhaps the toolstack could write something to xenstore containing the literal tap device name which it asked qemu for? Then we can simply read it back here, e.g. /libxl/tap/0/tapX.Y -> $XENBUS_PATH (0 being the backend domain and the content being the xenbus path so we don't need to magic it up).

Quoted 9 lines
Quoted 3 lines

The toolstack already writes something in xenstore, namely $XENBUS_PATH/bridge.

XENBUS_PATH here is really the vif backend path, not the tap path, although they in some way are aliased so in many cases that ok. I was just thinking it might be useful to have a backend space for the tap device only (since the guest can see the vif backend dir).

So you prefer this approach to solving the problem?

Quoted 18 lines
Quoted 18 lines

IMO, the problem is in vif-bridge

bridge=${bridge:-}
bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")

if [ -z "$bridge" ]
then
bridge=$(brctl show | cut -d "
" -f 2 | cut -f 1)

if [ -z "$bridge" ]
then
fatal "Could not find bridge, and none was specified"
fi
else
...

Quoted 7 lines
Quoted 4 lines

If the toolstack hasn't written anything to xenstore, vif-bridge happily connects the tap device to the first bridge it finds. Shouldn't vif-bridge just exit if no bridge is specified?

I think that behaviour is historical (which isn't to say it's correct).

Connecting the device to an arbitrary bridge seems dangerous to me. What if the bridge is on a sensitive VLAN?

Quoted 2 lines

FWIW xl defaults to writing xenbr0. I don't know what xend does.

xend writes nothing to that node if bridge is not specified in the vif config :-(. I suppose that is the reason for the hack in vif-bridge, which was a bad fix IMO.

Thanks,
Jim

Quoted 3 lines

Ian.

#6 lore raw
Quoted 7 lines · Jim Fehlig
Quoted 5 lines

XENBUS_PATH here is really the vif backend path, not the tap path, although they in some way are aliased so in many cases that ok. I was just thinking it might be useful to have a backend space for the tap device only (since the guest can see the vif backend dir).

So you prefer this approach to solving the problem?

It's probably the right thing to do long term but your initial patch seems like a reasonable enough fix right now.

Ian.

Quoted 42 lines
Quoted 19 lines
Quoted 19 lines

IMO, the problem is in vif-bridge

bridge=${bridge:-}
bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge")

if [ -z "$bridge" ]
then
bridge=$(brctl show | cut -d "
" -f 2 | cut -f 1)

if [ -z "$bridge" ]
then
fatal "Could not find bridge, and none was specified"
fi
else
...

Quoted 7 lines
Quoted 4 lines

If the toolstack hasn't written anything to xenstore, vif-bridge happily connects the tap device to the first bridge it finds. Shouldn't vif-bridge just exit if no bridge is specified?

I think that behaviour is historical (which isn't to say it's correct).

Connecting the device to an arbitrary bridge seems dangerous to me. What if the bridge is on a sensitive VLAN?

Quoted 2 lines

FWIW xl defaults to writing xenbr0. I don't know what xend does.

xend writes nothing to that node if bridge is not specified in the vif config :-(. I suppose that is the reason for the hack in vif-bridge, which was a bad fix IMO.

Thanks,
Jim

Quoted 3 lines

Ian.