From: Ally Sommers dropbear.sh@gmail.com
Deleting the socket file is a common pattern with AF_UNIX sockets, and is analogous to unbinding.
Ugliness removed by Ralf Habacker. --- server/fd.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/server/fd.c b/server/fd.c index bb0e90d99d0..6af09f6a129 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1953,22 +1953,43 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam
if (fd->unix_fd == -1) { + if (stat( name, &st )) + { + file_set_error(); + goto error; + } + /* check for trailing slash on file path */ if ((errno == ENOENT || (errno == ENOTDIR && !(options & FILE_DIRECTORY_FILE))) && name[strlen(name) - 1] == '/') + { set_error( STATUS_OBJECT_NAME_INVALID ); + goto error; + } + /* POSIX requires that open(2) throws EOPNOTSUPP when `path` is a Unix + * socket. BSD throws EOPNOTSUPP in this case and the additional case of + * O_SHLOCK or O_EXLOCK being passed when `path` resides on a filesystem + * without lock support. Contrary to POSIX, Linux returns ENXIO in this + * case, so we also check that error code here. + */ + else if ((errno == EOPNOTSUPP || errno == ENXIO) && S_ISSOCK(st.st_mode) && (options & FILE_DELETE_ON_CLOSE)) + ; /* no error, go to regular deletion code path */ else + { file_set_error(); - goto error; + goto error; + } } }
fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen ); fd->unix_name = NULL; - fstat( fd->unix_fd, &st ); + /* st was set from the file name if the file could not be opened */ + if (fd->unix_fd != -1) + fstat( fd->unix_fd, &st ); *mode = st.st_mode;
/* only bother with an inode for normal files and directories */ - if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) + if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISSOCK(st.st_mode)) { unsigned int err; struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );