On Mon, Nov 17, 2008 at 6:19 AM, Subrata Modak
<[EMAIL PROTECTED]> wrote:
>
> On Fri, 2008-11-14 at 12:40 -0500, Michael Kerrisk wrote:
>> > Here's the latest version, for review-n-test enjoyment:
>>
>> Andrew,
>>
>> I made a few small tweaks to the changelog: wording fixes, and para
>> break fixes; other than that, changed the text to say that I rewrote
>> (rather than updated) the test program. Please substitute it with the
>> following.
>>
>> Cheers,
>>
>> Michael
>
> Michael,
>
> I just did a quick patch for your test to run on LTP. If you have no
> issue(s), can we add this to LTP ?
I haven't run this within the LTP framework, but reading it, it looks
okay. And of course, please add to LTP.
Cheers,
Michael
> LTP-list,
>
> Can you also enrich this patch ?
>
> --
> diff -uprN
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/accept4_01.c
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/accept4_01.c
> ---
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/accept4_01.c
> 1970-01-01 05:30:00.000000000 +0530
> +++
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/accept4_01.c
> 2008-11-17 16:42:25.000000000 +0530
> @@ -0,0 +1,293 @@
> +/******************************************************************************/
> +/*
> */
> +/* Copyright (C) 2008, Linux Foundation,
> */
> +/* written by Michael Kerrisk <[EMAIL PROTECTED]>
> */
> +/*
> */
> +/* Licensed under the GNU GPLv2 or later.
> */
> +/* This program is free software; you can redistribute it and/or
> modify */
> +/* it under the terms of the GNU General Public License as published by
> */
> +/* the Free Software Foundation; either version 2 of the License, or
> */
> +/* (at your option) any later version.
> */
> +/*
> */
> +/* This program is distributed in the hope that it will be useful,
> */
> +/* but WITHOUT ANY WARRANTY; without even the implied warranty of
> */
> +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> */
> +/* the GNU General Public License for more details.
> */
> +/*
> */
> +/* You should have received a copy of the GNU General Public License
> */
> +/* along with this program; if not, write to the Free Software
> */
> +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
> USA */
> +/*
> */
> +/******************************************************************************/
> +
> +/******************************************************************************/
> +/*
> */
> +/* File: accept4_01.c
> */
> +/*
> */
> +/* Description: This will test the newly introduced syscall accept4()
> */
> +/*
> */
> +/* Total Tests: 4
> */
> +/*
> */
> +/* Test Name: accept4_01
> */
> +/*
> */
> +/* Author: Michael Kerrisk <[EMAIL PROTECTED]>
> */
> +/*
> */
> +/* History: Created - Nov 17 2008 - Michael
> <[EMAIL PROTECTED]> */
> +/* Initial Porting to LTP
> */
> +/* - Nov 17 2008 - Subrata
> <[EMAIL PROTECTED]> */
> +/*
> */
> +/******************************************************************************/
> +
> +#define _GNU_SOURCE
> +#include <unistd.h>
> +#include <sys/syscall.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include "test.h"
> +#include "usctest.h"
> +
> +#define PORT_NUM 33333
> +
> +#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
> +
> +/**********************************************************************/
> +
> +/* The following is what we need until glibc gets a wrapper for
> + accept4() */
> +
> +/* Flags for socket(), socketpair(), accept4() */
> +#ifndef O_CLOEXEC
> +# define O_CLOEXEC 02000000
> +#endif
> +
> +#ifndef SOCK_CLOEXEC
> +#define SOCK_CLOEXEC O_CLOEXEC
> +#endif
> +#ifndef SOCK_NONBLOCK
> +#define SOCK_NONBLOCK O_NONBLOCK
> +#endif
> +
> +#ifdef __x86_64__
> +#define SYS_ACCEPT4 288
> +#elif __i386__
> +#define USE_SOCKETCALL 1
> +#define SYS_ACCEPT4 18
> +#else
> +#error "Sorry -- don't know the syscall # on this architecture"
> +#endif
> +
> +/* Extern Global Variables */
> +extern int Tst_count; /* counter for tst_xxx routines.
> */
> +extern char *TESTDIR; /* temporary dir created by
> tst_tmpdir() */
> +
> +/* Global Variables */
> +char *TCID = "accept04_01"; /* test program identifier. */
> +int TST_TOTAL = 1; /* total number of tests in this
> file. */
> +
> +/* Extern Global Functions */
> +/******************************************************************************/
> +/*
> */
> +/* Function: cleanup
> */
> +/*
> */
> +/* Description: Performs all one time clean up for this test on
> successful */
> +/* completion, premature exit or failure. Closes all
> temporary */
> +/* files, removes all temporary directories exits the test
> with */
> +/* appropriate return code by calling tst_exit() function.
> */
> +/*
> */
> +/* Input: None.
> */
> +/*
> */
> +/* Output: None.
> */
> +/*
> */
> +/* Return: On failure - Exits calling tst_exit(). Non '0' return
> code. */
> +/* On success - Exits calling tst_exit(). With '0' return
> code. */
> +/*
> */
> +/******************************************************************************/
> +/* We would need this for many more reasons in future
> */
> +extern void
> +cleanup()
> +{
> + /* Remove tmp dir and all files in it */
> + TEST_CLEANUP;
> + tst_rmdir();
> +
> + /* Exit with appropriate return code. */
> + tst_exit();
> +}
> +
> +
> +/* Local Functions */
> +/******************************************************************************/
> +/*
> */
> +/* Function: setup
> */
> +/*
> */
> +/* Description: Performs all one time setup for this test. This
> function is */
> +/* typically used to capture signals, create temporary
> dirs */
> +/* and temporary files that may be used in the course of
> this */
> +/* test.
> */
> +/*
> */
> +/* Input: None.
> */
> +/*
> */
> +/* Output: None.
> */
> +/*
> */
> +/* Return: On failure - Exits by calling cleanup().
> */
> +/* On success - returns 0.
> */
> +/*
> */
> +/******************************************************************************/
> +void
> +setup()
> +{
> + /* Capture signals if any */
> + /* Create temporary directories */
> + TEST_PAUSE;
> + tst_tmpdir();
> +}
> +
> +
> +static int
> +accept4(int fd, struct sockaddr *sockaddr, socklen_t *addrlen, int
> flags)
> +{
> + tst_resm(TINFO, "Calling accept4(): flags = %x", flags);
> + if (flags != 0) {
> + tst_resm(TINFO," (");
> + if (flags & SOCK_CLOEXEC)
> + tst_resm(TINFO,"SOCK_CLOEXEC");
> + if ((flags & SOCK_CLOEXEC) && (flags & SOCK_NONBLOCK))
> + tst_resm(TINFO," ");
> + if (flags & SOCK_NONBLOCK)
> + tst_resm(TINFO,"SOCK_NONBLOCK");
> + tst_resm(TINFO,")");
> + }
> + tst_resm(TINFO,"\n");
> +
> +#if USE_SOCKETCALL
> + long args[6];
> +
> + args[0] = fd;
> + args[1] = (long) sockaddr;
> + args[2] = (long) addrlen;
> + args[3] = flags;
> +
> + return syscall(SYS_socketcall, SYS_ACCEPT4, args);
> +#else
> + return syscall(SYS_accept4, fd, sockaddr, addrlen, flags);
> +#endif
> +}
> +
> +/**********************************************************************/
> +
> +
> +static int
> +do_test(int lfd, struct sockaddr_in *conn_addr,
> + int closeonexec_flag, int nonblock_flag)
> +{
> + int connfd, acceptfd;
> + int fdf, flf, fdf_pass, flf_pass;
> + struct sockaddr_in claddr;
> + socklen_t addrlen;
> +
> + tst_resm(TINFO,"=======================================\n");
> +
> + connfd = socket(AF_INET, SOCK_STREAM, 0);
> + if (connfd == -1)
> + tst_brkm(TBROK, cleanup, "Socket Error");
> + if (connect(connfd, (struct sockaddr *) conn_addr,
> + sizeof(struct sockaddr_in)) == -1)
> + tst_brkm(TBROK, cleanup, "Connect Error");
> +
> + addrlen = sizeof(struct sockaddr_in);
> + acceptfd = accept4(lfd, (struct sockaddr *) &claddr, &addrlen,
> + closeonexec_flag | nonblock_flag);
> + if (acceptfd == -1) {
> + tst_brkm(TBROK, cleanup, "accept4() Error");
> + close(connfd);
> + return 0;
> + }
> +
> + fdf = fcntl(acceptfd, F_GETFD);
> + if (fdf == -1)
> + tst_brkm(TBROK, cleanup, "fcntl:F_GETFD");
> + fdf_pass = ((fdf & FD_CLOEXEC) != 0) ==
> + ((closeonexec_flag & SOCK_CLOEXEC) != 0);
> + tst_resm(TINFO, "Close-on-exec flag is %sset (%s); ", (fdf &
> FD_CLOEXEC) ? "" : "not ", fdf_pass ? "OK" : "failed");
> +
> + flf = fcntl(acceptfd, F_GETFL);
> + if (flf == -1)
> + tst_brkm(TBROK, cleanup, "fcntl:F_GETFD");
> + flf_pass = ((flf & O_NONBLOCK) != 0) ==
> + ((nonblock_flag & SOCK_NONBLOCK) !=0);
> + tst_resm(TINFO, "nonblock flag is %sset (%s)\n", (flf &
> O_NONBLOCK) ? "" : "not ", flf_pass ? "OK" : "failed");
> +
> + close(acceptfd);
> + close(connfd);
> +
> + tst_resm(TINFO, "Test result: %s\n", (fdf_pass && flf_pass) ?
> "PASS" : "FAIL");
> + return fdf_pass && flf_pass;
> +}
> +
> +
> +static int
> +create_listening_socket(int port_num)
> +{
> + struct sockaddr_in svaddr;
> + int lfd;
> + int optval;
> +
> + memset(&svaddr, 0, sizeof(struct sockaddr_in));
> + svaddr.sin_family = AF_INET;
> + svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
> + svaddr.sin_port = htons(port_num);
> +
> + lfd = socket(AF_INET, SOCK_STREAM, 0);
> + if (lfd == -1)
> + tst_brkm(TBROK, cleanup, "Socket Error");
> +
> + optval = 1;
> + if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval,
> + sizeof(optval)) == -1)
> + tst_brkm(TBROK, cleanup, "Setsockopt Error");
> +
> + if (bind(lfd, (struct sockaddr *) &svaddr,
> + sizeof(struct sockaddr_in)) == -1)
> + tst_brkm(TBROK, cleanup, "Bind Error");
> +
> + if (listen(lfd, 5) == -1)
> + tst_brkm(TBROK, cleanup, "Listen Error");
> +
> + return lfd;
> +}
> +
> +
> +int
> +main(int argc, char *argv[])
> +{
> + struct sockaddr_in conn_addr;
> + int lfd;
> + int port_num;
> + int passed=1;
> +
> + setup();
> + port_num = (argc > 1) ? atoi(argv[1]) : PORT_NUM;
> +
> + memset(&conn_addr, 0, sizeof(struct sockaddr_in));
> + conn_addr.sin_family = AF_INET;
> + conn_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
> + conn_addr.sin_port = htons(port_num);
> +
> + lfd = create_listening_socket(port_num);
> +
> + if (!do_test(lfd, &conn_addr, 0, 0))
> + passed = 0;
> + if (!do_test(lfd, &conn_addr, SOCK_CLOEXEC, 0))
> + passed = 0;
> + if (!do_test(lfd, &conn_addr, 0, SOCK_NONBLOCK))
> + passed = 0;
> + if (!do_test(lfd, &conn_addr, SOCK_CLOEXEC, SOCK_NONBLOCK))
> + passed = 0;
> + close(lfd);
> + exit(passed ? EXIT_SUCCESS : EXIT_FAILURE);
> +}
> diff -uprN
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/Makefile
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/Makefile
> ---
> ltp-intermediate-20081117/testcases/kernel/syscalls/accept4.orig/Makefile
> 1970-01-01 05:30:00.000000000 +0530
> +++ ltp-intermediate-20081117/testcases/kernel/syscalls/accept4/Makefile
> 2008-11-17 16:32:49.000000000 +0530
> @@ -0,0 +1,31 @@
> +#
> +# Copyright (c) International Business Machines Corp., 2008
> +#
> +# This program is free software; you can redistribute it and/or
> modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> +# the GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> 02110-1301 USA
> +#
> +
> +CFLAGS += -I../../../../include -Wall
> +LDLIBS += -L../../../../lib -lltp
> +
> +SRCS = $(wildcard *.c)
> +TARGETS = $(patsubst %.c,%,$(SRCS))
> +
> +all: $(TARGETS)
> +
> +install:
> + @set -e; for i in $(TARGETS); do ln -f $$i ../../../bin/$$i ; done
> +
> +clean:
> + rm -f $(TARGETS)
> --- ltp-intermediate-20081117/runtest/syscalls.orig 2008-11-17
> 16:38:43.000000000 +0530
> +++ ltp-intermediate-20081117/runtest/syscalls 2008-11-17
> 16:39:10.000000000 +0530
> @@ -2,6 +2,7 @@
> abort01 ulimit -c 1024;abort01
>
> accept01 accept01
> +accept4_01 accept4_01
>
> access01 access01
> access02 access02
>
>
> Regards--
> Subrata
>
>>
>> ===
>> From: Ulrich Drepper <[EMAIL PROTECTED]>
>>
>> Introduce a new accept4() system call. The addition of this system call
>> matches analogous changes in 2.6.27 (dup3(), evenfd2(), signalfd4(),
>> inotify_init1(), epoll_create1(), pipe2()) which added new system calls
>> that differed from analogous traditional system calls in adding a flags
>> argument that can be used to access additional functionality.
>>
>> The accept4() system call is exactly the same as accept(), except that
>> it adds a flags bit-mask argument. Two flags are initially implemented.
>> (Most of the new system calls in 2.6.27 also had both of these flags.)
>>
>> SOCK_CLOEXEC causes the close-on-exec (FD_CLOEXEC) flag to be enabled
>> for the new file descriptor returned by accept4(). This is a useful
>> security feature to avoid leaking information in a multithreaded
>> program where one thread is doing an accept() at the same time as
>> another thread is doing a fork() plus exec(). More details here:
>> http://udrepper.livejournal.com/20407.html "Secure File Descriptor Handling",
>> Ulrich Drepper).
>>
>> The other flag is SOCK_NONBLOCK, which causes the O_NONBLOCK flag
>> to be enabled on the new open file description created by accept4().
>> (This flag is merely a convenience, saving the use of additional calls
>> fcntl(F_GETFL) and fcntl (F_SETFL) to achieve the same result.
>>
>> Here's a test program. Works on x86-32. Should work on x86-64, but
>> I (mtk) don't have a system to hand to test with.
>>
>> It tests accept4() with each of the four possible combinations of
>> SOCK_CLOEXEC and SOCK_NONBLOCK set/clear in 'flags', and verifies
>> that the appropriate flags are set on the file descriptor/open file
>> description returned by accept4().
>>
>> I tested Ulrich's patch in this thread by applying against 2.6.28-rc2,
>> and it passes according to my test program.
>>
>> /* test_accept4.c
>>
>> Copyright (C) 2008, Linux Foundation, written by Michael Kerrisk
>> <[EMAIL PROTECTED]>
>>
>> Licensed under the GNU GPLv2 or later.
>> */
>> #define _GNU_SOURCE
>> #include <unistd.h>
>> #include <sys/syscall.h>
>> #include <sys/socket.h>
>> #include <netinet/in.h>
>> #include <stdlib.h>
>> #include <fcntl.h>
>> #include <stdio.h>
>> #include <string.h>
>>
>> #define PORT_NUM 33333
>>
>> #define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
>>
>> /**********************************************************************/
>>
>> /* The following is what we need until glibc gets a wrapper for
>> accept4() */
>>
>> /* Flags for socket(), socketpair(), accept4() */
>> #ifndef SOCK_CLOEXEC
>> #define SOCK_CLOEXEC O_CLOEXEC
>> #endif
>> #ifndef SOCK_NONBLOCK
>> #define SOCK_NONBLOCK O_NONBLOCK
>> #endif
>>
>> #ifdef __x86_64__
>> #define SYS_accept4 288
>> #elif __i386__
>> #define USE_SOCKETCALL 1
>> #define SYS_ACCEPT4 18
>> #else
>> #error "Sorry -- don't know the syscall # on this architecture"
>> #endif
>>
>> static int
>> accept4(int fd, struct sockaddr *sockaddr, socklen_t *addrlen, int flags)
>> {
>> printf("Calling accept4(): flags = %x", flags);
>> if (flags != 0) {
>> printf(" (");
>> if (flags & SOCK_CLOEXEC)
>> printf("SOCK_CLOEXEC");
>> if ((flags & SOCK_CLOEXEC) && (flags & SOCK_NONBLOCK))
>> printf(" ");
>> if (flags & SOCK_NONBLOCK)
>> printf("SOCK_NONBLOCK");
>> printf(")");
>> }
>> printf("\n");
>>
>> #if USE_SOCKETCALL
>> long args[6];
>>
>> args[0] = fd;
>> args[1] = (long) sockaddr;
>> args[2] = (long) addrlen;
>> args[3] = flags;
>>
>> return syscall(SYS_socketcall, SYS_ACCEPT4, args);
>> #else
>> return syscall(SYS_accept4, fd, sockaddr, addrlen, flags);
>> #endif
>> }
>>
>> /**********************************************************************/
>>
>>
>> static int
>> do_test(int lfd, struct sockaddr_in *conn_addr,
>> int closeonexec_flag, int nonblock_flag)
>> {
>> int connfd, acceptfd;
>> int fdf, flf, fdf_pass, flf_pass;
>> struct sockaddr_in claddr;
>> socklen_t addrlen;
>>
>> printf("=======================================\n");
>>
>> connfd = socket(AF_INET, SOCK_STREAM, 0);
>> if (connfd == -1)
>> die("socket");
>> if (connect(connfd, (struct sockaddr *) conn_addr,
>> sizeof(struct sockaddr_in)) == -1)
>> die("connect");
>>
>> addrlen = sizeof(struct sockaddr_in);
>> acceptfd = accept4(lfd, (struct sockaddr *) &claddr, &addrlen,
>> closeonexec_flag | nonblock_flag);
>> if (acceptfd == -1) {
>> perror("accept4()");
>> close(connfd);
>> return 0;
>> }
>>
>> fdf = fcntl(acceptfd, F_GETFD);
>> if (fdf == -1)
>> die("fcntl:F_GETFD");
>> fdf_pass = ((fdf & FD_CLOEXEC) != 0) ==
>> ((closeonexec_flag & SOCK_CLOEXEC) != 0);
>> printf("Close-on-exec flag is %sset (%s); ",
>> (fdf & FD_CLOEXEC) ? "" : "not ",
>> fdf_pass ? "OK" : "failed");
>>
>> flf = fcntl(acceptfd, F_GETFL);
>> if (flf == -1)
>> die("fcntl:F_GETFD");
>> flf_pass = ((flf & O_NONBLOCK) != 0) ==
>> ((nonblock_flag & SOCK_NONBLOCK) !=0);
>> printf("nonblock flag is %sset (%s)\n",
>> (flf & O_NONBLOCK) ? "" : "not ",
>> flf_pass ? "OK" : "failed");
>>
>> close(acceptfd);
>> close(connfd);
>>
>> printf("Test result: %s\n", (fdf_pass && flf_pass) ? "PASS" : "FAIL");
>> return fdf_pass && flf_pass;
>> }
>>
>>
>> static int
>> create_listening_socket(int port_num)
>> {
>> struct sockaddr_in svaddr;
>> int lfd;
>> int optval;
>>
>> memset(&svaddr, 0, sizeof(struct sockaddr_in));
>> svaddr.sin_family = AF_INET;
>> svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
>> svaddr.sin_port = htons(port_num);
>>
>> lfd = socket(AF_INET, SOCK_STREAM, 0);
>> if (lfd == -1)
>> die("socket");
>>
>> optval = 1;
>> if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval,
>> sizeof(optval)) == -1)
>> die("setsockopt");
>>
>> if (bind(lfd, (struct sockaddr *) &svaddr,
>> sizeof(struct sockaddr_in)) == -1)
>> die("bind");
>>
>> if (listen(lfd, 5) == -1)
>> die("listen");
>>
>> return lfd;
>> }
>>
>>
>> int
>> main(int argc, char *argv[])
>> {
>> struct sockaddr_in conn_addr;
>> int lfd;
>> int port_num;
>> int passed;
>>
>> passed = 1;
>>
>> port_num = (argc > 1) ? atoi(argv[1]) : PORT_NUM;
>>
>> memset(&conn_addr, 0, sizeof(struct sockaddr_in));
>> conn_addr.sin_family = AF_INET;
>> conn_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
>> conn_addr.sin_port = htons(port_num);
>>
>> lfd = create_listening_socket(port_num);
>>
>> if (!do_test(lfd, &conn_addr, 0, 0))
>> passed = 0;
>> if (!do_test(lfd, &conn_addr, SOCK_CLOEXEC, 0))
>> passed = 0;
>> if (!do_test(lfd, &conn_addr, 0, SOCK_NONBLOCK))
>> passed = 0;
>> if (!do_test(lfd, &conn_addr, SOCK_CLOEXEC, SOCK_NONBLOCK))
>> passed = 0;
>>
>> close(lfd);
>>
>> exit(passed ? EXIT_SUCCESS : EXIT_FAILURE);
>> }
>>
>> [EMAIL PROTECTED]: rewrote changelog and test program]
>> Signed-off-by: Ulrich Drepper <[EMAIL PROTECTED]>
>> Tested-by: Michael Kerrisk <[EMAIL PROTECTED]>
>> Acked-by: Michael Kerrisk <[EMAIL PROTECTED]>
>> Cc: <[EMAIL PROTECTED]>
>> Cc: <[EMAIL PROTECTED]>
>> Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
>
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git
man-pages online: http://www.kernel.org/doc/man-pages/online_pages.html
Found a bug? http://www.kernel.org/doc/man-pages/reporting_bugs.html
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list