From 6935428a29ece41828cb55c6c22710a7c1535010 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 14 Nov 2014 11:30:50 +0100 Subject: libcsupport: Avoid TOCTOU and format errors --- cpukit/libcsupport/src/pwdgrp.c | 42 ++++----- testsuites/libtests/Makefile.am | 1 + testsuites/libtests/configure.ac | 1 + testsuites/libtests/pwdgrp01/Makefile.am | 19 +++++ testsuites/libtests/pwdgrp01/init.c | 136 ++++++++++++++++++++++++++++++ testsuites/libtests/pwdgrp01/pwdgrp01.doc | 19 +++++ testsuites/libtests/pwdgrp01/pwdgrp01.scn | 2 + 7 files changed, 200 insertions(+), 20 deletions(-) create mode 100644 testsuites/libtests/pwdgrp01/Makefile.am create mode 100644 testsuites/libtests/pwdgrp01/init.c create mode 100644 testsuites/libtests/pwdgrp01/pwdgrp01.doc create mode 100644 testsuites/libtests/pwdgrp01/pwdgrp01.scn diff --git a/cpukit/libcsupport/src/pwdgrp.c b/cpukit/libcsupport/src/pwdgrp.c index c10cbab719..a531b8b2ff 100644 --- a/cpukit/libcsupport/src/pwdgrp.c +++ b/cpukit/libcsupport/src/pwdgrp.c @@ -39,40 +39,42 @@ static pthread_once_t pwdgrp_once = PTHREAD_ONCE_INIT; +static void init_file(const char *name, const char *content) +{ + FILE *fp = fopen(name, "wx"); + + if (fp != NULL) { + fputs(content, fp); + fclose(fp); + } +} + /** * Initialize useable but dummy databases */ static void pwdgrp_init(void) { - FILE *fp; - mkdir("/etc", 0777); /* * Initialize /etc/passwd */ - if ((fp = fopen("/etc/passwd", "r")) != NULL) { - fclose(fp); - } - else if ((fp = fopen("/etc/passwd", "w")) != NULL) { - fprintf(fp, "root:*:0:0:root::/:/bin/sh\n" - "rtems:*:1:1:RTEMS Application::/:/bin/sh\n" - "tty:!:2:2:tty owner::/:/bin/false\n" ); - fclose(fp); - } + init_file( + "/etc/passwd", + "root:*:0:0:root::/:/bin/sh\n" + "rtems:*:1:1:RTEMS Application::/:/bin/sh\n" + "tty:!:2:2:tty owner::/:/bin/false\n" + ); /* * Initialize /etc/group */ - if ((fp = fopen("/etc/group", "r")) != NULL) { - fclose(fp); - } - else if ((fp = fopen("/etc/group", "w")) != NULL) { - fprintf( fp, "root:x:0:root\n" - "rtems:x:1:rtems\n" - "tty:x:2:tty\n" ); - fclose(fp); - } + init_file( + "/etc/group", + "root:x:0:root\n" + "rtems:x:1:rtems\n" + "tty:x:2:tty\n" + ); } void _libcsupport_pwdgrp_init(void) diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am index 278b2320a1..b04535c927 100644 --- a/testsuites/libtests/Makefile.am +++ b/testsuites/libtests/Makefile.am @@ -1,6 +1,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal _SUBDIRS = POSIX +_SUBDIRS += pwdgrp01 _SUBDIRS += crypt01 _SUBDIRS += sha _SUBDIRS += i2c01 diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac index 437b760814..b1a7277948 100644 --- a/testsuites/libtests/configure.ac +++ b/testsuites/libtests/configure.ac @@ -66,6 +66,7 @@ AS_IF([test x"$HAVE_LIBDL" = x"yes"],[ # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +pwdgrp01/Makefile crypt01/Makefile sha/Makefile i2c01/Makefile diff --git a/testsuites/libtests/pwdgrp01/Makefile.am b/testsuites/libtests/pwdgrp01/Makefile.am new file mode 100644 index 0000000000..e624b26171 --- /dev/null +++ b/testsuites/libtests/pwdgrp01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = pwdgrp01 +pwdgrp01_SOURCES = init.c + +dist_rtems_tests_DATA = pwdgrp01.scn pwdgrp01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(pwdgrp01_OBJECTS) +LINK_LIBS = $(pwdgrp01_LDLIBS) + +pwdgrp01$(EXEEXT): $(pwdgrp01_OBJECTS) $(pwdgrp01_DEPENDENCIES) + @rm -f pwdgrp01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/libtests/pwdgrp01/init.c b/testsuites/libtests/pwdgrp01/init.c new file mode 100644 index 0000000000..f1be7bbfcd --- /dev/null +++ b/testsuites/libtests/pwdgrp01/init.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include +#include +#include + +#include "tmacros.h" + +const char rtems_test_name[] = "PWDGRP 1"; + +static void create_file(const char *name, const char *content) +{ + FILE *fp; + int rv; + + fp = fopen(name, "wx"); + rtems_test_assert(fp != NULL); + + rv = fputs(content, fp); + rtems_test_assert(rv == 0); + + rv = fclose(fp); + rtems_test_assert(rv == 0); +} + +static void assert_pwd(struct passwd *pwd) +{ + rtems_test_assert(strcmp(pwd->pw_name, "moop") == 0); + rtems_test_assert(strcmp(pwd->pw_passwd, "foo") == 0); + rtems_test_assert(pwd->pw_uid == 1); + rtems_test_assert(pwd->pw_gid == 3); + rtems_test_assert(strcmp(pwd->pw_comment, "blob") == 0); + rtems_test_assert(strcmp(pwd->pw_gecos, "a") == 0); + rtems_test_assert(strcmp(pwd->pw_dir, "b") == 0); + rtems_test_assert(strcmp(pwd->pw_shell, "c") == 0); +} + +static void assert_grp(struct group *grp) +{ + rtems_test_assert(strcmp(grp->gr_name, "blub") == 0); + rtems_test_assert(strcmp(grp->gr_passwd, "bar") == 0); + rtems_test_assert(grp->gr_gid == 3); + rtems_test_assert(strcmp(grp->gr_mem[0], "moop") == 0); + rtems_test_assert(grp->gr_mem[1] == NULL); +} + +static void test(void) +{ + int rv; + struct passwd pwd; + struct group grp; + struct passwd *pwd_res; + struct group *grp_res; + char buf[256]; + + rv = mkdir("/etc", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + rtems_test_assert(rv == 0); + + create_file( + "/etc/passwd", + "moop:foo:1:3:blob:a:b:c\n" + ); + + create_file( + "/etc/group", + "blub:bar:3:moop\n" + ); + + memset(&pwd, 0xff, sizeof(pwd)); + rv = getpwnam_r("moop", &pwd, &buf[0], sizeof(buf), &pwd_res); + rtems_test_assert(rv == 0); + rtems_test_assert(&pwd == pwd_res); + assert_pwd(pwd_res); + + memset(&pwd, 0xff, sizeof(pwd)); + rv = getpwuid_r(1, &pwd, &buf[0], sizeof(buf), &pwd_res); + rtems_test_assert(rv == 0); + rtems_test_assert(&pwd == pwd_res); + assert_pwd(pwd_res); + + memset(&grp, 0xff, sizeof(grp)); + rv = getgrnam_r("blub", &grp, &buf[0], sizeof(buf), &grp_res); + rtems_test_assert(rv == 0); + rtems_test_assert(&grp == grp_res); + assert_grp(grp_res); + + memset(&grp, 0xff, sizeof(grp)); + rv = getgrgid_r(3, &grp, &buf[0], sizeof(buf), &grp_res); + rtems_test_assert(rv == 0); + rtems_test_assert(&grp == grp_res); + assert_grp(grp_res); +} + +static void Init(rtems_task_argument arg) +{ + TEST_BEGIN(); + + test(); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4 + +#define CONFIGURE_MAXIMUM_TASKS 1 + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/libtests/pwdgrp01/pwdgrp01.doc b/testsuites/libtests/pwdgrp01/pwdgrp01.doc new file mode 100644 index 0000000000..eaba717769 --- /dev/null +++ b/testsuites/libtests/pwdgrp01/pwdgrp01.doc @@ -0,0 +1,19 @@ +This file describes the directives and concepts tested by this test set. + +test set name: pwdgrp01 + +directives: + + - _libcsupport_pwdgrp_init + - getpwnam_r + - getpwuid_r + - getgrnam_r + - getgrgid_r + +concepts: + + - Ensure that _libcsupport_pwdgrp_init() doesn't overwrite existing files. + - Ensure that getpwnam_r() and getpwuid_r() return the values specified by + custom /etc/passwd. + - Ensure that getgrnam_r() and getgrgid_r() return the values specified by + custom /etc/group. diff --git a/testsuites/libtests/pwdgrp01/pwdgrp01.scn b/testsuites/libtests/pwdgrp01/pwdgrp01.scn new file mode 100644 index 0000000000..df47c678ac --- /dev/null +++ b/testsuites/libtests/pwdgrp01/pwdgrp01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST PWDGRP 1 *** +*** END OF TEST PWDGRP 1 *** -- cgit v1.2.3