Bug 1555464

Summary: ocf:heartbeat:exportfs: Character class in square brackets causes monitor operation to fail
Product: Red Hat Enterprise Linux 7 Reporter: Reid Wahl <nwahl>
Component: resource-agentsAssignee: Oyvind Albrigtsen <oalbrigt>
Status: CLOSED ERRATA QA Contact: cluster-qe <cluster-qe>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.4CC: agk, cluster-maint, fdinitto, mlisik, ngore, nwahl
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: resource-agents-3.9.5-125.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-10-30 11:39:23 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
exportfs_test resource with new sed string for testing
none
proposed patch
none
proposed patch
none
proposed patch nwahl: review?

Description Reid Wahl 2018-03-14 18:43:19 UTC
Description of problem:
In the ocf:heartbeat:exportfs resource agent, the use of a character class list in square brackets causes the monitor operation to fail. According to `man 5 exports`, this is valid wildcard syntax for an export.

    wildcards
                  Machine names may contain the wildcard characters * and ?, or may contain character class lists within [square brackets].

The start operation works fine and creates the export.
    # pcs resource create myexport ocf:heartbeat:exportfs directory=/mnt clientspec='192.168.22.2[23]' fsid=1001 --group testgroup

    # pcs resource show myexport
     Resource: myexport (class=ocf provider=heartbeat type=exportfs)
      Attributes: clientspec=192.168.22.2[23] directory=/mnt fsid=1001
      Operations: monitor interval=10 timeout=20 (myexport-monitor-interval-10)
                  start interval=0s timeout=40 (myexport-start-interval-0s)
                  stop interval=0s timeout=120 (myexport-stop-interval-0s)

    # exportfs -v
    /mnt          	192.168.22.2[23](ro,sync,wdelay,hide,no_subtree_check,fsid=1001,sec=sys,secure,root_squash,no_all_squash)

However, the monitor operation fails continuously. The resource loops through a sequence of "start success, monitor failure, stop success, start success, monitor failure..."

    # pcs status
    ...
     Resource Group: testgroup
         myLVM	(ocf::heartbeat:LVM):	Started fastvm-centos-7-4-23
         myFS	(ocf::heartbeat:Filesystem):	Started fastvm-centos-7-4-23
         myNFS	(ocf::heartbeat:nfsserver):	Started fastvm-centos-7-4-23
         myexport	(ocf::heartbeat:exportfs):	FAILED fastvm-centos-7-4-23

    Failed Actions:
    * myexport_monitor_10000 on fastvm-centos-7-4-23 'not running' (7): call=19020, status=complete, exitreason='none',
        last-rc-change='Wed Mar 14 19:22:00 2018', queued=0ms, exec=23ms

The exportfs_monitor() function calls the is_exported() function:
    204 is_exported() {
    205         local dir=$1
    206         local spec=$2
    207 
    208         # IPv6 addressed are encased in brackets that need to be removed
    209         spec=$(echo $spec | sed 's/\[//;s/\]//')
    210 
    211         exportfs |
    212                 sed -e '$! N; s/\n[[:space:]]\+/ /; t; s/[[:space:]]\+\([^[:space:]]\+\)\(\n\|$\)/ \1\2/g; P;D;' |
    213                 grep -q -x -F "$dir $spec"
    214 }

The problem is in line 209. The function strips square bracket characters from the spec before using it as a search pattern. This is because square brackets are placed around IPv6 addresses as a special designator when CREATING the export (i.e., in clientspec) but are not present when DISPLAYING an IPv6 export. For example:
    # exportfs [fe80::]/64:/var/tmp
    # exportfs -v
    /var/tmp      	fe80::/64(ro,sync,wdelay,hide,no_subtree_check,sec=sys,secure,root_squash,no_all_squash)

So it's necessary to strip square brackets before grepping for an IPv6 export.

However, this breaks IPv4 exportfs clientspecs with character class list wildcards.


Version-Release number of selected component (if applicable):
resource-agents-3.9.5-105.el7_4.6
resource-agents-3.9.5-124.el7


How reproducible:
Always


Steps to Reproduce:
# pcs resource create myLVM ocf:heartbeat:LVM volgrpname=clus_vg --group testgroup
# mkfs.xfs /dev/clus_vg/lv1
# pcs resource create myFS ocf:heartbeat:Filesystem device=/dev/clus_vg/lv1 directory=/mnt fstype=xfs --group testgroup
# pcs resource create myNFS ocf:heartbeat:nfsserver --group testgroup
# pcs resource create myexport ocf:heartbeat:exportfs directory=/mnt clientspec='192.168.22.2[23]' options=ro fsid=1001 --group testgroup


Actual results:
    # pcs status
    ...
     Resource Group: testgroup
         myLVM	(ocf::heartbeat:LVM):	Started fastvm-centos-7-4-23
         myFS	(ocf::heartbeat:Filesystem):	Started fastvm-centos-7-4-23
         myNFS	(ocf::heartbeat:nfsserver):	Started fastvm-centos-7-4-23
         myexport	(ocf::heartbeat:exportfs):	FAILED fastvm-centos-7-4-23

    Failed Actions:
    * myexport_monitor_10000 on fastvm-centos-7-4-23 'not running' (7): call=19020, status=complete, exitreason='none',
        last-rc-change='Wed Mar 14 19:22:00 2018', queued=0ms, exec=23ms


Expected results:
    # pcs status
    ...
     Resource Group: testgroup
         myLVM	(ocf::heartbeat:LVM):	Started fastvm-centos-7-4-23
         myFS	(ocf::heartbeat:Filesystem):	Started fastvm-centos-7-4-23
         myNFS	(ocf::heartbeat:nfsserver):	Started fastvm-centos-7-4-23
         myexport	(ocf::heartbeat:exportfs):	Started fastvm-centos-7-4-23


Additional info:

Comment 2 Reid Wahl 2018-03-14 18:50:57 UTC
Created attachment 1408127 [details]
exportfs_test resource with new sed string for testing

Comment 3 Reid Wahl 2018-03-14 18:57:15 UTC
Created attachment 1408129 [details]
proposed patch

Changed line 209 from:
        spec=$(echo $spec | sed 's/\[//;s/\]//')

to:
        spec=$(echo $spec | sed -r 's/^\[(.*:.*)\]/\1/')


We could alternatively remove the opening carat can change it to:
        spec=$(echo $spec | sed -r 's/\[(.*:.*)\]/\1/')


I appreciate any feedback.

Comment 4 Reid Wahl 2018-03-14 23:21:35 UTC
Upon further testing, I see that my use case is flawed -- "Wildcard characters  generally do not work on IP addresses, though they may work by accident when reverse DNS lookups fail." However, the issue would still be present if a user includes square brackets in a hostname wildcard clientspec.

Upstream, the bracket stripping has been confined to the start and end of the string.

	spec="$(echo "$OCF_RESKEY_clientspec" | sed -e 's/^\[*//' -e 's/\]*$//')"

I see two issues with this.
  1. There's no reason a user should be restricted from opening or closing the clientspec string with a character class wildcard (even though this would likely be rare in practice).
  2. This sed operation does not strip the closing bracket if an IPv6 network is specified with a CIDR netmask.
       # exportfs [fe80::]/64:/var/tmp

So my current thought is either:
        spec=$(echo $spec | sed -r 's/^\[(.*:.*)\]/\1/')
or
        spec=$(echo $spec | sed -r 's%^\[(.*:.*)\](/[0-9]+)?%\1\2%')

Comment 5 Reid Wahl 2018-03-15 00:13:55 UTC
I've submitted https://github.com/ClusterLabs/resource-agents/pull/1124 as a proposed upstream patch.

Comment 6 Reid Wahl 2018-03-22 17:13:38 UTC
Created attachment 1411802 [details]
proposed patch

Using case statement as we have now done in upstream commit https://github.com/ClusterLabs/resource-agents/commit/64d392d412ce9e14d4b33a70cb2180890db15a36.

Moved clientspec processing from is_exported() into exportfs_monitor(), as in upstream.

Comment 7 Reid Wahl 2018-03-22 17:23:54 UTC
Created attachment 1411807 [details]
proposed patch

Using case statement as we have now done in upstream commit https://github.com/ClusterLabs/resource-agents/commit/64d392d412ce9e14d4b33a70cb2180890db15a36.

Moved clientspec processing from is_exported() into exportfs_monitor(), as in upstream.

Comment 12 errata-xmlrpc 2018-10-30 11:39:23 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2018:3278