zdtm: Use safe helper function to initialize unix socket sockaddr structure

The helper function removes code duplication from tests that want to
initialize unix socket address to an absolute file path, derived from
current working directory of the test + relative filename of a resulting
socket. Because the former code used cwd = get_current_dir_name() as
part of absolute filename generation, the resulting filepath could later
cause failure of bind systcall due to unchecked permissions and
introduce confusing permission errors.

Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
This commit is contained in:
Valeriy Vdovin 2020-02-03 15:27:40 +03:00 committed by Andrei Vagin
parent 691b4a4e7e
commit fa705e418b
6 changed files with 33 additions and 60 deletions

View file

@ -4,7 +4,7 @@ CFLAGS += $(USERCFLAGS)
LIB := libzdtmtst.a
LIBSRC := datagen.c msg.c parseargs.c test.c streamutil.c lock.c ns.c tcp.c fs.c sysctl.c
LIBSRC := datagen.c msg.c parseargs.c test.c streamutil.c lock.c ns.c tcp.c unix.c fs.c sysctl.c
LIBOBJ := $(LIBSRC:%.c=%.o)
BIN := groups

19
test/zdtm/lib/unix.c Normal file
View file

@ -0,0 +1,19 @@
#include <sys/socket.h>
#include <sys/un.h>
#include "zdtmtst.h"
#include "fs.h"
int unix_fill_sock_name(struct sockaddr_un *name, char *relFilename)
{
char *cwd;
if (get_cwd_check_perm(&cwd)) {
pr_err("failed to get current working directory with valid permissions.\n");
return -1;
}
name->sun_family = AF_LOCAL;
ssprintf(name->sun_path, "%s/%s", cwd, relFilename);
return 0;
}

View file

@ -149,6 +149,9 @@ extern int tcp_init_server(int family, int *port);
extern int tcp_accept_server(int sock);
extern int tcp_init_client(int family, char *servIP, unsigned short servPort);
struct sockaddr_un;
extern int unix_fill_sock_name(struct sockaddr_un *name, char *relFilename);
struct zdtm_tcp_opts {
bool reuseaddr;
bool reuseport;

View file

@ -16,19 +16,6 @@ const char *test_author = "Tycho Andersen <tycho.andersen@canonical.com>";
char *dirname;
TEST_OPTION(dirname, string, "directory name", 1);
static int fill_sock_name(struct sockaddr_un *name, const char *filename)
{
char *cwd;
cwd = get_current_dir_name();
if (strlen(filename) + strlen(cwd) + 1 >= sizeof(name->sun_path))
return -1;
name->sun_family = AF_LOCAL;
ssprintf(name->sun_path, "%s/%s", cwd, filename);
return 0;
}
static int bind_and_listen(struct sockaddr_un *addr)
{
int sk;
@ -71,10 +58,8 @@ int main(int argc, char **argv)
goto out;
}
if (fill_sock_name(&addr, filename) < 0) {
pr_err("filename \"%s\" is too long\n", filename);
if (unix_fill_sock_name(&addr, filename))
goto out;
}
sk1 = bind_and_listen(&addr);
if (sk1 < 0)

View file

@ -17,28 +17,13 @@ const char *test_author = "Roman Kagan <rkagan@parallels.com>";
char *filename;
TEST_OPTION(filename, string, "file name", 1);
static int fill_sock_name(struct sockaddr_un *name, const char *filename)
{
char *cwd;
cwd = get_current_dir_name();
if (strlen(filename) + strlen(cwd) + 1 >= sizeof(name->sun_path))
return -1;
name->sun_family = AF_LOCAL;
sprintf(name->sun_path, "%s/%s", cwd, filename);
return 0;
}
static int setup_srv_sock(void)
{
struct sockaddr_un name;
int sock;
if (fill_sock_name(&name, filename) < 0) {
pr_perror("filename \"%s\" is too long", filename);
if (unix_fill_sock_name(&name, filename))
return -1;
}
sock = socket(PF_LOCAL, SOCK_STREAM, 0);
if (sock < 0) {
@ -67,7 +52,7 @@ static int setup_clnt_sock(void)
struct sockaddr_un name;
int sock;
if (fill_sock_name(&name, filename) < 0)
if (unix_fill_sock_name(&name, filename))
return -1;
sock = socket(PF_LOCAL, SOCK_STREAM, 0);

View file

@ -24,22 +24,6 @@ const char *test_author = "Cyrill Gorcunov <gorcunov@openvz.org>";
char *dirname;
TEST_OPTION(dirname, string, "directory name", 1);
static int fill_sock_name(struct sockaddr_un *name, const char *filename)
{
char *cwd;
cwd = get_current_dir_name();
if (strlen(filename) + strlen(cwd) + 1 >= sizeof(name->sun_path)) {
pr_err("Name %s/%s is too long for socket\n",
cwd, filename);
return -1;
}
name->sun_family = AF_LOCAL;
ssprintf(name->sun_path, "%s/%s", cwd, filename);
return 0;
}
static int sk_alloc_bind(int type, struct sockaddr_un *addr)
{
int sk;
@ -155,10 +139,9 @@ int main(int argc, char **argv)
*/
ssprintf(filename, "%s/%s", subdir_dg, "sk-dt");
if (fill_sock_name(&addr, filename) < 0) {
pr_err("%s is too long for socket\n", filename);
if (unix_fill_sock_name(&addr, filename))
return 1;
}
unlink(addr.sun_path);
sk_dgram[0] = sk_alloc_bind(SOCK_DGRAM, &addr);
@ -184,10 +167,9 @@ int main(int argc, char **argv)
test_msg("sk-dt: alloc/connect/unlink %d %s\n", sk_dgram[3], addr.sun_path);
ssprintf(filename, "%s/%s", dirname, "sole");
if (fill_sock_name(&addr, filename) < 0) {
pr_err("%s is too long for socket\n", filename);
if (unix_fill_sock_name(&addr, filename))
return 1;
}
unlink(addr.sun_path);
sk_dgram[4] = sk_alloc_bind(SOCK_DGRAM, &addr);
@ -237,7 +219,7 @@ int main(int argc, char **argv)
sk_dgram_pair[0], sk_dgram_pair[1]);
ssprintf(filename, "%s/%s", subdir_dg, "sk-dtp");
if (fill_sock_name(&addr, filename) < 0) {
if (unix_fill_sock_name(&addr, filename)) {
pr_err("%s is too long for socket\n", filename);
return 1;
}
@ -270,10 +252,9 @@ int main(int argc, char **argv)
* - delete socket on fs
*/
ssprintf(filename, "%s/%s", subdir_st, "sk-st");
if (fill_sock_name(&addr, filename) < 0) {
pr_err("%s is too long for socket\n", filename);
if (unix_fill_sock_name(&addr, filename))
return 1;
}
unlink(addr.sun_path);
sk_st[0] = sk_alloc_bind(SOCK_STREAM, &addr);