@@ -19,8 +19,15 @@ static int chdir_len(const char *orig, int len)
struct unix_sockaddr_context {
char *orig_dir;
+ unsigned int disallow_chdir:1;
};
+#define UNIX_SOCKADDR_CONTEXT_INIT \
+{ \
+ .orig_dir=NULL, \
+ .disallow_chdir=0, \
+}
+
static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
{
if (!ctx->orig_dir)
@@ -40,7 +47,11 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
{
int size = strlen(path) + 1;
- ctx->orig_dir = NULL;
+ if (ctx->disallow_chdir && size > sizeof(sa->sun_path)) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
if (size > sizeof(sa->sun_path)) {
const char *slash = find_last_dir_sep(path);
const char *dir;
@@ -75,7 +86,7 @@ int unix_stream_connect(const char *path)
{
int fd, saved_errno;
struct sockaddr_un sa;
- struct unix_sockaddr_context ctx;
+ struct unix_sockaddr_context ctx = UNIX_SOCKADDR_CONTEXT_INIT;
if (unix_sockaddr_init(&sa, path, &ctx) < 0)
return -1;
@@ -97,7 +108,7 @@ int unix_stream_listen(const char *path)
{
int fd, saved_errno;
struct sockaddr_un sa;
- struct unix_sockaddr_context ctx;
+ struct unix_sockaddr_context ctx = UNIX_SOCKADDR_CONTEXT_INIT;
unlink(path);
@@ -129,7 +140,9 @@ int unix_stream_listen_gently(const char *path,
int bind_successful = 0;
int saved_errno;
struct sockaddr_un sa;
- struct unix_sockaddr_context ctx;
+ struct unix_sockaddr_context ctx = UNIX_SOCKADDR_CONTEXT_INIT;
+
+ ctx.disallow_chdir = opts->disallow_chdir;
if (unix_sockaddr_init(&sa, path, &ctx) < 0)
goto fail;
@@ -7,6 +7,7 @@ int unix_stream_listen(const char *path);
struct unix_stream_listen_opts {
int listen_backlog_size;
unsigned int force_unlink_before_bind:1;
+ unsigned int disallow_chdir:1;
};
int unix_stream_listen_gently(const char *path,