Bug 10037 - do_mknod fails to create socket file
Summary: do_mknod fails to create socket file
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 3.0.9
Hardware: All Solaris
: P5 normal (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
Depends on:
Reported: 2013-07-19 06:30 UTC by Simon Klinkert
Modified: 2013-11-05 11:20 UTC (History)
0 users

See Also:

mknod patch file (2.50 KB, application/octet-stream)
2013-07-19 06:30 UTC, Simon Klinkert
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Klinkert 2013-07-19 06:30:45 UTC
Created attachment 9065 [details]
mknod patch file


I'm observing a strange problem with rsync on Solaris/Illumos.

My command 

rsync -rlHpogt -T /tmp --block-size=4096 --inplace --delete --checksum --no-whole-file --specials /var/data /var/data2 

results into this error message (truncated path):

error: mknod "/var/data2/<many directories>/socketfile" failed: No such file or directory (2)
error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1052) [sender=3.0.9]

After lots of debugging I found out, that do_mknod() wants to create a socket file. The given variable pathname contains a 127 characters path (with many directories).

Now consider this line in do_mknod:

strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);

It copies pathname into sun_path without any length checking. The function strlcpy truncates in my case the path because sun_path is limited to 108 characters on at least Solaris/Illumos. Maybe this is a problem on Linux as well (see also: http://www.kernelsources.org/source/xref/illumos-gate/usr/src/uts/common/sys/un.h#55 and for Linux http://www.kernelsources.org/source/xref/linux/include/uapi/linux/un.h#10). The bind() call succeeds (to be honest, I don't really know why. Probably the truncated path exists as well) and then do_mknod() calls do_chmod() for the full path… which fails with ENOENT. I tested it with rsync 3.0.7 and 3.0.9 with the same result.

I attached a little patch with a workaround which seems to be working (for me). Basically, I do a chdir() to step into the deepest directory of pathname to keep the path as short as possible and after bind() I step back into the previous directory.

I guess there are better ways to fix this, but maybe somebody will help this quick workaround.

Simon Klinkert
Comment 1 Wayne Davison 2013-10-27 17:14:50 UTC
I've checked-in a fix that causes the function to return the ENAMETOOLONG error if the sun_path buffer overflows.
Comment 2 Simon Klinkert 2013-11-05 11:20:52 UTC
Returning ENAMETOOLONG is somehow clean, but on the other hand not really helpful for the user. I think it might be better to try to handle this error with chdir() and a shorter path but that seems to be a fundamental problem in rsync (3.0.9).