UDS: terminate canonical path string

When you provided a string with junk after the terminating nul to a
UNIX domain socket and used bind(2), the canonical path function would
not properly terminate the new string. This caused VFS to return
ENAMETOOLONG on an otherwise valid path name.

Test case is added to test56.

Change-Id: I883b6be23d9e4ea13c3cee28cbb3726343df037f
This commit is contained in:
Thomas Veerman 2013-03-08 14:17:13 +00:00
parent 08283d6d4d
commit 76ddef10da
2 changed files with 18 additions and 3 deletions

View file

@ -760,14 +760,14 @@ struct fproc *rfp;
} }
/* now we have to retrieve the name of the parent directory */ /* now we have to retrieve the name of the parent directory */
if (get_name(parent_dir, dir_vp, component) != OK) { if ((r = get_name(parent_dir, dir_vp, component)) != OK) {
unlock_vnode(parent_dir); unlock_vnode(parent_dir);
unlock_vmnt(parent_vmp); unlock_vmnt(parent_vmp);
unlock_vnode(dir_vp); unlock_vnode(dir_vp);
unlock_vmnt(dir_vmp); unlock_vmnt(dir_vmp);
put_vnode(parent_dir); put_vnode(parent_dir);
put_vnode(dir_vp); put_vnode(dir_vp);
return(ENOENT); return(r);
} }
len += strlen(component) + 1; len += strlen(component) + 1;
@ -809,7 +809,7 @@ struct fproc *rfp;
/* add the leading slash */ /* add the leading slash */
len = strlen(orig_path); len = strlen(orig_path);
if (strlen(orig_path) >= PATH_MAX) return(ENAMETOOLONG); if (strlen(orig_path) >= PATH_MAX) return(ENAMETOOLONG);
memmove(orig_path+1, orig_path, len); memmove(orig_path+1, orig_path, len + 1 /* include terminating nul */);
orig_path[0] = '/'; orig_path[0] = '/';
/* remove trailing slash if there is any */ /* remove trailing slash if there is any */

View file

@ -567,6 +567,21 @@ void test_bind(void)
UNLINK(TEST_SYM_A); UNLINK(TEST_SYM_A);
UNLINK(TEST_SYM_B); UNLINK(TEST_SYM_B);
/* Test bind with garbage in sockaddr_un */
memset(&addr, '?', sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
addr.sun_path[0] = 'f';
addr.sun_path[1] = 'o';
addr.sun_path[2] = 'o';
addr.sun_path[3] = '\0';
SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
rc = bind(sd, (struct sockaddr *) &addr, strlen(addr.sun_path) + 1);
if (rc == -1) {
test_fail("bind() should have worked");
}
CLOSE(sd);
UNLINK(TEST_SUN_PATH);
debug("leaving test_bind()"); debug("leaving test_bind()");
} }