Date: Mon, 21 Apr 2014 17:40:23 +0000 (UTC) From: Jilles Tjoelker <jilles@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264737 - in head: lib/libc/stdio tools/regression/lib/libc/stdio Message-ID: <201404211740.s3LHeNv3044981@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jilles Date: Mon Apr 21 17:40:23 2014 New Revision: 264737 URL: http://svnweb.freebsd.org/changeset/base/264737 Log: libc/stdio: Fail fdopen() on an execute-only fd. An execute-only fd (opened with O_EXEC) allows neither read() nor write() and is therefore incompatible with all stdio modes. Therefore, the [EINVAL] error applies. Also adjust the similar check in freopen() with a NULL path, even though this checks an fd which is already from a FILE. Added: head/tools/regression/lib/libc/stdio/test-fdopen.c (contents, props changed) head/tools/regression/lib/libc/stdio/test-fdopen.t (contents, props changed) head/tools/regression/lib/libc/stdio/test-freopen.c (contents, props changed) head/tools/regression/lib/libc/stdio/test-freopen.t (contents, props changed) Modified: head/lib/libc/stdio/fdopen.c head/lib/libc/stdio/freopen.c head/tools/regression/lib/libc/stdio/Makefile Modified: head/lib/libc/stdio/fdopen.c ============================================================================== --- head/lib/libc/stdio/fdopen.c Mon Apr 21 17:17:23 2014 (r264736) +++ head/lib/libc/stdio/fdopen.c Mon Apr 21 17:40:23 2014 (r264737) @@ -70,7 +70,8 @@ fdopen(int fd, const char *mode) /* Make sure the mode the user wants is a subset of the actual mode. */ if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0) return (NULL); - tmp = fdflags & O_ACCMODE; + /* Work around incorrect O_ACCMODE. */ + tmp = fdflags & (O_ACCMODE | O_EXEC); if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return (NULL); Modified: head/lib/libc/stdio/freopen.c ============================================================================== --- head/lib/libc/stdio/freopen.c Mon Apr 21 17:17:23 2014 (r264736) +++ head/lib/libc/stdio/freopen.c Mon Apr 21 17:40:23 2014 (r264737) @@ -92,8 +92,9 @@ freopen(const char * __restrict file, co errno = sverrno; return (NULL); } - if ((dflags & O_ACCMODE) != O_RDWR && (dflags & O_ACCMODE) != - (oflags & O_ACCMODE)) { + /* Work around incorrect O_ACCMODE. */ + if ((dflags & O_ACCMODE) != O_RDWR && + (dflags & (O_ACCMODE | O_EXEC)) != (oflags & O_ACCMODE)) { fclose(fp); FUNLOCKFILE(fp); errno = EINVAL; Modified: head/tools/regression/lib/libc/stdio/Makefile ============================================================================== --- head/tools/regression/lib/libc/stdio/Makefile Mon Apr 21 17:17:23 2014 (r264736) +++ head/tools/regression/lib/libc/stdio/Makefile Mon Apr 21 17:40:23 2014 (r264737) @@ -1,7 +1,9 @@ # $FreeBSD$ -TESTS= test-fmemopen \ +TESTS= test-fdopen \ + test-fmemopen \ test-fopen \ + test-freopen \ test-getdelim \ test-mkostemp \ test-open_memstream \ Added: head/tools/regression/lib/libc/stdio/test-fdopen.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/lib/libc/stdio/test-fdopen.c Mon Apr 21 17:40:23 2014 (r264737) @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2014 Jilles Tjoelker + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +static int testnum = 1; + +static void +runtest(const char *fname, int intmode, const char *strmode, bool success) +{ + FILE *fp; + int fd; + + fd = open(fname, intmode); + if (fd == -1) { + printf("not ok %d - open(\"%s\", %#x) failed\n", + testnum++, fname, intmode); + return; + } + fp = fdopen(fd, strmode); + if (fp == NULL) { + close(fd); + if (success) + printf("not ok %d - " + "fdopen(open(\"%s\", %#x), \"%s\") failed\n", + testnum++, fname, intmode, strmode); + else + printf("ok %d - " + "fdopen(open(\"%s\", %#x), \"%s\") failed\n", + testnum++, fname, intmode, strmode); + return; + } + if (success) + printf("ok %d - " + "fdopen(open(\"%s\", %#x), \"%s\") succeeded\n", + testnum++, fname, intmode, strmode); + else + printf("not ok %d - " + "fdopen(open(\"%s\", %#x), \"%s\") succeeded\n", + testnum++, fname, intmode, strmode); + fclose(fp); +} + +/* + * Test program for fdopen(). + */ +int +main(int argc, char *argv[]) +{ + printf("1..19\n"); + runtest("/dev/null", O_RDONLY, "r", true); + runtest("/dev/null", O_WRONLY, "r", false); + runtest("/dev/null", O_RDWR, "r", true); + runtest("/dev/null", O_RDONLY, "w", false); + runtest("/dev/null", O_WRONLY, "w", true); + runtest("/dev/null", O_RDWR, "w", true); + runtest("/dev/null", O_RDONLY, "a", false); + runtest("/dev/null", O_WRONLY, "a", true); + runtest("/dev/null", O_RDWR, "a", true); + runtest("/dev/null", O_RDONLY, "r+", false); + runtest("/dev/null", O_WRONLY, "r+", false); + runtest("/dev/null", O_RDWR, "r+", true); + runtest("/dev/null", O_RDONLY, "w+", false); + runtest("/dev/null", O_WRONLY, "w+", false); + runtest("/dev/null", O_RDWR, "w+", true); + runtest("/bin/sh", O_EXEC, "r", false); + runtest("/bin/sh", O_EXEC, "w", false); + runtest("/bin/sh", O_EXEC, "r+", false); + runtest("/bin/sh", O_EXEC, "w+", false); + + return 0; +} + +/* vim:ts=8:cin:sw=8 + * */ Added: head/tools/regression/lib/libc/stdio/test-fdopen.t ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/lib/libc/stdio/test-fdopen.t Mon Apr 21 17:40:23 2014 (r264737) @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable Added: head/tools/regression/lib/libc/stdio/test-freopen.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/lib/libc/stdio/test-freopen.c Mon Apr 21 17:40:23 2014 (r264737) @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2014 Jilles Tjoelker + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +static int testnum = 1; + +static void +runtest(const char *fname1, const char *mode1, const char *fname2, + const char *mode2, bool success) +{ + FILE *fp1, *fp2; + const char *fname2_print; + + fname2_print = fname2 != NULL ? fname2 : "<NULL>"; + fp1 = fopen(fname1, mode1); + if (fp1 == NULL) { + printf("not ok %d - fopen(\"%s\", \"%s\") failed\n", + testnum++, fname1, mode1); + return; + } + fp2 = freopen(fname2, mode2, fp1); + if (fp2 == NULL) { + fclose(fp1); + if (success) + printf("not ok %d - " + "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) " + "failed\n", + testnum++, fname2_print, mode2, fname1, mode1); + else + printf("ok %d - " + "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) " + "failed\n", + testnum++, fname2_print, mode2, fname1, mode1); + return; + } + if (success) + printf("ok %d - " + "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) " + "succeeded\n", + testnum++, fname2_print, mode2, fname1, mode1); + else + printf("not ok %d - " + "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) " + "succeeded\n", + testnum++, fname2_print, mode2, fname1, mode1); + fclose(fp2); +} + +/* + * Test program for freopen(). + */ +int +main(int argc, char *argv[]) +{ + printf("1..19\n"); + runtest("/dev/null", "r", NULL, "r", true); + runtest("/dev/null", "w", NULL, "r", false); + runtest("/dev/null", "r+", NULL, "r", true); + runtest("/dev/null", "r", NULL, "w", false); + runtest("/dev/null", "w", NULL, "w", true); + runtest("/dev/null", "r+", NULL, "w", true); + runtest("/dev/null", "r", NULL, "a", false); + runtest("/dev/null", "w", NULL, "a", true); + runtest("/dev/null", "r+", NULL, "a", true); + runtest("/dev/null", "r", NULL, "r+", false); + runtest("/dev/null", "w", NULL, "r+", false); + runtest("/dev/null", "r+", NULL, "r+", true); + runtest("/dev/null", "r", NULL, "w+", false); + runtest("/dev/null", "w", NULL, "w+", false); + runtest("/dev/null", "r+", NULL, "w+", true); + runtest("/bin/sh", "r", NULL, "r", true); + runtest("/bin/sh", "r", "/bin/sh", "r", true); + runtest("/bin/sh", "r", "/dev/null", "r", true); + runtest("/bin/sh", "r", "/dev/null", "w", true); + + return 0; +} + +/* vim:ts=8:cin:sw=8 + * */ Added: head/tools/regression/lib/libc/stdio/test-freopen.t ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/regression/lib/libc/stdio/test-freopen.t Mon Apr 21 17:40:23 2014 (r264737) @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404211740.s3LHeNv3044981>