From owner-svn-src-head@FreeBSD.ORG Mon Apr 21 17:40:25 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 20A60C30; Mon, 21 Apr 2014 17:40:25 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 00D5D1168; Mon, 21 Apr 2014 17:40:25 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s3LHeOKl044990; Mon, 21 Apr 2014 17:40:24 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s3LHeNv3044981; Mon, 21 Apr 2014 17:40:23 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <201404211740.s3LHeNv3044981@svn.freebsd.org> From: Jilles Tjoelker Date: Mon, 21 Apr 2014 17:40:23 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Apr 2014 17:40:25 -0000 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +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 : ""; + 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