Skip site navigation (1)Skip section navigation (2)
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>