On 07/24/2015 07:50 PM, Andy Lutomirski wrote:
> On Fri, Jul 24, 2015 at 6:47 AM, Denys Vlasenko <dvlas...@redhat.com> wrote:
>> SYSCALL32 code is nearly identical to SYSCALL32, except for initial
>> section. Merge them.
>>
>> The removal is split into two parts, to make review eaiser. This is part 1.
>>
>> auditsys_entry_common and auditsys_exit macros are indented one more tab 
>> without
>> any changes. This prevents diff from becoming unreadable.
>> They will be removed in part 2.
> 
> I need to read these more closely, which is, at present, exceeding my
> ability to look at asm.  (See the big NMI thread.)  I'll look soon.
> 
> Meanwhile, this code is incredibly fragile wrt syscall restart.
> (Syscall restart on compat is really weird.)  Do we have a decent test
> for it?

How about this? (Feel free to expand, this is a first cut only).

$ ./test_restart
[RUN]   Test restart of read()
[OK]    Restart of read() worked
[RUN]   Test restart of recv()
[OK]    Restart of recv() worked





#undef _GNU_SOURCE
#define _GNU_SOURCE 1
#undef __USE_GNU
#define __USE_GNU 1
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
//#include <sys/ptrace.h>
#include <sys/wait.h>

void signal_SA_RESTART_empty_mask(int sig, void (*handler)(int))
{
        struct sigaction sa;
        memset(&sa, 0, sizeof(sa));
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART;
        sa.sa_handler = handler;
        sigaction(sig, &sa, NULL);
}

int make_writer(void)
{
        int pid, fd[2];
        if (pipe(fd)) exit(1);
        pid = fork();
        if (pid < 0) exit(1);
        if (pid == 0) {
                /* child */
                usleep(50*1000);
                write(fd[1], "123456789", 10);
                exit(0);
        }
        close(fd[1]);
        return fd[0];
}

int make_sender(void)
{
        int pid, fd[2];
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) exit(1);
        pid = fork();
        if (pid < 0) exit(1);
        if (pid == 0) {
                /* child */
                usleep(50*1000);
                write(fd[1], "123456789", 10);
                exit(0);
        }
        close(fd[1]);
        return fd[0];
}

int got_sig;

void sighandler(int sig)
{
        got_sig = 1;
}

void prepare(char buf[10])
{
        got_sig = 0;
        strcpy(buf, "qwertyuio");
        ualarm(25*1000, 0);
}

int check(const char *test_type, int len, char buf[10])
{
        int err = 0;
        if (len != 10 || strcmp(buf, "123456789") != 0) {
                printf("[FAIL]\tRestarted %s() returns wrong result\n", 
test_type);
                err = 1;
        }
        if (!got_sig) {
                printf("[FAIL]\tSignal was expected on %s read() but wasn't 
seen\n", test_type);
                err = 1;
        }
        if (!err)
                printf("[OK]\tRestart of %s() worked\n", test_type);
        return err;
}

int main(int argc, char **argv, char **envp)
{
        char buf[10];
        int fd;
        int len;
        int err;

        signal_SA_RESTART_empty_mask(SIGALRM, sighandler);

        printf("[RUN]\tTest restart of read()\n");
        fd = make_writer();
        prepare(buf);
        len = read(fd, buf, 10);
        err = check("read", len, buf);
        close(fd);

        printf("[RUN]\tTest restart of recv()\n");
        fd = make_sender();
        prepare(buf);
        len = recv(fd, buf, 10, MSG_PEEK);
        err |= check("recv", len, buf);
        if (!err) {
                /* Check that restarted recv() indeed had MSG_PEEK:
                 * i.e. that it did not consume the data.
                 */
                strcpy(buf, "qwertyuio");
                len = recv(fd, buf, 10, 0);
                if (len != 10 || strcmp(buf, "123456789") != 0) {
                        printf("[FAIL]\tRestarted %s() had no MSG_PEEK flag\n", 
"recv");
                        err = 1;
                }
        }
        close(fd);

        return err;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to