Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

always replace spaces in symlinks, unless string_escape=none #4837

Merged
merged 3 commits into from Jan 11, 2017

Conversation

ddstreet
Copy link
Contributor

@ddstreet ddstreet commented Dec 5, 2016

The default when adding a symlink string is to leave spaces in the string,
but since the list of symlinks to create is space-separated, leaving
spaces in individual symlink values creates multiple symlinks, instead of
one symlink with spaces in the name; which is never what is actually
desired. This was fixed only for md and dm a long, long time ago with
commmit ee173c5 ("replace spaces in dm
and md name symlinks"), but this applies to all devices that create
symlinks; the default should always be to replace spaces, as any rules
that actually do want to specify multiple symlinks at once should manually
specify string_escape=none (or use multiple SYMLINK+="" rules), instead of
every other rule needing to specify string_escape=replace (or every other
rule introducing bugs if they don't specify string_escape=replace).

This is not a widespread problem currently because most of the rules that
create symlinks use values that are already whitespace-replaced, e.g.
both the 'scsi_id' and 'ata_id' programs already replace all whitespace
in SCSI/ATA device model/serial strings that are used to create the
disk/by-id symlinks. However new buses like NVMe don't use a separate
program; NVMe rules directly use the sysfs attr values for model and
serial strings, which can contain spaces, and break symlinks when they
do contain spaces.

Fixes: #4833

@poettering poettering added the udev label Dec 5, 2016
@kaysievers
Copy link
Contributor

Hmm, that stuff is there since day one of udev, in the early days it was the only way to create multiple links. Not that links separated by space was ever a good idea, but maybe something is actually still using it. Can't we just add the escaping to the NVME rules like we did for md/dm?

@ddstreet
Copy link
Contributor Author

ddstreet commented Dec 6, 2016

Can't we just add the escaping to the NVME rules like we did for md/dm?

Because just like that "fix" only fixed it for md/dm, doing the same again would only fix it for NVMe, not for any other rule that creates symlinks. So this problem will keep happening in the future as as more rules are added that encounter the same bug, and as more people use devices with spaces in fields used for symlinks. It will be very non-obvious as to why things are failing. And, there are absolutely no rules that actually use this "feature" - are there?

Why would we keep default behavior that causes hard-to-debug problems only for select users/devices, and provides no benefit to anyone? What code (besides test cases) is actually expecting this behavior?

@martinpitt martinpitt added the ci-fails/needs-rework 🔥 Please rework this, the CI noticed an issue with the PR label Dec 6, 2016
@martinpitt
Copy link
Contributor

This also breaks test/udev-test.pl.

@ddstreet
Copy link
Contributor Author

ddstreet commented Dec 6, 2016

pull request updated to fix test/udev-test.pl test case (by using string_escape=none for tests that use spaces in SYMLINK value), and update man page clarifying that spaces in SYMLINK values will be replaced by default, unless the string_escape=none option is used.

@ddstreet
Copy link
Contributor Author

ddstreet commented Dec 6, 2016

updated pull request (with patch series of 3 patches: fix the problem, update the test cases in test/udev-test.pl, update the man page) now passes all checks. I think ci-fails/needs-rework label can be removed.

@martinpitt martinpitt removed the ci-fails/needs-rework 🔥 Please rework this, the CI noticed an issue with the PR label Dec 8, 2016
@keszybz
Copy link
Member

keszybz commented Dec 11, 2016

I think we should retain existing behaviour of creating multiple symlinks when a space is present in SYMLINKS format. This is a long-standing and known behaviour. But only when it is present directly in the specified string, and not when the space comes from an expanded format.

Hence:

  • SYMLINK+='foo bar' → two symlinks 'foo' and 'bar'
  • SYMLINK+='/dev/disk/$attr{xxx}' → always one symlink
  • SYMLINK+='/dev/disk/$attr{xxx} /dev/disk/something-else-$attr{xxx}' → always two symlinks

This will allow us to catch the common mistake, while retaining compatibility. Of course behaviour will change if somebody was counting on getting multiple symlinks from an expanded pattern, but I'd say that's rather insane.

@ddstreet
Copy link
Contributor Author

SYMLINK+='foo bar' → two symlinks 'foo' and 'bar'
SYMLINK+='/dev/disk/$attr{xxx}' → always one symlink
SYMLINK+='/dev/disk/$attr{xxx} /dev/disk/something-else-$attr{xxx}' → always two symlinks

I'm +1 on that, as it will fix the real problem here (unexpected spaces in the expanded variables). Any spaces written explicitly into a SYMLINK value, not coming from variable expansion, certainly aren't unexpected spaces.

Kay et. al., is that approach acceptable? I can update my pull request if so.

@keszybz
Copy link
Member

keszybz commented Dec 17, 2016

@ddstreet can you update your PR? I don't see any opposition.

@poettering poettering added the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Dec 20, 2016
…s in dest

Instead of returning 0, which is unhelpful, return the number of chars
copied into the dest string.  This allows callers that care about that
to easily use it, instead of having to calculate the strlen.

No current users of the function check the return value, so this does not
break any existing code; it is used in the following patch.
If replace_whitespace is true, each substitution value has all its
whitespace removed/replaced by util_replace_whitespace (except the
SUBST_RESULT substitution - $result{} or %c{} - which handles spaces
itself as field separators).  All existing callers are updated to
pass false, so no functional change is made by this patch.

This is needed so the SYMLINK assignment can replace any spaces
introduced through variable substitution, becuase the SYMLINK value is
a space-separated list of symlinks to create.  Any variables that
contain spaces will thus unexpectedly change the symlink value from
a single symlink to multiple incorrectly-named symlinks.

This is used in the next patch, which enables the whitespace
replacement for SYMLINK variable substitution.
If the string_escape option is either unset or 'replace' (i.e. if it is
not 'none'), then enable whitespace replacement in SYMLINK variable
substitution values, as added in the last patch.

This will keep any whitespace that is directly contained in a SYMLINK
value, but will replace any whitespace that is added to the SYMLINK
value as a result of variable substitution (except $result/%c).

This fixes bug 4833.
@ddstreet
Copy link
Contributor Author

ddstreet commented Jan 3, 2017

can you update your PR? I don't see any opposition

I updated the pull request as discussed, to replace all whitespace in SYMLINK variable substitution values (except $result/%c substitution, as that handles spaces itself). It's a bit more code than before, but stays very close to the original behavior, while still fixing the actual bug. It doesn't require any changes to test cases, since they only (currently) test hardcoded spaces and multi-field %c substitution, which both are unaffected by this pull request (their spaces aren't replaced).

The only SYMLINK assignments that would break from this change are those that expect spaces in variable values, and thus expect a single (non-%c) variable value to create multiple symlinks; and that is an insane expectation, and nobody should be doing that.

@ddstreet
Copy link
Contributor Author

ddstreet commented Jan 6, 2017

@kaysievers any complaints/suggestions for the new patch series?

@keszybz keszybz removed the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Jan 11, 2017
@keszybz
Copy link
Member

keszybz commented Jan 11, 2017

OK, let's give this a go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

NVMe symlinks broken by spaces in NVMe model number strings
5 participants