]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-rules: all values can contain escaped double quotes now (#6890)
authorFranck Bui <fbui@suse.com>
Thu, 28 Sep 2017 06:53:46 +0000 (08:53 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 28 Sep 2017 06:53:46 +0000 (08:53 +0200)
This is primarly useful to support escaped double quotes in PROGRAM or
IMPORT{program} directives.

The only possibilty before this patch was to use an external shell script but
this seems too cumbersome for trivial logics such as

 PROGRAM=="/bin/sh -c 'FOO=\"%s{model}\"; echo ${FOO:0:4}'"

or any similar shell constructs that needs to deals with patterns including
whitespaces.

As it's the case for single quote and for directives running a program, words
within escaped double quotes will be considered as a single argument.

Fixes: #6835
src/udev/udev-event.c
src/udev/udev-rules.c
test/udev-test.pl

index 09f7baf08220460d97d496850a26ebea5977d056..4cadff7f6fa0881e18c2fe5ebeb2f078a6fb8c02 100644 (file)
@@ -720,10 +720,12 @@ int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]) {
 
         pos = cmd;
         while (pos != NULL && pos[0] != '\0') {
-                if (pos[0] == '\'') {
-                        /* do not separate quotes */
+                if (IN_SET(pos[0], '\'', '"')) {
+                        /* do not separate quotes or double quotes */
+                        char delim[2] = { pos[0], '\0' };
+
                         pos++;
-                        argv[i] = strsep(&pos, "\'");
+                        argv[i] = strsep(&pos, delim);
                         if (pos != NULL)
                                 while (pos[0] == ' ')
                                         pos++;
index 2c5bcc38cdde2089cad66d47ff28a9048c817a2a..5ab697e3994f623b0c6b5bed82bb3b0467ac712f 100644 (file)
@@ -718,6 +718,7 @@ static void attr_subst_subdir(char *attr, size_t len) {
 static int get_key(struct udev *udev, char **line, char **key, enum operation_type *op, char **value) {
         char *linepos;
         char *temp;
+        unsigned i, j;
 
         linepos = *line;
         if (linepos == NULL || linepos[0] == '\0')
@@ -793,14 +794,25 @@ static int get_key(struct udev *udev, char **line, char **key, enum operation_ty
         *value = linepos;
 
         /* terminate */
-        temp = strchr(linepos, '"');
-        if (!temp)
-                return -1;
-        temp[0] = '\0';
-        temp++;
+        for (i = 0, j = 0; ; i++, j++) {
+
+                if (linepos[i] == '"')
+                        break;
+
+                if (linepos[i] == '\0')
+                        return -1;
+
+                /* double quotes can be escaped */
+                if (linepos[i] == '\\')
+                        if (linepos[i+1] == '"')
+                                i++;
+
+                linepos[j] = linepos[i];
+        }
+        linepos[j] = '\0';
 
         /* move line to next key */
-        *line = temp;
+        *line = linepos + i + 1;
         return 0;
 }
 
index 7e334790041c2209ac5a9e816b0ad5bef78728b0..0d348e5c08c360c04986832a6f6ecaac65c356be 100755 (executable)
@@ -330,6 +330,30 @@ EOF
                 exp_name        => "foo7" ,
                 rules           => <<EOF
 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4'   'foo5   foo6   foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
+EOF
+        },
+        {
+                desc            => "program arguments combined with escaped double quotes, part 1",
+                devpath         => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
+                exp_name        => "foo2" ,
+                rules           => <<EOF
+SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf %%s \\\"foo1 foo2\\\" | grep \\\"foo1 foo2\\\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
+EOF
+        },
+        {
+                desc            => "program arguments combined with escaped double quotes, part 2",
+                devpath         => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
+                exp_name        => "foo2" ,
+                rules           => <<EOF
+SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c \\\"printf %%s 'foo1 foo2' | grep 'foo1 foo2'\\\"", KERNEL=="sda5", SYMLINK+="%c{2}"
+EOF
+        },
+        {
+                desc            => "program arguments combined with escaped double quotes, part 3",
+                devpath         => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
+                exp_name        => "foo2" ,
+                rules           => <<EOF
+SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf \\\"%%s %%s\\\" \\\"foo1 foo2\\\" \\\"foo3\\\"| grep \\\"foo1 foo2\\\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
 EOF
         },
         {