Deployer: When control path = 104 'the too long for Unix domain socket' is fired.

Created on 4 Sep 2017  路  15Comments  路  Source: deployphp/deployer

| Q | A
| ----------------- | ---
| Issue Type | Bug
| Deployer Version | 6.0.3
| Local Machine OS | MAC
| Remote Machine OS | ?

Description

If you're reporting a bug, please include following information

Steps to reproduce

Content of deploy.php

When https://github.com/deployphp/deployer/blob/15274524b28c94e5967fa509a91680f599ddd23d/src/Ssh/Arguments.php#L128 equals to

Output log

With enabled option for verbose output -vvv.

  [Deployer\Exception\RuntimeException (-1)]
  The command "rm -f /srv/http/<username>/.dep/deploy.lock" failed.
  Exit Code: -1 (Unknown error)
  Host Name: acceptance
  ================
  unix_listener: "<path with 104 chars>" too long for Unix domain
   socket
bug

Most helpful comment

Hi :raising_hand_man:,

A quick fix for those who are stuck: you can disable ssh multiplexing by adding the snippet below into your deployer config:

set('ssh_multiplexing', false);

Also, since @giraz82 describes that this is about a socket. Would it be an option to place the socket file in another directory? /var/run would be preferred, but since we'll run into permission problems I'd say that /tmp would also suffice.

All 15 comments

Any news about this?
I think there is a bug in how the $controlPath length is tested against the maximum acceptable value (104) for two reasons:
At the beginning

$controlPath = "~/.ssh/deployer_$connectionData";

but the real socket path is something like this:

/Users/name.surname/.ssh/[email protected]

with the real home path instead of "~" and with a I-think-random-generated string at the end.

So, in my local machine, according to my username, I tried with a more realistic

while (strlen($controlPath) > 65);

and now the switch falls inside first case:

case 1:
    $controlPath = "~/.ssh/deployer_%C";

and so deploy works correctly, because the socket generated now is something like:

deployer_e9749a1af24a8814ecceff249c6e338c61c1a117

that is shorter than the one created before.

Is it possible to fix this behavior? Thank you

Hi, yes it pissible to fix, kets use real path instead of ~

Hi :raising_hand_man:,

A quick fix for those who are stuck: you can disable ssh multiplexing by adding the snippet below into your deployer config:

set('ssh_multiplexing', false);

Also, since @giraz82 describes that this is about a socket. Would it be an option to place the socket file in another directory? /var/run would be preferred, but since we'll run into permission problems I'd say that /tmp would also suffice.

Writing the socket into a /tmp folder sounds like a terrible idea (security). I think it should be fixed in https://github.com/deployphp/deployer/blob/master/src/Ssh/Arguments.php#L130. This should probably take into consider the real path (as mentioned by @antonmedv), since the real path is the path that seems to be character counted.

Edit: Do I read the code correctly, that it's just simply checking if those hardcoded, non-evaluated strings are less then 104 characters long? It's not substituting those ControlPath variables, is it? 馃槦

It uses ssh itself to replase them.

@nvaken I'm wondering about the potential security flaw when placing a file in the /tmp directory. If you give the file the right permissions e.g. 0600 I'm convinced that no other user is able to read or write in the socket. Am I missing something ? :open_mouth:

@antonmedv how does generateControlPath() replace them with SSH before checking up on the length?

@nstapelbroek I'm not entirely sure what the security implications the /tmp folder brings. Though, there are some sources (only one I can find now is wikibooks.org) which imply that it would be a bad idea. Also, I'm not sure about showing files with the usernames / hostnames / ports in the /tmp folder. Though, might not be as bad as I initially thought?

@nvaken you are right, it doesnt check it using ssh. MAybe remove them from generateControlPath completely then?

Only thing I can think of is that the method could construct the paths itself? I do think the length check is valuable by itself, if it worked correctly. I might be able to create a patch later this week as a suggestion, not sure yet though.

Alright, it's been a bit more then a week. 馃槵

I've just debugged the generateControlPath() a bit. I have a hostname that is 62 characters long, on port 22. Therefor $controlPath (which is checked on string length) becomes: deployer_[a-hostname-of-62-characters]:22, which results in a strlen of 74 which is easily within the 104 limit. Although, this does not take in account that this file will appended with a connection hash which, strangely isn't actually appended to the file. Which might result in the following: deployer_[a-hostname-of-62-characters]:22.H0tQPCvXD48DN6lN, but again, even this should be within the 104 limit, so what's up?

UNIX_PATH_MAX, that's what's up. After a bit of Googling this defines the max length for the domain sockets, it appears that this might be a bit different per OS. As far as I can tell, this is 104 for Mac OS and 108 for Linux. So, still, not less than what we're checking on; 104. After some testing and manually creating control paths, I found out that this includes the entire, expanded, absolute path to the file.

So, I've been looking if it's possible to evaluate OpenSSH tokens like %C without starting an actual connection, but I've been unable to find a solution for this. Therefor, I think it'd be best if we just keep calculating, but keep in mind that;

  1. The absolute path to the home dir needs to be included in the total length
  2. The prepended length (which seems to be 16) of the connection hash has to be included in the total length.

Also, I noticed that most of the case's do not use the .ssh subfolder, which I guess is a mistake.

I've worked out above and will be submitting a pull request later.

It'll probably be good if someone reviews my fix in detail. I think I've done it right, though I have to say I'm not a SSH Multiplexing guru. Also, this fix includes an additional fix which adds ~/.ssh to all possible paths, which I think should be in place, though, please review.

Just when this pull requests came to merge, I noticed some redundancies in the cases. REst assured, nothing that would break stuff though.

This is fine...

                case 1:
                    $controlPath = "$homeDir/.ssh/deployer_%C";
                    break;

Sure, no problem, but I think case 1 will almost always be shorter then 2

                case 2:
                    $controlPath = "$homeDir/.ssh/deployer_$connectionData";
                    break;

This doesn't make any sense, especially since I've added /.ssh in this path and is now identical to 1. Nothing breaking though...

                case 3:
                    $controlPath = "$homeDir/.ssh/deployer_%C";
                    break;

Sure, this is 5 characters shorter then 1.

                case 4:
                    $controlPath = "$homeDir/.ssh/mux_%C";
                    break;

This is the same as 2.

                default:
                    $controlPath = "$homeDir/.ssh/deployer_$connectionData";

I'd suggest removing case 2 and 3. Does that make sense to you @antonmedv? If so, I'll create a small update for that.

Yes, make sense. Maybe we can do some really short name in case of 3?

Not sure. I guess mux_ has been an acronym for multiplexer is quite short in itself. I don't think we are able to use _no_ prefix and %C is "only" 16 characters, so that totals to a 20 character filename which I think leaves plenty of space for the rest of the absolute path. Assuming a home directory structure of /users/[username]/ we leave room for a ~70 character username, seems plenty to me.

I'll try baking a update for the above today.

I guess this issue can now be closed @antonmedv?

Was this page helpful?
0 / 5 - 0 ratings